< prev index next >
src/hotspot/share/runtime/sharedRuntime.cpp
Print this page
*** 1149,1159 ****
callee = bytecode.static_target(CHECK_NH);
if (callee.is_null()) {
THROW_(vmSymbols::java_lang_NoSuchMethodException(), nullHandle);
}
}
! if (ValueTypePassFieldsAsArgs && callee->method_holder()->is_value()) {
// If the receiver is a value type that is passed as fields, no oop is available.
// Resolve the call without receiver null checking.
assert(bc == Bytecodes::_invokevirtual, "only allowed with invokevirtual");
assert(!attached_method.is_null(), "must have attached method");
constantPoolHandle constants(THREAD, caller->constants());
--- 1149,1160 ----
callee = bytecode.static_target(CHECK_NH);
if (callee.is_null()) {
THROW_(vmSymbols::java_lang_NoSuchMethodException(), nullHandle);
}
}
! // TODO for now, don't scalarize value type receivers because of interface calls
! if (ValueTypePassFieldsAsArgs && callee->method_holder()->is_value() && false) {
// If the receiver is a value type that is passed as fields, no oop is available.
// Resolve the call without receiver null checking.
assert(bc == Bytecodes::_invokevirtual, "only allowed with invokevirtual");
assert(!attached_method.is_null(), "must have attached method");
constantPoolHandle constants(THREAD, caller->constants());
*** 2294,2306 ****
// If value types are passed as fields, return 'in' to differentiate
// between a T_VALUETYPE and a T_OBJECT in the signature.
return ValueTypePassFieldsAsArgs ? in : adapter_encoding(T_OBJECT, false);
}
- case T_VALUETYPEPTR:
- return T_VALUETYPE; // TODO hack because we don't have enough bits to represent T_VALUETYPEPTR.
-
case T_OBJECT:
case T_ARRAY:
// In other words, we assume that any register good enough for
// an int or long is good enough for a managed pointer.
#ifdef _LP64
--- 2295,2304 ----
*** 2321,2331 ****
return T_CONFLICT;
}
}
public:
! AdapterFingerPrint(int total_args_passed, BasicType* sig_bt) {
// The fingerprint is based on the BasicType signature encoded
// into an array of ints with eight entries per int.
int* ptr;
int len = (total_args_passed + (_basic_types_per_int-1)) / _basic_types_per_int;
if (len <= _compact_int_count) {
--- 2319,2329 ----
return T_CONFLICT;
}
}
public:
! AdapterFingerPrint(int total_args_passed, const GrowableArray<SigEntry>* sig) {
// The fingerprint is based on the BasicType signature encoded
// into an array of ints with eight entries per int.
int* ptr;
int len = (total_args_passed + (_basic_types_per_int-1)) / _basic_types_per_int;
if (len <= _compact_int_count) {
*** 2348,2358 ****
for (int index = 0; index < len; index++) {
int value = 0;
for (int byte = 0; byte < _basic_types_per_int; byte++) {
int bt = 0;
if (sig_index < total_args_passed) {
! BasicType sbt = sig_bt[sig_index++];
if (ValueTypePassFieldsAsArgs && sbt == T_VALUETYPE) {
// Found start of value type in signature
vt_count++;
} else if (ValueTypePassFieldsAsArgs && sbt == T_VOID &&
prev_sbt != T_LONG && prev_sbt != T_DOUBLE) {
--- 2346,2356 ----
for (int index = 0; index < len; index++) {
int value = 0;
for (int byte = 0; byte < _basic_types_per_int; byte++) {
int bt = 0;
if (sig_index < total_args_passed) {
! BasicType sbt = sig->at(sig_index++)._bt;
if (ValueTypePassFieldsAsArgs && sbt == T_VALUETYPE) {
// Found start of value type in signature
vt_count++;
} else if (ValueTypePassFieldsAsArgs && sbt == T_VOID &&
prev_sbt != T_LONG && prev_sbt != T_DOUBLE) {
*** 2452,2464 ****
public:
AdapterHandlerTable()
: BasicHashtable<mtCode>(293, (DumpSharedSpaces ? sizeof(CDSAdapterHandlerEntry) : sizeof(AdapterHandlerEntry))) { }
// Create a new entry suitable for insertion in the table
! AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry, Symbol* sig_extended) {
AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable<mtCode>::new_entry(fingerprint->compute_hash());
! entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, sig_extended);
if (DumpSharedSpaces) {
((CDSAdapterHandlerEntry*)entry)->init();
}
return entry;
}
--- 2450,2462 ----
public:
AdapterHandlerTable()
: BasicHashtable<mtCode>(293, (DumpSharedSpaces ? sizeof(CDSAdapterHandlerEntry) : sizeof(AdapterHandlerEntry))) { }
// Create a new entry suitable for insertion in the table
! AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_value_entry, address c2i_unverified_entry) {
AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable<mtCode>::new_entry(fingerprint->compute_hash());
! entry->init(fingerprint, i2c_entry, c2i_entry, c2i_value_entry, c2i_unverified_entry);
if (DumpSharedSpaces) {
((CDSAdapterHandlerEntry*)entry)->init();
}
return entry;
}
*** 2473,2485 ****
entry->deallocate();
BasicHashtable<mtCode>::free_entry(entry);
}
// Find a entry with the same fingerprint if it exists
! AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt) {
NOT_PRODUCT(_lookups++);
! AdapterFingerPrint fp(total_args_passed, sig_bt);
unsigned int hash = fp.compute_hash();
int index = hash_to_index(hash);
for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) {
NOT_PRODUCT(_buckets++);
if (e->hash() == hash) {
--- 2471,2483 ----
entry->deallocate();
BasicHashtable<mtCode>::free_entry(entry);
}
// Find a entry with the same fingerprint if it exists
! AdapterHandlerEntry* lookup(int total_args_passed, const GrowableArray<SigEntry>* sig) {
NOT_PRODUCT(_lookups++);
! AdapterFingerPrint fp(total_args_passed, sig);
unsigned int hash = fp.compute_hash();
int index = hash_to_index(hash);
for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) {
NOT_PRODUCT(_buckets++);
if (e->hash() == hash) {
*** 2597,2619 ****
// Pass wrong_method_abstract for the c2i transitions to return
// AbstractMethodError for invalid invocations.
address wrong_method_abstract = SharedRuntime::get_handle_wrong_method_abstract_stub();
_abstract_method_handler = AdapterHandlerLibrary::new_entry(new AdapterFingerPrint(0, NULL),
StubRoutines::throw_AbstractMethodError_entry(),
! wrong_method_abstract, wrong_method_abstract);
}
AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint,
address i2c_entry,
address c2i_entry,
! address c2i_unverified_entry,
! Symbol* sig_extended) {
! return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, sig_extended);
}
! AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method, TRAPS) {
! AdapterHandlerEntry* entry = get_adapter0(method, CHECK_NULL);
if (method->is_shared()) {
// See comments around Method::link_method()
MutexLocker mu(AdapterHandlerLibrary_lock);
if (method->adapter() == NULL) {
method->update_adapter_trampoline(entry);
--- 2595,2617 ----
// Pass wrong_method_abstract for the c2i transitions to return
// AbstractMethodError for invalid invocations.
address wrong_method_abstract = SharedRuntime::get_handle_wrong_method_abstract_stub();
_abstract_method_handler = AdapterHandlerLibrary::new_entry(new AdapterFingerPrint(0, NULL),
StubRoutines::throw_AbstractMethodError_entry(),
! wrong_method_abstract, wrong_method_abstract, wrong_method_abstract);
}
AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint,
address i2c_entry,
address c2i_entry,
! address c2i_value_entry,
! address c2i_unverified_entry) {
! return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_value_entry, c2i_unverified_entry);
}
! AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) {
! AdapterHandlerEntry* entry = get_adapter0(method);
if (method->is_shared()) {
// See comments around Method::link_method()
MutexLocker mu(AdapterHandlerLibrary_lock);
if (method->adapter() == NULL) {
method->update_adapter_trampoline(entry);
*** 2632,2642 ****
}
return entry;
}
! AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter0(const methodHandle& method, TRAPS) {
// Use customized signature handler. Need to lock around updates to
// the AdapterHandlerTable (it is not safe for concurrent readers
// and a single writer: this could be fixed if it becomes a
// problem).
--- 2630,2640 ----
}
return entry;
}
! AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter0(const methodHandle& method) {
// Use customized signature handler. Need to lock around updates to
// the AdapterHandlerTable (it is not safe for concurrent readers
// and a single writer: this could be fixed if it becomes a
// problem).
*** 2653,2724 ****
if (method->is_abstract()) {
return _abstract_method_handler;
}
! // Fill in the signature array, for the calling-convention call.
! GrowableArray<SigEntry> sig_extended;
! {
MutexUnlocker mul(AdapterHandlerLibrary_lock);
! Thread* THREAD = Thread::current();
! Klass* holder = method->method_holder();
! GrowableArray<BasicType> sig_bt_tmp;
! int i = 0;
! if (!method->is_static()) { // Pass in receiver first
! if (holder->is_value()) {
! ValueKlass* vk = ValueKlass::cast(holder);
! if (!ValueTypePassFieldsAsArgs) {
! // If we don't pass value types as arguments or if the holder of
! // the method is __Value, we must pass a reference.
! sig_extended.push(SigEntry(T_VALUETYPEPTR));
! } else {
! const Array<SigEntry>* sig_vk = vk->extended_sig();
! sig_extended.appendAll(sig_vk);
! }
} else {
! sig_extended.push(SigEntry(T_OBJECT));
}
}
for (SignatureStream ss(method->signature()); !ss.at_return_type(); ss.next()) {
! Symbol* sym = ss.as_symbol_or_null();
! if (sym != NULL && sym->is_Q_signature()) {
! if (!ValueTypePassFieldsAsArgs) {
! sig_extended.push(SigEntry(T_VALUETYPEPTR));
! } else {
! // Method handle intrinsics with a __Value argument may be created during
! // compilation. Only do a full system dictionary lookup if the argument name
! // is not __Value, to avoid lookups from the compiler thread.
Klass* k = ss.as_klass(Handle(THREAD, holder->class_loader()),
Handle(THREAD, holder->protection_domain()),
! SignatureStream::ReturnNull, CHECK_NULL);
! const Array<SigEntry>* sig_vk = ValueKlass::cast(k)->extended_sig();
! sig_extended.appendAll(sig_vk);
}
- } else {
- sig_extended.push(SigEntry(ss.type()));
- if (ss.type() == T_LONG || ss.type() == T_DOUBLE) {
- sig_extended.push(SigEntry(T_VOID));
}
}
}
}
-
- int total_args_passed_cc = ValueTypePassFieldsAsArgs ? SigEntry::count_fields(sig_extended) : sig_extended.length();
- BasicType* sig_bt_cc = NEW_RESOURCE_ARRAY(BasicType, total_args_passed_cc);
- SigEntry::fill_sig_bt(sig_extended, sig_bt_cc, total_args_passed_cc, ValueTypePassFieldsAsArgs);
-
- int total_args_passed_fp = sig_extended.length();
- BasicType* sig_bt_fp = NEW_RESOURCE_ARRAY(BasicType, total_args_passed_fp);
- for (int i = 0; i < sig_extended.length(); i++) {
- sig_bt_fp[i] = sig_extended.at(i)._bt;
}
- VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed_cc);
-
// Lookup method signature's fingerprint
! entry = _adapters->lookup(total_args_passed_fp, sig_bt_fp);
#ifdef ASSERT
AdapterHandlerEntry* shared_entry = NULL;
// Start adapter sharing verification only after the VM is booted.
if (VerifyAdapterSharing && (entry != NULL)) {
--- 2651,2755 ----
if (method->is_abstract()) {
return _abstract_method_handler;
}
! bool has_value_arg = false;
! GrowableArray<SigEntry> sig(method->size_of_parameters());
! if (!method->is_static()) {
! // TODO for now, don't scalarize value type receivers because of interface calls
! //has_value_arg |= method->method_holder()->is_value();
! SigEntry::add_entry(&sig, T_OBJECT);
! }
! for (SignatureStream ss(method->signature()); !ss.at_return_type(); ss.next()) {
! BasicType bt = ss.type();
! if (bt == T_VALUETYPE) {
! has_value_arg = true;
! bt = T_OBJECT;
! }
! SigEntry::add_entry(&sig, bt);
! }
!
! // Get a description of the compiled java calling convention and the largest used (VMReg) stack slot usage
! VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, sig.length());
! int args_on_stack = SharedRuntime::java_calling_convention(&sig, regs);
!
! // Now compute the scalarized calling convention if there are value types in the signature
! GrowableArray<SigEntry> sig_cc = sig;
! VMRegPair* regs_cc = regs;
! SigEntry reserved_entry;
! int args_on_stack_cc = args_on_stack;
!
! if (ValueTypePassFieldsAsArgs && has_value_arg) {
MutexUnlocker mul(AdapterHandlerLibrary_lock);
! InstanceKlass* holder = method->method_holder();
! sig_cc = GrowableArray<SigEntry>(method->size_of_parameters());
! if (!method->is_static()) {
! // TODO for now, don't scalarize value type receivers because of interface calls
! if (false && holder->is_value()) {
! sig_cc.appendAll(ValueKlass::cast(holder)->extended_sig());
} else {
! SigEntry::add_entry(&sig_cc, T_OBJECT);
}
}
+ Thread* THREAD = Thread::current();
for (SignatureStream ss(method->signature()); !ss.at_return_type(); ss.next()) {
! if (ss.type() == T_VALUETYPE) {
Klass* k = ss.as_klass(Handle(THREAD, holder->class_loader()),
Handle(THREAD, holder->protection_domain()),
! SignatureStream::ReturnNull, THREAD);
! assert(k != NULL && !HAS_PENDING_EXCEPTION, "value klass should have been pre-loaded");
! sig_cc.appendAll(ValueKlass::cast(k)->extended_sig());
! } else {
! SigEntry::add_entry(&sig_cc, ss.type());
! }
! }
! regs_cc = NEW_RESOURCE_ARRAY(VMRegPair, sig_cc.length() + 2);
! args_on_stack_cc = SharedRuntime::java_calling_convention(&sig_cc, regs_cc);
!
! // This stack slot is occupied by the return address with the unscalarized calling
! // convention. Don't use it for argument with the scalarized calling convention.
! int ret_addr_slot = args_on_stack_cc - args_on_stack;
! if (ret_addr_slot > 0) {
! // Make sure stack of the scalarized calling convention with
! // the reserved entry (2 slots) is 16-byte (4 slots) aligned.
! int alignment = StackAlignmentInBytes/VMRegImpl::stack_slot_size;
! ret_addr_slot = align_up(ret_addr_slot + 2, alignment) - 2;
! // Find index in signature that belongs to return address slot
! reserved_entry._offset = 0;
! int sig_idx = 0;
! for (; sig_idx < sig_cc.length(); ++sig_idx) {
! if (SigEntry::skip_value_delimiters(&sig_cc, sig_idx)) {
! VMReg first = regs_cc[reserved_entry._offset].first();
! if (first->is_stack()) {
! // Select a type for the reserved entry that will end up on the stack
! reserved_entry._bt = sig_cc.at(sig_idx)._bt;
! if ((int)first->reg2stack() == ret_addr_slot) {
! break;
}
}
+ reserved_entry._offset++;
}
}
+ // Insert reserved entry and re-compute calling convention
+ SigEntry::insert_reserved_entry(&sig_cc, sig_idx, reserved_entry._bt);
+ args_on_stack_cc = SharedRuntime::java_calling_convention(&sig_cc, regs_cc);
+ }
+ // Upper bound on stack arguments to avoid hitting the argument limit and
+ // bailing out of compilation ("unsupported incoming calling sequence").
+ // TODO we need a reasonable limit (flag?) here
+ if (args_on_stack_cc > 50) {
+ // Don't scalarize value type arguments
+ sig_cc = sig;
+ regs_cc = regs;
+ args_on_stack_cc = args_on_stack;
}
}
// Lookup method signature's fingerprint
! entry = _adapters->lookup(sig_cc.length(), &sig_cc);
#ifdef ASSERT
AdapterHandlerEntry* shared_entry = NULL;
// Start adapter sharing verification only after the VM is booted.
if (VerifyAdapterSharing && (entry != NULL)) {
*** 2729,2743 ****
if (entry != NULL) {
return entry;
}
- // Get a description of the compiled java calling convention and the largest used (VMReg) stack slot usage
- int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt_cc, regs, total_args_passed_cc, false);
-
// Make a C heap allocated version of the fingerprint to store in the adapter
! fingerprint = new AdapterFingerPrint(total_args_passed_fp, sig_bt_fp);
// StubRoutines::code2() is initialized after this function can be called. As a result,
// VerifyAdapterCalls and VerifyAdapterSharing can fail if we re-use code that generated
// prior to StubRoutines::code2() being set. Checks refer to checks generated in an I2C
// stub that ensure that an I2C stub is called from an interpreter frame.
--- 2760,2771 ----
if (entry != NULL) {
return entry;
}
// Make a C heap allocated version of the fingerprint to store in the adapter
! fingerprint = new AdapterFingerPrint(sig_cc.length(), &sig_cc);
// StubRoutines::code2() is initialized after this function can be called. As a result,
// VerifyAdapterCalls and VerifyAdapterSharing can fail if we re-use code that generated
// prior to StubRoutines::code2() being set. Checks refer to checks generated in an I2C
// stub that ensure that an I2C stub is called from an interpreter frame.
*** 2751,2765 ****
buffer.insts()->initialize_shared_locs((relocInfo*)buffer_locs,
sizeof(buffer_locs)/sizeof(relocInfo));
MacroAssembler _masm(&buffer);
entry = SharedRuntime::generate_i2c2i_adapters(&_masm,
! comp_args_on_stack,
! sig_extended,
regs,
fingerprint,
new_adapter);
#ifdef ASSERT
if (VerifyAdapterSharing) {
if (shared_entry != NULL) {
assert(shared_entry->compare_code(buf->code_begin(), buffer.insts_size()), "code must match");
// Release the one just created and return the original
--- 2779,2805 ----
buffer.insts()->initialize_shared_locs((relocInfo*)buffer_locs,
sizeof(buffer_locs)/sizeof(relocInfo));
MacroAssembler _masm(&buffer);
entry = SharedRuntime::generate_i2c2i_adapters(&_masm,
! args_on_stack,
! args_on_stack_cc,
! &sig,
regs,
+ &sig_cc,
+ regs_cc,
fingerprint,
new_adapter);
+
+ if (regs != regs_cc) {
+ // Save a C heap allocated version of the scalarized signature and store it in the adapter
+ GrowableArray<SigEntry>* heap_sig = new (ResourceObj::C_HEAP, mtInternal)GrowableArray<SigEntry>(method->size_of_parameters(), true);
+ heap_sig->appendAll(&sig_cc);
+ entry->set_sig_cc(heap_sig);
+ entry->set_res_entry(reserved_entry);
+ }
+
#ifdef ASSERT
if (VerifyAdapterSharing) {
if (shared_entry != NULL) {
assert(shared_entry->compare_code(buf->code_begin(), buffer.insts_size()), "code must match");
// Release the one just created and return the original
*** 2824,2833 ****
--- 2864,2874 ----
address AdapterHandlerEntry::base_address() {
address base = _i2c_entry;
if (base == NULL) base = _c2i_entry;
assert(base <= _c2i_entry || _c2i_entry == NULL, "");
+ assert(base <= _c2i_value_entry || _c2i_value_entry == NULL, "");
assert(base <= _c2i_unverified_entry || _c2i_unverified_entry == NULL, "");
return base;
}
void AdapterHandlerEntry::relocate(address new_base) {
*** 2836,2853 ****
--- 2877,2899 ----
ptrdiff_t delta = new_base - old_base;
if (_i2c_entry != NULL)
_i2c_entry += delta;
if (_c2i_entry != NULL)
_c2i_entry += delta;
+ if (_c2i_value_entry != NULL)
+ _c2i_value_entry += delta;
if (_c2i_unverified_entry != NULL)
_c2i_unverified_entry += delta;
assert(base_address() == new_base, "");
}
void AdapterHandlerEntry::deallocate() {
delete _fingerprint;
+ if (_sig_cc != NULL) {
+ delete _sig_cc;
+ }
#ifdef ASSERT
if (_saved_code) FREE_C_HEAP_ARRAY(unsigned char, _saved_code);
#endif
}
*** 2916,2938 ****
if (!method->is_static()) // Pass in receiver first
sig_bt[i++] = T_OBJECT;
SignatureStream ss(method->signature());
for (; !ss.at_return_type(); ss.next()) {
BasicType bt = ss.type();
- if (bt == T_VALUETYPE) {
- #ifdef ASSERT
- Thread* THREAD = Thread::current();
- // Avoid class loading from compiler thread
- if (THREAD->can_call_java()) {
- Handle class_loader(THREAD, method->method_holder()->class_loader());
- Handle protection_domain(THREAD, method->method_holder()->protection_domain());
- Klass* k = ss.as_klass(class_loader, protection_domain, SignatureStream::ReturnNull, THREAD);
- assert(k != NULL && !HAS_PENDING_EXCEPTION, "can't resolve klass");
- }
- #endif
- bt = T_VALUETYPEPTR;
- }
sig_bt[i++] = bt; // Collect remaining bits of signature
if (ss.type() == T_LONG || ss.type() == T_DOUBLE)
sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots
}
assert(i == total_args_passed, "");
--- 2962,2971 ----
*** 3194,3206 ****
}
assert(false, "Should have found handler");
}
void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
! st->print_cr("AHE@" INTPTR_FORMAT ": %s i2c: " INTPTR_FORMAT " c2i: " INTPTR_FORMAT " c2iUV: " INTPTR_FORMAT,
p2i(this), fingerprint()->as_string(),
! p2i(get_i2c_entry()), p2i(get_c2i_entry()), p2i(get_c2i_unverified_entry()));
}
#if INCLUDE_CDS
--- 3227,3239 ----
}
assert(false, "Should have found handler");
}
void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
! st->print_cr("AHE@" INTPTR_FORMAT ": %s i2c: " INTPTR_FORMAT " c2i: " INTPTR_FORMAT " c2iMH: " INTPTR_FORMAT " c2iUV: " INTPTR_FORMAT,
p2i(this), fingerprint()->as_string(),
! p2i(get_i2c_entry()), p2i(get_c2i_entry()), p2i(get_c2i_value_entry()), p2i(get_c2i_unverified_entry()));
}
#if INCLUDE_CDS
*** 3303,3328 ****
ResourceMark rm;
JavaThread* THREAD = thread;
methodHandle callee(callee_method);
int nb_slots = 0;
! bool has_value_receiver = !callee->is_static() && callee->method_holder()->is_value();
if (has_value_receiver) {
nb_slots++;
}
! Handle class_loader(THREAD, callee->method_holder()->class_loader());
! Handle protection_domain(THREAD, callee->method_holder()->protection_domain());
for (SignatureStream ss(callee->signature()); !ss.at_return_type(); ss.next()) {
if (ss.type() == T_VALUETYPE) {
nb_slots++;
}
}
objArrayOop array_oop = oopFactory::new_objectArray(nb_slots, CHECK);
objArrayHandle array(THREAD, array_oop);
int i = 0;
if (has_value_receiver) {
! ValueKlass* vk = ValueKlass::cast(callee->method_holder());
oop res = vk->allocate_instance(CHECK);
array->obj_at_put(i, res);
i++;
}
for (SignatureStream ss(callee->signature()); !ss.at_return_type(); ss.next()) {
--- 3336,3364 ----
ResourceMark rm;
JavaThread* THREAD = thread;
methodHandle callee(callee_method);
int nb_slots = 0;
! InstanceKlass* holder = callee->method_holder();
! // TODO for now, don't scalarize value type receivers because of interface calls
! //bool has_value_receiver = !callee->is_static() && holder->is_value();
! bool has_value_receiver = false;
if (has_value_receiver) {
nb_slots++;
}
! Handle class_loader(THREAD, holder->class_loader());
! Handle protection_domain(THREAD, holder->protection_domain());
for (SignatureStream ss(callee->signature()); !ss.at_return_type(); ss.next()) {
if (ss.type() == T_VALUETYPE) {
nb_slots++;
}
}
objArrayOop array_oop = oopFactory::new_objectArray(nb_slots, CHECK);
objArrayHandle array(THREAD, array_oop);
int i = 0;
if (has_value_receiver) {
! ValueKlass* vk = ValueKlass::cast(holder);
oop res = vk->allocate_instance(CHECK);
array->obj_at_put(i, res);
i++;
}
for (SignatureStream ss(callee->signature()); !ss.at_return_type(); ss.next()) {
*** 3375,3385 ****
frame callerFrame = stubFrame.sender(®_map);
assert(callerFrame.is_interpreted_frame(), "should be coming from interpreter");
ValueKlass* vk = ValueKlass::cast(res->klass());
! const Array<SigEntry>* sig_vk = vk->extended_sig() ;
const Array<VMRegPair>* regs = vk->return_regs();
if (regs == NULL) {
// The fields of the value klass don't fit in registers, bail out
return;
--- 3411,3421 ----
frame callerFrame = stubFrame.sender(®_map);
assert(callerFrame.is_interpreted_frame(), "should be coming from interpreter");
ValueKlass* vk = ValueKlass::cast(res->klass());
! const Array<SigEntry>* sig_vk = vk->extended_sig();
const Array<VMRegPair>* regs = vk->return_regs();
if (regs == NULL) {
// The fields of the value klass don't fit in registers, bail out
return;
*** 3397,3444 ****
j++;
}
continue;
}
int off = sig_vk->at(i)._offset;
VMRegPair pair = regs->at(j);
address loc = reg_map.location(pair.first());
switch(bt) {
case T_BOOLEAN:
! *(intptr_t*)loc = *(jboolean*)((address)res + off);
break;
case T_CHAR:
! *(intptr_t*)loc = *(jchar*)((address)res + off);
break;
case T_BYTE:
! *(intptr_t*)loc = *(jbyte*)((address)res + off);
break;
case T_SHORT:
! *(intptr_t*)loc = *(jshort*)((address)res + off);
break;
case T_INT: {
! jint v = *(jint*)((address)res + off);
! *(intptr_t*)loc = v;
break;
}
case T_LONG:
#ifdef _LP64
! *(intptr_t*)loc = *(jlong*)((address)res + off);
#else
Unimplemented();
#endif
break;
case T_OBJECT:
case T_ARRAY: {
! oop v = HeapAccess<>::oop_load_at(res, off);
! *(oop*)loc = v;
break;
}
case T_FLOAT:
! *(jfloat*)loc = *(jfloat*)((address)res + off);
break;
case T_DOUBLE:
! *(jdouble*)loc = *(jdouble*)((address)res + off);
break;
default:
ShouldNotReachHere();
}
j++;
--- 3433,3479 ----
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*)loc = res->bool_field(off);
break;
case T_CHAR:
! *(jchar*)loc = res->char_field(off);
break;
case T_BYTE:
! *(jbyte*)loc = res->byte_field(off);
break;
case T_SHORT:
! *(jshort*)loc = res->short_field(off);
break;
case T_INT: {
! *(jint*)loc = res->int_field(off);
break;
}
case T_LONG:
#ifdef _LP64
! *(intptr_t*)loc = res->long_field(off);
#else
Unimplemented();
#endif
break;
case T_OBJECT:
case T_ARRAY: {
! *(oop*)loc = res->obj_field(off);
break;
}
case T_FLOAT:
! *(jfloat*)loc = res->float_field(off);
break;
case T_DOUBLE:
! *(jdouble*)loc = res->double_field(off);
break;
default:
ShouldNotReachHere();
}
j++;
*** 3481,3517 ****
clear_nth_bit(res, 0);
ValueKlass* vk = (ValueKlass*)res;
assert(verif_vk == vk, "broken calling convention");
assert(Metaspace::contains((void*)res), "should be klass");
! // Allocate handles for every oop fields so they are safe in case of
// a safepoint when allocating
GrowableArray<Handle> handles;
vk->save_oop_fields(reg_map, handles);
// It's unsafe to safepoint until we are here
-
- Handle new_vt;
JRT_BLOCK;
{
Thread* THREAD = thread;
oop vt = vk->realloc_result(reg_map, handles, CHECK);
! new_vt = Handle(thread, vt);
!
! #ifdef ASSERT
! javaVFrame* vf = javaVFrame::cast(vframe::new_vframe(&callerFrame, ®_map, thread));
! Method* m = vf->method();
! int bci = vf->bci();
! Bytecode_invoke inv(m, bci);
!
! methodHandle callee = inv.static_target(thread);
! assert(!thread->has_pending_exception(), "call resolution should work");
! ValueKlass* verif_vk2 = callee->returned_value_type(thread);
! assert(verif_vk == verif_vk2, "Bad value klass");
! #endif
}
JRT_BLOCK_END;
-
- thread->set_vm_result(new_vt());
}
JRT_END
--- 3516,3536 ----
clear_nth_bit(res, 0);
ValueKlass* vk = (ValueKlass*)res;
assert(verif_vk == vk, "broken calling convention");
assert(Metaspace::contains((void*)res), "should be klass");
! // Allocate handles for every oop field so they are safe in case of
// a safepoint when allocating
GrowableArray<Handle> handles;
vk->save_oop_fields(reg_map, handles);
// It's unsafe to safepoint until we are here
JRT_BLOCK;
{
Thread* THREAD = thread;
oop vt = vk->realloc_result(reg_map, handles, CHECK);
! thread->set_vm_result(vt);
}
JRT_BLOCK_END;
}
JRT_END
< prev index next >