duke@435: /* xdono@631: * Copyright 1999-2008 Sun Microsystems, Inc. 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: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: #include "incls/_precompiled.incl" duke@435: #include "incls/_ciInstanceKlass.cpp.incl" duke@435: duke@435: // ciInstanceKlass duke@435: // duke@435: // This class represents a klassOop in the HotSpot virtual machine duke@435: // 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"); duke@435: 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; duke@435: _is_initialized = ik->is_initialized(); duke@435: // Next line must follow and use the result of the previous line: duke@435: _is_linked = _is_initialized || ik->is_linked(); 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: duke@435: _nof_implementors = ik->nof_implementors(); duke@435: for (int i = 0; i < implementors_limit; i++) { duke@435: _implementors[i] = NULL; // we will fill these lazily duke@435: } 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: java_mirror(); 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) duke@435: : ciKlass(name, ciInstanceKlassKlass::make()) duke@435: { duke@435: assert(name->byte_at(0) != '[', "not an instance klass"); duke@435: _is_initialized = false; duke@435: _is_linked = false; duke@435: _nonstatic_field_size = -1; coleenp@548: _has_nonstatic_fields = false; duke@435: _nonstatic_fields = NULL; duke@435: _nof_implementors = -1; 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 duke@435: bool ciInstanceKlass::compute_shared_is_initialized() { duke@435: GUARDED_VM_ENTRY( duke@435: instanceKlass* ik = get_instanceKlass(); duke@435: _is_initialized = ik->is_initialized(); duke@435: return _is_initialized; duke@435: ) duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::compute_shared_is_linked duke@435: bool ciInstanceKlass::compute_shared_is_linked() { duke@435: GUARDED_VM_ENTRY( duke@435: instanceKlass* ik = get_instanceKlass(); duke@435: _is_linked = ik->is_linked(); duke@435: return _is_linked; 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( duke@435: 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::compute_shared_nof_implementors duke@435: int ciInstanceKlass::compute_shared_nof_implementors() { duke@435: // We requery this property, since it is a very old ciObject. duke@435: GUARDED_VM_ENTRY( duke@435: instanceKlass* ik = get_instanceKlass(); duke@435: _nof_implementors = ik->nof_implementors(); duke@435: return _nof_implementors; 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? duke@435: bool ciInstanceKlass::is_java_lang_Object() { duke@435: return equals(CURRENT_ENV->Object_klass()); duke@435: } duke@435: duke@435: // ------------------------------------------------------------------ duke@435: // ciInstanceKlass::uses_default_loader duke@435: bool ciInstanceKlass::uses_default_loader() { 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: // ------------------------------------------------------------------ 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( duke@435: klassOop super_klass = get_instanceKlass()->super(); duke@435: _super = CURRENT_ENV->get_object(super_klass)->as_instance_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. duke@435: ciInstance* ciInstanceKlass::java_mirror() { duke@435: assert(is_loaded(), "must be loaded"); duke@435: if (_java_mirror == NULL) { duke@435: _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; duke@435: instanceKlass* ik = get_instanceKlass(); duke@435: Klass* up = ik->up_cast_abstract(); duke@435: assert(up->oop_is_instance(), "must be instanceKlass"); duke@435: if (ik == up) { duke@435: return NULL; duke@435: } duke@435: return CURRENT_THREAD_ENV->get_object(up->as_klassOop())->as_instance_klass(); 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; duke@435: 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; never@1515: instanceKlass* k = get_instanceKlass(); never@1515: fieldDescriptor fd; never@1515: klassOop def = k->find_field(name->get_symbolOop(), signature->get_symbolOop(), 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(); kvn@479: instanceKlass* ik = get_instanceKlass(); kvn@479: int max_n_fields = ik->fields()->length()/instanceKlass::next_offset; kvn@479: kvn@479: _non_static_fields = kvn@479: new (curEnv->arena()) GrowableArray(max_n_fields); 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: #ifdef ASSERT coleenp@548: int last_offset = instanceOopDesc::base_offset_in_bytes(); duke@435: for (int i = 0; i < fields->length(); i++) { duke@435: ciField* field = fields->at(i); duke@435: int offset = field->offset_in_bytes(); coleenp@548: int size = (field->_type == NULL) ? heapOopSize : field->size_in_bytes(); duke@435: assert(last_offset <= offset, "no field overlap"); duke@435: if (last_offset > (int)sizeof(oopDesc)) duke@435: assert((offset - last_offset) < BytesPerLong, "no big holes"); duke@435: // Note: Two consecutive T_BYTE fields will be separated by wordSize-1 duke@435: // padding bytes if one of them is declared by a superclass. duke@435: // This is a minor inefficiency classFileParser.cpp. duke@435: last_offset = offset + size; duke@435: } kvn@600: assert(last_offset <= (int)instanceOopDesc::base_offset_in_bytes() + fsize, "no overflow"); duke@435: #endif duke@435: 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; duke@435: instanceKlass* k = get_instanceKlass(); duke@435: typeArrayOop fields_array = k->fields(); duke@435: for (int pass = 0; pass <= 1; pass++) { duke@435: for (int i = 0, alen = fields_array->length(); i < alen; i += instanceKlass::next_offset) { duke@435: fieldDescriptor fd; duke@435: fd.initialize(k->as_klassOop(), i); duke@435: if (fd.is_static()) continue; duke@435: if (pass == 0) { duke@435: flen += 1; duke@435: } else { duke@435: ciField* field = new (arena) ciField(&fd); duke@435: fields->append(field); duke@435: } duke@435: } duke@435: duke@435: // Between passes, allocate the array: duke@435: if (pass == 0) { duke@435: if (flen == 0) { duke@435: return NULL; // return nothing if none are locally declared duke@435: } duke@435: if (super_fields != NULL) { duke@435: flen += super_fields->length(); duke@435: } duke@435: fields = new (arena) GrowableArray(arena, flen, 0, NULL); duke@435: if (super_fields != NULL) { duke@435: fields->appendAll(super_fields); duke@435: } duke@435: } 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; duke@435: instanceKlass* k = get_instanceKlass(); duke@435: symbolOop name_sym = name->get_symbolOop(); duke@435: symbolOop sig_sym= signature->get_symbolOop(); duke@435: duke@435: methodOop m = k->find_method(name_sym, sig_sym); duke@435: if (m == NULL) return NULL; duke@435: duke@435: return CURRENT_THREAD_ENV->get_object(m)->as_method(); 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 { duke@435: 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: // Returns NULL if exact information is not available. duke@435: // Note that there are various races here, since my copy duke@435: // of _nof_implementors might be out of date with respect duke@435: // 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. duke@435: ciInstanceKlass* ciInstanceKlass::implementor(int n) { duke@435: if (n > implementors_limit) { duke@435: return NULL; duke@435: } duke@435: ciInstanceKlass* impl = _implementors[n]; duke@435: if (impl == NULL) { duke@435: if (_nof_implementors > implementors_limit) { duke@435: return NULL; duke@435: } duke@435: // Go into the VM to fetch the implementor. duke@435: { duke@435: VM_ENTRY_MARK; duke@435: klassOop k = get_instanceKlass()->implementor(n); duke@435: if (k != NULL) { duke@435: impl = CURRENT_THREAD_ENV->get_object(k)->as_instance_klass(); duke@435: } duke@435: } duke@435: // Memoize this result. duke@435: if (!is_shared()) { duke@435: _implementors[n] = (impl == NULL)? this: impl; duke@435: } duke@435: } else if (impl == this) { duke@435: impl = NULL; // memoized null result from a VM query duke@435: } duke@435: return impl; duke@435: }