Mercurial > hg > graal-jvmci-8
diff src/share/vm/oops/instanceKlass.hpp @ 6275:957c266d8bc5
Merge with http://hg.openjdk.java.net/hsx/hsx24/hotspot/
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 21 Aug 2012 10:39:19 +0200 |
parents | 33df1aeaebbf 04ade88d9712 |
children | dddcdb7ae209 |
line wrap: on
line diff
--- a/src/share/vm/oops/instanceKlass.hpp Mon Aug 20 15:21:31 2012 +0200 +++ b/src/share/vm/oops/instanceKlass.hpp Tue Aug 21 10:39:19 2012 +0200 @@ -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,10 @@ // [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 +// [EMBEDDED host klass ] only exist for an anonymous class (JSR 292 enabled) // forward declaration for class -- see below for definition @@ -153,10 +152,6 @@ oop* oop_block_beg() const { return adr_array_klasses(); } oop* oop_block_end() const { return adr_methods_default_annotations() + 1; } - enum { - implementors_limit = 2 // how many implems can we track? - }; - protected: // // The oop block. See comment in klass.hpp before making changes. @@ -173,8 +168,19 @@ objArrayOop _local_interfaces; // Interface (klassOops) this class implements transitively. objArrayOop _transitive_interfaces; - // Instance and static variable information, 5-tuples of shorts [access, name - // index, sig index, initval index, offset]. + // Instance and static variable information, starts with 6-tuples of shorts + // [access, name index, sig index, initval index, low_offset, high_offset] + // for all fields, followed by the generic signature data at the end of + // the array. Only fields with generic signature attributes have the generic + // signature data set in the array. The fields array looks like following: + // + // f1: [access, name index, sig index, initial value index, low_offset, high_offset] + // f2: [access, name index, sig index, initial value index, low_offset, high_offset] + // ... + // fn: [access, name index, sig index, initial value index, low_offset, high_offset] + // [generic signature index] + // [generic signature index] + // ... typeArrayOop _fields; // Constant pool for this class. constantPoolOop _constants; @@ -182,16 +188,20 @@ oop _class_loader; // Protection domain. oop _protection_domain; - // Host class, which grants its access privileges to this class also. - // This is only non-null for an anonymous class (JSR 292 enabled). - // The host class is either named, or a previously loaded anonymous class. - klassOop _host_klass; // Class signers. objArrayOop _signers; - // inner_classes attribute. + // The InnerClasses attribute and EnclosingMethod attribute. The + // _inner_classes is an array of shorts. If the class has InnerClasses + // attribute, then the _inner_classes array begins with 4-tuples of shorts + // [inner_class_info_index, outer_class_info_index, + // inner_name_index, inner_class_access_flags] for the InnerClasses + // attribute. If the EnclosingMethod attribute exists, it occupies the + // last two shorts [class_index, method_index] of the array. If only + // the InnerClasses attribute exists, the _inner_classes array length is + // number_of_inner_classes * 4. If the class has both InnerClasses + // 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. @@ -216,7 +226,9 @@ // Name of source file containing this klass, NULL if not specified. Symbol* _source_file_name; // the source debug extension for this klass, NULL if not specified. - Symbol* _source_debug_extension; + // Specified as UTF-8 string without terminating zero byte in the classfile, + // it is stored in the instanceklass as a NULL-terminated UTF-8 string + char* _source_debug_extension; // Generic signature, or null if none. Symbol* _generic_signature; // Array name derived from this class which needs unreferencing @@ -232,9 +244,13 @@ int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks bool _is_marked_dependent; // used for marking during flushing and deoptimization - bool _rewritten; // methods rewritten. - bool _has_nonstatic_fields; // for sizing with UseCompressedOops - bool _should_verify_class; // allow caching of preverification + enum { + _misc_rewritten = 1 << 0, // methods rewritten. + _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops + _misc_should_verify_class = 1 << 2, // allow caching of preverification + _misc_is_anonymous = 1 << 3 // has embedded _inner_classes field + }; + u2 _misc_flags; u2 _minor_version; // minor version number of class file u2 _major_version; // major version number of class file Thread* _init_thread; // Pointer to current thread doing initialization (to handle recusive initialization) @@ -247,12 +263,9 @@ 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<PreviousVersionNode *>* _previous_versions; - u2 _enclosing_method_class_index; // Constant pool index for class of enclosing method, or 0 if none - u2 _enclosing_method_method_index; // Constant pool index for name and type of enclosing method, or 0 if none // JVMTI fields can be moved to their own structure - see 6315920 unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH jint _cached_class_file_len; // JVMTI: length of above @@ -270,13 +283,36 @@ // 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. + // embedded host klass follows here + // The embedded host klass only exists in an anonymous class for + // dynamic language support (JSR 292 enabled). The host class grants + // its access privileges to this class also. The host class is either + // named, or a previously loaded anonymous class. A non-anonymous class + // or an anonymous class loaded through normal classloading does not + // have this embedded field. + // friend class instanceKlassKlass; friend class SystemDictionary; public: - bool has_nonstatic_fields() const { return _has_nonstatic_fields; } - void set_has_nonstatic_fields(bool b) { _has_nonstatic_fields = b; } + bool has_nonstatic_fields() const { + return (_misc_flags & _misc_has_nonstatic_fields) != 0; + } + void set_has_nonstatic_fields(bool b) { + if (b) { + _misc_flags |= _misc_has_nonstatic_fields; + } else { + _misc_flags &= ~_misc_has_nonstatic_fields; + } + } // field sizes int nonstatic_field_size() const { return _nonstatic_field_size; } @@ -328,9 +364,6 @@ // Number of Java declared fields int java_fields_count() const { return (int)_java_fields_count; } - // Number of fields including any injected fields - int all_fields_count() const { return _fields->length() / sizeof(FieldInfo::field_slots); } - typeArrayOop fields() const { return _fields; } void set_fields(typeArrayOop f, u2 java_fields_count) { @@ -351,6 +384,12 @@ inner_class_next_offset = 4 }; + enum EnclosingMethodAttributeOffset { + enclosing_method_class_index_offset = 0, + enclosing_method_method_index_offset = 1, + enclosing_method_attribute_size = 2 + }; + // method override check bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS); @@ -384,11 +423,19 @@ bool is_in_error_state() const { return _init_state == initialization_error; } bool is_reentrant_initialization(Thread *thread) { return thread == _init_thread; } ClassState init_state() { return (ClassState)_init_state; } - bool is_rewritten() const { return _rewritten; } + bool is_rewritten() const { return (_misc_flags & _misc_rewritten) != 0; } // defineClass specified verification - bool should_verify_class() const { return _should_verify_class; } - void set_should_verify_class(bool value) { _should_verify_class = value; } + bool should_verify_class() const { + return (_misc_flags & _misc_should_verify_class) != 0; + } + void set_should_verify_class(bool value) { + if (value) { + _misc_flags |= _misc_should_verify_class; + } else { + _misc_flags &= ~_misc_should_verify_class; + } + } // marking bool is_marked_dependent() const { return _is_marked_dependent; } @@ -457,9 +504,30 @@ void set_protection_domain(oop pd) { oop_store((oop*) &_protection_domain, pd); } // host class - oop host_klass() const { return _host_klass; } - void set_host_klass(oop host) { oop_store((oop*) &_host_klass, host); } - bool is_anonymous() const { return _host_klass != NULL; } + oop host_klass() const { + oop* hk = adr_host_klass(); + if (hk == NULL) { + return NULL; + } else { + return *hk; + } + } + void set_host_klass(oop host) { + assert(is_anonymous(), "not anonymous"); + oop* addr = adr_host_klass(); + assert(addr != NULL, "no reversed space"); + oop_store(addr, host); + } + bool is_anonymous() const { + return (_misc_flags & _misc_is_anonymous) != 0; + } + void set_is_anonymous(bool value) { + if (value) { + _misc_flags |= _misc_is_anonymous; + } else { + _misc_flags &= ~_misc_is_anonymous; + } + } // signers objArrayOop signers() const { return _signers; } @@ -476,8 +544,8 @@ void set_major_version(u2 major_version) { _major_version = major_version; } // source debug extension - Symbol* source_debug_extension() const { return _source_debug_extension; } - void set_source_debug_extension(Symbol* n); + char* source_debug_extension() const { return _source_debug_extension; } + void set_source_debug_extension(char* array, int length); // symbol unloading support (refcount already added) Symbol* array_name() { return _array_name; } @@ -533,11 +601,15 @@ Symbol* generic_signature() const { return _generic_signature; } void set_generic_signature(Symbol* sig) { _generic_signature = sig; } - u2 enclosing_method_class_index() const { return _enclosing_method_class_index; } - u2 enclosing_method_method_index() const { return _enclosing_method_method_index; } + u2 enclosing_method_data(int offset); + u2 enclosing_method_class_index() { + return enclosing_method_data(enclosing_method_class_index_offset); + } + u2 enclosing_method_method_index() { + return enclosing_method_data(enclosing_method_method_index_offset); + } void set_enclosing_method_indices(u2 class_index, - u2 method_index) { _enclosing_method_class_index = class_index; - _enclosing_method_method_index = method_index; } + u2 method_index); // jmethodID support static jmethodID get_jmethod_id(instanceKlassHandle ik_h, @@ -626,19 +698,40 @@ // support for stub routines static ByteSize init_state_offset() { return in_ByteSize(sizeof(klassOopDesc) + offset_of(instanceKlass, _init_state)); } + TRACE_DEFINE_OFFSET; static ByteSize init_thread_offset() { return in_ByteSize(sizeof(klassOopDesc) + offset_of(instanceKlass, _init_thread)); } // 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 = (klassOop*)adr_implementor(); + if (k == NULL) { + return NULL; + } else { + return *k; + } } - int nof_implementors() const { return _nof_implementors; } + + void set_implementor(klassOop k) { + assert(is_interface(), "not interface"); + oop* addr = adr_implementor(); + oop_store_without_check(addr, k); + } + + int nof_implementors() const { + klassOop k = implementor(); + if (k == NULL) { + return 0; + } else if (k != this->as_klassOop()) { + return 1; + } else { + return 2; + } + } + void add_implementor(klassOop k); // k is a new class that implements this interface void init_implementor(); // initialize @@ -646,7 +739,7 @@ void process_interfaces(Thread *thread); // virtual operations from Klass - bool is_leaf_class() const { return _subklass == NULL && _nof_implementors == 0; } + bool is_leaf_class() const { return _subklass == NULL; } objArrayOop compute_secondary_supers(int num_extra_slots, TRAPS); bool compute_is_subtype_of(klassOop k); bool can_be_primary_super_slow() const; @@ -675,7 +768,17 @@ // 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() || is_anonymous()) ? + align_object_offset(nonstatic_oop_map_size()) : + nonstatic_oop_map_size()) + + (is_interface() ? (int)sizeof(klassOop)/HeapWordSize : 0) + + (is_anonymous() ? (int)sizeof(klassOop)/HeapWordSize : 0)); + } 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); } @@ -692,6 +795,29 @@ return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length())); } + oop* adr_implementor() const { + if (is_interface()) { + return (oop*)(start_of_nonstatic_oop_maps() + + nonstatic_oop_map_count()); + } else { + return NULL; + } + }; + + oop* adr_host_klass() const { + if (is_anonymous()) { + oop* adr_impl = adr_implementor(); + if (adr_impl != NULL) { + return adr_impl + 1; + } else { + return (oop*)(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) {} @@ -765,7 +891,7 @@ #else void set_init_state(ClassState state) { _init_state = (u1)state; } #endif - void set_rewritten() { _rewritten = true; } + void set_rewritten() { _misc_flags |= _misc_rewritten; } void set_init_thread(Thread *thread) { _init_thread = thread; } u2 idnum_allocated_count() const { return _idnum_allocated_count; } @@ -798,10 +924,8 @@ oop* adr_constants() const { return (oop*)&this->_constants;} oop* adr_class_loader() const { return (oop*)&this->_class_loader;} oop* adr_protection_domain() const { return (oop*)&this->_protection_domain;} - 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_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;} @@ -885,7 +1009,7 @@ /* JNIid class for jfieldIDs only */ -class JNIid: public CHeapObj { +class JNIid: public CHeapObj<mtClass> { friend class VMStructs; private: klassOop _holder; @@ -936,7 +1060,7 @@ // reference must be used because a weak reference would be seen as // collectible. A GrowableArray of PreviousVersionNodes is attached // to the instanceKlass as needed. See PreviousVersionWalker below. -class PreviousVersionNode : public CHeapObj { +class PreviousVersionNode : public CHeapObj<mtClass> { private: // A shared ConstantPool is never collected so we'll always have // a reference to it so we can update items in the cache. We'll @@ -1031,7 +1155,7 @@ // noticed since an nmethod should be removed as many times are it's // added. // -class nmethodBucket: public CHeapObj { +class nmethodBucket: public CHeapObj<mtClass> { friend class VMStructs; private: nmethod* _nmethod; @@ -1052,4 +1176,83 @@ nmethod* get_nmethod() { return _nmethod; } }; +// An iterator that's used to access the inner classes indices in the +// instanceKlass::_inner_classes array. +class InnerClassesIterator : public StackObj { + private: + typeArrayHandle _inner_classes; + int _length; + int _idx; + public: + + InnerClassesIterator(instanceKlassHandle k) { + _inner_classes = k->inner_classes(); + if (k->inner_classes() != NULL) { + _length = _inner_classes->length(); + // The inner class array's length should be the multiple of + // inner_class_next_offset if it only contains the InnerClasses + // attribute data, or it should be + // n*inner_class_next_offset+enclosing_method_attribute_size + // if it also contains the EnclosingMethod data. + assert((_length % instanceKlass::inner_class_next_offset == 0 || + _length % instanceKlass::inner_class_next_offset == instanceKlass::enclosing_method_attribute_size), + "just checking"); + // Remove the enclosing_method portion if exists. + if (_length % instanceKlass::inner_class_next_offset == instanceKlass::enclosing_method_attribute_size) { + _length -= instanceKlass::enclosing_method_attribute_size; + } + } else { + _length = 0; + } + _idx = 0; + } + + int length() const { + return _length; + } + + void next() { + _idx += instanceKlass::inner_class_next_offset; + } + + bool done() const { + return (_idx >= _length); + } + + u2 inner_class_info_index() const { + return _inner_classes->ushort_at( + _idx + instanceKlass::inner_class_inner_class_info_offset); + } + + void set_inner_class_info_index(u2 index) { + _inner_classes->ushort_at_put( + _idx + instanceKlass::inner_class_inner_class_info_offset, index); + } + + u2 outer_class_info_index() const { + return _inner_classes->ushort_at( + _idx + instanceKlass::inner_class_outer_class_info_offset); + } + + void set_outer_class_info_index(u2 index) { + _inner_classes->ushort_at_put( + _idx + instanceKlass::inner_class_outer_class_info_offset, index); + } + + u2 inner_name_index() const { + return _inner_classes->ushort_at( + _idx + instanceKlass::inner_class_inner_name_offset); + } + + void set_inner_name_index(u2 index) { + _inner_classes->ushort_at_put( + _idx + instanceKlass::inner_class_inner_name_offset, index); + } + + u2 inner_access_flags() const { + return _inner_classes->ushort_at( + _idx + instanceKlass::inner_class_access_flags_offset); + } +}; + #endif // SHARE_VM_OOPS_INSTANCEKLASS_HPP