/* * Copyright (c) 1997, 2022, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// A ConstantPool is an array containing class constants as described in the // class file. // // Most of the constant pool entries are written during class parsing, which // is safe. For klass types, the constant pool entry is // modified when the entry is resolved. If a klass constant pool // entry is read without a lock, only the resolved state guarantees that // the entry in the constant pool is a klass object and not a Symbol*.
// This represents a JVM_CONSTANT_Class, JVM_CONSTANT_UnresolvedClass, or // JVM_CONSTANT_UnresolvedClassInError slot in the constant pool. class CPKlassSlot { // cp->symbol_at(_name_index) gives the name of the class. int _name_index;
// cp->_resolved_klasses->at(_resolved_klass_index) gives the Klass* for the class. int _resolved_klass_index; public: enum { // This is used during constant pool merging where the resolved klass index is // not yet known, and will be computed at a later stage (during a call to // initialize_unresolved_klasses()).
_temp_resolved_klass_index = 0xffff
};
CPKlassSlot(int n, int rk) {
_name_index = n;
_resolved_klass_index = rk;
} int name_index() const { return _name_index;
} int resolved_klass_index() const {
assert(_resolved_klass_index != _temp_resolved_klass_index, "constant pool merging was incomplete"); return _resolved_klass_index;
}
};
class ConstantPool : public Metadata { friendclass VMStructs; friendclass JVMCIVMStructs; friendclass BytecodeInterpreter; // Directly extracts a klass in the pool for fast instanceof/checkcast friendclass Universe; // For null constructor friendclass ClassPrelinker; // CDS private: // If you add a new field that points to any metaspace object, you // must add this field to ConstantPool::metaspace_pointers_do().
Array<u1>* _tags; // the tag array describing the constant pool's contents
ConstantPoolCache* _cache; // the cache holding interpreter runtime information
InstanceKlass* _pool_holder; // the corresponding class
Array<u2>* _operands; // for variable-sized (InvokeDynamic) nodes, usually empty
// Consider using an array of compressed klass pointers to // save space on 64-bit platforms.
Array<Klass*>* _resolved_klasses;
u2 _major_version; // major version number of class file
u2 _minor_version; // minor version number of class file
// Constant pool index to the utf8 entry of the Generic signature, // or 0 if none.
u2 _generic_signature_index; // Constant pool index to the utf8 entry for the name of source file // containing this klass, 0 if not specified.
u2 _source_file_name_index;
union { // set for CDS to restore resolved references int _resolved_reference_length; // keeps version number for redefined classes (used in backtrace) int _version;
} _saved;
bool has_preresolution() const { return (_flags & _has_preresolution) != 0; } void set_has_preresolution() {
assert(!is_shared(), "should never be called on shared ConstantPools");
_flags |= _has_preresolution;
}
// minor and major version numbers of class file
u2 major_version() const { return _major_version; } void set_major_version(u2 major_version) { _major_version = major_version; }
u2 minor_version() const { return _minor_version; } void set_minor_version(u2 minor_version) { _minor_version = minor_version; }
// Redefine classes support. If a method referring to this constant pool // is on the executing stack, or as a handle in vm code, this constant pool // can't be removed from the set of previous versions saved in the instance // class. bool on_stack() const; bool is_maybe_on_stack() const; void set_on_stack(constbool value);
// Faster than MetaspaceObj::is_shared() - used by set_on_stack() bool is_shared() const { return (_flags & _is_shared) != 0; }
// Create object cache in the constant pool void initialize_resolved_references(ClassLoaderData* loader_data, const intStack& reference_map, int constant_pool_map_length,
TRAPS);
// resolved strings, methodHandles and callsite objects from the constant pool
objArrayOop resolved_references() const;
objArrayOop resolved_references_or_null() const; // mapping resolved object array indexes to cp indexes and back. int object_to_cp_index(int index) { return reference_map()->at(index); } int cp_to_object_index(int index);
// Invokedynamic indexes. // They must look completely different from normal indexes. // The main reason is that byte swapping is sometimes done on normal indexes. // Finally, it is helpful for debugging to tell the two apart. staticbool is_invokedynamic_index(int i) { return (i < 0); } staticint decode_invokedynamic_index(int i) { assert(is_invokedynamic_index(i), ""); return ~i; } staticint encode_invokedynamic_index(int i) { assert(!is_invokedynamic_index(i), ""); return ~i; }
// The invokedynamic points at a CP cache entry. This entry points back // at the original CP entry (CONSTANT_InvokeDynamic) and also (via f2) at an entry // in the resolved_references array (which provides the appendix argument). int invokedynamic_cp_cache_index(int indy_index) const {
assert(is_invokedynamic_index(indy_index), "should be a invokedynamic index"); int cache_index = decode_invokedynamic_index(indy_index); return cache_index;
}
ConstantPoolCacheEntry* invokedynamic_cp_cache_entry_at(int indy_index) const { // decode index that invokedynamic points to. int cp_cache_index = invokedynamic_cp_cache_index(indy_index); return cache()->entry_at(cp_cache_index);
} // Given the per-instruction index of an indy instruction, report the // main constant pool entry for its bootstrap specifier. // From there, uncached_name/signature_ref_at will get the name/type. int invokedynamic_bootstrap_ref_index_at(int indy_index) const { return invokedynamic_cp_cache_entry_at(indy_index)->constant_pool_index();
}
// For temporary use while constructing constant pool void klass_index_at_put(int which, int name_index) {
tag_at_put(which, JVM_CONSTANT_ClassIndex);
*int_at_addr(which) = name_index;
}
// Hidden class support: void klass_at_put(int class_index, Klass* k);
void unresolved_klass_at_put(int which, int name_index, int resolved_klass_index) {
release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass);
void dynamic_constant_at_put(int which, int bsms_attribute_index, int name_and_type_index) {
tag_at_put(which, JVM_CONSTANT_Dynamic);
*int_at_addr(which) = ((jint) name_and_type_index<<16) | bsms_attribute_index;
}
void invoke_dynamic_at_put(int which, int bsms_attribute_index, int name_and_type_index) {
tag_at_put(which, JVM_CONSTANT_InvokeDynamic);
*int_at_addr(which) = ((jint) name_and_type_index<<16) | bsms_attribute_index;
}
void unresolved_string_at_put(int which, Symbol* s) {
assert(s->refcount() != 0, "should have nonzero refcount"); // Note that release_tag_at_put is not needed here because this is called only // when constructing a ConstantPool in a single thread, with no possibility // of concurrent access.
tag_at_put(which, JVM_CONSTANT_String);
*symbol_at_addr(which) = s;
}
void string_at_put(int which, int obj_index, oop str);
// For temporary use while constructing constant pool void string_index_at_put(int which, int string_index) {
tag_at_put(which, JVM_CONSTANT_StringIndex);
*int_at_addr(which) = string_index;
}
void field_at_put(int which, int class_index, int name_and_type_index) {
tag_at_put(which, JVM_CONSTANT_Fieldref);
*int_at_addr(which) = ((jint) name_and_type_index<<16) | class_index;
}
void method_at_put(int which, int class_index, int name_and_type_index) {
tag_at_put(which, JVM_CONSTANT_Methodref);
*int_at_addr(which) = ((jint) name_and_type_index<<16) | class_index;
}
void interface_method_at_put(int which, int class_index, int name_and_type_index) {
tag_at_put(which, JVM_CONSTANT_InterfaceMethodref);
*int_at_addr(which) = ((jint) name_and_type_index<<16) | class_index; // Not so nice
}
void name_and_type_at_put(int which, int name_index, int signature_index) {
tag_at_put(which, JVM_CONSTANT_NameAndType);
*int_at_addr(which) = ((jint) signature_index<<16) | name_index; // Not so nice
}
CPKlassSlot klass_slot_at(int which) const {
assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(), "Corrupted constant pool"); int value = *int_at_addr(which); int name_index = extract_high_short_from_int(value); int resolved_klass_index = extract_low_short_from_int(value); return CPKlassSlot(name_index, resolved_klass_index);
}
Symbol* klass_name_at(int which) const; // Returns the name, w/o resolving. int klass_name_index_at(int which) const { return klass_slot_at(which).name_index();
}
Klass* resolved_klass_at(int which) const; // Used by Compiler
// RedefineClasses() API support:
Symbol* klass_at_noresolve(int which) { return klass_name_at(which); } void temp_unresolved_klass_at_put(int which, int name_index) { // Used only during constant pool merging for class redefinition. The resolved klass index // will be initialized later by a call to initialize_unresolved_klasses().
unresolved_klass_at_put(which, name_index, CPKlassSlot::_temp_resolved_klass_index);
}
// Version that can be used before string oop array is created.
oop uncached_string_at(int which, TRAPS);
// only called when we are sure a string entry is already resolved (via an // earlier string_at call.
oop resolved_string_at(int which) {
assert(tag_at(which).is_string(), "Corrupted constant pool"); // Must do an acquire here in case another thread resolved the klass // behind our back, lest we later load stale values thru the oop. // we might want a volatile_obj_at in ObjArrayKlass. int obj_index = cp_to_object_index(which); return resolved_references()->obj_at(obj_index);
}
// Returns an UTF8 for a CONSTANT_String entry at a given index. // UTF8 char* representation was chosen to avoid conversion of // java_lang_Strings at resolved entries into Symbol*s // or vice versa. char* string_at_noresolve(int which);
// Derived queries:
Symbol* method_handle_name_ref_at(int which) { int member = method_handle_index_at(which); return impl_name_ref_at(member, true);
}
Symbol* method_handle_signature_ref_at(int which) { int member = method_handle_index_at(which); return impl_signature_ref_at(member, true);
} int method_handle_klass_index_at(int which) { int member = method_handle_index_at(which); return impl_klass_ref_index_at(member, true);
}
Symbol* method_type_signature_at(int which) { int sym = method_type_index_at(which); return symbol_at(sym);
}
int bootstrap_name_and_type_ref_index_at(int which) {
assert(tag_at(which).has_bootstrap(), "Corrupted constant pool"); return extract_high_short_from_int(*int_at_addr(which));
} int bootstrap_methods_attribute_index(int which) {
assert(tag_at(which).has_bootstrap(), "Corrupted constant pool"); return extract_low_short_from_int(*int_at_addr(which));
} int bootstrap_operand_base(int which) { int bsms_attribute_index = bootstrap_methods_attribute_index(which); return operand_offset_at(operands(), bsms_attribute_index);
} // The first part of the operands array consists of an index into the second part. // Extract a 32-bit index value from the first part. staticint operand_offset_at(Array<u2>* operands, int bsms_attribute_index) { int n = (bsms_attribute_index * 2);
assert(n >= 0 && n+2 <= operands->length(), "oob"); // The first 32-bit index points to the beginning of the second part // of the operands array. Make sure this index is in the first part.
DEBUG_ONLY(int second_part = build_int_from_shorts(operands->at(0),
operands->at(1)));
assert(second_part == 0 || n+2 <= second_part, "oob (2)"); int offset = build_int_from_shorts(operands->at(n+0),
operands->at(n+1)); // The offset itself must point into the second part of the array.
assert(offset == 0 || offset >= second_part && offset <= operands->length(), "oob (3)"); return offset;
} staticvoid operand_offset_at_put(Array<u2>* operands, int bsms_attribute_index, int offset) { int n = bsms_attribute_index * 2;
assert(n >= 0 && n+2 <= operands->length(), "oob");
operands->at_put(n+0, extract_low_short_from_int(offset));
operands->at_put(n+1, extract_high_short_from_int(offset));
} staticint operand_array_length(Array<u2>* operands) { if (operands == NULL || operands->length() == 0) return 0; int second_part = operand_offset_at(operands, 0); return (second_part / 2);
}
#ifdef ASSERT // operand tuples fit together exactly, end to end staticint operand_limit_at(Array<u2>* operands, int bsms_attribute_index) { int nextidx = bsms_attribute_index + 1; if (nextidx == operand_array_length(operands)) return operands->length(); else return operand_offset_at(operands, nextidx);
} int bootstrap_operand_limit(int which) { int bsms_attribute_index = bootstrap_methods_attribute_index(which); return operand_limit_at(operands(), bsms_attribute_index);
} #endif//ASSERT
// Layout of InvokeDynamic and Dynamic bootstrap method specifier // data in second part of operands array. This encodes one record in // the BootstrapMethods attribute. The whole specifier also includes // the name and type information from the main constant pool entry. enum {
_indy_bsm_offset = 0, // CONSTANT_MethodHandle bsm
_indy_argc_offset = 1, // u2 argc
_indy_argv_offset = 2 // u2 argv[argc]
};
// These functions are used in RedefineClasses for CP merge
int operand_offset_at(int bsms_attribute_index) {
assert(0 <= bsms_attribute_index &&
bsms_attribute_index < operand_array_length(operands()), "Corrupted CP operands"); return operand_offset_at(operands(), bsms_attribute_index);
} int operand_bootstrap_method_ref_index_at(int bsms_attribute_index) { int offset = operand_offset_at(bsms_attribute_index); return operands()->at(offset + _indy_bsm_offset);
} int operand_argument_count_at(int bsms_attribute_index) { int offset = operand_offset_at(bsms_attribute_index); int argc = operands()->at(offset + _indy_argc_offset); return argc;
} int operand_argument_index_at(int bsms_attribute_index, int j) { int offset = operand_offset_at(bsms_attribute_index); return operands()->at(offset + _indy_argv_offset + j);
} int operand_next_offset_at(int bsms_attribute_index) { int offset = operand_offset_at(bsms_attribute_index) + _indy_argv_offset
+ operand_argument_count_at(bsms_attribute_index); return offset;
} // Compare a bootstrap specifier data in the operands arrays bool compare_operand_to(int bsms_attribute_index1, const constantPoolHandle& cp2, int bsms_attribute_index2); // Find a bootstrap specifier data in the operands array int find_matching_operand(int bsms_attribute_index, const constantPoolHandle& search_cp, int operands_cur_len); // Resize the operands array with delta_len and delta_size void resize_operands(int delta_len, int delta_size, TRAPS); // Extend the operands array with the length and size of the ext_cp operands void extend_operands(const constantPoolHandle& ext_cp, TRAPS); // Shrink the operands array to a smaller array with new_len length void shrink_operands(int new_len, TRAPS);
int bootstrap_method_ref_index_at(int which) {
assert(tag_at(which).has_bootstrap(), "Corrupted constant pool"); int op_base = bootstrap_operand_base(which); return operands()->at(op_base + _indy_bsm_offset);
} int bootstrap_argument_count_at(int which) {
assert(tag_at(which).has_bootstrap(), "Corrupted constant pool"); int op_base = bootstrap_operand_base(which); int argc = operands()->at(op_base + _indy_argc_offset);
DEBUG_ONLY(int end_offset = op_base + _indy_argv_offset + argc; int next_offset = bootstrap_operand_limit(which));
assert(end_offset == next_offset, "matched ending"); return argc;
} int bootstrap_argument_index_at(int which, int j) { int op_base = bootstrap_operand_base(which);
DEBUG_ONLY(int argc = operands()->at(op_base + _indy_argc_offset));
assert((uint)j < (uint)argc, "oob"); return operands()->at(op_base + _indy_argv_offset + j);
}
// The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve, // name_and_type_ref_index_at) all expect to be passed indices obtained // directly from the bytecode. // If the indices are meant to refer to fields or methods, they are // actually rewritten constant pool cache indices. // The routine remap_instruction_operand_from_cache manages the adjustment // of these values back to constant pool indices.
// There are also "uncached" versions which do not adjust the operand index; see below.
// FIXME: Consider renaming these with a prefix "cached_" to make the distinction clear. // In a few cases (the verifier) there are uses before a cpcache has been built, // which are handled by a dynamic check in remap_instruction_operand_from_cache. // FIXME: Remove the dynamic check, and adjust all callers to specify the correct mode.
// Lookup for entries consisting of (name_index, signature_index) int name_ref_index_at(int which_nt); // == low-order jshort of name_and_type_at(which_nt) int signature_ref_index_at(int which_nt); // == high-order jshort of name_and_type_at(which_nt)
// Get the tag for a constant, which may involve a constant dynamic
constantTag constant_tag_at(int which); // Get the basic type for a constant, which may involve a constant dynamic
BasicType basic_type_for_constant_at(int which);
// Used by CDS. These classes need to access the private ConstantPool() constructor. template <class T> friendclass CppVtableTesterA; template <class T> friendclass CppVtableTesterB; template <class T> friendclass CppVtableCloner;
// Used by compiler to prevent classloading. static Method* method_at_if_loaded (const constantPoolHandle& this_cp, int which); staticbool has_appendix_at_if_loaded (const constantPoolHandle& this_cp, int which); static oop appendix_at_if_loaded (const constantPoolHandle& this_cp, int which); staticbool has_local_signature_at_if_loaded (const constantPoolHandle& this_cp, int which); static Klass* klass_at_if_loaded (const constantPoolHandle& this_cp, int which);
// Routines currently used for annotations (only called by jvm.cpp) but which might be used in the // future by other Java code. These take constant pool indices rather than // constant pool cache indices as do the peer methods above.
Symbol* uncached_klass_ref_at_noresolve(int which);
Symbol* uncached_name_ref_at(int which) { return impl_name_ref_at(which, true); }
Symbol* uncached_signature_ref_at(int which) { return impl_signature_ref_at(which, true); } int uncached_klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, true); } int uncached_name_and_type_ref_index_at(int which) { return impl_name_and_type_ref_index_at(which, true); }
#ifdef ASSERT enum { CPCACHE_INDEX_TAG = 0x10000 }; // helps keep CP cache indices distinct from CP indices #else enum { CPCACHE_INDEX_TAG = 0 }; // in product mode, this zero value is a no-op #endif//ASSERT
int impl_klass_ref_index_at(int which, bool uncached); int impl_name_and_type_ref_index_at(int which, bool uncached);
constantTag impl_tag_ref_at(int which, bool uncached);
// Used while constructing constant pool (only by ClassFileParser)
jint klass_index_at(int which) {
assert(tag_at(which).is_klass_index(), "Corrupted constant pool"); return *int_at_addr(which);
}
// Implementation of methods that needs an exposed 'this' pointer, in order to // handle GC while executing the method static Klass* klass_at_impl(const constantPoolHandle& this_cp, int which, TRAPS); static oop string_at_impl(const constantPoolHandle& this_cp, int which, int obj_index, TRAPS);
// Copy cpool bytes into byte array. // Returns: // int > 0, count of the raw cpool bytes that have been copied // 0, OutOfMemory error // -1, Internal error int copy_cpool_bytes(int cpool_size,
SymbolHash* tbl, unsignedchar *bytes);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.