From 047730405f180c546c20c59cd633421e26553eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=88=B1=E7=89=B9=E6=AF=8F=E7=BE=8A=E9=98=9F?= Date: Fri, 5 Jun 2026 18:04:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20VM=20=E6=94=AF=E6=8C=81=E5=8A=A8?= =?UTF-8?q?=E9=9D=99=E6=80=81=E5=B1=9E=E6=80=A7=E8=AF=BB=E5=86=99=E5=AD=97?= =?UTF-8?q?=E8=8A=82=E7=A0=81=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_vm/src/vm.rs | 76 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/crates/oxide_vm/src/vm.rs b/crates/oxide_vm/src/vm.rs index 3d370ee..609d42e 100644 --- a/crates/oxide_vm/src/vm.rs +++ b/crates/oxide_vm/src/vm.rs @@ -309,6 +309,82 @@ impl Vm { } } + OpCode::GET_PROP => { + let obj_ptr = self.regs[rd].as_object_ptr() as *mut JsObject; + if obj_ptr.is_null() { + return Err("GET_PROP on non-object".into()); + } + let obj = unsafe { &*obj_ptr }; + let prop_val = self.constants[opcode::imm16(instr) as usize]; + let prop_name_si = prop_val.as_string_index(); + if let Some(offset) = shape::lookup_offset(obj.shape_id(), prop_name_si) { + self.regs[a] = obj.get_prop(offset); + } else { + self.regs[a] = JsValue::undefined(); + } + } + + OpCode::GET_PROP_DYNAMIC => { + let obj_ptr = self.regs[rd].as_object_ptr() as *mut JsObject; + if obj_ptr.is_null() { + return Err("GET_PROP_DYNAMIC on non-object".into()); + } + let obj = unsafe { &*obj_ptr }; + let key_val = self.regs[a]; + if !key_val.is_string() { + return Err("GET_PROP_DYNAMIC key not a string".into()); + } + let prop_name_si = key_val.as_string_index(); + if let Some(offset) = shape::lookup_offset(obj.shape_id(), prop_name_si) { + self.regs[b] = obj.get_prop(offset); + } else { + self.regs[b] = JsValue::undefined(); + } + } + + OpCode::SET_PROP => { + let obj_ptr = self.regs[rd].as_object_ptr() as *mut JsObject; + if obj_ptr.is_null() { + return Err("SET_PROP on non-object".into()); + } + let obj = unsafe { &mut *obj_ptr }; + let prop_val = self.constants[opcode::imm16(instr) as usize]; + let prop_name_si = prop_val.as_string_index(); + if let Some(offset) = shape::lookup_offset(obj.shape_id(), prop_name_si) { + obj.set_prop(offset, self.regs[a]); + } else { + let new_offset = obj.prop_count(); + let new_shape_id = shape::make_shape(obj.shape_id(), prop_name_si); + obj.set_shape_id(new_shape_id); + obj.set_prop_count(new_offset + 1); + obj.set_prop(new_offset, self.regs[a]); + obj.bump_generation(); + } + } + + OpCode::SET_PROP_DYNAMIC => { + let obj_ptr = self.regs[rd].as_object_ptr() as *mut JsObject; + if obj_ptr.is_null() { + return Err("SET_PROP_DYNAMIC on non-object".into()); + } + let obj = unsafe { &mut *obj_ptr }; + let key_val = self.regs[a]; + if !key_val.is_string() { + return Err("SET_PROP_DYNAMIC key not a string".into()); + } + let prop_name_si = key_val.as_string_index(); + if let Some(offset) = shape::lookup_offset(obj.shape_id(), prop_name_si) { + obj.set_prop(offset, self.regs[b]); + } else { + let new_offset = obj.prop_count(); + let new_shape_id = shape::make_shape(obj.shape_id(), prop_name_si); + obj.set_shape_id(new_shape_id); + obj.set_prop_count(new_offset + 1); + obj.set_prop(new_offset, self.regs[b]); + obj.bump_generation(); + } + } + OpCode::NEW_OBJECT => { let obj = self .epoch