Char arrays
This commit is contained in:
parent
6610b09c16
commit
c6e4ecec3d
6 changed files with 407 additions and 55 deletions
160
src/jvm.rs
160
src/jvm.rs
|
@ -193,7 +193,7 @@ impl JVM {
|
|||
);
|
||||
}
|
||||
|
||||
fn make_primitive_class(&mut self, class_name: &str, class_descriptor: &str) -> ObjectReference {
|
||||
fn make_primitive_class(&mut self, class_name: &str, class_descriptor: &str, string_names: bool) -> ObjectReference {
|
||||
let class_class_index = self.class_store.class_idx_from_name(&String::from("java/lang/Class")).unwrap();
|
||||
let data_class_index = self.class_store.class_idx_from_name(&String::from("::NativeClassData")).unwrap();
|
||||
|
||||
|
@ -209,15 +209,17 @@ impl JVM {
|
|||
&self.class_store,
|
||||
).unwrap();
|
||||
|
||||
let name_string_ref = self.heap_area.make_handmade_string(&class_name.into(), &self.class_store);
|
||||
// set name string object
|
||||
self.heap_area.object_area.set_object_field(
|
||||
primitive_class_object,
|
||||
"name",
|
||||
FieldValue::Reference(name_string_ref),
|
||||
class_class_index,
|
||||
&self.class_store,
|
||||
).unwrap();
|
||||
if string_names {
|
||||
let name_string_ref = self.heap_area.make_handmade_string(&class_name.into(), &self.class_store);
|
||||
// set name string object
|
||||
self.heap_area.object_area.set_object_field(
|
||||
primitive_class_object,
|
||||
"name",
|
||||
FieldValue::Reference(name_string_ref),
|
||||
class_class_index,
|
||||
&self.class_store,
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
// set native name index on class data
|
||||
self.heap_area.object_area.set_object_field(
|
||||
|
@ -365,22 +367,7 @@ impl JVM {
|
|||
|
||||
self.heap_area.fill_byte_cache(&self.class_store);
|
||||
|
||||
self.class_store.primitive_classes.int_class = self.make_primitive_class("int", "I");
|
||||
self.class_store.primitive_classes.byte_class = self.make_primitive_class("byte", "B");
|
||||
self.class_store.primitive_classes.char_class = self.make_primitive_class("char", "C");
|
||||
self.class_store.primitive_classes.long_class = self.make_primitive_class("long", "J");
|
||||
self.class_store.primitive_classes.float_class = self.make_primitive_class("float", "F");
|
||||
self.class_store.primitive_classes.short_class = self.make_primitive_class("short", "S");
|
||||
self.class_store.primitive_classes.double_class = self.make_primitive_class("double", "D");
|
||||
self.class_store.primitive_classes.boolean_class = self.make_primitive_class("boolean", "Z");
|
||||
|
||||
self.make_array_class(
|
||||
self.class_store.primitive_classes.int_class,
|
||||
AbstractTypeDescription {
|
||||
array_level: 0,
|
||||
kind: AbstractTypeKind::Int(),
|
||||
}
|
||||
);
|
||||
self.class_store.primitive_classes.byte_class = self.make_primitive_class("byte", "B", false);
|
||||
self.make_array_class(
|
||||
self.class_store.primitive_classes.byte_class,
|
||||
AbstractTypeDescription {
|
||||
|
@ -388,6 +375,39 @@ impl JVM {
|
|||
kind: AbstractTypeKind::Byte(),
|
||||
}
|
||||
);
|
||||
{
|
||||
// we can only make a byte class name after the byte array is loaded
|
||||
let string_ref = self.heap_area.make_handmade_string(&String::from("byte"), &self.class_store);
|
||||
self.heap_area.object_area.set_object_field(
|
||||
self.class_store.primitive_classes.byte_class,
|
||||
"name",
|
||||
FieldValue::Reference(string_ref),
|
||||
class_class_index,
|
||||
&self.class_store
|
||||
).unwrap();
|
||||
}
|
||||
self.class_store.primitive_classes.int_class = self.make_primitive_class("int", "I", true);
|
||||
self.class_store.primitive_classes.char_class = self.make_primitive_class("char", "C", true);
|
||||
self.class_store.primitive_classes.long_class = self.make_primitive_class("long", "J", true);
|
||||
self.class_store.primitive_classes.float_class = self.make_primitive_class("float", "F", true);
|
||||
self.class_store.primitive_classes.short_class = self.make_primitive_class("short", "S", true);
|
||||
self.class_store.primitive_classes.double_class = self.make_primitive_class("double", "D", true);
|
||||
self.class_store.primitive_classes.boolean_class = self.make_primitive_class("boolean", "Z", true);
|
||||
|
||||
self.make_array_class(
|
||||
self.class_store.primitive_classes.char_class,
|
||||
AbstractTypeDescription {
|
||||
array_level: 0,
|
||||
kind: AbstractTypeKind::Char(),
|
||||
}
|
||||
);
|
||||
self.make_array_class(
|
||||
self.class_store.primitive_classes.int_class,
|
||||
AbstractTypeDescription {
|
||||
array_level: 0,
|
||||
kind: AbstractTypeKind::Int(),
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
let string_refs = arguments.iter()
|
||||
|
@ -672,7 +692,7 @@ impl JVM {
|
|||
|
||||
let element = self.heap_area.object_area.get_array_element(array_reference, element_index);
|
||||
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(element)))?;
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(element))?;
|
||||
},
|
||||
|
||||
Instruction::BranchAlways(branch_offset) => {
|
||||
|
@ -690,6 +710,16 @@ impl JVM {
|
|||
}
|
||||
}
|
||||
|
||||
Instruction::BranchIntGreaterEquals(branch_offset) => {
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
|
||||
if value_1 >= value_2 {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
frame.instruction_pointer = if branch_offset < 0 { frame.instruction_pointer - branch_offset.abs() as u32} else { frame.instruction_pointer + branch_offset.abs() as u32};
|
||||
}
|
||||
}
|
||||
|
||||
Instruction::BranchIntInequality(branch_offset) => {
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
|
@ -774,6 +804,26 @@ impl JVM {
|
|||
}
|
||||
}
|
||||
|
||||
Instruction::CheckCast(classref_index) => {
|
||||
// TODO: Class loading checks
|
||||
let class_name = class.gather_class(classref_index)?;
|
||||
let class_index = self.class_store.class_idx_from_name(class_name).unwrap();
|
||||
let class_object_ref = self.class_store.get_class_objectref_from_index(class_index);
|
||||
let native_class_description = self.heap_area.object_area.get_class_ref_native_class_name(class_object_ref, &self.class_store);
|
||||
let class_description = AbstractTypeDescription::parse_full(native_class_description)?;
|
||||
|
||||
let object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
||||
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
|
||||
let object_description = AbstractTypeDescription::parse_full(native_class_name)?;
|
||||
|
||||
if ! self.class_store.are_types_compatible(&object_description, &class_description) {
|
||||
// TODO: Throw Exception
|
||||
return Err(Error::RunTimeError(format!("Trying to cast an object of type {native_class_name} to {class_name}")))
|
||||
}
|
||||
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(object)))?;
|
||||
}
|
||||
|
||||
Instruction::CompareFloatG() => {
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
|
||||
|
@ -886,8 +936,27 @@ impl JVM {
|
|||
wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(fetched_value))?;
|
||||
}
|
||||
|
||||
Instruction::IncrementLocalInt(index, constant) => {
|
||||
let int = wrap_stackframe_error(class, method, frame.load_local_int(index as u16))?;
|
||||
|
||||
wrap_stackframe_error(class, method, frame.store_local(index as u16, StackValue::Int(int + constant as i32)))?;
|
||||
}
|
||||
|
||||
Instruction::InstanceOf(classref_index) => {
|
||||
// TODO: Class loading checks
|
||||
let class_name = class.gather_class(classref_index)?;
|
||||
let class_index = self.class_store.class_idx_from_name(class_name).unwrap();
|
||||
let class_object_ref = self.class_store.get_class_objectref_from_index(class_index);
|
||||
let native_class_description = self.heap_area.object_area.get_class_ref_native_class_name(class_object_ref, &self.class_store);
|
||||
let class_description = AbstractTypeDescription::parse_full(native_class_description)?;
|
||||
|
||||
let object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
||||
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
|
||||
let object_description = AbstractTypeDescription::parse_full(native_class_name)?;
|
||||
|
||||
let instruction_result = if self.class_store.are_types_compatible(&object_description, &class_description) { 1 } else { 0 };
|
||||
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(instruction_result)))?;
|
||||
}
|
||||
|
||||
Instruction::InvokeSpecial(methodref_index) => {
|
||||
|
@ -1085,6 +1154,15 @@ impl JVM {
|
|||
}
|
||||
}
|
||||
|
||||
Instruction::LoadFromBArray() => {
|
||||
let index = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
let array = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
||||
|
||||
let element = self.heap_area.object_area.get_array_element(array, index);
|
||||
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(element))?;
|
||||
}
|
||||
|
||||
Instruction::LoadConstant(index) => {
|
||||
// TODO: Handle error instead of unwrap
|
||||
match class.pool_entry(index as u16).unwrap() {
|
||||
|
@ -1283,6 +1361,7 @@ impl JVM {
|
|||
Instruction::NewPrimitiveArray(array_type) => {
|
||||
let array_capacity = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
|
||||
const CHAR: u8 = 5;
|
||||
const BYTE: u8 = 8;
|
||||
let array_ref = match array_type {
|
||||
BYTE => {
|
||||
|
@ -1291,6 +1370,12 @@ impl JVM {
|
|||
array_ref
|
||||
}
|
||||
|
||||
CHAR => {
|
||||
let array_ref = self.heap_area.make_primitive_char_array(array_capacity as usize, &self.class_store);
|
||||
|
||||
array_ref
|
||||
}
|
||||
|
||||
_ => todo!()
|
||||
};
|
||||
|
||||
|
@ -1333,6 +1418,9 @@ impl JVM {
|
|||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(2.0)))?;
|
||||
}
|
||||
|
||||
Instruction::PushConstIntM1() => {
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(-1)))?;
|
||||
}
|
||||
Instruction::PushConstInt0() => {
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(0)))?;
|
||||
}
|
||||
|
@ -1364,6 +1452,7 @@ impl JVM {
|
|||
_ => match wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))? {
|
||||
StackValue::Int(i) => FieldValue::Int(i),
|
||||
StackValue::Reference(r) => FieldValue::Reference(r),
|
||||
StackValue::Float(f) => FieldValue::Float(f),
|
||||
stack_value @ _ => {
|
||||
println!("{stack_value:?}");
|
||||
todo!()
|
||||
|
@ -1511,31 +1600,38 @@ impl JVM {
|
|||
self.heap_area.object_area.set_array_element(array_ref, index as usize, FieldValue::Reference(value));
|
||||
}
|
||||
|
||||
Instruction::SubtractInt() => {
|
||||
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 - value_2)))?;
|
||||
}
|
||||
|
||||
Instruction::StoreLocalInt(index) => {
|
||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
|
||||
wrap_stackframe_error(class, method, frame.store_local(index as u16, StackValue::Int(int)))?;
|
||||
},
|
||||
}
|
||||
Instruction::StoreLocalInt0() => {
|
||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
|
||||
wrap_stackframe_error(class, method, frame.store_local(0, StackValue::Int(int)))?;
|
||||
},
|
||||
}
|
||||
Instruction::StoreLocalInt1() => {
|
||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
|
||||
wrap_stackframe_error(class, method, frame.store_local(1, StackValue::Int(int)))?;
|
||||
},
|
||||
}
|
||||
Instruction::StoreLocalInt2() => {
|
||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
|
||||
wrap_stackframe_error(class, method, frame.store_local(2, StackValue::Int(int)))?;
|
||||
},
|
||||
}
|
||||
Instruction::StoreLocalInt3() => {
|
||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
|
||||
wrap_stackframe_error(class, method, frame.store_local(3, StackValue::Int(int)))?;
|
||||
},
|
||||
}
|
||||
|
||||
Instruction::StoreReference0() => {
|
||||
let reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue