feat: 增加 CreateRegExp 字节码,正则字面量每次执行创建新对象
This commit is contained in:
@@ -91,6 +91,7 @@ pub enum OpCode {
|
||||
SET_HOME_OBJECT = 0x47,
|
||||
DEFINE_ACCESSOR = 0x48,
|
||||
CREATE_CLOSURE = 0x4A,
|
||||
CREATE_REGEXP = 0x4B,
|
||||
|
||||
// ── Object Property (0x50-0x5F) ──
|
||||
IC_GET_PROP = 0x50,
|
||||
@@ -240,6 +241,7 @@ impl TryFrom<u8> for OpCode {
|
||||
0x47 => Ok(OpCode::SET_HOME_OBJECT),
|
||||
0x48 => Ok(OpCode::DEFINE_ACCESSOR),
|
||||
0x4A => Ok(OpCode::CREATE_CLOSURE),
|
||||
0x4B => Ok(OpCode::CREATE_REGEXP),
|
||||
0x50 => Ok(OpCode::IC_GET_PROP),
|
||||
0x51 => Ok(OpCode::IC_SET_PROP),
|
||||
0x52 => Ok(OpCode::GET_PROP),
|
||||
@@ -360,6 +362,7 @@ impl fmt::Display for OpCode {
|
||||
OpCode::SET_HOME_OBJECT => "SET_HOME_OBJECT",
|
||||
OpCode::DEFINE_ACCESSOR => "DEFINE_ACCESSOR",
|
||||
OpCode::CREATE_CLOSURE => "CREATE_CLOSURE",
|
||||
OpCode::CREATE_REGEXP => "CREATE_REGEXP",
|
||||
OpCode::IC_GET_PROP => "IC_GET_PROP",
|
||||
OpCode::IC_SET_PROP => "IC_SET_PROP",
|
||||
OpCode::GET_PROP => "GET_PROP",
|
||||
|
||||
@@ -18,7 +18,11 @@ impl Compiler {
|
||||
}
|
||||
|
||||
pub(in crate::counter) fn count_regexp_literal(&self, ctx: &mut CompileCtx) {
|
||||
ctx.alloc_reg();
|
||||
ctx.alloc_reg(); // pattern reg (LOAD_CONST)
|
||||
ctx.projected_pc += 1;
|
||||
ctx.alloc_reg(); // flags reg (LOAD_CONST)
|
||||
ctx.projected_pc += 1;
|
||||
ctx.alloc_reg(); // result reg (CREATE_REGEXP)
|
||||
ctx.projected_pc += 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,11 +68,16 @@ impl Compiler {
|
||||
let raw_str = raw.to_string();
|
||||
if raw_str.len() >= 2 && raw_str.starts_with('/') {
|
||||
let last_slash = raw_str.rfind('/').unwrap_or(raw_str.len() - 1);
|
||||
let pattern = &raw_str[1..last_slash];
|
||||
let flags = &raw_str[last_slash + 1..];
|
||||
let ci = ctx.add_constant(Constant::RegExp(pattern.to_string(), flags.to_string()));
|
||||
let pattern = raw_str[1..last_slash].to_string();
|
||||
let flags = raw_str[last_slash + 1..].to_string();
|
||||
let pat_ci = ctx.add_constant(Constant::String(pattern));
|
||||
let pat_reg = ctx.alloc_reg();
|
||||
ctx.emit_load_const(pat_reg, pat_ci);
|
||||
let flags_ci = ctx.add_constant(Constant::String(flags));
|
||||
let flags_reg = ctx.alloc_reg();
|
||||
ctx.emit_load_const(flags_reg, flags_ci);
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.emit_load_const(r, ci);
|
||||
ctx.emit(opcode::encode(OpCode::CREATE_REGEXP, r, pat_reg, flags_reg));
|
||||
Ok(r)
|
||||
} else {
|
||||
Err(format!("unsupported regexp literal: {:?}", lit))
|
||||
|
||||
@@ -752,6 +752,37 @@ impl Vm {
|
||||
);
|
||||
self.regs[rd] = result;
|
||||
}
|
||||
OpCode::CREATE_REGEXP => {
|
||||
let pat_val = self.regs[a];
|
||||
let flags_val = self.regs[b];
|
||||
let ctor_ptr =
|
||||
self.session.builtin_world().regexp_constructor.as_ptr() as *mut JsObject;
|
||||
let ctor = unsafe { &*ctor_ptr };
|
||||
let Some(native_fn) = ctor.native_fn() else {
|
||||
self.raise_error_kind("TypeError", "RegExp constructor unavailable")?;
|
||||
return Ok(JsValue::undefined());
|
||||
};
|
||||
let saved_0 = self.regs[0];
|
||||
let saved_1 = self.regs[1];
|
||||
let saved_2 = self.regs[2];
|
||||
self.regs[0] = JsValue::undefined();
|
||||
self.regs[1] = pat_val;
|
||||
self.regs[2] = flags_val;
|
||||
let func = unsafe { crate::vm::native_fn_ptr_to_fn(native_fn) };
|
||||
let result = match func(self, &[0, 1, 2]) {
|
||||
crate::native::NativeResult::Ok(v) => v,
|
||||
crate::native::NativeResult::Err(e) => {
|
||||
return Err(self.error_message_text("TypeError", &self.error_text(e)));
|
||||
}
|
||||
crate::native::NativeResult::TailCall { .. } => {
|
||||
return Err(self.error_message_text("TypeError", "unexpected tail call"));
|
||||
}
|
||||
};
|
||||
self.regs[0] = saved_0;
|
||||
self.regs[1] = saved_1;
|
||||
self.regs[2] = saved_2;
|
||||
self.regs[rd] = result;
|
||||
}
|
||||
|
||||
OpCode::ADD => {
|
||||
self.dispatch_add(rd, a, b)?;
|
||||
|
||||
Reference in New Issue
Block a user