--- old/src/share/vm/runtime/sharedRuntime.cpp 2017-05-15 17:07:22.014606363 +0200 +++ new/src/share/vm/runtime/sharedRuntime.cpp 2017-05-15 17:07:21.866606368 +0200 @@ -1108,6 +1108,7 @@ Bytecode_invoke bytecode(caller, bci); int bytecode_index = bytecode.index(); + bc = bytecode.invoke_code(); methodHandle attached_method = extract_attached_method(vfst); if (attached_method.not_null()) { @@ -1133,9 +1134,9 @@ } break; } + } else { + assert(ValueTypePassFieldsAsArgs, "invalid use of attached methods"); } - } else { - bc = bytecode.invoke_code(); } bool has_receiver = bc != Bytecodes::_invokestatic && @@ -1162,8 +1163,9 @@ // 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()); - LinkInfo link_info(constants, bytecode_index, CHECK_NH); + LinkInfo link_info(attached_method->method_holder(), attached_method->name(), attached_method->signature()); LinkResolver::resolve_virtual_call(callinfo, receiver, NULL, link_info, /*check_null_or_abstract*/ false, CHECK_NH); return receiver; // is null } else { @@ -1372,6 +1374,10 @@ if (ValueTypePassFieldsAsArgs && callee_method->method_holder()->is_value()) { // If the receiver is a value type that is passed as fields, no oop is available receiver_klass = callee_method->method_holder(); + if (FullGCALotWithValueTypes) { + // Trigger a full GC to verify that the GC knows about the contents of oop fields + Universe::heap()->collect(GCCause::_full_gc_alot); + } } else { assert(receiver.not_null() || invoke_code == Bytecodes::_invokehandle, "sanity check"); receiver_klass = invoke_code == Bytecodes::_invokehandle ? NULL : receiver->klass(); @@ -2456,9 +2462,9 @@ : BasicHashtable(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) { + AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry, Symbol* sig_extended) { AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable::new_entry(fingerprint->compute_hash()); - entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); + entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, sig_extended); if (DumpSharedSpaces) { ((CDSAdapterHandlerEntry*)entry)->init(); } @@ -2607,8 +2613,9 @@ AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, - address c2i_unverified_entry) { - return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); + address c2i_unverified_entry, + Symbol* sig_extended) { + return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, sig_extended); } // Value type arguments are not passed by reference, instead each @@ -3353,3 +3360,26 @@ thread->set_vm_result_2(callee()); // TODO: required to keep callee live? } JRT_END + +// Iterate of the array of heap allocated value types and apply the GC post barrier to all reference fields. +// This is called from the C2I adapter after value type arguments are heap allocated and initialized. +JRT_LEAF(void, SharedRuntime::apply_post_barriers(JavaThread* thread, objArrayOopDesc* array)) +{ + assert(ValueTypePassFieldsAsArgs, "no reason to call this"); + assert(array->is_oop(), "should be oop"); + for (int i = 0; i < array->length(); ++i) { + instanceOop valueOop = (instanceOop)array->obj_at(i); + ValueKlass* vk = ValueKlass::cast(valueOop->klass()); + if (vk->contains_oops()) { + const address dst_oop_addr = ((address) (void*) valueOop); + OopMapBlock* map = vk->start_of_nonstatic_oop_maps(); + OopMapBlock* const end = map + vk->nonstatic_oop_map_count(); + while (map != end) { + address doop_address = dst_oop_addr + map->offset(); + oopDesc::bs()->write_ref_array((HeapWord*) doop_address, map->count()); + map++; + } + } + } +} +JRT_END