--- old/src/share/vm/opto/callGenerator.cpp 2017-06-16 17:48:35.732843495 +0200 +++ new/src/share/vm/opto/callGenerator.cpp 2017-06-16 17:48:31.413856285 +0200 @@ -966,11 +966,24 @@ ciType* t = signature->type_at(i); if (t->is_klass()) { Node* arg = kit.argument(receiver_skip + j); - const TypeOopPtr* arg_type = arg->bottom_type()->isa_oopptr(); - const Type* sig_type = TypeOopPtr::make_from_klass(t->as_klass()); - if (arg_type != NULL && !arg_type->higher_equal(sig_type)) { - Node* cast_obj = gvn.transform(new CheckCastPPNode(kit.control(), arg, sig_type)); - kit.set_argument(receiver_skip + j, cast_obj); + const Type* arg_type = arg->bottom_type()->isa_ptr(); + const Type* sig_type = TypeOopPtr::make_from_klass(t->as_klass()); + if (t->is_valuetype()) { + if (arg_type->isa_valuetype() && t == kit.C->env()->___Value_klass()) { + assert(arg->is_ValueType(), "inconsistent"); + Node* vt = arg->as_ValueType()->store_to_memory(&kit); + kit.set_argument(receiver_skip + j, vt); + } else if (arg_type->isa_valuetypeptr() && t != kit.C->env()->___Value_klass()) { + const Type* sig_type = TypeOopPtr::make_from_klass(t->as_klass()); + Node* cast = gvn.transform(new CheckCastPPNode(kit.control(), arg, sig_type)); + Node* vt = ValueTypeNode::make(gvn, kit.merged_memory(), cast); + kit.set_argument(receiver_skip + j, vt); + } + } else { + if (arg_type->isa_oopptr() && !arg_type->higher_equal(sig_type)) { + Node* cast_obj = gvn.transform(new CheckCastPPNode(kit.control(), arg, sig_type)); + kit.set_argument(receiver_skip + j, cast_obj); + } } } j += t->size(); // long and double take two slots