< prev index next >

src/hotspot/share/ci/ciInstanceKlass.cpp

Print this page

        

*** 25,40 **** --- 25,42 ---- #include "precompiled.hpp" #include "ci/ciField.hpp" #include "ci/ciInstance.hpp" #include "ci/ciInstanceKlass.hpp" #include "ci/ciUtilities.inline.hpp" + #include "ci/ciValueKlass.hpp" #include "classfile/systemDictionary.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "oops/fieldStreams.hpp" + #include "oops/valueKlass.hpp" #include "runtime/fieldDescriptor.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/jniHandles.inline.hpp" // ciInstanceKlass
*** 61,72 **** _init_state = ik->init_state(); _nonstatic_field_size = ik->nonstatic_field_size(); _has_nonstatic_fields = ik->has_nonstatic_fields(); _has_nonstatic_concrete_methods = ik->has_nonstatic_concrete_methods(); _is_unsafe_anonymous = ik->is_unsafe_anonymous(); ! _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _has_injected_fields = -1; _implementor = NULL; // we will fill these lazily // Ensure that the metadata wrapped by the ciMetadata is kept alive by GC. // This is primarily useful for metadata which is considered as weak roots // by the GC but need to be strong roots if reachable from a current compilation. --- 63,75 ---- _init_state = ik->init_state(); _nonstatic_field_size = ik->nonstatic_field_size(); _has_nonstatic_fields = ik->has_nonstatic_fields(); _has_nonstatic_concrete_methods = ik->has_nonstatic_concrete_methods(); _is_unsafe_anonymous = ik->is_unsafe_anonymous(); ! _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields _has_injected_fields = -1; + _vcc_klass = NULL; _implementor = NULL; // we will fill these lazily // Ensure that the metadata wrapped by the ciMetadata is kept alive by GC. // This is primarily useful for metadata which is considered as weak roots // by the GC but need to be strong roots if reachable from a current compilation.
*** 111,129 **** _field_cache = NULL; } // Version for unloaded classes: ciInstanceKlass::ciInstanceKlass(ciSymbol* name, ! jobject loader, jobject protection_domain) ! : ciKlass(name, T_OBJECT) { assert(name->char_at(0) != '[', "not an instance klass"); _init_state = (InstanceKlass::ClassState)0; _nonstatic_field_size = -1; _has_nonstatic_fields = false; ! _nonstatic_fields = NULL; _has_injected_fields = -1; _is_unsafe_anonymous = false; _loader = loader; _protection_domain = protection_domain; _is_shared = false; _super = NULL; --- 114,134 ---- _field_cache = NULL; } // Version for unloaded classes: ciInstanceKlass::ciInstanceKlass(ciSymbol* name, ! jobject loader, jobject protection_domain, ! BasicType bt) ! : ciKlass(name, bt) { assert(name->char_at(0) != '[', "not an instance klass"); _init_state = (InstanceKlass::ClassState)0; _nonstatic_field_size = -1; _has_nonstatic_fields = false; ! _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields _has_injected_fields = -1; + _vcc_klass = NULL; _is_unsafe_anonymous = false; _loader = loader; _protection_domain = protection_domain; _is_shared = false; _super = NULL;
*** 414,423 **** --- 419,451 ---- } ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd); return field; } + ciField* ciInstanceKlass::get_non_flattened_field_by_offset(int field_offset) { + if (super() != NULL && super()->has_nonstatic_fields()) { + ciField* f = super()->get_non_flattened_field_by_offset(field_offset); + if (f != NULL) { + return f; + } + } + + VM_ENTRY_MARK; + InstanceKlass* k = get_instanceKlass(); + Arena* arena = CURRENT_ENV->arena(); + for (JavaFieldStream fs(k); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) continue; + fieldDescriptor& fd = fs.field_descriptor(); + if (fd.offset() == field_offset) { + ciField* f = new (arena) ciField(&fd); + return f; + } + } + + return NULL; + } + // ------------------------------------------------------------------ // ciInstanceKlass::get_field_by_name ciField* ciInstanceKlass::get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static) { VM_ENTRY_MARK; InstanceKlass* k = get_instanceKlass();
*** 481,502 **** } else { return 0; } } - int flen = fields->length(); - - // Now sort them by offset, ascending. - // (In principle, they could mix with superclass fields.) - fields->sort(sort_field_by_offset); _nonstatic_fields = fields; ! return flen; } ! GrowableArray<ciField*>* ! ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*>* ! super_fields) { ASSERT_IN_VM; Arena* arena = CURRENT_ENV->arena(); int flen = 0; GrowableArray<ciField*>* fields = NULL; InstanceKlass* k = get_instanceKlass(); --- 509,523 ---- } else { return 0; } } _nonstatic_fields = fields; ! return fields->length(); } ! GrowableArray<ciField*>* ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields, bool flatten) { ASSERT_IN_VM; Arena* arena = CURRENT_ENV->arena(); int flen = 0; GrowableArray<ciField*>* fields = NULL; InstanceKlass* k = get_instanceKlass();
*** 510,531 **** --- 531,576 ---- return NULL; // return nothing if none are locally declared } if (super_fields != NULL) { flen += super_fields->length(); } + fields = new (arena) GrowableArray<ciField*>(arena, flen, 0, NULL); if (super_fields != NULL) { fields->appendAll(super_fields); } for (JavaFieldStream fs(k); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) continue; fieldDescriptor& fd = fs.field_descriptor(); + if (fd.is_flattened() && flatten) { + // Value type fields are embedded + int field_offset = fd.offset(); + // Get ValueKlass and adjust number of fields + Klass* k = get_instanceKlass()->get_value_field_klass(fd.index()); + ciValueKlass* vk = CURRENT_ENV->get_klass(k)->as_value_klass(); + flen += vk->nof_nonstatic_fields() - 1; + // Iterate over fields of the flattened value type and copy them to 'this' + for (int i = 0; i < vk->nof_nonstatic_fields(); ++i) { + ciField* flattened_field = vk->nonstatic_field_at(i); + // Adjust offset to account for missing oop header + int offset = field_offset + (flattened_field->offset() - vk->first_field_offset()); + // A flattened field can be treated as final if the non-flattened + // field is declared final or the holder klass is a value type itself. + bool is_final = fd.is_final() || is_valuetype(); + ciField* field = new (arena) ciField(flattened_field, this, offset, is_final); + fields->append(field); + } + } else { ciField* field = new (arena) ciField(&fd); fields->append(field); } + } assert(fields->length() == flen, "sanity"); + // Now sort them by offset, ascending. + // (In principle, they could mix with superclass fields.) + fields->sort(sort_field_by_offset); return fields; } bool ciInstanceKlass::compute_injected_fields_helper() { ASSERT_IN_VM;
*** 629,674 **** return CURRENT_ENV->get_instance_klass(unsafe_anonymous_host); } return NULL; } // Utility class for printing of the contents of the static fields for // use by compilation replay. It only prints out the information that // could be consumed by the compiler, so for primitive types it prints // out the actual value. For Strings it's the actual string value. // For array types it it's first level array size since that's the // only value which statically unchangeable. For all other reference // types it simply prints out the dynamic type. ! class StaticFinalFieldPrinter : public FieldClosure { outputStream* _out; const char* _holder; public: StaticFinalFieldPrinter(outputStream* out, const char* holder) : ! _out(out), ! _holder(holder) { } void do_field(fieldDescriptor* fd) { if (fd->is_final() && !fd->has_initial_value()) { ResourceMark rm; ! oop mirror = fd->field_holder()->java_mirror(); ! _out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii()); ! switch (fd->field_type()) { ! case T_BYTE: _out->print_cr("%d", mirror->byte_field(fd->offset())); break; ! case T_BOOLEAN: _out->print_cr("%d", mirror->bool_field(fd->offset())); break; ! case T_SHORT: _out->print_cr("%d", mirror->short_field(fd->offset())); break; ! case T_CHAR: _out->print_cr("%d", mirror->char_field(fd->offset())); break; ! case T_INT: _out->print_cr("%d", mirror->int_field(fd->offset())); break; ! case T_LONG: _out->print_cr(INT64_FORMAT, (int64_t)(mirror->long_field(fd->offset()))); break; case T_FLOAT: { float f = mirror->float_field(fd->offset()); ! _out->print_cr("%d", *(int*)&f); break; } case T_DOUBLE: { double d = mirror->double_field(fd->offset()); ! _out->print_cr(INT64_FORMAT, *(int64_t*)&d); break; } case T_ARRAY: // fall-through case T_OBJECT: { oop value = mirror->obj_field_acquire(fd->offset()); --- 674,756 ---- return CURRENT_ENV->get_instance_klass(unsafe_anonymous_host); } return NULL; } + ciInstanceKlass* ciInstanceKlass::vcc_klass() { + return NULL; + } + // Utility class for printing of the contents of the static fields for // use by compilation replay. It only prints out the information that // could be consumed by the compiler, so for primitive types it prints // out the actual value. For Strings it's the actual string value. // For array types it it's first level array size since that's the // only value which statically unchangeable. For all other reference // types it simply prints out the dynamic type. ! class StaticFieldPrinter : public FieldClosure { ! protected: outputStream* _out; + public: + StaticFieldPrinter(outputStream* out) : + _out(out) { + } + void do_field_helper(fieldDescriptor* fd, oop obj, bool flattened); + }; + + class StaticFinalFieldPrinter : public StaticFieldPrinter { const char* _holder; public: StaticFinalFieldPrinter(outputStream* out, const char* holder) : ! StaticFieldPrinter(out), _holder(holder) { } void do_field(fieldDescriptor* fd) { if (fd->is_final() && !fd->has_initial_value()) { ResourceMark rm; ! InstanceKlass* holder = fd->field_holder(); ! oop mirror = holder->java_mirror(); ! _out->print("staticfield %s %s ", _holder, fd->name()->as_quoted_ascii()); ! BasicType bt = fd->field_type(); ! if (bt != T_OBJECT && bt != T_ARRAY) { ! _out->print("%s ", fd->signature()->as_quoted_ascii()); ! } ! do_field_helper(fd, mirror, false); ! _out->cr(); ! } ! } ! }; ! ! class ValueTypeFieldPrinter : public StaticFieldPrinter { ! oop _obj; ! public: ! ValueTypeFieldPrinter(outputStream* out, oop obj) : ! StaticFieldPrinter(out), _obj(obj) { ! } ! void do_field(fieldDescriptor* fd) { ! do_field_helper(fd, _obj, true); ! _out->print(" "); ! } ! }; ! ! void StaticFieldPrinter::do_field_helper(fieldDescriptor* fd, oop mirror, bool flattened) { ! BasicType bt = fd->field_type(); ! switch (bt) { ! case T_BYTE: _out->print("%d", mirror->byte_field(fd->offset())); break; ! case T_BOOLEAN: _out->print("%d", mirror->bool_field(fd->offset())); break; ! case T_SHORT: _out->print("%d", mirror->short_field(fd->offset())); break; ! case T_CHAR: _out->print("%d", mirror->char_field(fd->offset())); break; ! case T_INT: _out->print("%d", mirror->int_field(fd->offset())); break; ! case T_LONG: _out->print(INT64_FORMAT, (int64_t)(mirror->long_field(fd->offset()))); break; case T_FLOAT: { float f = mirror->float_field(fd->offset()); ! _out->print("%d", *(int*)&f); break; } case T_DOUBLE: { double d = mirror->double_field(fd->offset()); ! _out->print(INT64_FORMAT, *(int64_t*)&d); break; } case T_ARRAY: // fall-through case T_OBJECT: { oop value = mirror->obj_field_acquire(fd->offset());
*** 684,710 **** _out->print_cr("%s", klass_name); } } else if (value->is_array()) { typeArrayOop ta = (typeArrayOop)value; _out->print("%d", ta->length()); ! if (value->is_objArray()) { objArrayOop oa = (objArrayOop)value; const char* klass_name = value->klass()->name()->as_quoted_ascii(); _out->print(" %s", klass_name); } _out->cr(); } else { ShouldNotReachHere(); } break; } ! default: ! ShouldNotReachHere(); } } } ! }; void ciInstanceKlass::dump_replay_data(outputStream* out) { ResourceMark rm; --- 766,812 ---- _out->print_cr("%s", klass_name); } } else if (value->is_array()) { typeArrayOop ta = (typeArrayOop)value; _out->print("%d", ta->length()); ! if (value->is_objArray() || value->is_valueArray()) { objArrayOop oa = (objArrayOop)value; const char* klass_name = value->klass()->name()->as_quoted_ascii(); _out->print(" %s", klass_name); } _out->cr(); } else { ShouldNotReachHere(); } break; } ! case T_VALUETYPE: { ! ResetNoHandleMark rnhm; ! Thread* THREAD = Thread::current(); ! SignatureStream ss(fd->signature(), false); ! Symbol* name = ss.as_symbol(THREAD); ! assert(!HAS_PENDING_EXCEPTION, "can resolve klass?"); ! InstanceKlass* holder = fd->field_holder(); ! Klass* k = SystemDictionary::find(name, Handle(THREAD, holder->class_loader()), ! Handle(THREAD, holder->protection_domain()), THREAD); ! assert(k != NULL && !HAS_PENDING_EXCEPTION, "can resolve klass?"); ! ValueKlass* vk = ValueKlass::cast(k); ! oop obj; ! if (flattened) { ! int field_offset = fd->offset() - vk->first_field_offset(); ! obj = (oop)((address)mirror + field_offset); ! } else { ! obj = mirror->obj_field_acquire(fd->offset()); } + ValueTypeFieldPrinter print_field(_out, obj); + vk->do_nonstatic_fields(&print_field); + break; } + default: + ShouldNotReachHere(); } ! } void ciInstanceKlass::dump_replay_data(outputStream* out) { ResourceMark rm;
< prev index next >