Skip to content

Commit

Permalink
feat: Don't compile twice when two function have the same body
Browse files Browse the repository at this point in the history
closes #178
  • Loading branch information
giann committed Nov 20, 2024
1 parent 6172cca commit 53004ce
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/Chunk.zig
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,29 @@ const Self = @This();

pub const max_constants = std.math.maxInt(u24);

const RegistryContext = struct {
pub fn hash(_: RegistryContext, key: Self) u64 {
return std.hash.Wyhash.hash(
0,
std.mem.sliceAsBytes(key.code.items),
);
}

pub fn eql(_: RegistryContext, a: Self, b: Self) bool {
return std.mem.eql(u32, a.code.items, b.code.items) and
std.mem.eql(Value, a.constants.items, b.constants.items);
}
};

pub fn HashMap(V: type) type {
return std.HashMap(
Self,
V,
RegistryContext,
std.hash_map.default_max_load_percentage,
);
}

allocator: std.mem.Allocator,
/// AST
ast: Ast,
Expand Down
31 changes: 31 additions & 0 deletions src/Jit.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const ZigType = @import("zigtypes.zig").Type;
const ExternApi = @import("jit_extern_api.zig").ExternApi;
const api = @import("lib/buzz_api.zig");
const io = @import("io.zig");
const Chunk = @import("Chunk.zig");

pub const Error = error{
CantCompile,
Expand Down Expand Up @@ -80,6 +81,11 @@ const GenState = struct {
}
};

const CompiledFunction = struct {
native: *anyopaque,
native_raw: *anyopaque,
};

const Self = @This();

vm: *VM,
Expand All @@ -102,6 +108,8 @@ modules: std.ArrayList(m.MIR_module_t),
call_count: u128 = 0,
/// Keeps track of time spent in the JIT
jit_time: usize = 0,
/// Closures already compiled (hash is bytecode list), useful to compile once a function
compiled_functions_bodies: Chunk.HashMap(CompiledFunction),

pub fn init(vm: *VM) Self {
return .{
Expand All @@ -113,6 +121,7 @@ pub fn init(vm: *VM) Self {
.objclosures_queue = std.AutoHashMap(*o.ObjClosure, void).init(vm.gc.allocator),
.required_ext_api = std.AutoHashMap(ExternApi, void).init(vm.gc.allocator),
.modules = std.ArrayList(m.MIR_module_t).init(vm.gc.allocator),
.compiled_functions_bodies = Chunk.HashMap(CompiledFunction).init(vm.gc.allocator),
};
}

Expand All @@ -125,6 +134,7 @@ pub fn deinit(self: *Self) void {
self.objclosures_queue.deinit();
self.modules.deinit();
self.required_ext_api.deinit();
self.compiled_functions_bodies.deinit();
m.MIR_finish(self.ctx);
}

Expand All @@ -141,6 +151,19 @@ fn reset(self: *Self) void {

pub fn compileFunction(self: *Self, ast: Ast, closure: *o.ObjClosure) Error!void {
const function = closure.function;

// Did we already compile a function with the same body?
if (self.compiled_functions_bodies.get(function.chunk)) |compiled| {
function.native = compiled.native;
function.native_raw = compiled.native_raw;

if (BuildOptions.jit_debug) {
io.print("Reusing previous compilation\n", .{});
}

return;
}

const ast_node = function.node;

var seen = std.AutoHashMap(Ast.Node.Index, void).init(self.vm.gc.allocator);
Expand Down Expand Up @@ -214,6 +237,14 @@ pub fn compileFunction(self: *Self, ast: Ast, closure: *o.ObjClosure) Error!void
if (kv2.key_ptr.*.function.node == node) {
kv2.key_ptr.*.function.native = native;
kv2.key_ptr.*.function.native_raw = native_raw;

try self.compiled_functions_bodies.put(
kv2.key_ptr.*.function.chunk,
.{
.native = native.?,
.native_raw = native_raw.?,
},
);
break;
}
}
Expand Down

0 comments on commit 53004ce

Please sign in to comment.