--- old/src/share/vm/opto/callGenerator.cpp 2016-12-13 16:55:41.720290503 +0100 +++ new/src/share/vm/opto/callGenerator.cpp 2016-12-13 16:55:41.657290625 +0100 @@ -372,11 +372,7 @@ return; } - // FIXME: late inlining of methods that take value type arguments is - // broken: arguments at the call are set up so fields of value type - // arguments are passed but code here expects a single argument per - // value type (a ValueTypeNode) instead. - const TypeTuple *r = call->tf()->domain_sig(); + const TypeTuple *r = call->tf()->domain_cc(); for (int i1 = 0; i1 < method()->arg_size(); i1++) { if (call->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) { assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); @@ -404,26 +400,48 @@ map->init_req(i1, call->in(i1)); } + PhaseGVN& gvn = *C->initial_gvn(); // Make sure the state is a MergeMem for parsing. if (!map->in(TypeFunc::Memory)->is_MergeMem()) { Node* mem = MergeMemNode::make(map->in(TypeFunc::Memory)); - C->initial_gvn()->set_type_bottom(mem); + gvn.set_type_bottom(mem); map->set_req(TypeFunc::Memory, mem); } - uint nargs = method()->arg_size(); // blow away old call arguments Node* top = C->top(); - for (uint i1 = 0; i1 < nargs; i1++) { - map->set_req(TypeFunc::Parms + i1, top); + for (uint i1 = TypeFunc::Parms; i1 < call->_tf->domain_cc()->cnt(); i1++) { + map->set_req(i1, top); } jvms->set_map(map); // Make enough space in the expression stack to transfer // the incoming arguments and return value. map->ensure_stack(jvms, jvms->method()->max_stack()); + const TypeTuple *domain_sig = call->_tf->domain_sig(); + uint nargs = method()->arg_size(); + assert(domain_sig->cnt() - TypeFunc::Parms == nargs, "inconsistent signature"); + + uint j = TypeFunc::Parms; for (uint i1 = 0; i1 < nargs; i1++) { - map->set_argument(jvms, i1, call->in(TypeFunc::Parms + i1)); + const Type* t = domain_sig->field_at(TypeFunc::Parms + i1); + if (!ValueTypePassFieldsAsArgs) { + Node* arg = call->in(TypeFunc::Parms + i1); + if (t->isa_valuetypeptr()) { + arg = ValueTypeNode::make(gvn, map->memory(), arg); + } + map->set_argument(jvms, i1, arg); + } else { + if (t->isa_valuetypeptr()) { + ciValueKlass* vk = t->is_valuetypeptr()->value_type()->value_klass(); + Node* vt = C->create_vt_node(call, vk, vk, 0, j); + map->set_argument(jvms, i1, gvn.transform(vt)); + j += vk->value_arg_slots(); + } else { + map->set_argument(jvms, i1, call->in(j)); + j++; + } + } } C->print_inlining_assert_ready(); @@ -466,6 +484,10 @@ C->env()->notice_inlined_method(_inline_cg->method()); C->set_inlining_progress(true); + if (result->is_ValueType()) { + result = result->as_ValueType()->store_to_memory(&kit); + } + kit.replace_call(call, result, true); }