diff --git a/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java b/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java index 4cbc1447ea9b9789e51c78525e6f409be8355f5b..a7d7d4ee76872761645502abb0b765a4a0593ee8 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java +++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java @@ -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 @@ public class VirtualMachineImpl extends MirrorImpl implements PathSearchingVirtu 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 --git a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index d75d890485c2bf77c8a41f2ffd0844727c66583c..f342eb72882ae706c906aaf5cb553b7fe2711ed4 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -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 @@ public class InstanceKlass extends Klass { 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 @@ public class InstanceKlass extends Klass { 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 @@ public class InstanceKlass extends Klass { 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 class InstanceKlass extends Klass { 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 @@ public class InstanceKlass extends Klass { 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 --git a/src/share/vm/c1/c1_GraphBuilder.cpp b/src/share/vm/c1/c1_GraphBuilder.cpp index b4659d97261583eb47f695d867eb4e1eea408ae4..34fdb591c2e670ed46bbb17f255dc0a4416b7841 100644 --- a/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/src/share/vm/c1/c1_GraphBuilder.cpp @@ -1694,7 +1694,9 @@ void GraphBuilder::invoke(Bytecodes::Code code) { // 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 --git a/src/share/vm/ci/ciInstanceKlass.cpp b/src/share/vm/ci/ciInstanceKlass.cpp index b7c2ab758506ccd18dab2ec4d9a86ba74588e071..be730a00ce925f3e86cfdba12c1d62929d3a7596 100644 --- a/src/share/vm/ci/ciInstanceKlass.cpp +++ b/src/share/vm/ci/ciInstanceKlass.cpp @@ -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 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : _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 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name, _nonstatic_field_size = -1; _has_nonstatic_fields = false; _nonstatic_fields = NULL; - _nof_implementors = -1; _loader = loader; _protection_domain = protection_domain; _is_shared = false; @@ -132,17 +128,6 @@ bool ciInstanceKlass::compute_shared_has_subklass() { ) } -// ------------------------------------------------------------------ -// 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() { @@ -540,7 +525,7 @@ bool ciInstanceKlass::is_leaf_type() { 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 @@ bool ciInstanceKlass::is_leaf_type() { // 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 --git a/src/share/vm/ci/ciInstanceKlass.hpp b/src/share/vm/ci/ciInstanceKlass.hpp index 05ecf87a1e2cdc525c4af6d278b63d89f135ec1e..f8d0a7bd9ebf4d87b5dcfb8e0c2fc8ed49a8abd3 100644 --- a/src/share/vm/ci/ciInstanceKlass.hpp +++ b/src/share/vm/ci/ciInstanceKlass.hpp @@ -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 @@ private: 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 @@ protected: 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 @@ public: 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 @@ public: // 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 --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp index 7ace834a086e1d3bdf7f892d682f5a303c5e4b37..218f2c986bb749c32c70cf8971c3d344060312bb 100644 --- a/src/share/vm/classfile/classFileParser.cpp +++ b/src/share/vm/classfile/classFileParser.cpp @@ -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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, 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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, "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 --git a/src/share/vm/code/dependencies.cpp b/src/share/vm/code/dependencies.cpp index a3fd99ecd45836080e53a9e74deb3a6bcc83774c..3d6705680bfc311aa68d66b689e7fc075b5bde8c 100644 --- a/src/share/vm/code/dependencies.cpp +++ b/src/share/vm/code/dependencies.cpp @@ -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 @@ klassOop ClassHierarchyWalker::find_witness_anywhere(klassOop context_type, // (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 @@ klassOop Dependencies::check_leaf_type(klassOop ctxk) { } 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 --git a/src/share/vm/memory/oopFactory.cpp b/src/share/vm/memory/oopFactory.cpp index c6e644c96d41e1642a028c92dc6c568a4e616de3..fcac438bbe34db222fcea0f4492f410811e30f8a 100644 --- a/src/share/vm/memory/oopFactory.cpp +++ b/src/share/vm/memory/oopFactory.cpp @@ -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 @@ constantPoolCacheOop oopFactory::new_constantPoolCache(int length, 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 --git a/src/share/vm/memory/oopFactory.hpp b/src/share/vm/memory/oopFactory.hpp index dbb42f05332831017b9a9d717eabf7df44d14727..61faf8e3db796d43136642eb7381eea3408a523a 100644 --- a/src/share/vm/memory/oopFactory.hpp +++ b/src/share/vm/memory/oopFactory.hpp @@ -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 @@ class oopFactory: AllStatic { int vtable_len, int itable_len, int static_field_size, unsigned int nonstatic_oop_map_count, + AccessFlags access_flags, ReferenceType rt, TRAPS); // Methods diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp index 81edd80946f6b4f5a938e7727e96419260d019fe..aa5f7765a79173c3bffcc4d7dde59b43a149c1f6 100644 --- a/src/share/vm/oops/instanceKlass.cpp +++ b/src/share/vm/oops/instanceKlass.cpp @@ -567,8 +567,18 @@ void instanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle 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 @@ void instanceKlass::add_implementor(klassOop k) { // 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::add_implementor(klassOop k) { } 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 @@ int instanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { 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 --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp index 9cbfa0fbfb6dc3ea2aa7fa2b3a10cb39bdc05f28..32a00f5c6b02cd12dd5817d84500a17f7ec05235 100644 --- a/src/share/vm/oops/instanceKlass.hpp +++ b/src/share/vm/oops/instanceKlass.hpp @@ -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 @@ class instanceKlass: public Klass { 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 @@ class instanceKlass: public Klass { // 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 @@ class instanceKlass: public Klass { 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 @@ class instanceKlass: public Klass { // 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 @@ class instanceKlass: public Klass { // 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; + } + } + + 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; + } } - int nof_implementors() const { return _nof_implementors; } + void add_implementor(klassOop k); // k is a new class that implements this interface void init_implementor(); // initialize @@ -693,7 +711,15 @@ class instanceKlass: public Klass { // 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 @@ class instanceKlass: public Klass { 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 @@ private: 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 --git a/src/share/vm/oops/instanceKlassKlass.cpp b/src/share/vm/oops/instanceKlassKlass.cpp index 2ceef2a9107c2c7e6f9df88a29a5d4f22344d8b3..808b6e569992ca353b85100306f93b6fd1d2e144 100644 --- a/src/share/vm/oops/instanceKlassKlass.cpp +++ b/src/share/vm/oops/instanceKlassKlass.cpp @@ -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 @@ void instanceKlassKlass::oop_follow_contents(oop obj) { 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 @@ int instanceKlassKlass::oop_oop_iterate(oop obj, OopClosure* blk) { 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 @@ int instanceKlassKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, 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 @@ int instanceKlassKlass::oop_adjust_pointers(oop obj) { 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 @@ int instanceKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { 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 @@ klassOop 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 @@ instanceKlassKlass::allocate_instance_klass(Symbol* name, int vtable_len, int it 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 @@ void instanceKlassKlass::oop_print_on(oop obj, outputStream* st) { 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 @@ void instanceKlassKlass::oop_verify_on(oop obj, outputStream* st) { } // 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 --git a/src/share/vm/oops/instanceKlassKlass.hpp b/src/share/vm/oops/instanceKlassKlass.hpp index 9cbabe24644d7c9a6757fab558af754a5504d676..ced9451da58f893afdd26e980263ff3beaaaff74 100644 --- a/src/share/vm/oops/instanceKlassKlass.hpp +++ b/src/share/vm/oops/instanceKlassKlass.hpp @@ -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 @@ class instanceKlassKlass : public klassKlass { int itable_len, int static_field_size, unsigned int nonstatic_oop_map_count, + AccessFlags access_flags, ReferenceType rt, TRAPS); diff --git a/src/share/vm/runtime/vmStructs.cpp b/src/share/vm/runtime/vmStructs.cpp index 924cde1540456a4fddaf75407e4abbb1ad7ba352..25d3b5b4179627dd7cbb6e570520d6aa68953b07 100644 --- a/src/share/vm/runtime/vmStructs.cpp +++ b/src/share/vm/runtime/vmStructs.cpp @@ -292,8 +292,6 @@ static inline uint64_t cast_uint64_t(size_t x) 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 @@ static inline uint64_t cast_uint64_t(size_t x) /* instanceKlass enum */ \ /*************************************/ \ \ - declare_constant(instanceKlass::implementors_limit) \ \ /*************************************/ \ /* FieldInfo FieldOffset enum */ \