diff --git a/core/engine/src/bytecompiler/expression/mod.rs b/core/engine/src/bytecompiler/expression/mod.rs index 8d86b322560..88d71f94ef1 100644 --- a/core/engine/src/bytecompiler/expression/mod.rs +++ b/core/engine/src/bytecompiler/expression/mod.rs @@ -110,25 +110,28 @@ impl ByteCompiler<'_> { Expression::PropertyAccess(access) => self.access_get(Access::Property { access }, dst), Expression::Conditional(op) => self.compile_conditional(op, dst), Expression::ArrayLiteral(literal) => { - let value = self.register_allocator.alloc(); - - self.bytecode.emit_store_new_array(dst.variable()); + let dst_op = dst.variable(); + self.bytecode.emit_store_new_array(dst_op); for element in literal.as_ref() { - if let Some(element) = element { - self.compile_expr(element, &value); - if let Expression::Spread(_) = element { + match element { + Some(Expression::Spread(spread)) => { + let value = self.register_allocator.alloc(); + self.compile_expr(spread.target(), &value); self.bytecode.emit_get_iterator(value.variable()); - self.bytecode.emit_push_iterator_to_array(dst.variable()); - } else { - self.bytecode - .emit_push_value_to_array(value.variable(), dst.variable()); + self.bytecode.emit_push_iterator_to_array(dst_op); + self.register_allocator.dealloc(value); + } + Some(elem) => { + self.compile_expr_operand(elem, |this, op| { + this.bytecode.emit_push_value_to_array(op, dst_op); + }); + } + None => { + self.bytecode.emit_push_elision_to_array(dst_op); } - } else { - self.bytecode.emit_push_elision_to_array(dst.variable()); } } - self.register_allocator.dealloc(value); } Expression::This(_this) => self.access_get(Access::This, dst), Expression::Spread(spread) => self.compile_expr(spread.target(), dst), @@ -354,24 +357,25 @@ impl ByteCompiler<'_> { if contains_spread { let array = self.register_allocator.alloc(); - let value = self.register_allocator.alloc(); + let array_op = array.variable(); - self.bytecode.emit_store_new_array(array.variable()); + self.bytecode.emit_store_new_array(array_op); for arg in super_call.arguments() { - self.compile_expr(arg, &value); - if let Expression::Spread(_) = arg { + if let Expression::Spread(spread) = arg { + let value = self.register_allocator.alloc(); + self.compile_expr(spread.target(), &value); self.bytecode.emit_get_iterator(value.variable()); - self.bytecode.emit_push_iterator_to_array(array.variable()); + self.bytecode.emit_push_iterator_to_array(array_op); + self.register_allocator.dealloc(value); } else { - self.bytecode - .emit_push_value_to_array(value.variable(), array.variable()); + self.compile_expr_operand(arg, |this, op| { + this.bytecode.emit_push_value_to_array(op, array_op); + }); } } self.push_from_register(&array); - - self.register_allocator.dealloc(value); self.register_allocator.dealloc(array); } else { for arg in super_call.arguments() { diff --git a/core/engine/src/bytecompiler/mod.rs b/core/engine/src/bytecompiler/mod.rs index 2efa019a694..b06bd1e8921 100644 --- a/core/engine/src/bytecompiler/mod.rs +++ b/core/engine/src/bytecompiler/mod.rs @@ -1730,7 +1730,9 @@ impl<'ctx> ByteCompiler<'ctx> { /// Compile an expression and leave the result on the stack. /// /// For call/new expressions, this avoids the `PopIntoRegister` + `PushFromRegister` - /// round-trip by leaving the call result directly on the stack. + /// round-trip by leaving the call result directly on the stack. For identifier + /// expressions resolving to a local or const-cached register, this pushes from + /// that register directly, avoiding a `Move` into a temporary. pub(crate) fn compile_expr_to_stack(&mut self, expr: &Expression) { match expr { Expression::Call(call) => { @@ -1743,10 +1745,9 @@ impl<'ctx> ByteCompiler<'ctx> { self.compile_expr_to_stack(parenthesized.expression()); } _ => { - let tmp = self.register_allocator.alloc(); - self.compile_expr(expr, &tmp); - self.push_from_register(&tmp); - self.register_allocator.dealloc(tmp); + self.compile_expr_operand(expr, |this, op| { + this.bytecode.emit_push_from_register(op); + }); } } } @@ -2079,24 +2080,25 @@ impl<'ctx> ByteCompiler<'ctx> { if contains_spread { let array = self.register_allocator.alloc(); - let value = self.register_allocator.alloc(); + let array_op = array.variable(); - self.bytecode.emit_store_new_array(array.variable()); + self.bytecode.emit_store_new_array(array_op); for arg in args { - self.compile_expr(arg, &value); - if let Expression::Spread(_) = arg { + if let Expression::Spread(spread) = arg { + let value = self.register_allocator.alloc(); + self.compile_expr(spread.target(), &value); self.bytecode.emit_get_iterator(value.variable()); - self.bytecode.emit_push_iterator_to_array(array.variable()); + self.bytecode.emit_push_iterator_to_array(array_op); + self.register_allocator.dealloc(value); } else { - self.bytecode - .emit_push_value_to_array(value.variable(), array.variable()); + self.compile_expr_operand(arg, |this, op| { + this.bytecode.emit_push_value_to_array(op, array_op); + }); } } self.push_from_register(&array); - - self.register_allocator.dealloc(value); self.register_allocator.dealloc(array); self.bytecode.emit_call_spread(); @@ -2649,28 +2651,26 @@ impl<'ctx> ByteCompiler<'ctx> { if contains_spread { let array = compiler.register_allocator.alloc(); - let value = compiler.register_allocator.alloc(); + let array_op = array.variable(); - compiler.bytecode.emit_store_new_array(array.variable()); + compiler.bytecode.emit_store_new_array(array_op); for arg in call.args() { - compiler.compile_expr(arg, &value); - if let Expression::Spread(_) = arg { + if let Expression::Spread(spread) = arg { + let value = compiler.register_allocator.alloc(); + compiler.compile_expr(spread.target(), &value); compiler.bytecode.emit_get_iterator(value.variable()); - compiler - .bytecode - .emit_push_iterator_to_array(array.variable()); + compiler.bytecode.emit_push_iterator_to_array(array_op); + compiler.register_allocator.dealloc(value); } else { - compiler - .bytecode - .emit_push_value_to_array(value.variable(), array.variable()); + compiler.compile_expr_operand(arg, |this, op| { + this.bytecode.emit_push_value_to_array(op, array_op); + }); } } compiler.push_from_register(&array); - compiler.register_allocator.dealloc(array); - compiler.register_allocator.dealloc(value); } else { for arg in call.args() { compiler.compile_expr_to_stack(arg); diff --git a/tests/insta-bytecode/src/snapshots/insta_bytecode__compile_bytecode@double-loop-function.js.snap b/tests/insta-bytecode/src/snapshots/insta_bytecode__compile_bytecode@double-loop-function.js.snap index 554a151dbc7..cf5237ef717 100644 --- a/tests/insta-bytecode/src/snapshots/insta_bytecode__compile_bytecode@double-loop-function.js.snap +++ b/tests/insta-bytecode/src/snapshots/insta_bytecode__compile_bytecode@double-loop-function.js.snap @@ -10,26 +10,25 @@ Location Handler Opcode Operands 00000b Jump address:00001a 000010 IncrementLoopIteration 000011 Inc src:r02, dst:r02 - 00001a JumpIfNotLessThan lhs:r02, rhs:r03, address:000083 + 00001a JumpIfNotLessThan lhs:r02, rhs:r03, address:00007a 000027 StoreZero dst:r05 00002c StoreInt8 value:50, dst:r06 000032 Jump address:000041 000037 IncrementLoopIteration 000038 Inc src:r05, dst:r05 - 000041 JumpIfNotLessThan lhs:r05, rhs:r06, address:00007e + 000041 JumpIfNotLessThan lhs:r05, rhs:r06, address:000075 00004e PushFromRegister src:r00 000053 GetNameGlobal dst:r07, binding_index:0, ic_index:0 000060 PushFromRegister src:r07 - 000065 Move src:r05, dst:r07 - 00006e PushFromRegister src:r07 - 000073 Call argument_count:1 - 000078 Pop - 000079 Jump address:000037 - 00007e Jump address:000010 - 000083 GetNameGlobal dst:r03, binding_index:1, ic_index:1 - 000090 SetAccumulator src:r03 - 000095 CheckReturn - 000096 Return + 000065 PushFromRegister src:r05 + 00006a Call argument_count:1 + 00006f Pop + 000070 Jump address:000037 + 000075 Jump address:000010 + 00007a GetNameGlobal dst:r03, binding_index:1, ic_index:1 + 000087 SetAccumulator src:r03 + 00008c CheckReturn + 00008d Return Register Count: 8, Flags: CodeBlockFlags(HAS_PROTOTYPE_PROPERTY) Constants: @@ -42,4 +41,4 @@ Handlers: Source Map: 0000: 17..56: (5, 25) 0001: 56..101: (6, 27) - 0002: 101..121: (7, 6) + 0002: 101..112: (7, 6)