@@ -39,10 +39,11 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "oops/constantPool.inline.hpp" #include "oops/cpCache.inline.hpp" #include "oops/fieldStreams.inline.hpp" + #include "oops/inlineKlass.inline.hpp" #include "oops/klass.inline.hpp" #include "oops/method.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/resolvedIndyEntry.hpp" #include "prims/jvmtiExport.hpp"
@@ -509,11 +510,11 @@ return nullptr; } return k; } obj = ciReplay::obj_field(obj, field); - // array + // TODO 8350865 I think we need to handle null-free/flat arrays here if (obj != nullptr && obj->is_objArray()) { objArrayOop arr = (objArrayOop)obj; int index = parse_int("index"); if (index >= arr->length()) { report_error("bad array index");
@@ -959,10 +960,11 @@ tty->print_cr("Resolving klass %s at %d", cp->klass_name_at(i)->as_utf8(), i); Klass* k = cp->klass_at(i, CHECK); } break; } + case JVM_CONSTANT_Long: case JVM_CONSTANT_Double: parsed_two_word = i + 1; case JVM_CONSTANT_ClassIndex:
@@ -1005,130 +1007,234 @@ } } } - // staticfield <klass> <name> <signature> <value> - // - // Initialize a class and fill in the value for a static field. - // This is useful when the compile was dependent on the value of - // static fields but it's impossible to properly rerun the static - // initializer. - void process_staticfield(TRAPS) { - InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK); - - if (k == nullptr || ReplaySuppressInitializers == 0 || - (ReplaySuppressInitializers == 2 && k->class_loader() == nullptr)) { - skip_remaining(); - return; - } - - assert(k->is_initialized(), "must be"); - - const char* field_name = parse_escaped_string(); - const char* field_signature = parse_string(); - fieldDescriptor fd; - Symbol* name = SymbolTable::new_symbol(field_name); - Symbol* sig = SymbolTable::new_symbol(field_signature); - if (!k->find_local_field(name, sig, &fd) || - !fd.is_static() || - fd.has_initial_value()) { - report_error(field_name); - return; + class InlineTypeFieldInitializer : public FieldClosure { + oop _vt; + CompileReplay* _replay; + public: + InlineTypeFieldInitializer(oop vt, CompileReplay* replay) + : _vt(vt), _replay(replay) {} + + void do_field(fieldDescriptor* fd) { + BasicType bt = fd->field_type(); + const char* string_value = fd->is_null_free_inline_type() ? nullptr : _replay->parse_escaped_string(); + switch (bt) { + case T_BYTE: { + int value = atoi(string_value); + _vt->byte_field_put(fd->offset(), value); + break; + } + case T_BOOLEAN: { + int value = atoi(string_value); + _vt->bool_field_put(fd->offset(), value); + break; + } + case T_SHORT: { + int value = atoi(string_value); + _vt->short_field_put(fd->offset(), value); + break; + } + case T_CHAR: { + int value = atoi(string_value); + _vt->char_field_put(fd->offset(), value); + break; + } + case T_INT: { + int value = atoi(string_value); + _vt->int_field_put(fd->offset(), value); + break; + } + case T_LONG: { + jlong value; + if (sscanf(string_value, JLONG_FORMAT, &value) != 1) { + fprintf(stderr, "Error parsing long: %s\n", string_value); + break; + } + _vt->long_field_put(fd->offset(), value); + break; + } + case T_FLOAT: { + float value = atof(string_value); + _vt->float_field_put(fd->offset(), value); + break; + } + case T_DOUBLE: { + double value = atof(string_value); + _vt->double_field_put(fd->offset(), value); + break; + } + case T_ARRAY: + case T_OBJECT: + if (!fd->is_null_free_inline_type()) { + JavaThread* THREAD = JavaThread::current(); + bool res = _replay->process_staticfield_reference(string_value, _vt, fd, THREAD); + assert(res, "should succeed for arrays & objects"); + break; + } else { + InlineKlass* vk = InlineKlass::cast(fd->field_holder()->get_inline_type_field_klass(fd->index())); + if (fd->is_flat()) { + int field_offset = fd->offset() - vk->payload_offset(); + oop obj = cast_to_oop(cast_from_oop<address>(_vt) + field_offset); + InlineTypeFieldInitializer init_fields(obj, _replay); + vk->do_nonstatic_fields(&init_fields); + } else { + oop value = vk->allocate_instance(JavaThread::current()); + _vt->obj_field_put(fd->offset(), value); + } + break; + } + default: { + fatal("Unhandled type: %s", type2name(bt)); + } + } } + }; - oop java_mirror = k->java_mirror(); + bool process_staticfield_reference(const char* field_signature, oop java_mirror, fieldDescriptor* fd, TRAPS) { if (field_signature[0] == JVM_SIGNATURE_ARRAY) { int length = parse_int("array length"); oop value = nullptr; if (length != -1) { if (field_signature[1] == JVM_SIGNATURE_ARRAY) { // multi dimensional array - ArrayKlass* kelem = (ArrayKlass *)parse_klass(CHECK); - if (kelem == nullptr) { - return; - } + Klass* k = resolve_klass(field_signature, CHECK_(true)); + ArrayKlass* kelem = (ArrayKlass *)k; int rank = 0; while (field_signature[rank] == JVM_SIGNATURE_ARRAY) { rank++; } jint* dims = NEW_RESOURCE_ARRAY(jint, rank); dims[0] = length; for (int i = 1; i < rank; i++) { dims[i] = 1; // These aren't relevant to the compiler } - value = kelem->multi_allocate(rank, dims, CHECK); + value = kelem->multi_allocate(rank, dims, CHECK_(true)); } else { if (strcmp(field_signature, "[B") == 0) { - value = oopFactory::new_byteArray(length, CHECK); + value = oopFactory::new_byteArray(length, CHECK_(true)); } else if (strcmp(field_signature, "[Z") == 0) { - value = oopFactory::new_boolArray(length, CHECK); + value = oopFactory::new_boolArray(length, CHECK_(true)); } else if (strcmp(field_signature, "[C") == 0) { - value = oopFactory::new_charArray(length, CHECK); + value = oopFactory::new_charArray(length, CHECK_(true)); } else if (strcmp(field_signature, "[S") == 0) { - value = oopFactory::new_shortArray(length, CHECK); + value = oopFactory::new_shortArray(length, CHECK_(true)); } else if (strcmp(field_signature, "[F") == 0) { - value = oopFactory::new_floatArray(length, CHECK); + value = oopFactory::new_floatArray(length, CHECK_(true)); } else if (strcmp(field_signature, "[D") == 0) { - value = oopFactory::new_doubleArray(length, CHECK); + value = oopFactory::new_doubleArray(length, CHECK_(true)); } else if (strcmp(field_signature, "[I") == 0) { - value = oopFactory::new_intArray(length, CHECK); + value = oopFactory::new_intArray(length, CHECK_(true)); } else if (strcmp(field_signature, "[J") == 0) { - value = oopFactory::new_longArray(length, CHECK); + value = oopFactory::new_longArray(length, CHECK_(true)); } else if (field_signature[0] == JVM_SIGNATURE_ARRAY && field_signature[1] == JVM_SIGNATURE_CLASS) { - Klass* actual_array_klass = parse_klass(CHECK); + Klass* actual_array_klass = parse_klass(CHECK_(true)); + // TODO 8350865 I think we need to handle null-free/flat arrays here Klass* kelem = ObjArrayKlass::cast(actual_array_klass)->element_klass(); - value = oopFactory::new_objArray(kelem, length, CHECK); + value = oopFactory::new_objArray(kelem, length, CHECK_(true)); } else { report_error("unhandled array staticfield"); } } + java_mirror->obj_field_put(fd->offset(), value); + return true; + } + } else if (strcmp(field_signature, "Ljava/lang/String;") == 0) { + const char* string_value = parse_escaped_string(); + Handle value = java_lang_String::create_from_str(string_value, CHECK_(true)); + java_mirror->obj_field_put(fd->offset(), value()); + return true; + } else if (field_signature[0] == JVM_SIGNATURE_CLASS) { + const char* instance = parse_escaped_string(); + oop value = nullptr; + if (instance != nullptr) { + Klass* k = resolve_klass(instance, CHECK_(true)); + value = InstanceKlass::cast(k)->allocate_instance(CHECK_(true)); } + java_mirror->obj_field_put(fd->offset(), value); + return true; + } + return false; + } + + // Initialize a class and fill in the value for a static field. + // This is useful when the compile was dependent on the value of + // static fields but it's impossible to properly rerun the static + // initializer. + void process_staticfield(TRAPS) { + InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK); + + if (k == nullptr || ReplaySuppressInitializers == 0 || + (ReplaySuppressInitializers == 2 && k->class_loader() == nullptr)) { + skip_remaining(); + return; + } + + assert(k->is_initialized(), "must be"); + + const char* field_name = parse_escaped_string(); + const char* field_signature = parse_string(); + fieldDescriptor fd; + Symbol* name = SymbolTable::new_symbol(field_name); + Symbol* sig = SymbolTable::new_symbol(field_signature); + if (!k->find_local_field(name, sig, &fd) || + !fd.is_static() || + fd.has_initial_value()) { + report_error(field_name); + return; + } + + oop java_mirror = k->java_mirror(); + if (strcmp(field_signature, "I") == 0) { + const char* string_value = parse_escaped_string(); + int value = atoi(string_value); + java_mirror->int_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "B") == 0) { + const char* string_value = parse_escaped_string(); + int value = atoi(string_value); + java_mirror->byte_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "C") == 0) { + const char* string_value = parse_escaped_string(); + int value = atoi(string_value); + java_mirror->char_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "S") == 0) { + const char* string_value = parse_escaped_string(); + int value = atoi(string_value); + java_mirror->short_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "Z") == 0) { + const char* string_value = parse_escaped_string(); + int value = atoi(string_value); + java_mirror->bool_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "J") == 0) { + const char* string_value = parse_escaped_string(); + jlong value; + if (sscanf(string_value, JLONG_FORMAT, &value) != 1) { + fprintf(stderr, "Error parsing long: %s\n", string_value); + return; + } + java_mirror->long_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "F") == 0) { + const char* string_value = parse_escaped_string(); + float value = atof(string_value); + java_mirror->float_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "D") == 0) { + const char* string_value = parse_escaped_string(); + double value = atof(string_value); + java_mirror->double_field_put(fd.offset(), value); + } else if (fd.is_null_free_inline_type()) { + Klass* kelem = resolve_klass(field_signature, CHECK); + InlineKlass* vk = InlineKlass::cast(kelem); + oop value = vk->allocate_instance(CHECK); + InlineTypeFieldInitializer init_fields(value, this); + vk->do_nonstatic_fields(&init_fields); java_mirror->obj_field_put(fd.offset(), value); } else { - const char* string_value = parse_escaped_string(); - if (strcmp(field_signature, "I") == 0) { - int value = atoi(string_value); - java_mirror->int_field_put(fd.offset(), value); - } else if (strcmp(field_signature, "B") == 0) { - int value = atoi(string_value); - java_mirror->byte_field_put(fd.offset(), value); - } else if (strcmp(field_signature, "C") == 0) { - int value = atoi(string_value); - java_mirror->char_field_put(fd.offset(), value); - } else if (strcmp(field_signature, "S") == 0) { - int value = atoi(string_value); - java_mirror->short_field_put(fd.offset(), value); - } else if (strcmp(field_signature, "Z") == 0) { - int value = atoi(string_value); - java_mirror->bool_field_put(fd.offset(), value); - } else if (strcmp(field_signature, "J") == 0) { - jlong value; - if (sscanf(string_value, JLONG_FORMAT, &value) != 1) { - fprintf(stderr, "Error parsing long: %s\n", string_value); - return; - } - java_mirror->long_field_put(fd.offset(), value); - } else if (strcmp(field_signature, "F") == 0) { - float value = atof(string_value); - java_mirror->float_field_put(fd.offset(), value); - } else if (strcmp(field_signature, "D") == 0) { - double value = atof(string_value); - java_mirror->double_field_put(fd.offset(), value); - } else if (strcmp(field_signature, "Ljava/lang/String;") == 0) { - Handle value = java_lang_String::create_from_str(string_value, CHECK); - java_mirror->obj_field_put(fd.offset(), value()); - } else if (field_signature[0] == JVM_SIGNATURE_CLASS) { - oop value = nullptr; - if (string_value != nullptr) { - Klass* k = resolve_klass(string_value, CHECK); - value = InstanceKlass::cast(k)->allocate_instance(CHECK); - } - java_mirror->obj_field_put(fd.offset(), value); - } else { + bool res = process_staticfield_reference(field_signature, java_mirror, &fd, CHECK); + if (!res) { report_error("unhandled staticfield"); } } }