duke@435: /* acorn@4497: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_OOPS_INSTANCEKLASS_HPP stefank@2314: #define SHARE_VM_OOPS_INSTANCEKLASS_HPP stefank@2314: coleenp@4037: #include "classfile/classLoaderData.hpp" coleenp@4037: #include "oops/annotations.hpp" coleenp@4037: #include "oops/constMethod.hpp" never@3137: #include "oops/fieldInfo.hpp" stefank@2314: #include "oops/instanceOop.hpp" stefank@2314: #include "oops/klassVtable.hpp" zgu@4400: #include "runtime/atomic.hpp" stefank@2314: #include "runtime/handles.hpp" stefank@2314: #include "runtime/os.hpp" stefank@2314: #include "utilities/accessFlags.hpp" stefank@2314: #include "utilities/bitMap.inline.hpp" jprovino@4542: #include "utilities/macros.hpp" stefank@2314: coleenp@4037: // An InstanceKlass is the VM level representation of a Java class. duke@435: // It contains all information needed for at class at execution runtime. duke@435: coleenp@4037: // InstanceKlass layout: duke@435: // [C++ vtbl pointer ] Klass duke@435: // [subtype cache ] Klass duke@435: // [instance size ] Klass duke@435: // [java mirror ] Klass duke@435: // [super ] Klass duke@435: // [access_flags ] Klass duke@435: // [name ] Klass duke@435: // [first subklass ] Klass duke@435: // [next sibling ] Klass duke@435: // [array klasses ] duke@435: // [methods ] duke@435: // [local interfaces ] duke@435: // [transitive interfaces ] duke@435: // [fields ] duke@435: // [constants ] duke@435: // [class loader ] duke@435: // [protection domain ] duke@435: // [signers ] duke@435: // [source file name ] duke@435: // [inner classes ] duke@435: // [static field size ] duke@435: // [nonstatic field size ] duke@435: // [static oop fields size ] duke@435: // [nonstatic oop maps size ] duke@435: // [has finalize method ] duke@435: // [deoptimization mark bit ] duke@435: // [initialization state ] duke@435: // [initializing thread ] duke@435: // [Java vtable length ] duke@435: // [oop map cache (stack maps) ] duke@435: // [EMBEDDED Java vtable ] size in words = vtable_len duke@435: // [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size jiangli@3701: // The embedded nonstatic oop-map blocks are short pairs (offset, length) jiangli@3701: // indicating where oops are located in instances of this klass. jiangli@3701: // [EMBEDDED implementor of the interface] only exist for interface jiangli@3741: // [EMBEDDED host klass ] only exist for an anonymous class (JSR 292 enabled) duke@435: duke@435: duke@435: // forward declaration for class -- see below for definition duke@435: class SuperTypeClosure; duke@435: class JNIid; duke@435: class jniIdMapBase; duke@435: class BreakpointInfo; duke@435: class fieldDescriptor; duke@435: class DepChange; duke@435: class nmethodBucket; duke@435: class PreviousVersionNode; duke@435: class JvmtiCachedClassFieldMap; duke@435: duke@435: // This is used in iterators below. duke@435: class FieldClosure: public StackObj { duke@435: public: duke@435: virtual void do_field(fieldDescriptor* fd) = 0; duke@435: }; duke@435: duke@435: #ifndef PRODUCT duke@435: // Print fields. duke@435: // If "obj" argument to constructor is NULL, prints static fields, otherwise prints non-static fields. duke@435: class FieldPrinter: public FieldClosure { duke@435: oop _obj; duke@435: outputStream* _st; duke@435: public: duke@435: FieldPrinter(outputStream* st, oop obj = NULL) : _obj(obj), _st(st) {} duke@435: void do_field(fieldDescriptor* fd); duke@435: }; duke@435: #endif // !PRODUCT duke@435: jcoomes@1373: // ValueObjs embedded in klass. Describes where oops are located in instances of jcoomes@1373: // this klass. jcoomes@1373: class OopMapBlock VALUE_OBJ_CLASS_SPEC { jcoomes@1373: public: jcoomes@1373: // Byte offset of the first oop mapped by this block. jcoomes@1374: int offset() const { return _offset; } jcoomes@1374: void set_offset(int offset) { _offset = offset; } jcoomes@1373: jcoomes@1373: // Number of oops in this block. jcoomes@1374: uint count() const { return _count; } jcoomes@1374: void set_count(uint count) { _count = count; } jcoomes@1373: jcoomes@1373: // sizeof(OopMapBlock) in HeapWords. jcoomes@1373: static const int size_in_words() { jcoomes@1373: return align_size_up(int(sizeof(OopMapBlock)), HeapWordSize) >> jcoomes@1373: LogHeapWordSize; jcoomes@1373: } jcoomes@1373: jcoomes@1373: private: jcoomes@1374: int _offset; jcoomes@1374: uint _count; jcoomes@1373: }; jcoomes@1373: coleenp@4037: class InstanceKlass: public Klass { duke@435: friend class VMStructs; coleenp@4037: friend class ClassFileParser; minqi@4267: friend class CompileReplay; coleenp@4037: coleenp@4037: protected: coleenp@4037: // Constructor coleenp@4037: InstanceKlass(int vtable_len, coleenp@4037: int itable_len, coleenp@4037: int static_field_size, coleenp@4037: int nonstatic_oop_map_size, coleenp@4037: ReferenceType rt, coleenp@4037: AccessFlags access_flags, coleenp@4037: bool is_anonymous); duke@435: public: coleenp@4037: static Klass* allocate_instance_klass(ClassLoaderData* loader_data, coleenp@4037: int vtable_len, coleenp@4037: int itable_len, coleenp@4037: int static_field_size, coleenp@4037: int nonstatic_oop_map_size, coleenp@4037: ReferenceType rt, coleenp@4037: AccessFlags access_flags, coleenp@4037: Symbol* name, coleenp@4572: Klass* super_klass, coleenp@4572: bool is_anonymous, coleenp@4037: TRAPS); coleenp@4037: coleenp@4037: InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); } coleenp@4037: duke@435: // See "The Java Virtual Machine Specification" section 2.16.2-5 for a detailed description duke@435: // of the class loading & initialization procedure, and the use of the states. duke@435: enum ClassState { duke@435: allocated, // allocated (but not yet linked) duke@435: loaded, // loaded and inserted in class hierarchy (but not linked yet) duke@435: linked, // successfully linked/verified (but not initialized yet) duke@435: being_initialized, // currently running class initializer duke@435: fully_initialized, // initialized (successfull final state) duke@435: initialization_error // error happened during initialization duke@435: }; duke@435: zgu@4400: static int number_of_instance_classes() { return _total_instanceKlass_count; } zgu@4400: zgu@4400: private: zgu@4400: static volatile int _total_instanceKlass_count; zgu@4400: duke@435: protected: duke@435: // Protection domain. duke@435: oop _protection_domain; duke@435: // Class signers. duke@435: objArrayOop _signers; coleenp@4037: // Initialization lock. Must be one per class and it has to be a VM internal coleenp@4037: // object so java code cannot lock it (like the mirror) coleenp@4037: // It has to be an object not a Mutex because it's held through java calls. coleenp@4037: volatile oop _init_lock; coleenp@4037: coleenp@4037: // Annotations for this class coleenp@4037: Annotations* _annotations; coleenp@4037: // Array classes holding elements of this class. coleenp@4037: Klass* _array_klasses; coleenp@4037: // Constant pool for this class. coleenp@4037: ConstantPool* _constants; jiangli@3670: // The InnerClasses attribute and EnclosingMethod attribute. The jiangli@3670: // _inner_classes is an array of shorts. If the class has InnerClasses jiangli@3670: // attribute, then the _inner_classes array begins with 4-tuples of shorts jiangli@3670: // [inner_class_info_index, outer_class_info_index, jiangli@3670: // inner_name_index, inner_class_access_flags] for the InnerClasses jiangli@3670: // attribute. If the EnclosingMethod attribute exists, it occupies the jiangli@3670: // last two shorts [class_index, method_index] of the array. If only jiangli@3670: // the InnerClasses attribute exists, the _inner_classes array length is jiangli@3670: // number_of_inner_classes * 4. If the class has both InnerClasses jiangli@3670: // and EnclosingMethod attributes the _inner_classes array length is jiangli@3670: // number_of_inner_classes * 4 + enclosing_method_attribute_size. coleenp@4037: Array* _inner_classes; duke@435: coleenp@2497: // Name of source file containing this klass, NULL if not specified. coleenp@2497: Symbol* _source_file_name; coleenp@2497: // the source debug extension for this klass, NULL if not specified. fparain@3906: // Specified as UTF-8 string without terminating zero byte in the classfile, fparain@3906: // it is stored in the instanceklass as a NULL-terminated UTF-8 string fparain@3906: char* _source_debug_extension; coleenp@2497: // Generic signature, or null if none. coleenp@2497: Symbol* _generic_signature; coleenp@2497: // Array name derived from this class which needs unreferencing coleenp@2497: // if this class is unloaded. coleenp@2497: Symbol* _array_name; coleenp@2497: kvn@600: // Number of heapOopSize words used by non-static fields in this klass kvn@600: // (including inherited fields but after header_size()). coleenp@548: int _nonstatic_field_size; coleenp@548: int _static_field_size; // number words used by static fields (oop and non-oop) in this klass jiangli@3373: u2 _static_oop_field_count;// number of static oop fields in this klass jiangli@3373: u2 _java_fields_count; // The number of declared Java fields jcoomes@1373: int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks coleenp@3366: jiangli@4436: // _is_marked_dependent can be set concurrently, thus cannot be part of the jiangli@4436: // _misc_flags. dcubed@3401: bool _is_marked_dependent; // used for marking during flushing and deoptimization jiangli@4436: jiangli@3741: enum { jiangli@3741: _misc_rewritten = 1 << 0, // methods rewritten. jiangli@3741: _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops jiangli@3741: _misc_should_verify_class = 1 << 2, // allow caching of preverification jwilhelm@4430: _misc_is_anonymous = 1 << 3, // has embedded _inner_classes field dlong@4439: _misc_is_contended = 1 << 4, // marked with contended annotation dlong@4439: _misc_has_default_methods = 1 << 5 // class/superclass/implemented interfaces has default methods jiangli@3741: }; jiangli@3741: u2 _misc_flags; duke@435: u2 _minor_version; // minor version number of class file duke@435: u2 _major_version; // major version number of class file duke@435: Thread* _init_thread; // Pointer to current thread doing initialization (to handle recusive initialization) duke@435: int _vtable_len; // length of Java vtable (in words) duke@435: int _itable_len; // length of Java itable (in words) duke@435: OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily) duke@435: JNIid* _jni_ids; // First JNI identifier for static fields in this class duke@435: jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none duke@435: int* _methods_cached_itable_indices; // itable_index cache for JNI invoke corresponding to methods idnum, or NULL duke@435: nmethodBucket* _dependencies; // list of dependent nmethods duke@435: nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class coleenp@4037: BreakpointInfo* _breakpoints; // bpt lists, managed by Method* duke@435: // Array of interesting part(s) of the previous version(s) of this coleenp@4037: // InstanceKlass. See PreviousVersionWalker below. duke@435: GrowableArray* _previous_versions; duke@435: // JVMTI fields can be moved to their own structure - see 6315920 duke@435: unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH duke@435: jint _cached_class_file_len; // JVMTI: length of above iklam@4509: iklam@4509: volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change iklam@4509: iklam@4509: // Class states are defined as ClassState (see above). iklam@4509: // Place the _init_state here to utilize the unused 2-byte after iklam@4509: // _idnum_allocated_count. iklam@4509: u1 _init_state; // state of class iklam@4509: u1 _reference_type; // reference type iklam@4509: iklam@4509: duke@435: JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration kamg@4245: coleenp@4712: NOT_PRODUCT(int _verify_count;) // to avoid redundant verifies coleenp@4712: coleenp@4037: // Method array. coleenp@4037: Array* _methods; coleenp@4037: // Interface (Klass*s) this class declares locally to implement. coleenp@4037: Array* _local_interfaces; coleenp@4037: // Interface (Klass*s) this class implements transitively. coleenp@4037: Array* _transitive_interfaces; coleenp@4037: // Int array containing the original order of method in the class file (for JVMTI). coleenp@4037: Array* _method_ordering; coleenp@4037: // Instance and static variable information, starts with 6-tuples of shorts coleenp@4037: // [access, name index, sig index, initval index, low_offset, high_offset] coleenp@4037: // for all fields, followed by the generic signature data at the end of coleenp@4037: // the array. Only fields with generic signature attributes have the generic coleenp@4037: // signature data set in the array. The fields array looks like following: coleenp@4037: // coleenp@4037: // f1: [access, name index, sig index, initial value index, low_offset, high_offset] coleenp@4037: // f2: [access, name index, sig index, initial value index, low_offset, high_offset] coleenp@4037: // ... coleenp@4037: // fn: [access, name index, sig index, initial value index, low_offset, high_offset] coleenp@4037: // [generic signature index] coleenp@4037: // [generic signature index] coleenp@4037: // ... coleenp@4037: Array* _fields; duke@435: duke@435: // embedded Java vtable follows here duke@435: // embedded Java itables follows here duke@435: // embedded static fields follows here duke@435: // embedded nonstatic oop-map blocks follows here jiangli@3701: // embedded implementor of this interface follows here jiangli@3701: // The embedded implementor only exists if the current klass is an jiangli@3701: // iterface. The possible values of the implementor fall into following jiangli@3701: // three cases: jiangli@3701: // NULL: no implementor. coleenp@4037: // A Klass* that's not itself: one implementor. jiangli@3701: // Itsef: more than one implementors. jiangli@3741: // embedded host klass follows here jiangli@3741: // The embedded host klass only exists in an anonymous class for jiangli@3741: // dynamic language support (JSR 292 enabled). The host class grants jiangli@3741: // its access privileges to this class also. The host class is either jiangli@3741: // named, or a previously loaded anonymous class. A non-anonymous class jiangli@3741: // or an anonymous class loaded through normal classloading does not jiangli@3741: // have this embedded field. jiangli@3741: // duke@435: duke@435: friend class SystemDictionary; duke@435: duke@435: public: jiangli@3741: bool has_nonstatic_fields() const { jiangli@3741: return (_misc_flags & _misc_has_nonstatic_fields) != 0; jiangli@3741: } jiangli@3741: void set_has_nonstatic_fields(bool b) { jiangli@3741: if (b) { jiangli@3741: _misc_flags |= _misc_has_nonstatic_fields; jiangli@3741: } else { jiangli@3741: _misc_flags &= ~_misc_has_nonstatic_fields; jiangli@3741: } jiangli@3741: } coleenp@548: duke@435: // field sizes duke@435: int nonstatic_field_size() const { return _nonstatic_field_size; } duke@435: void set_nonstatic_field_size(int size) { _nonstatic_field_size = size; } duke@435: duke@435: int static_field_size() const { return _static_field_size; } duke@435: void set_static_field_size(int size) { _static_field_size = size; } duke@435: jiangli@3373: int static_oop_field_count() const { return (int)_static_oop_field_count; } jiangli@3373: void set_static_oop_field_count(u2 size) { _static_oop_field_count = size; } duke@435: duke@435: // Java vtable duke@435: int vtable_length() const { return _vtable_len; } duke@435: void set_vtable_length(int len) { _vtable_len = len; } duke@435: duke@435: // Java itable duke@435: int itable_length() const { return _itable_len; } duke@435: void set_itable_length(int len) { _itable_len = len; } duke@435: duke@435: // array klasses coleenp@4037: Klass* array_klasses() const { return _array_klasses; } coleenp@4037: void set_array_klasses(Klass* k) { _array_klasses = k; } duke@435: duke@435: // methods coleenp@4037: Array* methods() const { return _methods; } coleenp@4037: void set_methods(Array* a) { _methods = a; } coleenp@4037: Method* method_with_idnum(int idnum); duke@435: duke@435: // method ordering coleenp@4037: Array* method_ordering() const { return _method_ordering; } coleenp@4037: void set_method_ordering(Array* m) { _method_ordering = m; } duke@435: duke@435: // interfaces coleenp@4037: Array* local_interfaces() const { return _local_interfaces; } coleenp@4037: void set_local_interfaces(Array* a) { coleenp@4037: guarantee(_local_interfaces == NULL || a == NULL, "Just checking"); coleenp@4037: _local_interfaces = a; } coleenp@4037: Array* transitive_interfaces() const { return _transitive_interfaces; } coleenp@4037: void set_transitive_interfaces(Array* a) { coleenp@4037: guarantee(_transitive_interfaces == NULL || a == NULL, "Just checking"); coleenp@4037: _transitive_interfaces = a; } duke@435: never@3137: private: never@3137: friend class fieldDescriptor; never@3137: FieldInfo* field(int index) const { return FieldInfo::from_field_array(_fields, index); } never@3137: never@3137: public: never@3137: int field_offset (int index) const { return field(index)->offset(); } never@3137: int field_access_flags(int index) const { return field(index)->access_flags(); } never@3137: Symbol* field_name (int index) const { return field(index)->name(constants()); } never@3137: Symbol* field_signature (int index) const { return field(index)->signature(constants()); } never@3137: never@3137: // Number of Java declared fields jiangli@3373: int java_fields_count() const { return (int)_java_fields_count; } never@3137: coleenp@4037: Array* fields() const { return _fields; } never@3137: coleenp@4037: void set_fields(Array* f, u2 java_fields_count) { coleenp@4037: guarantee(_fields == NULL || f == NULL, "Just checking"); coleenp@4037: _fields = f; never@3137: _java_fields_count = java_fields_count; duke@435: } duke@435: duke@435: // inner classes coleenp@4037: Array* inner_classes() const { return _inner_classes; } coleenp@4037: void set_inner_classes(Array* f) { _inner_classes = f; } duke@435: duke@435: enum InnerClassAttributeOffset { duke@435: // From http://mirror.eng/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc10.html#18814 duke@435: inner_class_inner_class_info_offset = 0, duke@435: inner_class_outer_class_info_offset = 1, duke@435: inner_class_inner_name_offset = 2, duke@435: inner_class_access_flags_offset = 3, duke@435: inner_class_next_offset = 4 duke@435: }; duke@435: jiangli@3670: enum EnclosingMethodAttributeOffset { jiangli@3670: enclosing_method_class_index_offset = 0, jiangli@3670: enclosing_method_method_index_offset = 1, jiangli@3670: enclosing_method_attribute_size = 2 jiangli@3670: }; jiangli@3670: acorn@1087: // method override check coleenp@2497: bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS); acorn@1087: duke@435: // package coleenp@4037: bool is_same_class_package(Klass* class2); coleenp@2497: bool is_same_class_package(oop classloader2, Symbol* classname2); coleenp@2497: static bool is_same_class_package(oop class_loader1, Symbol* class_name1, oop class_loader2, Symbol* class_name2); duke@435: jrose@1100: // find an enclosing class (defined where original code was, in jvm.cpp!) coleenp@4037: Klass* compute_enclosing_class(bool* inner_is_member, TRAPS) { coleenp@4037: instanceKlassHandle self(THREAD, this); xlu@1561: return compute_enclosing_class_impl(self, inner_is_member, THREAD); jrose@1100: } coleenp@4037: static Klass* compute_enclosing_class_impl(instanceKlassHandle self, xlu@1561: bool* inner_is_member, TRAPS); jrose@1100: jrose@1100: // tell if two classes have the same enclosing class (at package level) coleenp@4037: bool is_same_package_member(Klass* class2, TRAPS) { coleenp@4037: instanceKlassHandle self(THREAD, this); jrose@1100: return is_same_package_member_impl(self, class2, THREAD); jrose@1100: } jrose@1100: static bool is_same_package_member_impl(instanceKlassHandle self, coleenp@4037: Klass* class2, TRAPS); jrose@1100: duke@435: // initialization state duke@435: bool is_loaded() const { return _init_state >= loaded; } duke@435: bool is_linked() const { return _init_state >= linked; } duke@435: bool is_initialized() const { return _init_state == fully_initialized; } duke@435: bool is_not_initialized() const { return _init_state < being_initialized; } duke@435: bool is_being_initialized() const { return _init_state == being_initialized; } duke@435: bool is_in_error_state() const { return _init_state == initialization_error; } duke@435: bool is_reentrant_initialization(Thread *thread) { return thread == _init_thread; } coleenp@3368: ClassState init_state() { return (ClassState)_init_state; } jiangli@3741: bool is_rewritten() const { return (_misc_flags & _misc_rewritten) != 0; } acorn@1408: acorn@1408: // defineClass specified verification jiangli@3741: bool should_verify_class() const { jiangli@3741: return (_misc_flags & _misc_should_verify_class) != 0; jiangli@3741: } jiangli@3741: void set_should_verify_class(bool value) { jiangli@3741: if (value) { jiangli@3741: _misc_flags |= _misc_should_verify_class; jiangli@3741: } else { jiangli@3741: _misc_flags &= ~_misc_should_verify_class; jiangli@3741: } jiangli@3741: } duke@435: duke@435: // marking dcubed@3401: bool is_marked_dependent() const { return _is_marked_dependent; } dcubed@3401: void set_is_marked_dependent(bool value) { _is_marked_dependent = value; } duke@435: duke@435: // initialization (virtuals from Klass) duke@435: bool should_be_initialized() const; // means that initialize should be called duke@435: void initialize(TRAPS); duke@435: void link_class(TRAPS); duke@435: bool link_class_or_fail(TRAPS); // returns false on failure duke@435: void unlink_class(); duke@435: void rewrite_class(TRAPS); coleenp@4395: void link_methods(TRAPS); coleenp@4037: Method* class_initializer(); duke@435: duke@435: // set the class to initialized if no static initializer is present duke@435: void eager_initialize(Thread *thread); duke@435: duke@435: // reference type jiangli@3526: ReferenceType reference_type() const { return (ReferenceType)_reference_type; } jiangli@3526: void set_reference_type(ReferenceType t) { jiangli@3526: assert(t == (u1)t, "overflow"); jiangli@3526: _reference_type = (u1)t; jiangli@3526: } duke@435: coleenp@4037: static ByteSize reference_type_offset() { return in_ByteSize(offset_of(InstanceKlass, _reference_type)); } johnc@2781: duke@435: // find local field, returns true if found coleenp@2497: bool find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; duke@435: // find field in direct superinterfaces, returns the interface in which the field is defined coleenp@4037: Klass* find_interface_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; duke@435: // find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined coleenp@4037: Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; duke@435: // find instance or static fields according to JVM spec 5.4.3.2, returns the klass in which the field is defined coleenp@4037: Klass* find_field(Symbol* name, Symbol* sig, bool is_static, fieldDescriptor* fd) const; duke@435: duke@435: // find a non-static or static field given its offset within the class. duke@435: bool contains_field_offset(int offset) { coleenp@548: return instanceOopDesc::contains_field_offset(offset, nonstatic_field_size()); duke@435: } duke@435: duke@435: bool find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const; duke@435: bool find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const; duke@435: duke@435: // find a local method (returns NULL if not found) coleenp@4037: Method* find_method(Symbol* name, Symbol* signature) const; coleenp@4037: static Method* find_method(Array* methods, Symbol* name, Symbol* signature); duke@435: duke@435: // lookup operation (returns NULL if not found) coleenp@4037: Method* uncached_lookup_method(Symbol* name, Symbol* signature) const; duke@435: duke@435: // lookup a method in all the interfaces that this class implements duke@435: // (returns NULL if not found) coleenp@4037: Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature) const; duke@435: kamg@4245: // Find method indices by name. If a method with the specified name is kamg@4245: // found the index to the first method is returned, and 'end' is filled in kamg@4245: // with the index of first non-name-matching method. If no method is found kamg@4245: // -1 is returned. kamg@4245: int find_method_by_name(Symbol* name, int* end); kamg@4245: static int find_method_by_name(Array* methods, Symbol* name, int* end); kamg@4245: duke@435: // constant pool coleenp@4037: ConstantPool* constants() const { return _constants; } coleenp@4037: void set_constants(ConstantPool* c) { _constants = c; } duke@435: duke@435: // protection domain duke@435: oop protection_domain() { return _protection_domain; } coleenp@4037: void set_protection_domain(oop pd) { klass_oop_store(&_protection_domain, pd); } duke@435: jrose@866: // host class coleenp@4037: Klass* host_klass() const { coleenp@4037: Klass** hk = (Klass**)adr_host_klass(); jiangli@3741: if (hk == NULL) { jiangli@3741: return NULL; jiangli@3741: } else { jiangli@3741: return *hk; jiangli@3741: } jiangli@3741: } coleenp@4037: void set_host_klass(Klass* host) { jiangli@3741: assert(is_anonymous(), "not anonymous"); coleenp@4037: Klass** addr = (Klass**)adr_host_klass(); jiangli@3741: assert(addr != NULL, "no reversed space"); morris@4693: if (addr != NULL) { morris@4693: *addr = host; morris@4693: } jiangli@3741: } jiangli@3741: bool is_anonymous() const { jiangli@3741: return (_misc_flags & _misc_is_anonymous) != 0; jiangli@3741: } jiangli@3741: void set_is_anonymous(bool value) { jiangli@3741: if (value) { jiangli@3741: _misc_flags |= _misc_is_anonymous; jiangli@3741: } else { jiangli@3741: _misc_flags &= ~_misc_is_anonymous; jiangli@3741: } jiangli@3741: } jrose@866: coleenp@4345: // Oop that keeps the metadata for this class from being unloaded coleenp@4345: // in places where the metadata is stored in other places, like nmethods coleenp@4345: oop klass_holder() const { coleenp@4345: return is_anonymous() ? java_mirror() : class_loader(); coleenp@4345: } coleenp@4345: jwilhelm@4430: bool is_contended() const { jwilhelm@4430: return (_misc_flags & _misc_is_contended) != 0; jwilhelm@4430: } jwilhelm@4430: void set_is_contended(bool value) { jwilhelm@4430: if (value) { jwilhelm@4430: _misc_flags |= _misc_is_contended; jwilhelm@4430: } else { jwilhelm@4430: _misc_flags &= ~_misc_is_contended; jwilhelm@4430: } jwilhelm@4430: } jwilhelm@4430: duke@435: // signers duke@435: objArrayOop signers() const { return _signers; } coleenp@4037: void set_signers(objArrayOop s) { klass_oop_store((oop*)&_signers, s); } duke@435: duke@435: // source file name coleenp@2497: Symbol* source_file_name() const { return _source_file_name; } coleenp@2497: void set_source_file_name(Symbol* n); duke@435: duke@435: // minor and major version numbers of class file duke@435: u2 minor_version() const { return _minor_version; } duke@435: void set_minor_version(u2 minor_version) { _minor_version = minor_version; } duke@435: u2 major_version() const { return _major_version; } duke@435: void set_major_version(u2 major_version) { _major_version = major_version; } duke@435: duke@435: // source debug extension fparain@3906: char* source_debug_extension() const { return _source_debug_extension; } fparain@3906: void set_source_debug_extension(char* array, int length); coleenp@2497: coleenp@2497: // symbol unloading support (refcount already added) coleenp@2497: Symbol* array_name() { return _array_name; } coleenp@4712: void set_array_name(Symbol* name) { assert(_array_name == NULL || name == NULL, "name already created"); _array_name = name; } duke@435: duke@435: // nonstatic oop-map blocks jcoomes@1374: static int nonstatic_oop_map_size(unsigned int oop_map_count) { jcoomes@1373: return oop_map_count * OopMapBlock::size_in_words(); jcoomes@1373: } jcoomes@1374: unsigned int nonstatic_oop_map_count() const { jcoomes@1373: return _nonstatic_oop_map_size / OopMapBlock::size_in_words(); jcoomes@1373: } jcoomes@1373: int nonstatic_oop_map_size() const { return _nonstatic_oop_map_size; } jcoomes@1373: void set_nonstatic_oop_map_size(int words) { jcoomes@1373: _nonstatic_oop_map_size = words; jcoomes@1373: } duke@435: duke@435: // RedefineClasses() support for previous versions: duke@435: void add_previous_version(instanceKlassHandle ikh, BitMap *emcp_methods, duke@435: int emcp_method_count); dcubed@1412: // If the _previous_versions array is non-NULL, then this klass dcubed@1412: // has been redefined at least once even if we aren't currently dcubed@1412: // tracking a previous version. dcubed@1412: bool has_been_redefined() const { return _previous_versions != NULL; } duke@435: bool has_previous_version() const; duke@435: void init_previous_versions() { duke@435: _previous_versions = NULL; duke@435: } duke@435: GrowableArray* previous_versions() const { duke@435: return _previous_versions; duke@435: } duke@435: coleenp@4037: static void purge_previous_versions(InstanceKlass* ik); coleenp@4037: duke@435: // JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation duke@435: void set_cached_class_file(unsigned char *class_file_bytes, duke@435: jint class_file_len) { _cached_class_file_len = class_file_len; duke@435: _cached_class_file_bytes = class_file_bytes; } duke@435: jint get_cached_class_file_len() { return _cached_class_file_len; } duke@435: unsigned char * get_cached_class_file_bytes() { return _cached_class_file_bytes; } duke@435: duke@435: // JVMTI: Support for caching of field indices, types, and offsets duke@435: void set_jvmti_cached_class_field_map(JvmtiCachedClassFieldMap* descriptor) { duke@435: _jvmti_cached_class_field_map = descriptor; duke@435: } duke@435: JvmtiCachedClassFieldMap* jvmti_cached_class_field_map() const { duke@435: return _jvmti_cached_class_field_map; duke@435: } duke@435: jiangli@4436: bool has_default_methods() const { jiangli@4436: return (_misc_flags & _misc_has_default_methods) != 0; jiangli@4436: } jiangli@4436: void set_has_default_methods(bool b) { jiangli@4436: if (b) { jiangli@4436: _misc_flags |= _misc_has_default_methods; jiangli@4436: } else { jiangli@4436: _misc_flags &= ~_misc_has_default_methods; jiangli@4436: } jiangli@4436: } kamg@4245: coleenp@4037: // for adding methods, ConstMethod::UNSET_IDNUM means no more ids available duke@435: inline u2 next_method_idnum(); duke@435: void set_initial_method_idnum(u2 value) { _idnum_allocated_count = value; } duke@435: duke@435: // generics support coleenp@2497: Symbol* generic_signature() const { return _generic_signature; } coleenp@2497: void set_generic_signature(Symbol* sig) { _generic_signature = sig; } coleenp@2497: jiangli@3670: u2 enclosing_method_data(int offset); jiangli@3670: u2 enclosing_method_class_index() { jiangli@3670: return enclosing_method_data(enclosing_method_class_index_offset); jiangli@3670: } jiangli@3670: u2 enclosing_method_method_index() { jiangli@3670: return enclosing_method_data(enclosing_method_method_index_offset); jiangli@3670: } duke@435: void set_enclosing_method_indices(u2 class_index, jiangli@3670: u2 method_index); duke@435: duke@435: // jmethodID support dcubed@1412: static jmethodID get_jmethod_id(instanceKlassHandle ik_h, dcubed@1412: methodHandle method_h); dcubed@1412: static jmethodID get_jmethod_id_fetch_or_update(instanceKlassHandle ik_h, dcubed@1412: size_t idnum, jmethodID new_id, jmethodID* new_jmeths, dcubed@1412: jmethodID* to_dealloc_id_p, dcubed@1412: jmethodID** to_dealloc_jmeths_p); dcubed@1412: static void get_jmethod_id_length_value(jmethodID* cache, size_t idnum, dcubed@1412: size_t *length_p, jmethodID* id_p); coleenp@4037: jmethodID jmethod_id_or_null(Method* method); duke@435: duke@435: // cached itable index support duke@435: void set_cached_itable_index(size_t idnum, int index); duke@435: int cached_itable_index(size_t idnum); duke@435: duke@435: // annotations support coleenp@4037: Annotations* annotations() const { return _annotations; } coleenp@4037: void set_annotations(Annotations* anno) { _annotations = anno; } coleenp@4572: coleenp@4037: AnnotationArray* class_annotations() const { coleenp@4572: return (_annotations != NULL) ? _annotations->class_annotations() : NULL; coleenp@4037: } coleenp@4037: Array* fields_annotations() const { coleenp@4572: return (_annotations != NULL) ? _annotations->fields_annotations() : NULL; coleenp@4037: } coleenp@4572: AnnotationArray* class_type_annotations() const { coleenp@4572: return (_annotations != NULL) ? _annotations->class_type_annotations() : NULL; stefank@4393: } coleenp@4572: Array* fields_type_annotations() const { coleenp@4572: return (_annotations != NULL) ? _annotations->fields_type_annotations() : NULL; coleenp@4572: } duke@435: // allocation duke@435: instanceOop allocate_instance(TRAPS); duke@435: duke@435: // additional member function to return a handle duke@435: instanceHandle allocate_instance_handle(TRAPS) { return instanceHandle(THREAD, allocate_instance(THREAD)); } duke@435: duke@435: objArrayOop allocate_objArray(int n, int length, TRAPS); duke@435: // Helper function duke@435: static instanceOop register_finalizer(instanceOop i, TRAPS); duke@435: duke@435: // Check whether reflection/jni/jvm code is allowed to instantiate this class; duke@435: // if not, throw either an Error or an Exception. duke@435: virtual void check_valid_for_instantiation(bool throwError, TRAPS); duke@435: duke@435: // initialization duke@435: void call_class_initializer(TRAPS); duke@435: void set_initialization_state_and_notify(ClassState state, TRAPS); duke@435: duke@435: // OopMapCache support duke@435: OopMapCache* oop_map_cache() { return _oop_map_cache; } duke@435: void set_oop_map_cache(OopMapCache *cache) { _oop_map_cache = cache; } duke@435: void mask_for(methodHandle method, int bci, InterpreterOopMap* entry); duke@435: duke@435: // JNI identifier support (for static fields - for jni performance) duke@435: JNIid* jni_ids() { return _jni_ids; } duke@435: void set_jni_ids(JNIid* ids) { _jni_ids = ids; } duke@435: JNIid* jni_id_for(int offset); duke@435: duke@435: // maintenance of deoptimization dependencies duke@435: int mark_dependent_nmethods(DepChange& changes); duke@435: void add_dependent_nmethod(nmethod* nm); duke@435: void remove_dependent_nmethod(nmethod* nm); duke@435: duke@435: // On-stack replacement support duke@435: nmethod* osr_nmethods_head() const { return _osr_nmethods_head; }; duke@435: void set_osr_nmethods_head(nmethod* h) { _osr_nmethods_head = h; }; duke@435: void add_osr_nmethod(nmethod* n); duke@435: void remove_osr_nmethod(nmethod* n); coleenp@4037: nmethod* lookup_osr_nmethod(Method* const m, int bci, int level, bool match_level) const; duke@435: coleenp@4037: // Breakpoint support (see methods on Method* for details) duke@435: BreakpointInfo* breakpoints() const { return _breakpoints; }; duke@435: void set_breakpoints(BreakpointInfo* bps) { _breakpoints = bps; }; duke@435: duke@435: // support for stub routines coleenp@4037: static ByteSize init_state_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_state)); } rbackman@3709: TRACE_DEFINE_OFFSET; coleenp@4037: static ByteSize init_thread_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_thread)); } duke@435: duke@435: // subclass/subinterface checks coleenp@4037: bool implements_interface(Klass* k) const; duke@435: jiangli@3701: // Access to the implementor of an interface. coleenp@4037: Klass* implementor() const jiangli@3701: { coleenp@4037: Klass** k = adr_implementor(); jiangli@3701: if (k == NULL) { jiangli@3701: return NULL; jiangli@3701: } else { jiangli@3701: return *k; jiangli@3701: } duke@435: } jiangli@3701: coleenp@4037: void set_implementor(Klass* k) { jiangli@3701: assert(is_interface(), "not interface"); coleenp@4037: Klass** addr = adr_implementor(); morris@4693: assert(addr != NULL, "null addr"); morris@4693: if (addr != NULL) { morris@4693: *addr = k; morris@4693: } jiangli@3701: } jiangli@3701: jiangli@3701: int nof_implementors() const { coleenp@4037: Klass* k = implementor(); jiangli@3701: if (k == NULL) { jiangli@3701: return 0; coleenp@4037: } else if (k != this) { jiangli@3701: return 1; jiangli@3701: } else { jiangli@3701: return 2; jiangli@3701: } jiangli@3701: } jiangli@3701: coleenp@4037: void add_implementor(Klass* k); // k is a new class that implements this interface duke@435: void init_implementor(); // initialize duke@435: duke@435: // link this class into the implementors list of every interface it implements duke@435: void process_interfaces(Thread *thread); duke@435: duke@435: // virtual operations from Klass duke@435: bool is_leaf_class() const { return _subklass == NULL; } coleenp@4037: GrowableArray* compute_secondary_supers(int num_extra_slots); coleenp@4037: bool compute_is_subtype_of(Klass* k); duke@435: bool can_be_primary_super_slow() const; duke@435: int oop_size(oop obj) const { return size_helper(); } duke@435: bool oop_is_instance_slow() const { return true; } duke@435: duke@435: // Iterators duke@435: void do_local_static_fields(FieldClosure* cl); duke@435: void do_nonstatic_fields(FieldClosure* cl); // including inherited fields duke@435: void do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAPS); duke@435: coleenp@4037: void methods_do(void f(Method* method)); coleenp@4037: void array_klasses_do(void f(Klass* k)); coleenp@4037: void array_klasses_do(void f(Klass* k, TRAPS), TRAPS); coleenp@4037: void with_array_klasses_do(void f(Klass* k)); duke@435: bool super_types_do(SuperTypeClosure* blk); duke@435: coleenp@4037: // Casting from Klass* coleenp@4037: static InstanceKlass* cast(Klass* k) { never@2658: assert(k->is_klass(), "must be"); coleenp@4037: assert(k->oop_is_instance(), "cast to InstanceKlass"); coleenp@4037: return (InstanceKlass*) k; duke@435: } duke@435: kamg@4245: InstanceKlass* java_super() const { kamg@4245: return (super() == NULL) ? NULL : cast(super()); kamg@4245: } kamg@4245: duke@435: // Sizing (in words) coleenp@4037: static int header_size() { return align_object_offset(sizeof(InstanceKlass)/HeapWordSize); } coleenp@4572: coleenp@4037: static int size(int vtable_length, int itable_length, coleenp@4037: int nonstatic_oop_map_size, coleenp@4037: bool is_interface, bool is_anonymous) { coleenp@4037: return align_object_size(header_size() + coleenp@4037: align_object_offset(vtable_length) + coleenp@4037: align_object_offset(itable_length) + coleenp@4037: ((is_interface || is_anonymous) ? coleenp@4037: align_object_offset(nonstatic_oop_map_size) : coleenp@4037: nonstatic_oop_map_size) + coleenp@4037: (is_interface ? (int)sizeof(Klass*)/HeapWordSize : 0) + coleenp@4037: (is_anonymous ? (int)sizeof(Klass*)/HeapWordSize : 0)); coleenp@4037: } coleenp@4037: int size() const { return size(vtable_length(), coleenp@4037: itable_length(), coleenp@4037: nonstatic_oop_map_size(), coleenp@4037: is_interface(), coleenp@4037: is_anonymous()); coleenp@4037: } acorn@4497: #if INCLUDE_SERVICES acorn@4497: virtual void collect_statistics(KlassSizeStats *sz) const; acorn@4497: #endif jiangli@3701: duke@435: static int vtable_start_offset() { return header_size(); } coleenp@4037: static int vtable_length_offset() { return offset_of(InstanceKlass, _vtable_len) / HeapWordSize; } duke@435: coleenp@4037: intptr_t* start_of_vtable() const { return ((intptr_t*)this) + vtable_start_offset(); } duke@435: intptr_t* start_of_itable() const { return start_of_vtable() + align_object_offset(vtable_length()); } coleenp@4037: int itable_offset_in_words() const { return start_of_itable() - (intptr_t*)this; } duke@435: duke@435: intptr_t* end_of_itable() const { return start_of_itable() + itable_length(); } duke@435: never@2658: address static_field_addr(int offset); coleenp@548: coleenp@548: OopMapBlock* start_of_nonstatic_oop_maps() const { never@2658: return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length())); coleenp@548: } duke@435: coleenp@4572: Klass** end_of_nonstatic_oop_maps() const { coleenp@4572: return (Klass**)(start_of_nonstatic_oop_maps() + coleenp@4572: nonstatic_oop_map_count()); coleenp@4572: } coleenp@4572: coleenp@4037: Klass** adr_implementor() const { jiangli@3701: if (is_interface()) { coleenp@4572: return (Klass**)end_of_nonstatic_oop_maps(); jiangli@3701: } else { jiangli@3701: return NULL; jiangli@3701: } jiangli@3701: }; jiangli@3701: coleenp@4037: Klass** adr_host_klass() const { jiangli@3741: if (is_anonymous()) { coleenp@4037: Klass** adr_impl = adr_implementor(); jiangli@3741: if (adr_impl != NULL) { jiangli@3741: return adr_impl + 1; jiangli@3741: } else { coleenp@4572: return end_of_nonstatic_oop_maps(); jiangli@3741: } jiangli@3741: } else { jiangli@3741: return NULL; jiangli@3741: } jiangli@3741: } jiangli@3741: duke@435: // Allocation profiling support duke@435: juint alloc_size() const { return _alloc_count * size_helper(); } duke@435: void set_alloc_size(juint n) {} duke@435: duke@435: // Use this to return the size of an instance in heap words: duke@435: int size_helper() const { duke@435: return layout_helper_to_size_helper(layout_helper()); duke@435: } duke@435: duke@435: // This bit is initialized in classFileParser.cpp. duke@435: // It is false under any of the following conditions: duke@435: // - the class is abstract (including any interface) duke@435: // - the class has a finalizer (if !RegisterFinalizersAtInit) duke@435: // - the class size is larger than FastAllocateSizeLimit duke@435: // - the class is java/lang/Class, which cannot be allocated directly duke@435: bool can_be_fastpath_allocated() const { duke@435: return !layout_helper_needs_slow_path(layout_helper()); duke@435: } duke@435: duke@435: // Java vtable/itable duke@435: klassVtable* vtable() const; // return new klassVtable wrapper coleenp@4037: inline Method* method_at_vtable(int index); duke@435: klassItable* itable() const; // return new klassItable wrapper coleenp@4037: Method* method_at_itable(Klass* holder, int index, TRAPS); duke@435: duke@435: // Garbage collection coleenp@4037: virtual void oops_do(OopClosure* cl); coleenp@4037: duke@435: void oop_follow_contents(oop obj); duke@435: int oop_adjust_pointers(oop obj); duke@435: coleenp@4037: void clean_implementors_list(BoolObjectClosure* is_alive); coleenp@4037: void clean_method_data(BoolObjectClosure* is_alive); coleenp@4037: coleenp@4037: // Explicit metaspace deallocation of fields coleenp@4037: // For RedefineClasses, we need to deallocate instanceKlasses coleenp@4037: void deallocate_contents(ClassLoaderData* loader_data); coleenp@4037: coleenp@4037: // The constant pool is on stack if any of the methods are executing or coleenp@4037: // referenced by handles. coleenp@4037: bool on_stack() const { return _constants->on_stack(); } coleenp@4037: duke@435: void release_C_heap_structures(); duke@435: duke@435: // Parallel Scavenge and Parallel Old duke@435: PARALLEL_GC_DECLS duke@435: duke@435: // Naming jrose@1474: const char* signature_name() const; duke@435: duke@435: // Iterators coleenp@4037: int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) { duke@435: return oop_oop_iterate_v(obj, blk); duke@435: } duke@435: coleenp@4037: int oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) { duke@435: return oop_oop_iterate_v_m(obj, blk, mr); duke@435: } duke@435: ysr@777: #define InstanceKlass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \ ysr@777: int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* blk); \ ysr@777: int oop_oop_iterate##nv_suffix##_m(oop obj, OopClosureType* blk, \ duke@435: MemRegion mr); duke@435: duke@435: ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DECL) ysr@777: ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DECL) ysr@777: jprovino@4542: #if INCLUDE_ALL_GCS ysr@777: #define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ ysr@777: int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ysr@777: ysr@777: ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ysr@777: ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) jprovino@4542: #endif // INCLUDE_ALL_GCS duke@435: coleenp@4037: u2 idnum_allocated_count() const { return _idnum_allocated_count; } duke@435: private: duke@435: // initialization state duke@435: #ifdef ASSERT duke@435: void set_init_state(ClassState state); duke@435: #else coleenp@3368: void set_init_state(ClassState state) { _init_state = (u1)state; } duke@435: #endif jiangli@3741: void set_rewritten() { _misc_flags |= _misc_rewritten; } duke@435: void set_init_thread(Thread *thread) { _init_thread = thread; } duke@435: dcubed@1412: // The RedefineClasses() API can cause new method idnums to be needed dcubed@1412: // which will cause the caches to grow. Safety requires different dcubed@1412: // cache management logic if the caches can grow instead of just dcubed@1412: // going from NULL to non-NULL. dcubed@1412: bool idnum_can_increment() const { return has_been_redefined(); } duke@435: jmethodID* methods_jmethod_ids_acquire() const duke@435: { return (jmethodID*)OrderAccess::load_ptr_acquire(&_methods_jmethod_ids); } duke@435: void release_set_methods_jmethod_ids(jmethodID* jmeths) duke@435: { OrderAccess::release_store_ptr(&_methods_jmethod_ids, jmeths); } duke@435: duke@435: int* methods_cached_itable_indices_acquire() const duke@435: { return (int*)OrderAccess::load_ptr_acquire(&_methods_cached_itable_indices); } duke@435: void release_set_methods_cached_itable_indices(int* indices) duke@435: { OrderAccess::release_store_ptr(&_methods_cached_itable_indices, indices); } duke@435: coleenp@4037: // Lock during initialization coleenp@4037: volatile oop init_lock() const; coleenp@4037: void set_init_lock(oop value) { klass_oop_store(&_init_lock, value); } coleenp@4037: void fence_and_clear_init_lock(); // after fully_initialized duke@435: duke@435: // Offsets for memory management duke@435: oop* adr_protection_domain() const { return (oop*)&this->_protection_domain;} duke@435: oop* adr_signers() const { return (oop*)&this->_signers;} coleenp@4037: oop* adr_init_lock() const { return (oop*)&this->_init_lock;} duke@435: duke@435: // Static methods that are used to implement member methods where an exposed this pointer duke@435: // is needed due to possible GCs duke@435: static bool link_class_impl (instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS); duke@435: static bool verify_code (instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS); duke@435: static void initialize_impl (instanceKlassHandle this_oop, TRAPS); duke@435: static void eager_initialize_impl (instanceKlassHandle this_oop); duke@435: static void set_initialization_state_and_notify_impl (instanceKlassHandle this_oop, ClassState state, TRAPS); duke@435: static void call_class_initializer_impl (instanceKlassHandle this_oop, TRAPS); coleenp@4037: static Klass* array_klass_impl (instanceKlassHandle this_oop, bool or_null, int n, TRAPS); duke@435: static void do_local_static_fields_impl (instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS); duke@435: /* jni_id_for_impl for jfieldID only */ duke@435: static JNIid* jni_id_for_impl (instanceKlassHandle this_oop, int offset); duke@435: duke@435: // Returns the array class for the n'th dimension coleenp@4037: Klass* array_klass_impl(bool or_null, int n, TRAPS); duke@435: duke@435: // Returns the array class with this class as element type coleenp@4037: Klass* array_klass_impl(bool or_null, TRAPS); duke@435: duke@435: public: coleenp@4037: // CDS support - remove and restore oops from metadata. Oops are not shared. duke@435: virtual void remove_unshareable_info(); coleenp@4037: virtual void restore_unshareable_info(TRAPS); duke@435: duke@435: // jvm support duke@435: jint compute_modifier_flags(TRAPS) const; duke@435: duke@435: public: duke@435: // JVMTI support duke@435: jint jvmti_class_status() const; duke@435: duke@435: public: duke@435: // Printing coleenp@4037: #ifndef PRODUCT coleenp@4037: void print_on(outputStream* st) const; coleenp@4037: #endif coleenp@4037: void print_value_on(outputStream* st) const; coleenp@4037: jrose@1590: void oop_print_value_on(oop obj, outputStream* st); coleenp@4037: jrose@1590: #ifndef PRODUCT duke@435: void oop_print_on (oop obj, outputStream* st); duke@435: duke@435: void print_dependent_nmethods(bool verbose = false); duke@435: bool is_dependent_nmethod(nmethod* nm); duke@435: #endif duke@435: coleenp@4037: const char* internal_name() const; coleenp@4037: duke@435: // Verification coleenp@4037: void verify_on(outputStream* st); coleenp@4037: duke@435: void oop_verify_on(oop obj, outputStream* st); duke@435: }; duke@435: coleenp@4037: inline Method* InstanceKlass::method_at_vtable(int index) { duke@435: #ifndef PRODUCT duke@435: assert(index >= 0, "valid vtable index"); duke@435: if (DebugVtables) { duke@435: verify_vtable_index(index); duke@435: } duke@435: #endif duke@435: vtableEntry* ve = (vtableEntry*)start_of_vtable(); duke@435: return ve[index].method(); duke@435: } duke@435: duke@435: // for adding methods duke@435: // UNSET_IDNUM return means no more ids available coleenp@4037: inline u2 InstanceKlass::next_method_idnum() { coleenp@4037: if (_idnum_allocated_count == ConstMethod::MAX_IDNUM) { coleenp@4037: return ConstMethod::UNSET_IDNUM; // no more ids available duke@435: } else { duke@435: return _idnum_allocated_count++; duke@435: } duke@435: } duke@435: duke@435: duke@435: /* JNIid class for jfieldIDs only */ zgu@3900: class JNIid: public CHeapObj { duke@435: friend class VMStructs; duke@435: private: coleenp@4037: Klass* _holder; duke@435: JNIid* _next; duke@435: int _offset; duke@435: #ifdef ASSERT duke@435: bool _is_static_field_id; duke@435: #endif duke@435: duke@435: public: duke@435: // Accessors coleenp@4037: Klass* holder() const { return _holder; } duke@435: int offset() const { return _offset; } duke@435: JNIid* next() { return _next; } duke@435: // Constructor coleenp@4037: JNIid(Klass* holder, int offset, JNIid* next); duke@435: // Identifier lookup duke@435: JNIid* find(int offset); duke@435: never@2658: bool find_local_field(fieldDescriptor* fd) { coleenp@4037: return InstanceKlass::cast(holder())->find_local_field_from_offset(offset(), true, fd); never@2658: } never@2658: duke@435: static void deallocate(JNIid* id); duke@435: // Debugging duke@435: #ifdef ASSERT duke@435: bool is_static_field_id() const { return _is_static_field_id; } duke@435: void set_is_static_field_id() { _is_static_field_id = true; } duke@435: #endif coleenp@4037: void verify(Klass* holder); duke@435: }; duke@435: duke@435: duke@435: // If breakpoints are more numerous than just JVMTI breakpoints, duke@435: // consider compressing this data structure. coleenp@4037: // It is currently a simple linked list defined in method.hpp. duke@435: duke@435: class BreakpointInfo; duke@435: duke@435: duke@435: // A collection point for interesting information about the previous coleenp@4037: // version(s) of an InstanceKlass. This class uses weak references to duke@435: // the information so that the information may be collected as needed dcubed@482: // by the system. If the information is shared, then a regular dcubed@482: // reference must be used because a weak reference would be seen as dcubed@482: // collectible. A GrowableArray of PreviousVersionNodes is attached coleenp@4037: // to the InstanceKlass as needed. See PreviousVersionWalker below. zgu@3900: class PreviousVersionNode : public CHeapObj { duke@435: private: dcubed@482: // A shared ConstantPool is never collected so we'll always have dcubed@482: // a reference to it so we can update items in the cache. We'll dcubed@482: // have a weak reference to a non-shared ConstantPool until all dcubed@482: // of the methods (EMCP or obsolete) have been collected; the dcubed@482: // non-shared ConstantPool becomes collectible at that point. coleenp@4037: ConstantPool* _prev_constant_pool; // regular or weak reference dcubed@482: bool _prev_cp_is_weak; // true if not a shared ConstantPool dcubed@482: coleenp@4037: // If the previous version of the InstanceKlass doesn't have any duke@435: // EMCP methods, then _prev_EMCP_methods will be NULL. If all the duke@435: // EMCP methods have been collected, then _prev_EMCP_methods can duke@435: // have a length of zero. coleenp@4037: GrowableArray* _prev_EMCP_methods; duke@435: duke@435: public: coleenp@4037: PreviousVersionNode(ConstantPool* prev_constant_pool, bool prev_cp_is_weak, coleenp@4037: GrowableArray* prev_EMCP_methods); duke@435: ~PreviousVersionNode(); coleenp@4037: ConstantPool* prev_constant_pool() const { duke@435: return _prev_constant_pool; duke@435: } coleenp@4037: GrowableArray* prev_EMCP_methods() const { duke@435: return _prev_EMCP_methods; duke@435: } duke@435: }; duke@435: duke@435: duke@435: // A Handle-ized version of PreviousVersionNode. duke@435: class PreviousVersionInfo : public ResourceObj { duke@435: private: duke@435: constantPoolHandle _prev_constant_pool_handle; coleenp@4037: // If the previous version of the InstanceKlass doesn't have any duke@435: // EMCP methods, then _prev_EMCP_methods will be NULL. Since the duke@435: // methods cannot be collected while we hold a handle, duke@435: // _prev_EMCP_methods should never have a length of zero. duke@435: GrowableArray* _prev_EMCP_method_handles; duke@435: duke@435: public: duke@435: PreviousVersionInfo(PreviousVersionNode *pv_node); duke@435: ~PreviousVersionInfo(); duke@435: constantPoolHandle prev_constant_pool_handle() const { duke@435: return _prev_constant_pool_handle; duke@435: } duke@435: GrowableArray* prev_EMCP_method_handles() const { duke@435: return _prev_EMCP_method_handles; duke@435: } duke@435: }; duke@435: duke@435: duke@435: // Helper object for walking previous versions. This helper cleans up duke@435: // the Handles that it allocates when the helper object is destroyed. duke@435: // The PreviousVersionInfo object returned by next_previous_version() duke@435: // is only valid until a subsequent call to next_previous_version() or duke@435: // the helper object is destroyed. duke@435: class PreviousVersionWalker : public StackObj { duke@435: private: duke@435: GrowableArray* _previous_versions; duke@435: int _current_index; duke@435: // Fields for cleaning up when we are done walking the previous versions: duke@435: // A HandleMark for the PreviousVersionInfo handles: duke@435: HandleMark _hm; duke@435: duke@435: // It would be nice to have a ResourceMark field in this helper also, duke@435: // but the ResourceMark code says to be careful to delete handles held duke@435: // in GrowableArrays _before_ deleting the GrowableArray. Since we duke@435: // can't guarantee the order in which the fields are destroyed, we duke@435: // have to let the creator of the PreviousVersionWalker object do duke@435: // the right thing. Also, adding a ResourceMark here causes an duke@435: // include loop. duke@435: duke@435: // A pointer to the current info object so we can handle the deletes. duke@435: PreviousVersionInfo * _current_p; duke@435: duke@435: public: coleenp@4037: PreviousVersionWalker(InstanceKlass *ik); duke@435: ~PreviousVersionWalker(); duke@435: duke@435: // Return the interesting information for the next previous version duke@435: // of the klass. Returns NULL if there are no more previous versions. duke@435: PreviousVersionInfo* next_previous_version(); duke@435: }; stefank@2314: never@3138: never@3138: // never@3138: // nmethodBucket is used to record dependent nmethods for never@3138: // deoptimization. nmethod dependencies are actually never@3138: // pairs but we really only care about the klass part for purposes of never@3138: // finding nmethods which might need to be deoptimized. Instead of never@3138: // recording the method, a count of how many times a particular nmethod never@3138: // was recorded is kept. This ensures that any recording errors are never@3138: // noticed since an nmethod should be removed as many times are it's never@3138: // added. never@3138: // zgu@3900: class nmethodBucket: public CHeapObj { never@3138: friend class VMStructs; never@3138: private: never@3138: nmethod* _nmethod; never@3138: int _count; never@3138: nmethodBucket* _next; never@3138: never@3138: public: never@3138: nmethodBucket(nmethod* nmethod, nmethodBucket* next) { never@3138: _nmethod = nmethod; never@3138: _next = next; never@3138: _count = 1; never@3138: } never@3138: int count() { return _count; } never@3138: int increment() { _count += 1; return _count; } never@3138: int decrement() { _count -= 1; assert(_count >= 0, "don't underflow"); return _count; } never@3138: nmethodBucket* next() { return _next; } never@3138: void set_next(nmethodBucket* b) { _next = b; } never@3138: nmethod* get_nmethod() { return _nmethod; } never@3138: }; never@3138: jiangli@3670: // An iterator that's used to access the inner classes indices in the coleenp@4037: // InstanceKlass::_inner_classes array. jiangli@3670: class InnerClassesIterator : public StackObj { jiangli@3670: private: coleenp@4037: Array* _inner_classes; jiangli@3670: int _length; jiangli@3670: int _idx; jiangli@3670: public: jiangli@3670: jiangli@3670: InnerClassesIterator(instanceKlassHandle k) { jiangli@3670: _inner_classes = k->inner_classes(); jiangli@3670: if (k->inner_classes() != NULL) { jiangli@3670: _length = _inner_classes->length(); jiangli@3670: // The inner class array's length should be the multiple of jiangli@3670: // inner_class_next_offset if it only contains the InnerClasses jiangli@3670: // attribute data, or it should be jiangli@3670: // n*inner_class_next_offset+enclosing_method_attribute_size jiangli@3670: // if it also contains the EnclosingMethod data. coleenp@4037: assert((_length % InstanceKlass::inner_class_next_offset == 0 || coleenp@4037: _length % InstanceKlass::inner_class_next_offset == InstanceKlass::enclosing_method_attribute_size), jiangli@3670: "just checking"); jiangli@3670: // Remove the enclosing_method portion if exists. coleenp@4037: if (_length % InstanceKlass::inner_class_next_offset == InstanceKlass::enclosing_method_attribute_size) { coleenp@4037: _length -= InstanceKlass::enclosing_method_attribute_size; jiangli@3670: } jiangli@3670: } else { jiangli@3670: _length = 0; jiangli@3670: } jiangli@3670: _idx = 0; jiangli@3670: } jiangli@3670: jiangli@3670: int length() const { jiangli@3670: return _length; jiangli@3670: } jiangli@3670: jiangli@3670: void next() { coleenp@4037: _idx += InstanceKlass::inner_class_next_offset; jiangli@3670: } jiangli@3670: jiangli@3670: bool done() const { jiangli@3670: return (_idx >= _length); jiangli@3670: } jiangli@3670: jiangli@3670: u2 inner_class_info_index() const { coleenp@4037: return _inner_classes->at( coleenp@4037: _idx + InstanceKlass::inner_class_inner_class_info_offset); jiangli@3670: } jiangli@3670: jiangli@3670: void set_inner_class_info_index(u2 index) { coleenp@4037: _inner_classes->at_put( coleenp@4037: _idx + InstanceKlass::inner_class_inner_class_info_offset, index); jiangli@3670: } jiangli@3670: jiangli@3670: u2 outer_class_info_index() const { coleenp@4037: return _inner_classes->at( coleenp@4037: _idx + InstanceKlass::inner_class_outer_class_info_offset); jiangli@3670: } jiangli@3670: jiangli@3670: void set_outer_class_info_index(u2 index) { coleenp@4037: _inner_classes->at_put( coleenp@4037: _idx + InstanceKlass::inner_class_outer_class_info_offset, index); jiangli@3670: } jiangli@3670: jiangli@3670: u2 inner_name_index() const { coleenp@4037: return _inner_classes->at( coleenp@4037: _idx + InstanceKlass::inner_class_inner_name_offset); jiangli@3670: } jiangli@3670: jiangli@3670: void set_inner_name_index(u2 index) { coleenp@4037: _inner_classes->at_put( coleenp@4037: _idx + InstanceKlass::inner_class_inner_name_offset, index); jiangli@3670: } jiangli@3670: jiangli@3670: u2 inner_access_flags() const { coleenp@4037: return _inner_classes->at( coleenp@4037: _idx + InstanceKlass::inner_class_access_flags_offset); jiangli@3670: } jiangli@3670: }; jiangli@3670: stefank@2314: #endif // SHARE_VM_OOPS_INSTANCEKLASS_HPP