duke@435: /* drchase@5732: * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #include "precompiled.hpp" stefank@2314: #include "ci/ciField.hpp" stefank@2314: #include "ci/ciInstance.hpp" stefank@2314: #include "ci/ciInstanceKlass.hpp" stefank@2314: #include "ci/ciUtilities.hpp" stefank@2314: #include "classfile/systemDictionary.hpp" stefank@2314: #include "memory/allocation.hpp" stefank@2314: #include "memory/allocation.inline.hpp" stefank@2314: #include "oops/oop.inline.hpp" never@3137: #include "oops/fieldStreams.hpp" stefank@2314: #include "runtime/fieldDescriptor.hpp" duke@435: duke@435: // ciInstanceKlass duke@435: // coleenp@4037: // This class represents a Klass* in the HotSpot virtual machine coleenp@4037: // whose Klass part in an InstanceKlass. duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::ciInstanceKlass duke@435: // duke@435: // Loaded instance klass. kvn@479: ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : kvn@479: ciKlass(h_k), _non_static_fields(NULL) kvn@479: { duke@435: assert(get_Klass()->oop_is_instance(), "wrong type"); never@2551: assert(get_instanceKlass()->is_loaded(), "must be at least loaded"); coleenp@4037: InstanceKlass* ik = get_instanceKlass(); duke@435: duke@435: AccessFlags access_flags = ik->access_flags(); duke@435: _flags = ciFlags(access_flags); duke@435: _has_finalizer = access_flags.has_finalizer(); duke@435: _has_subklass = ik->subklass() != NULL; coleenp@3368: _init_state = ik->init_state(); duke@435: _nonstatic_field_size = ik->nonstatic_field_size(); coleenp@548: _has_nonstatic_fields = ik->has_nonstatic_fields(); duke@435: _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: duke@435: jiangli@3701: _implementor = NULL; // we will fill these lazily duke@435: duke@435: Thread *thread = Thread::current(); duke@435: if (ciObjectFactory::is_initialized()) { duke@435: _loader = JNIHandles::make_local(thread, ik->class_loader()); duke@435: _protection_domain = JNIHandles::make_local(thread, duke@435: ik->protection_domain()); duke@435: _is_shared = false; duke@435: } else { duke@435: Handle h_loader(thread, ik->class_loader()); duke@435: Handle h_protection_domain(thread, ik->protection_domain()); duke@435: _loader = JNIHandles::make_global(h_loader); duke@435: _protection_domain = JNIHandles::make_global(h_protection_domain); duke@435: _is_shared = true; duke@435: } duke@435: duke@435: // Lazy fields get filled in only upon request. duke@435: _super = NULL; duke@435: _java_mirror = NULL; duke@435: duke@435: if (is_shared()) { never@1577: if (h_k() != SystemDictionary::Object_klass()) { duke@435: super(); duke@435: } duke@435: //compute_nonstatic_fields(); // done outside of constructor duke@435: } duke@435: duke@435: _field_cache = NULL; duke@435: } duke@435: duke@435: // Version for unloaded classes: duke@435: ciInstanceKlass::ciInstanceKlass(ciSymbol* name, duke@435: jobject loader, jobject protection_domain) coleenp@4037: : ciKlass(name, T_OBJECT) duke@435: { duke@435: assert(name->byte_at(0) != '[', "not an instance klass"); coleenp@4037: _init_state = (InstanceKlass::ClassState)0; duke@435: _nonstatic_field_size = -1; coleenp@548: _has_nonstatic_fields = false; duke@435: _nonstatic_fields = NULL; duke@435: _loader = loader; duke@435: _protection_domain = protection_domain; duke@435: _is_shared = false; duke@435: _super = NULL; duke@435: _java_mirror = NULL; duke@435: _field_cache = NULL; duke@435: } duke@435: duke@435: duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::compute_shared_is_initialized never@2000: void ciInstanceKlass::compute_shared_init_state() { duke@435: GUARDED_VM_ENTRY( coleenp@4037: InstanceKlass* ik = get_instanceKlass(); coleenp@3368: _init_state = ik->init_state(); duke@435: ) duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::compute_shared_has_subklass duke@435: bool ciInstanceKlass::compute_shared_has_subklass() { duke@435: GUARDED_VM_ENTRY( coleenp@4037: InstanceKlass* ik = get_instanceKlass(); duke@435: _has_subklass = ik->subklass() != NULL; duke@435: return _has_subklass; duke@435: ) duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::loader duke@435: oop ciInstanceKlass::loader() { duke@435: ASSERT_IN_VM; duke@435: return JNIHandles::resolve(_loader); duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::loader_handle duke@435: jobject ciInstanceKlass::loader_handle() { duke@435: return _loader; duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::protection_domain duke@435: oop ciInstanceKlass::protection_domain() { duke@435: ASSERT_IN_VM; duke@435: return JNIHandles::resolve(_protection_domain); duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::protection_domain_handle duke@435: jobject ciInstanceKlass::protection_domain_handle() { duke@435: return _protection_domain; duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::field_cache duke@435: // duke@435: // Get the field cache associated with this klass. duke@435: ciConstantPoolCache* ciInstanceKlass::field_cache() { duke@435: if (is_shared()) { duke@435: return NULL; duke@435: } duke@435: if (_field_cache == NULL) { duke@435: assert(!is_java_lang_Object(), "Object has no fields"); duke@435: Arena* arena = CURRENT_ENV->arena(); duke@435: _field_cache = new (arena) ciConstantPoolCache(arena, 5); duke@435: } duke@435: return _field_cache; duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::get_canonical_holder duke@435: // duke@435: ciInstanceKlass* ciInstanceKlass::get_canonical_holder(int offset) { duke@435: #ifdef ASSERT duke@435: if (!(offset >= 0 && offset < layout_helper())) { duke@435: tty->print("*** get_canonical_holder(%d) on ", offset); duke@435: this->print(); duke@435: tty->print_cr(" ***"); duke@435: }; duke@435: assert(offset >= 0 && offset < layout_helper(), "offset must be tame"); duke@435: #endif duke@435: coleenp@548: if (offset < instanceOopDesc::base_offset_in_bytes()) { duke@435: // All header offsets belong properly to java/lang/Object. duke@435: return CURRENT_ENV->Object_klass(); duke@435: } duke@435: duke@435: ciInstanceKlass* self = this; duke@435: for (;;) { duke@435: assert(self->is_loaded(), "must be loaded to have size"); duke@435: ciInstanceKlass* super = self->super(); coleenp@548: if (super == NULL || super->nof_nonstatic_fields() == 0 || coleenp@548: !super->contains_field_offset(offset)) { duke@435: return self; duke@435: } else { duke@435: self = super; // return super->get_canonical_holder(offset) duke@435: } duke@435: } duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::is_java_lang_Object duke@435: // duke@435: // Is this klass java.lang.Object? coleenp@4037: bool ciInstanceKlass::is_java_lang_Object() const { duke@435: return equals(CURRENT_ENV->Object_klass()); duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::uses_default_loader kvn@5110: bool ciInstanceKlass::uses_default_loader() const { twisti@1573: // Note: We do not need to resolve the handle or enter the VM twisti@1573: // in order to test null-ness. twisti@1573: return _loader == NULL; twisti@1573: } twisti@1573: twisti@1573: // ------------------------------------------------------------------ kvn@5110: kvn@5110: /** kvn@5110: * Return basic type of boxed value for box klass or T_OBJECT if not. kvn@5110: */ kvn@5110: BasicType ciInstanceKlass::box_klass_type() const { kvn@5110: if (uses_default_loader() && is_loaded()) { kvn@5110: return SystemDictionary::box_klass_type(get_Klass()); kvn@5110: } else { kvn@5110: return T_OBJECT; kvn@5110: } kvn@5110: } kvn@5110: kvn@5110: /** kvn@5110: * Is this boxing klass? kvn@5110: */ kvn@5110: bool ciInstanceKlass::is_box_klass() const { kvn@5110: return is_java_primitive(box_klass_type()); kvn@5110: } kvn@5110: kvn@5110: /** kvn@5110: * Is this boxed value offset? kvn@5110: */ kvn@5110: bool ciInstanceKlass::is_boxed_value_offset(int offset) const { kvn@5110: BasicType bt = box_klass_type(); kvn@5110: return is_java_primitive(bt) && kvn@5110: (offset == java_lang_boxing_object::value_offset_in_bytes(bt)); kvn@5110: } kvn@5110: kvn@5110: // ------------------------------------------------------------------ twisti@1573: // ciInstanceKlass::is_in_package twisti@1573: // twisti@1573: // Is this klass in the given package? twisti@1573: bool ciInstanceKlass::is_in_package(const char* packagename, int len) { twisti@1573: // To avoid class loader mischief, this test always rejects application classes. twisti@1573: if (!uses_default_loader()) twisti@1573: return false; twisti@1573: GUARDED_VM_ENTRY( twisti@1573: return is_in_package_impl(packagename, len); twisti@1573: ) twisti@1573: } twisti@1573: twisti@1573: bool ciInstanceKlass::is_in_package_impl(const char* packagename, int len) { twisti@1573: ASSERT_IN_VM; twisti@1573: twisti@1573: // If packagename contains trailing '/' exclude it from the twisti@1573: // prefix-test since we test for it explicitly. twisti@1573: if (packagename[len - 1] == '/') twisti@1573: len--; twisti@1573: twisti@1573: if (!name()->starts_with(packagename, len)) twisti@1573: return false; twisti@1573: twisti@1573: // Test if the class name is something like "java/lang". twisti@1573: if ((len + 1) > name()->utf8_length()) twisti@1573: return false; twisti@1573: twisti@1573: // Test for trailing '/' twisti@1573: if ((char) name()->byte_at(len) != '/') twisti@1573: return false; twisti@1573: twisti@1573: // Make sure it's not actually in a subpackage: twisti@1573: if (name()->index_of_at(len+1, "/", 1) >= 0) twisti@1573: return false; twisti@1573: twisti@1573: return true; duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::print_impl duke@435: // duke@435: // Implementation of the print method. duke@435: void ciInstanceKlass::print_impl(outputStream* st) { duke@435: ciKlass::print_impl(st); duke@435: GUARDED_VM_ENTRY(st->print(" loader=0x%x", (address)loader());) duke@435: if (is_loaded()) { duke@435: st->print(" loaded=true initialized=%s finalized=%s subklass=%s size=%d flags=", duke@435: bool_to_str(is_initialized()), duke@435: bool_to_str(has_finalizer()), duke@435: bool_to_str(has_subklass()), duke@435: layout_helper()); duke@435: duke@435: _flags.print_klass_flags(); duke@435: duke@435: if (_super) { duke@435: st->print(" super="); duke@435: _super->print_name(); duke@435: } duke@435: if (_java_mirror) { duke@435: st->print(" mirror=PRESENT"); duke@435: } duke@435: } else { duke@435: st->print(" loaded=false"); duke@435: } duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::super duke@435: // duke@435: // Get the superklass of this klass. duke@435: ciInstanceKlass* ciInstanceKlass::super() { duke@435: assert(is_loaded(), "must be loaded"); duke@435: if (_super == NULL && !is_java_lang_Object()) { duke@435: GUARDED_VM_ENTRY( coleenp@4037: Klass* super_klass = get_instanceKlass()->super(); coleenp@4037: _super = CURRENT_ENV->get_instance_klass(super_klass); duke@435: ) duke@435: } duke@435: return _super; duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::java_mirror duke@435: // duke@435: // Get the instance of java.lang.Class corresponding to this klass. jrose@1959: // Cache it on this->_java_mirror. duke@435: ciInstance* ciInstanceKlass::java_mirror() { never@2658: if (is_shared()) { never@2658: return ciKlass::java_mirror(); never@2658: } duke@435: if (_java_mirror == NULL) { jrose@1959: _java_mirror = ciKlass::java_mirror(); duke@435: } duke@435: return _java_mirror; duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::unique_concrete_subklass duke@435: ciInstanceKlass* ciInstanceKlass::unique_concrete_subklass() { duke@435: if (!is_loaded()) return NULL; // No change if class is not loaded duke@435: if (!is_abstract()) return NULL; // Only applies to abstract classes. duke@435: if (!has_subklass()) return NULL; // Must have at least one subklass. duke@435: VM_ENTRY_MARK; coleenp@4037: InstanceKlass* ik = get_instanceKlass(); duke@435: Klass* up = ik->up_cast_abstract(); coleenp@4037: assert(up->oop_is_instance(), "must be InstanceKlass"); duke@435: if (ik == up) { duke@435: return NULL; duke@435: } coleenp@4037: return CURRENT_THREAD_ENV->get_instance_klass(up); duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::has_finalizable_subclass duke@435: bool ciInstanceKlass::has_finalizable_subclass() { duke@435: if (!is_loaded()) return true; duke@435: VM_ENTRY_MARK; duke@435: return Dependencies::find_finalizable_subclass(get_instanceKlass()) != NULL; duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::get_field_by_offset duke@435: ciField* ciInstanceKlass::get_field_by_offset(int field_offset, bool is_static) { duke@435: if (!is_static) { duke@435: for (int i = 0, len = nof_nonstatic_fields(); i < len; i++) { duke@435: ciField* field = _nonstatic_fields->at(i); duke@435: int field_off = field->offset_in_bytes(); duke@435: if (field_off == field_offset) duke@435: return field; duke@435: if (field_off > field_offset) duke@435: break; duke@435: // could do binary search or check bins, but probably not worth it duke@435: } duke@435: return NULL; duke@435: } duke@435: VM_ENTRY_MARK; coleenp@4037: InstanceKlass* k = get_instanceKlass(); duke@435: fieldDescriptor fd; duke@435: if (!k->find_field_from_offset(field_offset, is_static, &fd)) { duke@435: return NULL; duke@435: } duke@435: ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd); duke@435: return field; duke@435: } duke@435: kvn@479: // ------------------------------------------------------------------ never@1515: // ciInstanceKlass::get_field_by_name never@1515: ciField* ciInstanceKlass::get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static) { never@1515: VM_ENTRY_MARK; coleenp@4037: InstanceKlass* k = get_instanceKlass(); never@1515: fieldDescriptor fd; coleenp@4037: Klass* def = k->find_field(name->get_symbol(), signature->get_symbol(), is_static, &fd); never@1515: if (def == NULL) { never@1515: return NULL; never@1515: } never@1515: ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd); never@1515: return field; never@1515: } never@1515: never@1515: // ------------------------------------------------------------------ kvn@479: // ciInstanceKlass::non_static_fields. kvn@479: kvn@479: class NonStaticFieldFiller: public FieldClosure { kvn@479: GrowableArray* _arr; kvn@479: ciEnv* _curEnv; kvn@479: public: kvn@479: NonStaticFieldFiller(ciEnv* curEnv, GrowableArray* arr) : kvn@479: _curEnv(curEnv), _arr(arr) kvn@479: {} kvn@479: void do_field(fieldDescriptor* fd) { kvn@479: ciField* field = new (_curEnv->arena()) ciField(fd); kvn@479: _arr->append(field); kvn@479: } kvn@479: }; kvn@479: kvn@479: GrowableArray* ciInstanceKlass::non_static_fields() { kvn@479: if (_non_static_fields == NULL) { kvn@479: VM_ENTRY_MARK; kvn@479: ciEnv* curEnv = ciEnv::current(); coleenp@4037: InstanceKlass* ik = get_instanceKlass(); never@3137: int max_n_fields = ik->java_fields_count(); kvn@479: kvn@2040: Arena* arena = curEnv->arena(); kvn@479: _non_static_fields = kvn@2040: new (arena) GrowableArray(arena, max_n_fields, 0, NULL); kvn@479: NonStaticFieldFiller filler(curEnv, _non_static_fields); kvn@479: ik->do_nonstatic_fields(&filler); kvn@479: } kvn@479: return _non_static_fields; kvn@479: } kvn@479: duke@435: static int sort_field_by_offset(ciField** a, ciField** b) { duke@435: return (*a)->offset_in_bytes() - (*b)->offset_in_bytes(); duke@435: // (no worries about 32-bit overflow...) duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::compute_nonstatic_fields duke@435: int ciInstanceKlass::compute_nonstatic_fields() { duke@435: assert(is_loaded(), "must be loaded"); duke@435: duke@435: if (_nonstatic_fields != NULL) duke@435: return _nonstatic_fields->length(); duke@435: coleenp@548: if (!has_nonstatic_fields()) { duke@435: Arena* arena = CURRENT_ENV->arena(); duke@435: _nonstatic_fields = new (arena) GrowableArray(arena, 0, 0, NULL); duke@435: return 0; duke@435: } duke@435: assert(!is_java_lang_Object(), "bootstrap OK"); duke@435: coleenp@548: // Size in bytes of my fields, including inherited fields. kvn@600: int fsize = nonstatic_field_size() * heapOopSize; coleenp@548: duke@435: ciInstanceKlass* super = this->super(); duke@435: GrowableArray* super_fields = NULL; coleenp@548: if (super != NULL && super->has_nonstatic_fields()) { kvn@600: int super_fsize = super->nonstatic_field_size() * heapOopSize; coleenp@548: int super_flen = super->nof_nonstatic_fields(); duke@435: super_fields = super->_nonstatic_fields; duke@435: assert(super_flen == 0 || super_fields != NULL, "first get nof_fields"); coleenp@548: // See if I am no larger than my super; if so, I can use his fields. coleenp@548: if (fsize == super_fsize) { coleenp@548: _nonstatic_fields = super_fields; coleenp@548: return super_fields->length(); coleenp@548: } duke@435: } duke@435: duke@435: GrowableArray* fields = NULL; duke@435: GUARDED_VM_ENTRY({ duke@435: fields = compute_nonstatic_fields_impl(super_fields); duke@435: }); duke@435: duke@435: if (fields == NULL) { duke@435: // This can happen if this class (java.lang.Class) has invisible fields. duke@435: _nonstatic_fields = super_fields; duke@435: return super_fields->length(); duke@435: } duke@435: duke@435: int flen = fields->length(); duke@435: duke@435: // Now sort them by offset, ascending. duke@435: // (In principle, they could mix with superclass fields.) duke@435: fields->sort(sort_field_by_offset); duke@435: _nonstatic_fields = fields; duke@435: return flen; duke@435: } duke@435: duke@435: GrowableArray* duke@435: ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray* duke@435: super_fields) { duke@435: ASSERT_IN_VM; duke@435: Arena* arena = CURRENT_ENV->arena(); duke@435: int flen = 0; duke@435: GrowableArray* fields = NULL; coleenp@4037: InstanceKlass* k = get_instanceKlass(); never@3137: for (JavaFieldStream fs(k); !fs.done(); fs.next()) { never@3137: if (fs.access_flags().is_static()) continue; never@3137: flen += 1; never@3137: } duke@435: never@3137: // allocate the array: never@3137: if (flen == 0) { never@3137: return NULL; // return nothing if none are locally declared never@3137: } never@3137: if (super_fields != NULL) { never@3137: flen += super_fields->length(); never@3137: } never@3137: fields = new (arena) GrowableArray(arena, flen, 0, NULL); never@3137: if (super_fields != NULL) { never@3137: fields->appendAll(super_fields); never@3137: } never@3137: never@3137: for (JavaFieldStream fs(k); !fs.done(); fs.next()) { never@3137: if (fs.access_flags().is_static()) continue; drchase@5732: fieldDescriptor& fd = fs.field_descriptor(); never@3137: ciField* field = new (arena) ciField(&fd); never@3137: fields->append(field); duke@435: } duke@435: assert(fields->length() == flen, "sanity"); duke@435: return fields; duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::find_method duke@435: // duke@435: // Find a method in this klass. duke@435: ciMethod* ciInstanceKlass::find_method(ciSymbol* name, ciSymbol* signature) { duke@435: VM_ENTRY_MARK; coleenp@4037: InstanceKlass* k = get_instanceKlass(); coleenp@2497: Symbol* name_sym = name->get_symbol(); coleenp@2497: Symbol* sig_sym= signature->get_symbol(); duke@435: coleenp@4037: Method* m = k->find_method(name_sym, sig_sym); duke@435: if (m == NULL) return NULL; duke@435: coleenp@4037: return CURRENT_THREAD_ENV->get_method(m); duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::is_leaf_type duke@435: bool ciInstanceKlass::is_leaf_type() { duke@435: assert(is_loaded(), "must be loaded"); duke@435: if (is_shared()) { duke@435: return is_final(); // approximately correct duke@435: } else { jiangli@3701: return !_has_subklass && (nof_implementors() == 0); duke@435: } duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::implementor duke@435: // duke@435: // Report an implementor of this interface. duke@435: // Note that there are various races here, since my copy duke@435: // of _nof_implementors might be out of date with respect coleenp@4037: // to results returned by InstanceKlass::implementor. duke@435: // This is OK, since any dependencies we decide to assert duke@435: // will be checked later under the Compile_lock. jiangli@3701: ciInstanceKlass* ciInstanceKlass::implementor() { jiangli@3701: ciInstanceKlass* impl = _implementor; duke@435: if (impl == NULL) { duke@435: // Go into the VM to fetch the implementor. duke@435: { duke@435: VM_ENTRY_MARK; coleenp@4037: Klass* k = get_instanceKlass()->implementor(); duke@435: if (k != NULL) { coleenp@4037: if (k == get_instanceKlass()) { jiangli@3701: // More than one implementors. Use 'this' in this case. jiangli@3701: impl = this; jiangli@3701: } else { coleenp@4037: impl = CURRENT_THREAD_ENV->get_instance_klass(k); jiangli@3701: } duke@435: } duke@435: } duke@435: // Memoize this result. duke@435: if (!is_shared()) { jiangli@3701: _implementor = impl; duke@435: } duke@435: } duke@435: return impl; duke@435: } minqi@4267: minqi@4267: // Utility class for printing of the contents of the static fields for minqi@4267: // use by compilation replay. It only prints out the information that minqi@4267: // could be consumed by the compiler, so for primitive types it prints minqi@4267: // out the actual value. For Strings it's the actual string value. minqi@4267: // For array types it it's first level array size since that's the minqi@4267: // only value which statically unchangeable. For all other reference minqi@4267: // types it simply prints out the dynamic type. minqi@4267: minqi@4267: class StaticFinalFieldPrinter : public FieldClosure { minqi@4267: outputStream* _out; minqi@4267: const char* _holder; minqi@4267: public: minqi@4267: StaticFinalFieldPrinter(outputStream* out, const char* holder) : minqi@4267: _out(out), minqi@4267: _holder(holder) { minqi@4267: } minqi@4267: void do_field(fieldDescriptor* fd) { minqi@4267: if (fd->is_final() && !fd->has_initial_value()) { vlivanov@4531: ResourceMark rm; minqi@4267: oop mirror = fd->field_holder()->java_mirror(); minqi@4267: _out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii()); minqi@4267: switch (fd->field_type()) { minqi@4267: case T_BYTE: _out->print_cr("%d", mirror->byte_field(fd->offset())); break; minqi@4267: case T_BOOLEAN: _out->print_cr("%d", mirror->bool_field(fd->offset())); break; minqi@4267: case T_SHORT: _out->print_cr("%d", mirror->short_field(fd->offset())); break; minqi@4267: case T_CHAR: _out->print_cr("%d", mirror->char_field(fd->offset())); break; minqi@4267: case T_INT: _out->print_cr("%d", mirror->int_field(fd->offset())); break; minqi@4267: case T_LONG: _out->print_cr(INT64_FORMAT, mirror->long_field(fd->offset())); break; minqi@4267: case T_FLOAT: { minqi@4267: float f = mirror->float_field(fd->offset()); minqi@4267: _out->print_cr("%d", *(int*)&f); minqi@4267: break; minqi@4267: } minqi@4267: case T_DOUBLE: { minqi@4267: double d = mirror->double_field(fd->offset()); minqi@4267: _out->print_cr(INT64_FORMAT, *(jlong*)&d); minqi@4267: break; minqi@4267: } minqi@4267: case T_ARRAY: { minqi@4267: oop value = mirror->obj_field_acquire(fd->offset()); minqi@4267: if (value == NULL) { minqi@4267: _out->print_cr("null"); minqi@4267: } else { minqi@4267: typeArrayOop ta = (typeArrayOop)value; minqi@4267: _out->print("%d", ta->length()); minqi@4267: if (value->is_objArray()) { minqi@4267: objArrayOop oa = (objArrayOop)value; minqi@4267: const char* klass_name = value->klass()->name()->as_quoted_ascii(); minqi@4267: _out->print(" %s", klass_name); minqi@4267: } minqi@4267: _out->cr(); minqi@4267: } minqi@4267: break; minqi@4267: } minqi@4267: case T_OBJECT: { minqi@4267: oop value = mirror->obj_field_acquire(fd->offset()); minqi@4267: if (value == NULL) { minqi@4267: _out->print_cr("null"); minqi@4267: } else if (value->is_instance()) { minqi@4267: if (value->is_a(SystemDictionary::String_klass())) { minqi@4267: _out->print("\""); minqi@4267: _out->print_raw(java_lang_String::as_quoted_ascii(value)); minqi@4267: _out->print_cr("\""); minqi@4267: } else { minqi@4267: const char* klass_name = value->klass()->name()->as_quoted_ascii(); minqi@4267: _out->print_cr(klass_name); minqi@4267: } minqi@4267: } else { minqi@4267: ShouldNotReachHere(); minqi@4267: } minqi@4267: break; minqi@4267: } minqi@4267: default: minqi@4267: ShouldNotReachHere(); minqi@4267: } minqi@4267: } minqi@4267: } minqi@4267: }; minqi@4267: minqi@4267: minqi@4267: void ciInstanceKlass::dump_replay_data(outputStream* out) { vlivanov@4531: ResourceMark rm; vlivanov@4531: minqi@4267: InstanceKlass* ik = get_instanceKlass(); minqi@4267: ConstantPool* cp = ik->constants(); minqi@4267: minqi@4267: // Try to record related loaded classes minqi@4267: Klass* sub = ik->subklass(); minqi@4267: while (sub != NULL) { minqi@4267: if (sub->oop_is_instance()) { minqi@4267: out->print_cr("instanceKlass %s", sub->name()->as_quoted_ascii()); minqi@4267: } minqi@4267: sub = sub->next_sibling(); minqi@4267: } minqi@4267: minqi@4267: // Dump out the state of the constant pool tags. During replay the minqi@4267: // tags will be validated for things which shouldn't change and minqi@4267: // classes will be resolved if the tags indicate that they were minqi@4267: // resolved at compile time. minqi@4267: out->print("ciInstanceKlass %s %d %d %d", ik->name()->as_quoted_ascii(), minqi@4267: is_linked(), is_initialized(), cp->length()); minqi@4267: for (int index = 1; index < cp->length(); index++) { minqi@4267: out->print(" %d", cp->tags()->at(index)); minqi@4267: } minqi@4267: out->cr(); minqi@4267: if (is_initialized()) { minqi@4267: // Dump out the static final fields in case the compilation relies minqi@4267: // on their value for correct replay. minqi@4267: StaticFinalFieldPrinter sffp(out, ik->name()->as_quoted_ascii()); minqi@4267: ik->do_local_static_fields(&sffp); minqi@4267: } minqi@4267: }