--- old/src/share/vm/opto/callGenerator.cpp 2017-06-29 10:55:30.480126135 +0200 +++ new/src/share/vm/opto/callGenerator.cpp 2017-06-29 10:55:30.304126143 +0200 @@ -896,10 +896,11 @@ if (t->is_valuetype()) { assert(!(arg_type->isa_valuetype() && t == kit.C->env()->___Value_klass()), "need a pointer to the value type"); 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(arg_nb, vt); + } else { + assert(t == kit.C->env()->___Value_klass() || arg->is_ValueType(), "inconsistent argument"); } } else { if (arg_type->isa_oopptr() && !arg_type->higher_equal(sig_type)) { --- old/src/share/vm/opto/type.cpp 2017-06-29 10:55:31.148126103 +0200 +++ new/src/share/vm/opto/type.cpp 2017-06-29 10:55:30.952126113 +0200 @@ -261,7 +261,11 @@ return TypeRawPtr::make((address)(intptr_t)type->as_return_address()->bci()); case T_VALUETYPE: - return TypeValueType::make(type->as_value_klass()); + if (type == ciEnv::current()->___Value_klass()) { + return TypeValueTypePtr::NOTNULL; + } else { + return TypeValueType::make(type->as_value_klass()); + } default: // make sure we did not mix up the cases: --- old/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java 2017-06-29 10:55:32.080126060 +0200 +++ new/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java 2017-06-29 10:55:31.892126069 +0200 @@ -2566,6 +2566,45 @@ Asserts.assertEQ(vt.i, (int)staticVal3.c); } + // Test correct handling of __Value merges through PhiNodes + @Test() + public long test93() throws Throwable { + // Create a new value type + final MethodHandle dvt = MethodHandleBuilder.loadCode(MethodHandles.lookup(), "createValueType", + MethodType.methodType(ValueType.forClass(ValueCapableClass1.class).valueClass()), + CODE -> { + CODE. + iconst_1(). + anewarray(ValueType.forClass(ValueCapableClass1.class).valueClass()). + iconst_0(). + vaload(). + vreturn(); + }); + // Box the value type + final MethodHandle box = MethodHandleBuilder.loadCode(MethodHandles.lookup(), "boxValueType", + MethodType.methodType(ValueCapableClass1.class, ValueType.forClass(ValueCapableClass1.class).valueClass()), + CODE -> { + CODE. + vload(0). + vbox(ValueCapableClass1.class). + areturn(); + }); + long result = 0; + for (int i = 0; i < 10_000; ++i) { + // Merge __Value (ValueCapableClass1) from the two GWT branches, box to the VCC and access field + MethodHandle gwt = MethodHandles.guardWithTest(MethodHandles.constant(boolean.class, i % 2 == 0), dvt, dvt); + ValueCapableClass1 vcc = (ValueCapableClass1) MethodHandles.filterReturnValue(gwt, box).invokeExact(); + result += vcc.t; + } + return result; + } + + @DontCompile + public void test93_verifier(boolean warmup) throws Throwable { + long result = test93(); + Asserts.assertEQ(result, 0L); + } + // ========== Test infrastructure ========== private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();