diff --git a/crates/dash_compiler/src/instruction.rs b/crates/dash_compiler/src/instruction.rs index 82ecbd69..8eac3647 100755 --- a/crates/dash_compiler/src/instruction.rs +++ b/crates/dash_compiler/src/instruction.rs @@ -173,6 +173,7 @@ impl<'cx, 'inp> InstructionBuilder<'cx, 'inp> { pub fn build_jmp(&mut self, label: Label, is_local_label: bool) { self.write_instr(Instruction::Jmp); + self.write(0); self.build_jmp_header(label, is_local_label); } diff --git a/crates/dash_decompiler/src/decompiler.rs b/crates/dash_decompiler/src/decompiler.rs index 20373b20..7e7434af 100644 --- a/crates/dash_decompiler/src/decompiler.rs +++ b/crates/dash_decompiler/src/decompiler.rs @@ -159,6 +159,10 @@ impl<'buf> FunctionDecompiler<'buf> { | Instruction::JmpTrueP | Instruction::JmpUndefinedNP | Instruction::JmpUndefinedP => { + if let Instruction::Jmp = instr { + let _jmp_state = self.read()?; + } + let byte = self.read_i16()?; let offset = (self.reader.offset() as isize) + byte as isize; let arg = format!("@{offset:x}"); diff --git a/crates/dash_llvm_jit_backend/src/codegen/mod.rs b/crates/dash_llvm_jit_backend/src/codegen/mod.rs index 066dd9a7..b3f77e05 100644 --- a/crates/dash_llvm_jit_backend/src/codegen/mod.rs +++ b/crates/dash_llvm_jit_backend/src/codegen/mod.rs @@ -349,6 +349,8 @@ impl<'a, 'q, Q: CodegenQuery> CodegenCtxt<'a, 'q, Q> { } Instruction::Pop => drop(stack.pop()), Instruction::Jmp => { + // TODO: do we not need to read the count and jump state? + panic!(); let bb = &self.bb_map[&bbk]; let Some(BasicBlockSuccessor::Unconditional(target)) = &bb.successor else { panic!("unmatched basic block successor"); @@ -378,7 +380,12 @@ impl<'a, 'q, Q: CodegenQuery> CodegenCtxt<'a, 'q, Q> { let count = dcx.next_wide_signed(); let _target_ip = usize::try_from(index as i16 + count + 3).unwrap(); let bb = &self.bb_map[&bbk]; - let Some(BasicBlockSuccessor::Conditional { true_ip, false_ip, action: Some(action) }) = bb.successor else { + let Some(BasicBlockSuccessor::Conditional { + true_ip, + false_ip, + action: Some(action), + }) = bb.successor + else { panic!("unmatched basic block successor"); }; diff --git a/crates/dash_middle/src/compiler/constant.rs b/crates/dash_middle/src/compiler/constant.rs index 983e1135..cae740a4 100755 --- a/crates/dash_middle/src/compiler/constant.rs +++ b/crates/dash_middle/src/compiler/constant.rs @@ -32,6 +32,14 @@ impl Buffer { self.0.set(buf); ret } + pub fn with_mut(&self, fun: impl FnOnce(&mut [u8]) -> R) -> R { + let mut buf = self.0.take(); + // see above + debug_assert!(!buf.is_empty()); + let ret = fun(&mut buf); + self.0.set(buf); + ret + } } #[cfg(feature = "format")] diff --git a/crates/dash_typed_cfg/src/passes/bb_generation.rs b/crates/dash_typed_cfg/src/passes/bb_generation.rs index fb639f10..5bb653c4 100644 --- a/crates/dash_typed_cfg/src/passes/bb_generation.rs +++ b/crates/dash_typed_cfg/src/passes/bb_generation.rs @@ -62,8 +62,9 @@ pub fn find_labels(bytecode: &[u8]) -> Result { match instr { // Instructions we care about: Instruction::Jmp => { + let _state = dcx.next_byte(); let count = dcx.next_wide_signed(); - let target_ip = usize::try_from(index as i16 + count + 3).unwrap(); + let target_ip = usize::try_from(index as i16 + count + 4).unwrap(); labels.push(LabelKind::UnconditionalJumpTarget { target: target_ip }); } Instruction::JmpFalseP @@ -176,8 +177,9 @@ impl<'a, 'q, Q: BBGenerationQuery> BBGenerationCtxt<'a, 'q, Q> { match instr { // Instructions we care about: Instruction::Jmp => { + let _state = dcx.next_byte(); let count = dcx.next_wide_signed(); - let target_ip = usize::try_from(index as i16 + count + 3).unwrap(); + let target_ip = usize::try_from(index as i16 + count + 4).unwrap(); let this = self.bbs.get_mut(¤t_bb_ip).unwrap(); assert!(this.successor.is_none()); diff --git a/crates/dash_typed_cfg/src/passes/type_infer.rs b/crates/dash_typed_cfg/src/passes/type_infer.rs index 750e2a08..8df6954f 100644 --- a/crates/dash_typed_cfg/src/passes/type_infer.rs +++ b/crates/dash_typed_cfg/src/passes/type_infer.rs @@ -161,8 +161,9 @@ impl<'a, 'q, Q: TypeInferQuery> TypeInferCtxt<'a, 'q, Q> { ty_stack.pop(); } Instruction::Jmp => { + let _state = dcx.next_byte(); let count = dcx.next_wide_signed(); - let _target_ip = usize::try_from(index as i16 + count + 3).unwrap(); + let _target_ip = usize::try_from(index as i16 + count + 4).unwrap(); let bb = &self.bbs[&bbk]; let Some(BasicBlockSuccessor::Unconditional(succ)) = bb.successor else { @@ -194,7 +195,12 @@ impl<'a, 'q, Q: TypeInferQuery> TypeInferCtxt<'a, 'q, Q> { let _target_ip = usize::try_from(index as i16 + count + 3).unwrap(); let bb = &self.bbs[&bbk]; - let Some(BasicBlockSuccessor::Conditional { true_ip: true_, false_ip: false_, action }) = bb.successor else { + let Some(BasicBlockSuccessor::Conditional { + true_ip: true_, + false_ip: false_, + action, + }) = bb.successor + else { panic!("unmatched basic block successor"); }; diff --git a/crates/dash_typed_cfg/src/util.rs b/crates/dash_typed_cfg/src/util.rs index d336f5cb..6979721b 100644 --- a/crates/dash_typed_cfg/src/util.rs +++ b/crates/dash_typed_cfg/src/util.rs @@ -80,7 +80,10 @@ impl<'a> DecodeCtxt<'a> { | Instruction::Ne | Instruction::StrictEq | Instruction::StrictNe => {} - Instruction::Jmp => drop(self.next_wide()), + Instruction::Jmp => { + self.next_byte(); + self.next_wide(); + } Instruction::JmpFalseP | Instruction::JmpNullishP | Instruction::JmpTrueP | Instruction::JmpUndefinedP => { panic!("Conditional jumps cannot be ignored") } diff --git a/crates/dash_vm/src/dispatch.rs b/crates/dash_vm/src/dispatch.rs index b7451783..0304af68 100755 --- a/crates/dash_vm/src/dispatch.rs +++ b/crates/dash_vm/src/dispatch.rs @@ -899,6 +899,17 @@ mod handlers { } pub fn jmp<'sc, 'vm>(mut cx: DispatchContext<'sc, 'vm>) -> Result, Unrooted> { + let ip = cx.active_frame().ip; + let state = cx.fetch_and_inc_ip(); + if state == 100 { + cx.active_frame().function.buffer.with_mut(|b| { + b[ip] = 0; + }); + } else { + cx.active_frame().function.buffer.with_mut(|b| { + b[ip] += 1; + }); + } let offset = cx.fetchw_and_inc_ip() as i16; let frame = cx.active_frame_mut();