Skip to content

Commit

Permalink
feat: Tracing JIT
Browse files Browse the repository at this point in the history
- Profile loops: super simple right now, a simple counter
- When hits threshold, compile the node into a native function with no arguments
- Patch the bytecode to replace the loop with the function call

closes #134
  • Loading branch information
giann committed Apr 26, 2024
1 parent f26067d commit 3546ac8
Show file tree
Hide file tree
Showing 5 changed files with 328 additions and 72 deletions.
4 changes: 3 additions & 1 deletion src/Chunk.zig
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,16 @@ pub const OpCode = enum(u8) {
OP_LIST_APPEND,

OP_MAP,
// FIXMEL delete and only use OP_SET_MAP_SUBSCRIPT
// FIXME: delete and only use OP_SET_MAP_SUBSCRIPT
OP_SET_MAP,

OP_EXPORT,
OP_IMPORT,

OP_TO_STRING,
OP_TYPEOF,

OP_JIT,
};

/// A chunk of code to execute
Expand Down
49 changes: 34 additions & 15 deletions src/Codegen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ jit: ?*JIT,

reporter: Reporter,

const generators = [_]NodeGen{
noGen, // AnonymousObjectType,
const generators = [_]?NodeGen{
null, // AnonymousObjectType,
generateAs, // As,
generateAsyncCall, // AsyncCall,
generateBinary, // Binary,
Expand All @@ -73,27 +73,27 @@ const generators = [_]NodeGen{
generateEnum, // Enum,
generateExport, // Export,
generateExpression, // Expression,
noGen, // FiberType,
null, // FiberType,
generateFloat, // Float,
generateFor, // For,
generateForceUnwrap, // ForceUnwrap,
generateForEach, // ForEach,
generateFunction, // Function,
noGen, // FunctionType,
null, // FunctionType,
generateFunDeclaration, // FunDeclaration,
generateGenericResolve, // GenericResolve,
noGen, // GenericResolveType,
noGen, // GenericType,
null, // GenericResolveType,
null, // GenericType,
generateGrouping, // Grouping,
generateIf, // If,
generateImport, // Import,
generateInteger, // Integer,
generateIs, // Is,
generateList, // List,
noGen, // ListType,
null, // ListType,
generateMap, // Map,
noGen, // MapType,
noGen, // Namespace,
null, // MapType,
null, // Namespace,
generateNamedVariable, // NamedVariable,
generateNull, // Null,
generateObjectDeclaration, // ObjectDeclaration,
Expand All @@ -105,7 +105,7 @@ const generators = [_]NodeGen{
generateResolve, // Resolve,
generateResume, // Resume,
generateReturn, // Return,
noGen, // SimpleType,
null, // SimpleType,
generateString, // String,
generateStringLiteral, // StringLiteral,
generateSubscript, // Subscript,
Expand All @@ -115,7 +115,7 @@ const generators = [_]NodeGen{
generateTypeOfExpression, // TypeOfExpression,
generateUnary, // Unary,
generateUnwrap, // Unwrap,
noGen, // UserType,
null, // UserType,
generateVarDeclaration, // VarDeclaration,
generateVoid, // Void,
generateWhile, // While,
Expand Down Expand Up @@ -245,12 +245,12 @@ pub fn patchJump(self: *Self, offset: usize) void {
(@as(u32, @intCast(instruction)) << 24) | @as(u32, @intCast(jump));
}

pub fn patchTry(self: *Self, offset: usize) void {
pub fn patchTryOrJit(self: *Self, offset: usize) void {
std.debug.assert(offset < self.currentCode());

const jump: usize = self.currentCode();

if (jump > 16777215) {
if (jump > std.math.maxInt(u24)) {
self.reportError(
.block_too_large,
"Try block too large.",
Expand Down Expand Up @@ -408,7 +408,11 @@ inline fn generateNode(self: *Self, node: Ast.Node.Index, breaks: ?*std.ArrayLis
return null;
}

return try Self.generators[@intFromEnum(self.ast.nodes.items(.tag)[node])](self, node, breaks);
if (Self.generators[@intFromEnum(self.ast.nodes.items(.tag)[node])]) |generator| {
return generator(self, node, breaks);
}

return null;
}

fn nodeValue(self: *Self, node: Ast.Node.Index) Error!?Value {
Expand Down Expand Up @@ -1768,6 +1772,9 @@ fn generateFor(self: *Self, node: Ast.Node.Index, breaks: ?*std.ArrayList(usize)
return null;
}

const jit_jump = try self.emitJump(locations[node], .OP_JIT);
try self.emit(locations[node], node);

for (components.init_declarations) |decl| {
_ = try self.generateNode(decl, breaks);
}
Expand Down Expand Up @@ -1829,6 +1836,8 @@ fn generateFor(self: *Self, node: Ast.Node.Index, breaks: ?*std.ArrayList(usize)
try self.patchOptJumps(node);
try self.endScope(node);

self.patchTryOrJit(jit_jump);

return null;
}

Expand Down Expand Up @@ -2029,6 +2038,9 @@ fn generateForEach(self: *Self, node: Ast.Node.Index, breaks: ?*std.ArrayList(us
}
}

const jit_jump = try self.emitJump(locations[node], .OP_JIT);
try self.emit(locations[node], node);

_ = try self.generateNode(components.key, breaks);
_ = try self.generateNode(components.value, breaks);
_ = try self.generateNode(components.iterable, breaks);
Expand Down Expand Up @@ -2096,6 +2108,8 @@ fn generateForEach(self: *Self, node: Ast.Node.Index, breaks: ?*std.ArrayList(us
);
try self.endScope(node);

self.patchTryOrJit(jit_jump);

return null;
}

Expand Down Expand Up @@ -3484,7 +3498,7 @@ fn generateTry(self: *Self, node: Ast.Node.Index, breaks: ?*std.ArrayList(usize)
var exit_jumps = std.ArrayList(usize).init(self.gc.allocator);
defer exit_jumps.deinit();

self.patchTry(try_jump);
self.patchTryOrJit(try_jump);
var has_unconditional = components.unconditional_clause != null;
for (components.clauses) |clause| {
const error_type = type_defs[clause.type_def].?;
Expand Down Expand Up @@ -3831,6 +3845,9 @@ fn generateWhile(self: *Self, node: Ast.Node.Index, breaks: ?*std.ArrayList(usiz
return null;
}

const jit_jump = try self.emitJump(locations[node], .OP_JIT);
try self.emit(locations[node], node);

const loop_start: usize = self.currentCode();

if (condition_type_def.def_type == .Placeholder) {
Expand Down Expand Up @@ -3868,6 +3885,8 @@ fn generateWhile(self: *Self, node: Ast.Node.Index, breaks: ?*std.ArrayList(usiz
try self.patchOptJumps(node);
try self.endScope(node);

self.patchTryOrJit(jit_jump);

return null;
}

Expand Down
Loading

0 comments on commit 3546ac8

Please sign in to comment.