< prev index next >
src/hotspot/share/oops/valueKlass.cpp
Print this page
@@ -265,91 +265,75 @@
// function collects the fields of the value types (including embedded
// value type's fields) in a list. Included with the field's type is
// the offset of each field in the value type: i2c and c2i adapters
// need that to load or store fields. Finally, the list of fields is
// sorted in order of increasing offsets: the adapters and the
-// compiled code need and agreed upon order of fields.
+// compiled code need to agree upon the order of fields.
//
// The list of basic types that is returned starts with a T_VALUETYPE
-// and ends with an extra T_VOID. T_VALUETYPE/T_VOID are used as
+// and ends with an extra T_VOID. T_VALUETYPE/T_VOID pairs are used as
// delimiters. Every entry between the two is a field of the value
// type. If there's an embedded value type in the list, it also starts
// with a T_VALUETYPE and ends with a T_VOID. This is so we can
// generate a unique fingerprint for the method's adapters and we can
// generate the list of basic types from the interpreter point of view
// (value types passed as reference: iterate on the list until a
// T_VALUETYPE, drop everything until and including the closing
// T_VOID) or the compiler point of view (each field of the value
// types is an argument: drop all T_VALUETYPE/T_VOID from the list).
-GrowableArray<SigEntry> ValueKlass::collect_fields(int base_off) const {
- GrowableArray<SigEntry> sig_extended;
- sig_extended.push(SigEntry(T_VALUETYPE, base_off));
+int ValueKlass::collect_fields(GrowableArray<SigEntry>* sig, int base_off) const {
+ int count = 0;
+ SigEntry::add_entry(sig, T_VALUETYPE, base_off);
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) continue;
- fieldDescriptor& fd = fs.field_descriptor();
- BasicType bt = fd.field_type();
- int offset = base_off + fd.offset() - (base_off > 0 ? first_field_offset() : 0);
- if (bt == T_VALUETYPE) {
- if (fd.is_flattened()) {
- Symbol* signature = fd.signature();
- JavaThread* THREAD = JavaThread::current();
- oop loader = class_loader();
- oop domain = protection_domain();
- ResetNoHandleMark rnhm;
- HandleMark hm;
- NoSafepointVerifier nsv;
- Klass* klass = SystemDictionary::resolve_or_null(signature,
- Handle(THREAD, loader), Handle(THREAD, domain),
- THREAD);
- assert(klass != NULL && !HAS_PENDING_EXCEPTION, "lookup shouldn't fail");
- const GrowableArray<SigEntry>& embedded = ValueKlass::cast(klass)->collect_fields(offset);
- sig_extended.appendAll(&embedded);
- } else {
- sig_extended.push(SigEntry(T_VALUETYPEPTR, offset));
- }
+ int offset = base_off + fs.offset() - (base_off > 0 ? first_field_offset() : 0);
+ if (fs.is_flattened()) {
+ // Resolve klass of flattened value type field and recursively collect fields
+ Klass* vk = get_value_field_klass(fs.index());
+ count += ValueKlass::cast(vk)->collect_fields(sig, offset);
} else {
- sig_extended.push(SigEntry(bt, offset));
- if (bt == T_LONG || bt == T_DOUBLE) {
- sig_extended.push(SigEntry(T_VOID, offset));
+ BasicType bt = FieldType::basic_type(fs.signature());
+ if (bt == T_VALUETYPE) {
+ bt = T_OBJECT;
}
+ SigEntry::add_entry(sig, bt, offset);
+ count += type2size[bt];
}
}
int offset = base_off + size_helper()*HeapWordSize - (base_off > 0 ? first_field_offset() : 0);
- sig_extended.push(SigEntry(T_VOID, offset)); // hack: use T_VOID to mark end of value type fields
+ SigEntry::add_entry(sig, T_VOID, offset);
if (base_off == 0) {
- sig_extended.sort(SigEntry::compare);
+ sig->sort(SigEntry::compare);
}
- assert(sig_extended.at(0)._bt == T_VALUETYPE && sig_extended.at(sig_extended.length()-1)._bt == T_VOID, "broken structure");
- return sig_extended;
+ assert(sig->at(0)._bt == T_VALUETYPE && sig->at(sig->length()-1)._bt == T_VOID, "broken structure");
+ return count;
}
-void ValueKlass::initialize_calling_convention() {
+void ValueKlass::initialize_calling_convention(TRAPS) {
// Because the pack and unpack handler addresses need to be loadable from generated code,
// they are stored at a fixed offset in the klass metadata. Since value type klasses do
// not have a vtable, the vtable offset is used to store these addresses.
- //guarantee(vtable_length() == 0, "vtables are not supported in value klasses");
if (ValueTypeReturnedAsFields || ValueTypePassFieldsAsArgs) {
- Thread* THREAD = Thread::current();
- assert(!HAS_PENDING_EXCEPTION, "should have no exception");
ResourceMark rm;
- const GrowableArray<SigEntry>& sig_vk = collect_fields();
- int nb_fields = SigEntry::count_fields(sig_vk)+1;
- Array<SigEntry>* extended_sig = MetadataFactory::new_array<SigEntry>(class_loader_data(), sig_vk.length(), CHECK_AND_CLEAR);
+ GrowableArray<SigEntry> sig_vk;
+ int nb_fields = collect_fields(&sig_vk);
+ Array<SigEntry>* extended_sig = MetadataFactory::new_array<SigEntry>(class_loader_data(), sig_vk.length(), CHECK);
*((Array<SigEntry>**)adr_extended_sig()) = extended_sig;
for (int i = 0; i < sig_vk.length(); i++) {
extended_sig->at_put(i, sig_vk.at(i));
}
if (ValueTypeReturnedAsFields) {
+ nb_fields++;
BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, nb_fields);
sig_bt[0] = T_METADATA;
- SigEntry::fill_sig_bt(sig_vk, sig_bt+1, nb_fields-1, true);
+ SigEntry::fill_sig_bt(&sig_vk, sig_bt+1);
VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, nb_fields);
int total = SharedRuntime::java_return_convention(sig_bt, regs, nb_fields);
if (total > 0) {
- Array<VMRegPair>* return_regs = MetadataFactory::new_array<VMRegPair>(class_loader_data(), nb_fields, CHECK_AND_CLEAR);
+ Array<VMRegPair>* return_regs = MetadataFactory::new_array<VMRegPair>(class_loader_data(), nb_fields, CHECK);
*((Array<VMRegPair>**)adr_return_regs()) = return_regs;
for (int i = 0; i < nb_fields; i++) {
return_regs->at_put(i, regs[i]);
}
@@ -399,12 +383,11 @@
const Array<VMRegPair>* regs = return_regs();
int j = 1;
for (int i = 0; i < sig_vk->length(); i++) {
BasicType bt = sig_vk->at(i)._bt;
- if (bt == T_OBJECT || bt == T_VALUETYPEPTR || bt == T_ARRAY) {
- int off = sig_vk->at(i)._offset;
+ if (bt == T_OBJECT || bt == T_ARRAY) {
VMRegPair pair = regs->at(j);
address loc = reg_map.location(pair.first());
oop v = *(oop*)loc;
assert(v == NULL || oopDesc::is_oop(v), "not an oop?");
assert(Universe::heap()->is_in_or_null(v), "must be heap pointer");
@@ -432,11 +415,10 @@
int j = 1;
for (int i = 0, k = 0; i < sig_vk->length(); i++) {
BasicType bt = sig_vk->at(i)._bt;
if (bt == T_OBJECT || bt == T_ARRAY) {
- int off = sig_vk->at(i)._offset;
VMRegPair pair = regs->at(j);
address loc = reg_map.location(pair.first());
*(oop*)loc = handles.at(k++)();
}
if (bt == T_VALUETYPE) {
@@ -453,11 +435,10 @@
}
// Fields are in registers. Create an instance of the value type and
// initialize it with the values of the fields.
oop ValueKlass::realloc_result(const RegisterMap& reg_map, const GrowableArray<Handle>& handles, TRAPS) {
-
oop new_vt = allocate_instance(CHECK_NULL);
const Array<SigEntry>* sig_vk = extended_sig();
const Array<VMRegPair>* regs = return_regs();
int j = 1;
@@ -473,62 +454,54 @@
j++;
}
continue;
}
int off = sig_vk->at(i)._offset;
+ assert(off > 0, "offset in object should be positive");
VMRegPair pair = regs->at(j);
address loc = reg_map.location(pair.first());
switch(bt) {
case T_BOOLEAN: {
- jboolean v = *(intptr_t*)loc;
- *(jboolean*)((address)new_vt + off) = v;
+ new_vt->bool_field_put(off, *(jboolean*)loc);
break;
}
case T_CHAR: {
- jchar v = *(intptr_t*)loc;
- *(jchar*)((address)new_vt + off) = v;
+ new_vt->char_field_put(off, *(jchar*)loc);
break;
}
case T_BYTE: {
- jbyte v = *(intptr_t*)loc;
- *(jbyte*)((address)new_vt + off) = v;
+ new_vt->byte_field_put(off, *(jbyte*)loc);
break;
}
case T_SHORT: {
- jshort v = *(intptr_t*)loc;
- *(jshort*)((address)new_vt + off) = v;
+ new_vt->short_field_put(off, *(jshort*)loc);
break;
}
case T_INT: {
- jint v = *(intptr_t*)loc;
- *(jint*)((address)new_vt + off) = v;
+ new_vt->int_field_put(off, *(jint*)loc);
break;
}
case T_LONG: {
#ifdef _LP64
- jlong v = *(intptr_t*)loc;
- *(jlong*)((address)new_vt + off) = v;
+ new_vt->double_field_put(off, *(jdouble*)loc);
#else
Unimplemented();
#endif
break;
}
case T_OBJECT:
- case T_VALUETYPEPTR:
case T_ARRAY: {
Handle handle = handles.at(k++);
- HeapAccess<>::oop_store_at(new_vt, off, handle());
+ new_vt->obj_field_put(off, handle());
break;
}
case T_FLOAT: {
- jfloat v = *(jfloat*)loc;
- *(jfloat*)((address)new_vt + off) = v;
+ new_vt->float_field_put(off, *(jfloat*)loc);
break;
}
case T_DOUBLE: {
- jdouble v = *(jdouble*)loc;
- *(jdouble*)((address)new_vt + off) = v;
+ new_vt->double_field_put(off, *(jdouble*)loc);
break;
}
default:
ShouldNotReachHere();
}
< prev index next >