implement multianewarray

This commit is contained in:
Zack Buhman 2024-12-27 05:01:41 -06:00
parent 4f312ad42c
commit 168c0abbae
5 changed files with 106 additions and 22 deletions

View File

@ -9,6 +9,7 @@
#include "debug_class_file.h" #include "debug_class_file.h"
#include "memory_allocator.h" #include "memory_allocator.h"
#include "printf.h" #include "printf.h"
#include "field_size.h"
static void class_resolver_create_interfaces_hash_table(struct class_entry * class_entry) static void class_resolver_create_interfaces_hash_table(struct class_entry * class_entry)
{ {
@ -23,29 +24,13 @@ static void class_resolver_create_interfaces_hash_table(struct class_entry * cla
*/ */
} }
static int field_size(struct class_file * class_file, struct field_info * field_info) static int field_info_field_size(struct class_file * class_file, struct field_info * field_info)
{ {
struct constant * field_descriptor_constant = &class_file->constant_pool[field_info->descriptor_index - 1]; struct constant * field_descriptor_constant = &class_file->constant_pool[field_info->descriptor_index - 1];
#ifdef DEBUG #ifdef DEBUG
assert(field_descriptor_constant->tag == CONSTANT_Utf8); assert(field_descriptor_constant->tag == CONSTANT_Utf8);
#endif #endif
return field_size(field_descriptor_constant->utf8.bytes[0]);
switch (field_descriptor_constant->utf8.bytes[0]) {
case 'B': [[fallthrough]];
case 'C': [[fallthrough]];
case 'F': [[fallthrough]];
case 'I': [[fallthrough]];
case 'L': [[fallthrough]];
case 'S': [[fallthrough]];
case 'Z': [[fallthrough]];
case '[':
return 1;
case 'D': [[fallthrough]];
case 'J':
return 2;
default:
assert(false);
}
} }
static int32_t class_resolver_create_fields_hash_table(struct class_entry * class_entry) static int32_t class_resolver_create_fields_hash_table(struct class_entry * class_entry)
@ -72,10 +57,10 @@ static int32_t class_resolver_create_fields_hash_table(struct class_entry * clas
if (field_info->access_flags & FIELD_ACC_STATIC) { if (field_info->access_flags & FIELD_ACC_STATIC) {
field_entry[i].static_index = static_index; field_entry[i].static_index = static_index;
static_index += field_size(class_file, field_info); static_index += field_info_field_size(class_file, field_info);
} else { } else {
field_entry[i].instance_index = instance_index; field_entry[i].instance_index = instance_index;
instance_index += field_size(class_file, field_info); instance_index += field_info_field_size(class_file, field_info);
} }
field_entry[i].field_info = field_info; field_entry[i].field_info = field_info;

View File

@ -4,6 +4,7 @@
#include "class_resolver.h" #include "class_resolver.h"
#include "execute_helper.h" #include "execute_helper.h"
#include "printf.h" #include "printf.h"
#include "field_size.h"
void op_aaload(struct vm * vm) void op_aaload(struct vm * vm)
{ {
@ -1596,9 +1597,45 @@ void op_monitorexit(struct vm * vm)
assert(!"op_monitorexit"); assert(!"op_monitorexit");
} }
static int32_t * _multiarray(int32_t * dims, int num_dimensions, int level, uint8_t * type)
{
int32_t count = dims[level];
int32_t element_size = field_size_array(*type);
int32_t size = element_size * count + 4;
int32_t * arrayref = memory_allocate(size);
arrayref[0] = count;
int32_t u32_count = (size - 4 + 3) / 4;
for (int i = 0; i < u32_count; i++) {
if (level == num_dimensions - 1) {
arrayref[i + 1] = 0;
} else {
assert(*type == '[');
arrayref[1 + i] = (int32_t)_multiarray(dims, num_dimensions, level + 1, type + 1);
}
}
return arrayref;
}
void op_multianewarray(struct vm * vm, uint32_t index, uint32_t dimensions) void op_multianewarray(struct vm * vm, uint32_t index, uint32_t dimensions)
{ {
assert(!"op_multianewarray"); struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1];
assert(class_constant->tag == CONSTANT_Class);
struct constant * type_constant = &vm->current_frame->class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(type_constant->tag == CONSTANT_Utf8);
// The run-time constant pool entry at the index must be a symbolic reference
// to a class, array, or interface type
uint8_t * type = type_constant->utf8.bytes;
assert(*type == '[');
assert(dimensions > 0);
int32_t dims[dimensions];
for (int i = 0; i < dimensions; i++) {
dims[dimensions - i - 1] = operand_stack_pop_u32(vm->current_frame);
}
int32_t * arrayref = _multiarray(dims, dimensions, 0, type + 1);
operand_stack_push_u32(vm->current_frame, (uint32_t)arrayref);
} }
void op_new(struct vm * vm, uint32_t index) void op_new(struct vm * vm, uint32_t index)

43
c/field_size.h Normal file
View File

@ -0,0 +1,43 @@
#pragma once
static inline int field_size(uint8_t c)
{
switch (c) {
case 'B': [[fallthrough]];
case 'C': [[fallthrough]];
case 'F': [[fallthrough]];
case 'I': [[fallthrough]];
case 'L': [[fallthrough]];
case 'S': [[fallthrough]];
case 'Z': [[fallthrough]];
case '[':
return 1;
case 'D': [[fallthrough]];
case 'J':
return 2;
default:
assert(false);
}
}
static inline int field_size_array(uint8_t c)
{
switch (c) {
case 'Z': [[fallthrough]]; // boolean
case 'B': // byte
return 1;
case 'C': [[fallthrough]]; // char
case 'S': // short
return 2;
case 'F': [[fallthrough]]; // float
case 'I': [[fallthrough]]; // int
case 'L': [[fallthrough]]; // classref
case '[': // arrayref
return 4;
case 'D': [[fallthrough]];
case 'J':
return 8;
default:
assert(false);
}
}

19
p/MultiArray.java Normal file
View File

@ -0,0 +1,19 @@
package p;
class MultiArray {
static int test() {
byte[][][] arr = new byte[10][20][30];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 20; j++) {
for (int k = 0; k < 30; k++) {
arr[i][j][k] = (byte)(i * j * k);
}
}
}
return arr[2][9][4];
}
public static void main() {
test();
}
}

View File

@ -18,7 +18,7 @@ class WideInstruction {
k27, k28, k29, k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k40, k41, k42, k43, k27, k28, k29, k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k40, k41, k42, k43,
k44, k45, k46, k47, k48, k49, k50, k51, k52, k53, k54, k55, k56, k57 = 42; k44, k45, k46, k47, k48, k49, k50, k51, k52, k53, k54, k55, k56, k57 = 42;
for (int i = 0; i < 256; i += 1024) { for (int i = 0; i < 2560; i += 1024) {
k57 += 360; k57 += 360;
} }