mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8171392: Move Klass pointers outside of ConstantPool entries so ConstantPool can be read-only
Added _resolved_klasses; moved _resolved_references to ConstantPoolCache, etc. Reviewed-by: coleenp, lfoltan, simonis, aph
This commit is contained in:
parent
0c74ceb12d
commit
c386cec7b1
32 changed files with 527 additions and 231 deletions
|
@ -391,6 +391,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
|||
}
|
||||
|
||||
int index = 1; // declared outside of loops for portability
|
||||
int num_klasses = 0;
|
||||
|
||||
// first verification pass - validate cross references
|
||||
// and fixup class and string constants
|
||||
|
@ -459,7 +460,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
|||
check_property(valid_symbol_at(class_index),
|
||||
"Invalid constant pool index %u in class file %s",
|
||||
class_index, CHECK);
|
||||
cp->unresolved_klass_at_put(index, cp->symbol_at(class_index));
|
||||
cp->unresolved_klass_at_put(index, class_index, num_klasses++);
|
||||
break;
|
||||
}
|
||||
case JVM_CONSTANT_StringIndex: {
|
||||
|
@ -550,8 +551,19 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
|||
} // switch(tag)
|
||||
} // end of for
|
||||
|
||||
_first_patched_klass_resolved_index = num_klasses;
|
||||
cp->allocate_resolved_klasses(_loader_data, num_klasses + _max_num_patched_klasses, CHECK);
|
||||
|
||||
if (_cp_patches != NULL) {
|
||||
// need to treat this_class specially...
|
||||
|
||||
// Add dummy utf8 entries in the space reserved for names of patched classes. We'll use "*"
|
||||
// for now. These will be replaced with actual names of the patched classes in patch_class().
|
||||
Symbol* s = vmSymbols::star_name();
|
||||
for (int n=_orig_cp_size; n<cp->length(); n++) {
|
||||
cp->symbol_at_put(n, s);
|
||||
}
|
||||
|
||||
int this_class_index;
|
||||
{
|
||||
stream->guarantee_more(8, CHECK); // flags, this_class, super_class, infs_len
|
||||
|
@ -701,6 +713,14 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
|||
} // end of for
|
||||
}
|
||||
|
||||
void ClassFileParser::patch_class(ConstantPool* cp, int class_index, Klass* k, Symbol* name) {
|
||||
int name_index = _orig_cp_size + _num_patched_klasses;
|
||||
int resolved_klass_index = _first_patched_klass_resolved_index + _num_patched_klasses;
|
||||
|
||||
cp->klass_at_put(class_index, name_index, resolved_klass_index, k, name);
|
||||
_num_patched_klasses ++;
|
||||
}
|
||||
|
||||
void ClassFileParser::patch_constant_pool(ConstantPool* cp,
|
||||
int index,
|
||||
Handle patch,
|
||||
|
@ -718,13 +738,14 @@ void ClassFileParser::patch_constant_pool(ConstantPool* cp,
|
|||
guarantee_property(!java_lang_Class::is_primitive(patch()),
|
||||
"Illegal class patch at %d in class file %s",
|
||||
index, CHECK);
|
||||
cp->klass_at_put(index, java_lang_Class::as_Klass(patch()));
|
||||
Klass* k = java_lang_Class::as_Klass(patch());
|
||||
patch_class(cp, index, k, k->name());
|
||||
} else {
|
||||
guarantee_property(java_lang_String::is_instance(patch()),
|
||||
"Illegal class patch at %d in class file %s",
|
||||
index, CHECK);
|
||||
Symbol* const name = java_lang_String::as_symbol(patch(), CHECK);
|
||||
cp->unresolved_klass_at_put(index, name);
|
||||
patch_class(cp, index, NULL, name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -5340,8 +5361,14 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa
|
|||
ik->set_name(_class_name);
|
||||
|
||||
if (is_anonymous()) {
|
||||
// I am well known to myself
|
||||
ik->constants()->klass_at_put(_this_class_index, ik); // eagerly resolve
|
||||
// _this_class_index is a CONSTANT_Class entry that refers to this
|
||||
// anonymous class itself. If this class needs to refer to its own methods or
|
||||
// fields, it would use a CONSTANT_MethodRef, etc, which would reference
|
||||
// _this_class_index. However, because this class is anonymous (it's
|
||||
// not stored in SystemDictionary), _this_class_index cannot be resolved
|
||||
// with ConstantPool::klass_at_impl, which does a SystemDictionary lookup.
|
||||
// Therefore, we must eagerly resolve _this_class_index now.
|
||||
ik->constants()->klass_at_put(_this_class_index, ik);
|
||||
}
|
||||
|
||||
ik->set_minor_version(_minor_version);
|
||||
|
@ -5577,6 +5604,10 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
|
|||
_loader_data(loader_data),
|
||||
_host_klass(host_klass),
|
||||
_cp_patches(cp_patches),
|
||||
_num_patched_klasses(0),
|
||||
_max_num_patched_klasses(0),
|
||||
_orig_cp_size(0),
|
||||
_first_patched_klass_resolved_index(0),
|
||||
_super_klass(),
|
||||
_cp(NULL),
|
||||
_fields(NULL),
|
||||
|
@ -5647,6 +5678,25 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
|
|||
_need_verify = Verifier::should_verify_for(_loader_data->class_loader(),
|
||||
stream->need_verify());
|
||||
}
|
||||
if (_cp_patches != NULL) {
|
||||
int len = _cp_patches->length();
|
||||
for (int i=0; i<len; i++) {
|
||||
if (has_cp_patch_at(i)) {
|
||||
Handle patch = cp_patch_at(i);
|
||||
if (java_lang_String::is_instance(patch()) || java_lang_Class::is_instance(patch())) {
|
||||
// We need to append the names of the patched classes to the end of the constant pool,
|
||||
// because a patched class may have a Utf8 name that's not already included in the
|
||||
// original constant pool. These class names are used when patch_constant_pool()
|
||||
// calls patch_class().
|
||||
//
|
||||
// Note that a String in cp_patch_at(i) may be used to patch a Utf8, a String, or a Class.
|
||||
// At this point, we don't know the tag for index i yet, because we haven't parsed the
|
||||
// constant pool. So we can only assume the worst -- every String is used to patch a Class.
|
||||
_max_num_patched_klasses++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// synch back verification state to stream
|
||||
stream->set_verify(_need_verify);
|
||||
|
@ -5776,19 +5826,25 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
|
|||
}
|
||||
|
||||
stream->guarantee_more(3, CHECK); // length, first cp tag
|
||||
const u2 cp_size = stream->get_u2_fast();
|
||||
u2 cp_size = stream->get_u2_fast();
|
||||
|
||||
guarantee_property(
|
||||
cp_size >= 1, "Illegal constant pool size %u in class file %s",
|
||||
cp_size, CHECK);
|
||||
|
||||
_orig_cp_size = cp_size;
|
||||
if (int(cp_size) + _max_num_patched_klasses > 0xffff) {
|
||||
THROW_MSG(vmSymbols::java_lang_InternalError(), "not enough space for patched classes");
|
||||
}
|
||||
cp_size += _max_num_patched_klasses;
|
||||
|
||||
_cp = ConstantPool::allocate(_loader_data,
|
||||
cp_size,
|
||||
CHECK);
|
||||
|
||||
ConstantPool* const cp = _cp;
|
||||
|
||||
parse_constant_pool(stream, cp, cp_size, CHECK);
|
||||
parse_constant_pool(stream, cp, _orig_cp_size, CHECK);
|
||||
|
||||
assert(cp_size == (const u2)cp->length(), "invariant");
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue