# HG changeset patch # User jiangli # Date 1333073936 14400 # Node ID 48fd3da4025c23e07b9bcd674ad4f50a7960dd62 # Parent f3187578ddd303c012f57f401b414a627a8e9c20 7154670: The instanceKlass _implementors[] and _nof_implementors are not needed for non-interface klass. Summary: Change implementor to embedded instanceKlass field. Reviewed-by: sspitsyn, minqi, coleenp diff -r f3187578ddd3 -r 48fd3da4025c hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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 @@ -889,15 +889,9 @@ Klass kls = ((ReferenceTypeImpl)type).ref(); if (kls instanceof InstanceKlass) { InstanceKlass ik = (InstanceKlass) kls; - if (ik.isInterface()) { - if (ik.nofImplementors() == 0L) { - return new ArrayList(0); - } - } else { - // if the Klass is final or if there are no subklasses loaded yet - if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) { - includeSubtypes = false; - } + // if the Klass is final or if there are no subklasses loaded yet + if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) { + includeSubtypes = false; } } else { // no subtypes for primitive array types diff -r f3187578ddd3 -r 48fd3da4025c hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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 @@ -52,7 +52,6 @@ private static int HIGH_OFFSET; private static int GENERIC_SIGNATURE_INDEX_OFFSET; private static int FIELD_SLOTS; - public static int IMPLEMENTORS_LIMIT; // ClassState constants private static int CLASS_STATE_UNPARSABLE_BY_GC; @@ -70,13 +69,6 @@ methodOrdering = new OopField(type.getOopField("_method_ordering"), Oop.getHeaderSize()); localInterfaces = new OopField(type.getOopField("_local_interfaces"), Oop.getHeaderSize()); transitiveInterfaces = new OopField(type.getOopField("_transitive_interfaces"), Oop.getHeaderSize()); - nofImplementors = new CIntField(type.getCIntegerField("_nof_implementors"), Oop.getHeaderSize()); - IMPLEMENTORS_LIMIT = db.lookupIntConstant("instanceKlass::implementors_limit").intValue(); - implementors = new OopField[IMPLEMENTORS_LIMIT]; - for (int i = 0; i < IMPLEMENTORS_LIMIT; i++) { - long arrayOffset = Oop.getHeaderSize() + (i * db.getAddressSize()); - implementors[i] = new OopField(type.getOopField("_implementors[0]"), arrayOffset); - } fields = new OopField(type.getOopField("_fields"), Oop.getHeaderSize()); javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), Oop.getHeaderSize()); constants = new OopField(type.getOopField("_constants"), Oop.getHeaderSize()); @@ -136,8 +128,6 @@ private static OopField methodOrdering; private static OopField localInterfaces; private static OopField transitiveInterfaces; - private static CIntField nofImplementors; - private static OopField[] implementors; private static OopField fields; private static CIntField javaFieldsCount; private static OopField constants; @@ -317,9 +307,6 @@ public TypeArray getMethodOrdering() { return (TypeArray) methodOrdering.getValue(this); } public ObjArray getLocalInterfaces() { return (ObjArray) localInterfaces.getValue(this); } public ObjArray getTransitiveInterfaces() { return (ObjArray) transitiveInterfaces.getValue(this); } - public long nofImplementors() { return nofImplementors.getValue(this); } - public Klass getImplementor() { return (Klass) implementors[0].getValue(this); } - public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); } public TypeArray getFields() { return (TypeArray) fields.getValue(this); } public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); } public int getAllFieldsCount() { return (int)getFields().getLength() / FIELD_SLOTS; } @@ -527,9 +514,6 @@ visitor.doOop(methodOrdering, true); visitor.doOop(localInterfaces, true); visitor.doOop(transitiveInterfaces, true); - visitor.doCInt(nofImplementors, true); - for (int i = 0; i < IMPLEMENTORS_LIMIT; i++) - visitor.doOop(implementors[i], true); visitor.doOop(fields, true); visitor.doOop(constants, true); visitor.doOop(classLoader, true); diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/c1/c1_GraphBuilder.cpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Mar 29 22:18:56 2012 -0400 @@ -1694,7 +1694,9 @@ // they are roughly equivalent to Object. ciInstanceKlass* singleton = NULL; if (target->holder()->nof_implementors() == 1) { - singleton = target->holder()->implementor(0); + singleton = target->holder()->implementor(); + assert(singleton != NULL && singleton != target->holder(), + "just checking"); assert(holder->is_interface(), "invokeinterface to non interface?"); ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder; diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/ci/ciInstanceKlass.cpp --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. 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 @@ -59,10 +59,7 @@ _has_nonstatic_fields = ik->has_nonstatic_fields(); _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: - _nof_implementors = ik->nof_implementors(); - for (int i = 0; i < implementors_limit; i++) { - _implementors[i] = NULL; // we will fill these lazily - } + _implementor = NULL; // we will fill these lazily Thread *thread = Thread::current(); if (ciObjectFactory::is_initialized()) { @@ -102,7 +99,6 @@ _nonstatic_field_size = -1; _has_nonstatic_fields = false; _nonstatic_fields = NULL; - _nof_implementors = -1; _loader = loader; _protection_domain = protection_domain; _is_shared = false; @@ -133,17 +129,6 @@ } // ------------------------------------------------------------------ -// ciInstanceKlass::compute_shared_nof_implementors -int ciInstanceKlass::compute_shared_nof_implementors() { - // We requery this property, since it is a very old ciObject. - GUARDED_VM_ENTRY( - instanceKlass* ik = get_instanceKlass(); - _nof_implementors = ik->nof_implementors(); - return _nof_implementors; - ) -} - -// ------------------------------------------------------------------ // ciInstanceKlass::loader oop ciInstanceKlass::loader() { ASSERT_IN_VM; @@ -540,7 +525,7 @@ if (is_shared()) { return is_final(); // approximately correct } else { - return !_has_subklass && (_nof_implementors == 0); + return !_has_subklass && (nof_implementors() == 0); } } @@ -548,35 +533,31 @@ // ciInstanceKlass::implementor // // Report an implementor of this interface. -// Returns NULL if exact information is not available. // Note that there are various races here, since my copy // of _nof_implementors might be out of date with respect // to results returned by instanceKlass::implementor. // This is OK, since any dependencies we decide to assert // will be checked later under the Compile_lock. -ciInstanceKlass* ciInstanceKlass::implementor(int n) { - if (n >= implementors_limit) { - return NULL; - } - ciInstanceKlass* impl = _implementors[n]; +ciInstanceKlass* ciInstanceKlass::implementor() { + ciInstanceKlass* impl = _implementor; if (impl == NULL) { - if (_nof_implementors > implementors_limit) { - return NULL; - } // Go into the VM to fetch the implementor. { VM_ENTRY_MARK; - klassOop k = get_instanceKlass()->implementor(n); + klassOop k = get_instanceKlass()->implementor(); if (k != NULL) { - impl = CURRENT_THREAD_ENV->get_object(k)->as_instance_klass(); + if (k == get_instanceKlass()->as_klassOop()) { + // More than one implementors. Use 'this' in this case. + impl = this; + } else { + impl = CURRENT_THREAD_ENV->get_object(k)->as_instance_klass(); + } } } // Memoize this result. if (!is_shared()) { - _implementors[n] = (impl == NULL)? this: impl; + _implementor = impl; } - } else if (impl == this) { - impl = NULL; // memoized null result from a VM query } return impl; } diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/ci/ciInstanceKlass.hpp --- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. 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 @@ -65,9 +65,11 @@ ciConstantPoolCache* _field_cache; // cached map index->field GrowableArray* _nonstatic_fields; - enum { implementors_limit = instanceKlass::implementors_limit }; - ciInstanceKlass* _implementors[implementors_limit]; - jint _nof_implementors; + // The possible values of the _implementor fall into following three cases: + // NULL: no implementor. + // A ciInstanceKlass that's not itself: one implementor. + // Itsef: more than one implementors. + ciInstanceKlass* _implementor; GrowableArray* _non_static_fields; @@ -97,7 +99,6 @@ void compute_shared_init_state(); bool compute_shared_has_subklass(); - int compute_shared_nof_implementors(); int compute_nonstatic_fields(); GrowableArray* compute_nonstatic_fields_impl(GrowableArray* super_fields); @@ -158,10 +159,17 @@ assert(is_loaded(), "must be loaded"); return _nonstatic_oop_map_size; } ciInstanceKlass* super(); - jint nof_implementors() { + jint nof_implementors() { + ciInstanceKlass* impl; assert(is_loaded(), "must be loaded"); - if (_is_shared) return compute_shared_nof_implementors(); - return _nof_implementors; + impl = implementor(); + if (impl == NULL) { + return 0; + } else if (impl != this) { + return 1; + } else { + return 2; + } } ciInstanceKlass* get_canonical_holder(int offset); @@ -207,7 +215,7 @@ // but consider adding to vmSymbols.hpp instead. bool is_leaf_type(); - ciInstanceKlass* implementor(int n); + ciInstanceKlass* implementor(); // Is the defining class loader of this class the default loader? bool uses_default_loader(); diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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 @@ -3354,6 +3354,7 @@ klassOop ik = oopFactory::new_instanceKlass(name, vtable_size, itable_size, static_field_size, total_oop_map_count, + access_flags, rt, CHECK_(nullHandle)); instanceKlassHandle this_klass (THREAD, ik); @@ -3362,7 +3363,6 @@ "sanity"); // Fill in information already parsed - this_klass->set_access_flags(access_flags); this_klass->set_should_verify_class(verify); jint lh = Klass::instance_layout_helper(instance_size, false); this_klass->set_layout_helper(lh); diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/code/dependencies.cpp --- a/hotspot/src/share/vm/code/dependencies.cpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/code/dependencies.cpp Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. 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 @@ -1033,21 +1033,25 @@ // (Old CHA had the same limitation.) return context_type; } - for (int i = 0; i < nof_impls; i++) { - klassOop impl = instanceKlass::cast(context_type)->implementor(i); - if (impl == NULL) { - // implementors array overflowed => no exact info. + if (nof_impls > 0) { + klassOop impl = instanceKlass::cast(context_type)->implementor(); + assert(impl != NULL, "just checking"); + // If impl is the same as the context_type, then more than one + // implementor has seen. No exact info in this case. + if (impl == context_type) { return context_type; // report an inexact witness to this sad affair } if (do_counts) { NOT_PRODUCT(deps_find_witness_steps++); } if (is_participant(impl)) { - if (participants_hide_witnesses) continue; - // else fall through to process this guy's subclasses + if (!participants_hide_witnesses) { + ADD_SUBCLASS_CHAIN(impl); + } } else if (is_witness(impl) && !ignore_witness(impl)) { return impl; + } else { + ADD_SUBCLASS_CHAIN(impl); } - ADD_SUBCLASS_CHAIN(impl); } // Recursively process each non-trivial sibling chain. @@ -1174,8 +1178,9 @@ } else if (ctx->nof_implementors() != 0) { // if it is an interface, it must be unimplemented // (if it is not an interface, nof_implementors is always zero) - klassOop impl = ctx->implementor(0); - return (impl != NULL)? impl: ctxk; + klassOop impl = ctx->implementor(); + assert(impl != NULL, "must be set"); + return impl; } else { return NULL; } diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/memory/oopFactory.cpp --- a/hotspot/src/share/vm/memory/oopFactory.cpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/memory/oopFactory.cpp Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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 @@ -127,9 +127,12 @@ klassOop oopFactory::new_instanceKlass(Symbol* name, int vtable_len, int itable_len, int static_field_size, unsigned int nonstatic_oop_map_count, + AccessFlags access_flags, ReferenceType rt, TRAPS) { instanceKlassKlass* ikk = instanceKlassKlass::cast(Universe::instanceKlassKlassObj()); - return ikk->allocate_instance_klass(name, vtable_len, itable_len, static_field_size, nonstatic_oop_map_count, rt, CHECK_NULL); + return ikk->allocate_instance_klass(name, vtable_len, itable_len, + static_field_size, nonstatic_oop_map_count, + access_flags, rt, CHECK_NULL); } diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/memory/oopFactory.hpp --- a/hotspot/src/share/vm/memory/oopFactory.hpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/memory/oopFactory.hpp Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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 @@ -77,6 +77,7 @@ int vtable_len, int itable_len, int static_field_size, unsigned int nonstatic_oop_map_count, + AccessFlags access_flags, ReferenceType rt, TRAPS); // Methods diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Mar 29 22:18:56 2012 -0400 @@ -567,8 +567,18 @@ ol.notify_all(CHECK); } +// The embedded _implementor field can only record one implementor. +// When there are more than one implementors, the _implementor field +// is set to the interface klassOop itself. Following are the possible +// values for the _implementor field: +// NULL - no implementor +// implementor klassOop - one implementor +// self - more than one implementor +// +// The _implementor field only exists for interfaces. void instanceKlass::add_implementor(klassOop k) { assert(Compile_lock->owned_by_self(), ""); + assert(is_interface(), "not interface"); // Filter out my subinterfaces. // (Note: Interfaces are never on the subklass list.) if (instanceKlass::cast(k)->is_interface()) return; @@ -583,17 +593,13 @@ // Any supers of the super have the same (or fewer) transitive_interfaces. return; - // Update number of implementors - int i = _nof_implementors++; - - // Record this implementor, if there are not too many already - if (i < implementors_limit) { - assert(_implementors[i] == NULL, "should be exactly one implementor"); - oop_store_without_check((oop*)&_implementors[i], k); - } else if (i == implementors_limit) { - // clear out the list on first overflow - for (int i2 = 0; i2 < implementors_limit; i2++) - oop_store_without_check((oop*)&_implementors[i2], NULL); + klassOop ik = implementor(); + if (ik == NULL) { + set_implementor(k); + } else if (ik != this->as_klassOop()) { + // There is already an implementor. Use itself as an indicator of + // more than one implementors. + set_implementor(this->as_klassOop()); } // The implementor also implements the transitive_interfaces @@ -603,9 +609,9 @@ } void instanceKlass::init_implementor() { - for (int i = 0; i < implementors_limit; i++) - oop_store_without_check((oop*)&_implementors[i], NULL); - _nof_implementors = 0; + if (is_interface()) { + set_implementor(NULL); + } } @@ -1849,24 +1855,22 @@ void instanceKlass::follow_weak_klass_links( BoolObjectClosure* is_alive, OopClosure* keep_alive) { assert(is_alive->do_object_b(as_klassOop()), "this oop should be live"); - if (ClassUnloading) { - for (int i = 0; i < implementors_limit; i++) { - klassOop impl = _implementors[i]; - if (impl == NULL) break; // no more in the list - if (!is_alive->do_object_b(impl)) { - // remove this guy from the list by overwriting him with the tail - int lasti = --_nof_implementors; - assert(lasti >= i && lasti < implementors_limit, "just checking"); - _implementors[i] = _implementors[lasti]; - _implementors[lasti] = NULL; - --i; // rerun the loop at this index + + if (is_interface()) { + if (ClassUnloading) { + klassOop impl = implementor(); + if (impl != NULL) { + if (!is_alive->do_object_b(impl)) { + // remove this guy + *start_of_implementor() = NULL; + } } - } - } else { - for (int i = 0; i < implementors_limit; i++) { - keep_alive->do_oop(&adr_implementors()[i]); + } else { + assert(adr_implementor() != NULL, "just checking"); + keep_alive->do_oop(adr_implementor()); } } + Klass::follow_weak_klass_links(is_alive, keep_alive); } diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/oops/instanceKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlass.hpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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 @@ -56,8 +56,6 @@ // [methods ] // [local interfaces ] // [transitive interfaces ] -// [number of implementors ] -// [implementors ] klassOop[2] // [fields ] // [constants ] // [class loader ] @@ -77,9 +75,9 @@ // [oop map cache (stack maps) ] // [EMBEDDED Java vtable ] size in words = vtable_len // [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size -// -// The embedded nonstatic oop-map blocks are short pairs (offset, length) indicating -// where oops are located in instances of this klass. +// The embedded nonstatic oop-map blocks are short pairs (offset, length) +// indicating where oops are located in instances of this klass. +// [EMBEDDED implementor of the interface] only exist for interface // forward declaration for class -- see below for definition @@ -153,10 +151,6 @@ oop* oop_block_beg() const { return adr_array_klasses(); } oop* oop_block_end() const { return adr_methods_default_annotations() + 1; } - enum { - implementors_limit = 2 // how many implems can we track? - }; - protected: // // The oop block. See comment in klass.hpp before making changes. @@ -200,8 +194,6 @@ // and EnclosingMethod attributes the _inner_classes array length is // number_of_inner_classes * 4 + enclosing_method_attribute_size. typeArrayOop _inner_classes; - // Implementors of this interface (not valid if it overflows) - klassOop _implementors[implementors_limit]; // Annotations for this class, or null if none. typeArrayOop _class_annotations; // Annotation objects (byte arrays) for fields, or null if no annotations. @@ -257,7 +249,6 @@ nmethodBucket* _dependencies; // list of dependent nmethods nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class BreakpointInfo* _breakpoints; // bpt lists, managed by methodOop - int _nof_implementors; // No of implementors of this interface (zero if not an interface) // Array of interesting part(s) of the previous version(s) of this // instanceKlass. See PreviousVersionWalker below. GrowableArray* _previous_versions; @@ -278,6 +269,13 @@ // embedded Java itables follows here // embedded static fields follows here // embedded nonstatic oop-map blocks follows here + // embedded implementor of this interface follows here + // The embedded implementor only exists if the current klass is an + // iterface. The possible values of the implementor fall into following + // three cases: + // NULL: no implementor. + // A klassOop that's not itself: one implementor. + // Itsef: more than one implementors. friend class instanceKlassKlass; friend class SystemDictionary; @@ -649,14 +647,34 @@ // subclass/subinterface checks bool implements_interface(klassOop k) const; - // Access to implementors of an interface. We only store the count - // of implementors, and in case, there are only a few - // implementors, we store them in a short list. - // This accessor returns NULL if we walk off the end of the list. - klassOop implementor(int i) const { - return (i < implementors_limit)? _implementors[i]: (klassOop) NULL; + // Access to the implementor of an interface. + klassOop implementor() const + { + klassOop* k = start_of_implementor(); + if (k == NULL) { + return NULL; + } else { + return *k; + } } - int nof_implementors() const { return _nof_implementors; } + + void set_implementor(klassOop k) { + assert(is_interface(), "not interface"); + oop* addr = (oop*)start_of_implementor(); + oop_store_without_check(addr, k); + } + + int nof_implementors() const { + klassOop k = implementor(); + if (k == NULL) { + return 0; + } else if (k != this->as_klassOop()) { + return 1; + } else { + return 2; + } + } + void add_implementor(klassOop k); // k is a new class that implements this interface void init_implementor(); // initialize @@ -693,7 +711,15 @@ // Sizing (in words) static int header_size() { return align_object_offset(oopDesc::header_size() + sizeof(instanceKlass)/HeapWordSize); } - int object_size() const { return object_size(align_object_offset(vtable_length()) + align_object_offset(itable_length()) + nonstatic_oop_map_size()); } + + int object_size() const + { + return object_size(align_object_offset(vtable_length()) + + align_object_offset(itable_length()) + + (is_interface() ? + (align_object_offset(nonstatic_oop_map_size()) + (int)sizeof(klassOop)/HeapWordSize) : + nonstatic_oop_map_size())); + } static int vtable_start_offset() { return header_size(); } static int vtable_length_offset() { return oopDesc::header_size() + offset_of(instanceKlass, _vtable_len) / HeapWordSize; } static int object_size(int extra) { return align_object_size(header_size() + extra); } @@ -710,6 +736,15 @@ return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length())); } + klassOop* start_of_implementor() const { + if (is_interface()) { + return (klassOop*)(start_of_nonstatic_oop_maps() + + nonstatic_oop_map_count()); + } else { + return NULL; + } + }; + // Allocation profiling support juint alloc_size() const { return _alloc_count * size_helper(); } void set_alloc_size(juint n) {} @@ -819,7 +854,7 @@ oop* adr_host_klass() const { return (oop*)&this->_host_klass;} oop* adr_signers() const { return (oop*)&this->_signers;} oop* adr_inner_classes() const { return (oop*)&this->_inner_classes;} - oop* adr_implementors() const { return (oop*)&this->_implementors[0];} + oop* adr_implementor() const { return (oop*)start_of_implementor(); } oop* adr_methods_jmethod_ids() const { return (oop*)&this->_methods_jmethod_ids;} oop* adr_methods_cached_itable_indices() const { return (oop*)&this->_methods_cached_itable_indices;} oop* adr_class_annotations() const { return (oop*)&this->_class_annotations;} diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/oops/instanceKlassKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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 @@ -111,7 +111,7 @@ MarkSweep::mark_and_push(ik->adr_methods_parameter_annotations()); MarkSweep::mark_and_push(ik->adr_methods_default_annotations()); - // We do not follow adr_implementors() here. It is followed later + // We do not follow adr_implementor() here. It is followed later // in instanceKlass::follow_weak_klass_links() klassKlass::oop_follow_contents(obj); @@ -180,8 +180,8 @@ blk->do_oop(ik->adr_host_klass()); blk->do_oop(ik->adr_signers()); blk->do_oop(ik->adr_inner_classes()); - for (int i = 0; i < instanceKlass::implementors_limit; i++) { - blk->do_oop(&ik->adr_implementors()[i]); + if (ik->is_interface()) { + blk->do_oop(ik->adr_implementor()); } blk->do_oop(ik->adr_class_annotations()); blk->do_oop(ik->adr_fields_annotations()); @@ -232,9 +232,9 @@ if (mr.contains(adr)) blk->do_oop(adr); adr = ik->adr_inner_classes(); if (mr.contains(adr)) blk->do_oop(adr); - adr = ik->adr_implementors(); - for (int i = 0; i < instanceKlass::implementors_limit; i++) { - if (mr.contains(&adr[i])) blk->do_oop(&adr[i]); + if (ik->is_interface()) { + adr = ik->adr_implementor(); + if (mr.contains(adr)) blk->do_oop(adr); } adr = ik->adr_class_annotations(); if (mr.contains(adr)) blk->do_oop(adr); @@ -273,8 +273,8 @@ MarkSweep::adjust_pointer(ik->adr_host_klass()); MarkSweep::adjust_pointer(ik->adr_signers()); MarkSweep::adjust_pointer(ik->adr_inner_classes()); - for (int i = 0; i < instanceKlass::implementors_limit; i++) { - MarkSweep::adjust_pointer(&ik->adr_implementors()[i]); + if (ik->is_interface()) { + MarkSweep::adjust_pointer(ik->adr_implementor()); } MarkSweep::adjust_pointer(ik->adr_class_annotations()); MarkSweep::adjust_pointer(ik->adr_fields_annotations()); @@ -328,6 +328,9 @@ for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { PSParallelCompact::adjust_pointer(cur_oop); } + if (ik->is_interface()) { + PSParallelCompact::adjust_pointer(ik->adr_implementor()); + } OopClosure* closure = PSParallelCompact::adjust_root_pointer_closure(); iterate_c_heap_oops(ik, closure); @@ -342,11 +345,18 @@ instanceKlassKlass::allocate_instance_klass(Symbol* name, int vtable_len, int itable_len, int static_field_size, unsigned nonstatic_oop_map_count, + AccessFlags access_flags, ReferenceType rt, TRAPS) { const int nonstatic_oop_map_size = instanceKlass::nonstatic_oop_map_size(nonstatic_oop_map_count); - int size = instanceKlass::object_size(align_object_offset(vtable_len) + align_object_offset(itable_len) + nonstatic_oop_map_size); + int size = align_object_offset(vtable_len) + align_object_offset(itable_len); + if (access_flags.is_interface()) { + size += align_object_offset(nonstatic_oop_map_size) + (int)sizeof(klassOop)/HeapWordSize; + } else { + size += nonstatic_oop_map_size; + } + size = instanceKlass::object_size(size); // Allocation KlassHandle h_this_klass(THREAD, as_klassOop()); @@ -378,6 +388,7 @@ ik->set_itable_length(itable_len); ik->set_static_field_size(static_field_size); ik->set_nonstatic_oop_map_size(nonstatic_oop_map_size); + ik->set_access_flags(access_flags); assert(k()->size() == size, "wrong size for object"); ik->set_array_klasses(NULL); @@ -470,16 +481,12 @@ if (ik->is_interface()) { st->print_cr(BULLET"nof implementors: %d", ik->nof_implementors()); - int print_impl = 0; - for (int i = 0; i < instanceKlass::implementors_limit; i++) { - if (ik->implementor(i) != NULL) { - if (++print_impl == 1) - st->print_cr(BULLET"implementor: "); - st->print(" "); - ik->implementor(i)->print_value_on(st); - } + if (ik->nof_implementors() == 1) { + st->print_cr(BULLET"implementor: "); + st->print(" "); + ik->implementor()->print_value_on(st); + st->cr(); } - if (print_impl > 0) st->cr(); } st->print(BULLET"arrays: "); ik->array_klasses()->print_value_on(st); st->cr(); @@ -640,16 +647,12 @@ } // Verify implementor fields - bool saw_null_impl = false; - for (int i = 0; i < instanceKlass::implementors_limit; i++) { - klassOop im = ik->implementor(i); - if (im == NULL) { saw_null_impl = true; continue; } - guarantee(!saw_null_impl, "non-nulls must preceded all nulls"); + klassOop im = ik->implementor(); + if (im != NULL) { guarantee(ik->is_interface(), "only interfaces should have implementor set"); - guarantee(i < ik->nof_implementors(), "should only have one implementor"); guarantee(im->is_perm(), "should be in permspace"); guarantee(im->is_klass(), "should be klass"); - guarantee(!Klass::cast(klassOop(im))->is_interface(), "implementors cannot be interfaces"); + guarantee(!Klass::cast(klassOop(im))->is_interface() || im == ik->as_klassOop(), "implementors cannot be interfaces"); } // Verify local interfaces diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/oops/instanceKlassKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlassKlass.hpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/oops/instanceKlassKlass.hpp Thu Mar 29 22:18:56 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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 @@ -46,6 +46,7 @@ int itable_len, int static_field_size, unsigned int nonstatic_oop_map_count, + AccessFlags access_flags, ReferenceType rt, TRAPS); diff -r f3187578ddd3 -r 48fd3da4025c hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Sun Mar 25 18:08:52 2012 -0400 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Mar 29 22:18:56 2012 -0400 @@ -292,8 +292,6 @@ nonstatic_field(instanceKlass, _method_ordering, typeArrayOop) \ nonstatic_field(instanceKlass, _local_interfaces, objArrayOop) \ nonstatic_field(instanceKlass, _transitive_interfaces, objArrayOop) \ - nonstatic_field(instanceKlass, _nof_implementors, int) \ - nonstatic_field(instanceKlass, _implementors[0], klassOop) \ nonstatic_field(instanceKlass, _fields, typeArrayOop) \ nonstatic_field(instanceKlass, _java_fields_count, u2) \ nonstatic_field(instanceKlass, _constants, constantPoolOop) \ @@ -2343,7 +2341,6 @@ /* instanceKlass enum */ \ /*************************************/ \ \ - declare_constant(instanceKlass::implementors_limit) \ \ /*************************************/ \ /* FieldInfo FieldOffset enum */ \