mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
7086585: make Java field injection more flexible
Reviewed-by: jrose, twisti, kvn, coleenp
This commit is contained in:
parent
1ebca30d26
commit
e39ba1a5fe
39 changed files with 1073 additions and 991 deletions
|
@ -36,6 +36,7 @@
|
|||
#include "memory/oopFactory.hpp"
|
||||
#include "memory/universe.inline.hpp"
|
||||
#include "oops/constantPoolOop.hpp"
|
||||
#include "oops/fieldStreams.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/instanceMirrorKlass.hpp"
|
||||
#include "oops/klass.inline.hpp"
|
||||
|
@ -991,42 +992,98 @@ enum FieldAllocationType {
|
|||
STATIC_BYTE, // Boolean, Byte, char
|
||||
STATIC_SHORT, // shorts
|
||||
STATIC_WORD, // ints
|
||||
STATIC_DOUBLE, // long or double
|
||||
STATIC_ALIGNED_DOUBLE,// aligned long or double
|
||||
STATIC_DOUBLE, // aligned long or double
|
||||
NONSTATIC_OOP,
|
||||
NONSTATIC_BYTE,
|
||||
NONSTATIC_SHORT,
|
||||
NONSTATIC_WORD,
|
||||
NONSTATIC_DOUBLE,
|
||||
NONSTATIC_ALIGNED_DOUBLE
|
||||
MAX_FIELD_ALLOCATION_TYPE,
|
||||
BAD_ALLOCATION_TYPE = -1
|
||||
};
|
||||
|
||||
static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = {
|
||||
BAD_ALLOCATION_TYPE, // 0
|
||||
BAD_ALLOCATION_TYPE, // 1
|
||||
BAD_ALLOCATION_TYPE, // 2
|
||||
BAD_ALLOCATION_TYPE, // 3
|
||||
NONSTATIC_BYTE , // T_BOOLEAN = 4,
|
||||
NONSTATIC_SHORT, // T_CHAR = 5,
|
||||
NONSTATIC_WORD, // T_FLOAT = 6,
|
||||
NONSTATIC_DOUBLE, // T_DOUBLE = 7,
|
||||
NONSTATIC_BYTE, // T_BYTE = 8,
|
||||
NONSTATIC_SHORT, // T_SHORT = 9,
|
||||
NONSTATIC_WORD, // T_INT = 10,
|
||||
NONSTATIC_DOUBLE, // T_LONG = 11,
|
||||
NONSTATIC_OOP, // T_OBJECT = 12,
|
||||
NONSTATIC_OOP, // T_ARRAY = 13,
|
||||
BAD_ALLOCATION_TYPE, // T_VOID = 14,
|
||||
BAD_ALLOCATION_TYPE, // T_ADDRESS = 15,
|
||||
BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16,
|
||||
BAD_ALLOCATION_TYPE, // T_CONFLICT = 17,
|
||||
BAD_ALLOCATION_TYPE, // 0
|
||||
BAD_ALLOCATION_TYPE, // 1
|
||||
BAD_ALLOCATION_TYPE, // 2
|
||||
BAD_ALLOCATION_TYPE, // 3
|
||||
STATIC_BYTE , // T_BOOLEAN = 4,
|
||||
STATIC_SHORT, // T_CHAR = 5,
|
||||
STATIC_WORD, // T_FLOAT = 6,
|
||||
STATIC_DOUBLE, // T_DOUBLE = 7,
|
||||
STATIC_BYTE, // T_BYTE = 8,
|
||||
STATIC_SHORT, // T_SHORT = 9,
|
||||
STATIC_WORD, // T_INT = 10,
|
||||
STATIC_DOUBLE, // T_LONG = 11,
|
||||
STATIC_OOP, // T_OBJECT = 12,
|
||||
STATIC_OOP, // T_ARRAY = 13,
|
||||
BAD_ALLOCATION_TYPE, // T_VOID = 14,
|
||||
BAD_ALLOCATION_TYPE, // T_ADDRESS = 15,
|
||||
BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16,
|
||||
BAD_ALLOCATION_TYPE, // T_CONFLICT = 17,
|
||||
};
|
||||
|
||||
static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) {
|
||||
assert(type >= T_BOOLEAN && type < T_VOID, "only allowable values");
|
||||
FieldAllocationType result = _basic_type_to_atype[type + (is_static ? (T_CONFLICT + 1) : 0)];
|
||||
assert(result != BAD_ALLOCATION_TYPE, "bad type");
|
||||
return result;
|
||||
}
|
||||
|
||||
class FieldAllocationCount: public ResourceObj {
|
||||
public:
|
||||
unsigned int count[MAX_FIELD_ALLOCATION_TYPE];
|
||||
|
||||
FieldAllocationCount() {
|
||||
for (int i = 0; i < MAX_FIELD_ALLOCATION_TYPE; i++) {
|
||||
count[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FieldAllocationType update(bool is_static, BasicType type) {
|
||||
FieldAllocationType atype = basic_type_to_atype(is_static, type);
|
||||
count[atype]++;
|
||||
return atype;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct FieldAllocationCount {
|
||||
unsigned int static_oop_count;
|
||||
unsigned int static_byte_count;
|
||||
unsigned int static_short_count;
|
||||
unsigned int static_word_count;
|
||||
unsigned int static_double_count;
|
||||
unsigned int nonstatic_oop_count;
|
||||
unsigned int nonstatic_byte_count;
|
||||
unsigned int nonstatic_short_count;
|
||||
unsigned int nonstatic_word_count;
|
||||
unsigned int nonstatic_double_count;
|
||||
};
|
||||
|
||||
typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_interface,
|
||||
struct FieldAllocationCount *fac,
|
||||
objArrayHandle* fields_annotations, TRAPS) {
|
||||
typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name,
|
||||
constantPoolHandle cp, bool is_interface,
|
||||
FieldAllocationCount *fac,
|
||||
objArrayHandle* fields_annotations,
|
||||
int* java_fields_count_ptr, TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
typeArrayHandle nullHandle;
|
||||
cfs->guarantee_more(2, CHECK_(nullHandle)); // length
|
||||
u2 length = cfs->get_u2_fast();
|
||||
*java_fields_count_ptr = length;
|
||||
|
||||
int num_injected = 0;
|
||||
InjectedField* injected = JavaClasses::get_injected(class_name, &num_injected);
|
||||
|
||||
// Tuples of shorts [access, name index, sig index, initial value index, byte offset, generic signature index]
|
||||
typeArrayOop new_fields = oopFactory::new_permanent_shortArray(length*instanceKlass::next_offset, CHECK_(nullHandle));
|
||||
typeArrayOop new_fields = oopFactory::new_permanent_shortArray((length + num_injected) * FieldInfo::field_slots, CHECK_(nullHandle));
|
||||
typeArrayHandle fields(THREAD, new_fields);
|
||||
|
||||
int index = 0;
|
||||
typeArrayHandle field_annotations;
|
||||
for (int n = 0; n < length; n++) {
|
||||
cfs->guarantee_more(8, CHECK_(nullHandle)); // access_flags, name_index, descriptor_index, attributes_count
|
||||
|
@ -1077,93 +1134,77 @@ typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_int
|
|||
}
|
||||
}
|
||||
|
||||
fields->short_at_put(index++, access_flags.as_short());
|
||||
fields->short_at_put(index++, name_index);
|
||||
fields->short_at_put(index++, signature_index);
|
||||
fields->short_at_put(index++, constantvalue_index);
|
||||
FieldInfo* field = FieldInfo::from_field_array(fields(), n);
|
||||
field->initialize(access_flags.as_short(),
|
||||
name_index,
|
||||
signature_index,
|
||||
constantvalue_index,
|
||||
generic_signature_index,
|
||||
0);
|
||||
|
||||
BasicType type = cp->basic_type_for_signature_at(signature_index);
|
||||
|
||||
// Remember how many oops we encountered and compute allocation type
|
||||
BasicType type = cp->basic_type_for_signature_at(signature_index);
|
||||
FieldAllocationType atype;
|
||||
if ( is_static ) {
|
||||
switch ( type ) {
|
||||
case T_BOOLEAN:
|
||||
case T_BYTE:
|
||||
fac->static_byte_count++;
|
||||
atype = STATIC_BYTE;
|
||||
break;
|
||||
case T_LONG:
|
||||
case T_DOUBLE:
|
||||
if (Universe::field_type_should_be_aligned(type)) {
|
||||
atype = STATIC_ALIGNED_DOUBLE;
|
||||
} else {
|
||||
atype = STATIC_DOUBLE;
|
||||
}
|
||||
fac->static_double_count++;
|
||||
break;
|
||||
case T_CHAR:
|
||||
case T_SHORT:
|
||||
fac->static_short_count++;
|
||||
atype = STATIC_SHORT;
|
||||
break;
|
||||
case T_FLOAT:
|
||||
case T_INT:
|
||||
fac->static_word_count++;
|
||||
atype = STATIC_WORD;
|
||||
break;
|
||||
case T_ARRAY:
|
||||
case T_OBJECT:
|
||||
fac->static_oop_count++;
|
||||
atype = STATIC_OOP;
|
||||
break;
|
||||
case T_ADDRESS:
|
||||
case T_VOID:
|
||||
default:
|
||||
assert(0, "bad field type");
|
||||
}
|
||||
} else {
|
||||
switch ( type ) {
|
||||
case T_BOOLEAN:
|
||||
case T_BYTE:
|
||||
fac->nonstatic_byte_count++;
|
||||
atype = NONSTATIC_BYTE;
|
||||
break;
|
||||
case T_LONG:
|
||||
case T_DOUBLE:
|
||||
if (Universe::field_type_should_be_aligned(type)) {
|
||||
atype = NONSTATIC_ALIGNED_DOUBLE;
|
||||
} else {
|
||||
atype = NONSTATIC_DOUBLE;
|
||||
}
|
||||
fac->nonstatic_double_count++;
|
||||
break;
|
||||
case T_CHAR:
|
||||
case T_SHORT:
|
||||
fac->nonstatic_short_count++;
|
||||
atype = NONSTATIC_SHORT;
|
||||
break;
|
||||
case T_FLOAT:
|
||||
case T_INT:
|
||||
fac->nonstatic_word_count++;
|
||||
atype = NONSTATIC_WORD;
|
||||
break;
|
||||
case T_ARRAY:
|
||||
case T_OBJECT:
|
||||
fac->nonstatic_oop_count++;
|
||||
atype = NONSTATIC_OOP;
|
||||
break;
|
||||
case T_ADDRESS:
|
||||
case T_VOID:
|
||||
default:
|
||||
assert(0, "bad field type");
|
||||
}
|
||||
}
|
||||
FieldAllocationType atype = fac->update(is_static, type);
|
||||
|
||||
// The correct offset is computed later (all oop fields will be located together)
|
||||
// We temporarily store the allocation type in the offset field
|
||||
fields->short_at_put(index++, atype);
|
||||
fields->short_at_put(index++, 0); // Clear out high word of byte offset
|
||||
fields->short_at_put(index++, generic_signature_index);
|
||||
field->set_offset(atype);
|
||||
}
|
||||
|
||||
if (num_injected != 0) {
|
||||
int index = length;
|
||||
for (int n = 0; n < num_injected; n++) {
|
||||
// Check for duplicates
|
||||
if (injected[n].may_be_java) {
|
||||
Symbol* name = injected[n].name();
|
||||
Symbol* signature = injected[n].signature();
|
||||
bool duplicate = false;
|
||||
for (int i = 0; i < length; i++) {
|
||||
FieldInfo* f = FieldInfo::from_field_array(fields(), i);
|
||||
if (name == cp->symbol_at(f->name_index()) &&
|
||||
signature == cp->symbol_at(f->signature_index())) {
|
||||
// Symbol is desclared in Java so skip this one
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (duplicate) {
|
||||
// These will be removed from the field array at the end
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Injected field
|
||||
FieldInfo* field = FieldInfo::from_field_array(fields(), index);
|
||||
field->initialize(JVM_ACC_FIELD_INTERNAL,
|
||||
injected[n].name_index,
|
||||
injected[n].signature_index,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
|
||||
BasicType type = FieldType::basic_type(injected[n].signature());
|
||||
|
||||
// Remember how many oops we encountered and compute allocation type
|
||||
FieldAllocationType atype = fac->update(false, type);
|
||||
|
||||
// The correct offset is computed later (all oop fields will be located together)
|
||||
// We temporarily store the allocation type in the offset field
|
||||
field->set_offset(atype);
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index < length + num_injected) {
|
||||
// sometimes injected fields already exist in the Java source so
|
||||
// the fields array could be too long. In that case trim the
|
||||
// fields array.
|
||||
new_fields = oopFactory::new_permanent_shortArray(index * FieldInfo::field_slots, CHECK_(nullHandle));
|
||||
for (int i = 0; i < index * FieldInfo::field_slots; i++) {
|
||||
new_fields->short_at_put(i, fields->short_at(i));
|
||||
}
|
||||
fields = new_fields;
|
||||
}
|
||||
}
|
||||
|
||||
if (_need_verify && length > 1) {
|
||||
|
@ -1175,11 +1216,9 @@ typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_int
|
|||
bool dup = false;
|
||||
{
|
||||
debug_only(No_Safepoint_Verifier nsv;)
|
||||
for (int i = 0; i < length*instanceKlass::next_offset; i += instanceKlass::next_offset) {
|
||||
int name_index = fields->ushort_at(i + instanceKlass::name_index_offset);
|
||||
Symbol* name = cp->symbol_at(name_index);
|
||||
int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset);
|
||||
Symbol* sig = cp->symbol_at(sig_index);
|
||||
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
|
||||
Symbol* name = fs.name();
|
||||
Symbol* sig = fs.signature();
|
||||
// If no duplicates, add name/signature in hashtable names_and_sigs.
|
||||
if (!put_after_lookup(name, sig, names_and_sigs)) {
|
||||
dup = true;
|
||||
|
@ -2592,227 +2631,6 @@ typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annota
|
|||
}
|
||||
|
||||
|
||||
void ClassFileParser::java_lang_ref_Reference_fix_pre(typeArrayHandle* fields_ptr,
|
||||
constantPoolHandle cp, FieldAllocationCount *fac_ptr, TRAPS) {
|
||||
// This code is for compatibility with earlier jdk's that do not
|
||||
// have the "discovered" field in java.lang.ref.Reference. For 1.5
|
||||
// the check for the "discovered" field should issue a warning if
|
||||
// the field is not found. For 1.6 this code should be issue a
|
||||
// fatal error if the "discovered" field is not found.
|
||||
//
|
||||
// Increment fac.nonstatic_oop_count so that the start of the
|
||||
// next type of non-static oops leaves room for the fake oop.
|
||||
// Do not increment next_nonstatic_oop_offset so that the
|
||||
// fake oop is place after the java.lang.ref.Reference oop
|
||||
// fields.
|
||||
//
|
||||
// Check the fields in java.lang.ref.Reference for the "discovered"
|
||||
// field. If it is not present, artifically create a field for it.
|
||||
// This allows this VM to run on early JDK where the field is not
|
||||
// present.
|
||||
int reference_sig_index = 0;
|
||||
int reference_name_index = 0;
|
||||
int reference_index = 0;
|
||||
int extra = java_lang_ref_Reference::number_of_fake_oop_fields;
|
||||
const int n = (*fields_ptr)()->length();
|
||||
for (int i = 0; i < n; i += instanceKlass::next_offset ) {
|
||||
int name_index =
|
||||
(*fields_ptr)()->ushort_at(i + instanceKlass::name_index_offset);
|
||||
int sig_index =
|
||||
(*fields_ptr)()->ushort_at(i + instanceKlass::signature_index_offset);
|
||||
Symbol* f_name = cp->symbol_at(name_index);
|
||||
Symbol* f_sig = cp->symbol_at(sig_index);
|
||||
if (f_sig == vmSymbols::reference_signature() && reference_index == 0) {
|
||||
// Save the index for reference signature for later use.
|
||||
// The fake discovered field does not entries in the
|
||||
// constant pool so the index for its signature cannot
|
||||
// be extracted from the constant pool. It will need
|
||||
// later, however. It's signature is vmSymbols::reference_signature()
|
||||
// so same an index for that signature.
|
||||
reference_sig_index = sig_index;
|
||||
reference_name_index = name_index;
|
||||
reference_index = i;
|
||||
}
|
||||
if (f_name == vmSymbols::reference_discovered_name() &&
|
||||
f_sig == vmSymbols::reference_signature()) {
|
||||
// The values below are fake but will force extra
|
||||
// non-static oop fields and a corresponding non-static
|
||||
// oop map block to be allocated.
|
||||
extra = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (extra != 0) {
|
||||
fac_ptr->nonstatic_oop_count += extra;
|
||||
// Add the additional entry to "fields" so that the klass
|
||||
// contains the "discoverd" field and the field will be initialized
|
||||
// in instances of the object.
|
||||
int fields_with_fix_length = (*fields_ptr)()->length() +
|
||||
instanceKlass::next_offset;
|
||||
typeArrayOop ff = oopFactory::new_permanent_shortArray(
|
||||
fields_with_fix_length, CHECK);
|
||||
typeArrayHandle fields_with_fix(THREAD, ff);
|
||||
|
||||
// Take everything from the original but the length.
|
||||
for (int idx = 0; idx < (*fields_ptr)->length(); idx++) {
|
||||
fields_with_fix->ushort_at_put(idx, (*fields_ptr)->ushort_at(idx));
|
||||
}
|
||||
|
||||
// Add the fake field at the end.
|
||||
int i = (*fields_ptr)->length();
|
||||
// There is no name index for the fake "discovered" field nor
|
||||
// signature but a signature is needed so that the field will
|
||||
// be properly initialized. Use one found for
|
||||
// one of the other reference fields. Be sure the index for the
|
||||
// name is 0. In fieldDescriptor::initialize() the index of the
|
||||
// name is checked. That check is by passed for the last nonstatic
|
||||
// oop field in a java.lang.ref.Reference which is assumed to be
|
||||
// this artificial "discovered" field. An assertion checks that
|
||||
// the name index is 0.
|
||||
assert(reference_index != 0, "Missing signature for reference");
|
||||
|
||||
int j;
|
||||
for (j = 0; j < instanceKlass::next_offset; j++) {
|
||||
fields_with_fix->ushort_at_put(i + j,
|
||||
(*fields_ptr)->ushort_at(reference_index +j));
|
||||
}
|
||||
// Clear the public access flag and set the private access flag.
|
||||
short flags;
|
||||
flags =
|
||||
fields_with_fix->ushort_at(i + instanceKlass::access_flags_offset);
|
||||
assert(!(flags & JVM_RECOGNIZED_FIELD_MODIFIERS), "Unexpected access flags set");
|
||||
flags = flags & (~JVM_ACC_PUBLIC);
|
||||
flags = flags | JVM_ACC_PRIVATE;
|
||||
AccessFlags access_flags;
|
||||
access_flags.set_flags(flags);
|
||||
assert(!access_flags.is_public(), "Failed to clear public flag");
|
||||
assert(access_flags.is_private(), "Failed to set private flag");
|
||||
fields_with_fix->ushort_at_put(i + instanceKlass::access_flags_offset,
|
||||
flags);
|
||||
|
||||
assert(fields_with_fix->ushort_at(i + instanceKlass::name_index_offset)
|
||||
== reference_name_index, "The fake reference name is incorrect");
|
||||
assert(fields_with_fix->ushort_at(i + instanceKlass::signature_index_offset)
|
||||
== reference_sig_index, "The fake reference signature is incorrect");
|
||||
// The type of the field is stored in the low_offset entry during
|
||||
// parsing.
|
||||
assert(fields_with_fix->ushort_at(i + instanceKlass::low_offset) ==
|
||||
NONSTATIC_OOP, "The fake reference type is incorrect");
|
||||
|
||||
// "fields" is allocated in the permanent generation. Disgard
|
||||
// it and let it be collected.
|
||||
(*fields_ptr) = fields_with_fix;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void ClassFileParser::java_lang_Class_fix_pre(int* nonstatic_field_size,
|
||||
FieldAllocationCount *fac_ptr) {
|
||||
// Add fake fields for java.lang.Class instances
|
||||
//
|
||||
// This is not particularly nice. We should consider adding a
|
||||
// private transient object field at the Java level to
|
||||
// java.lang.Class. Alternatively we could add a subclass of
|
||||
// instanceKlass which provides an accessor and size computer for
|
||||
// this field, but that appears to be more code than this hack.
|
||||
//
|
||||
// NOTE that we wedge these in at the beginning rather than the
|
||||
// end of the object because the Class layout changed between JDK
|
||||
// 1.3 and JDK 1.4 with the new reflection implementation; some
|
||||
// nonstatic oop fields were added at the Java level. The offsets
|
||||
// of these fake fields can't change between these two JDK
|
||||
// versions because when the offsets are computed at bootstrap
|
||||
// time we don't know yet which version of the JDK we're running in.
|
||||
|
||||
// The values below are fake but will force three non-static oop fields and
|
||||
// a corresponding non-static oop map block to be allocated.
|
||||
const int extra = java_lang_Class::number_of_fake_oop_fields;
|
||||
fac_ptr->nonstatic_oop_count += extra;
|
||||
|
||||
// Reserve some leading space for fake ints
|
||||
*nonstatic_field_size += align_size_up(java_lang_Class::hc_number_of_fake_int_fields * BytesPerInt, heapOopSize) / heapOopSize;
|
||||
}
|
||||
|
||||
|
||||
void ClassFileParser::java_lang_Class_fix_post(int* next_nonstatic_oop_offset_ptr) {
|
||||
// Cause the extra fake fields in java.lang.Class to show up before
|
||||
// the Java fields for layout compatibility between 1.3 and 1.4
|
||||
// Incrementing next_nonstatic_oop_offset here advances the
|
||||
// location where the real java fields are placed.
|
||||
const int extra = java_lang_Class::number_of_fake_oop_fields;
|
||||
(*next_nonstatic_oop_offset_ptr) += (extra * heapOopSize);
|
||||
}
|
||||
|
||||
|
||||
// Force MethodHandle.vmentry to be an unmanaged pointer.
|
||||
// There is no way for a classfile to express this, so we must help it.
|
||||
void ClassFileParser::java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp,
|
||||
typeArrayHandle fields,
|
||||
FieldAllocationCount *fac_ptr,
|
||||
TRAPS) {
|
||||
// Add fake fields for java.lang.invoke.MethodHandle instances
|
||||
//
|
||||
// This is not particularly nice, but since there is no way to express
|
||||
// a native wordSize field in Java, we must do it at this level.
|
||||
|
||||
if (!EnableInvokeDynamic) return;
|
||||
|
||||
int word_sig_index = 0;
|
||||
const int cp_size = cp->length();
|
||||
for (int index = 1; index < cp_size; index++) {
|
||||
if (cp->tag_at(index).is_utf8() &&
|
||||
cp->symbol_at(index) == vmSymbols::machine_word_signature()) {
|
||||
word_sig_index = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (word_sig_index == 0)
|
||||
THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
|
||||
"missing I or J signature (for vmentry) in java.lang.invoke.MethodHandle");
|
||||
|
||||
// Find vmentry field and change the signature.
|
||||
bool found_vmentry = false;
|
||||
for (int i = 0; i < fields->length(); i += instanceKlass::next_offset) {
|
||||
int name_index = fields->ushort_at(i + instanceKlass::name_index_offset);
|
||||
int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset);
|
||||
int acc_flags = fields->ushort_at(i + instanceKlass::access_flags_offset);
|
||||
Symbol* f_name = cp->symbol_at(name_index);
|
||||
Symbol* f_sig = cp->symbol_at(sig_index);
|
||||
if (f_name == vmSymbols::vmentry_name() && (acc_flags & JVM_ACC_STATIC) == 0) {
|
||||
if (f_sig == vmSymbols::machine_word_signature()) {
|
||||
// If the signature of vmentry is already changed, we're done.
|
||||
found_vmentry = true;
|
||||
break;
|
||||
}
|
||||
else if (f_sig == vmSymbols::byte_signature()) {
|
||||
// Adjust the field type from byte to an unmanaged pointer.
|
||||
assert(fac_ptr->nonstatic_byte_count > 0, "");
|
||||
fac_ptr->nonstatic_byte_count -= 1;
|
||||
|
||||
fields->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index);
|
||||
assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64");
|
||||
if (wordSize == longSize) fac_ptr->nonstatic_double_count += 1;
|
||||
else fac_ptr->nonstatic_word_count += 1;
|
||||
|
||||
FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset);
|
||||
assert(atype == NONSTATIC_BYTE, "");
|
||||
FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD;
|
||||
fields->ushort_at_put(i + instanceKlass::low_offset, new_atype);
|
||||
|
||||
found_vmentry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_vmentry)
|
||||
THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
|
||||
"missing vmentry byte field in java.lang.invoke.MethodHandle");
|
||||
}
|
||||
|
||||
|
||||
instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
|
@ -3025,10 +2843,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||
local_interfaces = parse_interfaces(cp, itfs_len, class_loader, protection_domain, _class_name, CHECK_(nullHandle));
|
||||
}
|
||||
|
||||
int java_fields_count = 0;
|
||||
// Fields (offsets are filled in later)
|
||||
struct FieldAllocationCount fac = {0,0,0,0,0,0,0,0,0,0};
|
||||
FieldAllocationCount fac;
|
||||
objArrayHandle fields_annotations;
|
||||
typeArrayHandle fields = parse_fields(cp, access_flags.is_interface(), &fac, &fields_annotations, CHECK_(nullHandle));
|
||||
typeArrayHandle fields = parse_fields(class_name, cp, access_flags.is_interface(), &fac, &fields_annotations,
|
||||
&java_fields_count,
|
||||
CHECK_(nullHandle));
|
||||
// Methods
|
||||
bool has_final_method = false;
|
||||
AccessFlags promoted_flags;
|
||||
|
@ -3146,51 +2967,33 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||
// Calculate the starting byte offsets
|
||||
next_static_oop_offset = instanceMirrorKlass::offset_of_static_fields();
|
||||
next_static_double_offset = next_static_oop_offset +
|
||||
(fac.static_oop_count * heapOopSize);
|
||||
if ( fac.static_double_count &&
|
||||
(fac.count[STATIC_OOP] * heapOopSize);
|
||||
if ( fac.count[STATIC_DOUBLE] &&
|
||||
(Universe::field_type_should_be_aligned(T_DOUBLE) ||
|
||||
Universe::field_type_should_be_aligned(T_LONG)) ) {
|
||||
next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong);
|
||||
}
|
||||
|
||||
next_static_word_offset = next_static_double_offset +
|
||||
(fac.static_double_count * BytesPerLong);
|
||||
(fac.count[STATIC_DOUBLE] * BytesPerLong);
|
||||
next_static_short_offset = next_static_word_offset +
|
||||
(fac.static_word_count * BytesPerInt);
|
||||
(fac.count[STATIC_WORD] * BytesPerInt);
|
||||
next_static_byte_offset = next_static_short_offset +
|
||||
(fac.static_short_count * BytesPerShort);
|
||||
(fac.count[STATIC_SHORT] * BytesPerShort);
|
||||
next_static_type_offset = align_size_up((next_static_byte_offset +
|
||||
fac.static_byte_count ), wordSize );
|
||||
fac.count[STATIC_BYTE] ), wordSize );
|
||||
static_field_size = (next_static_type_offset -
|
||||
next_static_oop_offset) / wordSize;
|
||||
|
||||
// Add fake fields for java.lang.Class instances (also see below)
|
||||
if (class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) {
|
||||
java_lang_Class_fix_pre(&nonstatic_field_size, &fac);
|
||||
}
|
||||
|
||||
first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
|
||||
nonstatic_field_size * heapOopSize;
|
||||
next_nonstatic_field_offset = first_nonstatic_field_offset;
|
||||
|
||||
// adjust the vmentry field declaration in java.lang.invoke.MethodHandle
|
||||
if (EnableInvokeDynamic && class_name == vmSymbols::java_lang_invoke_MethodHandle() && class_loader.is_null()) {
|
||||
java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle));
|
||||
}
|
||||
|
||||
// Add a fake "discovered" field if it is not present
|
||||
// for compatibility with earlier jdk's.
|
||||
if (class_name == vmSymbols::java_lang_ref_Reference()
|
||||
&& class_loader.is_null()) {
|
||||
java_lang_ref_Reference_fix_pre(&fields, cp, &fac, CHECK_(nullHandle));
|
||||
}
|
||||
// end of "discovered" field compactibility fix
|
||||
|
||||
unsigned int nonstatic_double_count = fac.nonstatic_double_count;
|
||||
unsigned int nonstatic_word_count = fac.nonstatic_word_count;
|
||||
unsigned int nonstatic_short_count = fac.nonstatic_short_count;
|
||||
unsigned int nonstatic_byte_count = fac.nonstatic_byte_count;
|
||||
unsigned int nonstatic_oop_count = fac.nonstatic_oop_count;
|
||||
unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE];
|
||||
unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD];
|
||||
unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT];
|
||||
unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE];
|
||||
unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP];
|
||||
|
||||
bool super_has_nonstatic_fields =
|
||||
(super_klass() != NULL && super_klass->has_nonstatic_fields());
|
||||
|
@ -3210,20 +3013,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||
nonstatic_oop_counts = NEW_RESOURCE_ARRAY_IN_THREAD(
|
||||
THREAD, unsigned int, nonstatic_oop_count + 1);
|
||||
|
||||
// Add fake fields for java.lang.Class instances (also see above).
|
||||
// FieldsAllocationStyle and CompactFields values will be reset to default.
|
||||
if(class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) {
|
||||
java_lang_Class_fix_post(&next_nonstatic_field_offset);
|
||||
nonstatic_oop_offsets[0] = first_nonstatic_field_offset;
|
||||
const uint fake_oop_count = (next_nonstatic_field_offset -
|
||||
first_nonstatic_field_offset) / heapOopSize;
|
||||
nonstatic_oop_counts[0] = fake_oop_count;
|
||||
nonstatic_oop_map_count = 1;
|
||||
nonstatic_oop_count -= fake_oop_count;
|
||||
first_nonstatic_oop_offset = first_nonstatic_field_offset;
|
||||
} else {
|
||||
first_nonstatic_oop_offset = 0; // will be set for first oop field
|
||||
}
|
||||
first_nonstatic_oop_offset = 0; // will be set for first oop field
|
||||
|
||||
#ifndef PRODUCT
|
||||
if( PrintCompactFieldsSavings ) {
|
||||
|
@ -3378,10 +3168,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||
// Iterate over fields again and compute correct offsets.
|
||||
// The field allocation type was temporarily stored in the offset slot.
|
||||
// oop fields are located before non-oop fields (static and non-static).
|
||||
int len = fields->length();
|
||||
for (int i = 0; i < len; i += instanceKlass::next_offset) {
|
||||
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
|
||||
int real_offset;
|
||||
FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset);
|
||||
FieldAllocationType atype = (FieldAllocationType) fs.offset();
|
||||
switch (atype) {
|
||||
case STATIC_OOP:
|
||||
real_offset = next_static_oop_offset;
|
||||
|
@ -3399,7 +3188,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||
real_offset = next_static_word_offset;
|
||||
next_static_word_offset += BytesPerInt;
|
||||
break;
|
||||
case STATIC_ALIGNED_DOUBLE:
|
||||
case STATIC_DOUBLE:
|
||||
real_offset = next_static_double_offset;
|
||||
next_static_double_offset += BytesPerLong;
|
||||
|
@ -3461,7 +3249,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||
next_nonstatic_word_offset += BytesPerInt;
|
||||
}
|
||||
break;
|
||||
case NONSTATIC_ALIGNED_DOUBLE:
|
||||
case NONSTATIC_DOUBLE:
|
||||
real_offset = next_nonstatic_double_offset;
|
||||
next_nonstatic_double_offset += BytesPerLong;
|
||||
|
@ -3469,8 +3256,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
fields->short_at_put(i + instanceKlass::low_offset, extract_low_short_from_int(real_offset));
|
||||
fields->short_at_put(i + instanceKlass::high_offset, extract_high_short_from_int(real_offset));
|
||||
fs.set_offset(real_offset);
|
||||
}
|
||||
|
||||
// Size of instances
|
||||
|
@ -3517,12 +3303,12 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||
this_klass->set_class_loader(class_loader());
|
||||
this_klass->set_nonstatic_field_size(nonstatic_field_size);
|
||||
this_klass->set_has_nonstatic_fields(has_nonstatic_fields);
|
||||
this_klass->set_static_oop_field_count(fac.static_oop_count);
|
||||
this_klass->set_static_oop_field_count(fac.count[STATIC_OOP]);
|
||||
cp->set_pool_holder(this_klass());
|
||||
error_handler.set_in_error(false); // turn off error handler for cp
|
||||
this_klass->set_constants(cp());
|
||||
this_klass->set_local_interfaces(local_interfaces());
|
||||
this_klass->set_fields(fields());
|
||||
this_klass->set_fields(fields(), java_fields_count);
|
||||
this_klass->set_methods(methods());
|
||||
if (has_final_method) {
|
||||
this_klass->set_has_final_method();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue