Description
As of JDK9, after a ConstantPool is initialized, most of its entries are not modified at run time, even if constant pool resolution takes place. For example, when a FieldRef entry is resolved, additional data is written into the ConstantPoolCache, while the ConstantPool itself is unmodified.
The only exception is Class entries. When a Class entry is resolved in ConstantPool::klass_at_impl, the content of the entry is modified from a Symbol* to a Klass*. This causes a store into the address &ConstantPool::base[which] -- see the function ConstantPool::slot_at_put() in the JDK9 source code.
Outline:
A class constant is represented in the classfile as a CONSTANT_ClassIndex entry, which has a 2 byte value (an index to a CONSTANT_Utf8 entry, which is the name of the class).
During class file parsing, CONSTANT_ClassIndex entries are rewritten to CONSTANT_UnresolvedClass entries. In JDK 9, A CONSTANT_UnresolvedClass entry is represented by a Symbol* (with some lower bits set .. see CPSlot in constantPool.hpp). After class resolution, the CONSTANT_UnresolvedClass entry is changed to a CONSTANT_Class entry, and its content is changed to a Klass*.
The proposal is to change the representation of both CONSTANT_UnresolvedClass and CONSTANT_Class to be a pair of 16-bit unsigned integers:
class ConstantPool {
Array<Klass*>* _resolved_klass;
Klass* resolved_klass_at(int which) const { // Used by Compiler
guarantee(tag_at(which).is_klass(), "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.
int value = *int_at_addr(which);
int resolved_klass_index = extract_low_short_from_int(value);
int name_index = extract_high_short_from_int(value);
assert(tag_at(name_index).is_symbol(), "sanity");
Klass** adr = _resolved_klasses->adr_at(resolved_klass_index);
return (Klass*)OrderAccess::load_ptr_acquire(adr);
}
The name_index is the same value as in the original CONSTANT_ClassIndex entry -- i.e., the name of the class.
The resolved_klass_index is an unique index in the _resolved_klass for this particular entry. _resolved_klass is allocated during class file parsing, and its length equals to the number of CONSTANT_ClassIndex entries in the input class file.
+ If the class is not yet resolved, _resolved_klasses[resolved_klass_index] is NULL.
+ If the class is successfully resolved, _resolved_klasses[resolved_klass_index] contains the Klass pointer to this class.
Note that the value of this entry (i.e., *int_at_addr(which)), is unchanged during resolution of this entry.
The only exception is Class entries. When a Class entry is resolved in ConstantPool::klass_at_impl, the content of the entry is modified from a Symbol* to a Klass*. This causes a store into the address &ConstantPool::base[which] -- see the function ConstantPool::slot_at_put() in the JDK9 source code.
Outline:
A class constant is represented in the classfile as a CONSTANT_ClassIndex entry, which has a 2 byte value (an index to a CONSTANT_Utf8 entry, which is the name of the class).
During class file parsing, CONSTANT_ClassIndex entries are rewritten to CONSTANT_UnresolvedClass entries. In JDK 9, A CONSTANT_UnresolvedClass entry is represented by a Symbol* (with some lower bits set .. see CPSlot in constantPool.hpp). After class resolution, the CONSTANT_UnresolvedClass entry is changed to a CONSTANT_Class entry, and its content is changed to a Klass*.
The proposal is to change the representation of both CONSTANT_UnresolvedClass and CONSTANT_Class to be a pair of 16-bit unsigned integers:
class ConstantPool {
Array<Klass*>* _resolved_klass;
Klass* resolved_klass_at(int which) const { // Used by Compiler
guarantee(tag_at(which).is_klass(), "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.
int value = *int_at_addr(which);
int resolved_klass_index = extract_low_short_from_int(value);
int name_index = extract_high_short_from_int(value);
assert(tag_at(name_index).is_symbol(), "sanity");
Klass** adr = _resolved_klasses->adr_at(resolved_klass_index);
return (Klass*)OrderAccess::load_ptr_acquire(adr);
}
The name_index is the same value as in the original CONSTANT_ClassIndex entry -- i.e., the name of the class.
The resolved_klass_index is an unique index in the _resolved_klass for this particular entry. _resolved_klass is allocated during class file parsing, and its length equals to the number of CONSTANT_ClassIndex entries in the input class file.
+ If the class is not yet resolved, _resolved_klasses[resolved_klass_index] is NULL.
+ If the class is successfully resolved, _resolved_klasses[resolved_klass_index] contains the Klass pointer to this class.
Note that the value of this entry (i.e., *int_at_addr(which)), is unchanged during resolution of this entry.
Attachments
Issue Links
- relates to
-
JDK-8179769 serviceability/sa/TestCpoolForInvokeDynamic.java failing after changes for JDK-8171392
-
- Closed
-
-
JDK-8172987 Change ConstantPool entry size from 64 bits to 32 bits
-
- Closed
-