Skip to content

Commit

Permalink
Add support of lookupswitch ops
Browse files Browse the repository at this point in the history
  • Loading branch information
hextriclosan committed Oct 22, 2024
1 parent fff3fe7 commit 9170e54
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 0 deletions.
12 changes: 12 additions & 0 deletions tests/should_do_trivial_switch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mod utils;
use utils::get_int;
use utils::setup;

#[test]
fn should_do_trivial_switch() {
let mut vm = setup();
let last_frame_value = vm
.run("samples.javacore.switches.trivial.SwitchExample")
.unwrap();
assert_eq!(300, get_int(last_frame_value))
}
30 changes: 30 additions & 0 deletions tests/test_data/SwitchExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package samples.javacore.switches.trivial;

public class SwitchExample {

public static void main(String[] args) {
int value = 30;
int result = switched(value);
}

private static int switched(int value) {
int result;
switch (value) {
case 10:
result = 100;
break;
case 20:
result = 200;
break;
case 30:
result = 300;
break;
default:
result = -1;
break;
}

return result;
}

}
Binary file not shown.
42 changes: 42 additions & 0 deletions vm/src/execution_engine/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,35 @@ impl Engine {
stack_frame.advance_pc(offset);
println!("GOTO -> offset={offset}");
}
LOOKUPSWITCH => {
let key = stack_frame.pop();
let instruction_pc = stack_frame.pc() as i16;
stack_frame.adjust_pc_to_4();

stack_frame.advance_pc(-1);
let default_offset = Self::extract_four_bytes(stack_frame) as i16;
let npairs = Self::extract_four_bytes(stack_frame);

let mut match_found = false;
for _ in 0..npairs {
let case_key = Self::extract_four_bytes(stack_frame);
let offset = Self::extract_four_bytes(stack_frame) as i16;

if key == case_key {
let current_pc = stack_frame.pc() as i16;
stack_frame.advance_pc(offset + instruction_pc - current_pc);
match_found = true;
break;
}
}

if !match_found {
let current_pc = stack_frame.pc() as i16;
stack_frame.advance_pc(default_offset + instruction_pc - current_pc);
}

println!("LOOKUPSWITCH -> default_offset={default_offset}, npairs={npairs}");
}
IRETURN => {
let ret = stack_frame.pop();
stack_frames.pop();
Expand Down Expand Up @@ -1564,6 +1593,19 @@ impl Engine {
(high << 8) | (low)
}

fn extract_four_bytes(stack_frame: &mut StackFrame) -> i32 {
stack_frame.incr_pc();
let byte1 = stack_frame.get_bytecode_byte() as u32;
stack_frame.incr_pc();
let byte2 = stack_frame.get_bytecode_byte() as u32;
stack_frame.incr_pc();
let byte3 = stack_frame.get_bytecode_byte() as u32;
stack_frame.incr_pc();
let byte4 = stack_frame.get_bytecode_byte() as u32;

((byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4) as i32
}

fn branch<T>(op: impl Fn(T, T) -> bool, stack_frame: &mut StackFrame, op_code: &str)
where
T: PartialOrd + TryFrom<i32> + Copy + std::fmt::Display,
Expand Down
11 changes: 11 additions & 0 deletions vm/src/stack/stack_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ impl<'a> StackFrame {
self.advance_pc(1)
}

pub fn adjust_pc_to_4(&mut self) {
while self.pc % 4 != 0 {
self.pc += 1;
}
}

pub fn pc(&self) -> usize {
println!("bytecode_ref: {:?}", self.bytecode_ref);
self.pc
}

pub(crate) fn advance_pc(&mut self, offset: i16) {
if offset >= 0 {
self.pc += offset as usize;
Expand Down

0 comments on commit 9170e54

Please sign in to comment.