7086585: make Java field injection more flexible

Reviewed-by: jrose, twisti, kvn, coleenp
This commit is contained in:
Tom Rodriguez 2011-09-10 17:29:02 -07:00
parent 1ebca30d26
commit e39ba1a5fe
39 changed files with 1073 additions and 991 deletions

View File

@ -39,28 +39,20 @@ public class Field {
/** Constructor for fields that are named in an InstanceKlass's
fields array (i.e., named, non-VM fields) */
Field(InstanceKlass holder, int fieldArrayIndex) {
Field(InstanceKlass holder, int fieldIndex) {
this.holder = holder;
this.fieldArrayIndex = fieldArrayIndex;
this.fieldIndex = fieldIndex;
ConstantPool cp = holder.getConstants();
TypeArray fields = holder.getFields();
short access = fields.getShortAt(fieldArrayIndex + InstanceKlass.ACCESS_FLAGS_OFFSET);
short nameIndex = fields.getShortAt(fieldArrayIndex + InstanceKlass.NAME_INDEX_OFFSET);
short signatureIndex = fields.getShortAt(fieldArrayIndex + InstanceKlass.SIGNATURE_INDEX_OFFSET);
offset = VM.getVM().buildIntFromShorts(fields.getShortAt(fieldArrayIndex + InstanceKlass.LOW_OFFSET),
fields.getShortAt(fieldArrayIndex + InstanceKlass.HIGH_OFFSET));
short genericSignatureIndex = fields.getShortAt(fieldArrayIndex + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET);
Symbol name = cp.getSymbolAt(nameIndex);
offset = holder.getFieldOffset(fieldIndex);
genericSignature = holder.getFieldGenericSignature(fieldIndex);
Symbol name = holder.getFieldName(fieldIndex);
id = new NamedFieldIdentifier(name.asString());
signature = cp.getSymbolAt(signatureIndex);
if (genericSignatureIndex != 0) {
genericSignature = cp.getSymbolAt(genericSignatureIndex);
} else {
genericSignature = null;
}
signature = holder.getFieldSignature(fieldIndex);
fieldType = new FieldType(signature);
short access = holder.getFieldAccessFlags(fieldIndex);
accessFlags = new AccessFlags(access);
}
@ -73,7 +65,7 @@ public class Field {
private Symbol signature;
private Symbol genericSignature;
private AccessFlags accessFlags;
private int fieldArrayIndex;
private int fieldIndex;
/** Returns the byte offset of the field within the object or klass */
public long getOffset() { return offset; }
@ -101,8 +93,8 @@ public class Field {
/** (Named, non-VM fields only) Returns the index in the fields
TypeArray for this field. Equivalent to the "index" in the VM's
fieldDescriptors. */
public int getFieldArrayIndex() {
return fieldArrayIndex;
public int getFieldIndex() {
return fieldIndex;
}
/** (Named, non-VM fields only) Retrieves the access flags. */

View File

@ -51,7 +51,7 @@ public class InstanceKlass extends Klass {
public static int LOW_OFFSET;
public static int HIGH_OFFSET;
public static int GENERIC_SIGNATURE_INDEX_OFFSET;
public static int NEXT_OFFSET;
public static int FIELD_SLOTS;
public static int IMPLEMENTORS_LIMIT;
// ClassState constants
@ -78,6 +78,7 @@ public class InstanceKlass extends Klass {
implementors[i] = new OopField(type.getOopField("_implementors[0]"), arrayOffset);
}
fields = new OopField(type.getOopField("_fields"), Oop.getHeaderSize());
javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), Oop.getHeaderSize());
constants = new OopField(type.getOopField("_constants"), Oop.getHeaderSize());
classLoader = new OopField(type.getOopField("_class_loader"), Oop.getHeaderSize());
protectionDomain = new OopField(type.getOopField("_protection_domain"), Oop.getHeaderSize());
@ -100,14 +101,14 @@ public class InstanceKlass extends Klass {
headerSize = alignObjectOffset(Oop.getHeaderSize() + type.getSize());
// read field offset constants
ACCESS_FLAGS_OFFSET = db.lookupIntConstant("instanceKlass::access_flags_offset").intValue();
NAME_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::name_index_offset").intValue();
SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::signature_index_offset").intValue();
INITVAL_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::initval_index_offset").intValue();
LOW_OFFSET = db.lookupIntConstant("instanceKlass::low_offset").intValue();
HIGH_OFFSET = db.lookupIntConstant("instanceKlass::high_offset").intValue();
GENERIC_SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::generic_signature_offset").intValue();
NEXT_OFFSET = db.lookupIntConstant("instanceKlass::next_offset").intValue();
ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue();
NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue();
SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue();
INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue();
LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_offset").intValue();
HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_offset").intValue();
GENERIC_SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::generic_signature_offset").intValue();
FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue();
// read ClassState constants
CLASS_STATE_UNPARSABLE_BY_GC = db.lookupIntConstant("instanceKlass::unparsable_by_gc").intValue();
CLASS_STATE_ALLOCATED = db.lookupIntConstant("instanceKlass::allocated").intValue();
@ -131,6 +132,7 @@ public class InstanceKlass extends Klass {
private static CIntField nofImplementors;
private static OopField[] implementors;
private static OopField fields;
private static CIntField javaFieldsCount;
private static OopField constants;
private static OopField classLoader;
private static OopField protectionDomain;
@ -247,6 +249,34 @@ public class InstanceKlass extends Klass {
public static long getHeaderSize() { return headerSize; }
public short getFieldAccessFlags(int index) {
return getFields().getShortAt(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET);
}
public Symbol getFieldName(int index) {
int nameIndex = getFields().getShortAt(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
return getConstants().getSymbolAt(nameIndex);
}
public Symbol getFieldSignature(int index) {
int signatureIndex = getFields().getShortAt(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
return getConstants().getSymbolAt(signatureIndex);
}
public Symbol getFieldGenericSignature(int index) {
short genericSignatureIndex = getFields().getShortAt(index * FIELD_SLOTS + GENERIC_SIGNATURE_INDEX_OFFSET);
if (genericSignatureIndex != 0) {
return getConstants().getSymbolAt(genericSignatureIndex);
}
return null;
}
public int getFieldOffset(int index) {
TypeArray fields = getFields();
return VM.getVM().buildIntFromShorts(fields.getShortAt(index * FIELD_SLOTS + LOW_OFFSET),
fields.getShortAt(index * FIELD_SLOTS + HIGH_OFFSET));
}
// Accessors for declared fields
public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); }
public ObjArray getMethods() { return (ObjArray) methods.getValue(this); }
@ -257,6 +287,8 @@ public class InstanceKlass extends Klass {
public Klass getImplementor() { return (Klass) implementors[0].getValue(this); }
public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); }
public TypeArray getFields() { return (TypeArray) fields.getValue(this); }
public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); }
public int getAllFieldsCount() { return (int)getFields().getLength(); }
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
public Oop getClassLoader() { return classLoader.getValue(this); }
public Oop getProtectionDomain() { return protectionDomain.getValue(this); }
@ -480,8 +512,8 @@ public class InstanceKlass extends Klass {
void iterateStaticFieldsInternal(OopVisitor visitor) {
TypeArray fields = getFields();
int length = (int) fields.getLength();
for (int index = 0; index < length; index += NEXT_OFFSET) {
int length = getJavaFieldsCount();
for (int index = 0; index < length; index += FIELD_SLOTS) {
short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex));
@ -502,8 +534,8 @@ public class InstanceKlass extends Klass {
}
TypeArray fields = getFields();
int length = (int) fields.getLength();
for (int index = 0; index < length; index += NEXT_OFFSET) {
int length = getJavaFieldsCount();
for (int index = 0; index < length; index += FIELD_SLOTS) {
short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
@ -518,9 +550,9 @@ public class InstanceKlass extends Klass {
/** Field access by name. */
public Field findLocalField(Symbol name, Symbol sig) {
TypeArray fields = getFields();
int n = (int) fields.getLength();
int length = (int) fields.getLength();
ConstantPool cp = getConstants();
for (int i = 0; i < n; i += NEXT_OFFSET) {
for (int i = 0; i < length; i += FIELD_SLOTS) {
int nameIndex = fields.getShortAt(i + NAME_INDEX_OFFSET);
int sigIndex = fields.getShortAt(i + SIGNATURE_INDEX_OFFSET);
Symbol f_name = cp.getSymbolAt(nameIndex);
@ -613,9 +645,9 @@ public class InstanceKlass extends Klass {
// not including inherited fields.
TypeArray fields = getFields();
int length = (int) fields.getLength();
List immediateFields = new ArrayList(length / NEXT_OFFSET);
for (int index = 0; index < length; index += NEXT_OFFSET) {
int length = getJavaFieldsCount();
List immediateFields = new ArrayList(length);
for (int index = 0; index < length; index += FIELD_SLOTS) {
immediateFields.add(getFieldByIndex(index));
}

View File

@ -55,13 +55,13 @@ public class java_lang_Class {
// klass and oop_size are HotSpot magic fields and hence we can't
// find them from InstanceKlass for java.lang.Class.
Type jlc = db.lookupType("java_lang_Class");
int klassOffset = (int) jlc.getCIntegerField("klass_offset").getValue();
int klassOffset = (int) jlc.getCIntegerField("_klass_offset").getValue();
if (VM.getVM().isCompressedOopsEnabled()) {
klassField = new NarrowOopField(new NamedFieldIdentifier("klass"), klassOffset, true);
} else {
klassField = new OopField(new NamedFieldIdentifier("klass"), klassOffset, true);
}
int oopSizeOffset = (int) jlc.getCIntegerField("oop_size_offset").getValue();
int oopSizeOffset = (int) jlc.getCIntegerField("_oop_size_offset").getValue();
oopSizeField = new IntField(new NamedFieldIdentifier("oop_size"), oopSizeOffset, true);
}

View File

@ -380,15 +380,15 @@ public class ClassWriter implements /* imports */ ClassConstants
protected void writeFields() throws IOException {
TypeArray fields = klass.getFields();
final int length = (int) fields.getLength();
final int length = klass.getJavaFieldsCount();
// write number of fields
dos.writeShort((short) (length / InstanceKlass.NEXT_OFFSET) );
dos.writeShort((short) (length / InstanceKlass.FIELD_SLOTS) );
if (DEBUG) debugMessage("number of fields = "
+ length/InstanceKlass.NEXT_OFFSET);
+ length/InstanceKlass.FIELD_SLOTS);
for (int index = 0; index < length; index += InstanceKlass.NEXT_OFFSET) {
for (int index = 0; index < length; index += InstanceKlass.FIELD_SLOTS) {
short accessFlags = fields.getShortAt(index + InstanceKlass.ACCESS_FLAGS_OFFSET);
dos.writeShort(accessFlags & (short) JVM_RECOGNIZED_FIELD_MODIFIERS);

View File

@ -150,16 +150,13 @@ public class SOQL extends Tool {
}
// list immediate fields only
TypeArray fields = klass.getFields();
int numFields = (int) fields.getLength();
int numFields = klass.getJavaFieldsCount();
ConstantPool cp = klass.getConstants();
out.println("fields");
if (numFields != 0) {
for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) {
int nameIndex = fields.getShortAt(f + InstanceKlass.NAME_INDEX_OFFSET);
int sigIndex = fields.getShortAt(f + InstanceKlass.SIGNATURE_INDEX_OFFSET);
Symbol f_name = cp.getSymbolAt(nameIndex);
Symbol f_sig = cp.getSymbolAt(sigIndex);
for (int f = 0; f < numFields; f++){
Symbol f_name = klass.getFieldName(f);
Symbol f_sig = klass.getFieldSignature(f);
StringBuffer sigBuf = new StringBuffer();
new SignatureConverter(f_sig, sigBuf).dispatchField();
out.print('\t');

View File

@ -1116,20 +1116,15 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
InstanceKlass kls = (InstanceKlass) obj;
buf.append(" " + kls.getName().asString() + "={");
int flen = ov.fieldsSize();
TypeArray klfields = kls.getFields();
int klen = (int) klfields.getLength();
ConstantPool cp = kls.getConstants();
int klen = kls.getJavaFieldsCount();
int findex = 0;
for (int index = 0; index < klen; index += kls.NEXT_OFFSET) {
int accsFlags = klfields.getShortAt(index + kls.ACCESS_FLAGS_OFFSET);
int nameIndex = klfields.getShortAt(index + kls.NAME_INDEX_OFFSET);
for (int index = 0; index < klen; index++) {
int accsFlags = kls.getFieldAccessFlags(index);
Symbol f_name = kls.getFieldName(index);
AccessFlags access = new AccessFlags(accsFlags);
if (!access.isStatic()) {
ScopeValue svf = ov.getFieldAt(findex++);
String fstr = scopeValueAsString(sd, svf);
Symbol f_name = cp.getSymbolAt(nameIndex);
buf.append(" [" + f_name.asString() + " :"+ index + "]=(#" + fstr + ")");
}
}
@ -1819,13 +1814,11 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
protected String genHTMLListForFields(InstanceKlass klass) {
Formatter buf = new Formatter(genHTML);
TypeArray fields = klass.getFields();
int numFields = (int) fields.getLength();
ConstantPool cp = klass.getConstants();
int numFields = klass.getJavaFieldsCount();
if (numFields != 0) {
buf.h3("Fields");
buf.beginList();
for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) {
for (int f = 0; f < numFields; f++) {
sun.jvm.hotspot.oops.Field field = klass.getFieldByIndex(f);
String f_name = ((NamedFieldIdentifier)field.getID()).getName();
Symbol f_sig = field.getSignature();

View File

@ -76,5 +76,5 @@ while [ ! -s $tmp ] ; do
sleep 2
done
$jdk/bin/java -showversion ${OPTIONS} -classpath $javacp SASanityChecker $pid
$jdk/bin/java -showversion ${OPTIONS} -classpath $javacp $* SASanityChecker $pid
kill -9 $pid

View File

@ -3257,15 +3257,10 @@ void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register m
Register temp_reg) {
assert_different_registers(vmslots_reg, mh_reg, temp_reg);
// load mh.type.form.vmslots
if (java_lang_invoke_MethodHandle::vmslots_offset_in_bytes() != 0) {
// hoist vmslots into every mh to avoid dependent load chain
ld( Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmslots_offset_in_bytes, temp_reg)), vmslots_reg);
} else {
Register temp2_reg = vmslots_reg;
load_heap_oop(Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg);
load_heap_oop(Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg);
ld( Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg);
}
Register temp2_reg = vmslots_reg;
load_heap_oop(Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg);
load_heap_oop(Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg);
ld( Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg);
}
@ -4966,4 +4961,3 @@ void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Lab
cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop);
nop(); // Separate short branches
}

View File

@ -8004,15 +8004,10 @@ void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register m
Register temp_reg) {
assert_different_registers(vmslots_reg, mh_reg, temp_reg);
// load mh.type.form.vmslots
if (java_lang_invoke_MethodHandle::vmslots_offset_in_bytes() != 0) {
// hoist vmslots into every mh to avoid dependent load chain
movl(vmslots_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmslots_offset_in_bytes, temp_reg)));
} else {
Register temp2_reg = vmslots_reg;
load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)));
load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)));
movl(vmslots_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)));
}
Register temp2_reg = vmslots_reg;
load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)));
load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)));
movl(vmslots_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)));
}

View File

@ -31,6 +31,7 @@
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "runtime/fieldDescriptor.hpp"
// ciInstanceKlass
@ -412,7 +413,7 @@ GrowableArray<ciField*>* ciInstanceKlass::non_static_fields() {
VM_ENTRY_MARK;
ciEnv* curEnv = ciEnv::current();
instanceKlass* ik = get_instanceKlass();
int max_n_fields = ik->fields()->length()/instanceKlass::next_offset;
int max_n_fields = ik->java_fields_count();
Arena* arena = curEnv->arena();
_non_static_fields =
@ -476,23 +477,6 @@ int ciInstanceKlass::compute_nonstatic_fields() {
// Now sort them by offset, ascending.
// (In principle, they could mix with superclass fields.)
fields->sort(sort_field_by_offset);
#ifdef ASSERT
int last_offset = instanceOopDesc::base_offset_in_bytes();
for (int i = 0; i < fields->length(); i++) {
ciField* field = fields->at(i);
int offset = field->offset_in_bytes();
int size = (field->_type == NULL) ? heapOopSize : field->size_in_bytes();
assert(last_offset <= offset, err_msg("no field overlap: %d <= %d", last_offset, offset));
if (last_offset > (int)sizeof(oopDesc))
assert((offset - last_offset) < BytesPerLong, "no big holes");
// Note: Two consecutive T_BYTE fields will be separated by wordSize-1
// padding bytes if one of them is declared by a superclass.
// This is a minor inefficiency classFileParser.cpp.
last_offset = offset + size;
}
assert(last_offset <= (int)instanceOopDesc::base_offset_in_bytes() + fsize, "no overflow");
#endif
_nonstatic_fields = fields;
return flen;
}
@ -505,33 +489,29 @@ ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*>*
int flen = 0;
GrowableArray<ciField*>* fields = NULL;
instanceKlass* k = get_instanceKlass();
typeArrayOop fields_array = k->fields();
for (int pass = 0; pass <= 1; pass++) {
for (int i = 0, alen = fields_array->length(); i < alen; i += instanceKlass::next_offset) {
fieldDescriptor fd;
fd.initialize(k->as_klassOop(), i);
if (fd.is_static()) continue;
if (pass == 0) {
flen += 1;
} else {
ciField* field = new (arena) ciField(&fd);
fields->append(field);
}
}
for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) continue;
flen += 1;
}
// Between passes, allocate the array:
if (pass == 0) {
if (flen == 0) {
return NULL; // return nothing if none are locally declared
}
if (super_fields != NULL) {
flen += super_fields->length();
}
fields = new (arena) GrowableArray<ciField*>(arena, flen, 0, NULL);
if (super_fields != NULL) {
fields->appendAll(super_fields);
}
}
// allocate the array:
if (flen == 0) {
return NULL; // return nothing if none are locally declared
}
if (super_fields != NULL) {
flen += super_fields->length();
}
fields = new (arena) GrowableArray<ciField*>(arena, flen, 0, NULL);
if (super_fields != NULL) {
fields->appendAll(super_fields);
}
for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) continue;
fieldDescriptor fd;
fd.initialize(k->as_klassOop(), fs.index());
ciField* field = new (arena) ciField(&fd);
fields->append(field);
}
assert(fields->length() == flen, "sanity");
return fields;

View File

@ -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();

View File

@ -33,6 +33,9 @@
#include "utilities/accessFlags.hpp"
class TempNewSymbol;
class FieldAllocationCount;
// Parser for for .class files
//
// The bytes describing the class file structure is read from a Stream object
@ -84,9 +87,11 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
bool* is_synthetic_addr,
u2* generic_signature_index_addr,
typeArrayHandle* field_annotations, TRAPS);
typeArrayHandle parse_fields(constantPoolHandle cp, bool is_interface,
struct FieldAllocationCount *fac,
objArrayHandle* fields_annotations, TRAPS);
typeArrayHandle parse_fields(Symbol* class_name,
constantPoolHandle cp, bool is_interface,
FieldAllocationCount *fac,
objArrayHandle* fields_annotations,
int* java_fields_count_ptr, TRAPS);
// Method parsing
methodHandle parse_method(constantPoolHandle cp, bool is_interface,
@ -150,25 +155,6 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
objArrayHandle compute_transitive_interfaces(instanceKlassHandle super,
objArrayHandle local_ifs, TRAPS);
// Special handling for certain classes.
// Add the "discovered" field to java.lang.ref.Reference if
// it does not exist.
void java_lang_ref_Reference_fix_pre(typeArrayHandle* fields_ptr,
constantPoolHandle cp,
FieldAllocationCount *fac_ptr, TRAPS);
// Adjust the field allocation counts for java.lang.Class to add
// fake fields.
void java_lang_Class_fix_pre(int* nonstatic_field_size,
FieldAllocationCount *fac_ptr);
// Adjust the next_nonstatic_oop_offset to place the fake fields
// before any Java fields.
void java_lang_Class_fix_post(int* next_nonstatic_oop_offset);
// Adjust the field allocation counts for java.lang.invoke.MethodHandle to add
// a fake address (void*) field.
void java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp,
typeArrayHandle fields,
FieldAllocationCount *fac_ptr, TRAPS);
// Format checker methods
void classfile_parse_error(const char* msg, TRAPS);
void classfile_parse_error(const char* msg, int index, TRAPS);

View File

@ -33,6 +33,7 @@
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/klass.hpp"
@ -58,6 +59,49 @@
# include "thread_windows.inline.hpp"
#endif
#define INJECTED_FIELD_COMPUTE_OFFSET(klass, name, signature, may_be_java) \
klass::_##name##_offset = JavaClasses::compute_injected_offset(JavaClasses::klass##_##name##_enum);
#define DECLARE_INJECTED_FIELD(klass, name, signature, may_be_java) \
{ SystemDictionary::WK_KLASS_ENUM_NAME(klass), vmSymbols::VM_SYMBOL_ENUM_NAME(name##_name), vmSymbols::VM_SYMBOL_ENUM_NAME(signature), may_be_java },
InjectedField JavaClasses::_injected_fields[] = {
ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD)
};
int JavaClasses::compute_injected_offset(InjectedFieldID id) {
return _injected_fields[id].compute_offset();
}
InjectedField* JavaClasses::get_injected(Symbol* class_name, int* field_count) {
*field_count = 0;
vmSymbols::SID sid = vmSymbols::find_sid(class_name);
if (sid == vmSymbols::NO_SID) {
// Only well known classes can inject fields
return NULL;
}
int count = 0;
int start = -1;
#define LOOKUP_INJECTED_FIELD(klass, name, signature, may_be_java) \
if (sid == vmSymbols::VM_SYMBOL_ENUM_NAME(klass)) { \
count++; \
if (start == -1) start = klass##_##name##_enum; \
}
ALL_INJECTED_FIELDS(LOOKUP_INJECTED_FIELD);
#undef LOOKUP_INJECTED_FIELD
if (start != -1) {
*field_count = count;
return _injected_fields + start;
}
return NULL;
}
static bool find_field(instanceKlass* ik,
Symbol* name_symbol, Symbol* signature_symbol,
fieldDescriptor* fd,
@ -428,24 +472,19 @@ static void initialize_static_field(fieldDescriptor* fd, TRAPS) {
}
// During bootstrap, java.lang.Class wasn't loaded so static field
// offsets were computed without the size added it. Go back and
// update all the static field offsets to included the size.
static void fixup_static_field(fieldDescriptor* fd, TRAPS) {
if (fd->is_static()) {
int real_offset = fd->offset() + instanceMirrorKlass::offset_of_static_fields();
typeArrayOop fields = instanceKlass::cast(fd->field_holder())->fields();
fields->short_at_put(fd->index() + instanceKlass::low_offset, extract_low_short_from_int(real_offset));
fields->short_at_put(fd->index() + instanceKlass::high_offset, extract_high_short_from_int(real_offset));
}
}
void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) {
assert(instanceMirrorKlass::offset_of_static_fields() != 0, "must have been computed already");
if (k->oop_is_instance()) {
// Fixup the offsets
instanceKlass::cast(k())->do_local_static_fields(&fixup_static_field, CHECK);
// During bootstrap, java.lang.Class wasn't loaded so static field
// offsets were computed without the size added it. Go back and
// update all the static field offsets to included the size.
for (JavaFieldStream fs(instanceKlass::cast(k())); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
int real_offset = fs.offset() + instanceMirrorKlass::offset_of_static_fields();
fs.set_offset(real_offset);
}
}
}
create_mirror(k, CHECK);
}
@ -462,7 +501,7 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
// Allocate mirror (java.lang.Class instance)
Handle mirror = instanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0);
// Setup indirections
mirror->obj_field_put(klass_offset, k());
mirror->obj_field_put(_klass_offset, k());
k->set_java_mirror(mirror());
instanceMirrorKlass* mk = instanceMirrorKlass::cast(mirror->klass());
@ -504,25 +543,22 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
int java_lang_Class::oop_size(oop java_class) {
assert(oop_size_offset != 0, "must be set");
return java_class->int_field(oop_size_offset);
assert(_oop_size_offset != 0, "must be set");
return java_class->int_field(_oop_size_offset);
}
void java_lang_Class::set_oop_size(oop java_class, int size) {
assert(oop_size_offset != 0, "must be set");
java_class->int_field_put(oop_size_offset, size);
assert(_oop_size_offset != 0, "must be set");
java_class->int_field_put(_oop_size_offset, size);
}
int java_lang_Class::static_oop_field_count(oop java_class) {
assert(static_oop_field_count_offset != 0, "must be set");
return java_class->int_field(static_oop_field_count_offset);
assert(_static_oop_field_count_offset != 0, "must be set");
return java_class->int_field(_static_oop_field_count_offset);
}
void java_lang_Class::set_static_oop_field_count(oop java_class, int size) {
assert(static_oop_field_count_offset != 0, "must be set");
java_class->int_field_put(static_oop_field_count_offset, size);
assert(_static_oop_field_count_offset != 0, "must be set");
java_class->int_field_put(_static_oop_field_count_offset, size);
}
oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) {
// This should be improved by adding a field at the Java level or by
// introducing a new VM klass (see comment in ClassFileParser)
@ -542,7 +578,7 @@ oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, Basic
klassOop java_lang_Class::as_klassOop(oop java_class) {
//%note memory_2
assert(java_lang_Class::is_instance(java_class), "must be a Class object");
klassOop k = klassOop(java_class->obj_field(klass_offset));
klassOop k = klassOop(java_class->obj_field(_klass_offset));
assert(k == NULL || k->is_klass(), "type check");
return k;
}
@ -598,7 +634,7 @@ Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found,
klassOop java_lang_Class::array_klass(oop java_class) {
klassOop k = klassOop(java_class->obj_field(array_klass_offset));
klassOop k = klassOop(java_class->obj_field(_array_klass_offset));
assert(k == NULL || k->is_klass() && Klass::cast(k)->oop_is_javaArray(), "should be array klass");
return k;
}
@ -606,12 +642,12 @@ klassOop java_lang_Class::array_klass(oop java_class) {
void java_lang_Class::set_array_klass(oop java_class, klassOop klass) {
assert(klass->is_klass() && Klass::cast(klass)->oop_is_javaArray(), "should be array klass");
java_class->obj_field_put(array_klass_offset, klass);
java_class->obj_field_put(_array_klass_offset, klass);
}
methodOop java_lang_Class::resolved_constructor(oop java_class) {
oop constructor = java_class->obj_field(resolved_constructor_offset);
oop constructor = java_class->obj_field(_resolved_constructor_offset);
assert(constructor == NULL || constructor->is_method(), "should be method");
return methodOop(constructor);
}
@ -619,21 +655,21 @@ methodOop java_lang_Class::resolved_constructor(oop java_class) {
void java_lang_Class::set_resolved_constructor(oop java_class, methodOop constructor) {
assert(constructor->is_method(), "should be method");
java_class->obj_field_put(resolved_constructor_offset, constructor);
java_class->obj_field_put(_resolved_constructor_offset, constructor);
}
bool java_lang_Class::is_primitive(oop java_class) {
// should assert:
//assert(java_lang_Class::is_instance(java_class), "must be a Class object");
klassOop k = klassOop(java_class->obj_field(klass_offset));
klassOop k = klassOop(java_class->obj_field(_klass_offset));
return k == NULL;
}
BasicType java_lang_Class::primitive_type(oop java_class) {
assert(java_lang_Class::is_primitive(java_class), "just checking");
klassOop ak = klassOop(java_class->obj_field(array_klass_offset));
klassOop ak = klassOop(java_class->obj_field(_array_klass_offset));
BasicType type = T_VOID;
if (ak != NULL) {
// Note: create_basic_type_mirror above initializes ak to a non-null value.
@ -668,34 +704,18 @@ oop java_lang_Class::primitive_mirror(BasicType t) {
bool java_lang_Class::offsets_computed = false;
int java_lang_Class::classRedefinedCount_offset = -1;
int java_lang_Class::parallelCapable_offset = -1;
void java_lang_Class::compute_offsets() {
assert(!offsets_computed, "offsets should be initialized only once");
offsets_computed = true;
klassOop k = SystemDictionary::Class_klass();
klassOop klass_oop = SystemDictionary::Class_klass();
// The classRedefinedCount field is only present starting in 1.5,
// so don't go fatal.
compute_optional_offset(classRedefinedCount_offset,
k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
klass_oop, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
// The field indicating parallelCapable (parallelLockMap) is only present starting in 7,
klassOop k1 = SystemDictionary::ClassLoader_klass();
compute_optional_offset(parallelCapable_offset,
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
}
// For class loader classes, parallelCapable defined
// based on non-null field
// Written to by java.lang.ClassLoader, vm only reads this field, doesn't set it
bool java_lang_Class::parallelCapable(oop class_loader) {
if (!JDK_Version::is_gte_jdk17x_version()
|| parallelCapable_offset == -1) {
// Default for backward compatibility is false
return false;
}
return (class_loader->obj_field(parallelCapable_offset) != NULL);
CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
int java_lang_Class::classRedefinedCount(oop the_class_mirror) {
@ -2308,7 +2328,6 @@ void java_lang_ref_SoftReference::set_clock(jlong value) {
int java_lang_invoke_MethodHandle::_type_offset;
int java_lang_invoke_MethodHandle::_vmtarget_offset;
int java_lang_invoke_MethodHandle::_vmentry_offset;
int java_lang_invoke_MethodHandle::_vmslots_offset;
int java_lang_invoke_MemberName::_clazz_offset;
int java_lang_invoke_MemberName::_name_offset;
@ -2327,35 +2346,30 @@ int java_lang_invoke_AdapterMethodHandle::_conversion_offset;
int java_lang_invoke_CountingMethodHandle::_vmcount_offset;
void java_lang_invoke_MethodHandle::compute_offsets() {
klassOop k = SystemDictionary::MethodHandle_klass();
if (k != NULL && EnableInvokeDynamic) {
klassOop klass_oop = SystemDictionary::MethodHandle_klass();
if (klass_oop != NULL && EnableInvokeDynamic) {
bool allow_super = false;
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super);
compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), allow_super);
compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), allow_super);
// Note: MH.vmslots (if it is present) is a hoisted copy of MH.type.form.vmslots.
// It is optional pending experiments to keep or toss.
compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), allow_super);
compute_offset(_type_offset, klass_oop, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super);
METHODHANDLE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
}
void java_lang_invoke_MemberName::compute_offsets() {
klassOop k = SystemDictionary::MemberName_klass();
if (k != NULL && EnableInvokeDynamic) {
compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature());
compute_offset(_flags_offset, k, vmSymbols::flags_name(), vmSymbols::int_signature());
compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature());
compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature());
klassOop klass_oop = SystemDictionary::MemberName_klass();
if (klass_oop != NULL && EnableInvokeDynamic) {
compute_offset(_clazz_offset, klass_oop, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(_name_offset, klass_oop, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(_type_offset, klass_oop, vmSymbols::type_name(), vmSymbols::object_signature());
compute_offset(_flags_offset, klass_oop, vmSymbols::flags_name(), vmSymbols::int_signature());
compute_offset(_vmindex_offset, klass_oop, vmSymbols::vmindex_name(), vmSymbols::int_signature());
MEMBERNAME_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
}
void java_lang_invoke_DirectMethodHandle::compute_offsets() {
klassOop k = SystemDictionary::DirectMethodHandle_klass();
if (k != NULL && EnableInvokeDynamic) {
compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true);
DIRECTMETHODHANDLE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
}
@ -2399,31 +2413,9 @@ void java_lang_invoke_MethodHandle::set_type(oop mh, oop mtype) {
mh->obj_field_put(_type_offset, mtype);
}
int java_lang_invoke_MethodHandle::vmslots(oop mh) {
int vmslots_offset = _vmslots_offset;
if (vmslots_offset != 0) {
#ifdef ASSERT
int x = mh->int_field(vmslots_offset);
int y = compute_vmslots(mh);
assert(x == y, "correct hoisted value");
#endif
return mh->int_field(vmslots_offset);
} else {
return compute_vmslots(mh);
}
}
// if MH.vmslots exists, hoist into it the value of type.form.vmslots
void java_lang_invoke_MethodHandle::init_vmslots(oop mh) {
int vmslots_offset = _vmslots_offset;
if (vmslots_offset != 0) {
mh->int_field_put(vmslots_offset, compute_vmslots(mh));
}
}
// fetch type.form.vmslots, which is the number of JVM stack slots
// required to carry the arguments of this MH
int java_lang_invoke_MethodHandle::compute_vmslots(oop mh) {
int java_lang_invoke_MethodHandle::vmslots(oop mh) {
oop mtype = type(mh);
if (mtype == NULL) return 0; // Java code would get NPE
oop form = java_lang_invoke_MethodType::form(mtype);
@ -2643,6 +2635,7 @@ void java_lang_invoke_MethodTypeForm::compute_offsets() {
compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_lang_invoke_MethodType_signature(), true);
compute_optional_offset(_genericInvoker_offset, k, vmSymbols::genericInvoker_name(), vmSymbols::java_lang_invoke_MethodHandle_signature(), true);
if (_genericInvoker_offset == 0) _genericInvoker_offset = -1; // set to explicit "empty" value
METHODTYPEFORM_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
}
@ -2751,6 +2744,18 @@ oop java_security_AccessControlContext::create(objArrayHandle context, bool isPr
// Support for java_lang_ClassLoader
bool java_lang_ClassLoader::offsets_computed = false;
int java_lang_ClassLoader::parallelCapable_offset = -1;
void java_lang_ClassLoader::compute_offsets() {
assert(!offsets_computed, "offsets should be initialized only once");
offsets_computed = true;
// The field indicating parallelCapable (parallelLockMap) is only present starting in 7,
klassOop k1 = SystemDictionary::ClassLoader_klass();
compute_optional_offset(parallelCapable_offset,
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
}
oop java_lang_ClassLoader::parent(oop loader) {
assert(loader->is_oop(), "loader must be oop");
@ -2758,6 +2763,18 @@ oop java_lang_ClassLoader::parent(oop loader) {
}
// For class loader classes, parallelCapable defined
// based on non-null field
// Written to by java.lang.ClassLoader, vm only reads this field, doesn't set it
bool java_lang_ClassLoader::parallelCapable(oop class_loader) {
if (!JDK_Version::is_gte_jdk17x_version()
|| parallelCapable_offset == -1) {
// Default for backward compatibility is false
return false;
}
return (class_loader->obj_field(parallelCapable_offset) != NULL);
}
bool java_lang_ClassLoader::is_trusted_loader(oop loader) {
// Fix for 4474172; see evaluation for more details
loader = non_reflection_class_loader(loader);
@ -2807,12 +2824,11 @@ int java_lang_String::value_offset;
int java_lang_String::offset_offset;
int java_lang_String::count_offset;
int java_lang_String::hash_offset;
int java_lang_Class::klass_offset;
int java_lang_Class::array_klass_offset;
int java_lang_Class::resolved_constructor_offset;
int java_lang_Class::number_of_fake_oop_fields;
int java_lang_Class::oop_size_offset;
int java_lang_Class::static_oop_field_count_offset;
int java_lang_Class::_klass_offset;
int java_lang_Class::_array_klass_offset;
int java_lang_Class::_resolved_constructor_offset;
int java_lang_Class::_oop_size_offset;
int java_lang_Class::_static_oop_field_count_offset;
int java_lang_Throwable::backtrace_offset;
int java_lang_Throwable::detailMessage_offset;
int java_lang_Throwable::cause_offset;
@ -2925,20 +2941,20 @@ int java_nio_Buffer::limit_offset() {
void java_nio_Buffer::compute_offsets() {
klassOop k = SystemDictionary::java_nio_Buffer_klass();
klassOop k = SystemDictionary::nio_Buffer_klass();
assert(k != NULL, "must be loaded in 1.4+");
compute_offset(_limit_offset, k, vmSymbols::limit_name(), vmSymbols::int_signature());
}
// Support for intrinsification of sun.misc.AtomicLongCSImpl.attemptUpdate
int sun_misc_AtomicLongCSImpl::value_offset() {
assert(SystemDictionary::sun_misc_AtomicLongCSImpl_klass() != NULL, "can't call this");
assert(SystemDictionary::AtomicLongCSImpl_klass() != NULL, "can't call this");
return _value_offset;
}
void sun_misc_AtomicLongCSImpl::compute_offsets() {
klassOop k = SystemDictionary::sun_misc_AtomicLongCSImpl_klass();
klassOop k = SystemDictionary::AtomicLongCSImpl_klass();
// If this class is not present, its value field offset won't be referenced.
if (k != NULL) {
compute_offset(_value_offset, k, vmSymbols::value_name(), vmSymbols::long_signature());
@ -2973,23 +2989,6 @@ void JavaClasses::compute_hard_coded_offsets() {
java_lang_String::count_offset = java_lang_String::offset_offset + sizeof (jint);
java_lang_String::hash_offset = java_lang_String::count_offset + sizeof (jint);
{
// Do the Class Class
int offset = header;
java_lang_Class::oop_size_offset = header;
offset += BytesPerInt;
java_lang_Class::static_oop_field_count_offset = offset;
offset = align_size_up(offset + BytesPerInt, x);
java_lang_Class::klass_offset = offset;
offset += x;
java_lang_Class::array_klass_offset = offset;
offset += x;
java_lang_Class::resolved_constructor_offset = offset;
}
// This is NOT an offset
java_lang_Class::number_of_fake_oop_fields = java_lang_Class::hc_number_of_fake_oop_fields;
// Throwable Class
java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header;
java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header;
@ -3041,8 +3040,8 @@ void JavaClasses::compute_hard_coded_offsets() {
// Compute non-hard-coded field offsets of all the classes in this file
void JavaClasses::compute_offsets() {
java_lang_Class::compute_offsets();
// java_lang_Class::compute_offsets was called earlier in bootstrap
java_lang_ClassLoader::compute_offsets();
java_lang_Thread::compute_offsets();
java_lang_ThreadGroup::compute_offsets();
if (EnableInvokeDynamic) {
@ -3267,6 +3266,23 @@ void JavaClasses::check_offsets() {
#endif // PRODUCT
int InjectedField::compute_offset() {
klassOop klass_oop = klass();
for (AllFieldStream fs(instanceKlass::cast(klass_oop)); !fs.done(); fs.next()) {
if (!may_be_java && !fs.access_flags().is_internal()) {
// Only look at injected fields
continue;
}
if (fs.name() == name() && fs.signature() == signature()) {
return fs.offset();
}
}
ResourceMark rm;
tty->print_cr("Invalid layout of %s at %s", instanceKlass::cast(klass_oop)->external_name(), name()->as_C_string());
fatal("Invalid layout of preloaded class");
return -1;
}
void javaClasses_init() {
JavaClasses::compute_offsets();
JavaClasses::check_offsets();

View File

@ -156,30 +156,32 @@ class java_lang_String : AllStatic {
// Interface to java.lang.Class objects
#define CLASS_INJECTED_FIELDS(macro) \
macro(java_lang_Class, klass, object_signature, false) \
macro(java_lang_Class, resolved_constructor, object_signature, false) \
macro(java_lang_Class, array_klass, object_signature, false) \
macro(java_lang_Class, oop_size, int_signature, false) \
macro(java_lang_Class, static_oop_field_count, int_signature, false)
class java_lang_Class : AllStatic {
friend class VMStructs;
friend class VMStructs;
private:
// The fake offsets are added by the class loader when java.lang.Class is loaded
enum {
hc_number_of_fake_oop_fields = 3,
hc_number_of_fake_int_fields = 2
};
static int _klass_offset;
static int _resolved_constructor_offset;
static int _array_klass_offset;
static int klass_offset;
static int resolved_constructor_offset;
static int array_klass_offset;
static int number_of_fake_oop_fields;
static int _oop_size_offset;
static int _static_oop_field_count_offset;
static int oop_size_offset;
static int static_oop_field_count_offset;
static void compute_offsets();
static bool offsets_computed;
static int classRedefinedCount_offset;
static int parallelCapable_offset;
public:
static void compute_offsets();
// Instance creation
static oop create_mirror(KlassHandle k, TRAPS);
static void fixup_mirror(KlassHandle k, TRAPS);
@ -209,14 +211,12 @@ class java_lang_Class : AllStatic {
static klassOop array_klass(oop java_class);
static void set_array_klass(oop java_class, klassOop klass);
// compiler support for class operations
static int klass_offset_in_bytes() { return klass_offset; }
static int resolved_constructor_offset_in_bytes() { return resolved_constructor_offset; }
static int array_klass_offset_in_bytes() { return array_klass_offset; }
static int klass_offset_in_bytes() { return _klass_offset; }
static int resolved_constructor_offset_in_bytes() { return _resolved_constructor_offset; }
static int array_klass_offset_in_bytes() { return _array_klass_offset; }
// Support for classRedefinedCount field
static int classRedefinedCount(oop the_class_mirror);
static void set_classRedefinedCount(oop the_class_mirror, int value);
// Support for parallelCapable field
static bool parallelCapable(oop the_class_mirror);
static int oop_size(oop java_class);
static void set_oop_size(oop java_class, int size);
@ -834,16 +834,19 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
// Interface to java.lang.invoke.MethodHandle objects
#define METHODHANDLE_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_MethodHandle, vmentry, intptr_signature, false) \
macro(java_lang_invoke_MethodHandle, vmtarget, object_signature, true)
class MethodHandleEntry;
class java_lang_invoke_MethodHandle: AllStatic {
friend class JavaClasses;
private:
static int _vmentry_offset; // assembly code trampoline for MH
static int _vmtarget_offset; // class-specific target reference
static int _vmentry_offset; // assembly code trampoline for MH
static int _vmtarget_offset; // class-specific target reference
static int _type_offset; // the MethodType of this MH
static int _vmslots_offset; // OPTIONAL hoisted type.form.vmslots
static void compute_offsets();
@ -859,8 +862,6 @@ class java_lang_invoke_MethodHandle: AllStatic {
static void set_vmentry(oop mh, MethodHandleEntry* data);
static int vmslots(oop mh);
static void init_vmslots(oop mh);
static int compute_vmslots(oop mh);
// Testers
static bool is_subclass(klassOop klass) {
@ -874,14 +875,15 @@ class java_lang_invoke_MethodHandle: AllStatic {
static int type_offset_in_bytes() { return _type_offset; }
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
static int vmentry_offset_in_bytes() { return _vmentry_offset; }
static int vmslots_offset_in_bytes() { return _vmslots_offset; }
};
#define DIRECTMETHODHANDLE_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_DirectMethodHandle, vmindex, int_signature, true)
class java_lang_invoke_DirectMethodHandle: public java_lang_invoke_MethodHandle {
friend class JavaClasses;
private:
// _vmtarget_offset; // method or class or interface
static int _vmindex_offset; // negative or vtable idx or itable idx
static void compute_offsets();
@ -1012,6 +1014,9 @@ class java_lang_invoke_CountingMethodHandle: public java_lang_invoke_MethodHandl
// Interface to java.lang.invoke.MemberName objects
// (These are a private interface for Java code to query the class hierarchy.)
#define MEMBERNAME_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_MemberName, vmtarget, object_signature, true)
class java_lang_invoke_MemberName: AllStatic {
friend class JavaClasses;
@ -1121,6 +1126,10 @@ class java_lang_invoke_MethodType: AllStatic {
static int form_offset_in_bytes() { return _form_offset; }
};
#define METHODTYPEFORM_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_MethodTypeForm, vmslots, int_signature, true) \
macro(java_lang_invoke_MethodTypeForm, vmlayout, object_signature, true)
class java_lang_invoke_MethodTypeForm: AllStatic {
friend class JavaClasses;
@ -1135,6 +1144,8 @@ class java_lang_invoke_MethodTypeForm: AllStatic {
public:
// Accessors
static int vmslots(oop mtform);
static void set_vmslots(oop mtform, int vmslots);
static oop erasedType(oop mtform);
static oop genericInvoker(oop mtform);
@ -1156,8 +1167,6 @@ class java_lang_invoke_CallSite: AllStatic {
private:
static int _target_offset;
static int _caller_method_offset;
static int _caller_bci_offset;
static void compute_offsets();
@ -1169,12 +1178,6 @@ public:
static volatile oop target_volatile(oop site) { return site->obj_field_volatile( _target_offset); }
static void set_target_volatile(oop site, oop target) { site->obj_field_put_volatile(_target_offset, target); }
static oop caller_method(oop site);
static void set_caller_method(oop site, oop ref);
static jint caller_bci(oop site);
static void set_caller_bci(oop site, jint bci);
// Testers
static bool is_subclass(klassOop klass) {
return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass());
@ -1185,8 +1188,6 @@ public:
// Accessors for code generation:
static int target_offset_in_bytes() { return _target_offset; }
static int caller_method_offset_in_bytes() { return _caller_method_offset; }
static int caller_bci_offset_in_bytes() { return _caller_bci_offset; }
};
@ -1217,11 +1218,18 @@ class java_lang_ClassLoader : AllStatic {
hc_parent_offset = 0
};
static bool offsets_computed;
static int parent_offset;
static int parallelCapable_offset;
static void compute_offsets();
public:
static oop parent(oop loader);
// Support for parallelCapable field
static bool parallelCapable(oop the_class_mirror);
static bool is_trusted_loader(oop loader);
// Fix for 4474172
@ -1343,17 +1351,71 @@ class java_util_concurrent_locks_AbstractOwnableSynchronizer : AllStatic {
static oop get_owner_threadObj(oop obj);
};
// Use to declare fields that need to be injected into Java classes
// for the JVM to use. The name_index and signature_index are
// declared in vmSymbols. The may_be_java flag is used to declare
// fields that might already exist in Java but should be injected if
// they don't. Otherwise the field is unconditionally injected and
// the JVM uses the injected one. This is to ensure that name
// collisions don't occur. In general may_be_java should be false
// unless there's a good reason.
class InjectedField {
public:
const SystemDictionary::WKID klass_id;
const vmSymbols::SID name_index;
const vmSymbols::SID signature_index;
const bool may_be_java;
klassOop klass() const { return SystemDictionary::well_known_klass(klass_id); }
Symbol* name() const { return lookup_symbol(name_index); }
Symbol* signature() const { return lookup_symbol(signature_index); }
int compute_offset();
// Find the Symbol for this index
static Symbol* lookup_symbol(int symbol_index) {
return vmSymbols::symbol_at((vmSymbols::SID)symbol_index);
}
};
#define DECLARE_INJECTED_FIELD_ENUM(klass, name, signature, may_be_java) \
klass##_##name##_enum,
#define ALL_INJECTED_FIELDS(macro) \
CLASS_INJECTED_FIELDS(macro) \
METHODHANDLE_INJECTED_FIELDS(macro) \
DIRECTMETHODHANDLE_INJECTED_FIELDS(macro) \
MEMBERNAME_INJECTED_FIELDS(macro) \
METHODTYPEFORM_INJECTED_FIELDS(macro)
// Interface to hard-coded offset checking
class JavaClasses : AllStatic {
private:
static InjectedField _injected_fields[];
static bool check_offset(const char *klass_name, int offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
static bool check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
static bool check_constant(const char *klass_name, int constant, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
public:
enum InjectedFieldID {
ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD_ENUM)
MAX_enum
};
static int compute_injected_offset(InjectedFieldID id);
static void compute_hard_coded_offsets();
static void compute_offsets();
static void check_offsets() PRODUCT_RETURN;
static InjectedField* get_injected(Symbol* class_name, int* field_count);
};
#undef DECLARE_INJECTED_FIELD_ENUM
#endif // SHARE_VM_CLASSFILE_JAVACLASSES_HPP

View File

@ -125,13 +125,13 @@ bool SystemDictionary::is_internal_format(Symbol* class_name) {
bool SystemDictionary::is_parallelCapable(Handle class_loader) {
if (UnsyncloadClass || class_loader.is_null()) return true;
if (AlwaysLockClassLoader) return false;
return java_lang_Class::parallelCapable(class_loader());
return java_lang_ClassLoader::parallelCapable(class_loader());
}
// ----------------------------------------------------------------------------
// ParallelDefineClass flag does not apply to bootclass loader
bool SystemDictionary::is_parallelDefine(Handle class_loader) {
if (class_loader.is_null()) return false;
if (AllowParallelDefineClass && java_lang_Class::parallelCapable(class_loader())) {
if (AllowParallelDefineClass && java_lang_ClassLoader::parallelCapable(class_loader())) {
return true;
}
return false;
@ -1290,7 +1290,7 @@ static instanceKlassHandle download_and_retry_class_load(
Symbol* class_name,
TRAPS) {
klassOop dlm = SystemDictionary::sun_jkernel_DownloadManager_klass();
klassOop dlm = SystemDictionary::DownloadManager_klass();
instanceKlassHandle nk;
// If download manager class isn't loaded just return.
@ -1953,7 +1953,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
// first do Object, String, Class
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK);
debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(Class_klass)));
java_lang_Class::compute_offsets();
// Fixup mirrors for classes loaded before java.lang.Class.
// These calls iterate over the objects currently in the perm gen
@ -2001,7 +2001,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
//_box_klasses[T_ARRAY] = WK_KLASS(object_klass);
#ifdef KERNEL
if (sun_jkernel_DownloadManager_klass() == NULL) {
if (DownloadManager_klass() == NULL) {
warning("Cannot find sun/jkernel/DownloadManager");
}
#endif // KERNEL
@ -2736,7 +2736,7 @@ class ClassStatistics: AllStatic {
class_size += ik->local_interfaces()->size();
class_size += ik->transitive_interfaces()->size();
// We do not have to count implementors, since we only store one!
class_size += ik->fields()->size();
class_size += ik->all_fields_count() * FieldInfo::field_slots;
}
}

View File

@ -133,15 +133,15 @@ class SymbolPropertyTable;
template(reflect_Method_klass, java_lang_reflect_Method, Pre) \
template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \
\
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \
template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \
template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \
template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \
template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
\
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
template(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292) \
@ -168,14 +168,14 @@ class SymbolPropertyTable;
template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
template(java_nio_Buffer_klass, java_nio_Buffer, Opt) \
template(nio_Buffer_klass, java_nio_Buffer, Opt) \
\
/* If this class isn't present, it won't be referenced. */ \
template(sun_misc_AtomicLongCSImpl_klass, sun_misc_AtomicLongCSImpl, Opt) \
template(AtomicLongCSImpl_klass, sun_misc_AtomicLongCSImpl, Opt) \
\
template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \
template(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \
\
template(sun_misc_PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \
template(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \
\
/* Preload boxing klasses */ \
template(Boolean_klass, java_lang_Boolean, Pre) \
@ -199,7 +199,7 @@ class SystemDictionary : AllStatic {
enum WKID {
NO_WKID = 0,
#define WK_KLASS_ENUM(name, ignore_s, ignore_o) WK_KLASS_ENUM_NAME(name),
#define WK_KLASS_ENUM(name, symbol, ignore_o) WK_KLASS_ENUM_NAME(name), WK_KLASS_ENUM_NAME(symbol) = WK_KLASS_ENUM_NAME(name),
WK_KLASSES_DO(WK_KLASS_ENUM)
#undef WK_KLASS_ENUM
@ -426,11 +426,16 @@ public:
}
public:
#define WK_KLASS_DECLARE(name, ignore_symbol, option) \
#define WK_KLASS_DECLARE(name, symbol, option) \
static klassOop name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); }
WK_KLASSES_DO(WK_KLASS_DECLARE);
#undef WK_KLASS_DECLARE
static klassOop well_known_klass(WKID id) {
assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
return _well_known_klasses[id];
}
// Local definition for direct access to the private array:
#define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]

View File

@ -264,8 +264,8 @@
template(setTargetNormal_name, "setTargetNormal") \
template(setTargetVolatile_name, "setTargetVolatile") \
template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \
NOT_LP64( do_alias(intptr_signature, int_signature) ) \
LP64_ONLY( do_alias(intptr_signature, long_signature) ) \
template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \
\
/* common method and field names */ \
@ -365,6 +365,11 @@
template(erasedType_name, "erasedType") \
template(genericInvoker_name, "genericInvoker") \
template(append_name, "append") \
template(klass_name, "klass") \
template(resolved_constructor_name, "resolved_constructor") \
template(array_klass_name, "array_klass") \
template(oop_size_name, "oop_size") \
template(static_oop_field_count_name, "static_oop_field_count") \
\
/* non-intrinsic name/signature pairs: */ \
template(register_method_name, "register") \

View File

@ -984,11 +984,8 @@ ConstantPoolCacheEntry *cp_entry))
// check the access_flags for the field in the klass
instanceKlass* ik = instanceKlass::cast(java_lang_Class::as_klassOop(cp_entry->f1()));
typeArrayOop fields = ik->fields();
int index = cp_entry->field_index();
assert(index < fields->length(), "holders field index is out of range");
// bail out if field accesses are not watched
if ((fields->ushort_at(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return;
if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return;
switch(cp_entry->flag_state()) {
case btos: // fall through
@ -1021,11 +1018,9 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread,
// check the access_flags for the field in the klass
instanceKlass* ik = instanceKlass::cast(k);
typeArrayOop fields = ik->fields();
int index = cp_entry->field_index();
assert(index < fields->length(), "holders field index is out of range");
// bail out if field modifications are not watched
if ((fields->ushort_at(index) & JVM_ACC_FIELD_MODIFICATION_WATCHED) == 0) return;
if ((ik->field_access_flags(index) & JVM_ACC_FIELD_MODIFICATION_WATCHED) == 0) return;
char sig_type = '\0';

View File

@ -128,17 +128,13 @@ bool ConstantPoolCacheEntry::same_methodOop(oop cur_f1, oop f1) {
void ConstantPoolCacheEntry::set_field(Bytecodes::Code get_code,
Bytecodes::Code put_code,
KlassHandle field_holder,
int orig_field_index,
int field_index,
int field_offset,
TosState field_type,
bool is_final,
bool is_volatile) {
set_f1(field_holder()->java_mirror());
set_f2(field_offset);
// The field index is used by jvm/ti and is the index into fields() array
// in holder instanceKlass. This is scaled by instanceKlass::next_offset.
assert((orig_field_index % instanceKlass::next_offset) == 0, "wierd index");
const int field_index = orig_field_index / instanceKlass::next_offset;
assert(field_index <= field_index_mask,
"field index does not fit in low flag bits");
set_flags(as_flags(field_type, is_final, false, is_volatile, false, false) |
@ -149,7 +145,7 @@ void ConstantPoolCacheEntry::set_field(Bytecodes::Code get_code,
}
int ConstantPoolCacheEntry::field_index() const {
return (_flags & field_index_mask) * instanceKlass::next_offset;
return (_flags & field_index_mask);
}
void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code,

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2011, 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.
*
*/
#ifndef SHARE_VM_OOPS_FIELDINFO_HPP
#define SHARE_VM_OOPS_FIELDINFO_HPP
#include "oops/typeArrayOop.hpp"
#include "classfile/vmSymbols.hpp"
// This class represents the field information contained in the fields
// array of an instanceKlass. Currently it's laid on top an array of
// Java shorts but in the future it could simply be used as a real
// array type. FieldInfo generally shouldn't be used directly.
// Fields should be queried either through instanceKlass or through
// the various FieldStreams.
class FieldInfo VALUE_OBJ_CLASS_SPEC {
friend class fieldDescriptor;
friend class JavaFieldStream;
friend class ClassFileParser;
public:
// fields
// Field info extracted from the class file and stored
// as an array of 7 shorts
enum FieldOffset {
access_flags_offset = 0,
name_index_offset = 1,
signature_index_offset = 2,
initval_index_offset = 3,
low_offset = 4,
high_offset = 5,
generic_signature_offset = 6,
field_slots = 7
};
private:
u2 _shorts[field_slots];
void set_name_index(u2 val) { _shorts[name_index_offset] = val; }
void set_signature_index(u2 val) { _shorts[signature_index_offset] = val; }
void set_initval_index(u2 val) { _shorts[initval_index_offset] = val; }
void set_generic_signature_index(u2 val) { _shorts[generic_signature_offset] = val; }
u2 name_index() const { return _shorts[name_index_offset]; }
u2 signature_index() const { return _shorts[signature_index_offset]; }
u2 initval_index() const { return _shorts[initval_index_offset]; }
u2 generic_signature_index() const { return _shorts[generic_signature_offset]; }
public:
static FieldInfo* from_field_array(typeArrayOop fields, int index) {
return ((FieldInfo*)fields->short_at_addr(index * field_slots));
}
void initialize(u2 access_flags,
u2 name_index,
u2 signature_index,
u2 initval_index,
u2 generic_signature_index,
u4 offset) {
_shorts[access_flags_offset] = access_flags;
_shorts[name_index_offset] = name_index;
_shorts[signature_index_offset] = signature_index;
_shorts[initval_index_offset] = initval_index;
_shorts[generic_signature_offset] = generic_signature_index;
set_offset(offset);
}
u2 access_flags() const { return _shorts[access_flags_offset]; }
u4 offset() const { return build_int_from_shorts(_shorts[low_offset], _shorts[high_offset]); }
Symbol* name(constantPoolHandle cp) const {
int index = name_index();
if (is_internal()) {
return lookup_symbol(index);
}
return cp->symbol_at(index);
}
Symbol* signature(constantPoolHandle cp) const {
int index = signature_index();
if (is_internal()) {
return lookup_symbol(index);
}
return cp->symbol_at(index);
}
Symbol* generic_signature(constantPoolHandle cp) const {
int index = generic_signature_index();
if (index == 0) {
return NULL;
}
return cp->symbol_at(index);
}
void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; }
void set_offset(u4 val) {
_shorts[low_offset] = extract_low_short_from_int(val);
_shorts[high_offset] = extract_high_short_from_int(val);
}
bool is_internal() const {
return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0;
}
Symbol* lookup_symbol(int symbol_index) const {
assert(is_internal(), "only internal fields");
return vmSymbols::symbol_at((vmSymbols::SID)symbol_index);
}
};
#endif // SHARE_VM_OOPS_FIELDINFO_HPP

View File

@ -0,0 +1,174 @@
/*
* Copyright (c) 2011, 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.
*
*/
#ifndef SHARE_VM_OOPS_FIELDSTREAMS_HPP
#define SHARE_VM_OOPS_FIELDSTREAMS_HPP
#include "oops/instanceKlass.hpp"
#include "oops/fieldInfo.hpp"
// The is the base class for iteration over the fields array
// describing the declared fields in the class. Several subclasses
// are provided depending on the kind of iteration required. The
// JavaFieldStream is for iterating over regular Java fields and it
// generally the preferred iterator. InternalFieldStream only
// iterates over fields that have been injected by the JVM.
// AllFieldStream exposes all fields and should only be used in rare
// cases.
class FieldStreamBase : public StackObj {
protected:
typeArrayHandle _fields;
constantPoolHandle _constants;
int _index;
int _limit;
FieldInfo* field() const { return FieldInfo::from_field_array(_fields(), _index); }
FieldStreamBase(typeArrayHandle fields, constantPoolHandle constants, int start, int limit) {
_fields = fields;
_constants = constants;
_index = start;
_limit = limit;
}
FieldStreamBase(typeArrayHandle fields, constantPoolHandle constants) {
_fields = fields;
_constants = constants;
_index = 0;
_limit = fields->length() / FieldInfo::field_slots;
}
public:
FieldStreamBase(instanceKlass* klass) {
_fields = klass->fields();
_constants = klass->constants();
_index = 0;
_limit = klass->java_fields_count();
}
FieldStreamBase(instanceKlassHandle klass) {
_fields = klass->fields();
_constants = klass->constants();
_index = 0;
_limit = klass->java_fields_count();
}
// accessors
int index() const { return _index; }
void next() { _index += 1; }
bool done() const { return _index >= _limit; }
// Accessors for current field
AccessFlags access_flags() const {
AccessFlags flags;
flags.set_flags(field()->access_flags());
return flags;
}
void set_access_flags(u2 flags) const {
field()->set_access_flags(flags);
}
void set_access_flags(AccessFlags flags) const {
set_access_flags(flags.as_short());
}
Symbol* name() const {
return field()->name(_constants);
}
Symbol* signature() const {
return field()->signature(_constants);
}
Symbol* generic_signature() const {
return field()->generic_signature(_constants);
}
int offset() const {
return field()->offset();
}
void set_offset(int offset) {
field()->set_offset(offset);
}
};
// Iterate over only the internal fields
class JavaFieldStream : public FieldStreamBase {
public:
JavaFieldStream(instanceKlass* k): FieldStreamBase(k->fields(), k->constants(), 0, k->java_fields_count()) {}
JavaFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), 0, k->java_fields_count()) {}
int name_index() const {
assert(!field()->is_internal(), "regular only");
return field()->name_index();
}
void set_name_index(int index) {
assert(!field()->is_internal(), "regular only");
field()->set_name_index(index);
}
int signature_index() const {
assert(!field()->is_internal(), "regular only");
return field()->signature_index();
}
void set_signature_index(int index) {
assert(!field()->is_internal(), "regular only");
field()->set_signature_index(index);
}
int generic_signature_index() const {
assert(!field()->is_internal(), "regular only");
return field()->generic_signature_index();
}
void set_generic_signature_index(int index) {
assert(!field()->is_internal(), "regular only");
field()->set_generic_signature_index(index);
}
int initval_index() const {
assert(!field()->is_internal(), "regular only");
return field()->initval_index();
}
void set_initval_index(int index) {
assert(!field()->is_internal(), "regular only");
return field()->set_initval_index(index);
}
};
// Iterate over only the internal fields
class InternalFieldStream : public FieldStreamBase {
public:
InternalFieldStream(instanceKlass* k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), k->all_fields_count()) {}
InternalFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), k->all_fields_count()) {}
};
class AllFieldStream : public FieldStreamBase {
public:
AllFieldStream(typeArrayHandle fields, constantPoolHandle constants): FieldStreamBase(fields, constants) {}
AllFieldStream(instanceKlass* k): FieldStreamBase(k->fields(), k->constants()) {}
AllFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants()) {}
};
#endif // SHARE_VM_OOPS_FIELDSTREAMS_HPP

View File

@ -36,6 +36,7 @@
#include "memory/genOopClosures.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/permGen.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceOop.hpp"
@ -782,14 +783,11 @@ void instanceKlass::mask_for(methodHandle method, int bci,
bool instanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
const int n = fields()->length();
for (int i = 0; i < n; i += next_offset ) {
int name_index = fields()->ushort_at(i + name_index_offset);
int sig_index = fields()->ushort_at(i + signature_index_offset);
Symbol* f_name = constants()->symbol_at(name_index);
Symbol* f_sig = constants()->symbol_at(sig_index);
for (JavaFieldStream fs(as_klassOop()); !fs.done(); fs.next()) {
Symbol* f_name = fs.name();
Symbol* f_sig = fs.signature();
if (f_name == name && f_sig == sig) {
fd->initialize(as_klassOop(), i);
fd->initialize(as_klassOop(), fs.index());
return true;
}
}
@ -803,11 +801,10 @@ void instanceKlass::shared_symbols_iterate(SymbolClosure* closure) {
closure->do_symbol(&_source_file_name);
closure->do_symbol(&_source_debug_extension);
const int n = fields()->length();
for (int i = 0; i < n; i += next_offset ) {
int name_index = fields()->ushort_at(i + name_index_offset);
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
int name_index = fs.name_index();
closure->do_symbol(constants()->symbol_at_addr(name_index));
int sig_index = fields()->ushort_at(i + signature_index_offset);
int sig_index = fs.signature_index();
closure->do_symbol(constants()->symbol_at_addr(sig_index));
}
}
@ -872,10 +869,9 @@ klassOop instanceKlass::find_field(Symbol* name, Symbol* sig, bool is_static, fi
bool instanceKlass::find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const {
int length = fields()->length();
for (int i = 0; i < length; i += next_offset) {
if (offset_from_fields( i ) == offset) {
fd->initialize(as_klassOop(), i);
for (JavaFieldStream fs(as_klassOop()); !fs.done(); fs.next()) {
if (fs.offset() == offset) {
fd->initialize(as_klassOop(), fs.index());
if (fd->is_static() == is_static) return true;
}
}
@ -906,11 +902,12 @@ void instanceKlass::methods_do(void f(methodOop method)) {
void instanceKlass::do_local_static_fields(FieldClosure* cl) {
fieldDescriptor fd;
int length = fields()->length();
for (int i = 0; i < length; i += next_offset) {
fd.initialize(as_klassOop(), i);
if (fd.is_static()) cl->do_field(&fd);
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
fieldDescriptor fd;
fd.initialize(as_klassOop(), fs.index());
cl->do_field(&fd);
}
}
}
@ -922,11 +919,12 @@ void instanceKlass::do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAP
void instanceKlass::do_local_static_fields_impl(instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS) {
fieldDescriptor fd;
int length = this_oop->fields()->length();
for (int i = 0; i < length; i += next_offset) {
fd.initialize(this_oop(), i);
if (fd.is_static()) { f(&fd, CHECK); } // Do NOT remove {}! (CHECK macro expands into several statements)
for (JavaFieldStream fs(this_oop()); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
fieldDescriptor fd;
fd.initialize(this_oop(), fs.index());
f(&fd, CHECK);
}
}
}
@ -941,11 +939,11 @@ void instanceKlass::do_nonstatic_fields(FieldClosure* cl) {
super->do_nonstatic_fields(cl);
}
fieldDescriptor fd;
int length = fields()->length();
int length = java_fields_count();
// In DebugInfo nonstatic fields are sorted by offset.
int* fields_sorted = NEW_C_HEAP_ARRAY(int, 2*(length+1));
int j = 0;
for (int i = 0; i < length; i += next_offset) {
for (int i = 0; i < length; i += 1) {
fd.initialize(as_klassOop(), i);
if (!fd.is_static()) {
fields_sorted[j + 0] = fd.offset();
@ -2411,43 +2409,6 @@ void instanceKlass::oop_verify_on(oop obj, outputStream* st) {
oop_oop_iterate(obj, &blk);
}
#ifndef PRODUCT
void instanceKlass::verify_class_klass_nonstatic_oop_maps(klassOop k) {
// This verification code is disabled. JDK_Version::is_gte_jdk14x_version()
// cannot be called since this function is called before the VM is
// able to determine what JDK version is running with.
// The check below always is false since 1.4.
return;
// This verification code temporarily disabled for the 1.4
// reflection implementation since java.lang.Class now has
// Java-level instance fields. Should rewrite this to handle this
// case.
if (!(JDK_Version::is_gte_jdk14x_version() && UseNewReflection)) {
// Verify that java.lang.Class instances have a fake oop field added.
instanceKlass* ik = instanceKlass::cast(k);
// Check that we have the right class
static bool first_time = true;
guarantee(k == SystemDictionary::Class_klass() && first_time, "Invalid verify of maps");
first_time = false;
const int extra = java_lang_Class::number_of_fake_oop_fields;
guarantee(ik->nonstatic_field_size() == extra, "just checking");
guarantee(ik->nonstatic_oop_map_count() == 1, "just checking");
guarantee(ik->size_helper() == align_object_size(instanceOopDesc::header_size() + extra), "just checking");
// Check that the map is (2,extra)
int offset = java_lang_Class::klass_offset;
OopMapBlock* map = ik->start_of_nonstatic_oop_maps();
guarantee(map->offset() == offset && map->count() == (unsigned int) extra,
"sanity");
}
}
#endif // ndef PRODUCT
// JNIid class for jfieldIDs only
// Note to reviewers:
// These JNI functions are just moved over to column 1 and not changed

View File

@ -27,6 +27,7 @@
#include "oops/constMethodOop.hpp"
#include "oops/constantPoolOop.hpp"
#include "oops/fieldInfo.hpp"
#include "oops/instanceOop.hpp"
#include "oops/klassOop.hpp"
#include "oops/klassVtable.hpp"
@ -228,6 +229,7 @@ class instanceKlass: public Klass {
int _static_field_size; // number words used by static fields (oop and non-oop) in this klass
int _static_oop_field_count;// number of static oop fields in this klass
int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
int _java_fields_count; // The number of declared Java fields
bool _is_marked_dependent; // used for marking during flushing and deoptimization
bool _rewritten; // methods rewritten.
bool _has_nonstatic_fields; // for sizing with UseCompressedOops
@ -307,27 +309,28 @@ class instanceKlass: public Klass {
objArrayOop transitive_interfaces() const { return _transitive_interfaces; }
void set_transitive_interfaces(objArrayOop a) { oop_store_without_check((oop*) &_transitive_interfaces, (oop) a); }
// fields
// Field info extracted from the class file and stored
// as an array of 7 shorts
enum FieldOffset {
access_flags_offset = 0,
name_index_offset = 1,
signature_index_offset = 2,
initval_index_offset = 3,
low_offset = 4,
high_offset = 5,
generic_signature_offset = 6,
next_offset = 7
};
private:
friend class fieldDescriptor;
FieldInfo* field(int index) const { return FieldInfo::from_field_array(_fields, index); }
public:
int field_offset (int index) const { return field(index)->offset(); }
int field_access_flags(int index) const { return field(index)->access_flags(); }
Symbol* field_name (int index) const { return field(index)->name(constants()); }
Symbol* field_signature (int index) const { return field(index)->signature(constants()); }
// Number of Java declared fields
int java_fields_count() const { return _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; }
int offset_from_fields( int index ) const {
return build_int_from_shorts( fields()->ushort_at(index + low_offset),
fields()->ushort_at(index + high_offset) );
}
void set_fields(typeArrayOop f) { oop_store_without_check((oop*) &_fields, (oop) f); }
void set_fields(typeArrayOop f, int java_fields_count) {
oop_store_without_check((oop*) &_fields, (oop) f);
_java_fields_count = java_fields_count;
}
// inner classes
typeArrayOop inner_classes() const { return _inner_classes; }
@ -842,10 +845,6 @@ public:
// Verification
const char* internal_name() const;
void oop_verify_on(oop obj, outputStream* st);
#ifndef PRODUCT
static void verify_class_klass_nonstatic_oop_maps(klassOop k) PRODUCT_RETURN;
#endif
};
inline methodOop instanceKlass::method_at_vtable(int index) {

View File

@ -386,7 +386,7 @@ instanceKlassKlass::allocate_instance_klass(Symbol* name, int vtable_len, int it
ik->set_local_interfaces(NULL);
ik->set_transitive_interfaces(NULL);
ik->init_implementor();
ik->set_fields(NULL);
ik->set_fields(NULL, 0);
ik->set_constants(NULL);
ik->set_class_loader(NULL);
ik->set_protection_domain(NULL);

View File

@ -492,7 +492,7 @@ JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field))
// First check if this is a static field
if (modifiers & JVM_ACC_STATIC) {
intptr_t offset = instanceKlass::cast(k1())->offset_from_fields( slot );
intptr_t offset = instanceKlass::cast(k1())->field_offset( slot );
JNIid* id = instanceKlass::cast(k1())->jni_id_for(offset);
assert(id != NULL, "corrupt Field object");
debug_only(id->set_is_static_field_id();)
@ -504,7 +504,7 @@ JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field))
// The slot is the index of the field description in the field-array
// The jfieldID is the offset of the field within the object
// It may also have hash bits for k, if VerifyJNIFields is turned on.
intptr_t offset = instanceKlass::cast(k1())->offset_from_fields( slot );
intptr_t offset = instanceKlass::cast(k1())->field_offset( slot );
assert(instanceKlass::cast(k1())->contains_field_offset(offset), "stay within object");
ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset);
return ret;

View File

@ -32,6 +32,7 @@
#include "gc_interface/collectedHeap.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "prims/jvm.h"
@ -1493,7 +1494,7 @@ JVM_ENTRY(jbyteArray, JVM_GetFieldAnnotations(JNIEnv *env, jobject field))
fieldDescriptor fd;
KlassHandle kh(THREAD, k);
intptr_t offset = instanceKlass::cast(kh())->offset_from_fields(slot);
intptr_t offset = instanceKlass::cast(kh())->field_offset(slot);
if (modifiers & JVM_ACC_STATIC) {
// for static fields we only look in the current class
@ -1593,9 +1594,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass,
// Ensure class is linked
k->link_class(CHECK_NULL);
typeArrayHandle fields(THREAD, k->fields());
int fields_len = fields->length();
// 4496456 We need to filter out java.lang.Throwable.backtrace
bool skip_backtrace = false;
@ -1604,12 +1602,11 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass,
if (publicOnly) {
num_fields = 0;
for (int i = 0, j = 0; i < fields_len; i += instanceKlass::next_offset, j++) {
int mods = fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS;
if (mods & JVM_ACC_PUBLIC) ++num_fields;
for (JavaFieldStream fs(k()); !fs.done(); fs.next()) {
if (fs.access_flags().is_public()) ++num_fields;
}
} else {
num_fields = fields_len / instanceKlass::next_offset;
num_fields = k->java_fields_count();
if (k() == SystemDictionary::Throwable_klass()) {
num_fields--;
@ -1622,16 +1619,15 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass,
int out_idx = 0;
fieldDescriptor fd;
for (int i = 0; i < fields_len; i += instanceKlass::next_offset) {
for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
if (skip_backtrace) {
// 4496456 skip java.lang.Throwable.backtrace
int offset = k->offset_from_fields(i);
int offset = fs.offset();
if (offset == java_lang_Throwable::get_backtrace_offset()) continue;
}
int mods = fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS;
if (!publicOnly || (mods & JVM_ACC_PUBLIC)) {
fd.initialize(k(), i);
if (!publicOnly || fs.access_flags().is_public()) {
fd.initialize(k(), fs.index());
oop field = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL);
result->obj_at_put(out_idx, field);
++out_idx;
@ -2119,7 +2115,7 @@ JVM_QUICK_ENTRY(jint, JVM_GetClassFieldsCount(JNIEnv *env, jclass cls))
k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
if (!Klass::cast(k)->oop_is_instance())
return 0;
return instanceKlass::cast(k)->fields()->length() / instanceKlass::next_offset;
return instanceKlass::cast(k)->java_fields_count();
JVM_END
@ -2215,8 +2211,7 @@ JVM_QUICK_ENTRY(jint, JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field
JVMWrapper("JVM_GetFieldIxModifiers");
klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
typeArrayOop fields = instanceKlass::cast(k)->fields();
return fields->ushort_at(field_index * instanceKlass::next_offset + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS;
return instanceKlass::cast(k)->field_access_flags(field_index) & JVM_RECOGNIZED_FIELD_MODIFIERS;
JVM_END
@ -2399,7 +2394,7 @@ JVM_ENTRY(const char*, JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cls, jint
JVM_END
JVM_QUICK_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls))
JVM_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls))
JVMWrapper("JVM_GetCPFieldModifiers");
klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
klassOop k_called = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(called_cls));
@ -2411,12 +2406,9 @@ JVM_QUICK_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_in
case JVM_CONSTANT_Fieldref: {
Symbol* name = cp->uncached_name_ref_at(cp_index);
Symbol* signature = cp->uncached_signature_ref_at(cp_index);
typeArrayOop fields = instanceKlass::cast(k_called)->fields();
int fields_count = fields->length();
for (int i = 0; i < fields_count; i += instanceKlass::next_offset) {
if (cp_called->symbol_at(fields->ushort_at(i + instanceKlass::name_index_offset)) == name &&
cp_called->symbol_at(fields->ushort_at(i + instanceKlass::signature_index_offset)) == signature) {
return fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS;
for (JavaFieldStream fs(k_called); !fs.done(); fs.next()) {
if (fs.name() == name && fs.signature() == signature) {
return fs.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS;
}
}
return -1;

View File

@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "classfile/symbolTable.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "oops/fieldStreams.hpp"
#include "prims/jvmtiClassFileReconstituter.hpp"
#include "runtime/signature.hpp"
#ifdef TARGET_ARCH_x86
@ -52,25 +53,22 @@
// JVMSpec| field_info fields[fields_count];
void JvmtiClassFileReconstituter::write_field_infos() {
HandleMark hm(thread());
typeArrayHandle fields(thread(), ikh()->fields());
int fields_length = fields->length();
int num_fields = fields_length / instanceKlass::next_offset;
objArrayHandle fields_anno(thread(), ikh()->fields_annotations());
write_u2(num_fields);
for (int index = 0; index < fields_length; index += instanceKlass::next_offset) {
AccessFlags access_flags;
int flags = fields->ushort_at(index + instanceKlass::access_flags_offset);
access_flags.set_flags(flags);
int name_index = fields->ushort_at(index + instanceKlass::name_index_offset);
int signature_index = fields->ushort_at(index + instanceKlass::signature_index_offset);
int initial_value_index = fields->ushort_at(index + instanceKlass::initval_index_offset);
// Compute the real number of Java fields
int java_fields = ikh()->java_fields_count();
write_u2(java_fields * FieldInfo::field_slots);
for (JavaFieldStream fs(ikh()); !fs.done(); fs.next()) {
AccessFlags access_flags = fs.access_flags();
int name_index = fs.name_index();
int signature_index = fs.signature_index();
int initial_value_index = fs.initval_index();
guarantee(name_index != 0 && signature_index != 0, "bad constant pool index for field");
int offset = ikh()->offset_from_fields( index );
int generic_signature_index =
fields->ushort_at(index + instanceKlass::generic_signature_offset);
// int offset = ikh()->field_offset( index );
int generic_signature_index = fs.generic_signature_index();
typeArrayHandle anno(thread(), fields_anno.not_null() ?
(typeArrayOop)(fields_anno->obj_at(index / instanceKlass::next_offset)) :
(typeArrayOop)(fields_anno->obj_at(fs.index())) :
(typeArrayOop)NULL);
// JVMSpec| field_info {
@ -81,7 +79,7 @@ void JvmtiClassFileReconstituter::write_field_infos() {
// JVMSpec| attribute_info attributes[attributes_count];
// JVMSpec| }
write_u2(flags & JVM_RECOGNIZED_FIELD_MODIFIERS);
write_u2(access_flags.as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS);
write_u2(name_index);
write_u2(signature_index);
int attr_count = 0;

View File

@ -2044,7 +2044,6 @@ JvmtiEnv::SetFieldAccessWatch(fieldDescriptor* fdesc_ptr) {
// make sure we haven't set this watch before
if (fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_DUPLICATE;
fdesc_ptr->set_is_field_access_watched(true);
update_klass_field_access_flag(fdesc_ptr);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, true);
@ -2057,7 +2056,6 @@ JvmtiEnv::ClearFieldAccessWatch(fieldDescriptor* fdesc_ptr) {
// make sure we have a watch to clear
if (!fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_NOT_FOUND;
fdesc_ptr->set_is_field_access_watched(false);
update_klass_field_access_flag(fdesc_ptr);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, false);
@ -2070,7 +2068,6 @@ JvmtiEnv::SetFieldModificationWatch(fieldDescriptor* fdesc_ptr) {
// make sure we haven't set this watch before
if (fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_DUPLICATE;
fdesc_ptr->set_is_field_modification_watched(true);
update_klass_field_access_flag(fdesc_ptr);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, true);
@ -2083,7 +2080,6 @@ JvmtiEnv::ClearFieldModificationWatch(fieldDescriptor* fdesc_ptr) {
// make sure we have a watch to clear
if (!fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_NOT_FOUND;
fdesc_ptr->set_is_field_modification_watched(false);
update_klass_field_access_flag(fdesc_ptr);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, false);

View File

@ -565,15 +565,6 @@ JvmtiEnvBase::get_JavaThread(jthread jni_thread) {
}
// update the access_flags for the field in the klass
void
JvmtiEnvBase::update_klass_field_access_flag(fieldDescriptor *fd) {
instanceKlass* ik = instanceKlass::cast(fd->field_holder());
typeArrayOop fields = ik->fields();
fields->ushort_at_put(fd->index(), (jushort)fd->access_flags().as_short());
}
// return the vframe on the specified thread and depth, NULL if no such frame
vframe*
JvmtiEnvBase::vframeFor(JavaThread* java_thread, jint depth) {

View File

@ -267,8 +267,6 @@ class JvmtiEnvBase : public CHeapObj {
// convert to a jni jclass from a non-null klassOop
jclass get_jni_class_non_null(klassOop k);
void update_klass_field_access_flag(fieldDescriptor *fd);
jint count_locked_objects(JavaThread *java_thread, Handle hobj);
jvmtiError get_locked_objects_in_frame(JavaThread *calling_thread,
JavaThread* java_thread,

View File

@ -30,6 +30,7 @@
#include "interpreter/rewriter.hpp"
#include "memory/gcLocker.hpp"
#include "memory/universe.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/klassVtable.hpp"
#include "prims/jvmtiImpl.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
@ -551,41 +552,35 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
// Check if the number, names, types and order of fields declared in these classes
// are the same.
typeArrayOop k_old_fields = the_class->fields();
typeArrayOop k_new_fields = scratch_class->fields();
int n_fields = k_old_fields->length();
if (n_fields != k_new_fields->length()) {
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
}
for (i = 0; i < n_fields; i += instanceKlass::next_offset) {
JavaFieldStream old_fs(the_class);
JavaFieldStream new_fs(scratch_class);
for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) {
// access
old_flags = k_old_fields->ushort_at(i + instanceKlass::access_flags_offset);
new_flags = k_new_fields->ushort_at(i + instanceKlass::access_flags_offset);
old_flags = old_fs.access_flags().as_short();
new_flags = new_fs.access_flags().as_short();
if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) {
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
}
// offset
if (k_old_fields->short_at(i + instanceKlass::low_offset) !=
k_new_fields->short_at(i + instanceKlass::low_offset) ||
k_old_fields->short_at(i + instanceKlass::high_offset) !=
k_new_fields->short_at(i + instanceKlass::high_offset)) {
if (old_fs.offset() != new_fs.offset()) {
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
}
// name and signature
jshort name_index = k_old_fields->short_at(i + instanceKlass::name_index_offset);
jshort sig_index = k_old_fields->short_at(i +instanceKlass::signature_index_offset);
Symbol* name_sym1 = the_class->constants()->symbol_at(name_index);
Symbol* sig_sym1 = the_class->constants()->symbol_at(sig_index);
name_index = k_new_fields->short_at(i + instanceKlass::name_index_offset);
sig_index = k_new_fields->short_at(i + instanceKlass::signature_index_offset);
Symbol* name_sym2 = scratch_class->constants()->symbol_at(name_index);
Symbol* sig_sym2 = scratch_class->constants()->symbol_at(sig_index);
Symbol* name_sym1 = the_class->constants()->symbol_at(old_fs.name_index());
Symbol* sig_sym1 = the_class->constants()->symbol_at(old_fs.signature_index());
Symbol* name_sym2 = scratch_class->constants()->symbol_at(new_fs.name_index());
Symbol* sig_sym2 = scratch_class->constants()->symbol_at(new_fs.signature_index());
if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) {
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
}
}
// If both streams aren't done then we have a differing number of
// fields.
if (!old_fs.done() || !new_fs.done()) {
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
}
// Do a parallel walk through the old and new methods. Detect
// cases where they match (exist in both), have been added in
// the new methods, or have been deleted (exist only in the
@ -2369,38 +2364,34 @@ void VM_RedefineClasses::set_new_constant_pool(
int i; // for portability
// update each field in klass to use new constant pool indices as needed
typeArrayHandle fields(THREAD, scratch_class->fields());
int n_fields = fields->length();
for (i = 0; i < n_fields; i += instanceKlass::next_offset) {
jshort cur_index = fields->short_at(i + instanceKlass::name_index_offset);
for (JavaFieldStream fs(scratch_class); !fs.done(); fs.next()) {
jshort cur_index = fs.name_index();
jshort new_index = find_new_index(cur_index);
if (new_index != 0) {
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
("field-name_index change: %d to %d", cur_index, new_index));
fields->short_at_put(i + instanceKlass::name_index_offset, new_index);
fs.set_name_index(new_index);
}
cur_index = fields->short_at(i + instanceKlass::signature_index_offset);
cur_index = fs.signature_index();
new_index = find_new_index(cur_index);
if (new_index != 0) {
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
("field-signature_index change: %d to %d", cur_index, new_index));
fields->short_at_put(i + instanceKlass::signature_index_offset,
new_index);
fs.set_signature_index(new_index);
}
cur_index = fields->short_at(i + instanceKlass::initval_index_offset);
cur_index = fs.initval_index();
new_index = find_new_index(cur_index);
if (new_index != 0) {
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
("field-initval_index change: %d to %d", cur_index, new_index));
fields->short_at_put(i + instanceKlass::initval_index_offset, new_index);
fs.set_initval_index(new_index);
}
cur_index = fields->short_at(i + instanceKlass::generic_signature_offset);
cur_index = fs.generic_signature_index();
new_index = find_new_index(cur_index);
if (new_index != 0) {
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
("field-generic_signature change: %d to %d", cur_index, new_index));
fields->short_at_put(i + instanceKlass::generic_signature_offset,
new_index);
fs.set_generic_signature_index(new_index);
}
} // end for each field

View File

@ -520,7 +520,7 @@ void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) {
int slot = java_lang_reflect_Field::slot(target_oop); // fd.index()
int mods = java_lang_reflect_Field::modifiers(target_oop);
klassOop k = java_lang_Class::as_klassOop(clazz);
int offset = instanceKlass::cast(k)->offset_from_fields(slot);
int offset = instanceKlass::cast(k)->field_offset(slot);
init_MemberName(mname_oop, k, accessFlags_from(mods), offset);
} else {
KlassHandle receiver_limit; int decode_flags = 0;
@ -1632,8 +1632,6 @@ void MethodHandles::init_DirectMethodHandle(Handle mh, methodHandle m, bool do_d
THROW(vmSymbols::java_lang_InternalError());
}
java_lang_invoke_MethodHandle::init_vmslots(mh());
if (VerifyMethodHandles) {
// The privileged code which invokes this routine should not make
// a mistake about types, but it's better to verify.
@ -1756,7 +1754,6 @@ void MethodHandles::init_BoundMethodHandle_with_receiver(Handle mh,
if (m.is_null()) { THROW(vmSymbols::java_lang_InternalError()); }
if (m->is_abstract()) { THROW(vmSymbols::java_lang_AbstractMethodError()); }
java_lang_invoke_MethodHandle::init_vmslots(mh());
int vmargslot = m->size_of_parameters() - 1;
assert(java_lang_invoke_BoundMethodHandle::vmargslot(mh()) == vmargslot, "");
@ -1862,7 +1859,6 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum,
THROW(vmSymbols::java_lang_InternalError());
}
java_lang_invoke_MethodHandle::init_vmslots(mh());
int argslot = java_lang_invoke_BoundMethodHandle::vmargslot(mh());
if (VerifyMethodHandles) {
@ -2686,6 +2682,7 @@ void MethodHandles::ensure_vmlayout_field(Handle target, TRAPS) {
java_lang_invoke_MethodTypeForm::init_vmlayout(mtform(), cookie);
}
}
assert(java_lang_invoke_MethodTypeForm::vmslots(mtform()) == argument_slot_count(mtype()), "must agree");
}
#ifdef ASSERT

View File

@ -719,7 +719,7 @@ jint find_field_offset(jobject field, int must_be_static, TRAPS) {
}
}
int offset = instanceKlass::cast(k)->offset_from_fields(slot);
int offset = instanceKlass::cast(k)->field_offset(slot);
return field_offset_from_byte_offset(offset);
}

View File

@ -42,59 +42,51 @@ typeArrayOop fieldDescriptor::annotations() const {
objArrayOop md = ik->fields_annotations();
if (md == NULL)
return NULL;
assert((index() % instanceKlass::next_offset) == 0, "");
return typeArrayOop(md->obj_at(index() / instanceKlass::next_offset));
return typeArrayOop(md->obj_at(index()));
}
constantTag fieldDescriptor::initial_value_tag() const {
return constants()->tag_at(_initial_value_index);
return constants()->tag_at(initial_value_index());
}
jint fieldDescriptor::int_initial_value() const {
return constants()->int_at(_initial_value_index);
return constants()->int_at(initial_value_index());
}
jlong fieldDescriptor::long_initial_value() const {
return constants()->long_at(_initial_value_index);
return constants()->long_at(initial_value_index());
}
jfloat fieldDescriptor::float_initial_value() const {
return constants()->float_at(_initial_value_index);
return constants()->float_at(initial_value_index());
}
jdouble fieldDescriptor::double_initial_value() const {
return constants()->double_at(_initial_value_index);
return constants()->double_at(initial_value_index());
}
oop fieldDescriptor::string_initial_value(TRAPS) const {
return constants()->string_at(_initial_value_index, CHECK_0);
return constants()->string_at(initial_value_index(), CHECK_0);
}
void fieldDescriptor::initialize(klassOop k, int index) {
instanceKlass* ik = instanceKlass::cast(k);
_cp = ik->constants();
typeArrayOop fields = ik->fields();
FieldInfo* f = ik->field(index);
assert(!f->is_internal(), "regular Java fields only");
assert(fields->length() % instanceKlass::next_offset == 0, "Illegal size of field array");
assert(fields->length() >= index + instanceKlass::next_offset, "Illegal size of field array");
_access_flags.set_field_flags(fields->ushort_at(index + instanceKlass::access_flags_offset));
_name_index = fields->ushort_at(index + instanceKlass::name_index_offset);
_signature_index = fields->ushort_at(index + instanceKlass::signature_index_offset);
_initial_value_index = fields->ushort_at(index + instanceKlass::initval_index_offset);
guarantee(_name_index != 0 && _signature_index != 0, "bad constant pool index for fieldDescriptor");
_offset = ik->offset_from_fields( index );
_generic_signature_index = fields->ushort_at(index + instanceKlass::generic_signature_offset);
_access_flags = accessFlags_from(f->access_flags());
guarantee(f->name_index() != 0 && f->signature_index() != 0, "bad constant pool index for fieldDescriptor");
_index = index;
}
#ifndef PRODUCT
void fieldDescriptor::print_on(outputStream* st) const {
_access_flags.print_on(st);
constants()->symbol_at(_name_index)->print_value_on(st);
access_flags().print_on(st);
name()->print_value_on(st);
st->print(" ");
constants()->symbol_at(_signature_index)->print_value_on(st);
signature()->print_value_on(st);
st->print(" @%d ", offset());
if (WizardMode && has_initial_value()) {
st->print("(initval ");

View File

@ -40,29 +40,40 @@
class fieldDescriptor VALUE_OBJ_CLASS_SPEC {
private:
AccessFlags _access_flags;
int _name_index;
int _signature_index;
int _initial_value_index;
int _offset;
int _generic_signature_index;
int _index; // index into fields() array
int _index; // the field index
constantPoolHandle _cp;
// update the access_flags for the field in the klass
void update_klass_field_access_flag() {
instanceKlass* ik = instanceKlass::cast(field_holder());
ik->field(index())->set_access_flags(_access_flags.as_short());
}
FieldInfo* field() const {
instanceKlass* ik = instanceKlass::cast(field_holder());
return ik->field(_index);
}
public:
Symbol* name() const { return _cp->symbol_at(_name_index); }
Symbol* signature() const { return _cp->symbol_at(_signature_index); }
Symbol* name() const {
return field()->name(_cp);
}
Symbol* signature() const {
return field()->signature(_cp);
}
klassOop field_holder() const { return _cp->pool_holder(); }
constantPoolOop constants() const { return _cp(); }
AccessFlags access_flags() const { return _access_flags; }
oop loader() const;
// Offset (in words) of field from start of instanceOop / klassOop
int offset() const { return _offset; }
Symbol* generic_signature() const { return (_generic_signature_index > 0 ? _cp->symbol_at(_generic_signature_index) : (Symbol*)NULL); }
int offset() const { return field()->offset(); }
Symbol* generic_signature() const { return field()->generic_signature(_cp); }
int index() const { return _index; }
typeArrayOop annotations() const;
// Initial field value
bool has_initial_value() const { return _initial_value_index != 0; }
bool has_initial_value() const { return field()->initval_index() != 0; }
int initial_value_index() const { return field()->initval_index(); }
constantTag initial_value_tag() const; // The tag will return true on one of is_int(), is_long(), is_single(), is_double()
jint int_initial_value() const;
jlong long_initial_value() const;
@ -74,25 +85,31 @@ class fieldDescriptor VALUE_OBJ_CLASS_SPEC {
BasicType field_type() const { return FieldType::basic_type(signature()); }
// Access flags
bool is_public() const { return _access_flags.is_public(); }
bool is_private() const { return _access_flags.is_private(); }
bool is_protected() const { return _access_flags.is_protected(); }
bool is_public() const { return access_flags().is_public(); }
bool is_private() const { return access_flags().is_private(); }
bool is_protected() const { return access_flags().is_protected(); }
bool is_package_private() const { return !is_public() && !is_private() && !is_protected(); }
bool is_static() const { return _access_flags.is_static(); }
bool is_final() const { return _access_flags.is_final(); }
bool is_volatile() const { return _access_flags.is_volatile(); }
bool is_transient() const { return _access_flags.is_transient(); }
bool is_static() const { return access_flags().is_static(); }
bool is_final() const { return access_flags().is_final(); }
bool is_volatile() const { return access_flags().is_volatile(); }
bool is_transient() const { return access_flags().is_transient(); }
bool is_synthetic() const { return _access_flags.is_synthetic(); }
bool is_synthetic() const { return access_flags().is_synthetic(); }
bool is_field_access_watched() const { return _access_flags.is_field_access_watched(); }
bool is_field_access_watched() const { return access_flags().is_field_access_watched(); }
bool is_field_modification_watched() const
{ return _access_flags.is_field_modification_watched(); }
void set_is_field_access_watched(const bool value)
{ _access_flags.set_is_field_access_watched(value); }
void set_is_field_modification_watched(const bool value)
{ _access_flags.set_is_field_modification_watched(value); }
{ return access_flags().is_field_modification_watched(); }
void set_is_field_access_watched(const bool value) {
_access_flags.set_is_field_access_watched(value);
update_klass_field_access_flag();
}
void set_is_field_modification_watched(const bool value) {
_access_flags.set_is_field_modification_watched(value);
update_klass_field_access_flag();
}
// Initialization
void initialize(klassOop k, int index);

View File

@ -107,10 +107,8 @@ class MethodStream : public KlassStream {
class FieldStream : public KlassStream {
private:
int length() const { return fields()->length(); }
constantPoolOop constants() const { return _klass->constants(); }
protected:
typeArrayOop fields() const { return _klass->fields(); }
int length() const { return _klass->java_fields_count(); }
public:
FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only)
: KlassStream(klass, local_only, classes_only) {
@ -118,26 +116,23 @@ class FieldStream : public KlassStream {
next();
}
void next() { _index -= instanceKlass::next_offset; }
void next() { _index -= 1; }
// Accessors for current field
AccessFlags access_flags() const {
AccessFlags flags;
flags.set_flags(fields()->ushort_at(index() + instanceKlass::access_flags_offset));
flags.set_flags(_klass->field_access_flags(_index));
return flags;
}
Symbol* name() const {
int name_index = fields()->ushort_at(index() + instanceKlass::name_index_offset);
return constants()->symbol_at(name_index);
return _klass->field_name(_index);
}
Symbol* signature() const {
int signature_index = fields()->ushort_at(index() +
instanceKlass::signature_index_offset);
return constants()->symbol_at(signature_index);
return _klass->field_signature(_index);
}
// missing: initval()
int offset() const {
return _klass->offset_from_fields( index() );
return _klass->field_offset( index() );
}
};
@ -213,10 +208,10 @@ class FilteredFieldStream : public FieldStream {
}
int field_count();
void next() {
_index -= instanceKlass::next_offset;
_index -= 1;
if (has_filtered_field()) {
while (_index >=0 && FilteredFieldsMap::is_filtered_field((klassOop)_klass(), offset())) {
_index -= instanceKlass::next_offset;
_index -= 1;
}
}
}

View File

@ -966,7 +966,7 @@ static void call_initializeSystemClass(TRAPS) {
// General purpose hook into Java code, run once when the VM is initialized.
// The Java library method itself may be changed independently from the VM.
static void call_postVMInitHook(TRAPS) {
klassOop k = SystemDictionary::sun_misc_PostVMInitHook_klass();
klassOop k = SystemDictionary::PostVMInitHook_klass();
instanceKlassHandle klass (THREAD, k);
if (klass.not_null()) {
JavaValue result(T_VOID);

View File

@ -261,6 +261,7 @@ static inline uint64_t cast_uint64_t(size_t x)
nonstatic_field(instanceKlass, _nof_implementors, int) \
nonstatic_field(instanceKlass, _implementors[0], klassOop) \
nonstatic_field(instanceKlass, _fields, typeArrayOop) \
nonstatic_field(instanceKlass, _java_fields_count, int) \
nonstatic_field(instanceKlass, _constants, constantPoolOop) \
nonstatic_field(instanceKlass, _class_loader, oop) \
nonstatic_field(instanceKlass, _protection_domain, oop) \
@ -967,11 +968,11 @@ static inline uint64_t cast_uint64_t(size_t x)
/* java_lang_Class fields */ \
/*********************************/ \
\
static_field(java_lang_Class, klass_offset, int) \
static_field(java_lang_Class, resolved_constructor_offset, int) \
static_field(java_lang_Class, array_klass_offset, int) \
static_field(java_lang_Class, oop_size_offset, int) \
static_field(java_lang_Class, static_oop_field_count_offset, int) \
static_field(java_lang_Class, _klass_offset, int) \
static_field(java_lang_Class, _resolved_constructor_offset, int) \
static_field(java_lang_Class, _array_klass_offset, int) \
static_field(java_lang_Class, _oop_size_offset, int) \
static_field(java_lang_Class, _static_oop_field_count_offset, int) \
\
/************************/ \
/* Miscellaneous fields */ \
@ -1662,19 +1663,24 @@ static inline uint64_t cast_uint64_t(size_t x)
declare_constant(constMethodOopDesc::_has_localvariable_table) \
\
/*************************************/ \
/* instanceKlass FieldOffset enum */ \
/* instanceKlass enum */ \
/*************************************/ \
\
declare_constant(instanceKlass::access_flags_offset) \
declare_constant(instanceKlass::name_index_offset) \
declare_constant(instanceKlass::signature_index_offset) \
declare_constant(instanceKlass::initval_index_offset) \
declare_constant(instanceKlass::low_offset) \
declare_constant(instanceKlass::high_offset) \
declare_constant(instanceKlass::generic_signature_offset) \
declare_constant(instanceKlass::next_offset) \
declare_constant(instanceKlass::implementors_limit) \
\
/*************************************/ \
/* FieldInfo FieldOffset enum */ \
/*************************************/ \
\
declare_constant(FieldInfo::access_flags_offset) \
declare_constant(FieldInfo::name_index_offset) \
declare_constant(FieldInfo::signature_index_offset) \
declare_constant(FieldInfo::initval_index_offset) \
declare_constant(FieldInfo::low_offset) \
declare_constant(FieldInfo::high_offset) \
declare_constant(FieldInfo::generic_signature_offset) \
declare_constant(FieldInfo::field_slots) \
\
/************************************************/ \
/* instanceKlass InnerClassAttributeOffset enum */ \
/************************************************/ \

View File

@ -79,9 +79,14 @@ enum {
// Note that the class-related ACC_ANNOTATION bit conflicts with these flags.
JVM_ACC_FIELD_ACCESS_WATCHED = 0x00002000, // field access is watched by JVMTI
JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000, // field modification is watched by JVMTI
JVM_ACC_FIELD_INTERNAL = 0x00000400, // internal field, same as JVM_ACC_ABSTRACT
JVM_ACC_FIELD_INTERNAL_FLAGS = JVM_ACC_FIELD_ACCESS_WATCHED |
JVM_ACC_FIELD_MODIFICATION_WATCHED |
JVM_ACC_FIELD_INTERNAL,
// flags accepted by set_field_flags()
JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS
JVM_ACC_FIELD_FLAGS = JVM_RECOGNIZED_FIELD_MODIFIERS | JVM_ACC_FIELD_INTERNAL_FLAGS
};
@ -150,13 +155,17 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
bool is_field_access_watched() const { return (_flags & JVM_ACC_FIELD_ACCESS_WATCHED) != 0; }
bool is_field_modification_watched() const
{ return (_flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; }
bool is_internal() const { return (_flags & JVM_ACC_FIELD_INTERNAL) != 0; }
// get .class file flags
jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); }
// Initialization
void add_promoted_flags(jint flags) { _flags |= (flags & JVM_ACC_PROMOTED_FLAGS); }
void set_field_flags(jint flags) { _flags = (flags & JVM_ACC_FIELD_FLAGS); }
void set_field_flags(jint flags) {
assert((flags & JVM_ACC_FIELD_FLAGS) == flags, "only recognized flags");
_flags = (flags & JVM_ACC_FIELD_FLAGS);
}
void set_flags(jint flags) { _flags = (flags & JVM_ACC_WRITTEN_FLAGS); }
void set_queued_for_compilation() { atomic_set_bits(JVM_ACC_QUEUED); }
@ -218,8 +227,8 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
}
// Conversion
jshort as_short() { return (jshort)_flags; }
jint as_int() { return _flags; }
jshort as_short() const { return (jshort)_flags; }
jint as_int() const { return _flags; }
inline friend AccessFlags accessFlags_from(jint flags);