--- old/src/share/vm/opto/valuetypenode.cpp 2017-06-01 17:27:47.044201033 +0200 +++ new/src/share/vm/opto/valuetypenode.cpp 2017-06-01 17:27:46.968201132 +0200 @@ -369,7 +369,14 @@ } } -uint ValueTypeNode::set_arguments_for_java_call(CallJavaNode* call, int base_input, const GraphKit& kit, ciValueKlass* base_vk, int base_offset) { +void ValueTypeNode::pass_klass(Node* n, uint pos, const GraphKit& kit) { + ciValueKlass* vk = value_klass(); + const TypeKlassPtr* tk = TypeKlassPtr::make(vk); + Node* arg = kit.makecon(tk); + n->init_req(pos, arg); +} + +uint ValueTypeNode::pass_fields(Node* n, int base_input, const GraphKit& kit, ciValueKlass* base_vk, int base_offset) { ciValueKlass* vk = value_klass(); if (base_vk == NULL) { base_vk = vk; @@ -381,7 +388,7 @@ Node* arg = field_value(i); if (f_type->is_valuetype()) { ciValueKlass* embedded_vk = f_type->as_value_klass(); - edges += arg->as_ValueType()->set_arguments_for_java_call(call, base_input, kit, base_vk, offset); + edges += arg->as_ValueType()->pass_fields(n, base_input, kit, base_vk, offset); } else { int j = 0; int extra = 0; for (; j < base_vk->nof_nonstatic_fields(); j++) { @@ -395,11 +402,11 @@ extra++; } } - call->init_req(base_input + j + extra, arg); + n->init_req(base_input + j + extra, arg); edges++; BasicType bt = f_type->basic_type(); if (bt == T_LONG || bt == T_DOUBLE) { - call->init_req(base_input + j + extra + 1, kit.top()); + n->init_req(base_input + j + extra + 1, kit.top()); edges++; } } @@ -427,6 +434,37 @@ return NULL; } +// When a call returns multiple values, it has several result +// projections, one per field. Replacing the result of the call by a +// value type node (after late inlining) requires that for each result +// projection, we find the corresponding value type field. +void ValueTypeNode::replace_call_results(Node* call, Compile* C) { + ciValueKlass* vk = value_klass(); + for (DUIterator_Fast imax, i = call->fast_outs(imax); i < imax; i++) { + ProjNode *pn = call->fast_out(i)->as_Proj(); + uint con = pn->_con; + if (con >= TypeFunc::Parms+1) { + uint field_nb = con - (TypeFunc::Parms+1); + int extra = 0; + for (uint j = 0; j < field_nb - extra; j++) { + ciField* f = vk->nonstatic_field_at(j); + BasicType bt = f->type()->basic_type(); + if (bt == T_LONG || bt == T_DOUBLE) { + extra++; + } + } + ciField* f = vk->nonstatic_field_at(field_nb - extra); + Node* field = field_value_by_offset(f->offset(), true); + + C->gvn_replace_by(pn, field); + C->initial_gvn()->hash_delete(pn); + pn->set_req(0, C->top()); + --i; --imax; + } + } +} + + #ifndef PRODUCT void ValueTypeNode::dump_spec(outputStream* st) const {