feat: 增加 CreateClosure 字节码,函数字面量每次执行创建新闭包
This commit is contained in:
@@ -90,6 +90,7 @@ pub enum OpCode {
|
|||||||
SUPER_STATIC_GET_PROP = 0x46,
|
SUPER_STATIC_GET_PROP = 0x46,
|
||||||
SET_HOME_OBJECT = 0x47,
|
SET_HOME_OBJECT = 0x47,
|
||||||
DEFINE_ACCESSOR = 0x48,
|
DEFINE_ACCESSOR = 0x48,
|
||||||
|
CREATE_CLOSURE = 0x4A,
|
||||||
|
|
||||||
// ── Object Property (0x50-0x5F) ──
|
// ── Object Property (0x50-0x5F) ──
|
||||||
IC_GET_PROP = 0x50,
|
IC_GET_PROP = 0x50,
|
||||||
@@ -238,6 +239,7 @@ impl TryFrom<u8> for OpCode {
|
|||||||
0x46 => Ok(OpCode::SUPER_STATIC_GET_PROP),
|
0x46 => Ok(OpCode::SUPER_STATIC_GET_PROP),
|
||||||
0x47 => Ok(OpCode::SET_HOME_OBJECT),
|
0x47 => Ok(OpCode::SET_HOME_OBJECT),
|
||||||
0x48 => Ok(OpCode::DEFINE_ACCESSOR),
|
0x48 => Ok(OpCode::DEFINE_ACCESSOR),
|
||||||
|
0x4A => Ok(OpCode::CREATE_CLOSURE),
|
||||||
0x50 => Ok(OpCode::IC_GET_PROP),
|
0x50 => Ok(OpCode::IC_GET_PROP),
|
||||||
0x51 => Ok(OpCode::IC_SET_PROP),
|
0x51 => Ok(OpCode::IC_SET_PROP),
|
||||||
0x52 => Ok(OpCode::GET_PROP),
|
0x52 => Ok(OpCode::GET_PROP),
|
||||||
@@ -357,6 +359,7 @@ impl fmt::Display for OpCode {
|
|||||||
OpCode::SUPER_STATIC_GET_PROP => "SUPER_STATIC_GET_PROP",
|
OpCode::SUPER_STATIC_GET_PROP => "SUPER_STATIC_GET_PROP",
|
||||||
OpCode::SET_HOME_OBJECT => "SET_HOME_OBJECT",
|
OpCode::SET_HOME_OBJECT => "SET_HOME_OBJECT",
|
||||||
OpCode::DEFINE_ACCESSOR => "DEFINE_ACCESSOR",
|
OpCode::DEFINE_ACCESSOR => "DEFINE_ACCESSOR",
|
||||||
|
OpCode::CREATE_CLOSURE => "CREATE_CLOSURE",
|
||||||
OpCode::IC_GET_PROP => "IC_GET_PROP",
|
OpCode::IC_GET_PROP => "IC_GET_PROP",
|
||||||
OpCode::IC_SET_PROP => "IC_SET_PROP",
|
OpCode::IC_SET_PROP => "IC_SET_PROP",
|
||||||
OpCode::GET_PROP => "GET_PROP",
|
OpCode::GET_PROP => "GET_PROP",
|
||||||
|
|||||||
@@ -254,6 +254,11 @@ impl CompileCtx {
|
|||||||
self.emit(opcode::encode(OpCode::LOAD_CONST, reg, (idx & 0xFF) as u8, ((idx >> 8) & 0xFF) as u8));
|
self.emit(opcode::encode(OpCode::LOAD_CONST, reg, (idx & 0xFF) as u8, ((idx >> 8) & 0xFF) as u8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn emit_create_closure(&mut self, reg: u8, sub_idx: u32) {
|
||||||
|
let idx = sub_idx as u16;
|
||||||
|
self.emit(opcode::encode(OpCode::CREATE_CLOSURE, reg, (idx & 0xFF) as u8, ((idx >> 8) & 0xFF) as u8));
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn count_word(&mut self) {
|
pub(crate) fn count_word(&mut self) {
|
||||||
self.projected_pc += 1;
|
self.projected_pc += 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,9 +37,8 @@ impl Compiler {
|
|||||||
// 1-indexed: 0 = no sub_module (sentinel)
|
// 1-indexed: 0 = no sub_module (sentinel)
|
||||||
let sub_idx = ctx.sub_modules.len() as u32;
|
let sub_idx = ctx.sub_modules.len() as u32;
|
||||||
|
|
||||||
let const_idx = ctx.add_constant(Constant::BytecodeFunc(sub_idx));
|
|
||||||
let r = ctx.alloc_reg();
|
let r = ctx.alloc_reg();
|
||||||
ctx.emit_load_const(r, const_idx);
|
ctx.emit_create_closure(r, sub_idx);
|
||||||
Ok(r)
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,9 +71,8 @@ impl Compiler {
|
|||||||
// 1-indexed: 0 = no sub_module (sentinel)
|
// 1-indexed: 0 = no sub_module (sentinel)
|
||||||
let sub_idx = ctx.sub_modules.len() as u32;
|
let sub_idx = ctx.sub_modules.len() as u32;
|
||||||
|
|
||||||
let const_idx = ctx.add_constant(Constant::BytecodeFunc(sub_idx));
|
|
||||||
let r = ctx.alloc_reg();
|
let r = ctx.alloc_reg();
|
||||||
ctx.emit_load_const(r, const_idx);
|
ctx.emit_create_closure(r, sub_idx);
|
||||||
Ok(r)
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -811,8 +811,7 @@ impl Compiler {
|
|||||||
ctor_module.function_name = ctor_name.clone();
|
ctor_module.function_name = ctor_name.clone();
|
||||||
ctx.sub_modules.push(ctor_module);
|
ctx.sub_modules.push(ctor_module);
|
||||||
|
|
||||||
let ctor_idx = ctx.add_constant(Constant::BytecodeFunc(ctx.sub_modules.len() as u32));
|
ctx.emit_create_closure(ctor_reg, ctx.sub_modules.len() as u32);
|
||||||
ctx.emit_load_const(ctor_reg, ctor_idx);
|
|
||||||
ctx.emit(opcode::encode(OpCode::NEW_OBJECT, proto_reg, 0, 0));
|
ctx.emit(opcode::encode(OpCode::NEW_OBJECT, proto_reg, 0, 0));
|
||||||
|
|
||||||
if let Some(super_reg) = super_reg {
|
if let Some(super_reg) = super_reg {
|
||||||
@@ -947,9 +946,8 @@ impl Compiler {
|
|||||||
method_module.needs_home_object = true;
|
method_module.needs_home_object = true;
|
||||||
ctx.sub_modules.push(method_module);
|
ctx.sub_modules.push(method_module);
|
||||||
|
|
||||||
let method_idx = ctx.add_constant(Constant::BytecodeFunc(ctx.sub_modules.len() as u32));
|
|
||||||
let method_reg = ctx.alloc_reg();
|
let method_reg = ctx.alloc_reg();
|
||||||
ctx.emit_load_const(method_reg, method_idx);
|
ctx.emit_create_closure(method_reg, ctx.sub_modules.len() as u32);
|
||||||
ctx.emit(opcode::encode(OpCode::SET_HOME_OBJECT, method_reg, home_reg, 0));
|
ctx.emit(opcode::encode(OpCode::SET_HOME_OBJECT, method_reg, home_reg, 0));
|
||||||
Ok(method_reg)
|
Ok(method_reg)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,8 +77,7 @@ impl Compiler {
|
|||||||
|
|
||||||
let var_reg = ctx.lookup(&name)?;
|
let var_reg = ctx.lookup(&name)?;
|
||||||
ctx.reserve_reg(var_reg);
|
ctx.reserve_reg(var_reg);
|
||||||
let const_idx = ctx.add_constant(Constant::BytecodeFunc(sub_idx));
|
ctx.emit_create_closure(var_reg, sub_idx);
|
||||||
ctx.emit_load_const(var_reg, const_idx);
|
|
||||||
ctx.emit(opcode::encode(OpCode::STORE_VAR, var_reg, var_reg, 0));
|
ctx.emit(opcode::encode(OpCode::STORE_VAR, var_reg, var_reg, 0));
|
||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|||||||
@@ -739,6 +739,20 @@ impl Vm {
|
|||||||
self.dispatch_load_const(rd, instr)?;
|
self.dispatch_load_const(rd, instr)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OpCode::CREATE_CLOSURE => {
|
||||||
|
let sub_idx = opcode::imm16(instr) as u32;
|
||||||
|
debug_assert!(sub_idx > 0 && (sub_idx as usize) <= self.sub_modules.len());
|
||||||
|
let sub = &self.sub_modules[sub_idx as usize - 1];
|
||||||
|
let result = self.create_function_object(
|
||||||
|
sub_idx,
|
||||||
|
sub.is_arrow,
|
||||||
|
sub.is_class_constructor,
|
||||||
|
sub.is_derived_constructor,
|
||||||
|
sub.needs_home_object,
|
||||||
|
);
|
||||||
|
self.regs[rd] = result;
|
||||||
|
}
|
||||||
|
|
||||||
OpCode::ADD => {
|
OpCode::ADD => {
|
||||||
self.dispatch_add(rd, a, b)?;
|
self.dispatch_add(rd, a, b)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,8 +158,7 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let global_ptr = self.session.global_object().as_ptr() as *mut JsObject;
|
self.regs[254] = JsValue::undefined();
|
||||||
self.regs[254] = JsValue::from_js_object(global_ptr);
|
|
||||||
|
|
||||||
self.dispatch()
|
self.dispatch()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ impl Vm {
|
|||||||
/// Create a function JsObject for a BytecodeFunc constant.
|
/// Create a function JsObject for a BytecodeFunc constant.
|
||||||
/// When `is_arrow` is true, captures the current `this` (regs[254])
|
/// When `is_arrow` is true, captures the current `this` (regs[254])
|
||||||
/// for lexical this binding at call time.
|
/// for lexical this binding at call time.
|
||||||
fn create_function_object(
|
pub(crate) fn create_function_object(
|
||||||
&mut self, sub_idx: u32, is_arrow: bool, is_class_constructor: bool, is_derived_constructor: bool,
|
&mut self, sub_idx: u32, is_arrow: bool, is_class_constructor: bool, is_derived_constructor: bool,
|
||||||
needs_home_object: bool,
|
needs_home_object: bool,
|
||||||
) -> JsValue {
|
) -> JsValue {
|
||||||
|
|||||||
Reference in New Issue
Block a user