Skip to content

Commit 0278d9d

Browse files
committed
refactor: update CallStack to store reference to VM
1 parent 3342323 commit 0278d9d

35 files changed

+252
-379
lines changed

ristretto_vm/src/call_stack.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,46 @@
11
use crate::arguments::Arguments;
2-
use crate::Error::PoisonedLock;
2+
use crate::Error::{PoisonedLock, RuntimeError};
33
use crate::{native_methods, Frame, Result, VM};
44
use ristretto_classloader::Error::MethodNotFound;
55
use ristretto_classloader::{Class, Method, Value};
6-
use std::sync::{Arc, RwLock};
6+
use std::sync::{Arc, RwLock, Weak};
77
use tracing::{debug, event_enabled, Level};
88

99
/// A call stack is a stack of frames that are executed in order.
1010
#[derive(Debug, Default)]
1111
pub struct CallStack {
12+
pub(crate) vm: Weak<VM>,
1213
pub(crate) frames: Arc<RwLock<Vec<Arc<RwLock<Frame>>>>>,
1314
}
1415

1516
impl CallStack {
1617
/// Create a new call stack.
1718
#[must_use]
18-
pub fn new() -> Self {
19+
pub fn new(vm: &Weak<VM>) -> Self {
1920
CallStack {
21+
vm: vm.clone(),
2022
frames: Arc::new(RwLock::new(Vec::new())),
2123
}
2224
}
2325

26+
/// Get the virtual machine that owns the call stack.
27+
///
28+
/// # Errors
29+
/// if the virtual machine cannot be accessed.
30+
pub fn vm(&self) -> Result<Arc<VM>> {
31+
match self.vm.upgrade() {
32+
Some(vm) => Ok(vm),
33+
None => Err(RuntimeError("VM is not available".to_string())),
34+
}
35+
}
36+
2437
/// Add a new frame to the call stack and invoke the method. To invoke a method on an object
2538
/// reference, the object reference must be the first argument in the arguments vector.
2639
///
2740
/// # Errors
2841
/// if the method cannot be invoked.
2942
pub fn execute(
3043
&self,
31-
vm: &VM,
3244
class: &Arc<Class>,
3345
method: &Arc<Method>,
3446
arguments: Vec<Value>,
@@ -47,7 +59,7 @@ impl CallStack {
4759

4860
let (result, frame_added) = if let Some(rust_method) = rust_method {
4961
let arguments = Arguments::new(arguments);
50-
let result = rust_method(vm, self, arguments);
62+
let result = rust_method(self, arguments);
5163
(result, false)
5264
} else if method.is_native() {
5365
return Err(MethodNotFound {
@@ -71,7 +83,7 @@ impl CallStack {
7183
let mut frame = frame
7284
.write()
7385
.map_err(|error| PoisonedLock(error.to_string()))?;
74-
let result = frame.execute(vm, self);
86+
let result = frame.execute(self);
7587
(result, true)
7688
};
7789

ristretto_vm/src/frame.rs

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::instruction::{
2121
ret, ret_w, saload, sastore, sipush, swap, tableswitch,
2222
};
2323
use crate::Error::{InvalidOperand, InvalidProgramCounter};
24-
use crate::{CallStack, LocalVariables, OperandStack, Result, VM};
24+
use crate::{CallStack, LocalVariables, OperandStack, Result};
2525
use ristretto_classfile::attributes::Instruction;
2626
use ristretto_classloader::{Class, Method, Value};
2727
use std::sync::Arc;
@@ -72,7 +72,7 @@ impl Frame {
7272
/// # Errors
7373
/// * if the program counter is invalid
7474
/// * if an invalid instruction is encountered
75-
pub fn execute(&mut self, vm: &VM, call_stack: &CallStack) -> Result<Option<Value>> {
75+
pub fn execute(&mut self, call_stack: &CallStack) -> Result<Option<Value>> {
7676
// TODO: avoid cloning code
7777
let code = self.method.code().clone();
7878

@@ -85,7 +85,7 @@ impl Frame {
8585
self.debug_execute(instruction)?;
8686
}
8787

88-
let result = self.process(vm, call_stack, instruction);
88+
let result = self.process(call_stack, instruction);
8989
match result {
9090
Ok(Continue) => self.program_counter += 1,
9191
Ok(ContinueAtPosition(pc)) => self.program_counter = pc,
@@ -126,7 +126,6 @@ impl Frame {
126126
#[expect(clippy::too_many_lines)]
127127
fn process(
128128
&mut self,
129-
vm: &VM,
130129
call_stack: &CallStack,
131130
instruction: &Instruction,
132131
) -> Result<ExecutionResult> {
@@ -149,8 +148,8 @@ impl Frame {
149148
Instruction::Dconst_1 => dconst_1(&mut self.stack),
150149
Instruction::Bipush(value) => bipush(&mut self.stack, *value),
151150
Instruction::Sipush(value) => sipush(&mut self.stack, *value),
152-
Instruction::Ldc(index) => ldc(vm, call_stack, self, *index),
153-
Instruction::Ldc_w(index) => ldc_w(vm, call_stack, self, *index),
151+
Instruction::Ldc(index) => ldc(call_stack, self, *index),
152+
Instruction::Ldc_w(index) => ldc_w(call_stack, self, *index),
154153
Instruction::Ldc2_w(index) => ldc2_w(self, *index),
155154
Instruction::Iload(index) => iload(&self.locals, &mut self.stack, *index),
156155
Instruction::Lload(index) => lload(&self.locals, &mut self.stack, *index),
@@ -324,14 +323,12 @@ impl Frame {
324323
Instruction::Areturn => areturn(&mut self.stack),
325324
Instruction::Return => Ok(Return(None)),
326325
Instruction::Getstatic(index) => getstatic(
327-
vm,
328326
call_stack,
329327
&mut self.stack,
330328
self.class.constant_pool(),
331329
*index,
332330
),
333331
Instruction::Putstatic(index) => putstatic(
334-
vm,
335332
call_stack,
336333
&mut self.stack,
337334
self.class.constant_pool(),
@@ -344,51 +341,45 @@ impl Frame {
344341
putfield(&mut self.stack, self.class.constant_pool(), *index)
345342
}
346343
Instruction::Invokevirtual(index) => invokevirtual(
347-
vm,
348344
call_stack,
349345
&mut self.stack,
350346
self.class.constant_pool(),
351347
*index,
352348
),
353349
Instruction::Invokespecial(index) => invokespecial(
354-
vm,
355350
call_stack,
356351
&mut self.stack,
357352
self.class.constant_pool(),
358353
*index,
359354
),
360355
Instruction::Invokestatic(index) => invokestatic(
361-
vm,
362356
call_stack,
363357
&mut self.stack,
364358
self.class.constant_pool(),
365359
*index,
366360
),
367361
Instruction::Invokeinterface(index, count) => invokeinterface(
368-
vm,
369362
call_stack,
370363
&mut self.stack,
371364
self.class.constant_pool(),
372365
*index,
373366
*count,
374367
),
375368
Instruction::Invokedynamic(index) => invokedynamic(
376-
vm,
377369
call_stack,
378370
&mut self.stack,
379371
self.class.constant_pool(),
380372
*index,
381373
),
382374
Instruction::New(index) => new(
383-
vm,
384375
call_stack,
385376
&mut self.stack,
386377
self.class.constant_pool(),
387378
*index,
388379
),
389380
Instruction::Newarray(array_type) => newarray(&mut self.stack, array_type),
390381
Instruction::Anewarray(index) => {
391-
anewarray(vm, call_stack, &mut self.stack, &self.class, *index)
382+
anewarray(call_stack, &mut self.stack, &self.class, *index)
392383
}
393384
Instruction::Arraylength => arraylength(&mut self.stack),
394385
Instruction::Athrow => todo!(),
@@ -419,7 +410,6 @@ impl Frame {
419410
})
420411
}
421412
Instruction::Multianewarray(index, dimensions) => multianewarray(
422-
vm,
423413
call_stack,
424414
&mut self.stack,
425415
&self.class,
@@ -458,29 +448,30 @@ mod tests {
458448
use super::*;
459449
use crate::call_stack::CallStack;
460450
use crate::configuration::ConfigurationBuilder;
451+
use crate::VM;
461452
use ristretto_classloader::ClassPath;
462453
use std::path::PathBuf;
463454

464-
fn get_class(class_name: &str) -> Result<(VM, CallStack, Arc<Class>)> {
455+
fn get_class(class_name: &str) -> Result<(CallStack, Arc<Class>)> {
465456
let cargo_manifest = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
466457
let classes_path = cargo_manifest.join("../classes");
467458
let class_path = ClassPath::from(classes_path.to_string_lossy());
468459
let configuration = ConfigurationBuilder::new()
469460
.class_path(class_path.clone())
470461
.build();
471462
let vm = VM::new(configuration)?;
472-
let call_stack = CallStack::new();
463+
let call_stack = CallStack::new(&Arc::downgrade(&vm));
473464
let class = vm.class(&call_stack, class_name)?;
474-
Ok((vm, call_stack, class))
465+
Ok((call_stack, class))
475466
}
476467

477468
#[test]
478469
fn test_execute() -> Result<()> {
479-
let (vm, call_stack, class) = get_class("Expressions")?;
470+
let (call_stack, class) = get_class("Expressions")?;
480471
let method = class.method("add", "(II)I").expect("method not found");
481472
let arguments = vec![Value::Int(1), Value::Int(2)];
482473
let mut frame = Frame::new(&class, &method, arguments)?;
483-
let result = frame.execute(&vm, &call_stack)?;
474+
let result = frame.execute(&call_stack)?;
484475
assert!(matches!(result, Some(Value::Int(3))));
485476
Ok(())
486477
}
@@ -495,8 +486,8 @@ mod tests {
495486

496487
#[test]
497488
fn test_process_nop() -> Result<()> {
498-
let (vm, call_stack, mut frame) = crate::test::frame()?;
499-
let process_result = frame.process(&vm, &call_stack, &Instruction::Nop)?;
489+
let (_vm, call_stack, mut frame) = crate::test::frame()?;
490+
let process_result = frame.process(&call_stack, &Instruction::Nop)?;
500491
assert_eq!(Continue, process_result);
501492
assert!(frame.locals.is_empty());
502493
assert!(frame.stack.is_empty());
@@ -505,8 +496,8 @@ mod tests {
505496

506497
#[test]
507498
fn test_process_return() -> Result<()> {
508-
let (vm, call_stack, mut frame) = crate::test::frame()?;
509-
let process_result = frame.process(&vm, &call_stack, &Instruction::Return)?;
499+
let (_vm, call_stack, mut frame) = crate::test::frame()?;
500+
let process_result = frame.process(&call_stack, &Instruction::Return)?;
510501
assert!(matches!(process_result, Return(None)));
511502
Ok(())
512503
}
@@ -518,27 +509,27 @@ mod tests {
518509

519510
#[test]
520511
fn test_process_monitorenter() -> Result<()> {
521-
let (vm, call_stack, mut frame) = crate::test::frame()?;
512+
let (_vm, call_stack, mut frame) = crate::test::frame()?;
522513
frame.stack.push_object(None)?;
523-
let process_result = frame.process(&vm, &call_stack, &Instruction::Monitorenter)?;
514+
let process_result = frame.process(&call_stack, &Instruction::Monitorenter)?;
524515
assert_eq!(Continue, process_result);
525516
Ok(())
526517
}
527518

528519
#[test]
529520
fn test_process_monitorexit() -> Result<()> {
530-
let (vm, call_stack, mut frame) = crate::test::frame()?;
521+
let (_vm, call_stack, mut frame) = crate::test::frame()?;
531522
frame.stack.push_object(None)?;
532-
let process_result = frame.process(&vm, &call_stack, &Instruction::Monitorexit)?;
523+
let process_result = frame.process(&call_stack, &Instruction::Monitorexit)?;
533524
assert_eq!(Continue, process_result);
534525
Ok(())
535526
}
536527

537528
#[test]
538529
fn test_process_wide() -> Result<()> {
539-
let (vm, call_stack, mut frame) = crate::test::frame()?;
530+
let (_vm, call_stack, mut frame) = crate::test::frame()?;
540531
assert!(matches!(
541-
frame.process(&vm, &call_stack, &Instruction::Wide),
532+
frame.process(&call_stack, &Instruction::Wide),
542533
Err(InvalidOperand {
543534
expected,
544535
actual
@@ -549,8 +540,8 @@ mod tests {
549540

550541
#[test]
551542
fn test_process_breakpoint() -> Result<()> {
552-
let (vm, call_stack, mut frame) = crate::test::frame()?;
553-
let process_result = frame.process(&vm, &call_stack, &Instruction::Breakpoint)?;
543+
let (_vm, call_stack, mut frame) = crate::test::frame()?;
544+
let process_result = frame.process(&call_stack, &Instruction::Breakpoint)?;
554545
assert_eq!(Continue, process_result);
555546
assert!(frame.locals.is_empty());
556547
assert!(frame.stack.is_empty());
@@ -559,8 +550,8 @@ mod tests {
559550

560551
#[test]
561552
fn test_process_impdep1() -> Result<()> {
562-
let (vm, call_stack, mut frame) = crate::test::frame()?;
563-
let process_result = frame.process(&vm, &call_stack, &Instruction::Impdep1)?;
553+
let (_vm, call_stack, mut frame) = crate::test::frame()?;
554+
let process_result = frame.process(&call_stack, &Instruction::Impdep1)?;
564555
assert_eq!(Continue, process_result);
565556
assert!(frame.locals.is_empty());
566557
assert!(frame.stack.is_empty());
@@ -569,8 +560,8 @@ mod tests {
569560

570561
#[test]
571562
fn test_process_impdep2() -> Result<()> {
572-
let (vm, call_stack, mut frame) = crate::test::frame()?;
573-
let process_result = frame.process(&vm, &call_stack, &Instruction::Impdep2)?;
563+
let (_vm, call_stack, mut frame) = crate::test::frame()?;
564+
let process_result = frame.process(&call_stack, &Instruction::Impdep2)?;
574565
assert_eq!(Continue, process_result);
575566
assert!(frame.locals.is_empty());
576567
assert!(frame.stack.is_empty());

0 commit comments

Comments
 (0)