You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
vm: lower by-ref/named/spread calls to dedicated ByExprs opcodes
Previously, function/method calls whose argument shape required
the full ctx.Call binding pipeline (by-ref params, named args,
spread) were lowered to OP_CLASS_CONST / OP_TRY_FINALLY — generic
AST.Run() delegation that ran the entire runnableFunctionCall /
runObjectFunc / runnableFunctionCallRef node as one opaque step.
Replace that with three dedicated opcodes that hand the raw
argument-expression list to ctx.Call:
- OP_CALL_USER_BY_EXPRS: foo($a, $b, ...)
- OP_OBJECT_CALL_BY_EXPRS: $obj->method($a, $b, ...)
- OP_CALL_INDIRECT_BY_EXPRS: $f($a, $b, ...)
The arg expressions live in a new Function.SubArgs slice (parallel
to SubASTs / SubFns) so the opcode only carries the SubArgs index.
At runtime, each handler resolves its callable (same CallableCache
hookup as OP_CALL_USER, same ResolveCallable as OP_CALL_INDIRECT,
same method-lookup as OP_OBJECT_CALL) then calls ctx.Call(...,
exprs, ...), which evaluates each expression with by-ref binding,
named-arg reordering, and spread expansion — the path the AST
runner's runnableFunctionCall.Run already takes.
For OP_OBJECT_CALL_BY_EXPRS, extract a sibling helper
CallInstanceMethodByExprs in core/compiler/dispatch.go that
mirrors CallInstanceMethod byte-for-byte; only the terminal call
switches from ctx.CallZVal to ctx.Call so by-ref params bind
correctly. The __call magic-method fallback still uses ZVal args
(the magic array needs them), so the helper evaluates exprs
up-front for that branch only.
emit_call.go's emitFunctionCall and emitFunctionCallRef, and
emit_object.go's emitObjectFuncCall, now route the
by-ref/special-args/writable-arg cases through these opcodes
instead of emitCallViaAST. Stmt-context drops the result with
OP_POP; OP_REFRESH_SLOTS follows each call so subsequent slot-
cache reads see any caller-local mutations from a by-ref param.
Smoke tests pass: sort/array_pop/preg_match by-ref builtins,
user-function by-ref params, closure by-ref params, instance
method by-ref params, mixed named+positional+spread args,
array_walk by-ref callback, __call fallback, nullsafe with
spread args.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
0 commit comments