--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/oops/klass.cpp Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,562 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+# include "incls/_precompiled.incl"
+# include "incls/_klass.cpp.incl"
+
+
+bool Klass::is_subclass_of(klassOop k) const {
+ // Run up the super chain and check
+ klassOop t = as_klassOop();
+
+ if (t == k) return true;
+ t = Klass::cast(t)->super();
+
+ while (t != NULL) {
+ if (t == k) return true;
+ t = Klass::cast(t)->super();
+ }
+ return false;
+}
+
+bool Klass::search_secondary_supers(klassOop k) const {
+ // Put some extra logic here out-of-line, before the search proper.
+ // This cuts down the size of the inline method.
+
+ // This is necessary, since I am never in my own secondary_super list.
+ if (this->as_klassOop() == k)
+ return true;
+ // Scan the array-of-objects for a match
+ int cnt = secondary_supers()->length();
+ for (int i = 0; i < cnt; i++) {
+ if (secondary_supers()->obj_at(i) == k) {
+ ((Klass*)this)->set_secondary_super_cache(k);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Return self, except for abstract classes with exactly 1
+// implementor. Then return the 1 concrete implementation.
+Klass *Klass::up_cast_abstract() {
+ Klass *r = this;
+ while( r->is_abstract() ) { // Receiver is abstract?
+ Klass *s = r->subklass(); // Check for exactly 1 subklass
+ if( !s || s->next_sibling() ) // Oops; wrong count; give up
+ return this; // Return 'this' as a no-progress flag
+ r = s; // Loop till find concrete class
+ }
+ return r; // Return the 1 concrete class
+}
+
+// Find LCA in class heirarchy
+Klass *Klass::LCA( Klass *k2 ) {
+ Klass *k1 = this;
+ while( 1 ) {
+ if( k1->is_subtype_of(k2->as_klassOop()) ) return k2;
+ if( k2->is_subtype_of(k1->as_klassOop()) ) return k1;
+ k1 = k1->super()->klass_part();
+ k2 = k2->super()->klass_part();
+ }
+}
+
+
+void Klass::check_valid_for_instantiation(bool throwError, TRAPS) {
+ ResourceMark rm(THREAD);
+ THROW_MSG(throwError ? vmSymbols::java_lang_InstantiationError()
+ : vmSymbols::java_lang_InstantiationException(), external_name());
+}
+
+
+void Klass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) {
+ THROW(vmSymbols::java_lang_ArrayStoreException());
+}
+
+
+void Klass::initialize(TRAPS) {
+ ShouldNotReachHere();
+}
+
+bool Klass::compute_is_subtype_of(klassOop k) {
+ assert(k->is_klass(), "argument must be a class");
+ return is_subclass_of(k);
+}
+
+
+methodOop Klass::uncached_lookup_method(symbolOop name, symbolOop signature) const {
+#ifdef ASSERT
+ tty->print_cr("Error: uncached_lookup_method called on a klass oop."
+ " Likely error: reflection method does not correctly"
+ " wrap return value in a mirror object.");
+#endif
+ ShouldNotReachHere();
+ return NULL;
+}
+
+klassOop Klass::base_create_klass_oop(KlassHandle& klass, int size,
+ const Klass_vtbl& vtbl, TRAPS) {
+ size = align_object_size(size);
+ // allocate and initialize vtable
+ Klass* kl = (Klass*) vtbl.allocate_permanent(klass, size, CHECK_NULL);
+ klassOop k = kl->as_klassOop();
+
+ { // Preinitialize supertype information.
+ // A later call to initialize_supers() may update these settings:
+ kl->set_super(NULL);
+ for (juint i = 0; i < Klass::primary_super_limit(); i++) {
+ kl->_primary_supers[i] = NULL;
+ }
+ kl->set_secondary_supers(NULL);
+ oop_store_without_check((oop*) &kl->_primary_supers[0], k);
+ kl->set_super_check_offset(primary_supers_offset_in_bytes() + sizeof(oopDesc));
+ }
+
+ kl->set_java_mirror(NULL);
+ kl->set_modifier_flags(0);
+ kl->set_layout_helper(Klass::_lh_neutral_value);
+ kl->set_name(NULL);
+ AccessFlags af;
+ af.set_flags(0);
+ kl->set_access_flags(af);
+ kl->set_subklass(NULL);
+ kl->set_next_sibling(NULL);
+ kl->set_alloc_count(0);
+ kl->set_alloc_size(0);
+
+ kl->set_prototype_header(markOopDesc::prototype());
+ kl->set_biased_lock_revocation_count(0);
+ kl->set_last_biased_lock_bulk_revocation_time(0);
+
+ return k;
+}
+
+KlassHandle Klass::base_create_klass(KlassHandle& klass, int size,
+ const Klass_vtbl& vtbl, TRAPS) {
+ klassOop ek = base_create_klass_oop(klass, size, vtbl, THREAD);
+ return KlassHandle(THREAD, ek);
+}
+
+void Klass_vtbl::post_new_init_klass(KlassHandle& klass,
+ klassOop new_klass,
+ int size) const {
+ assert(!new_klass->klass_part()->null_vtbl(), "Not a complete klass");
+ CollectedHeap::post_allocation_install_obj_klass(klass, new_klass, size);
+}
+
+void* Klass_vtbl::operator new(size_t ignored, KlassHandle& klass,
+ int size, TRAPS) {
+ // The vtable pointer is installed during the execution of
+ // constructors in the call to permanent_obj_allocate(). Delay
+ // the installation of the klass pointer into the new klass "k"
+ // until after the vtable pointer has been installed (i.e., until
+ // after the return of permanent_obj_allocate().
+ klassOop k =
+ (klassOop) CollectedHeap::permanent_obj_allocate_no_klass_install(klass,
+ size, CHECK_NULL);
+ return k->klass_part();
+}
+
+jint Klass::array_layout_helper(BasicType etype) {
+ assert(etype >= T_BOOLEAN && etype <= T_OBJECT, "valid etype");
+ // Note that T_ARRAY is not allowed here.
+ int hsize = arrayOopDesc::base_offset_in_bytes(etype);
+ int esize = type2aelembytes[etype];
+ bool isobj = (etype == T_OBJECT);
+ int tag = isobj ? _lh_array_tag_obj_value : _lh_array_tag_type_value;
+ int lh = array_layout_helper(tag, hsize, etype, exact_log2(esize));
+
+ assert(lh < (int)_lh_neutral_value, "must look like an array layout");
+ assert(layout_helper_is_javaArray(lh), "correct kind");
+ assert(layout_helper_is_objArray(lh) == isobj, "correct kind");
+ assert(layout_helper_is_typeArray(lh) == !isobj, "correct kind");
+ assert(layout_helper_header_size(lh) == hsize, "correct decode");
+ assert(layout_helper_element_type(lh) == etype, "correct decode");
+ assert(1 << layout_helper_log2_element_size(lh) == esize, "correct decode");
+
+ return lh;
+}
+
+bool Klass::can_be_primary_super_slow() const {
+ if (super() == NULL)
+ return true;
+ else if (super()->klass_part()->super_depth() >= primary_super_limit()-1)
+ return false;
+ else
+ return true;
+}
+
+void Klass::initialize_supers(klassOop k, TRAPS) {
+ if (FastSuperclassLimit == 0) {
+ // None of the other machinery matters.
+ set_super(k);
+ return;
+ }
+ if (k == NULL) {
+ set_super(NULL);
+ oop_store_without_check((oop*) &_primary_supers[0], (oop) this->as_klassOop());
+ assert(super_depth() == 0, "Object must already be initialized properly");
+ } else if (k != super() || k == SystemDictionary::object_klass()) {
+ assert(super() == NULL || super() == SystemDictionary::object_klass(),
+ "initialize this only once to a non-trivial value");
+ set_super(k);
+ Klass* sup = k->klass_part();
+ int sup_depth = sup->super_depth();
+ juint my_depth = MIN2(sup_depth + 1, (int)primary_super_limit());
+ if (!can_be_primary_super_slow())
+ my_depth = primary_super_limit();
+ for (juint i = 0; i < my_depth; i++) {
+ oop_store_without_check((oop*) &_primary_supers[i], (oop) sup->_primary_supers[i]);
+ }
+ klassOop *super_check_cell;
+ if (my_depth < primary_super_limit()) {
+ oop_store_without_check((oop*) &_primary_supers[my_depth], (oop) this->as_klassOop());
+ super_check_cell = &_primary_supers[my_depth];
+ } else {
+ // Overflow of the primary_supers array forces me to be secondary.
+ super_check_cell = &_secondary_super_cache;
+ }
+ set_super_check_offset((address)super_check_cell - (address) this->as_klassOop());
+
+#ifdef ASSERT
+ {
+ juint j = super_depth();
+ assert(j == my_depth, "computed accessor gets right answer");
+ klassOop t = as_klassOop();
+ while (!Klass::cast(t)->can_be_primary_super()) {
+ t = Klass::cast(t)->super();
+ j = Klass::cast(t)->super_depth();
+ }
+ for (juint j1 = j+1; j1 < primary_super_limit(); j1++) {
+ assert(primary_super_of_depth(j1) == NULL, "super list padding");
+ }
+ while (t != NULL) {
+ assert(primary_super_of_depth(j) == t, "super list initialization");
+ t = Klass::cast(t)->super();
+ --j;
+ }
+ assert(j == (juint)-1, "correct depth count");
+ }
+#endif
+ }
+
+ if (secondary_supers() == NULL) {
+ KlassHandle this_kh (THREAD, this);
+
+ // Now compute the list of secondary supertypes.
+ // Secondaries can occasionally be on the super chain,
+ // if the inline "_primary_supers" array overflows.
+ int extras = 0;
+ klassOop p;
+ for (p = super(); !(p == NULL || p->klass_part()->can_be_primary_super()); p = p->klass_part()->super()) {
+ ++extras;
+ }
+
+ // Compute the "real" non-extra secondaries.
+ objArrayOop secondary_oops = compute_secondary_supers(extras, CHECK);
+ objArrayHandle secondaries (THREAD, secondary_oops);
+
+ // Store the extra secondaries in the first array positions:
+ int fillp = extras;
+ for (p = this_kh->super(); !(p == NULL || p->klass_part()->can_be_primary_super()); p = p->klass_part()->super()) {
+ int i; // Scan for overflow primaries being duplicates of 2nd'arys
+
+ // This happens frequently for very deeply nested arrays: the
+ // primary superclass chain overflows into the secondary. The
+ // secondary list contains the element_klass's secondaries with
+ // an extra array dimension added. If the element_klass's
+ // secondary list already contains some primary overflows, they
+ // (with the extra level of array-ness) will collide with the
+ // normal primary superclass overflows.
+ for( i = extras; i < secondaries->length(); i++ )
+ if( secondaries->obj_at(i) == p )
+ break;
+ if( i < secondaries->length() )
+ continue; // It's a dup, don't put it in
+ secondaries->obj_at_put(--fillp, p);
+ }
+ // See if we had some dup's, so the array has holes in it.
+ if( fillp > 0 ) {
+ // Pack the array. Drop the old secondaries array on the floor
+ // and let GC reclaim it.
+ objArrayOop s2 = oopFactory::new_system_objArray(secondaries->length() - fillp, CHECK);
+ for( int i = 0; i < s2->length(); i++ )
+ s2->obj_at_put( i, secondaries->obj_at(i+fillp) );
+ secondaries = objArrayHandle(THREAD, s2);
+ }
+
+ #ifdef ASSERT
+ if (secondaries() != Universe::the_array_interfaces_array()) {
+ // We must not copy any NULL placeholders left over from bootstrap.
+ for (int j = 0; j < secondaries->length(); j++) {
+ assert(secondaries->obj_at(j) != NULL, "correct bootstrapping order");
+ }
+ }
+ #endif
+
+ this_kh->set_secondary_supers(secondaries());
+ }
+}
+
+objArrayOop Klass::compute_secondary_supers(int num_extra_slots, TRAPS) {
+ assert(num_extra_slots == 0, "override for complex klasses");
+ return Universe::the_empty_system_obj_array();
+}
+
+
+Klass* Klass::subklass() const {
+ return _subklass == NULL ? NULL : Klass::cast(_subklass);
+}
+
+instanceKlass* Klass::superklass() const {
+ assert(super() == NULL || super()->klass_part()->oop_is_instance(), "must be instance klass");
+ return _super == NULL ? NULL : instanceKlass::cast(_super);
+}
+
+Klass* Klass::next_sibling() const {
+ return _next_sibling == NULL ? NULL : Klass::cast(_next_sibling);
+}
+
+void Klass::set_subklass(klassOop s) {
+ assert(s != as_klassOop(), "sanity check");
+ oop_store_without_check((oop*)&_subklass, s);
+}
+
+void Klass::set_next_sibling(klassOop s) {
+ assert(s != as_klassOop(), "sanity check");
+ oop_store_without_check((oop*)&_next_sibling, s);
+}
+
+void Klass::append_to_sibling_list() {
+ debug_only(if (!SharedSkipVerify) as_klassOop()->verify();)
+ // add ourselves to superklass' subklass list
+ instanceKlass* super = superklass();
+ if (super == NULL) return; // special case: class Object
+ assert(SharedSkipVerify ||
+ (!super->is_interface() // interfaces cannot be supers
+ && (super->superklass() == NULL || !is_interface())),
+ "an interface can only be a subklass of Object");
+ klassOop prev_first_subklass = super->subklass_oop();
+ if (prev_first_subklass != NULL) {
+ // set our sibling to be the superklass' previous first subklass
+ set_next_sibling(prev_first_subklass);
+ }
+ // make ourselves the superklass' first subklass
+ super->set_subklass(as_klassOop());
+ debug_only(if (!SharedSkipVerify) as_klassOop()->verify();)
+}
+
+void Klass::remove_from_sibling_list() {
+ // remove receiver from sibling list
+ instanceKlass* super = superklass();
+ assert(super != NULL || as_klassOop() == SystemDictionary::object_klass(), "should have super");
+ if (super == NULL) return; // special case: class Object
+ if (super->subklass() == this) {
+ // first subklass
+ super->set_subklass(_next_sibling);
+ } else {
+ Klass* sib = super->subklass();
+ while (sib->next_sibling() != this) {
+ sib = sib->next_sibling();
+ };
+ sib->set_next_sibling(_next_sibling);
+ }
+}
+
+void Klass::follow_weak_klass_links( BoolObjectClosure* is_alive, OopClosure* keep_alive) {
+ // This klass is alive but the subklass and siblings are not followed/updated.
+ // We update the subklass link and the subklass' sibling links here.
+ // Our own sibling link will be updated by our superclass (which must be alive
+ // since we are).
+ assert(is_alive->do_object_b(as_klassOop()), "just checking, this should be live");
+ if (ClassUnloading) {
+ klassOop sub = subklass_oop();
+ if (sub != NULL && !is_alive->do_object_b(sub)) {
+ // first subklass not alive, find first one alive
+ do {
+#ifndef PRODUCT
+ if (TraceClassUnloading && WizardMode) {
+ ResourceMark rm;
+ tty->print_cr("[Unlinking class (subclass) %s]", sub->klass_part()->external_name());
+ }
+#endif
+ sub = sub->klass_part()->next_sibling_oop();
+ } while (sub != NULL && !is_alive->do_object_b(sub));
+ set_subklass(sub);
+ }
+ // now update the subklass' sibling list
+ while (sub != NULL) {
+ klassOop next = sub->klass_part()->next_sibling_oop();
+ if (next != NULL && !is_alive->do_object_b(next)) {
+ // first sibling not alive, find first one alive
+ do {
+#ifndef PRODUCT
+ if (TraceClassUnloading && WizardMode) {
+ ResourceMark rm;
+ tty->print_cr("[Unlinking class (sibling) %s]", next->klass_part()->external_name());
+ }
+#endif
+ next = next->klass_part()->next_sibling_oop();
+ } while (next != NULL && !is_alive->do_object_b(next));
+ sub->klass_part()->set_next_sibling(next);
+ }
+ sub = next;
+ }
+ } else {
+ // Always follow subklass and sibling link. This will prevent any klasses from
+ // being unloaded (all classes are transitively linked from java.lang.Object).
+ keep_alive->do_oop(adr_subklass());
+ keep_alive->do_oop(adr_next_sibling());
+ }
+}
+
+
+void Klass::remove_unshareable_info() {
+ if (oop_is_instance()) {
+ instanceKlass* ik = (instanceKlass*)this;
+ if (ik->is_linked()) {
+ ik->unlink_class();
+ }
+ }
+ set_subklass(NULL);
+ set_next_sibling(NULL);
+}
+
+
+klassOop Klass::array_klass_or_null(int rank) {
+ EXCEPTION_MARK;
+ // No exception can be thrown by array_klass_impl when called with or_null == true.
+ // (In anycase, the execption mark will fail if it do so)
+ return array_klass_impl(true, rank, THREAD);
+}
+
+
+klassOop Klass::array_klass_or_null() {
+ EXCEPTION_MARK;
+ // No exception can be thrown by array_klass_impl when called with or_null == true.
+ // (In anycase, the execption mark will fail if it do so)
+ return array_klass_impl(true, THREAD);
+}
+
+
+klassOop Klass::array_klass_impl(bool or_null, int rank, TRAPS) {
+ fatal("array_klass should be dispatched to instanceKlass, objArrayKlass or typeArrayKlass");
+ return NULL;
+}
+
+
+klassOop Klass::array_klass_impl(bool or_null, TRAPS) {
+ fatal("array_klass should be dispatched to instanceKlass, objArrayKlass or typeArrayKlass");
+ return NULL;
+}
+
+
+void Klass::with_array_klasses_do(void f(klassOop k)) {
+ f(as_klassOop());
+}
+
+
+const char* Klass::external_name() const {
+ return name()->as_klass_external_name();
+}
+
+
+char* Klass::signature_name() const {
+ return name()->as_C_string();
+}
+
+// Unless overridden, modifier_flags is 0.
+jint Klass::compute_modifier_flags(TRAPS) const {
+ return 0;
+}
+
+int Klass::atomic_incr_biased_lock_revocation_count() {
+ return (int) Atomic::add(1, &_biased_lock_revocation_count);
+}
+
+// Unless overridden, jvmti_class_status has no flags set.
+jint Klass::jvmti_class_status() const {
+ return 0;
+}
+
+#ifndef PRODUCT
+
+// Printing
+
+void Klass::oop_print_on(oop obj, outputStream* st) {
+ ResourceMark rm;
+ // print title
+ st->print_cr("%s ", internal_name());
+ obj->print_address_on(st);
+
+ if (WizardMode) {
+ // print header
+ obj->mark()->print_on(st);
+ }
+
+ // print class
+ st->print(" - klass: ");
+ obj->klass()->print_value_on(st);
+ st->cr();
+}
+
+
+void Klass::oop_print_value_on(oop obj, outputStream* st) {
+ // print title
+ ResourceMark rm; // Cannot print in debug mode without this
+ st->print("%s", internal_name());
+ obj->print_address_on(st);
+}
+
+#endif
+
+// Verification
+
+void Klass::oop_verify_on(oop obj, outputStream* st) {
+ guarantee(obj->is_oop(), "should be oop");
+ guarantee(obj->klass()->is_perm(), "should be in permspace");
+ guarantee(obj->klass()->is_klass(), "klass field is not a klass");
+}
+
+
+void Klass::oop_verify_old_oop(oop obj, oop* p, bool allow_dirty) {
+ /* $$$ I think this functionality should be handled by verification of
+
+ RememberedSet::verify_old_oop(obj, p, allow_dirty, false);
+
+ the card table. */
+}
+
+#ifndef PRODUCT
+
+void Klass::verify_vtable_index(int i) {
+ assert(oop_is_instance() || oop_is_array(), "only instanceKlass and arrayKlass have vtables");
+ if (oop_is_instance()) {
+ assert(i>=0 && i<((instanceKlass*)this)->vtable_length()/vtableEntry::size(), "index out of bounds");
+ } else {
+ assert(i>=0 && i<((arrayKlass*)this)->vtable_length()/vtableEntry::size(), "index out of bounds");
+ }
+}
+
+#endif