perf: misc inlines and branch hints

Inlined trivial functions, added cold branch hints to error paths, added
likely branch hints to common paths
pull/9645/head
Qwerasd 2025-11-17 21:34:33 -07:00
parent 58c26957b4
commit 3e8d94bb1c
6 changed files with 58 additions and 14 deletions

View File

@ -312,6 +312,7 @@ pub fn next(self: *Parser, c: u8) [3]?Action {
pub inline fn collect(self: *Parser, c: u8) void {
if (self.intermediates_idx >= MAX_INTERMEDIATE) {
@branchHint(.cold);
log.warn("invalid intermediates count", .{});
return;
}
@ -386,6 +387,7 @@ inline fn doAction(self: *Parser, action: TransitionAction, c: u8) ?Action {
// We only allow colon or mixed separators for the 'm' command.
if (c != 'm' and self.params_sep.count() > 0) {
@branchHint(.cold);
log.warn(
"CSI colon or mixed separators only allowed for 'm' command, got: {f}",
.{result},

View File

@ -293,7 +293,10 @@ pub fn print(self: *Terminal, c: u21) !void {
// log.debug("print={x} y={} x={}", .{ c, self.screens.active.cursor.y, self.screens.active.cursor.x });
// If we're not on the main display, do nothing for now
if (self.status_display != .main) return;
if (self.status_display != .main) {
@branchHint(.cold);
return;
}
// After doing any printing, wrapping, scrolling, etc. we want to ensure
// that our screen remains in a consistent state.
@ -313,6 +316,7 @@ pub fn print(self: *Terminal, c: u21) !void {
self.modes.get(.grapheme_cluster) and
self.screens.active.cursor.x > 0)
grapheme: {
@branchHint(.unlikely);
// We need the previous cell to determine if we're at a grapheme
// break or not. If we are NOT, then we are still combining the
// same grapheme. Otherwise, we can stay in this cell.
@ -478,6 +482,7 @@ pub fn print(self: *Terminal, c: u21) !void {
// Attach zero-width characters to our cell as grapheme data.
if (width == 0) {
@branchHint(.unlikely);
// If we have grapheme clustering enabled, we don't blindly attach
// any zero width character to our cells and we instead just ignore
// it.
@ -535,6 +540,7 @@ pub fn print(self: *Terminal, c: u21) !void {
switch (width) {
// Single cell is very easy: just write in the cell
1 => {
@branchHint(.likely);
self.screens.active.cursorMarkDirty();
@call(.always_inline, printCell, .{ self, c, .narrow });
},
@ -602,10 +608,14 @@ fn printCell(
self.screens.active.charset.single_shift = null;
break :blk key_once;
} else self.screens.active.charset.gl;
const set = self.screens.active.charset.charsets.get(key);
// UTF-8 or ASCII is used as-is
if (set == .utf8 or set == .ascii) break :c unmapped_c;
if (set == .utf8 or set == .ascii) {
@branchHint(.likely);
break :c unmapped_c;
}
// If we're outside of ASCII range this is an invalid value in
// this table so we just return space.
@ -718,6 +728,7 @@ fn printCell(
// row so that the renderer can lookup rows with these much faster.
if (comptime build_options.kitty_graphics) {
if (c == kitty.graphics.unicode.placeholder) {
@branchHint(.unlikely);
self.screens.active.cursor.page_row.kitty_virtual_placeholder = true;
}
}
@ -727,6 +738,7 @@ fn printCell(
// overwriting the same hyperlink.
if (self.screens.active.cursor.hyperlink_id > 0) {
self.screens.active.cursorSetHyperlink() catch |err| {
@branchHint(.unlikely);
log.warn("error reallocating for more hyperlink space, ignoring hyperlink err={}", .{err});
assert(!cell.hyperlink);
};

View File

@ -356,8 +356,12 @@ pub const RGB = packed struct(u24) {
///
/// The value should be between 0.0 and 1.0, inclusive.
fn fromIntensity(value: []const u8) !u8 {
const i = std.fmt.parseFloat(f64, value) catch return error.InvalidFormat;
const i = std.fmt.parseFloat(f64, value) catch {
@branchHint(.cold);
return error.InvalidFormat;
};
if (i < 0.0 or i > 1.0) {
@branchHint(.cold);
return error.InvalidFormat;
}
@ -370,10 +374,15 @@ pub const RGB = packed struct(u24) {
/// value scaled in 4, 8, 12, or 16 bits, respectively.
fn fromHex(value: []const u8) !u8 {
if (value.len == 0 or value.len > 4) {
@branchHint(.cold);
return error.InvalidFormat;
}
const color = std.fmt.parseUnsigned(u16, value, 16) catch return error.InvalidFormat;
const color = std.fmt.parseUnsigned(u16, value, 16) catch {
@branchHint(.cold);
return error.InvalidFormat;
};
const divisor: usize = switch (value.len) {
1 => std.math.maxInt(u4),
2 => std.math.maxInt(u8),
@ -407,6 +416,7 @@ pub const RGB = packed struct(u24) {
/// per color channel.
pub fn parse(value: []const u8) !RGB {
if (value.len == 0) {
@branchHint(.cold);
return error.InvalidFormat;
}
@ -433,7 +443,10 @@ pub const RGB = packed struct(u24) {
.b = try RGB.fromHex(value[9..13]),
},
else => return error.InvalidFormat,
else => {
@branchHint(.cold);
return error.InvalidFormat;
},
}
}
@ -443,6 +456,7 @@ pub const RGB = packed struct(u24) {
if (x11_color.map.get(std.mem.trim(u8, value, " "))) |rgb| return rgb;
if (value.len < "rgb:a/a/a".len or !std.mem.eql(u8, value[0..3], "rgb")) {
@branchHint(.cold);
return error.InvalidFormat;
}
@ -454,6 +468,7 @@ pub const RGB = packed struct(u24) {
} else false;
if (value[i] != ':') {
@branchHint(.cold);
return error.InvalidFormat;
}
@ -462,8 +477,10 @@ pub const RGB = packed struct(u24) {
const r = r: {
const slice = if (std.mem.indexOfScalarPos(u8, value, i, '/')) |end|
value[i..end]
else
else {
@branchHint(.cold);
return error.InvalidFormat;
};
i += slice.len + 1;
@ -476,8 +493,10 @@ pub const RGB = packed struct(u24) {
const g = g: {
const slice = if (std.mem.indexOfScalarPos(u8, value, i, '/')) |end|
value[i..end]
else
else {
@branchHint(.cold);
return error.InvalidFormat;
};
i += slice.len + 1;

View File

@ -524,6 +524,7 @@ pub const Parser = struct {
// We always keep space for 1 byte at the end to null-terminate
// values.
if (self.buf_idx >= self.buf.len - 1) {
@branchHint(.cold);
if (self.state != .invalid) {
log.warn(
"OSC sequence too long (> {d}), ignoring. state={}",
@ -1048,6 +1049,7 @@ pub const Parser = struct {
';' => {
const ext = self.buf[self.buf_start .. self.buf_idx - 1];
if (!std.mem.eql(u8, ext, "notify")) {
@branchHint(.cold);
log.warn("unknown rxvt extension: {s}", .{ext});
self.state = .invalid;
return;
@ -1601,11 +1603,13 @@ pub const Parser = struct {
fn endKittyColorProtocolOption(self: *Parser, kind: enum { key_only, key_and_value }, final: bool) void {
if (self.temp_state.key.len == 0) {
@branchHint(.cold);
log.warn("zero length key in kitty color protocol", .{});
return;
}
const key = kitty_color.Kind.parse(self.temp_state.key) orelse {
@branchHint(.cold);
log.warn("unknown key in kitty color protocol: {s}", .{self.temp_state.key});
return;
};
@ -1620,6 +1624,7 @@ pub const Parser = struct {
.kitty_color_protocol => |*v| {
// Cap our allocation amount for our list.
if (v.list.items.len >= @as(usize, kitty_color.Kind.max) * 2) {
@branchHint(.cold);
self.state = .invalid;
log.warn("exceeded limit for number of keys in kitty color protocol, ignoring", .{});
return;
@ -1631,11 +1636,13 @@ pub const Parser = struct {
if (kind == .key_only or value.len == 0) {
v.list.append(alloc, .{ .reset = key }) catch |err| {
@branchHint(.cold);
log.warn("unable to append kitty color protocol option: {}", .{err});
return;
};
} else if (mem.eql(u8, "?", value)) {
v.list.append(alloc, .{ .query = key }) catch |err| {
@branchHint(.cold);
log.warn("unable to append kitty color protocol option: {}", .{err});
return;
};
@ -1651,6 +1658,7 @@ pub const Parser = struct {
},
},
}) catch |err| {
@branchHint(.cold);
log.warn("unable to append kitty color protocol option: {}", .{err});
return;
};
@ -1681,6 +1689,7 @@ pub const Parser = struct {
const alloc = self.alloc.?;
const list = self.buf_dynamic.?;
list.append(alloc, 0) catch {
@branchHint(.cold);
log.warn("allocation failed on allocable string termination", .{});
self.temp_state.str.* = "";
return;

View File

@ -1896,7 +1896,7 @@ pub const Cell = packed struct(u64) {
return cell;
}
pub fn isZero(self: Cell) bool {
pub inline fn isZero(self: Cell) bool {
return @as(u64, @bitCast(self)) == 0;
}
@ -1906,7 +1906,7 @@ pub const Cell = packed struct(u64) {
/// - Cell text is blank
/// - Cell is styled but only with a background color and no text
/// - Cell has a unicode placeholder for Kitty graphics protocol
pub fn hasText(self: Cell) bool {
pub inline fn hasText(self: Cell) bool {
return switch (self.content_tag) {
.codepoint,
.codepoint_grapheme,
@ -1918,7 +1918,7 @@ pub const Cell = packed struct(u64) {
};
}
pub fn codepoint(self: Cell) u21 {
pub inline fn codepoint(self: Cell) u21 {
return switch (self.content_tag) {
.codepoint,
.codepoint_grapheme,
@ -1931,14 +1931,14 @@ pub const Cell = packed struct(u64) {
}
/// The width in grid cells that this cell takes up.
pub fn gridWidth(self: Cell) u2 {
pub inline fn gridWidth(self: Cell) u2 {
return switch (self.wide) {
.narrow, .spacer_head, .spacer_tail => 1,
.wide => 2,
};
}
pub fn hasStyling(self: Cell) bool {
pub inline fn hasStyling(self: Cell) bool {
return self.style_id != stylepkg.default_id;
}
@ -1957,12 +1957,12 @@ pub const Cell = packed struct(u64) {
};
}
pub fn hasGrapheme(self: Cell) bool {
pub inline fn hasGrapheme(self: Cell) bool {
return self.content_tag == .codepoint_grapheme;
}
/// Returns true if the set of cells has text in it.
pub fn hasTextAny(cells: []const Cell) bool {
pub inline fn hasTextAny(cells: []const Cell) bool {
for (cells) |cell| {
if (cell.hasText()) return true;
}

View File

@ -256,6 +256,7 @@ pub fn RefCountedSet(
// we may end up with a PSL of `len` which would exceed the bounds.
// In such a case, we claim to be out of memory.
if (self.psl_stats[self.psl_stats.len - 1] > 0) {
@branchHint(.cold);
return AddError.OutOfMemory;
}
@ -308,6 +309,7 @@ pub fn RefCountedSet(
if (items[id].meta.ref == 0) {
// See comment in `addContext` for details.
if (self.psl_stats[self.psl_stats.len - 1] > 0) {
@branchHint(.cold);
return AddError.OutOfMemory;
}