2024-09-02 19:28:22 +02:00
use crate ::classfile ::{ JavaClassFile , AttributeData } ;
2024-09-02 15:42:42 +02:00
use crate ::heap_area ::ObjectReference ;
2024-08-30 15:33:54 +02:00
#[ derive(Copy, Clone, Debug) ]
2024-09-02 17:46:00 +02:00
pub enum StackValue {
2024-08-30 15:33:54 +02:00
Boolean ( bool ) ,
Byte ( u8 ) ,
Char ( u16 ) ,
Short ( u16 ) ,
2024-09-02 15:42:42 +02:00
Int ( i32 ) ,
Float ( f32 ) ,
Reference ( ObjectReference ) ,
2024-08-30 15:33:54 +02:00
ReturnAddress ( u32 ) ,
Double0 ( u32 ) ,
Double1 ( u32 ) ,
Long0 ( u32 ) ,
Long1 ( u32 ) ,
Empty ( ) ,
}
#[ derive(Debug) ]
pub struct OperandStack {
2024-09-02 17:46:00 +02:00
stack : Box < [ StackValue ] > ,
2024-08-30 15:33:54 +02:00
depth : u16 ,
}
2024-09-02 15:42:42 +02:00
#[ derive(Debug) ]
pub enum Error {
PushError ( String ) ,
LocalError ( String ) ,
}
2024-08-30 15:33:54 +02:00
impl OperandStack {
fn new ( size : u16 ) -> Self {
return OperandStack {
2024-09-02 17:46:00 +02:00
stack : vec ! [ StackValue ::Empty ( ) ; size . into ( ) ] . into_boxed_slice ( ) ,
2024-08-30 15:33:54 +02:00
depth : 0 ,
}
}
2024-09-02 15:42:42 +02:00
2024-09-02 17:46:00 +02:00
pub fn push ( & mut self , value : StackValue ) -> Result < ( ) , Error > {
2024-09-02 15:42:42 +02:00
if self . depth as usize = = self . stack . len ( ) {
return Err ( Error ::PushError ( format! ( " Trying to push onto full operand stack, capacity: {} , value: {:?} " , self . depth , value ) ) )
}
self . stack [ self . depth as usize ] = value ;
self . depth + = 1 ;
Ok ( ( ) )
}
2024-09-05 00:33:14 +02:00
pub fn pop_computational_1 ( & mut self , index : usize ) -> Result < StackValue , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
StackValue ::Long0 ( _ ) | StackValue ::Long1 ( _ ) | StackValue ::Double0 ( _ ) | StackValue ::Double1 ( _ ) = > {
Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected type with computational type 1 but found ' {:?} ' " , index , value ) ) )
} ,
_ = > Ok ( value ) ,
}
}
2024-09-02 15:42:42 +02:00
pub fn pop_boolean ( & mut self , index : usize ) -> Result < bool , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Boolean ( b ) = > Ok ( b ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Boolean but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_byte ( & mut self , index : usize ) -> Result < u8 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Byte ( b ) = > Ok ( b ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Byte but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_char ( & mut self , index : usize ) -> Result < u16 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Char ( c ) = > Ok ( c ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Char but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_short ( & mut self , index : usize ) -> Result < u16 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Short ( s ) = > Ok ( s ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Short but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_int ( & mut self , index : usize ) -> Result < i32 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Int ( i ) = > Ok ( i ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Int but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_float ( & mut self , index : usize ) -> Result < f32 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Float ( f ) = > Ok ( f ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Float but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_reference ( & mut self , index : usize ) -> Result < ObjectReference , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Reference ( o ) = > Ok ( o ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Reference but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_returnaddress ( & mut self , index : usize ) -> Result < u32 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::ReturnAddress ( a ) = > Ok ( a ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected ReturnAddress but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_double0 ( & mut self , index : usize ) -> Result < u32 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Double0 ( a ) = > Ok ( a ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Double0 but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_double1 ( & mut self , index : usize ) -> Result < u32 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Double1 ( a ) = > Ok ( a ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Double1 but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_long0 ( & mut self , index : usize ) -> Result < u32 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Long0 ( a ) = > Ok ( a ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Long0 but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_long1 ( & mut self , index : usize ) -> Result < u32 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let value = self . stack [ absolute_index ] ;
self . depth - = 1 ;
match value {
2024-09-02 17:46:00 +02:00
StackValue ::Long1 ( a ) = > Ok ( a ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function operand stack, expected Long1 but found ' {:?} ' " , index , value ) ) )
}
}
pub fn pop_double ( & mut self , index : usize ) -> Result < f64 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let higher_bytes = self . stack [ absolute_index ] ;
let lower_bytes = self . stack [ absolute_index + 1 ] ;
self . depth - = 2 ;
match ( higher_bytes , lower_bytes ) {
2024-09-02 17:46:00 +02:00
( StackValue ::Double0 ( hi ) , StackValue ::Double1 ( lo ) ) = > {
2024-09-02 15:42:42 +02:00
let v : u64 = ( ( hi as u64 ) < < 32 ) | lo as u64 ;
Ok (
f64 ::from_bits ( v )
)
} ,
_ = > Err ( Error ::LocalError ( format! ( " Mismatched types at index {} of the function operand stack, expected (Double0, Double1) but found ' {:?} ' " , index , ( higher_bytes , lower_bytes ) ) ) )
}
}
pub fn pop_long ( & mut self , index : usize ) -> Result < u64 , Error > {
let absolute_index = self . depth as usize - 1 - index ;
let higher_bytes = self . stack [ absolute_index ] ;
let lower_bytes = self . stack [ absolute_index + 1 ] ;
self . depth - = 2 ;
match ( higher_bytes , lower_bytes ) {
2024-09-02 17:46:00 +02:00
( StackValue ::Long0 ( hi ) , StackValue ::Long1 ( lo ) ) = > {
2024-09-02 15:42:42 +02:00
Ok ( ( ( hi as u64 ) < < 32 ) | lo as u64 )
} ,
_ = > Err ( Error ::LocalError ( format! ( " Mismatched types at index {} of the function operand stack, expected (Long0, Long1) but found ' {:?} ' " , index , ( higher_bytes , lower_bytes ) ) ) )
}
}
2024-08-30 15:33:54 +02:00
}
#[ derive(Debug) ]
pub struct StackFrame {
2024-09-02 17:46:00 +02:00
pub locals : Box < [ StackValue ] > ,
2024-09-02 11:28:00 +02:00
pub operand_stack : OperandStack ,
pub class_index : usize ,
pub method_index : u16 ,
pub instruction_pointer : u32 ,
2024-08-30 15:33:54 +02:00
}
impl StackFrame {
2024-09-02 17:46:00 +02:00
pub fn new ( classfile : & JavaClassFile , class_index : usize , method_index : u16 , arguments : & [ StackValue ] ) -> Self {
2024-08-30 15:33:54 +02:00
let method_info = & classfile . methods [ method_index as usize ] ;
let code_data = match & method_info . attributes [ method_info . code_attribute_index ] . data {
AttributeData ::Code ( data ) = > data ,
_ = > unreachable! ( ) ,
} ;
2024-09-02 17:46:00 +02:00
let mut locals = vec! [ StackValue ::Empty ( ) ; code_data . max_locals . into ( ) ] . into_boxed_slice ( ) ;
2024-09-02 11:28:00 +02:00
assert! ( locals . len ( ) > = arguments . len ( ) ) ;
for ( index , v ) in arguments . iter ( ) . enumerate ( ) {
locals [ index ] = * v ;
}
2024-08-30 15:33:54 +02:00
StackFrame {
2024-09-02 11:28:00 +02:00
locals ,
2024-08-30 15:33:54 +02:00
operand_stack : OperandStack ::new ( code_data . max_stack ) ,
2024-09-02 11:28:00 +02:00
class_index ,
2024-08-30 15:33:54 +02:00
method_index ,
instruction_pointer : 0 ,
}
}
2024-09-02 15:42:42 +02:00
pub fn load_local_int ( & self , index : u16 ) -> Result < i32 , Error > {
let local = self . locals [ index as usize ] ;
match local {
2024-09-02 17:46:00 +02:00
StackValue ::Int ( i ) = > Ok ( i ) ,
2024-09-02 15:42:42 +02:00
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function locals, expected Int but found ' {:?} ' " , index , local ) ) )
}
}
2024-09-05 00:33:14 +02:00
pub fn load_local_reference ( & self , index : u16 ) -> Result < ObjectReference , Error > {
let local = self . locals [ index as usize ] ;
match local {
StackValue ::Reference ( r ) = > Ok ( r ) ,
_ = > Err ( Error ::LocalError ( format! ( " Mismatched type at index {} of the function locals, expected Reference but found ' {:?} ' " , index , local ) ) )
}
}
2024-09-02 17:46:00 +02:00
pub fn store_local ( & mut self , index : u16 , value : StackValue ) -> Result < ( ) , Error > {
2024-09-02 15:42:42 +02:00
let field = self . locals . get_mut ( index as usize ) ;
match field {
Some ( f ) = > {
* f = value ;
Ok ( ( ) )
} ,
None = > {
Err ( Error ::LocalError ( format! ( " Tried to get local at index {} when max_locals is {} " , index , self . locals . len ( ) ) ) )
}
}
}
2024-08-30 15:33:54 +02:00
}