84 lines
4.1 KiB
C
84 lines
4.1 KiB
C
struct objectref * class_resolver_lookup_string(struct vm * vm,
|
|
struct class_entry * class_entry,
|
|
const int string_index)
|
|
{
|
|
debugf("class_resolver_lookup_string: %d\n", string_index);
|
|
if (class_entry->attribute_entry[string_index - 1].string_objectref != nullptr) {
|
|
debugf("class_resolver_lookup_string: [cached]\n");
|
|
return class_entry->attribute_entry[string_index - 1].string_objectref;
|
|
}
|
|
|
|
struct constant * string_constant = &class_entry->class_file->constant_pool[string_index - 1];
|
|
assert(string_constant->tag == CONSTANT_String);
|
|
|
|
struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_constant->string.string_index - 1];
|
|
assert(utf8_constant->tag == CONSTANT_Utf8);
|
|
|
|
struct class_entry * string_class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
|
|
vm->class_hash_table.entry,
|
|
(const uint8_t *)"java/lang/String",
|
|
16);
|
|
debugf("string class entry: %p\n", string_class_entry);
|
|
|
|
int32_t count = utf8_constant->utf8.length;
|
|
struct arrayref * arrayref = prim_array_allocate(vm, 1, count);
|
|
assert(arrayref != nullptr);
|
|
arrayref->class_entry = nullptr; // byte[]
|
|
arrayref->length = utf8_constant->utf8.length;
|
|
for (int i = 0; i < utf8_constant->utf8.length; i++) {
|
|
arrayref->u8[i] = utf8_constant->utf8.bytes[i];
|
|
}
|
|
|
|
assert(string_class_entry != nullptr);
|
|
int fields_count = string_class_entry->instance_fields_count;
|
|
struct objectref * objectref = obj_allocate(vm, fields_count);
|
|
assert(objectref != nullptr);
|
|
objectref->class_entry = string_class_entry;
|
|
for (int i = 0; i < fields_count; i++) {
|
|
objectref->oref[i] = nullptr;
|
|
}
|
|
objectref->aref[0] = arrayref;
|
|
|
|
// cache the result
|
|
class_entry->attribute_entry[string_index - 1].string_objectref = objectref;
|
|
|
|
return objectref;
|
|
}
|
|
|
|
static inline void class_entry_field_entry_from_constant_index(struct vm * vm,
|
|
int32_t index,
|
|
struct class_entry ** class_entry,
|
|
struct field_entry ** field_entry,
|
|
struct constant ** field_descriptor_constant)
|
|
{
|
|
struct constant * fieldref_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1];
|
|
#ifdef DEBUG
|
|
assert(fieldref_constant->tag == CONSTANT_Fieldref);
|
|
#endif
|
|
|
|
*class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length,
|
|
vm->class_hash_table.entry,
|
|
vm->current_frame->class_entry,
|
|
fieldref_constant->fieldref.class_index);
|
|
|
|
assert(*class_entry != nullptr);
|
|
|
|
int fields_hash_table_length = (*class_entry)->fields.length;
|
|
struct hash_table_entry * fields_hash_table = (*class_entry)->fields.entry;
|
|
|
|
*field_entry = class_resolver_lookup_field_from_fieldref_index(fields_hash_table_length,
|
|
fields_hash_table,
|
|
vm->current_frame->class_entry,
|
|
index);
|
|
assert(*field_entry != nullptr);
|
|
|
|
struct constant * nameandtype_constant = &vm->current_frame->class_entry->class_file->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1];
|
|
#ifdef DEBUG
|
|
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
|
|
#endif
|
|
*field_descriptor_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
|
|
#ifdef DEBUG
|
|
assert((*field_descriptor_constant)->tag == CONSTANT_Utf8);
|
|
#endif
|
|
}
|