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 /** Constructor for fields that are named in an InstanceKlass's
fields array (i.e., named, non-VM fields) */ fields array (i.e., named, non-VM fields) */
Field(InstanceKlass holder, int fieldArrayIndex) { Field(InstanceKlass holder, int fieldIndex) {
this.holder = holder; this.holder = holder;
this.fieldArrayIndex = fieldArrayIndex; this.fieldIndex = fieldIndex;
ConstantPool cp = holder.getConstants(); offset = holder.getFieldOffset(fieldIndex);
TypeArray fields = holder.getFields(); genericSignature = holder.getFieldGenericSignature(fieldIndex);
short access = fields.getShortAt(fieldArrayIndex + InstanceKlass.ACCESS_FLAGS_OFFSET);
short nameIndex = fields.getShortAt(fieldArrayIndex + InstanceKlass.NAME_INDEX_OFFSET); Symbol name = holder.getFieldName(fieldIndex);
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);
id = new NamedFieldIdentifier(name.asString()); 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); fieldType = new FieldType(signature);
short access = holder.getFieldAccessFlags(fieldIndex);
accessFlags = new AccessFlags(access); accessFlags = new AccessFlags(access);
} }
@ -73,7 +65,7 @@ public class Field {
private Symbol signature; private Symbol signature;
private Symbol genericSignature; private Symbol genericSignature;
private AccessFlags accessFlags; private AccessFlags accessFlags;
private int fieldArrayIndex; private int fieldIndex;
/** Returns the byte offset of the field within the object or klass */ /** Returns the byte offset of the field within the object or klass */
public long getOffset() { return offset; } public long getOffset() { return offset; }
@ -101,8 +93,8 @@ public class Field {
/** (Named, non-VM fields only) Returns the index in the fields /** (Named, non-VM fields only) Returns the index in the fields
TypeArray for this field. Equivalent to the "index" in the VM's TypeArray for this field. Equivalent to the "index" in the VM's
fieldDescriptors. */ fieldDescriptors. */
public int getFieldArrayIndex() { public int getFieldIndex() {
return fieldArrayIndex; return fieldIndex;
} }
/** (Named, non-VM fields only) Retrieves the access flags. */ /** (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 LOW_OFFSET;
public static int HIGH_OFFSET; public static int HIGH_OFFSET;
public static int GENERIC_SIGNATURE_INDEX_OFFSET; public static int GENERIC_SIGNATURE_INDEX_OFFSET;
public static int NEXT_OFFSET; public static int FIELD_SLOTS;
public static int IMPLEMENTORS_LIMIT; public static int IMPLEMENTORS_LIMIT;
// ClassState constants // ClassState constants
@ -78,6 +78,7 @@ public class InstanceKlass extends Klass {
implementors[i] = new OopField(type.getOopField("_implementors[0]"), arrayOffset); implementors[i] = new OopField(type.getOopField("_implementors[0]"), arrayOffset);
} }
fields = new OopField(type.getOopField("_fields"), Oop.getHeaderSize()); 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()); constants = new OopField(type.getOopField("_constants"), Oop.getHeaderSize());
classLoader = new OopField(type.getOopField("_class_loader"), Oop.getHeaderSize()); classLoader = new OopField(type.getOopField("_class_loader"), Oop.getHeaderSize());
protectionDomain = new OopField(type.getOopField("_protection_domain"), 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()); headerSize = alignObjectOffset(Oop.getHeaderSize() + type.getSize());
// read field offset constants // read field offset constants
ACCESS_FLAGS_OFFSET = db.lookupIntConstant("instanceKlass::access_flags_offset").intValue(); ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue();
NAME_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::name_index_offset").intValue(); NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue();
SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::signature_index_offset").intValue(); SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue();
INITVAL_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::initval_index_offset").intValue(); INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue();
LOW_OFFSET = db.lookupIntConstant("instanceKlass::low_offset").intValue(); LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_offset").intValue();
HIGH_OFFSET = db.lookupIntConstant("instanceKlass::high_offset").intValue(); HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_offset").intValue();
GENERIC_SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::generic_signature_offset").intValue(); GENERIC_SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::generic_signature_offset").intValue();
NEXT_OFFSET = db.lookupIntConstant("instanceKlass::next_offset").intValue(); FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue();
// read ClassState constants // read ClassState constants
CLASS_STATE_UNPARSABLE_BY_GC = db.lookupIntConstant("instanceKlass::unparsable_by_gc").intValue(); CLASS_STATE_UNPARSABLE_BY_GC = db.lookupIntConstant("instanceKlass::unparsable_by_gc").intValue();
CLASS_STATE_ALLOCATED = db.lookupIntConstant("instanceKlass::allocated").intValue(); CLASS_STATE_ALLOCATED = db.lookupIntConstant("instanceKlass::allocated").intValue();
@ -131,6 +132,7 @@ public class InstanceKlass extends Klass {
private static CIntField nofImplementors; private static CIntField nofImplementors;
private static OopField[] implementors; private static OopField[] implementors;
private static OopField fields; private static OopField fields;
private static CIntField javaFieldsCount;
private static OopField constants; private static OopField constants;
private static OopField classLoader; private static OopField classLoader;
private static OopField protectionDomain; private static OopField protectionDomain;
@ -247,6 +249,34 @@ public class InstanceKlass extends Klass {
public static long getHeaderSize() { return headerSize; } 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 // Accessors for declared fields
public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); } public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); }
public ObjArray getMethods() { return (ObjArray) methods.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() { return (Klass) implementors[0].getValue(this); }
public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); } public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); }
public TypeArray getFields() { return (TypeArray) fields.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 ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
public Oop getClassLoader() { return classLoader.getValue(this); } public Oop getClassLoader() { return classLoader.getValue(this); }
public Oop getProtectionDomain() { return protectionDomain.getValue(this); } public Oop getProtectionDomain() { return protectionDomain.getValue(this); }
@ -480,8 +512,8 @@ public class InstanceKlass extends Klass {
void iterateStaticFieldsInternal(OopVisitor visitor) { void iterateStaticFieldsInternal(OopVisitor visitor) {
TypeArray fields = getFields(); TypeArray fields = getFields();
int length = (int) fields.getLength(); int length = getJavaFieldsCount();
for (int index = 0; index < length; index += NEXT_OFFSET) { for (int index = 0; index < length; index += FIELD_SLOTS) {
short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex)); FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex));
@ -502,8 +534,8 @@ public class InstanceKlass extends Klass {
} }
TypeArray fields = getFields(); TypeArray fields = getFields();
int length = (int) fields.getLength(); int length = getJavaFieldsCount();
for (int index = 0; index < length; index += NEXT_OFFSET) { for (int index = 0; index < length; index += FIELD_SLOTS) {
short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
@ -518,9 +550,9 @@ public class InstanceKlass extends Klass {
/** Field access by name. */ /** Field access by name. */
public Field findLocalField(Symbol name, Symbol sig) { public Field findLocalField(Symbol name, Symbol sig) {
TypeArray fields = getFields(); TypeArray fields = getFields();
int n = (int) fields.getLength(); int length = (int) fields.getLength();
ConstantPool cp = getConstants(); 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 nameIndex = fields.getShortAt(i + NAME_INDEX_OFFSET);
int sigIndex = fields.getShortAt(i + SIGNATURE_INDEX_OFFSET); int sigIndex = fields.getShortAt(i + SIGNATURE_INDEX_OFFSET);
Symbol f_name = cp.getSymbolAt(nameIndex); Symbol f_name = cp.getSymbolAt(nameIndex);
@ -613,9 +645,9 @@ public class InstanceKlass extends Klass {
// not including inherited fields. // not including inherited fields.
TypeArray fields = getFields(); TypeArray fields = getFields();
int length = (int) fields.getLength(); int length = getJavaFieldsCount();
List immediateFields = new ArrayList(length / NEXT_OFFSET); List immediateFields = new ArrayList(length);
for (int index = 0; index < length; index += NEXT_OFFSET) { for (int index = 0; index < length; index += FIELD_SLOTS) {
immediateFields.add(getFieldByIndex(index)); 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 // klass and oop_size are HotSpot magic fields and hence we can't
// find them from InstanceKlass for java.lang.Class. // find them from InstanceKlass for java.lang.Class.
Type jlc = db.lookupType("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()) { if (VM.getVM().isCompressedOopsEnabled()) {
klassField = new NarrowOopField(new NamedFieldIdentifier("klass"), klassOffset, true); klassField = new NarrowOopField(new NamedFieldIdentifier("klass"), klassOffset, true);
} else { } else {
klassField = new OopField(new NamedFieldIdentifier("klass"), klassOffset, true); 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); 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 { protected void writeFields() throws IOException {
TypeArray fields = klass.getFields(); TypeArray fields = klass.getFields();
final int length = (int) fields.getLength(); final int length = klass.getJavaFieldsCount();
// write number of fields // write number of fields
dos.writeShort((short) (length / InstanceKlass.NEXT_OFFSET) ); dos.writeShort((short) (length / InstanceKlass.FIELD_SLOTS) );
if (DEBUG) debugMessage("number of fields = " 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); short accessFlags = fields.getShortAt(index + InstanceKlass.ACCESS_FLAGS_OFFSET);
dos.writeShort(accessFlags & (short) JVM_RECOGNIZED_FIELD_MODIFIERS); dos.writeShort(accessFlags & (short) JVM_RECOGNIZED_FIELD_MODIFIERS);

View file

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

View file

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

View file

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

View file

@ -3257,16 +3257,11 @@ void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register m
Register temp_reg) { Register temp_reg) {
assert_different_registers(vmslots_reg, mh_reg, temp_reg); assert_different_registers(vmslots_reg, mh_reg, temp_reg);
// load mh.type.form.vmslots // 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; 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(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); 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); ld( Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg);
} }
}
void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg, bool emit_delayed_nop) { void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg, bool emit_delayed_nop) {
@ -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); cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop);
nop(); // Separate short branches nop(); // Separate short branches
} }

View file

@ -8004,16 +8004,11 @@ void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register m
Register temp_reg) { Register temp_reg) {
assert_different_registers(vmslots_reg, mh_reg, temp_reg); assert_different_registers(vmslots_reg, mh_reg, temp_reg);
// load mh.type.form.vmslots // 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; 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(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))); 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))); movl(vmslots_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)));
} }
}
// registers on entry: // registers on entry:

View file

@ -31,6 +31,7 @@
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "runtime/fieldDescriptor.hpp" #include "runtime/fieldDescriptor.hpp"
// ciInstanceKlass // ciInstanceKlass
@ -412,7 +413,7 @@ GrowableArray<ciField*>* ciInstanceKlass::non_static_fields() {
VM_ENTRY_MARK; VM_ENTRY_MARK;
ciEnv* curEnv = ciEnv::current(); ciEnv* curEnv = ciEnv::current();
instanceKlass* ik = get_instanceKlass(); 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(); Arena* arena = curEnv->arena();
_non_static_fields = _non_static_fields =
@ -476,23 +477,6 @@ int ciInstanceKlass::compute_nonstatic_fields() {
// Now sort them by offset, ascending. // Now sort them by offset, ascending.
// (In principle, they could mix with superclass fields.) // (In principle, they could mix with superclass fields.)
fields->sort(sort_field_by_offset); 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; _nonstatic_fields = fields;
return flen; return flen;
} }
@ -505,22 +489,12 @@ ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*>*
int flen = 0; int flen = 0;
GrowableArray<ciField*>* fields = NULL; GrowableArray<ciField*>* fields = NULL;
instanceKlass* k = get_instanceKlass(); instanceKlass* k = get_instanceKlass();
typeArrayOop fields_array = k->fields(); for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
for (int pass = 0; pass <= 1; pass++) { if (fs.access_flags().is_static()) continue;
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; flen += 1;
} else {
ciField* field = new (arena) ciField(&fd);
fields->append(field);
}
} }
// Between passes, allocate the array: // allocate the array:
if (pass == 0) {
if (flen == 0) { if (flen == 0) {
return NULL; // return nothing if none are locally declared return NULL; // return nothing if none are locally declared
} }
@ -531,7 +505,13 @@ ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*>*
if (super_fields != NULL) { if (super_fields != NULL) {
fields->appendAll(super_fields); 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"); assert(fields->length() == flen, "sanity");
return fields; return fields;

View file

@ -36,6 +36,7 @@
#include "memory/oopFactory.hpp" #include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp" #include "memory/universe.inline.hpp"
#include "oops/constantPoolOop.hpp" #include "oops/constantPoolOop.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/instanceKlass.hpp" #include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp" #include "oops/instanceMirrorKlass.hpp"
#include "oops/klass.inline.hpp" #include "oops/klass.inline.hpp"
@ -991,42 +992,98 @@ enum FieldAllocationType {
STATIC_BYTE, // Boolean, Byte, char STATIC_BYTE, // Boolean, Byte, char
STATIC_SHORT, // shorts STATIC_SHORT, // shorts
STATIC_WORD, // ints STATIC_WORD, // ints
STATIC_DOUBLE, // long or double STATIC_DOUBLE, // aligned long or double
STATIC_ALIGNED_DOUBLE,// aligned long or double
NONSTATIC_OOP, NONSTATIC_OOP,
NONSTATIC_BYTE, NONSTATIC_BYTE,
NONSTATIC_SHORT, NONSTATIC_SHORT,
NONSTATIC_WORD, NONSTATIC_WORD,
NONSTATIC_DOUBLE, 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 { typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name,
unsigned int static_oop_count; constantPoolHandle cp, bool is_interface,
unsigned int static_byte_count; FieldAllocationCount *fac,
unsigned int static_short_count; objArrayHandle* fields_annotations,
unsigned int static_word_count; int* java_fields_count_ptr, TRAPS) {
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) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
typeArrayHandle nullHandle; typeArrayHandle nullHandle;
cfs->guarantee_more(2, CHECK_(nullHandle)); // length cfs->guarantee_more(2, CHECK_(nullHandle)); // length
u2 length = cfs->get_u2_fast(); 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] // 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); typeArrayHandle fields(THREAD, new_fields);
int index = 0;
typeArrayHandle field_annotations; typeArrayHandle field_annotations;
for (int n = 0; n < length; n++) { for (int n = 0; n < length; n++) {
cfs->guarantee_more(8, CHECK_(nullHandle)); // access_flags, name_index, descriptor_index, attributes_count 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()); FieldInfo* field = FieldInfo::from_field_array(fields(), n);
fields->short_at_put(index++, name_index); field->initialize(access_flags.as_short(),
fields->short_at_put(index++, signature_index); name_index,
fields->short_at_put(index++, constantvalue_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 // Remember how many oops we encountered and compute allocation type
BasicType type = cp->basic_type_for_signature_at(signature_index); FieldAllocationType atype = fac->update(is_static, type);
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");
}
}
// The correct offset is computed later (all oop fields will be located together) // The correct offset is computed later (all oop fields will be located together)
// We temporarily store the allocation type in the offset field // We temporarily store the allocation type in the offset field
fields->short_at_put(index++, atype); field->set_offset(atype);
fields->short_at_put(index++, 0); // Clear out high word of byte offset }
fields->short_at_put(index++, generic_signature_index);
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) { if (_need_verify && length > 1) {
@ -1175,11 +1216,9 @@ typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_int
bool dup = false; bool dup = false;
{ {
debug_only(No_Safepoint_Verifier nsv;) debug_only(No_Safepoint_Verifier nsv;)
for (int i = 0; i < length*instanceKlass::next_offset; i += instanceKlass::next_offset) { for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
int name_index = fields->ushort_at(i + instanceKlass::name_index_offset); Symbol* name = fs.name();
Symbol* name = cp->symbol_at(name_index); Symbol* sig = fs.signature();
int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset);
Symbol* sig = cp->symbol_at(sig_index);
// If no duplicates, add name/signature in hashtable names_and_sigs. // If no duplicates, add name/signature in hashtable names_and_sigs.
if (!put_after_lookup(name, sig, names_and_sigs)) { if (!put_after_lookup(name, sig, names_and_sigs)) {
dup = true; 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, instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
Handle class_loader, Handle class_loader,
Handle protection_domain, 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)); 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) // Fields (offsets are filled in later)
struct FieldAllocationCount fac = {0,0,0,0,0,0,0,0,0,0}; FieldAllocationCount fac;
objArrayHandle fields_annotations; 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 // Methods
bool has_final_method = false; bool has_final_method = false;
AccessFlags promoted_flags; AccessFlags promoted_flags;
@ -3146,51 +2967,33 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// Calculate the starting byte offsets // Calculate the starting byte offsets
next_static_oop_offset = instanceMirrorKlass::offset_of_static_fields(); next_static_oop_offset = instanceMirrorKlass::offset_of_static_fields();
next_static_double_offset = next_static_oop_offset + next_static_double_offset = next_static_oop_offset +
(fac.static_oop_count * heapOopSize); (fac.count[STATIC_OOP] * heapOopSize);
if ( fac.static_double_count && if ( fac.count[STATIC_DOUBLE] &&
(Universe::field_type_should_be_aligned(T_DOUBLE) || (Universe::field_type_should_be_aligned(T_DOUBLE) ||
Universe::field_type_should_be_aligned(T_LONG)) ) { Universe::field_type_should_be_aligned(T_LONG)) ) {
next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong); next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong);
} }
next_static_word_offset = next_static_double_offset + 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 + 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 + 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 + 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 - static_field_size = (next_static_type_offset -
next_static_oop_offset) / wordSize; 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() + first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
nonstatic_field_size * heapOopSize; nonstatic_field_size * heapOopSize;
next_nonstatic_field_offset = first_nonstatic_field_offset; next_nonstatic_field_offset = first_nonstatic_field_offset;
// adjust the vmentry field declaration in java.lang.invoke.MethodHandle unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE];
if (EnableInvokeDynamic && class_name == vmSymbols::java_lang_invoke_MethodHandle() && class_loader.is_null()) { unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD];
java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); 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];
// 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;
bool super_has_nonstatic_fields = bool super_has_nonstatic_fields =
(super_klass() != NULL && super_klass->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( nonstatic_oop_counts = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, unsigned int, nonstatic_oop_count + 1); 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 #ifndef PRODUCT
if( PrintCompactFieldsSavings ) { if( PrintCompactFieldsSavings ) {
@ -3378,10 +3168,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// Iterate over fields again and compute correct offsets. // Iterate over fields again and compute correct offsets.
// The field allocation type was temporarily stored in the offset slot. // The field allocation type was temporarily stored in the offset slot.
// oop fields are located before non-oop fields (static and non-static). // oop fields are located before non-oop fields (static and non-static).
int len = fields->length(); for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
for (int i = 0; i < len; i += instanceKlass::next_offset) {
int real_offset; int real_offset;
FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset); FieldAllocationType atype = (FieldAllocationType) fs.offset();
switch (atype) { switch (atype) {
case STATIC_OOP: case STATIC_OOP:
real_offset = next_static_oop_offset; real_offset = next_static_oop_offset;
@ -3399,7 +3188,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
real_offset = next_static_word_offset; real_offset = next_static_word_offset;
next_static_word_offset += BytesPerInt; next_static_word_offset += BytesPerInt;
break; break;
case STATIC_ALIGNED_DOUBLE:
case STATIC_DOUBLE: case STATIC_DOUBLE:
real_offset = next_static_double_offset; real_offset = next_static_double_offset;
next_static_double_offset += BytesPerLong; next_static_double_offset += BytesPerLong;
@ -3461,7 +3249,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
next_nonstatic_word_offset += BytesPerInt; next_nonstatic_word_offset += BytesPerInt;
} }
break; break;
case NONSTATIC_ALIGNED_DOUBLE:
case NONSTATIC_DOUBLE: case NONSTATIC_DOUBLE:
real_offset = next_nonstatic_double_offset; real_offset = next_nonstatic_double_offset;
next_nonstatic_double_offset += BytesPerLong; next_nonstatic_double_offset += BytesPerLong;
@ -3469,8 +3256,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
default: default:
ShouldNotReachHere(); ShouldNotReachHere();
} }
fields->short_at_put(i + instanceKlass::low_offset, extract_low_short_from_int(real_offset)); fs.set_offset(real_offset);
fields->short_at_put(i + instanceKlass::high_offset, extract_high_short_from_int(real_offset));
} }
// Size of instances // Size of instances
@ -3517,12 +3303,12 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
this_klass->set_class_loader(class_loader()); this_klass->set_class_loader(class_loader());
this_klass->set_nonstatic_field_size(nonstatic_field_size); this_klass->set_nonstatic_field_size(nonstatic_field_size);
this_klass->set_has_nonstatic_fields(has_nonstatic_fields); 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()); cp->set_pool_holder(this_klass());
error_handler.set_in_error(false); // turn off error handler for cp error_handler.set_in_error(false); // turn off error handler for cp
this_klass->set_constants(cp()); this_klass->set_constants(cp());
this_klass->set_local_interfaces(local_interfaces()); 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()); this_klass->set_methods(methods());
if (has_final_method) { if (has_final_method) {
this_klass->set_has_final_method(); this_klass->set_has_final_method();

View file

@ -33,6 +33,9 @@
#include "utilities/accessFlags.hpp" #include "utilities/accessFlags.hpp"
class TempNewSymbol; class TempNewSymbol;
class FieldAllocationCount;
// Parser for for .class files // Parser for for .class files
// //
// The bytes describing the class file structure is read from a Stream object // 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, bool* is_synthetic_addr,
u2* generic_signature_index_addr, u2* generic_signature_index_addr,
typeArrayHandle* field_annotations, TRAPS); typeArrayHandle* field_annotations, TRAPS);
typeArrayHandle parse_fields(constantPoolHandle cp, bool is_interface, typeArrayHandle parse_fields(Symbol* class_name,
struct FieldAllocationCount *fac, constantPoolHandle cp, bool is_interface,
objArrayHandle* fields_annotations, TRAPS); FieldAllocationCount *fac,
objArrayHandle* fields_annotations,
int* java_fields_count_ptr, TRAPS);
// Method parsing // Method parsing
methodHandle parse_method(constantPoolHandle cp, bool is_interface, 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 compute_transitive_interfaces(instanceKlassHandle super,
objArrayHandle local_ifs, TRAPS); 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 // Format checker methods
void classfile_parse_error(const char* msg, TRAPS); void classfile_parse_error(const char* msg, TRAPS);
void classfile_parse_error(const char* msg, int index, TRAPS); void classfile_parse_error(const char* msg, int index, TRAPS);

View file

@ -33,6 +33,7 @@
#include "memory/oopFactory.hpp" #include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp" #include "memory/universe.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/instanceKlass.hpp" #include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp" #include "oops/instanceMirrorKlass.hpp"
#include "oops/klass.hpp" #include "oops/klass.hpp"
@ -58,6 +59,49 @@
# include "thread_windows.inline.hpp" # include "thread_windows.inline.hpp"
#endif #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, static bool find_field(instanceKlass* ik,
Symbol* name_symbol, Symbol* signature_symbol, Symbol* name_symbol, Symbol* signature_symbol,
fieldDescriptor* fd, 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) { void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) {
assert(instanceMirrorKlass::offset_of_static_fields() != 0, "must have been computed already"); assert(instanceMirrorKlass::offset_of_static_fields() != 0, "must have been computed already");
if (k->oop_is_instance()) { if (k->oop_is_instance()) {
// Fixup the offsets // During bootstrap, java.lang.Class wasn't loaded so static field
instanceKlass::cast(k())->do_local_static_fields(&fixup_static_field, CHECK); // 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); create_mirror(k, CHECK);
} }
@ -462,7 +501,7 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
// Allocate mirror (java.lang.Class instance) // Allocate mirror (java.lang.Class instance)
Handle mirror = instanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0); Handle mirror = instanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0);
// Setup indirections // Setup indirections
mirror->obj_field_put(klass_offset, k()); mirror->obj_field_put(_klass_offset, k());
k->set_java_mirror(mirror()); k->set_java_mirror(mirror());
instanceMirrorKlass* mk = instanceMirrorKlass::cast(mirror->klass()); 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) { int java_lang_Class::oop_size(oop java_class) {
assert(oop_size_offset != 0, "must be set"); assert(_oop_size_offset != 0, "must be set");
return java_class->int_field(oop_size_offset); return java_class->int_field(_oop_size_offset);
} }
void java_lang_Class::set_oop_size(oop java_class, int size) { void java_lang_Class::set_oop_size(oop java_class, int size) {
assert(oop_size_offset != 0, "must be set"); assert(_oop_size_offset != 0, "must be set");
java_class->int_field_put(oop_size_offset, size); java_class->int_field_put(_oop_size_offset, size);
} }
int java_lang_Class::static_oop_field_count(oop java_class) { int java_lang_Class::static_oop_field_count(oop java_class) {
assert(static_oop_field_count_offset != 0, "must be set"); assert(_static_oop_field_count_offset != 0, "must be set");
return java_class->int_field(static_oop_field_count_offset); return java_class->int_field(_static_oop_field_count_offset);
} }
void java_lang_Class::set_static_oop_field_count(oop java_class, int size) { void java_lang_Class::set_static_oop_field_count(oop java_class, int size) {
assert(static_oop_field_count_offset != 0, "must be set"); assert(_static_oop_field_count_offset != 0, "must be set");
java_class->int_field_put(static_oop_field_count_offset, size); 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) { 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 // This should be improved by adding a field at the Java level or by
// introducing a new VM klass (see comment in ClassFileParser) // 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) { klassOop java_lang_Class::as_klassOop(oop java_class) {
//%note memory_2 //%note memory_2
assert(java_lang_Class::is_instance(java_class), "must be a Class object"); 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"); assert(k == NULL || k->is_klass(), "type check");
return k; 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 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"); assert(k == NULL || k->is_klass() && Klass::cast(k)->oop_is_javaArray(), "should be array klass");
return k; 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) { 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"); 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) { 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"); assert(constructor == NULL || constructor->is_method(), "should be method");
return methodOop(constructor); 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) { void java_lang_Class::set_resolved_constructor(oop java_class, methodOop constructor) {
assert(constructor->is_method(), "should be method"); 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) { bool java_lang_Class::is_primitive(oop java_class) {
// should assert: // should assert:
//assert(java_lang_Class::is_instance(java_class), "must be a Class object"); //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; return k == NULL;
} }
BasicType java_lang_Class::primitive_type(oop java_class) { BasicType java_lang_Class::primitive_type(oop java_class) {
assert(java_lang_Class::is_primitive(java_class), "just checking"); 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; BasicType type = T_VOID;
if (ak != NULL) { if (ak != NULL) {
// Note: create_basic_type_mirror above initializes ak to a non-null value. // 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; bool java_lang_Class::offsets_computed = false;
int java_lang_Class::classRedefinedCount_offset = -1; int java_lang_Class::classRedefinedCount_offset = -1;
int java_lang_Class::parallelCapable_offset = -1;
void java_lang_Class::compute_offsets() { void java_lang_Class::compute_offsets() {
assert(!offsets_computed, "offsets should be initialized only once"); assert(!offsets_computed, "offsets should be initialized only once");
offsets_computed = true; offsets_computed = true;
klassOop k = SystemDictionary::Class_klass(); klassOop klass_oop = SystemDictionary::Class_klass();
// The classRedefinedCount field is only present starting in 1.5, // The classRedefinedCount field is only present starting in 1.5,
// so don't go fatal. // so don't go fatal.
compute_optional_offset(classRedefinedCount_offset, 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, CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
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);
} }
int java_lang_Class::classRedefinedCount(oop the_class_mirror) { 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::_type_offset;
int java_lang_invoke_MethodHandle::_vmtarget_offset; int java_lang_invoke_MethodHandle::_vmtarget_offset;
int java_lang_invoke_MethodHandle::_vmentry_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::_clazz_offset;
int java_lang_invoke_MemberName::_name_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; int java_lang_invoke_CountingMethodHandle::_vmcount_offset;
void java_lang_invoke_MethodHandle::compute_offsets() { void java_lang_invoke_MethodHandle::compute_offsets() {
klassOop k = SystemDictionary::MethodHandle_klass(); klassOop klass_oop = SystemDictionary::MethodHandle_klass();
if (k != NULL && EnableInvokeDynamic) { if (klass_oop != NULL && EnableInvokeDynamic) {
bool allow_super = false; bool allow_super = false;
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super); compute_offset(_type_offset, klass_oop, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super);
compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), allow_super); METHODHANDLE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
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);
} }
} }
void java_lang_invoke_MemberName::compute_offsets() { void java_lang_invoke_MemberName::compute_offsets() {
klassOop k = SystemDictionary::MemberName_klass(); klassOop klass_oop = SystemDictionary::MemberName_klass();
if (k != NULL && EnableInvokeDynamic) { if (klass_oop != NULL && EnableInvokeDynamic) {
compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); compute_offset(_clazz_offset, klass_oop, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(_name_offset, klass_oop, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature()); compute_offset(_type_offset, klass_oop, vmSymbols::type_name(), vmSymbols::object_signature());
compute_offset(_flags_offset, k, vmSymbols::flags_name(), vmSymbols::int_signature()); compute_offset(_flags_offset, klass_oop, vmSymbols::flags_name(), vmSymbols::int_signature());
compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature()); compute_offset(_vmindex_offset, klass_oop, vmSymbols::vmindex_name(), vmSymbols::int_signature());
compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature()); MEMBERNAME_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
} }
} }
void java_lang_invoke_DirectMethodHandle::compute_offsets() { void java_lang_invoke_DirectMethodHandle::compute_offsets() {
klassOop k = SystemDictionary::DirectMethodHandle_klass(); klassOop k = SystemDictionary::DirectMethodHandle_klass();
if (k != NULL && EnableInvokeDynamic) { 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); 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 // fetch type.form.vmslots, which is the number of JVM stack slots
// required to carry the arguments of this MH // 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); oop mtype = type(mh);
if (mtype == NULL) return 0; // Java code would get NPE if (mtype == NULL) return 0; // Java code would get NPE
oop form = java_lang_invoke_MethodType::form(mtype); 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(_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); 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 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 // 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) { oop java_lang_ClassLoader::parent(oop loader) {
assert(loader->is_oop(), "loader must be oop"); 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) { bool java_lang_ClassLoader::is_trusted_loader(oop loader) {
// Fix for 4474172; see evaluation for more details // Fix for 4474172; see evaluation for more details
loader = non_reflection_class_loader(loader); 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::offset_offset;
int java_lang_String::count_offset; int java_lang_String::count_offset;
int java_lang_String::hash_offset; int java_lang_String::hash_offset;
int java_lang_Class::klass_offset; int java_lang_Class::_klass_offset;
int java_lang_Class::array_klass_offset; int java_lang_Class::_array_klass_offset;
int java_lang_Class::resolved_constructor_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::oop_size_offset; int java_lang_Class::_static_oop_field_count_offset;
int java_lang_Class::static_oop_field_count_offset;
int java_lang_Throwable::backtrace_offset; int java_lang_Throwable::backtrace_offset;
int java_lang_Throwable::detailMessage_offset; int java_lang_Throwable::detailMessage_offset;
int java_lang_Throwable::cause_offset; int java_lang_Throwable::cause_offset;
@ -2925,20 +2941,20 @@ int java_nio_Buffer::limit_offset() {
void java_nio_Buffer::compute_offsets() { 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+"); assert(k != NULL, "must be loaded in 1.4+");
compute_offset(_limit_offset, k, vmSymbols::limit_name(), vmSymbols::int_signature()); compute_offset(_limit_offset, k, vmSymbols::limit_name(), vmSymbols::int_signature());
} }
// Support for intrinsification of sun.misc.AtomicLongCSImpl.attemptUpdate // Support for intrinsification of sun.misc.AtomicLongCSImpl.attemptUpdate
int sun_misc_AtomicLongCSImpl::value_offset() { 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; return _value_offset;
} }
void sun_misc_AtomicLongCSImpl::compute_offsets() { 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 this class is not present, its value field offset won't be referenced.
if (k != NULL) { if (k != NULL) {
compute_offset(_value_offset, k, vmSymbols::value_name(), vmSymbols::long_signature()); 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::count_offset = java_lang_String::offset_offset + sizeof (jint);
java_lang_String::hash_offset = java_lang_String::count_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 // Throwable Class
java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header; 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; 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 // Compute non-hard-coded field offsets of all the classes in this file
void JavaClasses::compute_offsets() { void JavaClasses::compute_offsets() {
// java_lang_Class::compute_offsets was called earlier in bootstrap
java_lang_Class::compute_offsets(); java_lang_ClassLoader::compute_offsets();
java_lang_Thread::compute_offsets(); java_lang_Thread::compute_offsets();
java_lang_ThreadGroup::compute_offsets(); java_lang_ThreadGroup::compute_offsets();
if (EnableInvokeDynamic) { if (EnableInvokeDynamic) {
@ -3267,6 +3266,23 @@ void JavaClasses::check_offsets() {
#endif // PRODUCT #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() { void javaClasses_init() {
JavaClasses::compute_offsets(); JavaClasses::compute_offsets();
JavaClasses::check_offsets(); JavaClasses::check_offsets();

View file

@ -156,30 +156,32 @@ class java_lang_String : AllStatic {
// Interface to java.lang.Class objects // 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 { class java_lang_Class : AllStatic {
friend class VMStructs; friend class VMStructs;
private: private:
// The fake offsets are added by the class loader when java.lang.Class is loaded // The fake offsets are added by the class loader when java.lang.Class is loaded
enum { static int _klass_offset;
hc_number_of_fake_oop_fields = 3, static int _resolved_constructor_offset;
hc_number_of_fake_int_fields = 2 static int _array_klass_offset;
};
static int klass_offset; static int _oop_size_offset;
static int resolved_constructor_offset; static int _static_oop_field_count_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 void compute_offsets();
static bool offsets_computed; static bool offsets_computed;
static int classRedefinedCount_offset; static int classRedefinedCount_offset;
static int parallelCapable_offset;
public: public:
static void compute_offsets();
// Instance creation // Instance creation
static oop create_mirror(KlassHandle k, TRAPS); static oop create_mirror(KlassHandle k, TRAPS);
static void fixup_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 klassOop array_klass(oop java_class);
static void set_array_klass(oop java_class, klassOop klass); static void set_array_klass(oop java_class, klassOop klass);
// compiler support for class operations // compiler support for class operations
static int klass_offset_in_bytes() { return klass_offset; } static int klass_offset_in_bytes() { return _klass_offset; }
static int resolved_constructor_offset_in_bytes() { return resolved_constructor_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 array_klass_offset_in_bytes() { return _array_klass_offset; }
// Support for classRedefinedCount field // Support for classRedefinedCount field
static int classRedefinedCount(oop the_class_mirror); static int classRedefinedCount(oop the_class_mirror);
static void set_classRedefinedCount(oop the_class_mirror, int value); 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 int oop_size(oop java_class);
static void set_oop_size(oop java_class, int size); static void set_oop_size(oop java_class, int size);
@ -834,6 +834,10 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
// Interface to java.lang.invoke.MethodHandle objects // 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 MethodHandleEntry;
class java_lang_invoke_MethodHandle: AllStatic { class java_lang_invoke_MethodHandle: AllStatic {
@ -843,7 +847,6 @@ class java_lang_invoke_MethodHandle: AllStatic {
static int _vmentry_offset; // assembly code trampoline for MH static int _vmentry_offset; // assembly code trampoline for MH
static int _vmtarget_offset; // class-specific target reference static int _vmtarget_offset; // class-specific target reference
static int _type_offset; // the MethodType of this MH static int _type_offset; // the MethodType of this MH
static int _vmslots_offset; // OPTIONAL hoisted type.form.vmslots
static void compute_offsets(); static void compute_offsets();
@ -859,8 +862,6 @@ class java_lang_invoke_MethodHandle: AllStatic {
static void set_vmentry(oop mh, MethodHandleEntry* data); static void set_vmentry(oop mh, MethodHandleEntry* data);
static int vmslots(oop mh); static int vmslots(oop mh);
static void init_vmslots(oop mh);
static int compute_vmslots(oop mh);
// Testers // Testers
static bool is_subclass(klassOop klass) { 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 type_offset_in_bytes() { return _type_offset; }
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; } static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
static int vmentry_offset_in_bytes() { return _vmentry_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 { class java_lang_invoke_DirectMethodHandle: public java_lang_invoke_MethodHandle {
friend class JavaClasses; friend class JavaClasses;
private: private:
// _vmtarget_offset; // method or class or interface
static int _vmindex_offset; // negative or vtable idx or itable idx static int _vmindex_offset; // negative or vtable idx or itable idx
static void compute_offsets(); 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 // Interface to java.lang.invoke.MemberName objects
// (These are a private interface for Java code to query the class hierarchy.) // (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 { class java_lang_invoke_MemberName: AllStatic {
friend class JavaClasses; friend class JavaClasses;
@ -1121,6 +1126,10 @@ class java_lang_invoke_MethodType: AllStatic {
static int form_offset_in_bytes() { return _form_offset; } 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 { class java_lang_invoke_MethodTypeForm: AllStatic {
friend class JavaClasses; friend class JavaClasses;
@ -1135,6 +1144,8 @@ class java_lang_invoke_MethodTypeForm: AllStatic {
public: public:
// Accessors // Accessors
static int vmslots(oop mtform); static int vmslots(oop mtform);
static void set_vmslots(oop mtform, int vmslots);
static oop erasedType(oop mtform); static oop erasedType(oop mtform);
static oop genericInvoker(oop mtform); static oop genericInvoker(oop mtform);
@ -1156,8 +1167,6 @@ class java_lang_invoke_CallSite: AllStatic {
private: private:
static int _target_offset; static int _target_offset;
static int _caller_method_offset;
static int _caller_bci_offset;
static void compute_offsets(); static void compute_offsets();
@ -1169,12 +1178,6 @@ public:
static volatile oop target_volatile(oop site) { return site->obj_field_volatile( _target_offset); } 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 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 // Testers
static bool is_subclass(klassOop klass) { static bool is_subclass(klassOop klass) {
return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass()); return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass());
@ -1185,8 +1188,6 @@ public:
// Accessors for code generation: // Accessors for code generation:
static int target_offset_in_bytes() { return _target_offset; } 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 hc_parent_offset = 0
}; };
static bool offsets_computed;
static int parent_offset; static int parent_offset;
static int parallelCapable_offset;
static void compute_offsets();
public: public:
static oop parent(oop loader); static oop parent(oop loader);
// Support for parallelCapable field
static bool parallelCapable(oop the_class_mirror);
static bool is_trusted_loader(oop loader); static bool is_trusted_loader(oop loader);
// Fix for 4474172 // Fix for 4474172
@ -1343,17 +1351,71 @@ class java_util_concurrent_locks_AbstractOwnableSynchronizer : AllStatic {
static oop get_owner_threadObj(oop obj); 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 // Interface to hard-coded offset checking
class JavaClasses : AllStatic { class JavaClasses : AllStatic {
private: 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_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_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; static bool check_constant(const char *klass_name, int constant, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
public: 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_hard_coded_offsets();
static void compute_offsets(); static void compute_offsets();
static void check_offsets() PRODUCT_RETURN; 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 #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) { bool SystemDictionary::is_parallelCapable(Handle class_loader) {
if (UnsyncloadClass || class_loader.is_null()) return true; if (UnsyncloadClass || class_loader.is_null()) return true;
if (AlwaysLockClassLoader) return false; 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 // ParallelDefineClass flag does not apply to bootclass loader
bool SystemDictionary::is_parallelDefine(Handle class_loader) { bool SystemDictionary::is_parallelDefine(Handle class_loader) {
if (class_loader.is_null()) return false; 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 true;
} }
return false; return false;
@ -1290,7 +1290,7 @@ static instanceKlassHandle download_and_retry_class_load(
Symbol* class_name, Symbol* class_name,
TRAPS) { TRAPS) {
klassOop dlm = SystemDictionary::sun_jkernel_DownloadManager_klass(); klassOop dlm = SystemDictionary::DownloadManager_klass();
instanceKlassHandle nk; instanceKlassHandle nk;
// If download manager class isn't loaded just return. // If download manager class isn't loaded just return.
@ -1953,7 +1953,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
// first do Object, String, Class // first do Object, String, Class
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK); 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. // Fixup mirrors for classes loaded before java.lang.Class.
// These calls iterate over the objects currently in the perm gen // 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); //_box_klasses[T_ARRAY] = WK_KLASS(object_klass);
#ifdef KERNEL #ifdef KERNEL
if (sun_jkernel_DownloadManager_klass() == NULL) { if (DownloadManager_klass() == NULL) {
warning("Cannot find sun/jkernel/DownloadManager"); warning("Cannot find sun/jkernel/DownloadManager");
} }
#endif // KERNEL #endif // KERNEL
@ -2736,7 +2736,7 @@ class ClassStatistics: AllStatic {
class_size += ik->local_interfaces()->size(); class_size += ik->local_interfaces()->size();
class_size += ik->transitive_interfaces()->size(); class_size += ik->transitive_interfaces()->size();
// We do not have to count implementors, since we only store one! // 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

@ -168,14 +168,14 @@ class SymbolPropertyTable;
template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \ template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ /* 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. */ \ /* 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. */ \ /* 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 */ \ /* Preload boxing klasses */ \
template(Boolean_klass, java_lang_Boolean, Pre) \ template(Boolean_klass, java_lang_Boolean, Pre) \
@ -199,7 +199,7 @@ class SystemDictionary : AllStatic {
enum WKID { enum WKID {
NO_WKID = 0, 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) WK_KLASSES_DO(WK_KLASS_ENUM)
#undef WK_KLASS_ENUM #undef WK_KLASS_ENUM
@ -426,11 +426,16 @@ public:
} }
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)]); } static klassOop name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); }
WK_KLASSES_DO(WK_KLASS_DECLARE); WK_KLASSES_DO(WK_KLASS_DECLARE);
#undef 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: // Local definition for direct access to the private array:
#define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)] #define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]

View file

@ -264,8 +264,8 @@
template(setTargetNormal_name, "setTargetNormal") \ template(setTargetNormal_name, "setTargetNormal") \
template(setTargetVolatile_name, "setTargetVolatile") \ template(setTargetVolatile_name, "setTargetVolatile") \
template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \ template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ NOT_LP64( do_alias(intptr_signature, int_signature) ) \
LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ LP64_ONLY( do_alias(intptr_signature, long_signature) ) \
template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \ template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \
\ \
/* common method and field names */ \ /* common method and field names */ \
@ -365,6 +365,11 @@
template(erasedType_name, "erasedType") \ template(erasedType_name, "erasedType") \
template(genericInvoker_name, "genericInvoker") \ template(genericInvoker_name, "genericInvoker") \
template(append_name, "append") \ 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: */ \ /* non-intrinsic name/signature pairs: */ \
template(register_method_name, "register") \ template(register_method_name, "register") \

View file

@ -984,11 +984,8 @@ ConstantPoolCacheEntry *cp_entry))
// check the access_flags for the field in the klass // check the access_flags for the field in the klass
instanceKlass* ik = instanceKlass::cast(java_lang_Class::as_klassOop(cp_entry->f1())); instanceKlass* ik = instanceKlass::cast(java_lang_Class::as_klassOop(cp_entry->f1()));
typeArrayOop fields = ik->fields();
int index = cp_entry->field_index(); int index = cp_entry->field_index();
assert(index < fields->length(), "holders field index is out of range"); if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return;
// bail out if field accesses are not watched
if ((fields->ushort_at(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return;
switch(cp_entry->flag_state()) { switch(cp_entry->flag_state()) {
case btos: // fall through 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 // check the access_flags for the field in the klass
instanceKlass* ik = instanceKlass::cast(k); instanceKlass* ik = instanceKlass::cast(k);
typeArrayOop fields = ik->fields();
int index = cp_entry->field_index(); 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 // 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'; 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, void ConstantPoolCacheEntry::set_field(Bytecodes::Code get_code,
Bytecodes::Code put_code, Bytecodes::Code put_code,
KlassHandle field_holder, KlassHandle field_holder,
int orig_field_index, int field_index,
int field_offset, int field_offset,
TosState field_type, TosState field_type,
bool is_final, bool is_final,
bool is_volatile) { bool is_volatile) {
set_f1(field_holder()->java_mirror()); set_f1(field_holder()->java_mirror());
set_f2(field_offset); 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, assert(field_index <= field_index_mask,
"field index does not fit in low flag bits"); "field index does not fit in low flag bits");
set_flags(as_flags(field_type, is_final, false, is_volatile, false, false) | 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 { 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, 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/genOopClosures.inline.hpp"
#include "memory/oopFactory.hpp" #include "memory/oopFactory.hpp"
#include "memory/permGen.hpp" #include "memory/permGen.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/instanceKlass.hpp" #include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp" #include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceOop.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 { bool instanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
const int n = fields()->length(); for (JavaFieldStream fs(as_klassOop()); !fs.done(); fs.next()) {
for (int i = 0; i < n; i += next_offset ) { Symbol* f_name = fs.name();
int name_index = fields()->ushort_at(i + name_index_offset); Symbol* f_sig = fs.signature();
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);
if (f_name == name && f_sig == sig) { if (f_name == name && f_sig == sig) {
fd->initialize(as_klassOop(), i); fd->initialize(as_klassOop(), fs.index());
return true; return true;
} }
} }
@ -803,11 +801,10 @@ void instanceKlass::shared_symbols_iterate(SymbolClosure* closure) {
closure->do_symbol(&_source_file_name); closure->do_symbol(&_source_file_name);
closure->do_symbol(&_source_debug_extension); closure->do_symbol(&_source_debug_extension);
const int n = fields()->length(); for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
for (int i = 0; i < n; i += next_offset ) { int name_index = fs.name_index();
int name_index = fields()->ushort_at(i + name_index_offset);
closure->do_symbol(constants()->symbol_at_addr(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)); 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 { bool instanceKlass::find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const {
int length = fields()->length(); for (JavaFieldStream fs(as_klassOop()); !fs.done(); fs.next()) {
for (int i = 0; i < length; i += next_offset) { if (fs.offset() == offset) {
if (offset_from_fields( i ) == offset) { fd->initialize(as_klassOop(), fs.index());
fd->initialize(as_klassOop(), i);
if (fd->is_static() == is_static) return true; 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) { void instanceKlass::do_local_static_fields(FieldClosure* cl) {
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
fieldDescriptor fd; fieldDescriptor fd;
int length = fields()->length(); fd.initialize(as_klassOop(), fs.index());
for (int i = 0; i < length; i += next_offset) { cl->do_field(&fd);
fd.initialize(as_klassOop(), i); }
if (fd.is_static()) 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) { void instanceKlass::do_local_static_fields_impl(instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS) {
for (JavaFieldStream fs(this_oop()); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
fieldDescriptor fd; fieldDescriptor fd;
int length = this_oop->fields()->length(); fd.initialize(this_oop(), fs.index());
for (int i = 0; i < length; i += next_offset) { f(&fd, CHECK);
fd.initialize(this_oop(), i); }
if (fd.is_static()) { f(&fd, CHECK); } // Do NOT remove {}! (CHECK macro expands into several statements)
} }
} }
@ -941,11 +939,11 @@ void instanceKlass::do_nonstatic_fields(FieldClosure* cl) {
super->do_nonstatic_fields(cl); super->do_nonstatic_fields(cl);
} }
fieldDescriptor fd; fieldDescriptor fd;
int length = fields()->length(); int length = java_fields_count();
// In DebugInfo nonstatic fields are sorted by offset. // In DebugInfo nonstatic fields are sorted by offset.
int* fields_sorted = NEW_C_HEAP_ARRAY(int, 2*(length+1)); int* fields_sorted = NEW_C_HEAP_ARRAY(int, 2*(length+1));
int j = 0; 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); fd.initialize(as_klassOop(), i);
if (!fd.is_static()) { if (!fd.is_static()) {
fields_sorted[j + 0] = fd.offset(); fields_sorted[j + 0] = fd.offset();
@ -2411,43 +2409,6 @@ void instanceKlass::oop_verify_on(oop obj, outputStream* st) {
oop_oop_iterate(obj, &blk); 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 // JNIid class for jfieldIDs only
// Note to reviewers: // Note to reviewers:
// These JNI functions are just moved over to column 1 and not changed // 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/constMethodOop.hpp"
#include "oops/constantPoolOop.hpp" #include "oops/constantPoolOop.hpp"
#include "oops/fieldInfo.hpp"
#include "oops/instanceOop.hpp" #include "oops/instanceOop.hpp"
#include "oops/klassOop.hpp" #include "oops/klassOop.hpp"
#include "oops/klassVtable.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_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 _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 _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 _is_marked_dependent; // used for marking during flushing and deoptimization
bool _rewritten; // methods rewritten. bool _rewritten; // methods rewritten.
bool _has_nonstatic_fields; // for sizing with UseCompressedOops bool _has_nonstatic_fields; // for sizing with UseCompressedOops
@ -307,27 +309,28 @@ class instanceKlass: public Klass {
objArrayOop transitive_interfaces() const { return _transitive_interfaces; } objArrayOop transitive_interfaces() const { return _transitive_interfaces; }
void set_transitive_interfaces(objArrayOop a) { oop_store_without_check((oop*) &_transitive_interfaces, (oop) a); } void set_transitive_interfaces(objArrayOop a) { oop_store_without_check((oop*) &_transitive_interfaces, (oop) a); }
// fields private:
// Field info extracted from the class file and stored friend class fieldDescriptor;
// as an array of 7 shorts FieldInfo* field(int index) const { return FieldInfo::from_field_array(_fields, index); }
enum FieldOffset {
access_flags_offset = 0, public:
name_index_offset = 1, int field_offset (int index) const { return field(index)->offset(); }
signature_index_offset = 2, int field_access_flags(int index) const { return field(index)->access_flags(); }
initval_index_offset = 3, Symbol* field_name (int index) const { return field(index)->name(constants()); }
low_offset = 4, Symbol* field_signature (int index) const { return field(index)->signature(constants()); }
high_offset = 5,
generic_signature_offset = 6, // Number of Java declared fields
next_offset = 7 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; } 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 // inner classes
typeArrayOop inner_classes() const { return _inner_classes; } typeArrayOop inner_classes() const { return _inner_classes; }
@ -842,10 +845,6 @@ public:
// Verification // Verification
const char* internal_name() const; const char* internal_name() const;
void oop_verify_on(oop obj, outputStream* st); 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) { 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_local_interfaces(NULL);
ik->set_transitive_interfaces(NULL); ik->set_transitive_interfaces(NULL);
ik->init_implementor(); ik->init_implementor();
ik->set_fields(NULL); ik->set_fields(NULL, 0);
ik->set_constants(NULL); ik->set_constants(NULL);
ik->set_class_loader(NULL); ik->set_class_loader(NULL);
ik->set_protection_domain(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 // First check if this is a static field
if (modifiers & JVM_ACC_STATIC) { 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); JNIid* id = instanceKlass::cast(k1())->jni_id_for(offset);
assert(id != NULL, "corrupt Field object"); assert(id != NULL, "corrupt Field object");
debug_only(id->set_is_static_field_id();) 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 slot is the index of the field description in the field-array
// The jfieldID is the offset of the field within the object // The jfieldID is the offset of the field within the object
// It may also have hash bits for k, if VerifyJNIFields is turned on. // 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"); assert(instanceKlass::cast(k1())->contains_field_offset(offset), "stay within object");
ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset); ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset);
return ret; return ret;

View file

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

View file

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

View file

@ -2044,7 +2044,6 @@ JvmtiEnv::SetFieldAccessWatch(fieldDescriptor* fdesc_ptr) {
// make sure we haven't set this watch before // make sure we haven't set this watch before
if (fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_DUPLICATE; if (fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_DUPLICATE;
fdesc_ptr->set_is_field_access_watched(true); fdesc_ptr->set_is_field_access_watched(true);
update_klass_field_access_flag(fdesc_ptr);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, true); 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 // make sure we have a watch to clear
if (!fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_NOT_FOUND; if (!fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_NOT_FOUND;
fdesc_ptr->set_is_field_access_watched(false); fdesc_ptr->set_is_field_access_watched(false);
update_klass_field_access_flag(fdesc_ptr);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, false); 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 // make sure we haven't set this watch before
if (fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_DUPLICATE; if (fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_DUPLICATE;
fdesc_ptr->set_is_field_modification_watched(true); fdesc_ptr->set_is_field_modification_watched(true);
update_klass_field_access_flag(fdesc_ptr);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, true); 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 // make sure we have a watch to clear
if (!fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_NOT_FOUND; if (!fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_NOT_FOUND;
fdesc_ptr->set_is_field_modification_watched(false); fdesc_ptr->set_is_field_modification_watched(false);
update_klass_field_access_flag(fdesc_ptr);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, false); 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 // return the vframe on the specified thread and depth, NULL if no such frame
vframe* vframe*
JvmtiEnvBase::vframeFor(JavaThread* java_thread, jint depth) { 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 // convert to a jni jclass from a non-null klassOop
jclass get_jni_class_non_null(klassOop k); 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); jint count_locked_objects(JavaThread *java_thread, Handle hobj);
jvmtiError get_locked_objects_in_frame(JavaThread *calling_thread, jvmtiError get_locked_objects_in_frame(JavaThread *calling_thread,
JavaThread* java_thread, JavaThread* java_thread,

View file

@ -30,6 +30,7 @@
#include "interpreter/rewriter.hpp" #include "interpreter/rewriter.hpp"
#include "memory/gcLocker.hpp" #include "memory/gcLocker.hpp"
#include "memory/universe.inline.hpp" #include "memory/universe.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/klassVtable.hpp" #include "oops/klassVtable.hpp"
#include "prims/jvmtiImpl.hpp" #include "prims/jvmtiImpl.hpp"
#include "prims/jvmtiRedefineClasses.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 // Check if the number, names, types and order of fields declared in these classes
// are the same. // are the same.
typeArrayOop k_old_fields = the_class->fields(); JavaFieldStream old_fs(the_class);
typeArrayOop k_new_fields = scratch_class->fields(); JavaFieldStream new_fs(scratch_class);
int n_fields = k_old_fields->length(); for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) {
if (n_fields != k_new_fields->length()) {
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
}
for (i = 0; i < n_fields; i += instanceKlass::next_offset) {
// access // access
old_flags = k_old_fields->ushort_at(i + instanceKlass::access_flags_offset); old_flags = old_fs.access_flags().as_short();
new_flags = k_new_fields->ushort_at(i + instanceKlass::access_flags_offset); new_flags = new_fs.access_flags().as_short();
if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) { if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) {
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
} }
// offset // offset
if (k_old_fields->short_at(i + instanceKlass::low_offset) != if (old_fs.offset() != new_fs.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)) {
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
} }
// name and signature // name and signature
jshort name_index = k_old_fields->short_at(i + instanceKlass::name_index_offset); Symbol* name_sym1 = the_class->constants()->symbol_at(old_fs.name_index());
jshort sig_index = k_old_fields->short_at(i +instanceKlass::signature_index_offset); Symbol* sig_sym1 = the_class->constants()->symbol_at(old_fs.signature_index());
Symbol* name_sym1 = the_class->constants()->symbol_at(name_index); Symbol* name_sym2 = scratch_class->constants()->symbol_at(new_fs.name_index());
Symbol* sig_sym1 = the_class->constants()->symbol_at(sig_index); Symbol* sig_sym2 = scratch_class->constants()->symbol_at(new_fs.signature_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);
if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) { if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) {
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; 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 // Do a parallel walk through the old and new methods. Detect
// cases where they match (exist in both), have been added in // cases where they match (exist in both), have been added in
// the new methods, or have been deleted (exist only in the // 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 int i; // for portability
// update each field in klass to use new constant pool indices as needed // update each field in klass to use new constant pool indices as needed
typeArrayHandle fields(THREAD, scratch_class->fields()); for (JavaFieldStream fs(scratch_class); !fs.done(); fs.next()) {
int n_fields = fields->length(); jshort cur_index = fs.name_index();
for (i = 0; i < n_fields; i += instanceKlass::next_offset) {
jshort cur_index = fields->short_at(i + instanceKlass::name_index_offset);
jshort new_index = find_new_index(cur_index); jshort new_index = find_new_index(cur_index);
if (new_index != 0) { if (new_index != 0) {
RC_TRACE_WITH_THREAD(0x00080000, THREAD, RC_TRACE_WITH_THREAD(0x00080000, THREAD,
("field-name_index change: %d to %d", cur_index, new_index)); ("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); new_index = find_new_index(cur_index);
if (new_index != 0) { if (new_index != 0) {
RC_TRACE_WITH_THREAD(0x00080000, THREAD, RC_TRACE_WITH_THREAD(0x00080000, THREAD,
("field-signature_index change: %d to %d", cur_index, new_index)); ("field-signature_index change: %d to %d", cur_index, new_index));
fields->short_at_put(i + instanceKlass::signature_index_offset, fs.set_signature_index(new_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); new_index = find_new_index(cur_index);
if (new_index != 0) { if (new_index != 0) {
RC_TRACE_WITH_THREAD(0x00080000, THREAD, RC_TRACE_WITH_THREAD(0x00080000, THREAD,
("field-initval_index change: %d to %d", cur_index, new_index)); ("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); new_index = find_new_index(cur_index);
if (new_index != 0) { if (new_index != 0) {
RC_TRACE_WITH_THREAD(0x00080000, THREAD, RC_TRACE_WITH_THREAD(0x00080000, THREAD,
("field-generic_signature change: %d to %d", cur_index, new_index)); ("field-generic_signature change: %d to %d", cur_index, new_index));
fields->short_at_put(i + instanceKlass::generic_signature_offset, fs.set_generic_signature_index(new_index);
new_index);
} }
} // end for each field } // 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 slot = java_lang_reflect_Field::slot(target_oop); // fd.index()
int mods = java_lang_reflect_Field::modifiers(target_oop); int mods = java_lang_reflect_Field::modifiers(target_oop);
klassOop k = java_lang_Class::as_klassOop(clazz); 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); init_MemberName(mname_oop, k, accessFlags_from(mods), offset);
} else { } else {
KlassHandle receiver_limit; int decode_flags = 0; 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()); THROW(vmSymbols::java_lang_InternalError());
} }
java_lang_invoke_MethodHandle::init_vmslots(mh());
if (VerifyMethodHandles) { if (VerifyMethodHandles) {
// The privileged code which invokes this routine should not make // The privileged code which invokes this routine should not make
// a mistake about types, but it's better to verify. // 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_null()) { THROW(vmSymbols::java_lang_InternalError()); }
if (m->is_abstract()) { THROW(vmSymbols::java_lang_AbstractMethodError()); } if (m->is_abstract()) { THROW(vmSymbols::java_lang_AbstractMethodError()); }
java_lang_invoke_MethodHandle::init_vmslots(mh());
int vmargslot = m->size_of_parameters() - 1; int vmargslot = m->size_of_parameters() - 1;
assert(java_lang_invoke_BoundMethodHandle::vmargslot(mh()) == vmargslot, ""); 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()); THROW(vmSymbols::java_lang_InternalError());
} }
java_lang_invoke_MethodHandle::init_vmslots(mh());
int argslot = java_lang_invoke_BoundMethodHandle::vmargslot(mh()); int argslot = java_lang_invoke_BoundMethodHandle::vmargslot(mh());
if (VerifyMethodHandles) { if (VerifyMethodHandles) {
@ -2686,6 +2682,7 @@ void MethodHandles::ensure_vmlayout_field(Handle target, TRAPS) {
java_lang_invoke_MethodTypeForm::init_vmlayout(mtform(), cookie); java_lang_invoke_MethodTypeForm::init_vmlayout(mtform(), cookie);
} }
} }
assert(java_lang_invoke_MethodTypeForm::vmslots(mtform()) == argument_slot_count(mtype()), "must agree");
} }
#ifdef ASSERT #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); return field_offset_from_byte_offset(offset);
} }

View file

@ -42,59 +42,51 @@ typeArrayOop fieldDescriptor::annotations() const {
objArrayOop md = ik->fields_annotations(); objArrayOop md = ik->fields_annotations();
if (md == NULL) if (md == NULL)
return NULL; return NULL;
assert((index() % instanceKlass::next_offset) == 0, ""); return typeArrayOop(md->obj_at(index()));
return typeArrayOop(md->obj_at(index() / instanceKlass::next_offset));
} }
constantTag fieldDescriptor::initial_value_tag() const { 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 { 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 { 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 { 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 { 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 { 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) { void fieldDescriptor::initialize(klassOop k, int index) {
instanceKlass* ik = instanceKlass::cast(k); instanceKlass* ik = instanceKlass::cast(k);
_cp = ik->constants(); _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"); _access_flags = accessFlags_from(f->access_flags());
assert(fields->length() >= index + instanceKlass::next_offset, "Illegal size of field array"); guarantee(f->name_index() != 0 && f->signature_index() != 0, "bad constant pool index for fieldDescriptor");
_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);
_index = index; _index = index;
} }
#ifndef PRODUCT #ifndef PRODUCT
void fieldDescriptor::print_on(outputStream* st) const { void fieldDescriptor::print_on(outputStream* st) const {
_access_flags.print_on(st); access_flags().print_on(st);
constants()->symbol_at(_name_index)->print_value_on(st); name()->print_value_on(st);
st->print(" "); st->print(" ");
constants()->symbol_at(_signature_index)->print_value_on(st); signature()->print_value_on(st);
st->print(" @%d ", offset()); st->print(" @%d ", offset());
if (WizardMode && has_initial_value()) { if (WizardMode && has_initial_value()) {
st->print("(initval "); st->print("(initval ");

View file

@ -40,29 +40,40 @@
class fieldDescriptor VALUE_OBJ_CLASS_SPEC { class fieldDescriptor VALUE_OBJ_CLASS_SPEC {
private: private:
AccessFlags _access_flags; AccessFlags _access_flags;
int _name_index; int _index; // the field index
int _signature_index;
int _initial_value_index;
int _offset;
int _generic_signature_index;
int _index; // index into fields() array
constantPoolHandle _cp; 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: public:
Symbol* name() const { return _cp->symbol_at(_name_index); } Symbol* name() const {
Symbol* signature() const { return _cp->symbol_at(_signature_index); } return field()->name(_cp);
}
Symbol* signature() const {
return field()->signature(_cp);
}
klassOop field_holder() const { return _cp->pool_holder(); } klassOop field_holder() const { return _cp->pool_holder(); }
constantPoolOop constants() const { return _cp(); } constantPoolOop constants() const { return _cp(); }
AccessFlags access_flags() const { return _access_flags; } AccessFlags access_flags() const { return _access_flags; }
oop loader() const; oop loader() const;
// Offset (in words) of field from start of instanceOop / klassOop // Offset (in words) of field from start of instanceOop / klassOop
int offset() const { return _offset; } int offset() const { return field()->offset(); }
Symbol* generic_signature() const { return (_generic_signature_index > 0 ? _cp->symbol_at(_generic_signature_index) : (Symbol*)NULL); } Symbol* generic_signature() const { return field()->generic_signature(_cp); }
int index() const { return _index; } int index() const { return _index; }
typeArrayOop annotations() const; typeArrayOop annotations() const;
// Initial field value // 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() 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; jint int_initial_value() const;
jlong long_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()); } BasicType field_type() const { return FieldType::basic_type(signature()); }
// Access flags // Access flags
bool is_public() const { return _access_flags.is_public(); } bool is_public() const { return access_flags().is_public(); }
bool is_private() const { return _access_flags.is_private(); } bool is_private() const { return access_flags().is_private(); }
bool is_protected() const { return _access_flags.is_protected(); } bool is_protected() const { return access_flags().is_protected(); }
bool is_package_private() const { return !is_public() && !is_private() && !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_static() const { return access_flags().is_static(); }
bool is_final() const { return _access_flags.is_final(); } bool is_final() const { return access_flags().is_final(); }
bool is_volatile() const { return _access_flags.is_volatile(); } bool is_volatile() const { return access_flags().is_volatile(); }
bool is_transient() const { return _access_flags.is_transient(); } 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 bool is_field_modification_watched() const
{ return _access_flags.is_field_modification_watched(); } { 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_access_watched(const bool value) {
void set_is_field_modification_watched(const bool value) _access_flags.set_is_field_access_watched(value);
{ _access_flags.set_is_field_modification_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 // Initialization
void initialize(klassOop k, int index); void initialize(klassOop k, int index);

View file

@ -107,10 +107,8 @@ class MethodStream : public KlassStream {
class FieldStream : public KlassStream { class FieldStream : public KlassStream {
private: private:
int length() const { return fields()->length(); } int length() const { return _klass->java_fields_count(); }
constantPoolOop constants() const { return _klass->constants(); }
protected:
typeArrayOop fields() const { return _klass->fields(); }
public: public:
FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only) FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only)
: KlassStream(klass, local_only, classes_only) { : KlassStream(klass, local_only, classes_only) {
@ -118,26 +116,23 @@ class FieldStream : public KlassStream {
next(); next();
} }
void next() { _index -= instanceKlass::next_offset; } void next() { _index -= 1; }
// Accessors for current field // Accessors for current field
AccessFlags access_flags() const { AccessFlags access_flags() const {
AccessFlags flags; AccessFlags flags;
flags.set_flags(fields()->ushort_at(index() + instanceKlass::access_flags_offset)); flags.set_flags(_klass->field_access_flags(_index));
return flags; return flags;
} }
Symbol* name() const { Symbol* name() const {
int name_index = fields()->ushort_at(index() + instanceKlass::name_index_offset); return _klass->field_name(_index);
return constants()->symbol_at(name_index);
} }
Symbol* signature() const { Symbol* signature() const {
int signature_index = fields()->ushort_at(index() + return _klass->field_signature(_index);
instanceKlass::signature_index_offset);
return constants()->symbol_at(signature_index);
} }
// missing: initval() // missing: initval()
int offset() const { 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(); int field_count();
void next() { void next() {
_index -= instanceKlass::next_offset; _index -= 1;
if (has_filtered_field()) { if (has_filtered_field()) {
while (_index >=0 && FilteredFieldsMap::is_filtered_field((klassOop)_klass(), offset())) { 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. // 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. // The Java library method itself may be changed independently from the VM.
static void call_postVMInitHook(TRAPS) { static void call_postVMInitHook(TRAPS) {
klassOop k = SystemDictionary::sun_misc_PostVMInitHook_klass(); klassOop k = SystemDictionary::PostVMInitHook_klass();
instanceKlassHandle klass (THREAD, k); instanceKlassHandle klass (THREAD, k);
if (klass.not_null()) { if (klass.not_null()) {
JavaValue result(T_VOID); 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, _nof_implementors, int) \
nonstatic_field(instanceKlass, _implementors[0], klassOop) \ nonstatic_field(instanceKlass, _implementors[0], klassOop) \
nonstatic_field(instanceKlass, _fields, typeArrayOop) \ nonstatic_field(instanceKlass, _fields, typeArrayOop) \
nonstatic_field(instanceKlass, _java_fields_count, int) \
nonstatic_field(instanceKlass, _constants, constantPoolOop) \ nonstatic_field(instanceKlass, _constants, constantPoolOop) \
nonstatic_field(instanceKlass, _class_loader, oop) \ nonstatic_field(instanceKlass, _class_loader, oop) \
nonstatic_field(instanceKlass, _protection_domain, 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 */ \ /* java_lang_Class fields */ \
/*********************************/ \ /*********************************/ \
\ \
static_field(java_lang_Class, klass_offset, int) \ static_field(java_lang_Class, _klass_offset, int) \
static_field(java_lang_Class, resolved_constructor_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, _array_klass_offset, int) \
static_field(java_lang_Class, oop_size_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, _static_oop_field_count_offset, int) \
\ \
/************************/ \ /************************/ \
/* Miscellaneous fields */ \ /* Miscellaneous fields */ \
@ -1662,19 +1663,24 @@ static inline uint64_t cast_uint64_t(size_t x)
declare_constant(constMethodOopDesc::_has_localvariable_table) \ 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) \ 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 */ \ /* instanceKlass InnerClassAttributeOffset enum */ \
/************************************************/ \ /************************************************/ \

View file

@ -79,9 +79,14 @@ enum {
// Note that the class-related ACC_ANNOTATION bit conflicts with these flags. // 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_ACCESS_WATCHED = 0x00002000, // field access is watched by JVMTI
JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000, // field modification 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() // 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_access_watched() const { return (_flags & JVM_ACC_FIELD_ACCESS_WATCHED) != 0; }
bool is_field_modification_watched() const bool is_field_modification_watched() const
{ return (_flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; } { return (_flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; }
bool is_internal() const { return (_flags & JVM_ACC_FIELD_INTERNAL) != 0; }
// get .class file flags // get .class file flags
jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); } jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); }
// Initialization // Initialization
void add_promoted_flags(jint flags) { _flags |= (flags & JVM_ACC_PROMOTED_FLAGS); } 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_flags(jint flags) { _flags = (flags & JVM_ACC_WRITTEN_FLAGS); }
void set_queued_for_compilation() { atomic_set_bits(JVM_ACC_QUEUED); } void set_queued_for_compilation() { atomic_set_bits(JVM_ACC_QUEUED); }
@ -218,8 +227,8 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
} }
// Conversion // Conversion
jshort as_short() { return (jshort)_flags; } jshort as_short() const { return (jshort)_flags; }
jint as_int() { return _flags; } jint as_int() const { return _flags; }
inline friend AccessFlags accessFlags_from(jint flags); inline friend AccessFlags accessFlags_from(jint flags);