Skip to content

Commit

Permalink
fix(jit): Don't blacklist function with a yield statement
Browse files Browse the repository at this point in the history
We already forbid async call from being jit compiled, no need then to do the same for functions containing yield statements.
Those function, when call outside a fiber, will behave normally and yield statement are evaluated without giving back control flow to anything.
  • Loading branch information
giann committed Jul 2, 2024
1 parent 0b0be57 commit a63b5f7
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 13 deletions.
39 changes: 28 additions & 11 deletions src/Ast.zig
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,11 @@ pub fn usesFiber(self: Self, node: Node.Index, seen: *std.AutoHashMap(Node.Index
return switch (self.nodes.items(.tag)[node]) {
.As => try self.usesFiber(components.As.left, seen),
.AsyncCall,
.Resolve,
.Resume,
.Yield,
.Resolve,
=> true,
.Binary => try self.usesFiber(components.Binary.left, seen) or try self.usesFiber(components.Binary.right, seen),
.Binary => try self.usesFiber(components.Binary.left, seen) or
try self.usesFiber(components.Binary.right, seen),
.Block => blk: {
for (components.Block) |stmt| {
if (try self.usesFiber(stmt, seen)) {
Expand Down Expand Up @@ -264,7 +264,10 @@ pub fn usesFiber(self: Self, node: Node.Index, seen: *std.AutoHashMap(Node.Index
break :blk false;
},
.Call => call: {
if (try self.usesFiber(components.Call.callee, seen) or (components.Call.catch_default != null and try self.usesFiber(components.Call.catch_default.?, seen))) {
if (try self.usesFiber(components.Call.callee, seen) or
(components.Call.catch_default != null and
try self.usesFiber(components.Call.catch_default.?, seen)))
{
break :call true;
}

Expand Down Expand Up @@ -319,10 +322,15 @@ pub fn usesFiber(self: Self, node: Node.Index, seen: *std.AutoHashMap(Node.Index
break :for_loop false;
},
.ForceUnwrap => try self.usesFiber(components.ForceUnwrap.unwrapped, seen),
.ForEach => try self.usesFiber(components.ForEach.iterable, seen) or try self.usesFiber(components.ForEach.key, seen) or try self.usesFiber(components.ForEach.value, seen) or try self.usesFiber(components.ForEach.body, seen),
.ForEach => try self.usesFiber(components.ForEach.iterable, seen) or
try self.usesFiber(components.ForEach.key, seen) or
try self.usesFiber(components.ForEach.value, seen) or
try self.usesFiber(components.ForEach.body, seen),
.Function => components.Function.body != null and try self.usesFiber(components.Function.body.?, seen),
.Grouping => try self.usesFiber(components.Grouping, seen),
.If => try self.usesFiber(components.If.condition, seen) or try self.usesFiber(components.If.body, seen) or (components.If.else_branch != null and try self.usesFiber(components.If.else_branch.?, seen)),
.If => try self.usesFiber(components.If.condition, seen) or
try self.usesFiber(components.If.body, seen) or (components.If.else_branch != null and
try self.usesFiber(components.If.else_branch.?, seen)),
.Is => try self.usesFiber(components.Is.left, seen),
.List => list: {
for (components.List.items) |item| {
Expand All @@ -335,14 +343,17 @@ pub fn usesFiber(self: Self, node: Node.Index, seen: *std.AutoHashMap(Node.Index
},
.Map => map: {
for (components.Map.entries) |entry| {
if (try self.usesFiber(entry.key, seen) or try self.usesFiber(entry.value, seen)) {
if (try self.usesFiber(entry.key, seen) or
try self.usesFiber(entry.value, seen))
{
break :map true;
}
}

break :map false;
},
.NamedVariable => components.NamedVariable.value != null and try self.usesFiber(components.NamedVariable.value.?, seen),
.NamedVariable => components.NamedVariable.value != null and
try self.usesFiber(components.NamedVariable.value.?, seen),
.ObjectInit => obj_init: {
for (components.ObjectInit.properties) |property| {
if (try self.usesFiber(property.value, seen)) {
Expand All @@ -353,12 +364,17 @@ pub fn usesFiber(self: Self, node: Node.Index, seen: *std.AutoHashMap(Node.Index
break :obj_init false;
},
.Out => try self.usesFiber(components.Out, seen),
.Range => try self.usesFiber(components.Range.low, seen) or try self.usesFiber(components.Range.high, seen),
.Range => try self.usesFiber(components.Range.low, seen) or
try self.usesFiber(components.Range.high, seen),
.Return => components.Return.value != null and try self.usesFiber(components.Return.value.?, seen),
.Subscript => try self.usesFiber(components.Subscript.subscripted, seen) or try self.usesFiber(components.Subscript.index, seen) or (components.Subscript.value != null and try self.usesFiber(components.Subscript.value.?, seen)),
.Subscript => try self.usesFiber(components.Subscript.subscripted, seen) or
try self.usesFiber(components.Subscript.index, seen) or
(components.Subscript.value != null and try self.usesFiber(components.Subscript.value.?, seen)),
.Throw => try self.usesFiber(components.Throw.expression, seen),
.Try => @"try": {
if (try self.usesFiber(components.Try.body, seen) or (components.Try.unconditional_clause != null and try self.usesFiber(components.Try.unconditional_clause.?, seen))) {
if (try self.usesFiber(components.Try.body, seen) or
(components.Try.unconditional_clause != null and try self.usesFiber(components.Try.unconditional_clause.?, seen)))
{
break :@"try" true;
}

Expand All @@ -375,6 +391,7 @@ pub fn usesFiber(self: Self, node: Node.Index, seen: *std.AutoHashMap(Node.Index
.Unwrap => try self.usesFiber(components.Unwrap.unwrapped, seen),
.VarDeclaration => components.VarDeclaration.value != null and try self.usesFiber(components.VarDeclaration.value.?, seen),
.While => try self.usesFiber(components.While.condition, seen) or try self.usesFiber(components.While.body, seen),
.Yield => false, // Yield is an issue only if the function is called within a fiber, and we already forbid async call from being jit compiled
else => false,
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/Jit.zig
Original file line number Diff line number Diff line change
Expand Up @@ -509,10 +509,10 @@ fn generateNode(self: *Self, node: Ast.Node.Index) Error!?m.MIR_op_t {
.ForEach => try self.generateForEach(node),
.TypeExpression => try self.generateTypeExpression(node),
.TypeOfExpression => try self.generateTypeOfExpression(node),
.Yield => try self.generateNode(components[node].Yield),
.AsyncCall,
.Resume,
.Resolve,
.Yield,
=> return Error.CantCompile,

else => {
Expand Down
3 changes: 2 additions & 1 deletion src/obj.zig
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,8 @@ pub const Obj = struct {
.List => ObjList.cast(self).?.type_def.eql(type_def),
.Map => ObjMap.cast(self).?.type_def.eql(type_def),
.Fiber => ObjFiber.cast(self).?.type_def.eql(type_def),
.UserData, .Native => unreachable, // TODO
.UserData => type_def.def_type == .UserData,
.Native => unreachable, // TODO
};
}

Expand Down

0 comments on commit a63b5f7

Please sign in to comment.