From maurizio.cimadamore at oracle.com Thu Jun 1 12:26:23 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 1 Jun 2017 13:26:23 +0100 Subject: [mvt] RFR - add support for q-types in lambda forms Message-ID: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> Hi, please review the following patches which add support for q-types in lambda forms (LFs). http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_hs/ http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_jdk/ Adding q-type support in LFs is not straightforward, and we have played with a number of approaches. The big issue is that LFs are a mechanism to _share_ code between method handles (MHs) and they do so by means of 'erasure' - that is, two method handles taking String and Integer can (in principle) share the underlying LF (whose type is erased to Object - or L in the basic type lingo). With value types, erasure/sharing becomes an issue - on the one hand, we have to make sure that value types are not erased to the basic type L - which would then lead to nonsensical bytecode generation (such as areturn on a value operand). On the other hand there's a question of how much type information on value types we want to preserve during LF spinning. Two options are available: 1) value types do not get erased. That is, if a method type mentions one or more value types, such types are not erased in the underlying method form (MF) 2) a new basic type is added for value types (Q) and all value types 'erase' to that We started our experiments with (1) - while it is doable, there are two major pain points: * keeping sharp type information on value types inside LF effectively undoes one of the big advantages of LFs - that is, code sharing. A MH taking a QPoint and a MH taking a QPerson will _not_ be able to share the underlying LF. * this approach is basically at odds with the rest of the LF machinery, which is fundamentally basic-type based. This is particularly evident in the handling of intrinsics (see LambdaForm.createFormsFor) where special LF (such as 'identity' or 'zero') are cached in an array that is indexed by basic type. If we followed this approach we would split the implementation in two: parts for which caching can be enabled, and parts for which caching is not possible. For these reasons, we moved on to consider (2). The most problematic aspect of (2) is to find a common type to which all values can be safely 'erased' to. Turns out that hotspot already has this type - that's what java.lang.__Value is used for. So, we can indeed define a new basic type for Q, and use the j.l.Class of j.l.Value as its standard representation (while Object.class is still used for the boxed representation). All the rest is can be regarded as implementation details - that is, we need to make sure that Q-types are erased accordingly when going to method types to MF - and we also need to make sure that LF with values in them generate the correct bytecode. This was a major implementation challenge, as the current InvokeBytecodeGenerator is written in terms of ASM which doesn't (yet) have support for value opcodes. To workaround the issue, I've written an alternate InvokeBytecodeGenerator - called LambdaFormBuilder which is specifically used to spin bytecode for LF containing values. This builder is based on the bytecode API already bundled with the valhalla repo. Now, to the practical bits :-) There are a bunch of flags I've added to enable the new support; the first and most important is: -Dvalhalla.enableValueLambdaForms=true which allows value types to survive MethodType->MethodForm conversion, and enables the alternate LambdaFormBuilder class for spinning bytecode. There's also a second flag: -Dvalhalla.enablePoolPatches=true Which can be used to allow constant pool patching in the MethodHandleBuilder machinery - this should bring the generated code for LambdaFormBuilder closer to what InvokeBytecodeGenerator was emitting. But it can be mostly regarded as an optional optimization. Finally, more work needs to be done in this area; first, this support only works if JIT is disabled (e.g. -Xint is used). Some work in this area is currently under way - see: http://mail.openjdk.java.net/pipermail/valhalla-dev/2017-May/002464.html Secondly, bound method handle are _not_ supported. It seems like adding support for Q-types here would require some major surgery to the underlying machinery (most of the signatures for BMH are expressed in terms of Object[] anyway - see insertArguments). I would like to thank Vladimir Ivanov - this work would not have been possible w/o his many thoughtful insights. I'd also like to thank Roland Westrelin for 'alpha-testing' this patch, a thankless job which led to many bug fixes. Maurizio From david.simms at oracle.com Thu Jun 1 12:36:19 2017 From: david.simms at oracle.com (david.simms at oracle.com) Date: Thu, 01 Jun 2017 12:36:19 +0000 Subject: hg: valhalla/valhalla/jdk: MH names generate classes within the same package as host class (VCC) Message-ID: <201706011236.v51CaK4H002522@aojmv0008.oracle.com> Changeset: 8fa3c4304495 Author: dsimms Date: 2017-06-01 12:22 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/8fa3c4304495 MH names generate classes within the same package as host class (VCC) ! src/java.base/share/classes/jdk/experimental/value/ValueType.java From rwestrel at redhat.com Thu Jun 1 15:06:44 2017 From: rwestrel at redhat.com (rwestrel at redhat.com) Date: Thu, 01 Jun 2017 15:06:44 +0000 Subject: hg: valhalla/valhalla/hotspot: ValueTypeTestBench test fix Message-ID: <201706011506.v51F6iiq002409@aojmv0008.oracle.com> Changeset: 9efeb455334c Author: roland Date: 2017-06-01 16:33 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/9efeb455334c ValueTypeTestBench test fix ! test/compiler/valhalla/valuetypes/ValueTypeTestBench.java From rwestrel at redhat.com Thu Jun 1 15:21:05 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Thu, 01 Jun 2017 17:21:05 +0200 Subject: replay fixes for value type reference fields Message-ID: http://cr.openjdk.java.net/~roland/valhalla/replay-reffields/webrev.00/ This should fix compilation replay so it handles reference fields in static value type fields. It also improves replay a bit: for object fields, replay dumps the signature of the field which could differ from the actual field type. An field declared as Object could even be an array.. With that change replay dumps the actual field type. Roland. From rwestrel at redhat.com Thu Jun 1 15:51:26 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Thu, 01 Jun 2017 17:51:26 +0200 Subject: Return value type fields in registers In-Reply-To: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> References: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> Message-ID: Thanks for the detailed review. Here is a new webrev: http://cr.openjdk.java.net/~roland/valhalla/returnconvention/webrev.02/ > I'm seeing build failures [1] on JPRT and the ValueTypeTestBench fails > on Windows [2] and crashes with an assert [3] on my machine. Build failures should be fixed now. I made sure it builds with precompiled headers disabled. I tried to figure out what could cause the windows failure but I can't say I have a clue. Registers for returns should be the same but used in a different order. I don't see why that would make a difference. I don't have access to a windows machine so I don't see what I can do about it. The assert failure should be fixed now. I added a new test case to reproduce it (test76). Interestingly it causes a crash with ValueTypeReturnedAsFields off. I found that's because we allocate in vreturn, we can actually throw in a return which is not something c2 expects. 2308 set_bci(InvocationEntryBci); in parse1.cpp breaks the exception handling logic. I commented it out and everything seems to work. I also look at the code and saw no reason for clearing the bci. > compile.cpp > - Why is the change in line 2869 necessary? It's not. Removed. > - It would be good to add a reference field to MyValue3 to extend > coverage Done. It caused some new failures in escape analysis so there's some new changes there. Roland. From paul.sandoz at oracle.com Fri Jun 2 00:00:06 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 1 Jun 2017 17:00:06 -0700 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> Message-ID: <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> > On 1 Jun 2017, at 05:26, Maurizio Cimadamore wrote: > > Hi, > please review the following patches which add support for q-types in lambda forms (LFs). > > http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_hs/ > http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_jdk/ > A minor point, it can make it easier to remember the flags if they are grouped in a known place, such as MethodHandleStatics. At least the test has some tabs vs. spaces, which results in off-kilter formatting. Perhaps auto format the code in IntellJ? For BMHs i am guessing we would require some expansion to include Q in the set of support basic types e.g. Species_Q and appropriate modifications to the code generation like you did for LamdaForm? Paul. > Adding q-type support in LFs is not straightforward, and we have played with a number of approaches. The big issue is that LFs are a mechanism to _share_ code between method handles (MHs) and they do so by means of 'erasure' - that is, two method handles taking String and Integer can (in principle) share the underlying LF (whose type is erased to Object - or L in the basic type lingo). > > With value types, erasure/sharing becomes an issue - on the one hand, we have to make sure that value types are not erased to the basic type L - which would then lead to nonsensical bytecode generation (such as areturn on a value operand). On the other hand there's a question of how much type information on value types we want to preserve during LF spinning. Two options are available: > > 1) value types do not get erased. That is, if a method type mentions one or more value types, such types are not erased in the underlying method form (MF) > 2) a new basic type is added for value types (Q) and all value types 'erase' to that > > We started our experiments with (1) - while it is doable, there are two major pain points: > > * keeping sharp type information on value types inside LF effectively undoes one of the big advantages of LFs - that is, code sharing. A MH taking a QPoint and a MH taking a QPerson will _not_ be able to share the underlying LF. > > * this approach is basically at odds with the rest of the LF machinery, which is fundamentally basic-type based. This is particularly evident in the handling of intrinsics (see LambdaForm.createFormsFor) where special LF (such as 'identity' or 'zero') are cached in an array that is indexed by basic type. If we followed this approach we would split the implementation in two: parts for which caching can be enabled, and parts for which caching is not possible. > > For these reasons, we moved on to consider (2). The most problematic aspect of (2) is to find a common type to which all values can be safely 'erased' to. Turns out that hotspot already has this type - that's what java.lang.__Value is used for. So, we can indeed define a new basic type for Q, and use the j.l.Class of j.l.Value as its standard representation (while Object.class is still used for the boxed representation). > > All the rest is can be regarded as implementation details - that is, we need to make sure that Q-types are erased accordingly when going to method types to MF - and we also need to make sure that LF with values in them generate the correct bytecode. This was a major implementation challenge, as the current InvokeBytecodeGenerator is written in terms of ASM which doesn't (yet) have support for value opcodes. To workaround the issue, I've written an alternate InvokeBytecodeGenerator - called LambdaFormBuilder which is specifically used to spin bytecode for LF containing values. This builder is based on the bytecode API already bundled with the valhalla repo. > > Now, to the practical bits :-) > > There are a bunch of flags I've added to enable the new support; the first and most important is: > > -Dvalhalla.enableValueLambdaForms=true > > which allows value types to survive MethodType->MethodForm conversion, and enables the alternate LambdaFormBuilder class for spinning bytecode. > > There's also a second flag: > > -Dvalhalla.enablePoolPatches=true > > Which can be used to allow constant pool patching in the MethodHandleBuilder machinery - this should bring the generated code for LambdaFormBuilder closer to what InvokeBytecodeGenerator was emitting. But it can be mostly regarded as an optional optimization. > > Finally, more work needs to be done in this area; first, this support only works if JIT is disabled (e.g. -Xint is used). Some work in this area is currently under way - see: > > http://mail.openjdk.java.net/pipermail/valhalla-dev/2017-May/002464.html > > Secondly, bound method handle are _not_ supported. It seems like adding support for Q-types here would require some major surgery to the underlying machinery (most of the signatures for BMH are expressed in terms of Object[] anyway - see insertArguments). > > > I would like to thank Vladimir Ivanov - this work would not have been possible w/o his many thoughtful insights. I'd also like to thank Roland Westrelin for 'alpha-testing' this patch, a thankless job which led to many bug fixes. > > Maurizio From maurizio.cimadamore at oracle.com Fri Jun 2 00:09:09 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 2 Jun 2017 01:09:09 +0100 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> Message-ID: On 02/06/17 01:00, Paul Sandoz wrote: >> On 1 Jun 2017, at 05:26, Maurizio Cimadamore wrote: >> >> Hi, >> please review the following patches which add support for q-types in lambda forms (LFs). >> >> http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_hs/ >> http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_jdk/ >> > A minor point, it can make it easier to remember the flags if they are grouped in a known place, such as MethodHandleStatics. Good suggestion, I'll do that > > At least the test has some tabs vs. spaces, which results in off-kilter formatting. Perhaps auto format the code in IntellJ? Yeah there's something up there... > > For BMHs i am guessing we would require some expansion to include Q in the set of support basic types e.g. Species_Q and appropriate modifications to the code generation like you did for LamdaForm? I think one problem is to fix BMH/Species_Q and the classes it heavily relies on (LambdaFormEditor) to support Q-types. But the other flip of the coin is to handle APIs - if you have a method handle that takes a Q-type, how do you 'bind' its argument? The APIs we have today are boxy. Some of these APIs are used internally by some of the BMH classes, so you could hit them through combinators too. Maurizio > > Paul. > > >> Adding q-type support in LFs is not straightforward, and we have played with a number of approaches. The big issue is that LFs are a mechanism to _share_ code between method handles (MHs) and they do so by means of 'erasure' - that is, two method handles taking String and Integer can (in principle) share the underlying LF (whose type is erased to Object - or L in the basic type lingo). >> >> With value types, erasure/sharing becomes an issue - on the one hand, we have to make sure that value types are not erased to the basic type L - which would then lead to nonsensical bytecode generation (such as areturn on a value operand). On the other hand there's a question of how much type information on value types we want to preserve during LF spinning. Two options are available: >> >> 1) value types do not get erased. That is, if a method type mentions one or more value types, such types are not erased in the underlying method form (MF) >> 2) a new basic type is added for value types (Q) and all value types 'erase' to that >> >> We started our experiments with (1) - while it is doable, there are two major pain points: >> >> * keeping sharp type information on value types inside LF effectively undoes one of the big advantages of LFs - that is, code sharing. A MH taking a QPoint and a MH taking a QPerson will _not_ be able to share the underlying LF. >> >> * this approach is basically at odds with the rest of the LF machinery, which is fundamentally basic-type based. This is particularly evident in the handling of intrinsics (see LambdaForm.createFormsFor) where special LF (such as 'identity' or 'zero') are cached in an array that is indexed by basic type. If we followed this approach we would split the implementation in two: parts for which caching can be enabled, and parts for which caching is not possible. >> >> For these reasons, we moved on to consider (2). The most problematic aspect of (2) is to find a common type to which all values can be safely 'erased' to. Turns out that hotspot already has this type - that's what java.lang.__Value is used for. So, we can indeed define a new basic type for Q, and use the j.l.Class of j.l.Value as its standard representation (while Object.class is still used for the boxed representation). >> >> All the rest is can be regarded as implementation details - that is, we need to make sure that Q-types are erased accordingly when going to method types to MF - and we also need to make sure that LF with values in them generate the correct bytecode. This was a major implementation challenge, as the current InvokeBytecodeGenerator is written in terms of ASM which doesn't (yet) have support for value opcodes. To workaround the issue, I've written an alternate InvokeBytecodeGenerator - called LambdaFormBuilder which is specifically used to spin bytecode for LF containing values. This builder is based on the bytecode API already bundled with the valhalla repo. >> >> Now, to the practical bits :-) >> >> There are a bunch of flags I've added to enable the new support; the first and most important is: >> >> -Dvalhalla.enableValueLambdaForms=true >> >> which allows value types to survive MethodType->MethodForm conversion, and enables the alternate LambdaFormBuilder class for spinning bytecode. >> >> There's also a second flag: >> >> -Dvalhalla.enablePoolPatches=true >> >> Which can be used to allow constant pool patching in the MethodHandleBuilder machinery - this should bring the generated code for LambdaFormBuilder closer to what InvokeBytecodeGenerator was emitting. But it can be mostly regarded as an optional optimization. >> >> Finally, more work needs to be done in this area; first, this support only works if JIT is disabled (e.g. -Xint is used). Some work in this area is currently under way - see: >> >> http://mail.openjdk.java.net/pipermail/valhalla-dev/2017-May/002464.html >> >> Secondly, bound method handle are _not_ supported. It seems like adding support for Q-types here would require some major surgery to the underlying machinery (most of the signatures for BMH are expressed in terms of Object[] anyway - see insertArguments). >> >> >> I would like to thank Vladimir Ivanov - this work would not have been possible w/o his many thoughtful insights. I'd also like to thank Roland Westrelin for 'alpha-testing' this patch, a thankless job which led to many bug fixes. >> >> Maurizio From tobias.hartmann at oracle.com Fri Jun 2 13:09:30 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Fri, 2 Jun 2017 15:09:30 +0200 Subject: Return value type fields in registers In-Reply-To: References: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> Message-ID: Hi Roland, I've executed some quick testing on JPRT on top of Maurizio's latest patch: http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_hs/ http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_jdk/ I see multiple failures: ValueTypesTestBench fails with: # Internal Error (/scratch/opt/jprt/T/P1/112707.tohartma/s/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp:889), pid=3999, tid=4000 # assert(false) failed: DEBUG MESSAGE: illegal bytecode sequence - method not verified Stack: [0x00007f9a958b1000,0x00007f9a959b2000], sp=0x00007f9a959afcf0, free space=1019k Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code) V [libjvm.so+0x169ce1f] VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x15f V [libjvm.so+0x169dbcf] VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x2f V [libjvm.so+0xacf6fd] report_vm_error(char const*, int, char const*, char const*, ...)+0xdd V [libjvm.so+0x11641c4] MacroAssembler::debug64(char*, long, long*)+0x204 j compiler.valhalla.valuetypes.ValueTypeTestBench.test75()Qcompiler/valhalla/valuetypes/MyValue3;+4 j compiler.valhalla.valuetypes.ValueTypeTestBench.test75_verifier(Z)V+32 v ~StubRoutines::call_stub On Windows it still fails with Caused by: java.lang.RuntimeException: assertEquals: expected 1309945560682 to equal -2494 at jdk.test.lib.Asserts.fail(Asserts.java:594) at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) at jdk.test.lib.Asserts.assertEquals(Asserts.java:189) at jdk.test.lib.Asserts.assertEQ(Asserts.java:166) at compiler.valhalla.valuetypes.ValueTypeTestBench.test54_verifier(ValueTypeTestBench.java:1612) runtime/valhalla/valuetypes/VboxUnbox.java fails with java.lang.RuntimeException: assertTrue: expected true, was false at jdk.test.lib.Asserts.fail(Asserts.java:594) at jdk.test.lib.Asserts.assertTrue(Asserts.java:486) at jdk.test.lib.Asserts.assertTrue(Asserts.java:472) at runtime.valhalla.valuetypes.VboxUnbox.testCorrectBoxing(VboxUnbox.java:63) at runtime.valhalla.valuetypes.VboxUnbox.main(VboxUnbox.java:41) I'm not sure though if those problems are related to your fix. I'll re-run without your changes. Best regards, Tobias On 01.06.2017 17:51, Roland Westrelin wrote: > > Thanks for the detailed review. Here is a new webrev: > > http://cr.openjdk.java.net/~roland/valhalla/returnconvention/webrev.02/ > >> I'm seeing build failures [1] on JPRT and the ValueTypeTestBench fails >> on Windows [2] and crashes with an assert [3] on my machine. > > Build failures should be fixed now. I made sure it builds with > precompiled headers disabled. > > I tried to figure out what could cause the windows failure but I can't > say I have a clue. Registers for returns should be the same but used in > a different order. I don't see why that would make a difference. I don't > have access to a windows machine so I don't see what I can do about it. > > The assert failure should be fixed now. I added a new test case to > reproduce it (test76). Interestingly it causes a crash with > ValueTypeReturnedAsFields off. I found that's because we allocate in > vreturn, we can actually throw in a return which is not something c2 > expects. > > 2308 set_bci(InvocationEntryBci); > > in parse1.cpp breaks the exception handling logic. I commented it out > and everything seems to work. I also look at the code and saw no reason > for clearing the bci. > >> compile.cpp >> - Why is the change in line 2869 necessary? > > It's not. Removed. > >> - It would be good to add a reference field to MyValue3 to extend >> coverage > > Done. It caused some new failures in escape analysis so there's some new > changes there. > > Roland. > From maurizio.cimadamore at oracle.com Fri Jun 2 14:16:52 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 2 Jun 2017 15:16:52 +0100 Subject: Return value type fields in registers In-Reply-To: References: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> Message-ID: Did you add the flag -Dvalhalla.enableValueLambdaForms=true to the mix? If not, the LF specialization will not kick in. Maurizio On 02/06/17 14:09, Tobias Hartmann wrote: > Hi Roland, > > I've executed some quick testing on JPRT on top of Maurizio's latest patch: > http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_hs/ > http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_jdk/ > > I see multiple failures: > > ValueTypesTestBench fails with: > > # Internal Error (/scratch/opt/jprt/T/P1/112707.tohartma/s/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp:889), pid=3999, tid=4000 > # assert(false) failed: DEBUG MESSAGE: illegal bytecode sequence - method not verified > > Stack: [0x00007f9a958b1000,0x00007f9a959b2000], sp=0x00007f9a959afcf0, free space=1019k > Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code) > V [libjvm.so+0x169ce1f] VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x15f > V [libjvm.so+0x169dbcf] VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x2f > V [libjvm.so+0xacf6fd] report_vm_error(char const*, int, char const*, char const*, ...)+0xdd > V [libjvm.so+0x11641c4] MacroAssembler::debug64(char*, long, long*)+0x204 > j compiler.valhalla.valuetypes.ValueTypeTestBench.test75()Qcompiler/valhalla/valuetypes/MyValue3;+4 > j compiler.valhalla.valuetypes.ValueTypeTestBench.test75_verifier(Z)V+32 > v ~StubRoutines::call_stub > > On Windows it still fails with > Caused by: java.lang.RuntimeException: assertEquals: expected 1309945560682 to equal -2494 > at jdk.test.lib.Asserts.fail(Asserts.java:594) > at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) > at jdk.test.lib.Asserts.assertEquals(Asserts.java:189) > at jdk.test.lib.Asserts.assertEQ(Asserts.java:166) > at compiler.valhalla.valuetypes.ValueTypeTestBench.test54_verifier(ValueTypeTestBench.java:1612) > > runtime/valhalla/valuetypes/VboxUnbox.java fails with > java.lang.RuntimeException: assertTrue: expected true, was false > at jdk.test.lib.Asserts.fail(Asserts.java:594) > at jdk.test.lib.Asserts.assertTrue(Asserts.java:486) > at jdk.test.lib.Asserts.assertTrue(Asserts.java:472) > at runtime.valhalla.valuetypes.VboxUnbox.testCorrectBoxing(VboxUnbox.java:63) > at runtime.valhalla.valuetypes.VboxUnbox.main(VboxUnbox.java:41) > > > I'm not sure though if those problems are related to your fix. I'll re-run without your changes. > > Best regards, > Tobias > > On 01.06.2017 17:51, Roland Westrelin wrote: >> Thanks for the detailed review. Here is a new webrev: >> >> http://cr.openjdk.java.net/~roland/valhalla/returnconvention/webrev.02/ >> >>> I'm seeing build failures [1] on JPRT and the ValueTypeTestBench fails >>> on Windows [2] and crashes with an assert [3] on my machine. >> Build failures should be fixed now. I made sure it builds with >> precompiled headers disabled. >> >> I tried to figure out what could cause the windows failure but I can't >> say I have a clue. Registers for returns should be the same but used in >> a different order. I don't see why that would make a difference. I don't >> have access to a windows machine so I don't see what I can do about it. >> >> The assert failure should be fixed now. I added a new test case to >> reproduce it (test76). Interestingly it causes a crash with >> ValueTypeReturnedAsFields off. I found that's because we allocate in >> vreturn, we can actually throw in a return which is not something c2 >> expects. >> >> 2308 set_bci(InvocationEntryBci); >> >> in parse1.cpp breaks the exception handling logic. I commented it out >> and everything seems to work. I also look at the code and saw no reason >> for clearing the bci. >> >>> compile.cpp >>> - Why is the change in line 2869 necessary? >> It's not. Removed. >> >>> - It would be good to add a reference field to MyValue3 to extend >>> coverage >> Done. It caused some new failures in escape analysis so there's some new >> changes there. >> >> Roland. >> From maurizio.cimadamore at oracle.com Fri Jun 2 14:44:11 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 2 Jun 2017 15:44:11 +0100 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> Message-ID: <8141c98b-18ec-1a3f-1b1f-c9352eda8781@oracle.com> Here's a second revision of the jdk changes: http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_jdk_v2 * I've shared the initialization of the static flag used by both LambdaForm and MethodTypeForm in MethodHandleStatics. * I've removed tabs from MVTTest Thanks Maurizio On 02/06/17 01:09, Maurizio Cimadamore wrote: > > > On 02/06/17 01:00, Paul Sandoz wrote: >>> On 1 Jun 2017, at 05:26, Maurizio Cimadamore >>> wrote: >>> >>> Hi, >>> please review the following patches which add support for q-types in >>> lambda forms (LFs). >>> >>> http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_hs/ >>> http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_jdk/ >>> >> A minor point, it can make it easier to remember the flags if they >> are grouped in a known place, such as MethodHandleStatics. > Good suggestion, I'll do that >> >> At least the test has some tabs vs. spaces, which results in >> off-kilter formatting. Perhaps auto format the code in IntellJ? > Yeah there's something up there... >> >> For BMHs i am guessing we would require some expansion to include Q >> in the set of support basic types e.g. Species_Q and appropriate >> modifications to the code generation like you did for LamdaForm? > I think one problem is to fix BMH/Species_Q and the classes it heavily > relies on (LambdaFormEditor) to support Q-types. But the other flip of > the coin is to handle APIs - if you have a method handle that takes a > Q-type, how do you 'bind' its argument? The APIs we have today are > boxy. Some of these APIs are used internally by some of the BMH > classes, so you could hit them through combinators too. > > Maurizio > >> >> Paul. >> >> >>> Adding q-type support in LFs is not straightforward, and we have >>> played with a number of approaches. The big issue is that LFs are a >>> mechanism to _share_ code between method handles (MHs) and they do >>> so by means of 'erasure' - that is, two method handles taking String >>> and Integer can (in principle) share the underlying LF (whose type >>> is erased to Object - or L in the basic type lingo). >>> >>> With value types, erasure/sharing becomes an issue - on the one >>> hand, we have to make sure that value types are not erased to the >>> basic type L - which would then lead to nonsensical bytecode >>> generation (such as areturn on a value operand). On the other hand >>> there's a question of how much type information on value types we >>> want to preserve during LF spinning. Two options are available: >>> >>> 1) value types do not get erased. That is, if a method type mentions >>> one or more value types, such types are not erased in the underlying >>> method form (MF) >>> 2) a new basic type is added for value types (Q) and all value types >>> 'erase' to that >>> >>> We started our experiments with (1) - while it is doable, there are >>> two major pain points: >>> >>> * keeping sharp type information on value types inside LF >>> effectively undoes one of the big advantages of LFs - that is, code >>> sharing. A MH taking a QPoint and a MH taking a QPerson will _not_ >>> be able to share the underlying LF. >>> >>> * this approach is basically at odds with the rest of the LF >>> machinery, which is fundamentally basic-type based. This is >>> particularly evident in the handling of intrinsics (see >>> LambdaForm.createFormsFor) where special LF (such as 'identity' or >>> 'zero') are cached in an array that is indexed by basic type. If we >>> followed this approach we would split the implementation in two: >>> parts for which caching can be enabled, and parts for which caching >>> is not possible. >>> >>> For these reasons, we moved on to consider (2). The most problematic >>> aspect of (2) is to find a common type to which all values can be >>> safely 'erased' to. Turns out that hotspot already has this type - >>> that's what java.lang.__Value is used for. So, we can indeed define >>> a new basic type for Q, and use the j.l.Class of j.l.Value as its >>> standard representation (while Object.class is still used for the >>> boxed representation). >>> >>> All the rest is can be regarded as implementation details - that is, >>> we need to make sure that Q-types are erased accordingly when going >>> to method types to MF - and we also need to make sure that LF with >>> values in them generate the correct bytecode. This was a major >>> implementation challenge, as the current InvokeBytecodeGenerator is >>> written in terms of ASM which doesn't (yet) have support for value >>> opcodes. To workaround the issue, I've written an alternate >>> InvokeBytecodeGenerator - called LambdaFormBuilder which is >>> specifically used to spin bytecode for LF containing values. This >>> builder is based on the bytecode API already bundled with the >>> valhalla repo. >>> >>> Now, to the practical bits :-) >>> >>> There are a bunch of flags I've added to enable the new support; the >>> first and most important is: >>> >>> -Dvalhalla.enableValueLambdaForms=true >>> >>> which allows value types to survive MethodType->MethodForm >>> conversion, and enables the alternate LambdaFormBuilder class for >>> spinning bytecode. >>> >>> There's also a second flag: >>> >>> -Dvalhalla.enablePoolPatches=true >>> >>> Which can be used to allow constant pool patching in the >>> MethodHandleBuilder machinery - this should bring the generated code >>> for LambdaFormBuilder closer to what InvokeBytecodeGenerator was >>> emitting. But it can be mostly regarded as an optional optimization. >>> >>> Finally, more work needs to be done in this area; first, this >>> support only works if JIT is disabled (e.g. -Xint is used). Some >>> work in this area is currently under way - see: >>> >>> http://mail.openjdk.java.net/pipermail/valhalla-dev/2017-May/002464.html >>> >>> >>> Secondly, bound method handle are _not_ supported. It seems like >>> adding support for Q-types here would require some major surgery to >>> the underlying machinery (most of the signatures for BMH are >>> expressed in terms of Object[] anyway - see insertArguments). >>> >>> >>> I would like to thank Vladimir Ivanov - this work would not have >>> been possible w/o his many thoughtful insights. I'd also like to >>> thank Roland Westrelin for 'alpha-testing' this patch, a thankless >>> job which led to many bug fixes. >>> >>> Maurizio > From paul.sandoz at oracle.com Fri Jun 2 16:49:27 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 2 Jun 2017 09:49:27 -0700 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <8141c98b-18ec-1a3f-1b1f-c9352eda8781@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <8141c98b-18ec-1a3f-1b1f-c9352eda8781@oracle.com> Message-ID: <99AB4C63-C5CE-4F94-9F0E-C74AB42DD37A@oracle.com> Looks good to me, Paul. > On 2 Jun 2017, at 07:44, Maurizio Cimadamore wrote: > > Here's a second revision of the jdk changes: > > http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_jdk_v2 > > * I've shared the initialization of the static flag used by both LambdaForm and MethodTypeForm in MethodHandleStatics. > * I've removed tabs from MVTTest > > Thanks > Maurizio From paul.sandoz at oracle.com Fri Jun 2 17:06:16 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 2 Jun 2017 10:06:16 -0700 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> Message-ID: <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> > On 1 Jun 2017, at 17:09, Maurizio Cimadamore wrote: >> >> For BMHs i am guessing we would require some expansion to include Q in the set of support basic types e.g. Species_Q and appropriate modifications to the code generation like you did for LamdaForm? > I think one problem is to fix BMH/Species_Q and the classes it heavily relies on (LambdaFormEditor) to support Q-types. Ok. > But the other flip of the coin is to handle APIs - if you have a method handle that takes a Q-type, how do you 'bind' its argument? The APIs we have today are boxy. Some of these APIs are used internally by some of the BMH classes, so you could hit them through combinators too. > Yeah: public MethodHandle bindTo(Object x) Do we need something like: public MethodHandle bindToValue (__Value v) ? Such a bifurcation is somewhat awkward. Paul. > Maurizio > >> >> Paul. >> >> >>> Adding q-type support in LFs is not straightforward, and we have played with a number of approaches. The big issue is that LFs are a mechanism to _share_ code between method handles (MHs) and they do so by means of 'erasure' - that is, two method handles taking String and Integer can (in principle) share the underlying LF (whose type is erased to Object - or L in the basic type lingo). >>> >>> With value types, erasure/sharing becomes an issue - on the one hand, we have to make sure that value types are not erased to the basic type L - which would then lead to nonsensical bytecode generation (such as areturn on a value operand). On the other hand there's a question of how much type information on value types we want to preserve during LF spinning. Two options are available: >>> >>> 1) value types do not get erased. That is, if a method type mentions one or more value types, such types are not erased in the underlying method form (MF) >>> 2) a new basic type is added for value types (Q) and all value types 'erase' to that >>> >>> We started our experiments with (1) - while it is doable, there are two major pain points: >>> >>> * keeping sharp type information on value types inside LF effectively undoes one of the big advantages of LFs - that is, code sharing. A MH taking a QPoint and a MH taking a QPerson will _not_ be able to share the underlying LF. >>> >>> * this approach is basically at odds with the rest of the LF machinery, which is fundamentally basic-type based. This is particularly evident in the handling of intrinsics (see LambdaForm.createFormsFor) where special LF (such as 'identity' or 'zero') are cached in an array that is indexed by basic type. If we followed this approach we would split the implementation in two: parts for which caching can be enabled, and parts for which caching is not possible. >>> >>> For these reasons, we moved on to consider (2). The most problematic aspect of (2) is to find a common type to which all values can be safely 'erased' to. Turns out that hotspot already has this type - that's what java.lang.__Value is used for. So, we can indeed define a new basic type for Q, and use the j.l.Class of j.l.Value as its standard representation (while Object.class is still used for the boxed representation). >>> >>> All the rest is can be regarded as implementation details - that is, we need to make sure that Q-types are erased accordingly when going to method types to MF - and we also need to make sure that LF with values in them generate the correct bytecode. This was a major implementation challenge, as the current InvokeBytecodeGenerator is written in terms of ASM which doesn't (yet) have support for value opcodes. To workaround the issue, I've written an alternate InvokeBytecodeGenerator - called LambdaFormBuilder which is specifically used to spin bytecode for LF containing values. This builder is based on the bytecode API already bundled with the valhalla repo. >>> >>> Now, to the practical bits :-) >>> >>> There are a bunch of flags I've added to enable the new support; the first and most important is: >>> >>> -Dvalhalla.enableValueLambdaForms=true >>> >>> which allows value types to survive MethodType->MethodForm conversion, and enables the alternate LambdaFormBuilder class for spinning bytecode. >>> >>> There's also a second flag: >>> >>> -Dvalhalla.enablePoolPatches=true >>> >>> Which can be used to allow constant pool patching in the MethodHandleBuilder machinery - this should bring the generated code for LambdaFormBuilder closer to what InvokeBytecodeGenerator was emitting. But it can be mostly regarded as an optional optimization. >>> >>> Finally, more work needs to be done in this area; first, this support only works if JIT is disabled (e.g. -Xint is used). Some work in this area is currently under way - see: >>> >>> http://mail.openjdk.java.net/pipermail/valhalla-dev/2017-May/002464.html >>> >>> Secondly, bound method handle are _not_ supported. It seems like adding support for Q-types here would require some major surgery to the underlying machinery (most of the signatures for BMH are expressed in terms of Object[] anyway - see insertArguments). >>> >>> >>> I would like to thank Vladimir Ivanov - this work would not have been possible w/o his many thoughtful insights. I'd also like to thank Roland Westrelin for 'alpha-testing' this patch, a thankless job which led to many bug fixes. >>> >>> Maurizio > From maurizio.cimadamore at oracle.com Fri Jun 2 17:27:29 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 2 Jun 2017 18:27:29 +0100 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> Message-ID: <901fb642-aaf8-1ab6-c5f6-09fee5ea8fcf@oracle.com> On 02/06/17 18:06, Paul Sandoz wrote: >> On 1 Jun 2017, at 17:09, Maurizio Cimadamore wrote: >>> For BMHs i am guessing we would require some expansion to include Q in the set of support basic types e.g. Species_Q and appropriate modifications to the code generation like you did for LamdaForm? >> I think one problem is to fix BMH/Species_Q and the classes it heavily relies on (LambdaFormEditor) to support Q-types. > Ok. > > >> But the other flip of the coin is to handle APIs - if you have a method handle that takes a Q-type, how do you 'bind' its argument? The APIs we have today are boxy. Some of these APIs are used internally by some of the BMH classes, so you could hit them through combinators too. >> > Yeah: > > public MethodHandle bindTo(Object x) > > Do we need something like: > > public MethodHandle bindToValue (__Value v) > > ? > > Such a bifurcation is somewhat awkward. Yep - it does look odd. The current working theory is that BMH should work (but will add boxing via asType adaptation) - so, in terms of capabilities, we should be there already. When the time comes, I think we should look at some of the complex combinators (I'm looking at you for loop :-)) and see whether intermediate boxing causes excessive penalty there. Maurizio > > Paul. > >> Maurizio >> >>> Paul. >>> >>> >>>> Adding q-type support in LFs is not straightforward, and we have played with a number of approaches. The big issue is that LFs are a mechanism to _share_ code between method handles (MHs) and they do so by means of 'erasure' - that is, two method handles taking String and Integer can (in principle) share the underlying LF (whose type is erased to Object - or L in the basic type lingo). >>>> >>>> With value types, erasure/sharing becomes an issue - on the one hand, we have to make sure that value types are not erased to the basic type L - which would then lead to nonsensical bytecode generation (such as areturn on a value operand). On the other hand there's a question of how much type information on value types we want to preserve during LF spinning. Two options are available: >>>> >>>> 1) value types do not get erased. That is, if a method type mentions one or more value types, such types are not erased in the underlying method form (MF) >>>> 2) a new basic type is added for value types (Q) and all value types 'erase' to that >>>> >>>> We started our experiments with (1) - while it is doable, there are two major pain points: >>>> >>>> * keeping sharp type information on value types inside LF effectively undoes one of the big advantages of LFs - that is, code sharing. A MH taking a QPoint and a MH taking a QPerson will _not_ be able to share the underlying LF. >>>> >>>> * this approach is basically at odds with the rest of the LF machinery, which is fundamentally basic-type based. This is particularly evident in the handling of intrinsics (see LambdaForm.createFormsFor) where special LF (such as 'identity' or 'zero') are cached in an array that is indexed by basic type. If we followed this approach we would split the implementation in two: parts for which caching can be enabled, and parts for which caching is not possible. >>>> >>>> For these reasons, we moved on to consider (2). The most problematic aspect of (2) is to find a common type to which all values can be safely 'erased' to. Turns out that hotspot already has this type - that's what java.lang.__Value is used for. So, we can indeed define a new basic type for Q, and use the j.l.Class of j.l.Value as its standard representation (while Object.class is still used for the boxed representation). >>>> >>>> All the rest is can be regarded as implementation details - that is, we need to make sure that Q-types are erased accordingly when going to method types to MF - and we also need to make sure that LF with values in them generate the correct bytecode. This was a major implementation challenge, as the current InvokeBytecodeGenerator is written in terms of ASM which doesn't (yet) have support for value opcodes. To workaround the issue, I've written an alternate InvokeBytecodeGenerator - called LambdaFormBuilder which is specifically used to spin bytecode for LF containing values. This builder is based on the bytecode API already bundled with the valhalla repo. >>>> >>>> Now, to the practical bits :-) >>>> >>>> There are a bunch of flags I've added to enable the new support; the first and most important is: >>>> >>>> -Dvalhalla.enableValueLambdaForms=true >>>> >>>> which allows value types to survive MethodType->MethodForm conversion, and enables the alternate LambdaFormBuilder class for spinning bytecode. >>>> >>>> There's also a second flag: >>>> >>>> -Dvalhalla.enablePoolPatches=true >>>> >>>> Which can be used to allow constant pool patching in the MethodHandleBuilder machinery - this should bring the generated code for LambdaFormBuilder closer to what InvokeBytecodeGenerator was emitting. But it can be mostly regarded as an optional optimization. >>>> >>>> Finally, more work needs to be done in this area; first, this support only works if JIT is disabled (e.g. -Xint is used). Some work in this area is currently under way - see: >>>> >>>> http://mail.openjdk.java.net/pipermail/valhalla-dev/2017-May/002464.html >>>> >>>> Secondly, bound method handle are _not_ supported. It seems like adding support for Q-types here would require some major surgery to the underlying machinery (most of the signatures for BMH are expressed in terms of Object[] anyway - see insertArguments). >>>> >>>> >>>> I would like to thank Vladimir Ivanov - this work would not have been possible w/o his many thoughtful insights. I'd also like to thank Roland Westrelin for 'alpha-testing' this patch, a thankless job which led to many bug fixes. >>>> >>>> Maurizio From paul.sandoz at oracle.com Fri Jun 2 17:50:22 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 2 Jun 2017 10:50:22 -0700 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <901fb642-aaf8-1ab6-c5f6-09fee5ea8fcf@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <901fb642-aaf8-1ab6-c5f6-09fee5ea8fcf@oracle.com> Message-ID: <64094C49-FDF2-4A19-BB6C-5494A2638CF4@oracle.com> > On 2 Jun 2017, at 10:27, Maurizio Cimadamore wrote: >> >>> But the other flip of the coin is to handle APIs - if you have a method handle that takes a Q-type, how do you 'bind' its argument? The APIs we have today are boxy. Some of these APIs are used internally by some of the BMH classes, so you could hit them through combinators too. >>> >> Yeah: >> >> public MethodHandle bindTo(Object x) >> >> Do we need something like: >> >> public MethodHandle bindToValue (__Value v) >> >> ? >> >> Such a bifurcation is somewhat awkward. > Yep - it does look odd. > > The current working theory is that BMH should work (but will add boxing via asType adaptation) - so, in terms of capabilities, we should be there already. > > When the time comes, I think we should look at some of the complex combinators (I'm looking at you for loop :-)) and see whether intermediate boxing causes excessive penalty there. > A start would be to add a simple loop test traversing over an array of Point reducing to one resulting Point. I can add something to the MVTTest, and perhaps refactor into more clearly separated tests of functionality. Paul. From maurizio.cimadamore at oracle.com Fri Jun 2 22:54:59 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 2 Jun 2017 23:54:59 +0100 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <64094C49-FDF2-4A19-BB6C-5494A2638CF4@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <901fb642-aaf8-1ab6-c5f6-09fee5ea8fcf@oracle.com> <64094C49-FDF2-4A19-BB6C-5494A2638CF4@oracle.com> Message-ID: <35b480a1-e485-7c15-9988-26e10e43447e@oracle.com> On 02/06/17 18:50, Paul Sandoz wrote: >> On 2 Jun 2017, at 10:27, Maurizio Cimadamore wrote: >>>> But the other flip of the coin is to handle APIs - if you have a method handle that takes a Q-type, how do you 'bind' its argument? The APIs we have today are boxy. Some of these APIs are used internally by some of the BMH classes, so you could hit them through combinators too. >>>> >>> Yeah: >>> >>> public MethodHandle bindTo(Object x) >>> >>> Do we need something like: >>> >>> public MethodHandle bindToValue (__Value v) >>> >>> ? >>> >>> Such a bifurcation is somewhat awkward. >> Yep - it does look odd. >> >> The current working theory is that BMH should work (but will add boxing via asType adaptation) - so, in terms of capabilities, we should be there already. >> >> When the time comes, I think we should look at some of the complex combinators (I'm looking at you for loop :-)) and see whether intermediate boxing causes excessive penalty there. >> > A start would be to add a simple loop test traversing over an array of Point reducing to one resulting Point. I can add something to the MVTTest, and perhaps refactor into more clearly separated tests of functionality. That'd be great - thanks! MVTTest is an hacky smoke test I've written to validate all the features of ValueType MHs. As such is by no means complete - it'd be great to have more stuff added to it, or to break it up by functionality as you proposed. Maurizio > > Paul. From forax at univ-mlv.fr Sat Jun 3 11:51:02 2017 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 3 Jun 2017 13:51:02 +0200 (CEST) Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> Message-ID: <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> Hi Paul, Hi Maurizio, bindTo() or insertArguments use the corresponding types from the method type to unbox the argument if necessary, so actually bindTo(3) will insert 3 and not the boxed Integer if the corresponding type is an int. The same way, a boxed value type can be unboxed if the corresponding type is a Q-type, so there is no need of a bindTo(__Value). In term of performance, this is not an issue because neither bindTo() nor insertArguments() should be called on a fast path. regards, R?mi ----- Mail original ----- > De: "Paul Sandoz" > ?: "Maurizio Cimadamore" > Cc: valhalla-dev at openjdk.java.net > Envoy?: Vendredi 2 Juin 2017 19:06:16 > Objet: Re: [mvt] RFR - add support for q-types in lambda forms >> On 1 Jun 2017, at 17:09, Maurizio Cimadamore >> wrote: >>> >>> For BMHs i am guessing we would require some expansion to include Q in the set >>> of support basic types e.g. Species_Q and appropriate modifications to the code >>> generation like you did for LamdaForm? >> I think one problem is to fix BMH/Species_Q and the classes it heavily relies on >> (LambdaFormEditor) to support Q-types. > > Ok. > > >> But the other flip of the coin is to handle APIs - if you have a method handle >> that takes a Q-type, how do you 'bind' its argument? The APIs we have today are >> boxy. Some of these APIs are used internally by some of the BMH classes, so you >> could hit them through combinators too. >> > > Yeah: > > public MethodHandle bindTo(Object x) > > Do we need something like: > > public MethodHandle bindToValue (__Value v) > > ? > > Such a bifurcation is somewhat awkward. > > Paul. > >> Maurizio >> >>> >>> Paul. >>> >>> >>>> Adding q-type support in LFs is not straightforward, and we have played with a >>>> number of approaches. The big issue is that LFs are a mechanism to _share_ code >>>> between method handles (MHs) and they do so by means of 'erasure' - that is, >>>> two method handles taking String and Integer can (in principle) share the >>>> underlying LF (whose type is erased to Object - or L in the basic type lingo). >>>> >>>> With value types, erasure/sharing becomes an issue - on the one hand, we have to >>>> make sure that value types are not erased to the basic type L - which would >>>> then lead to nonsensical bytecode generation (such as areturn on a value >>>> operand). On the other hand there's a question of how much type information on >>>> value types we want to preserve during LF spinning. Two options are available: >>>> >>>> 1) value types do not get erased. That is, if a method type mentions one or more >>>> value types, such types are not erased in the underlying method form (MF) >>>> 2) a new basic type is added for value types (Q) and all value types 'erase' to >>>> that >>>> >>>> We started our experiments with (1) - while it is doable, there are two major >>>> pain points: >>>> >>>> * keeping sharp type information on value types inside LF effectively undoes one >>>> of the big advantages of LFs - that is, code sharing. A MH taking a QPoint and >>>> a MH taking a QPerson will _not_ be able to share the underlying LF. >>>> >>>> * this approach is basically at odds with the rest of the LF machinery, which is >>>> fundamentally basic-type based. This is particularly evident in the handling of >>>> intrinsics (see LambdaForm.createFormsFor) where special LF (such as 'identity' >>>> or 'zero') are cached in an array that is indexed by basic type. If we followed >>>> this approach we would split the implementation in two: parts for which caching >>>> can be enabled, and parts for which caching is not possible. >>>> >>>> For these reasons, we moved on to consider (2). The most problematic aspect of >>>> (2) is to find a common type to which all values can be safely 'erased' to. >>>> Turns out that hotspot already has this type - that's what java.lang.__Value is >>>> used for. So, we can indeed define a new basic type for Q, and use the >>>> j.l.Class of j.l.Value as its standard representation (while Object.class is >>>> still used for the boxed representation). >>>> >>>> All the rest is can be regarded as implementation details - that is, we need to >>>> make sure that Q-types are erased accordingly when going to method types to MF >>>> - and we also need to make sure that LF with values in them generate the >>>> correct bytecode. This was a major implementation challenge, as the current >>>> InvokeBytecodeGenerator is written in terms of ASM which doesn't (yet) have >>>> support for value opcodes. To workaround the issue, I've written an alternate >>>> InvokeBytecodeGenerator - called LambdaFormBuilder which is specifically used >>>> to spin bytecode for LF containing values. This builder is based on the >>>> bytecode API already bundled with the valhalla repo. >>>> >>>> Now, to the practical bits :-) >>>> >>>> There are a bunch of flags I've added to enable the new support; the first and >>>> most important is: >>>> >>>> -Dvalhalla.enableValueLambdaForms=true >>>> >>>> which allows value types to survive MethodType->MethodForm conversion, and >>>> enables the alternate LambdaFormBuilder class for spinning bytecode. >>>> >>>> There's also a second flag: >>>> >>>> -Dvalhalla.enablePoolPatches=true >>>> >>>> Which can be used to allow constant pool patching in the MethodHandleBuilder >>>> machinery - this should bring the generated code for LambdaFormBuilder closer >>>> to what InvokeBytecodeGenerator was emitting. But it can be mostly regarded as >>>> an optional optimization. >>>> >>>> Finally, more work needs to be done in this area; first, this support only works >>>> if JIT is disabled (e.g. -Xint is used). Some work in this area is currently >>>> under way - see: >>>> >>>> http://mail.openjdk.java.net/pipermail/valhalla-dev/2017-May/002464.html >>>> >>>> Secondly, bound method handle are _not_ supported. It seems like adding support >>>> for Q-types here would require some major surgery to the underlying machinery >>>> (most of the signatures for BMH are expressed in terms of Object[] anyway - see >>>> insertArguments). >>>> >>>> >>>> I would like to thank Vladimir Ivanov - this work would not have been possible >>>> w/o his many thoughtful insights. I'd also like to thank Roland Westrelin for >>>> 'alpha-testing' this patch, a thankless job which led to many bug fixes. >>>> >>>> Maurizio From maurizio.cimadamore at oracle.com Sat Jun 3 13:56:58 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Sat, 3 Jun 2017 14:56:58 +0100 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> Message-ID: On 03/06/17 12:51, Remi Forax wrote: > Hi Paul, Hi Maurizio, > bindTo() or insertArguments use the corresponding types from the method type to unbox the argument if necessary, > so actually bindTo(3) will insert 3 and not the boxed Integer if the corresponding type is an int. > > The same way, a boxed value type can be unboxed if the corresponding type is a Q-type, > so there is no need of a bindTo(__Value). > > In term of performance, this is not an issue because neither bindTo() nor insertArguments() should be called on a fast path. Yeah - thanks for the clarification - this corresponds to my understanding of the model - that is, with BMH, boxing happens 'at the boundaries', when you set up the method handle chain - but I think that in order to get there you need at least to teach BMH about value types (that is, the Species_XYZ classes should have methods to construct bound versions with value types), otherwise the chain will just get boxed to Object internally. Maurizio > > regards, > R?mi > > ----- Mail original ----- >> De: "Paul Sandoz" >> ?: "Maurizio Cimadamore" >> Cc: valhalla-dev at openjdk.java.net >> Envoy?: Vendredi 2 Juin 2017 19:06:16 >> Objet: Re: [mvt] RFR - add support for q-types in lambda forms >>> On 1 Jun 2017, at 17:09, Maurizio Cimadamore >>> wrote: >>>> For BMHs i am guessing we would require some expansion to include Q in the set >>>> of support basic types e.g. Species_Q and appropriate modifications to the code >>>> generation like you did for LamdaForm? >>> I think one problem is to fix BMH/Species_Q and the classes it heavily relies on >>> (LambdaFormEditor) to support Q-types. >> Ok. >> >> >>> But the other flip of the coin is to handle APIs - if you have a method handle >>> that takes a Q-type, how do you 'bind' its argument? The APIs we have today are >>> boxy. Some of these APIs are used internally by some of the BMH classes, so you >>> could hit them through combinators too. >>> >> Yeah: >> >> public MethodHandle bindTo(Object x) >> >> Do we need something like: >> >> public MethodHandle bindToValue (__Value v) >> >> ? >> >> Such a bifurcation is somewhat awkward. >> >> Paul. >> >>> Maurizio >>> >>>> Paul. >>>> >>>> >>>>> Adding q-type support in LFs is not straightforward, and we have played with a >>>>> number of approaches. The big issue is that LFs are a mechanism to _share_ code >>>>> between method handles (MHs) and they do so by means of 'erasure' - that is, >>>>> two method handles taking String and Integer can (in principle) share the >>>>> underlying LF (whose type is erased to Object - or L in the basic type lingo). >>>>> >>>>> With value types, erasure/sharing becomes an issue - on the one hand, we have to >>>>> make sure that value types are not erased to the basic type L - which would >>>>> then lead to nonsensical bytecode generation (such as areturn on a value >>>>> operand). On the other hand there's a question of how much type information on >>>>> value types we want to preserve during LF spinning. Two options are available: >>>>> >>>>> 1) value types do not get erased. That is, if a method type mentions one or more >>>>> value types, such types are not erased in the underlying method form (MF) >>>>> 2) a new basic type is added for value types (Q) and all value types 'erase' to >>>>> that >>>>> >>>>> We started our experiments with (1) - while it is doable, there are two major >>>>> pain points: >>>>> >>>>> * keeping sharp type information on value types inside LF effectively undoes one >>>>> of the big advantages of LFs - that is, code sharing. A MH taking a QPoint and >>>>> a MH taking a QPerson will _not_ be able to share the underlying LF. >>>>> >>>>> * this approach is basically at odds with the rest of the LF machinery, which is >>>>> fundamentally basic-type based. This is particularly evident in the handling of >>>>> intrinsics (see LambdaForm.createFormsFor) where special LF (such as 'identity' >>>>> or 'zero') are cached in an array that is indexed by basic type. If we followed >>>>> this approach we would split the implementation in two: parts for which caching >>>>> can be enabled, and parts for which caching is not possible. >>>>> >>>>> For these reasons, we moved on to consider (2). The most problematic aspect of >>>>> (2) is to find a common type to which all values can be safely 'erased' to. >>>>> Turns out that hotspot already has this type - that's what java.lang.__Value is >>>>> used for. So, we can indeed define a new basic type for Q, and use the >>>>> j.l.Class of j.l.Value as its standard representation (while Object.class is >>>>> still used for the boxed representation). >>>>> >>>>> All the rest is can be regarded as implementation details - that is, we need to >>>>> make sure that Q-types are erased accordingly when going to method types to MF >>>>> - and we also need to make sure that LF with values in them generate the >>>>> correct bytecode. This was a major implementation challenge, as the current >>>>> InvokeBytecodeGenerator is written in terms of ASM which doesn't (yet) have >>>>> support for value opcodes. To workaround the issue, I've written an alternate >>>>> InvokeBytecodeGenerator - called LambdaFormBuilder which is specifically used >>>>> to spin bytecode for LF containing values. This builder is based on the >>>>> bytecode API already bundled with the valhalla repo. >>>>> >>>>> Now, to the practical bits :-) >>>>> >>>>> There are a bunch of flags I've added to enable the new support; the first and >>>>> most important is: >>>>> >>>>> -Dvalhalla.enableValueLambdaForms=true >>>>> >>>>> which allows value types to survive MethodType->MethodForm conversion, and >>>>> enables the alternate LambdaFormBuilder class for spinning bytecode. >>>>> >>>>> There's also a second flag: >>>>> >>>>> -Dvalhalla.enablePoolPatches=true >>>>> >>>>> Which can be used to allow constant pool patching in the MethodHandleBuilder >>>>> machinery - this should bring the generated code for LambdaFormBuilder closer >>>>> to what InvokeBytecodeGenerator was emitting. But it can be mostly regarded as >>>>> an optional optimization. >>>>> >>>>> Finally, more work needs to be done in this area; first, this support only works >>>>> if JIT is disabled (e.g. -Xint is used). Some work in this area is currently >>>>> under way - see: >>>>> >>>>> http://mail.openjdk.java.net/pipermail/valhalla-dev/2017-May/002464.html >>>>> >>>>> Secondly, bound method handle are _not_ supported. It seems like adding support >>>>> for Q-types here would require some major surgery to the underlying machinery >>>>> (most of the signatures for BMH are expressed in terms of Object[] anyway - see >>>>> insertArguments). >>>>> >>>>> >>>>> I would like to thank Vladimir Ivanov - this work would not have been possible >>>>> w/o his many thoughtful insights. I'd also like to thank Roland Westrelin for >>>>> 'alpha-testing' this patch, a thankless job which led to many bug fixes. >>>>> >>>>> Maurizio From david.simms at oracle.com Mon Jun 5 13:28:50 2017 From: david.simms at oracle.com (david.simms at oracle.com) Date: Mon, 05 Jun 2017 13:28:50 +0000 Subject: hg: valhalla/valhalla/hotspot: 2 new changesets Message-ID: <201706051328.v55DSpmV014378@aojmv0008.oracle.com> Changeset: 5ab79342fda2 Author: dsimms Date: 2017-06-05 15:24 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/5ab79342fda2 Fix missing register functions ! src/share/vm/prims/whitebox.cpp Changeset: ed097584c364 Author: dsimms Date: 2017-06-05 15:26 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/ed097584c364 Fix vwithfield assert with NULL arg ! src/share/vm/interpreter/interpreterRuntime.cpp From Paul.Sandoz at oracle.com Mon Jun 5 17:46:28 2017 From: Paul.Sandoz at oracle.com (Paul Sandoz) Date: Mon, 5 Jun 2017 10:46:28 -0700 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> Message-ID: <762C0F37-9AD1-45C9-B6BD-E963192FDDB8@oracle.com> Hi Remi, Yes thanks for clarifying, which simplifies things API-wise and makes sense in hindsight when considering just primitives. I am still getting to grips with this Q-type stuff, excuse my ignorance. The top value wrapper type (currently __Value) is sort of a box or carrier, but one without identity with immutable contents and the VM can single them out for optimisation. Correct? Paul. > On 3 Jun 2017, at 06:56, Maurizio Cimadamore wrote: > > > > On 03/06/17 12:51, Remi Forax wrote: >> Hi Paul, Hi Maurizio, >> bindTo() or insertArguments use the corresponding types from the method type to unbox the argument if necessary, >> so actually bindTo(3) will insert 3 and not the boxed Integer if the corresponding type is an int. >> >> The same way, a boxed value type can be unboxed if the corresponding type is a Q-type, >> so there is no need of a bindTo(__Value). >> >> In term of performance, this is not an issue because neither bindTo() nor insertArguments() should be called on a fast path. > Yeah - thanks for the clarification - this corresponds to my understanding of the model - that is, with BMH, boxing happens 'at the boundaries', when you set up the method handle chain - but I think that in order to get there you need at least to teach BMH about value types (that is, the Species_XYZ classes should have methods to construct bound versions with value types), otherwise the chain will just get boxed to Object internally. > > Maurizio >> >> regards, >> R?mi >> From karen.kinnear at oracle.com Mon Jun 5 17:56:44 2017 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Mon, 5 Jun 2017 13:56:44 -0400 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <762C0F37-9AD1-45C9-B6BD-E963192FDDB8@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> <762C0F37-9AD1-45C9-B6BD-E963192FDDB8@oracle.com> Message-ID: <01650095-A8A0-4AC0-9782-5EEBDC8001F5@oracle.com> The top value wrapper type today is sort of a marker type - i.e. you can not instantiate one, and in MVT you can currently use it in either a method signature or for vreturn. If you have other required uses - please let us know - we are working on how much we need to expose this in the JVMS draft. thanks, Karen > On Jun 5, 2017, at 1:46 PM, Paul Sandoz wrote: > > Hi Remi, > > Yes thanks for clarifying, which simplifies things API-wise and makes sense in hindsight when considering just primitives. > > I am still getting to grips with this Q-type stuff, excuse my ignorance. The top value wrapper type (currently __Value) is sort of a box or carrier, but one without identity with immutable contents and the VM can single them out for optimisation. Correct? > > Paul. > >> On 3 Jun 2017, at 06:56, Maurizio Cimadamore wrote: >> >> >> >> On 03/06/17 12:51, Remi Forax wrote: >>> Hi Paul, Hi Maurizio, >>> bindTo() or insertArguments use the corresponding types from the method type to unbox the argument if necessary, >>> so actually bindTo(3) will insert 3 and not the boxed Integer if the corresponding type is an int. >>> >>> The same way, a boxed value type can be unboxed if the corresponding type is a Q-type, >>> so there is no need of a bindTo(__Value). >>> >>> In term of performance, this is not an issue because neither bindTo() nor insertArguments() should be called on a fast path. >> Yeah - thanks for the clarification - this corresponds to my understanding of the model - that is, with BMH, boxing happens 'at the boundaries', when you set up the method handle chain - but I think that in order to get there you need at least to teach BMH about value types (that is, the Species_XYZ classes should have methods to construct bound versions with value types), otherwise the chain will just get boxed to Object internally. >> >> Maurizio >>> >>> regards, >>> R?mi >>> From paul.sandoz at oracle.com Mon Jun 5 18:20:21 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 5 Jun 2017 11:20:21 -0700 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <01650095-A8A0-4AC0-9782-5EEBDC8001F5@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> <762C0F37-9AD1-45C9-B6BD-E963192FDDB8@oracle.com> <01650095-A8A0-4AC0-9782-5EEBDC8001F5@oracle.com> Message-ID: One thing that concerns me about BMHs and Species is the possible combinatorial explosion if we have to create specific Species classes to hold values. At the moment the method handle internals operate on five basic types (L, I, J, F and D). What should the type of a Species field that holds a value augment which: 1) avoids boxing to Object; and 2) avoids a possible combinatorial explosion. ? Is there an intermediate carrier type we can use has less baggage than Object? Paul. > On 5 Jun 2017, at 10:56, Karen Kinnear wrote: > > The top value wrapper type today is sort of a marker type - i.e. you can not instantiate one, and in MVT > you can currently use it in either a method signature or for vreturn. > > If you have other required uses - please let us know - we are working on how much we need to expose this in the JVMS draft. > > thanks, > Karen > >> On Jun 5, 2017, at 1:46 PM, Paul Sandoz wrote: >> >> Hi Remi, >> >> Yes thanks for clarifying, which simplifies things API-wise and makes sense in hindsight when considering just primitives. >> >> I am still getting to grips with this Q-type stuff, excuse my ignorance. The top value wrapper type (currently __Value) is sort of a box or carrier, but one without identity with immutable contents and the VM can single them out for optimisation. Correct? >> >> Paul. >> >>> On 3 Jun 2017, at 06:56, Maurizio Cimadamore wrote: >>> >>> >>> >>> On 03/06/17 12:51, Remi Forax wrote: >>>> Hi Paul, Hi Maurizio, >>>> bindTo() or insertArguments use the corresponding types from the method type to unbox the argument if necessary, >>>> so actually bindTo(3) will insert 3 and not the boxed Integer if the corresponding type is an int. >>>> >>>> The same way, a boxed value type can be unboxed if the corresponding type is a Q-type, >>>> so there is no need of a bindTo(__Value). >>>> >>>> In term of performance, this is not an issue because neither bindTo() nor insertArguments() should be called on a fast path. >>> Yeah - thanks for the clarification - this corresponds to my understanding of the model - that is, with BMH, boxing happens 'at the boundaries', when you set up the method handle chain - but I think that in order to get there you need at least to teach BMH about value types (that is, the Species_XYZ classes should have methods to construct bound versions with value types), otherwise the chain will just get boxed to Object internally. >>> >>> Maurizio >>>> >>>> regards, >>>> R?mi >>>> > From forax at univ-mlv.fr Mon Jun 5 18:44:11 2017 From: forax at univ-mlv.fr (Remi Forax) Date: Mon, 5 Jun 2017 20:44:11 +0200 (CEST) Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> <762C0F37-9AD1-45C9-B6BD-E963192FDDB8@oracle.com> <01650095-A8A0-4AC0-9782-5EEBDC8001F5@oracle.com> Message-ID: <800472621.220481.1496688251225.JavaMail.zimbra@u-pem.fr> Hi Paul, John will say it better than me but the plan as far as i've understood is to just add a new Q basic type, represented by __Value in the signature as Karen said. R?mi ----- Mail original ----- > De: "Paul Sandoz" > ?: "Karen Kinnear" > Cc: valhalla-dev at openjdk.java.net > Envoy?: Lundi 5 Juin 2017 20:20:21 > Objet: Re: [mvt] RFR - add support for q-types in lambda forms > One thing that concerns me about BMHs and Species is the possible combinatorial > explosion if we have to create specific Species classes to hold values. At the > moment the method handle internals operate on five basic types (L, I, J, F and > D). > > What should the type of a Species field that holds a value augment which: > > 1) avoids boxing to Object; and > > 2) avoids a possible combinatorial explosion. > > ? > > Is there an intermediate carrier type we can use has less baggage than Object? > > Paul. > >> On 5 Jun 2017, at 10:56, Karen Kinnear wrote: >> >> The top value wrapper type today is sort of a marker type - i.e. you can not >> instantiate one, and in MVT >> you can currently use it in either a method signature or for vreturn. >> >> If you have other required uses - please let us know - we are working on how >> much we need to expose this in the JVMS draft. >> >> thanks, >> Karen >> >>> On Jun 5, 2017, at 1:46 PM, Paul Sandoz wrote: >>> >>> Hi Remi, >>> >>> Yes thanks for clarifying, which simplifies things API-wise and makes sense in >>> hindsight when considering just primitives. >>> >>> I am still getting to grips with this Q-type stuff, excuse my ignorance. The top >>> value wrapper type (currently __Value) is sort of a box or carrier, but one >>> without identity with immutable contents and the VM can single them out for >>> optimisation. Correct? >>> >>> Paul. >>> >>>> On 3 Jun 2017, at 06:56, Maurizio Cimadamore >>>> wrote: >>>> >>>> >>>> >>>> On 03/06/17 12:51, Remi Forax wrote: >>>>> Hi Paul, Hi Maurizio, >>>>> bindTo() or insertArguments use the corresponding types from the method type to >>>>> unbox the argument if necessary, >>>>> so actually bindTo(3) will insert 3 and not the boxed Integer if the >>>>> corresponding type is an int. >>>>> >>>>> The same way, a boxed value type can be unboxed if the corresponding type is a >>>>> Q-type, >>>>> so there is no need of a bindTo(__Value). >>>>> >>>>> In term of performance, this is not an issue because neither bindTo() nor >>>>> insertArguments() should be called on a fast path. >>>> Yeah - thanks for the clarification - this corresponds to my understanding of >>>> the model - that is, with BMH, boxing happens 'at the boundaries', when you set >>>> up the method handle chain - but I think that in order to get there you need at >>>> least to teach BMH about value types (that is, the Species_XYZ classes should >>>> have methods to construct bound versions with value types), otherwise the chain >>>> will just get boxed to Object internally. >>>> >>>> Maurizio >>>>> >>>>> regards, >>>>> R?mi >>>>> From maurizio.cimadamore at oracle.com Mon Jun 5 20:50:50 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 5 Jun 2017 21:50:50 +0100 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <800472621.220481.1496688251225.JavaMail.zimbra@u-pem.fr> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> <762C0F37-9AD1-45C9-B6BD-E963192FDDB8@oracle.com> <01650095-A8A0-4AC0-9782-5EEBDC8001F5@oracle.com> <800472621.220481.1496688251225.JavaMail.zimbra@u-pem.fr> Message-ID: On 05/06/17 19:44, Remi Forax wrote: > Hi Paul, > John will say it better than me but the plan as far as i've understood is to just add a new Q basic type, > represented by __Value in the signature as Karen said. Yep - that's what the lambda form patch I've sent does - it adds a new basic type and InvokeBytecodeGenerator has been expanded to handle the new basic type Q in LF signatures. Species classes should have an additional set of methods for binding to Q arguments. But I think these need to be spun in the bytecode, since I don't think if you name j.l.__Value in a method signature you'll get what you want at the bytecode level. Maurizio > > R?mi > > ----- Mail original ----- >> De: "Paul Sandoz" >> ?: "Karen Kinnear" >> Cc: valhalla-dev at openjdk.java.net >> Envoy?: Lundi 5 Juin 2017 20:20:21 >> Objet: Re: [mvt] RFR - add support for q-types in lambda forms >> One thing that concerns me about BMHs and Species is the possible combinatorial >> explosion if we have to create specific Species classes to hold values. At the >> moment the method handle internals operate on five basic types (L, I, J, F and >> D). >> >> What should the type of a Species field that holds a value augment which: >> >> 1) avoids boxing to Object; and >> >> 2) avoids a possible combinatorial explosion. >> >> ? >> >> Is there an intermediate carrier type we can use has less baggage than Object? >> >> Paul. >> >>> On 5 Jun 2017, at 10:56, Karen Kinnear wrote: >>> >>> The top value wrapper type today is sort of a marker type - i.e. you can not >>> instantiate one, and in MVT >>> you can currently use it in either a method signature or for vreturn. >>> >>> If you have other required uses - please let us know - we are working on how >>> much we need to expose this in the JVMS draft. >>> >>> thanks, >>> Karen >>> >>>> On Jun 5, 2017, at 1:46 PM, Paul Sandoz wrote: >>>> >>>> Hi Remi, >>>> >>>> Yes thanks for clarifying, which simplifies things API-wise and makes sense in >>>> hindsight when considering just primitives. >>>> >>>> I am still getting to grips with this Q-type stuff, excuse my ignorance. The top >>>> value wrapper type (currently __Value) is sort of a box or carrier, but one >>>> without identity with immutable contents and the VM can single them out for >>>> optimisation. Correct? >>>> >>>> Paul. >>>> >>>>> On 3 Jun 2017, at 06:56, Maurizio Cimadamore >>>>> wrote: >>>>> >>>>> >>>>> >>>>> On 03/06/17 12:51, Remi Forax wrote: >>>>>> Hi Paul, Hi Maurizio, >>>>>> bindTo() or insertArguments use the corresponding types from the method type to >>>>>> unbox the argument if necessary, >>>>>> so actually bindTo(3) will insert 3 and not the boxed Integer if the >>>>>> corresponding type is an int. >>>>>> >>>>>> The same way, a boxed value type can be unboxed if the corresponding type is a >>>>>> Q-type, >>>>>> so there is no need of a bindTo(__Value). >>>>>> >>>>>> In term of performance, this is not an issue because neither bindTo() nor >>>>>> insertArguments() should be called on a fast path. >>>>> Yeah - thanks for the clarification - this corresponds to my understanding of >>>>> the model - that is, with BMH, boxing happens 'at the boundaries', when you set >>>>> up the method handle chain - but I think that in order to get there you need at >>>>> least to teach BMH about value types (that is, the Species_XYZ classes should >>>>> have methods to construct bound versions with value types), otherwise the chain >>>>> will just get boxed to Object internally. >>>>> >>>>> Maurizio >>>>>> regards, >>>>>> R?mi >>>>>> From paul.sandoz at oracle.com Mon Jun 5 22:18:33 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 5 Jun 2017 15:18:33 -0700 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> <762C0F37-9AD1-45C9-B6BD-E963192FDDB8@oracle.com> <01650095-A8A0-4AC0-9782-5EEBDC8001F5@oracle.com> <800472621.220481.1496688251225.JavaMail.zimbra@u-pem.fr> Message-ID: > On 5 Jun 2017, at 13:50, Maurizio Cimadamore wrote: > > > > On 05/06/17 19:44, Remi Forax wrote: >> Hi Paul, >> John will say it better than me but the plan as far as i've understood is to just add a new Q basic type, >> represented by __Value in the signature as Karen said. > Yep - that's what the lambda form patch I've sent does - it adds a new basic type and InvokeBytecodeGenerator has been expanded to handle the new basic type Q in LF signatures. > > Species classes should have an additional set of methods for binding to Q arguments. But I think these need to be spun in the bytecode, since I don't think if you name j.l.__Value in a method signature you'll get what you want at the bytecode level. > What should be the signature of the Species fields bound to one or more values? Paul. (Separately Species classes themselves seem good candidates to be value classes, which i think we could do since we can spin ?em up.) > Maurizio >> >> R?mi >> >> ----- Mail original ----- >>> De: "Paul Sandoz" >>> ?: "Karen Kinnear" >>> Cc: valhalla-dev at openjdk.java.net >>> Envoy?: Lundi 5 Juin 2017 20:20:21 >>> Objet: Re: [mvt] RFR - add support for q-types in lambda forms >>> One thing that concerns me about BMHs and Species is the possible combinatorial >>> explosion if we have to create specific Species classes to hold values. At the >>> moment the method handle internals operate on five basic types (L, I, J, F and >>> D). >>> >>> What should the type of a Species field that holds a value augment which: >>> >>> 1) avoids boxing to Object; and >>> >>> 2) avoids a possible combinatorial explosion. >>> >>> ? >>> >>> Is there an intermediate carrier type we can use has less baggage than Object? >>> >>> Paul. From maurizio.cimadamore at oracle.com Mon Jun 5 23:12:47 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 6 Jun 2017 00:12:47 +0100 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> <762C0F37-9AD1-45C9-B6BD-E963192FDDB8@oracle.com> <01650095-A8A0-4AC0-9782-5EEBDC8001F5@oracle.com> <800472621.220481.1496688251225.JavaMail.zimbra@u-pem.fr> Message-ID: <455a9771-0ec3-5769-5278-dedcab19b6df@oracle.com> On 05/06/17 23:18, Paul Sandoz wrote: >> On 5 Jun 2017, at 13:50, Maurizio Cimadamore wrote: >> >> >> >> On 05/06/17 19:44, Remi Forax wrote: >>> Hi Paul, >>> John will say it better than me but the plan as far as i've understood is to just add a new Q basic type, >>> represented by __Value in the signature as Karen said. >> Yep - that's what the lambda form patch I've sent does - it adds a new basic type and InvokeBytecodeGenerator has been expanded to handle the new basic type Q in LF signatures. >> >> Species classes should have an additional set of methods for binding to Q arguments. But I think these need to be spun in the bytecode, since I don't think if you name j.l.__Value in a method signature you'll get what you want at the bytecode level. >> > What should be the signature of the Species fields bound to one or more values? I think Qjava/lang/__Value That's what we use in the signature of generated code corresponding to value-bearing lambda forms. Maurizio > > Paul. > > (Separately Species classes themselves seem good candidates to be value classes, which i think we could do since we can spin ?em up.) > >> Maurizio >>> R?mi >>> >>> ----- Mail original ----- >>>> De: "Paul Sandoz" >>>> ?: "Karen Kinnear" >>>> Cc: valhalla-dev at openjdk.java.net >>>> Envoy?: Lundi 5 Juin 2017 20:20:21 >>>> Objet: Re: [mvt] RFR - add support for q-types in lambda forms >>>> One thing that concerns me about BMHs and Species is the possible combinatorial >>>> explosion if we have to create specific Species classes to hold values. At the >>>> moment the method handle internals operate on five basic types (L, I, J, F and >>>> D). >>>> >>>> What should the type of a Species field that holds a value augment which: >>>> >>>> 1) avoids boxing to Object; and >>>> >>>> 2) avoids a possible combinatorial explosion. >>>> >>>> ? >>>> >>>> Is there an intermediate carrier type we can use has less baggage than Object? >>>> >>>> Paul. From paul.sandoz at oracle.com Mon Jun 5 23:29:02 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 5 Jun 2017 16:29:02 -0700 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <455a9771-0ec3-5769-5278-dedcab19b6df@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <60469027.3768939.1496490662867.JavaMail.zimbra@u-pem.fr> <762C0F37-9AD1-45C9-B6BD-E963192FDDB8@oracle.com> <01650095-A8A0-4AC0-9782-5EEBDC8001F5@oracle.com> <800472621.220481.1496688251225.JavaMail.zimbra@u-pem.fr> <455a9771-0ec3-5769-5278-dedcab19b6df@oracle.com> Message-ID: <74BC527B-C788-4595-893C-8D5AA51B0C6A@oracle.com> > On 5 Jun 2017, at 16:12, Maurizio Cimadamore wrote: > > > > On 05/06/17 23:18, Paul Sandoz wrote: >>> On 5 Jun 2017, at 13:50, Maurizio Cimadamore wrote: >>> >>> >>> >>> On 05/06/17 19:44, Remi Forax wrote: >>>> Hi Paul, >>>> John will say it better than me but the plan as far as i've understood is to just add a new Q basic type, >>>> represented by __Value in the signature as Karen said. >>> Yep - that's what the lambda form patch I've sent does - it adds a new basic type and InvokeBytecodeGenerator has been expanded to handle the new basic type Q in LF signatures. >>> >>> Species classes should have an additional set of methods for binding to Q arguments. But I think these need to be spun in the bytecode, since I don't think if you name j.l.__Value in a method signature you'll get what you want at the bytecode level. >>> >> What should be the signature of the Species fields bound to one or more values? > I think > > Qjava/lang/__Value > > That's what we use in the signature of generated code corresponding to value-bearing lambda forms. > IIUC that?s for method sigs/vreturn, so it?s all stack based. From reading Karen?s recent response i gather that it would not be possible (at least currently) to express __Value within a field descriptor. I suppose i should just try it... Paul.. From maurizio.cimadamore at oracle.com Tue Jun 6 11:43:00 2017 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Tue, 06 Jun 2017 11:43:00 +0000 Subject: hg: valhalla/valhalla/hotspot: Add support for Q-types to lambda forms Message-ID: <201706061143.v56Bh0hS022979@aojmv0008.oracle.com> Changeset: 0767f26001f2 Author: mcimadamore Date: 2017-06-06 12:40 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/0767f26001f2 Add support for Q-types to lambda forms Note: support is optional, and can be enabled using the flag: -Dvalhalla.enableValueLambdaForms=true ! src/share/vm/prims/methodHandles.cpp From maurizio.cimadamore at oracle.com Tue Jun 6 11:44:02 2017 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Tue, 06 Jun 2017 11:44:02 +0000 Subject: hg: valhalla/valhalla/jdk: Add support for Q-types to lambda forms Message-ID: <201706061144.v56Bi3F6023370@aojmv0008.oracle.com> Changeset: 0cb6a562cbbf Author: mcimadamore Date: 2017-06-06 12:39 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/0cb6a562cbbf Add support for Q-types to lambda forms Note: support is optional, and can be enabled using the flag: -Dvalhalla.enableValueLambdaForms=true ! src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java ! src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java ! src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java ! src/java.base/share/classes/java/lang/invoke/LambdaForm.java + src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java ! src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java ! src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java ! src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java ! src/java.base/share/classes/jdk/experimental/value/ValueType.java ! test/valhalla/mvt/MVTTest.java From maurizio.cimadamore at oracle.com Tue Jun 6 11:42:57 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 6 Jun 2017 12:42:57 +0100 Subject: [mvt] RFR - add support for q-types in lambda forms In-Reply-To: <99AB4C63-C5CE-4F94-9F0E-C74AB42DD37A@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <8141c98b-18ec-1a3f-1b1f-c9352eda8781@oracle.com> <99AB4C63-C5CE-4F94-9F0E-C74AB42DD37A@oracle.com> Message-ID: Thanks, pushed Mairizio On 02/06/17 17:49, Paul Sandoz wrote: > Looks good to me, > Paul. > >> On 2 Jun 2017, at 07:44, Maurizio Cimadamore wrote: >> >> Here's a second revision of the jdk changes: >> >> http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_jdk_v2 >> >> * I've shared the initialization of the static flag used by both LambdaForm and MethodTypeForm in MethodHandleStatics. >> * I've removed tabs from MVTTest >> >> Thanks >> Maurizio From rwestrel at redhat.com Tue Jun 6 12:07:34 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Tue, 06 Jun 2017 14:07:34 +0200 Subject: Return value type fields in registers In-Reply-To: References: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> Message-ID: Hi Tobias, > I've executed some quick testing on JPRT on top of Maurizio's latest patch: > http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_hs/ > http://cr.openjdk.java.net/~mcimadamore/specialized_lforms_jdk/ The only failure I see is: # Internal Error (/home/roland/valhalla/hotspot/src/share/vm/opto/parse3.cpp:554), pid=28067, tid=28104 # guarantee(target_vcc_klass->derive_value_type() != NULL) failed: vbox: Target class must have a derived value type class linked with runtime.valhalla.valuetypes.VboxUnbox that's reproducible with and without my patch. With my patch and -Dvalhalla.enableValueLambdaForms=true, everything else seems to work fine. Roland. From rwestrel at redhat.com Tue Jun 6 13:01:18 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Tue, 06 Jun 2017 15:01:18 +0200 Subject: Return value type fields in registers In-Reply-To: References: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> Message-ID: > On Windows it still fails with > Caused by: java.lang.RuntimeException: assertEquals: expected 1309945560682 to equal -2494 > at jdk.test.lib.Asserts.fail(Asserts.java:594) > at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) > at jdk.test.lib.Asserts.assertEquals(Asserts.java:189) > at jdk.test.lib.Asserts.assertEQ(Asserts.java:166) > at compiler.valhalla.valuetypes.ValueTypeTestBench.test54_verifier(ValueTypeTestBench.java:1612) The root cause on windows could missing shadown space. Can you try the patch below? Roland. diff --git a/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -4984,7 +4984,7 @@ // the runtime calls read or update those registers. This needs to // be in sync with SharedRuntime::java_return_convention(). enum layout { - pad_off, pad_off_2, + pad_off = frame::arg_reg_save_area_bytes/BytesPerInt, pad_off_2, rax_off, rax_off_2, j_rarg5_off, j_rarg5_2, j_rarg4_off, j_rarg4_2, From tobias.hartmann at oracle.com Tue Jun 6 13:07:50 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Tue, 6 Jun 2017 15:07:50 +0200 Subject: Return value type fields in registers In-Reply-To: References: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> Message-ID: Hi Roland, On 06.06.2017 14:07, Roland Westrelin wrote: > with runtime.valhalla.valuetypes.VboxUnbox that's reproducible with and > without my patch. Okay, I have a look at this. > With my patch and > -Dvalhalla.enableValueLambdaForms=true, everything else seems to work > fine. Right but then you need to add this switch to the ValueTypeTestBench, right? Best regards, Tobias From tobias.hartmann at oracle.com Tue Jun 6 13:08:23 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Tue, 6 Jun 2017 15:08:23 +0200 Subject: Return value type fields in registers In-Reply-To: References: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> Message-ID: Hi Roland, On 06.06.2017 15:01, Roland Westrelin wrote: > The root cause on windows could missing shadown space. Can you try the > patch below? Sure, I'll give it a spin. Best regards, Tobias From tobias.hartmann at oracle.com Tue Jun 6 13:10:01 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Tue, 6 Jun 2017 15:10:01 +0200 Subject: replay fixes for value type reference fields In-Reply-To: References: Message-ID: <07eb6803-7409-1af0-5fed-e176901a83d1@oracle.com> Hi Roland, On 01.06.2017 17:21, Roland Westrelin wrote: > http://cr.openjdk.java.net/~roland/valhalla/replay-reffields/webrev.00/ > > This should fix compilation replay so it handles reference fields in > static value type fields. It also improves replay a bit: for object > fields, replay dumps the signature of the field which could differ from > the actual field type. An field declared as Object could even be an > array.. With that change replay dumps the actual field type. Looks good to me! Best regards, Tobias From rwestrel at redhat.com Tue Jun 6 13:11:51 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Tue, 06 Jun 2017 15:11:51 +0200 Subject: Return value type fields in registers In-Reply-To: References: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> Message-ID: >> With my patch and >> -Dvalhalla.enableValueLambdaForms=true, everything else seems to work >> fine. > > Right but then you need to add this switch to the ValueTypeTestBench, right? Or change the default to true? Running with -Dvalhalla.enableValueLambdaForms=true currently causes some assert failures. My patch fixes them so I don't see why we would need to keep it off. Roland. From tobias.hartmann at oracle.com Tue Jun 6 13:13:13 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Tue, 6 Jun 2017 15:13:13 +0200 Subject: Return value type fields in registers In-Reply-To: References: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> Message-ID: On 06.06.2017 15:11, Roland Westrelin wrote: > Or change the default to true? > > Running with -Dvalhalla.enableValueLambdaForms=true currently causes > some assert failures. My patch fixes them so I don't see why we would > need to keep it off. Yes, I'm fine with enabling it by default. Best regards, Tobias From maurizio.cimadamore at oracle.com Tue Jun 6 15:01:32 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 6 Jun 2017 16:01:32 +0100 Subject: [mvt] RFR: add access check to ValueType method handle generation Message-ID: <07bac2a7-92c7-30b3-a224-e4ec66181756@oracle.com> Hi, this patch addresses an issue that was recently discovered during some internal testing. The culprit is that no access check is performed when generating bytecode for ValueType.findGetter and ValueType.findWither and, as a result it is possible to get your hand on a method handle that refers to inaccessible fields - execution will then fail with a more obscure error message when the class containing the synthetic MH bytecode is loaded/executed. The solution is to add an explicit Lookup parameter to these routines, to make sure that access checking is always performed before returning the (possibly cached) method handle. Note that the accessCheck could in principle apply to substitutabilityTest and substitutabilityHashCode, but we have decided to let these two pass for now (by using a sufficiently privileged lookup object to load the MH code). Cheers Maurizio From maurizio.cimadamore at oracle.com Tue Jun 6 15:01:59 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 6 Jun 2017 16:01:59 +0100 Subject: [mvt] RFR: add access check to ValueType method handle generation In-Reply-To: <07bac2a7-92c7-30b3-a224-e4ec66181756@oracle.com> References: <07bac2a7-92c7-30b3-a224-e4ec66181756@oracle.com> Message-ID: <4ab067e6-a055-273e-3f93-ff5fda033f81@oracle.com> Whoops - here's the webrev link http://cr.openjdk.java.net/~mcimadamore/mvt_access_check/ Maurizio On 06/06/17 16:01, Maurizio Cimadamore wrote: > Hi, > this patch addresses an issue that was recently discovered during some > internal testing. The culprit is that no access check is performed > when generating bytecode for ValueType.findGetter and > ValueType.findWither and, as a result it is possible to get your hand > on a method handle that refers to inaccessible fields - execution will > then fail with a more obscure error message when the class containing > the synthetic MH bytecode is loaded/executed. > > The solution is to add an explicit Lookup parameter to these routines, > to make sure that access checking is always performed before returning > the (possibly cached) method handle. > > Note that the accessCheck could in principle apply to > substitutabilityTest and substitutabilityHashCode, but we have decided > to let these two pass for now (by using a sufficiently privileged > lookup object to load the MH code). > > Cheers > Maurizio > From paul.sandoz at oracle.com Tue Jun 6 16:35:38 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 6 Jun 2017 09:35:38 -0700 Subject: [mvt] RFR: add access check to ValueType method handle generation In-Reply-To: <4ab067e6-a055-273e-3f93-ff5fda033f81@oracle.com> References: <07bac2a7-92c7-30b3-a224-e4ec66181756@oracle.com> <4ab067e6-a055-273e-3f93-ff5fda033f81@oracle.com> Message-ID: <2769F437-BE6A-4542-85C7-E19ADFBAA5C2@oracle.com> > On 6 Jun 2017, at 08:01, Maurizio Cimadamore wrote: > > Whoops - here's the webrev link > > http://cr.openjdk.java.net/~mcimadamore/mvt_access_check/ > +1 Paul. > Maurizio > > > On 06/06/17 16:01, Maurizio Cimadamore wrote: >> Hi, >> this patch addresses an issue that was recently discovered during some internal testing. The culprit is that no access check is performed when generating bytecode for ValueType.findGetter and ValueType.findWither and, as a result it is possible to get your hand on a method handle that refers to inaccessible fields - execution will then fail with a more obscure error message when the class containing the synthetic MH bytecode is loaded/executed. >> >> The solution is to add an explicit Lookup parameter to these routines, to make sure that access checking is always performed before returning the (possibly cached) method handle. >> >> Note that the accessCheck could in principle apply to substitutabilityTest and substitutabilityHashCode, but we have decided to let these two pass for now (by using a sufficiently privileged lookup object to load the MH code). >> >> Cheers >> Maurizio >> > From maurizio.cimadamore at oracle.com Tue Jun 6 16:47:06 2017 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Tue, 06 Jun 2017 16:47:06 +0000 Subject: hg: valhalla/valhalla/jdk: Add missing access checks to ValueType.findGetter/findWither Message-ID: <201706061647.v56Gl6vY000937@aojmv0008.oracle.com> Changeset: b02be6a99c5a Author: mcimadamore Date: 2017-06-06 17:45 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/b02be6a99c5a Add missing access checks to ValueType.findGetter/findWither ! src/java.base/share/classes/java/lang/invoke/MethodHandles.java ! src/java.base/share/classes/jdk/experimental/value/ValueType.java + test/valhalla/mvt/MVTAccessCheck.java ! test/valhalla/mvt/MVTTest.java + test/valhalla/mvt/PrivatePoint.java From maurizio.cimadamore at oracle.com Tue Jun 6 16:45:50 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 6 Jun 2017 17:45:50 +0100 Subject: [mvt] RFR: add access check to ValueType method handle generation In-Reply-To: <2769F437-BE6A-4542-85C7-E19ADFBAA5C2@oracle.com> References: <07bac2a7-92c7-30b3-a224-e4ec66181756@oracle.com> <4ab067e6-a055-273e-3f93-ff5fda033f81@oracle.com> <2769F437-BE6A-4542-85C7-E19ADFBAA5C2@oracle.com> Message-ID: Thanks - pushed. Maurizio On 06/06/17 17:35, Paul Sandoz wrote: >> On 6 Jun 2017, at 08:01, Maurizio Cimadamore wrote: >> >> Whoops - here's the webrev link >> >> http://cr.openjdk.java.net/~mcimadamore/mvt_access_check/ >> > +1 > > Paul. > >> Maurizio >> >> >> On 06/06/17 16:01, Maurizio Cimadamore wrote: >>> Hi, >>> this patch addresses an issue that was recently discovered during some internal testing. The culprit is that no access check is performed when generating bytecode for ValueType.findGetter and ValueType.findWither and, as a result it is possible to get your hand on a method handle that refers to inaccessible fields - execution will then fail with a more obscure error message when the class containing the synthetic MH bytecode is loaded/executed. >>> >>> The solution is to add an explicit Lookup parameter to these routines, to make sure that access checking is always performed before returning the (possibly cached) method handle. >>> >>> Note that the accessCheck could in principle apply to substitutabilityTest and substitutabilityHashCode, but we have decided to let these two pass for now (by using a sufficiently privileged lookup object to load the MH code). >>> >>> Cheers >>> Maurizio >>> From paul.sandoz at oracle.com Wed Jun 7 04:22:25 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 6 Jun 2017 21:22:25 -0700 Subject: [mvt] RFR MVTTest refactor In-Reply-To: <35b480a1-e485-7c15-9988-26e10e43447e@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <901fb642-aaf8-1ab6-c5f6-09fee5ea8fcf@oracle.com> <64094C49-FDF2-4A19-BB6C-5494A2638CF4@oracle.com> <35b480a1-e485-7c15-9988-26e10e43447e@oracle.com> Message-ID: http://cr.openjdk.java.net/~psandoz/valhalla/mvt-test/webrev/test/valhalla/mvt/MVTTest.java.sdiff.html Also includes a test with a counted loop (although i have yet to look at how that behaves regarding LFs). Paul. > On 2 Jun 2017, at 15:54, Maurizio Cimadamore wrote: > > > > On 02/06/17 18:50, Paul Sandoz wrote: >>> On 2 Jun 2017, at 10:27, Maurizio Cimadamore wrote: >>>>> But the other flip of the coin is to handle APIs - if you have a method handle that takes a Q-type, how do you 'bind' its argument? The APIs we have today are boxy. Some of these APIs are used internally by some of the BMH classes, so you could hit them through combinators too. >>>>> >>>> Yeah: >>>> >>>> public MethodHandle bindTo(Object x) >>>> >>>> Do we need something like: >>>> >>>> public MethodHandle bindToValue (__Value v) >>>> >>>> ? >>>> >>>> Such a bifurcation is somewhat awkward. >>> Yep - it does look odd. >>> >>> The current working theory is that BMH should work (but will add boxing via asType adaptation) - so, in terms of capabilities, we should be there already. >>> >>> When the time comes, I think we should look at some of the complex combinators (I'm looking at you for loop :-)) and see whether intermediate boxing causes excessive penalty there. >>> >> A start would be to add a simple loop test traversing over an array of Point reducing to one resulting Point. I can add something to the MVTTest, and perhaps refactor into more clearly separated tests of functionality. > That'd be great - thanks! MVTTest is an hacky smoke test I've written to validate all the features of ValueType MHs. As such is by no means complete - it'd be great to have more stuff added to it, or to break it up by functionality as you proposed. > > Maurizio > > >> >> Paul. > From maurizio.cimadamore at oracle.com Wed Jun 7 09:11:21 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Jun 2017 10:11:21 +0100 Subject: [mvt] RFR MVTTest refactor In-Reply-To: References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <901fb642-aaf8-1ab6-c5f6-09fee5ea8fcf@oracle.com> <64094C49-FDF2-4A19-BB6C-5494A2638CF4@oracle.com> <35b480a1-e485-7c15-9988-26e10e43447e@oracle.com> Message-ID: <3dd0ac56-2d59-7b4c-7bbc-7c30ad7461e2@oracle.com> This looks great! The very fact that the test works seems promising - of course there will be intermediate 'unwanted' boxing (which we'll want to get rid of), but it seems like the prototype can handle some degree of combinators well, which should enable some real world end to end testing. I think you should be a Valhalla committer - in case you have any issue please ping me and I'll push for you. Thanks again! Maurizio On 07/06/17 05:22, Paul Sandoz wrote: > http://cr.openjdk.java.net/~psandoz/valhalla/mvt-test/webrev/test/valhalla/mvt/MVTTest.java.sdiff.html > > > Also includes a test with a counted loop (although i have yet to look > at how that behaves regarding LFs). > > Paul. > >> On 2 Jun 2017, at 15:54, Maurizio Cimadamore >> > > wrote: >> >> >> >> On 02/06/17 18:50, Paul Sandoz wrote: >>>> On 2 Jun 2017, at 10:27, Maurizio Cimadamore >>>> >>> > wrote: >>>>>> But the other flip of the coin is to handle APIs - if you have a >>>>>> method handle that takes a Q-type, how do you 'bind' its >>>>>> argument? The APIs we have today are boxy. Some of these APIs are >>>>>> used internally by some of the BMH classes, so you could hit them >>>>>> through combinators too. >>>>>> >>>>> Yeah: >>>>> >>>>> public MethodHandle bindTo(Object x) >>>>> >>>>> Do we need something like: >>>>> >>>>> public MethodHandle bindToValue (__Value v) >>>>> >>>>> ? >>>>> >>>>> Such a bifurcation is somewhat awkward. >>>> Yep - it does look odd. >>>> >>>> The current working theory is that BMH should work (but will add >>>> boxing via asType adaptation) - so, in terms of capabilities, we >>>> should be there already. >>>> >>>> When the time comes, I think we should look at some of the complex >>>> combinators (I'm looking at you for loop :-)) and see whether >>>> intermediate boxing causes excessive penalty there. >>>> >>> A start would be to add a simple loop test traversing over an array >>> of Point reducing to one resulting Point. I can add something to the >>> MVTTest, and perhaps refactor into more clearly separated tests of >>> functionality. >> That'd be great - thanks! MVTTest is an hacky smoke test I've written >> to validate all the features of ValueType MHs. As such is by no means >> complete - it'd be great to have more stuff added to it, or to break >> it up by functionality as you proposed. >> >> Maurizio >> >> >>> >>> Paul. >> > From tobias.hartmann at oracle.com Wed Jun 7 12:00:13 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Wed, 7 Jun 2017 14:00:13 +0200 Subject: Return value type fields in registers In-Reply-To: References: <8bb37515-1fb2-6df4-0c06-e37264b1e51c@oracle.com> Message-ID: <7f76b75f-1128-9dd9-384f-24059b000c94@oracle.com> Hi Roland, I found some additional (build) problems. With below patch, no additional failures show up on JPRT. Also the Windows problem is gone. I'll look into the VboxUnbox failure next. I'm fine with pushing webrev.02 including below changes. Best regards, Tobias diff -r f453ec22aae0 src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Jun 07 12:41:45 2017 +0200 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Jun 07 13:27:47 2017 +0200 @@ -4984,7 +4984,7 @@ // the runtime calls read or update those registers. This needs to // be in sync with SharedRuntime::java_return_convention(). enum layout { - pad_off, pad_off_2, + pad_off = frame::arg_reg_save_area_bytes/BytesPerInt, pad_off_2, rax_off, rax_off_2, j_rarg5_off, j_rarg5_2, j_rarg4_off, j_rarg4_2, diff -r f453ec22aae0 src/share/vm/code/pcDesc.hpp --- a/src/share/vm/code/pcDesc.hpp Wed Jun 07 12:41:45 2017 +0200 +++ b/src/share/vm/code/pcDesc.hpp Wed Jun 07 13:27:47 2017 +0200 @@ -44,7 +44,7 @@ PCDESC_is_method_handle_invoke = 1 << 1, PCDESC_return_oop = 1 << 2, PCDESC_rethrow_exception = 1 << 3, - PCDESC_return_vt = 1 << 4, + PCDESC_return_vt = 1 << 4 }; int _flags; diff -r f453ec22aae0 src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Wed Jun 07 12:41:45 2017 +0200 +++ b/src/share/vm/opto/compile.cpp Wed Jun 07 13:27:47 2017 +0200 @@ -2696,9 +2696,9 @@ // call. Node* ret = call->proj_out(TypeFunc::Parms); assert(ret->bottom_type()->is_valuetypeptr()->klass() == env()->___Value_klass(), "unexpected return type from MH intrinsic"); - const TypeFunc* _tf = call->_tf; + const TypeFunc* tf = call->_tf; const TypeTuple* domain = OptoRuntime::store_value_type_fields_Type()->domain_cc(); - const TypeFunc* new_tf = TypeFunc::make(_tf->domain_sig(), _tf->domain_cc(), _tf->range_sig(), domain); + const TypeFunc* new_tf = TypeFunc::make(tf->domain_sig(), tf->domain_cc(), tf->range_sig(), domain); call->_tf = new_tf; CallProjections projs; diff -r f453ec22aae0 test/compiler/valhalla/valuetypes/ValueTypeTestBench.java --- a/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java Wed Jun 07 12:41:45 2017 +0200 +++ b/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java Wed Jun 07 13:27:47 2017 +0200 @@ -35,16 +35,16 @@ * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:+VerifyAdapterSharing * -XX:+EnableValhalla -XX:+EnableMVT -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:+ValueArrayFlatten * -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 -XX:+FullGCALotWithValueTypes - * compiler.valhalla.valuetypes.ValueTypeTestBench + * -Dvalhalla.enableValueLambdaForms=true compiler.valhalla.valuetypes.ValueTypeTestBench * @run main/othervm -Xbootclasspath/a:. -ea -noverify -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation * -XX:+EnableValhalla -XX:+EnableMVT -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:-ValueArrayFlatten - * compiler.valhalla.valuetypes.ValueTypeTestBench + * -Dvalhalla.enableValueLambdaForms=true compiler.valhalla.valuetypes.ValueTypeTestBench * @run main/othervm -Xbootclasspath/a:. -ea -noverify -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:+AlwaysIncrementalInline * -XX:+EnableValhalla -XX:+EnableMVT -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:+ValueArrayFlatten * -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 - * compiler.valhalla.valuetypes.ValueTypeTestBench + * -Dvalhalla.enableValueLambdaForms=true compiler.valhalla.valuetypes.ValueTypeTestBench */ package compiler.valhalla.valuetypes; From david.simms at oracle.com Wed Jun 7 13:12:14 2017 From: david.simms at oracle.com (david.simms at oracle.com) Date: Wed, 07 Jun 2017 13:12:14 +0000 Subject: hg: valhalla/valhalla: oopmap testing Message-ID: <201706071312.v57DCEOH001707@aojmv0008.oracle.com> Changeset: 69eb8d144599 Author: dsimms Date: 2017-06-07 15:10 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/rev/69eb8d144599 oopmap testing ! test/lib/sun/hotspot/WhiteBox.java From tobias.hartmann at oracle.com Wed Jun 7 13:48:30 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Wed, 7 Jun 2017 15:48:30 +0200 Subject: RFR: vbox/vunbox should throw ClassCastException if target type is invalid Message-ID: <66d005e9-551e-58d9-18fd-6fadf2215965@oracle.com> Hi, please review the following patch: http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.19/ The runtime/valhalla/valuetypes/VboxUnbox.java test currently fails with a guarantee during parsing because the target type of vbox/vunbox is invalid (see VboxUnbox::testIncorrectBoxing()t's 'String'). C2 should throw a ClassCastException in this case. Thanks, Tobias From paul.sandoz at oracle.com Wed Jun 7 16:43:10 2017 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Wed, 07 Jun 2017 16:43:10 +0000 Subject: hg: valhalla/valhalla/jdk: Refactor test into separate test methods and add a loop combinator Message-ID: <201706071643.v57GhAhK011339@aojmv0008.oracle.com> Changeset: 95829a1702e9 Author: psandoz Date: 2017-06-07 09:40 -0700 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/95829a1702e9 Refactor test into separate test methods and add a loop combinator test. ! test/valhalla/mvt/MVTTest.java From paul.sandoz at oracle.com Wed Jun 7 17:04:44 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 7 Jun 2017 10:04:44 -0700 Subject: [mvt] RFR MVTTest refactor In-Reply-To: <3dd0ac56-2d59-7b4c-7bbc-7c30ad7461e2@oracle.com> References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <901fb642-aaf8-1ab6-c5f6-09fee5ea8fcf@oracle.com> <64094C49-FDF2-4A19-BB6C-5494A2638CF4@oracle.com> <35b480a1-e485-7c15-9988-26e10e43447e@oracle.com> <3dd0ac56-2d59-7b4c-7bbc-7c30ad7461e2@oracle.com> Message-ID: > On 7 Jun 2017, at 02:11, Maurizio Cimadamore wrote: > > This looks great! The very fact that the test works seems promising - of course there will be intermediate 'unwanted' boxing (which we'll want to get rid of), but it seems like the prototype can handle some degree of combinators well, which should enable some real world end to end testing. > > Yes, i?ll add a few more test methods, unless i run into something tricky i?ll just push ?em without a webrev. > I think you should be a Valhalla committer - in case you have any issue please ping me and I'll push for you. > Thanks, i have access. Pushed. ? How can we tell if unwanted boxing is going on? is there a HotSpot XX flag we can use to trace the vbox/vunbox actions? As an experiment i removed the -Xint flag from the MVTTest and it passes, including if i up the loop iterations to 100000, which means C2 should be kicking in. ? I notice a difference between the declaration of a minimal value type in the JDK tests: @jvm.internal.value.DeriveValueType final class Point { And that in some VM tests: public __ByValue final class Point { How much should we depend on the more direct javac functionality for such tests? rather than going through the indirect MVT route for our tests? Paul. From maurizio.cimadamore at oracle.com Wed Jun 7 17:37:11 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Jun 2017 18:37:11 +0100 Subject: [mvt] RFR MVTTest refactor In-Reply-To: References: <92628a4e-9fd3-f852-7d44-509ca0b24950@oracle.com> <95E3367B-24C3-4E2F-8963-4E16893AA1EE@oracle.com> <2C657C01-2C5F-4EB5-9800-A54E96923082@oracle.com> <901fb642-aaf8-1ab6-c5f6-09fee5ea8fcf@oracle.com> <64094C49-FDF2-4A19-BB6C-5494A2638CF4@oracle.com> <35b480a1-e485-7c15-9988-26e10e43447e@oracle.com> <3dd0ac56-2d59-7b4c-7bbc-7c30ad7461e2@oracle.com> Message-ID: On 07/06/17 18:04, Paul Sandoz wrote: >> On 7 Jun 2017, at 02:11, Maurizio Cimadamore wrote: >> >> This looks great! The very fact that the test works seems promising - of course there will be intermediate 'unwanted' boxing (which we'll want to get rid of), but it seems like the prototype can handle some degree of combinators well, which should enable some real world end to end testing. >> >> > Yes, i?ll add a few more test methods, unless i run into something tricky i?ll just push ?em without a webrev. > > >> I think you should be a Valhalla committer - in case you have any issue please ping me and I'll push for you. >> > Thanks, i have access. Pushed. Thanks > > ? > > How can we tell if unwanted boxing is going on? is there a HotSpot XX flag we can use to trace the vbox/vunbox actions? Not aware of an hotspot flag, but you could easily put an assertion in the ValueType.box/unbox MH generators - to make sure you never hit them (or to dump info when you do) > > As an experiment i removed the -Xint flag from the MVTTest and it passes, including if i up the loop iterations to 100000, which means C2 should be kicking in. > > ? > > I notice a difference between the declaration of a minimal value type in the JDK tests: > > @jvm.internal.value.DeriveValueType > final class Point { > > And that in some VM tests: > > public __ByValue final class Point { > > How much should we depend on the more direct javac functionality for such tests? rather than going through the indirect MVT route for our tests? I think long term all tests should be either using bytecode spinning (e.g. MethodHandleBuilder) or MHs. But the value support in hotspot is shared between valhalla values and MVT, so there's some work to do to get there. Maurizio > > Paul. From frederic.parain at oracle.com Wed Jun 7 19:39:18 2017 From: frederic.parain at oracle.com (frederic.parain at oracle.com) Date: Wed, 07 Jun 2017 19:39:18 +0000 Subject: hg: valhalla/valhalla/hotspot: Fix and cleanup in vwithfield Message-ID: <201706071939.v57JdIJT016989@aojmv0008.oracle.com> Changeset: b03e14ea3e9b Author: fparain Date: 2017-06-07 15:38 -0400 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/b03e14ea3e9b Fix and cleanup in vwithfield ! src/share/vm/interpreter/interpreterRuntime.cpp From frederic.parain at oracle.com Wed Jun 7 19:41:58 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Wed, 7 Jun 2017 15:41:58 -0400 Subject: hg: valhalla/valhalla/hotspot: Fix and cleanup in vwithfield In-Reply-To: <201706071939.v57JdIJT016989@aojmv0008.oracle.com> References: <201706071939.v57JdIJT016989@aojmv0008.oracle.com> Message-ID: <00878C1F-A5DA-43CE-A859-E7B1C2323F0B@oracle.com> Fixing a bug in vwithfield leading to buggy stack management. Thanks to Mr Simms for having spotted and identify the issue. I took the opportunity to do a clean up of the vwithfield method, removing raw pointer arithmetic on the expression stack, using the frame API instead. Fred > On Jun 7, 2017, at 15:39, frederic.parain at oracle.com wrote: > > Changeset: b03e14ea3e9b > Author: fparain > Date: 2017-06-07 15:38 -0400 > URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/b03e14ea3e9b > > Fix and cleanup in vwithfield > > ! src/share/vm/interpreter/interpreterRuntime.cpp > From john.r.rose at oracle.com Wed Jun 7 20:17:22 2017 From: john.r.rose at oracle.com (John Rose) Date: Wed, 7 Jun 2017 13:17:22 -0700 Subject: FYI: What's in a CONSTANT_Class? Message-ID: http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2017-June/000256.html From karen.kinnear at oracle.com Wed Jun 7 21:04:35 2017 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Wed, 7 Jun 2017 17:04:35 -0400 Subject: hg: valhalla/valhalla/hotspot: Fix and cleanup in vwithfield In-Reply-To: <00878C1F-A5DA-43CE-A859-E7B1C2323F0B@oracle.com> References: <201706071939.v57JdIJT016989@aojmv0008.oracle.com> <00878C1F-A5DA-43CE-A859-E7B1C2323F0B@oracle.com> Message-ID: <04148716-2FC1-4AFC-A71B-C71B4621C833@oracle.com> Frederic, Looks good. Thank you for the cleanup. One question please - why do you add type2size(T_VALUETYPE) * stackElementSize when you return the size of the new value type result? thanks, Karen > On Jun 7, 2017, at 3:41 PM, Frederic Parain wrote: > > Fixing a bug in vwithfield leading to buggy stack management. > Thanks to Mr Simms for having spotted and identify the issue. > I took the opportunity to do a clean up of the vwithfield method, > removing raw pointer arithmetic on the expression stack, using > the frame API instead. > > Fred > > >> On Jun 7, 2017, at 15:39, frederic.parain at oracle.com wrote: >> >> Changeset: b03e14ea3e9b >> Author: fparain >> Date: 2017-06-07 15:38 -0400 >> URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/b03e14ea3e9b >> >> Fix and cleanup in vwithfield >> >> ! src/share/vm/interpreter/interpreterRuntime.cpp >> > From frederic.parain at oracle.com Wed Jun 7 21:16:36 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Wed, 7 Jun 2017 17:16:36 -0400 Subject: hg: valhalla/valhalla/hotspot: Fix and cleanup in vwithfield In-Reply-To: <04148716-2FC1-4AFC-A71B-C71B4621C833@oracle.com> References: <201706071939.v57JdIJT016989@aojmv0008.oracle.com> <00878C1F-A5DA-43CE-A859-E7B1C2323F0B@oracle.com> <04148716-2FC1-4AFC-A71B-C71B4621C833@oracle.com> Message-ID: Karen, The integer returned is not the size of the new value type, it?s a stack adjustment value. The vwithfield runtime entry returns a new value type in thread->vm_result and an integer which is used by the assembly code to adjust the stack pointer (the vwithfield bytecode must consume the new field value and the original value type passed on the stack before pushing the new value). We are doing this because we cannot manipulate the expression stack from the runtime and the assembly code doesn?t know the size of the new field value (one slot or two slot depending on the field type). The bug was that the stack adjustment returned was missing the size of the original value type passed on the stack, leading to a ?shift? of operands on the expression stack because the original value type was never popped. This issue caused some GC issues (because of the shift, there was a mismatch between the oopmap computed and the real location of references), and could eventually caused some stack overflow issues. Fred > On Jun 7, 2017, at 17:04, Karen Kinnear wrote: > > Frederic, > > Looks good. Thank you for the cleanup. > > One question please - why do you add type2size(T_VALUETYPE) * stackElementSize > when you return the size of the new value type result? > > thanks, > Karen > >> On Jun 7, 2017, at 3:41 PM, Frederic Parain wrote: >> >> Fixing a bug in vwithfield leading to buggy stack management. >> Thanks to Mr Simms for having spotted and identify the issue. >> I took the opportunity to do a clean up of the vwithfield method, >> removing raw pointer arithmetic on the expression stack, using >> the frame API instead. >> >> Fred >> >> >>> On Jun 7, 2017, at 15:39, frederic.parain at oracle.com wrote: >>> >>> Changeset: b03e14ea3e9b >>> Author: fparain >>> Date: 2017-06-07 15:38 -0400 >>> URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/b03e14ea3e9b >>> >>> Fix and cleanup in vwithfield >>> >>> ! src/share/vm/interpreter/interpreterRuntime.cpp >>> >> > From karen.kinnear at oracle.com Thu Jun 8 01:15:13 2017 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Wed, 7 Jun 2017 21:15:13 -0400 Subject: hg: valhalla/valhalla/hotspot: Fix and cleanup in vwithfield In-Reply-To: References: <201706071939.v57JdIJT016989@aojmv0008.oracle.com> <00878C1F-A5DA-43CE-A859-E7B1C2323F0B@oracle.com> <04148716-2FC1-4AFC-A71B-C71B4621C833@oracle.com> Message-ID: <7A788948-E873-4321-9C57-BCC098637BA9@oracle.com> Frederic, Thank you for the explanation. Got it - I had missed the original value type passed on the stack by reference needs to be popped off. thank you, Karen > On Jun 7, 2017, at 5:16 PM, Frederic Parain wrote: > > Karen, > > The integer returned is not the size of the new value type, it?s a stack > adjustment value. > > The vwithfield runtime entry returns a new value type in thread->vm_result > and an integer which is used by the assembly code to adjust the stack > pointer (the vwithfield bytecode must consume the new field value and the > original value type passed on the stack before pushing the new value). > We are doing this because we cannot manipulate the expression stack from > the runtime and the assembly code doesn?t know the size of > the new field value (one slot or two slot depending on the field type). > > The bug was that the stack adjustment returned was missing the size of > the original value type passed on the stack, leading to a ?shift? of operands > on the expression stack because the original value type was never popped. > This issue caused some GC issues (because of the shift, there was a > mismatch between the oopmap computed and the real location of references), > and could eventually caused some stack overflow issues. > > Fred > > >> On Jun 7, 2017, at 17:04, Karen Kinnear wrote: >> >> Frederic, >> >> Looks good. Thank you for the cleanup. >> >> One question please - why do you add type2size(T_VALUETYPE) * stackElementSize >> when you return the size of the new value type result? >> >> thanks, >> Karen >> >>> On Jun 7, 2017, at 3:41 PM, Frederic Parain wrote: >>> >>> Fixing a bug in vwithfield leading to buggy stack management. >>> Thanks to Mr Simms for having spotted and identify the issue. >>> I took the opportunity to do a clean up of the vwithfield method, >>> removing raw pointer arithmetic on the expression stack, using >>> the frame API instead. >>> >>> Fred >>> >>> >>>> On Jun 7, 2017, at 15:39, frederic.parain at oracle.com wrote: >>>> >>>> Changeset: b03e14ea3e9b >>>> Author: fparain >>>> Date: 2017-06-07 15:38 -0400 >>>> URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/b03e14ea3e9b >>>> >>>> Fix and cleanup in vwithfield >>>> >>>> ! src/share/vm/interpreter/interpreterRuntime.cpp >>>> >>> >> > From rwestrel at redhat.com Thu Jun 8 09:31:13 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Thu, 08 Jun 2017 11:31:13 +0200 Subject: RFR: vbox/vunbox should throw ClassCastException if target type is invalid In-Reply-To: <66d005e9-551e-58d9-18fd-6fadf2215965@oracle.com> References: <66d005e9-551e-58d9-18fd-6fadf2215965@oracle.com> Message-ID: > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.19/ 610 // Check if the class of the source is a subclass of the value-capable class 611 // corresponding to the target. 612 // TOOD: Implement profiling of vunbox bytecodes to enable type speculation. 613 if (target_vcc_klass == NULL || !target_vcc_klass->is_subclass_of(source_type->klass())) { The comment says class of the source subclass target's vcc but the code does the opposite check? Roland. From tobias.hartmann at oracle.com Thu Jun 8 13:47:48 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Thu, 8 Jun 2017 15:47:48 +0200 Subject: RFR: vbox/vunbox should throw ClassCastException if target type is invalid In-Reply-To: References: <66d005e9-551e-58d9-18fd-6fadf2215965@oracle.com> Message-ID: Hi Roland, On 08.06.2017 11:31, Roland Westrelin wrote: > 610 // Check if the class of the source is a subclass of the value-capable class > 611 // corresponding to the target. > 612 // TOOD: Implement profiling of vunbox bytecodes to enable type speculation. > 613 if (target_vcc_klass == NULL || !target_vcc_klass->is_subclass_of(source_type->klass())) { > > The comment says class of the source subclass target's vcc but the code > does the opposite check? Good catch, I fixed it: http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.19/ Thanks, Tobias From rwestrel at redhat.com Thu Jun 8 16:12:12 2017 From: rwestrel at redhat.com (rwestrel at redhat.com) Date: Thu, 08 Jun 2017 16:12:12 +0000 Subject: hg: valhalla/valhalla/hotspot: ciReplay support for value type reference fields Message-ID: <201706081612.v58GCCvS021843@aojmv0008.oracle.com> Changeset: e31f5c06438d Author: roland Date: 2017-06-01 17:13 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/e31f5c06438d ciReplay support for value type reference fields ! src/share/vm/ci/ciInstanceKlass.cpp ! src/share/vm/ci/ciReplay.cpp From rwestrel at redhat.com Thu Jun 8 16:39:00 2017 From: rwestrel at redhat.com (rwestrel at redhat.com) Date: Thu, 08 Jun 2017 16:39:00 +0000 Subject: hg: valhalla/valhalla/hotspot: multiple value return Message-ID: <201706081639.v58Gd0DS000620@aojmv0008.oracle.com> Changeset: 4cd1b06ce224 Author: roland Date: 2017-06-08 18:25 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/4cd1b06ce224 multiple value return ! src/cpu/ppc/vm/globals_ppc.hpp ! src/cpu/sparc/vm/globals_sparc.hpp ! src/cpu/x86/vm/globals_x86.hpp ! src/cpu/x86/vm/interp_masm_x86.cpp ! src/cpu/x86/vm/interp_masm_x86.hpp ! src/cpu/x86/vm/interpreterRT_x86_32.cpp ! src/cpu/x86/vm/macroAssembler_x86.cpp ! src/cpu/x86/vm/sharedRuntime_x86_32.cpp ! src/cpu/x86/vm/sharedRuntime_x86_64.cpp ! src/cpu/x86/vm/stubGenerator_x86_64.cpp ! src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp ! src/cpu/x86/vm/templateTable_x86.cpp ! src/cpu/zero/vm/globals_zero.hpp ! src/share/vm/c1/c1_IR.hpp ! src/share/vm/code/compiledMethod.cpp ! src/share/vm/code/debugInfoRec.cpp ! src/share/vm/code/debugInfoRec.hpp ! src/share/vm/code/nmethod.cpp ! src/share/vm/code/pcDesc.hpp ! src/share/vm/code/scopeDesc.cpp ! src/share/vm/code/scopeDesc.hpp ! src/share/vm/jvmci/jvmciCodeInstaller.cpp ! src/share/vm/oops/method.cpp ! src/share/vm/oops/method.hpp ! src/share/vm/oops/valueKlass.cpp ! src/share/vm/oops/valueKlass.hpp ! src/share/vm/opto/callGenerator.cpp ! src/share/vm/opto/callGenerator.hpp ! src/share/vm/opto/callnode.cpp ! src/share/vm/opto/callnode.hpp ! src/share/vm/opto/compile.cpp ! src/share/vm/opto/compile.hpp ! src/share/vm/opto/divnode.cpp ! src/share/vm/opto/divnode.hpp ! src/share/vm/opto/doCall.cpp ! src/share/vm/opto/escape.cpp ! src/share/vm/opto/generateOptoStub.cpp ! src/share/vm/opto/graphKit.cpp ! src/share/vm/opto/lcm.cpp ! src/share/vm/opto/machnode.cpp ! src/share/vm/opto/machnode.hpp ! src/share/vm/opto/macro.cpp ! src/share/vm/opto/matcher.cpp ! src/share/vm/opto/matcher.hpp ! src/share/vm/opto/memnode.cpp ! src/share/vm/opto/memnode.hpp ! src/share/vm/opto/multnode.cpp ! src/share/vm/opto/multnode.hpp ! src/share/vm/opto/output.cpp ! src/share/vm/opto/parse1.cpp ! src/share/vm/opto/runtime.cpp ! src/share/vm/opto/runtime.hpp ! src/share/vm/opto/type.cpp ! src/share/vm/opto/type.hpp ! src/share/vm/opto/valuetypenode.cpp ! src/share/vm/opto/valuetypenode.hpp ! src/share/vm/prims/jvmtiCodeBlobEvents.cpp ! src/share/vm/runtime/arguments.cpp ! src/share/vm/runtime/deoptimization.cpp ! src/share/vm/runtime/deoptimization.hpp ! src/share/vm/runtime/globals.hpp ! src/share/vm/runtime/safepoint.cpp ! src/share/vm/runtime/sharedRuntime.cpp ! src/share/vm/runtime/sharedRuntime.hpp ! src/share/vm/runtime/signature.cpp ! src/share/vm/runtime/signature.hpp ! src/share/vm/runtime/stubRoutines.cpp ! src/share/vm/runtime/stubRoutines.hpp ! src/share/vm/shark/sharkCacheDecache.cpp ! test/compiler/valhalla/valuetypes/ValueTypeTestBench.java From rwestrel at redhat.com Thu Jun 8 16:39:42 2017 From: rwestrel at redhat.com (rwestrel at redhat.com) Date: Thu, 08 Jun 2017 16:39:42 +0000 Subject: hg: valhalla/valhalla/jdk: set VALHALLA_ENABLE_VALUE_LFORMS to true by default Message-ID: <201706081639.v58GdgcS000755@aojmv0008.oracle.com> Changeset: e684de768294 Author: roland Date: 2017-06-08 18:37 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/e684de768294 set VALHALLA_ENABLE_VALUE_LFORMS to true by default ! src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java From sergey.kuksenko at oracle.com Thu Jun 8 22:46:19 2017 From: sergey.kuksenko at oracle.com (Sergey Kuksenko) Date: Thu, 8 Jun 2017 15:46:19 -0700 Subject: valhalla/valhalla/hotspot: multiple value return caused interpreter performance regression In-Reply-To: <201706081639.v58Gd0DS000620@aojmv0008.oracle.com> References: <201706081639.v58Gd0DS000620@aojmv0008.oracle.com> Message-ID: <25d32751-d558-b090-3c39-e84c417a70d8@oracle.com> Hi Roland, I've just realized that this patch causes more than 3x time interpreter performance regression (if method contains local variable of value type). Question to all: How big INTERPRETER performance regression will be considered as OK? I'll provide more details about the regression if we agreed that 3x times for the interpreter is too much. On 06/08/2017 09:39 AM, rwestrel at redhat.com wrote: > Changeset: 4cd1b06ce224 > Author: roland > Date: 2017-06-08 18:25 +0200 > URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/4cd1b06ce224 > > multiple value return > > ! src/cpu/ppc/vm/globals_ppc.hpp > ! src/cpu/sparc/vm/globals_sparc.hpp > ! src/cpu/x86/vm/globals_x86.hpp > ! src/cpu/x86/vm/interp_masm_x86.cpp > ! src/cpu/x86/vm/interp_masm_x86.hpp > ! src/cpu/x86/vm/interpreterRT_x86_32.cpp > ! src/cpu/x86/vm/macroAssembler_x86.cpp > ! src/cpu/x86/vm/sharedRuntime_x86_32.cpp > ! src/cpu/x86/vm/sharedRuntime_x86_64.cpp > ! src/cpu/x86/vm/stubGenerator_x86_64.cpp > ! src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp > ! src/cpu/x86/vm/templateTable_x86.cpp > ! src/cpu/zero/vm/globals_zero.hpp > ! src/share/vm/c1/c1_IR.hpp > ! src/share/vm/code/compiledMethod.cpp > ! src/share/vm/code/debugInfoRec.cpp > ! src/share/vm/code/debugInfoRec.hpp > ! src/share/vm/code/nmethod.cpp > ! src/share/vm/code/pcDesc.hpp > ! src/share/vm/code/scopeDesc.cpp > ! src/share/vm/code/scopeDesc.hpp > ! src/share/vm/jvmci/jvmciCodeInstaller.cpp > ! src/share/vm/oops/method.cpp > ! src/share/vm/oops/method.hpp > ! src/share/vm/oops/valueKlass.cpp > ! src/share/vm/oops/valueKlass.hpp > ! src/share/vm/opto/callGenerator.cpp > ! src/share/vm/opto/callGenerator.hpp > ! src/share/vm/opto/callnode.cpp > ! src/share/vm/opto/callnode.hpp > ! src/share/vm/opto/compile.cpp > ! src/share/vm/opto/compile.hpp > ! src/share/vm/opto/divnode.cpp > ! src/share/vm/opto/divnode.hpp > ! src/share/vm/opto/doCall.cpp > ! src/share/vm/opto/escape.cpp > ! src/share/vm/opto/generateOptoStub.cpp > ! src/share/vm/opto/graphKit.cpp > ! src/share/vm/opto/lcm.cpp > ! src/share/vm/opto/machnode.cpp > ! src/share/vm/opto/machnode.hpp > ! src/share/vm/opto/macro.cpp > ! src/share/vm/opto/matcher.cpp > ! src/share/vm/opto/matcher.hpp > ! src/share/vm/opto/memnode.cpp > ! src/share/vm/opto/memnode.hpp > ! src/share/vm/opto/multnode.cpp > ! src/share/vm/opto/multnode.hpp > ! src/share/vm/opto/output.cpp > ! src/share/vm/opto/parse1.cpp > ! src/share/vm/opto/runtime.cpp > ! src/share/vm/opto/runtime.hpp > ! src/share/vm/opto/type.cpp > ! src/share/vm/opto/type.hpp > ! src/share/vm/opto/valuetypenode.cpp > ! src/share/vm/opto/valuetypenode.hpp > ! src/share/vm/prims/jvmtiCodeBlobEvents.cpp > ! src/share/vm/runtime/arguments.cpp > ! src/share/vm/runtime/deoptimization.cpp > ! src/share/vm/runtime/deoptimization.hpp > ! src/share/vm/runtime/globals.hpp > ! src/share/vm/runtime/safepoint.cpp > ! src/share/vm/runtime/sharedRuntime.cpp > ! src/share/vm/runtime/sharedRuntime.hpp > ! src/share/vm/runtime/signature.cpp > ! src/share/vm/runtime/signature.hpp > ! src/share/vm/runtime/stubRoutines.cpp > ! src/share/vm/runtime/stubRoutines.hpp > ! src/share/vm/shark/sharkCacheDecache.cpp > ! test/compiler/valhalla/valuetypes/ValueTypeTestBench.java > -- Best regards, Sergey Kuksenko From rwestrel at redhat.com Fri Jun 9 10:54:33 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Fri, 09 Jun 2017 12:54:33 +0200 Subject: valhalla/valhalla/hotspot: multiple value return caused interpreter performance regression In-Reply-To: <25d32751-d558-b090-3c39-e84c417a70d8@oracle.com> References: <201706081639.v58Gd0DS000620@aojmv0008.oracle.com> <25d32751-d558-b090-3c39-e84c417a70d8@oracle.com> Message-ID: Hi Sergey, > I've just realized that this patch causes more than 3x time interpreter > performance regression (if method contains local variable of value type). > > Question to all: How big INTERPRETER performance regression will be > considered as OK? Thanks for the performance number. My change adds 2 runtime calls on method returns with a value type from interpreted callee to interpreted caller so a big performance drop is not surprising. My understanding is that we don't care too much about interpreter performance at this point. In any case, I would rather wait for Frederic's buffering change to be pushed before considering any improvement to the vreturn implementation. Roland. From rwestrel at redhat.com Fri Jun 9 11:05:46 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Fri, 09 Jun 2017 13:05:46 +0200 Subject: RFR: vbox/vunbox should throw ClassCastException if target type is invalid In-Reply-To: References: <66d005e9-551e-58d9-18fd-6fadf2215965@oracle.com> Message-ID: > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.19/ That looks good to me. Roland. From tobias.hartmann at oracle.com Fri Jun 9 13:05:50 2017 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Fri, 09 Jun 2017 13:05:50 +0000 Subject: hg: valhalla/valhalla/hotspot: box/vunbox should throw ClassCastException if target type is invalid Message-ID: <201706091305.v59D5od0007919@aojmv0008.oracle.com> Changeset: 06653fdee38e Author: thartmann Date: 2017-06-09 15:03 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/06653fdee38e box/vunbox should throw ClassCastException if target type is invalid ! src/share/vm/ci/ciTypeFlow.cpp ! src/share/vm/opto/parse3.cpp ! test/compiler/valhalla/valuetypes/ValueTypeTestBench.java From tobias.hartmann at oracle.com Fri Jun 9 13:04:21 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Fri, 9 Jun 2017 15:04:21 +0200 Subject: RFR: vbox/vunbox should throw ClassCastException if target type is invalid In-Reply-To: References: <66d005e9-551e-58d9-18fd-6fadf2215965@oracle.com> Message-ID: On 09.06.2017 13:05, Roland Westrelin wrote: >> http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.19/ > > That looks good to me. Thanks Roland. Best regards, Tobias From karen.kinnear at oracle.com Fri Jun 9 15:15:26 2017 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Fri, 9 Jun 2017 11:15:26 -0400 Subject: valhalla/valhalla/hotspot: multiple value return caused interpreter performance regression In-Reply-To: References: <201706081639.v58Gd0DS000620@aojmv0008.oracle.com> <25d32751-d558-b090-3c39-e84c417a70d8@oracle.com> Message-ID: <45E8B14D-40C6-43FA-8E9F-6B605BC31B56@oracle.com> I agree with Roland on pushing Frederic?s changes before considering the vreturn improvements (I think it is waiting on a code review?) My perspective on interpreter performance: We do not expect the interpreter implementation in MVT to give significant performance benefits for value types over references. Our goal has been to try to break even and minimize performance loss. In general for hotspot, our guidance on interpreter performance has been to look at it in two contexts 1) general throughput when run with a JIT 2) startup impact, since it runs prior to the JIT i.e. performance numbers for -Xint alone are not sufficient to drive decisions. I haven?t seen the results Sergey - do you have a wiki page with test results for MVT or a way to share intermediate performance information for specific changes? (delighted you are testing our optimizations!) thanks, Karen > On Jun 9, 2017, at 6:54 AM, Roland Westrelin wrote: > > > Hi Sergey, > >> I've just realized that this patch causes more than 3x time interpreter >> performance regression (if method contains local variable of value type). >> >> Question to all: How big INTERPRETER performance regression will be >> considered as OK? > > Thanks for the performance number. My change adds 2 runtime calls on > method returns with a value type from interpreted callee to interpreted > caller so a big performance drop is not surprising. > > My understanding is that we don't care too much about interpreter > performance at this point. In any case, I would rather wait for > Frederic's buffering change to be pushed before considering any > improvement to the vreturn implementation. > > Roland. From rwestrel at redhat.com Fri Jun 9 16:03:02 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Fri, 09 Jun 2017 18:03:02 +0200 Subject: couple questions on method handle combinators Message-ID: I've been playing with method handle combinators and value types. Here are 2 tests that I put together: http://cr.openjdk.java.net/~roland/valhalla/combinators/webrev.00/ but they don't do what I want. test77() runs fine but I noticed that if what test77_test() returns is not constant then, test77_target1() and test_target2() are not inlined: 876 82 b compiler.valhalla.valuetypes.ValueTypeTestBench::test77 (8 bytes) @ 4 java.lang.invoke.LambdaForm$MH/1308244637::invokeExact_MT (36 bytes) force inline by annotation @ 11 java.lang.invoke.Invokers::checkExactType (17 bytes) force inline by annotation @ 1 java.lang.invoke.MethodHandle::type (5 bytes) accessor @ 21 java.lang.invoke.Invokers::checkCustomized (23 bytes) force inline by annotation @ 1 java.lang.invoke.MethodHandleImpl::isCompileConstant (2 bytes) (intrinsic) @ 32 java.lang.invoke.LambdaForm$MH/597255128::guard (91 bytes) force inline by annotation @ 51 java.lang.invoke.LambdaForm$DMH/586617651::invokeVirtual (14 bytes) force inline by annotation @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) force inline by annotation @ 10 compiler.valhalla.valuetypes.ValueTypeTestBench::test77_test (5 bytes) accessor ! @ 63 java.lang.invoke.MethodHandleImpl::profileBoolean (34 bytes) (intrinsic) @ 79 java.lang.invoke.MethodHandleImpl::selectAlternative (8 bytes) inline (hot) @ 87 java.lang.invoke.MethodHandle::invokeBasic(L)Qjava/lang/__Value; (0 bytes) receiver not constant What I want is 2 inlined methods that return a value type and the 2 return values go through a merge point before the method handle call returns. Anyone sees way to get that with guardWithTest or something else? test78() attempts to build a loop whose result is a value type but creation of the loop combinator fails with: java.lang.ExceptionInInitializerError at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:563) at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:115) at java.base/java.lang.Thread.run(Thread.java:844) Caused by: java.lang.IllegalStateException: java.lang.ClassNotFoundException: compiler.valhalla.valuetypes.My at java.base/java.lang.invoke.MethodHandles.makeIdentity(MethodHandles.java:3432) at java.base/java.lang.invoke.MethodHandles.identity(MethodHandles.java:3363) at java.base/java.lang.invoke.MethodHandles.countedLoop(MethodHandles.java:5524) at java.base/java.lang.invoke.MethodHandles.countedLoop(MethodHandles.java:5389) at compiler.valhalla.valuetypes.ValueTypeTestBench.(ValueTypeTestBench.java:2314) ... 6 more Caused by: java.lang.ClassNotFoundException: compiler.valhalla.valuetypes.My at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:553) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:486) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:374) at java.base/valhalla.shady.MinimalValueTypes_1_0.getValueCapableClass(MinimalValueTypes_1_0.java:81) at java.base/java.lang.invoke.MethodHandles.makeIdentity(MethodHandles.java:3430) ... 10 more Anyone has any idea how to build the loop combinator? Roland. From maurizio.cimadamore at oracle.com Fri Jun 9 20:44:12 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 9 Jun 2017 21:44:12 +0100 Subject: couple questions on method handle combinators In-Reply-To: References: Message-ID: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> On 09/06/17 17:03, Roland Westrelin wrote: > I've been playing with method handle combinators and value types. Here > are 2 tests that I put together: > > http://cr.openjdk.java.net/~roland/valhalla/combinators/webrev.00/ > > but they don't do what I want. > > test77() runs fine but I noticed that if what test77_test() returns is > not constant then, test77_target1() and test_target2() are not inlined: > > 876 82 b compiler.valhalla.valuetypes.ValueTypeTestBench::test77 (8 bytes) > @ 4 java.lang.invoke.LambdaForm$MH/1308244637::invokeExact_MT (36 bytes) force inline by annotation > @ 11 java.lang.invoke.Invokers::checkExactType (17 bytes) force inline by annotation > @ 1 java.lang.invoke.MethodHandle::type (5 bytes) accessor > @ 21 java.lang.invoke.Invokers::checkCustomized (23 bytes) force inline by annotation > @ 1 java.lang.invoke.MethodHandleImpl::isCompileConstant (2 bytes) (intrinsic) > @ 32 java.lang.invoke.LambdaForm$MH/597255128::guard (91 bytes) force inline by annotation > @ 51 java.lang.invoke.LambdaForm$DMH/586617651::invokeVirtual (14 bytes) force inline by annotation > @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) force inline by annotation > @ 10 compiler.valhalla.valuetypes.ValueTypeTestBench::test77_test (5 bytes) accessor > ! @ 63 java.lang.invoke.MethodHandleImpl::profileBoolean (34 bytes) (intrinsic) > @ 79 java.lang.invoke.MethodHandleImpl::selectAlternative (8 bytes) inline (hot) > @ 87 java.lang.invoke.MethodHandle::invokeBasic(L)Qjava/lang/__Value; (0 bytes) receiver not constant > > What I want is 2 inlined methods that return a value type and the 2 > return values go through a merge point before the method handle call > returns. Anyone sees way to get that with guardWithTest or something > else? > > test78() attempts to build a loop whose result is a value type but > creation of the loop combinator fails with: I'll look into that. (I'll happily leave your other inlining questions to people more knowledgeable in that area). Maurizio > > java.lang.ExceptionInInitializerError > at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) > at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) > at java.base/java.lang.reflect.Method.invoke(Method.java:563) > at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:115) > at java.base/java.lang.Thread.run(Thread.java:844) > Caused by: java.lang.IllegalStateException: java.lang.ClassNotFoundException: compiler.valhalla.valuetypes.My > at java.base/java.lang.invoke.MethodHandles.makeIdentity(MethodHandles.java:3432) > at java.base/java.lang.invoke.MethodHandles.identity(MethodHandles.java:3363) > at java.base/java.lang.invoke.MethodHandles.countedLoop(MethodHandles.java:5524) > at java.base/java.lang.invoke.MethodHandles.countedLoop(MethodHandles.java:5389) > at compiler.valhalla.valuetypes.ValueTypeTestBench.(ValueTypeTestBench.java:2314) > ... 6 more > Caused by: java.lang.ClassNotFoundException: compiler.valhalla.valuetypes.My > at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:553) > at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185) > at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:486) > at java.base/java.lang.Class.forName0(Native Method) > at java.base/java.lang.Class.forName(Class.java:374) > at java.base/valhalla.shady.MinimalValueTypes_1_0.getValueCapableClass(MinimalValueTypes_1_0.java:81) > at java.base/java.lang.invoke.MethodHandles.makeIdentity(MethodHandles.java:3430) > ... 10 more > > Anyone has any idea how to build the loop combinator? > > Roland. From sergey.kuksenko at oracle.com Fri Jun 9 23:29:56 2017 From: sergey.kuksenko at oracle.com (Sergey Kuksenko) Date: Fri, 9 Jun 2017 16:29:56 -0700 Subject: valhalla/valhalla/hotspot: multiple value return caused interpreter performance regression In-Reply-To: <45E8B14D-40C6-43FA-8E9F-6B605BC31B56@oracle.com> References: <201706081639.v58Gd0DS000620@aojmv0008.oracle.com> <25d32751-d558-b090-3c39-e84c417a70d8@oracle.com> <45E8B14D-40C6-43FA-8E9F-6B605BC31B56@oracle.com> Message-ID: Karen, see my notes below On 06/09/2017 08:15 AM, Karen Kinnear wrote: > I agree with Roland on pushing Frederic?s changes before considering the vreturn improvements > (I think it is waiting on a code review?) > > My perspective on interpreter performance: > We do not expect the interpreter implementation in MVT to give significant performance > benefits for value types over references. Neither do I. > Our goal has been to try to break even and minimize > performance loss. Exactly, it's what I am tracking right now. > > In general for hotspot, our guidance on interpreter performance has been to look > at it in two contexts > 1) general throughput when run with a JIT The most easiest way - easy to measure, results are stable, etc. > 2) startup impact, since it runs prior to the JIT > i.e. performance numbers for -Xint alone are not sufficient to drive decisions. It's quite a hard way. I have to say that right now, we don't have startup benchmarks where interpreter has significant impact to startup performance. Other components like classloading, JIT compilation, verification and others have higher impact than interpreter. I could guess that even getting 3x times slowdown of the interpreter - we won't get more than 10% slowdown of startup time, that is acceptable. I will think about such kind of startup benchmarks after finishing JIT benchmarking. At the same moment, simply measure interpreter performance (-Xint) we get upper bound estimations how interpreter may has influence to startup (I agree that it's too "upper"). For example, before multiple value return patch the interpreter for value types was ~10% slower than analogue code with references, and in this case there is no necessity to worry about startup performance (I mean interpreter's impact). In case of 3x interpreter slowdown. We won't see any startup regression (on any application) right now due to the fact the all base classes loaded at startup are value-free and interpreting of value-free classes is untouched by that slowdown. And I could guess that we won't see any startup regressions caused by interpreter withing MVT project activity (It doesn't mean that I won't check it, but I don't expect any visible). The same situation is for extra allocations (boxing) in the interpreter - extra boxing or value buffering will have the same performance impact to general startup. Of course the situation may change later - when base classes will use value type heavily or customers will create application with lot of value classes at startup. If we've got 3x slowdown (with -Xint) and if (and only if) developers have ideas how to fix easily - we should fix it. If it can't fixed without significant efforts - lets postpone it, but not forget. > I haven?t seen the results > Sergey - do you have a wiki page with test results for MVT or a way to share intermediate > performance information for specific changes? (delighted you are testing our optimizations!) yes. I working on this right now. > > thanks, > Karen >> On Jun 9, 2017, at 6:54 AM, Roland Westrelin wrote: >> >> >> Hi Sergey, >> >>> I've just realized that this patch causes more than 3x time interpreter >>> performance regression (if method contains local variable of value type). >>> >>> Question to all: How big INTERPRETER performance regression will be >>> considered as OK? >> Thanks for the performance number. My change adds 2 runtime calls on >> method returns with a value type from interpreted callee to interpreted >> caller so a big performance drop is not surprising. >> >> My understanding is that we don't care too much about interpreter >> performance at this point. In any case, I would rather wait for >> Frederic's buffering change to be pushed before considering any >> improvement to the vreturn implementation. >> >> Roland. -- Best regards, Sergey Kuksenko From paul.sandoz at oracle.com Sat Jun 10 00:18:22 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 9 Jun 2017 17:18:22 -0700 Subject: couple questions on method handle combinators In-Reply-To: References: Message-ID: <4E3F85F5-A956-4188-A92C-D15EB3EC5E0D@oracle.com> Hi Roland, I think the general problem here is two distinct value worlds are colliding, the shadowy MVT value world, and the "avoiding the syntax bike shed painting" __ByValue value world. AFAICT the MVT API assumes that if the ACC_VALUE modifier is set on a class (Q type) then it should have a particular naming convention related to the value capable class from which the value type class was derived (the latter being named $Value, where is the name of the value capable class. This is why 6 characters are chopped of the end of the name of the class MyValue5. (There is some ?magic? in the VM that detects, when class file parsing, if a class is a value capable class and if so derives the value type class via an up call to Java, see valhalla.shady.MinimalValueTypes_1_0.createDerivedValueType) That assumption is encoded in areas of the method handle implementation, such as here: private static MethodHandle makeIdentity(Class ptype) { if (!MinimalValueTypes_1_0.isValueType(ptype)) { MethodType mtype = MethodType.methodType(ptype, ptype); LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype)); return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY); } else { try { return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(ptype)).identity(); } catch (ReflectiveOperationException ex) { throw new IllegalStateException(ex); } } } I am unsure how to unify these two worlds. For now it might be easiest if you keep tests for the two worlds separate i.e. when working with MethodHandles work in the MVT world. Paul. > On 9 Jun 2017, at 09:03, Roland Westrelin wrote: > test78() attempts to build a loop whose result is a value type but > creation of the loop combinator fails with: > > java.lang.ExceptionInInitializerError > at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) > at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) > at java.base/java.lang.reflect.Method.invoke(Method.java:563) > at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:115) > at java.base/java.lang.Thread.run(Thread.java:844) > Caused by: java.lang.IllegalStateException: java.lang.ClassNotFoundException: compiler.valhalla.valuetypes.My > at java.base/java.lang.invoke.MethodHandles.makeIdentity(MethodHandles.java:3432) > at java.base/java.lang.invoke.MethodHandles.identity(MethodHandles.java:3363) > at java.base/java.lang.invoke.MethodHandles.countedLoop(MethodHandles.java:5524) > at java.base/java.lang.invoke.MethodHandles.countedLoop(MethodHandles.java:5389) > at compiler.valhalla.valuetypes.ValueTypeTestBench.(ValueTypeTestBench.java:2314) > ... 6 more > Caused by: java.lang.ClassNotFoundException: compiler.valhalla.valuetypes.My > at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:553) > at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185) > at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:486) > at java.base/java.lang.Class.forName0(Native Method) > at java.base/java.lang.Class.forName(Class.java:374) > at java.base/valhalla.shady.MinimalValueTypes_1_0.getValueCapableClass(MinimalValueTypes_1_0.java:81) > at java.base/java.lang.invoke.MethodHandles.makeIdentity(MethodHandles.java:3430) > ... 10 more > > Anyone has any idea how to build the loop combinator? > > Roland. From david.simms at oracle.com Mon Jun 12 10:17:23 2017 From: david.simms at oracle.com (david.simms at oracle.com) Date: Mon, 12 Jun 2017 10:17:23 +0000 Subject: hg: valhalla/valhalla/jdk: Support for experimenting with vdefault + vwithfield Message-ID: <201706121017.v5CAHN2n025415@aojmv0008.oracle.com> Changeset: dd98f2d79dbd Author: dsimms Date: 2017-06-12 12:14 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/dd98f2d79dbd Support for experimenting with vdefault + vwithfield ! src/java.base/share/classes/jdk/experimental/bytecode/CodeBuilder.java ! src/java.base/share/classes/jdk/experimental/bytecode/Opcode.java ! src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java From david.simms at oracle.com Mon Jun 12 10:17:33 2017 From: david.simms at oracle.com (david.simms at oracle.com) Date: Mon, 12 Jun 2017 10:17:33 +0000 Subject: hg: valhalla/valhalla/hotspot: Test value type reference fields Message-ID: <201706121017.v5CAHY3M025854@aojmv0008.oracle.com> Changeset: 3a4ea109aeb9 Author: dsimms Date: 2017-06-12 12:15 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/3a4ea109aeb9 Test value type reference fields + test/runtime/valhalla/valuetypes/PersonVcc.java + test/runtime/valhalla/valuetypes/ValueOops.java From rwestrel at redhat.com Mon Jun 12 16:45:19 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Mon, 12 Jun 2017 18:45:19 +0200 Subject: couple questions on method handle combinators In-Reply-To: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> Message-ID: > (I'll happily leave your other inlining questions to people more > knowledgeable in that area). I could have phrased that question better. Let me try to give some context. For: MethodHandles.guardWithTest(test77_mh_test, test77_mh1, test77_mh2); AFAICT, the logic implemented by the lambda forms is: MethodHandle mh = selectAlternative(test77_mh_test, test77_mh1, test77_mh2); mh.invoke(...); So mh can't be a constant at the invoke if test77_mh_test returns either true and false. I suppose I expected something like: if (test77_mh_test.invoke()) { test77_mh1.invoke(); } else { test77_mh2.invoke(); } in which case, at the invoke sites the method handles could be known. The reason I'm experimenting with guardWithTest is that I'd like the lambda forms to follow a particular shape (to check if c2 can optimize the handling of the method handle call return properly): if ( ) { value_type_result = m1.invoke(); } else { value_type_result = m2.invoke(); } // value type result merged here return value_type_result; The merge of 2 return values is what I'm interested in. With a loop I expect I would get a similar pattern: value_type_result = init_mh.invoke(); for(;;) { value_type_result = body_mh.invoke(); // value type result merged here } return value_type_result; So I guess my question is: Is there no way to get guardWithTest to do what I want? Other than with loops and guardWithTest, is there another way to get a merge point with returned values from invokes? Roland. From paul.sandoz at oracle.com Mon Jun 12 17:21:55 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 12 Jun 2017 10:21:55 -0700 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> Message-ID: <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> Hi Roland, The GWT forms contain some special profiling logic for the boolean branch and AFAICT counting forms for target invocation (of either branch) are created to block the JIT inlining until they have been called enough times. I believe for this logic to work correctly it requires execution in the interpreter, otherwise the LF update may not be visible, since final fields are trusted to be stable, once C2 gets hold if it it will think it constant. Vladimir will know much more than I. This might all be getting in the way of what you want to achieve. It may be better for you to generate explicit byte code for that which you want to test (similar to that of recent tests David added). Paul. > On 12 Jun 2017, at 09:45, Roland Westrelin wrote: > > >> (I'll happily leave your other inlining questions to people more >> knowledgeable in that area). > > I could have phrased that question better. Let me try to give some > context. For: > > MethodHandles.guardWithTest(test77_mh_test, test77_mh1, test77_mh2); > > AFAICT, the logic implemented by the lambda forms is: > > MethodHandle mh = selectAlternative(test77_mh_test, test77_mh1, test77_mh2); > mh.invoke(...); > > So mh can't be a constant at the invoke if test77_mh_test returns either > true and false. > > I suppose I expected something like: > > if (test77_mh_test.invoke()) { > test77_mh1.invoke(); > } else { > test77_mh2.invoke(); > } > > in which case, at the invoke sites the method handles could be known. > > The reason I'm experimenting with guardWithTest is that I'd like the > lambda forms to follow a particular shape (to check if c2 can optimize > the handling of the method handle call return properly): > > if ( ) { > value_type_result = m1.invoke(); > } else { > value_type_result = m2.invoke(); > } > // value type result merged here > return value_type_result; > > The merge of 2 return values is what I'm interested in. With a loop I > expect I would get a similar pattern: > > value_type_result = init_mh.invoke(); > for(;;) { > value_type_result = body_mh.invoke(); // value type result merged here > } > return value_type_result; > > So I guess my question is: Is there no way to get guardWithTest to do > what I want? Other than with loops and guardWithTest, is there another > way to get a merge point with returned values from invokes? > > Roland. From rwestrel at redhat.com Mon Jun 12 18:46:00 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Mon, 12 Jun 2017 20:46:00 +0200 Subject: couple questions on method handle combinators In-Reply-To: <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> Message-ID: Hi Paul, > The GWT forms contain some special profiling logic for the boolean > branch and AFAICT counting forms for target invocation (of either > branch) are created to block the JIT inlining until they have been > called enough times. I believe for this logic to work correctly it > requires execution in the interpreter, otherwise the LF update may not > be visible, since final fields are trusted to be stable, once C2 gets > hold if it it will think it constant. Vladimir will know much more > than I. AFAICT, that logic only keeps track of frequencies and so the invoke target is only constant if one of the branch is never taken. > This might all be getting in the way of what you want to achieve. It > may be better for you to generate explicit byte code for that which > you want to test (similar to that of recent tests David added). In the code shape that I'm interested in, return values must be passed as __Value which is only used by lambda forms. Also, if that code shape is never used in practice then there's nothing to optimize. Roland. From paul.sandoz at oracle.com Mon Jun 12 19:27:22 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 12 Jun 2017 12:27:22 -0700 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> Message-ID: > On 12 Jun 2017, at 11:46, Roland Westrelin wrote: > > > Hi Paul, > >> The GWT forms contain some special profiling logic for the boolean >> branch and AFAICT counting forms for target invocation (of either >> branch) are created to block the JIT inlining until they have been >> called enough times. I believe for this logic to work correctly it >> requires execution in the interpreter, otherwise the LF update may not >> be visible, since final fields are trusted to be stable, once C2 gets >> hold if it it will think it constant. Vladimir will know much more >> than I. > > AFAICT, that logic only keeps track of frequencies and so the invoke > target is only constant if one of the branch is never taken. I don?t fully understand it and would need to write some tests and look out compiler output. > >> This might all be getting in the way of what you want to achieve. It >> may be better for you to generate explicit byte code for that which >> you want to test (similar to that of recent tests David added). > > In the code shape that I'm interested in, return values must be passed > as __Value which is only used by lambda forms. Ah, i missed that aspect. I suppose there is nothing stopping you generating byte code referring to __Value in method sigs. To investigate further i think we need to write a separate smaller GWT test for both values and refs. I can write such a test if that helps? and may want be useful for MH analysis. Paul. > Also, if that code shape > is never used in practice then there's nothing to optimize. > > Roland. From maurizio.cimadamore at oracle.com Mon Jun 12 20:13:32 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 12 Jun 2017 21:13:32 +0100 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> Message-ID: On 12/06/17 20:27, Paul Sandoz wrote: > To investigate further i think we need to write a separate smaller GWT test for both values and refs. I can write such a test if that helps? and may want be useful for MH analysis. +1 Thanks Paul, seems a solid plan Maurizio From paul.sandoz at oracle.com Tue Jun 13 00:00:53 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 12 Jun 2017 17:00:53 -0700 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> Message-ID: <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> Below is a simple test class. Unfortunately running this crashes the VM. Paul. # Internal Error (/Users/sandoz/Projects/jdk10/valhalla/hotspot/src/share/vm/utilities/growableArray.hpp:233), pid=35547, tid=29443 # assert(0 <= i && i < _len) failed: illegal index ... Stack: [0x0000000122332000,0x0000000122432000], sp=0x000000012242f1f0, free space=1012k Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code) V [libjvm.dylib+0xc99cb4] VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x4d4 V [libjvm.dylib+0xc9a476] VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x4a V [libjvm.dylib+0x4cb281] report_vm_error(char const*, int, char const*, char const*, ...)+0xcd V [libjvm.dylib+0x6a3ba6] GrowableArray::at(int) const+0x4e V [libjvm.dylib+0xa16335] TypeStackSlotEntries::post_initialize(Symbol*, bool, bool)+0xa9 V [libjvm.dylib+0xa164f5] CallTypeData::post_initialize(BytecodeStream*, MethodData*)+0x14d V [libjvm.dylib+0xa1895f] MethodData::post_initialize(BytecodeStream*)+0x81 V [libjvm.dylib+0xa18cf0] MethodData::initialize()+0x2d6 V [libjvm.dylib+0xa17a95] MethodData::allocate(ClassLoaderData*, methodHandle const&, Thread*)+0xa9 V [libjvm.dylib+0xa0c994] Method::build_interpreter_method_data(methodHandle const&, Thread*)+0x76 V [libjvm.dylib+0x6beaf0] InterpreterRuntime::profile_method(JavaThread*)+0x1ba j java.lang.invoke.LambdaForm$DMH.invokeStatic(Ljava/lang/Object;Qjava/lang/__Value;)Ljava/lang/Object;+0 java.base at 10-internal j java.lang.invoke.LambdaForm$MH.invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;I)Ljava/lang/Object;+169 java.base at 10-internal j java.lang.invoke.LambdaForm$MH.invoke_MT(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Ljava/lang/Object;+24 java.base at 10-internal j GWTTest.run_Q()I+20 > On 12 Jun 2017, at 13:13, Maurizio Cimadamore wrote: > > > > On 12/06/17 20:27, Paul Sandoz wrote: >> To investigate further i think we need to write a separate smaller GWT test for both values and refs. I can write such a test if that helps? and may want be useful for MH analysis. > +1 > > Thanks Paul, seems a solid plan > > Maurizio /* * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @run testng/othervm * -Xverify:none * -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions * -XX:-TieredCompilation * -XX:+EnableMVT * -Dvalhalla.enablePoolPatches=true * GWTTest */ /* * -Dvalhalla.dumpProxyClasses=. * -XX:+ValueTypePassFieldsAsArgs * -XX:+ValueTypeReturnedAsFields * -XX:+VerifyAdapterSharing * -XX:+EnableValhalla * -XX:+ValueArrayFlatten * -XX:ValueArrayElemMaxFlatSize=-1 * -XX:ValueArrayElemMaxFlatOops=-1 * -XX:+FullGCALotWithValueTypes */ import jdk.experimental.value.ValueType; import org.testng.annotations.Test; import valhalla.shady.MinimalValueTypes_1_0; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Objects; public class GWTTest { @jvm.internal.value.DeriveValueType static final class V { final int x; final int y; public V(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; V v = (V) o; return x == v.x && y == v.y; } @Override public int hashCode() { return Objects.hash(x, y); } @Override public String toString() { final StringBuffer sb = new StringBuffer(this.getClass().getSimpleName()); sb.append("{"); sb.append("x=").append(x); sb.append(", y=").append(y); sb.append('}'); return sb.toString(); } } static final ValueType VT = ValueType.forClass(V.class); static final Class DVT; static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); static final Object Q_V1_ARRAY; static final Object Q_V2_ARRAY; static final MethodHandle Q_MH_GWT; static final Object L_V1_ARRAY; static final Object L_V2_ARRAY; static final MethodHandle L_MH_GWT; static boolean test() { return false; } static { try { DVT = MinimalValueTypes_1_0.getValueTypeClass(V.class); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } try { Q_V1_ARRAY = MethodHandles.arrayConstructor(VT.arrayValueClass()).invoke(1); Q_V2_ARRAY = MethodHandles.arrayConstructor(VT.arrayValueClass()).invoke(1); MethodHandles.arrayElementSetter(VT.arrayValueClass()).invoke(Q_V1_ARRAY, 0, new V(1, 1)); MethodHandles.arrayElementSetter(VT.arrayValueClass()).invoke(Q_V2_ARRAY, 0, new V(2, 2)); Q_MH_GWT = MethodHandles.guardWithTest( MethodHandles.lookup().findStatic(GWTTest.class, "test", MethodType.methodType(boolean.class)), MethodHandles.dropArguments(MethodHandles.arrayElementGetter(VT.arrayValueClass()), 1, VT.arrayValueClass()), MethodHandles.dropArguments(MethodHandles.arrayElementGetter(VT.arrayValueClass()), 0, VT.arrayValueClass()) ); L_V1_ARRAY = new V[] { new V(1, 1) }; L_V2_ARRAY = new V[] { new V(2, 2) }; L_MH_GWT = MethodHandles.guardWithTest( MethodHandles.lookup().findStatic(GWTTest.class, "test", MethodType.methodType(boolean.class)), MethodHandles.dropArguments(MethodHandles.arrayElementGetter(V[].class), 1, V[].class), MethodHandles.dropArguments(MethodHandles.arrayElementGetter(V[].class), 0, V[].class) ); } catch (Throwable e) { throw new RuntimeException(e); } } static int run_Q() throws Throwable { int sum = 0; for (int i = 0; i < 100_000; i++) { V v = (V) Q_MH_GWT.invoke(Q_V1_ARRAY, Q_V2_ARRAY, 0); sum += v.x; } return sum; } @Test public void testGWT_Q() throws Throwable { int r = run_Q(); System.out.println(r); } static int run_L() throws Throwable { int sum = 0; for (int i = 0; i < 100_000; i++) { V v = (V) L_MH_GWT.invoke(L_V1_ARRAY, L_V2_ARRAY, 0); sum += v.x; } return sum; } @Test public void testGWT_L() throws Throwable { int r = run_L(); System.out.println(r); } public static void main(String[] args) throws Throwable { GWTTest t = new GWTTest(); t.testGWT_L(); t.testGWT_Q(); } } From rwestrel at redhat.com Tue Jun 13 13:14:53 2017 From: rwestrel at redhat.com (rwestrel at redhat.com) Date: Tue, 13 Jun 2017 13:14:53 +0000 Subject: hg: valhalla/valhalla/hotspot: ciValueArray + method data support for value type argument Message-ID: <201706131314.v5DDErGC014409@aojmv0008.oracle.com> Changeset: 8f7335072193 Author: roland Date: 2017-06-13 14:50 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/8f7335072193 ciValueArray + method data support for value type argument ! src/share/vm/ci/ciArray.hpp ! src/share/vm/ci/ciObject.hpp ! src/share/vm/ci/ciObjectFactory.cpp + src/share/vm/ci/ciValueArray.hpp ! src/share/vm/oops/methodData.cpp From rwestrel at redhat.com Tue Jun 13 13:16:54 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Tue, 13 Jun 2017 15:16:54 +0200 Subject: couple questions on method handle combinators In-Reply-To: <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> Message-ID: > Below is a simple test class. Unfortunately running this crashes the VM. I pushed a few fixes that should allow your test to run. Roland. From rwestrel at redhat.com Tue Jun 13 15:39:03 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Tue, 13 Jun 2017 17:39:03 +0200 Subject: couple questions on method handle combinators In-Reply-To: <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> Message-ID: > Below is a simple test class. Unfortunately running this crashes the VM. Thanks for putting the test together. C2 fails to inline much of anything... 2131 126 GWTTest::run_Q_helper (16 bytes) @ 10 java.lang.invoke.LambdaForm$MH/499105359::invoke_MT (28 bytes) force inline by annotation @ 9 java.lang.invoke.Invokers::checkGenericType (6 bytes) force inline by annotation @ 2 java.lang.invoke.MethodHandle::asType (28 bytes) inline (hot) @ 12 java.lang.invoke.MethodHandle::asTypeCached (21 bytes) inline (hot) @ 24 java.lang.invoke.MethodHandle::asTypeUncached (59 bytes) too big @ 16 java.lang.invoke.Invokers::checkCustomized (23 bytes) force inline by annotation @ 1 java.lang.invoke.MethodHandleImpl::isCompileConstant (2 bytes) (intrinsic) @ 19 java.lang.invoke.Invokers::maybeCustomize (28 bytes) don't inline by annotation @ 24 java.lang.invoke.MethodHandle::invokeBasic(LLI)L (0 bytes) receiver not constant with: static V run_Q_helper() throws Throwable { V v = (V) Q_MH_GWT.invoke(Q_V1_ARRAY, Q_V2_ARRAY, 0); return v; } static int run_Q() throws Throwable { int sum = 0; for (int i = 0; i < 100_000; i++) { V v = run_Q_helper(); sum += v.x; } return sum; } Roland. From sergey.kuksenko at oracle.com Tue Jun 13 20:04:30 2017 From: sergey.kuksenko at oracle.com (Sergey Kuksenko) Date: Tue, 13 Jun 2017 13:04:30 -0700 Subject: hg: valhalla/valhalla/jdk: Add support for Q-types to lambda forms In-Reply-To: <201706061144.v56Bi3F6023370@aojmv0008.oracle.com> References: <201706061144.v56Bi3F6023370@aojmv0008.oracle.com> Message-ID: <59733b95-fc38-0ed8-5feb-b360596abdfb@oracle.com> Maurizio, When you did that commit you accidentally rewrote previous commit which fixed names of generated classes. That causes ValueType.getWither doesn't work with value types other than from default package. Your code (see method getWither): result = MethodHandleBuilder.loadCode(lookup, "wither" + sourceClass().getName() + ":" + name, ... Should be: result = MethodHandleBuilder.loadCode(boxLookup, mhName("wither$" + name) On 06/06/2017 04:44 AM, maurizio.cimadamore at oracle.com wrote: > Changeset: 0cb6a562cbbf > Author: mcimadamore > Date: 2017-06-06 12:39 +0100 > URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/0cb6a562cbbf > > Add support for Q-types to lambda forms > Note: support is optional, and can be enabled using the flag: > -Dvalhalla.enableValueLambdaForms=true > > ! src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java > ! src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java > ! src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java > ! src/java.base/share/classes/java/lang/invoke/LambdaForm.java > + src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java > ! src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java > ! src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java > ! src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java > ! src/java.base/share/classes/jdk/experimental/value/ValueType.java > ! test/valhalla/mvt/MVTTest.java > -- Best regards, Sergey Kuksenko From paul.sandoz at oracle.com Tue Jun 13 21:10:13 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 13 Jun 2017 14:10:13 -0700 Subject: hg: valhalla/valhalla/jdk: Add support for Q-types to lambda forms In-Reply-To: <59733b95-fc38-0ed8-5feb-b360596abdfb@oracle.com> References: <201706061144.v56Bi3F6023370@aojmv0008.oracle.com> <59733b95-fc38-0ed8-5feb-b360596abdfb@oracle.com> Message-ID: <2037CDA6-E21C-4D40-B190-891AF9855BCC@oracle.com> Sergey, Do you have commit rights? If not i can commit this. Paul. > On 13 Jun 2017, at 13:04, Sergey Kuksenko wrote: > > Maurizio, > > When you did that commit you accidentally rewrote previous commit which fixed names of generated classes. > That causes ValueType.getWither doesn't work with value types other than from default package. > > Your code (see method getWither): > > result = MethodHandleBuilder.loadCode(lookup, "wither" + sourceClass().getName() + ":" + name, ... > > Should be: > > result = MethodHandleBuilder.loadCode(boxLookup, mhName("wither$" + name) > > > > On 06/06/2017 04:44 AM, maurizio.cimadamore at oracle.com wrote: >> Changeset: 0cb6a562cbbf >> Author: mcimadamore >> Date: 2017-06-06 12:39 +0100 >> URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/0cb6a562cbbf >> >> Add support for Q-types to lambda forms >> Note: support is optional, and can be enabled using the flag: >> -Dvalhalla.enableValueLambdaForms=true >> >> ! src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java >> ! src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java >> ! src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java >> ! src/java.base/share/classes/java/lang/invoke/LambdaForm.java >> + src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >> ! src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java >> ! src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java >> ! src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >> ! src/java.base/share/classes/jdk/experimental/value/ValueType.java >> ! test/valhalla/mvt/MVTTest.java >> > > -- > Best regards, > Sergey Kuksenko > From paul.sandoz at oracle.com Tue Jun 13 21:37:52 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 13 Jun 2017 14:37:52 -0700 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> Message-ID: <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> > On 13 Jun 2017, at 08:39, Roland Westrelin wrote: > > >> Below is a simple test class. Unfortunately running this crashes the VM. > Thanks for fixing HS, the test works for me now. > Thanks for putting the test together. C2 fails to inline much of > anything... > > 2131 126 GWTTest::run_Q_helper (16 bytes) > @ 10 java.lang.invoke.LambdaForm$MH/499105359::invoke_MT (28 bytes) force inline by annotation > @ 9 java.lang.invoke.Invokers::checkGenericType (6 bytes) force inline by annotation > @ 2 java.lang.invoke.MethodHandle::asType (28 bytes) inline (hot) > @ 12 java.lang.invoke.MethodHandle::asTypeCached (21 bytes) inline (hot) > @ 24 java.lang.invoke.MethodHandle::asTypeUncached (59 bytes) too big > @ 16 java.lang.invoke.Invokers::checkCustomized (23 bytes) force inline by annotation > @ 1 java.lang.invoke.MethodHandleImpl::isCompileConstant (2 bytes) (intrinsic) > @ 19 java.lang.invoke.Invokers::maybeCustomize (28 bytes) don't inline by annotation > @ 24 java.lang.invoke.MethodHandle::invokeBasic(LLI)L (0 bytes) receiver not constant > The is due to the call to invoke, which performs an asType transformation and thus the receiver is not constant. Same happens for L-based test, which if i change to use invokeExact (or a method sig that exactly matches the target) then inlining works: 1174 121 % GWTTest::run_L @ 4 (39 bytes) @ 1 java.lang.invoke.MethodHandle::type (5 bytes) accessor @ 20 java.lang.invoke.LambdaForm$MH020/2053442577::invokeExact_MT000_LLLIL_L (26 bytes) force inline by annotation @ 11 java.lang.invoke.Invokers::checkExactType (17 bytes) force inline by annotation @ 1 java.lang.invoke.MethodHandle::type (5 bytes) accessor @ 15 java.lang.invoke.Invokers::checkCustomized (23 bytes) force inline by annotation @ 1 java.lang.invoke.MethodHandleImpl::isCompileConstant (2 bytes) (intrinsic) @ 22 java.lang.invoke.LambdaForm$MH021/731128490::guard001_LLLI_L (114 bytes) force inline by annotation @ 7 java.lang.invoke.MethodHandleImpl::assertSame (49 bytes) inline (hot) @ 48 java.lang.invoke.LambdaForm$MH013/372289727::invoke010_LLLI_I (18 bytes) force inline by annotation @ 14 java.lang.invoke.DirectMethodHandle$Holder::invokeStatic (13 bytes) force inline by annotation @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) force inline by annotation @ 9 GWTTest::test (2 bytes) inline (hot) ! @ 62 java.lang.invoke.MethodHandleImpl::profileBoolean (34 bytes) (intrinsic) @ 110 java.lang.invoke.DelegatingMethodHandle$Holder::delegate (21 bytes) force inline by annotation @ 4 java.lang.invoke.MethodHandleImpl$CountingWrapper::getTarget (5 bytes) accessor @ 17 java.lang.invoke.LambdaForm$MH017/606100753::invoke012_LLLI_L (20 bytes) force inline by annotation @ 16 java.lang.invoke.DirectMethodHandle$Holder::invokeStatic (15 bytes) force inline by annotation @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) force inline by annotation @ 11 java.lang.invoke.MethodHandleImpl$ArrayAccessor::getElementL (4 bytes) inline (hot) The Q-based GWT form does not appear to show up in C2 compilation. Furthermore, the L-based GWT code generation has an intrinsic for byte code inlining the select alternative (including annotating the method with InjectedProfile). The Q-based code generator needs parity with such intrinsics. So even if we get to the point of getting better compilation behaviour we may run into other problems. I?ll poke around some more... Paul. > with: > > static V run_Q_helper() throws Throwable { > V v = (V) Q_MH_GWT.invoke(Q_V1_ARRAY, Q_V2_ARRAY, 0); > return v; > } > > static int run_Q() throws Throwable { > int sum = 0; > for (int i = 0; i < 100_000; i++) { > V v = run_Q_helper(); > sum += v.x; > } > return sum; > } > > Roland. From maurizio.cimadamore at oracle.com Tue Jun 13 22:50:00 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 13 Jun 2017 23:50:00 +0100 Subject: hg: valhalla/valhalla/jdk: Add support for Q-types to lambda forms In-Reply-To: <2037CDA6-E21C-4D40-B190-891AF9855BCC@oracle.com> References: <201706061144.v56Bi3F6023370@aojmv0008.oracle.com> <59733b95-fc38-0ed8-5feb-b360596abdfb@oracle.com> <2037CDA6-E21C-4D40-B190-891AF9855BCC@oracle.com> Message-ID: I agree that seems wrong - please let me know if you need me to push the fix, or if you wanna do it. Maurizio On 13/06/17 22:10, Paul Sandoz wrote: > Sergey, > > Do you have commit rights? If not i can commit this. > > Paul. > > >> On 13 Jun 2017, at 13:04, Sergey Kuksenko wrote: >> >> Maurizio, >> >> When you did that commit you accidentally rewrote previous commit which fixed names of generated classes. >> That causes ValueType.getWither doesn't work with value types other than from default package. >> >> Your code (see method getWither): >> >> result = MethodHandleBuilder.loadCode(lookup, "wither" + sourceClass().getName() + ":" + name, ... >> >> Should be: >> >> result = MethodHandleBuilder.loadCode(boxLookup, mhName("wither$" + name) >> >> >> >> On 06/06/2017 04:44 AM, maurizio.cimadamore at oracle.com wrote: >>> Changeset: 0cb6a562cbbf >>> Author: mcimadamore >>> Date: 2017-06-06 12:39 +0100 >>> URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/0cb6a562cbbf >>> >>> Add support for Q-types to lambda forms >>> Note: support is optional, and can be enabled using the flag: >>> -Dvalhalla.enableValueLambdaForms=true >>> >>> ! src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java >>> ! src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java >>> ! src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java >>> ! src/java.base/share/classes/java/lang/invoke/LambdaForm.java >>> + src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >>> ! src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java >>> ! src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java >>> ! src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >>> ! src/java.base/share/classes/jdk/experimental/value/ValueType.java >>> ! test/valhalla/mvt/MVTTest.java >>> >> -- >> Best regards, >> Sergey Kuksenko >> From paul.sandoz at oracle.com Tue Jun 13 23:05:11 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 13 Jun 2017 16:05:11 -0700 Subject: RFR improving the dumping of class files Message-ID: <4D2A9334-C7FA-47C7-98B2-6FE2B1BAC58B@oracle.com> The LambdaFormBuilder has the ability to dump class files but it overwrites previously generated files for the same invoker sub-name. - dumping uses the same property and technique as that for InvokerBytecodeGenerator. - anon Q-based LF classes are created under the class prefix "java/lang/invoke/LambdaForm$Value$?, sp L-based and Q-based LF byte codes are generated under the same directory. - when dumping the method name (which is unique for debugging, since dumping is considered debugging) is appended to the class name, making the files more identifiable (this is not something done for L-based LF classes, which i think we should change upstream). Paul. diff -r ff94d67133d3 src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java --- a/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java Tue Jun 13 14:54:26 2017 -0700 +++ b/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java Tue Jun 13 15:55:37 2017 -0700 @@ -56,10 +56,10 @@ /** * Utility class for spinning classfiles associated with lambda forms. */ -public class LambdaFormBuilder extends MethodHandleBuilder { +class LambdaFormBuilder extends MethodHandleBuilder { private static final String OBJ = "java/lang/Object"; - private static final String CLASS_PREFIX = "LambdaForm$"; + private static final String CLASS_PREFIX = "java/lang/invoke/LambdaForm$Value$"; private static final String DEFAULT_CLASS = "MH"; private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";"; @@ -71,6 +71,10 @@ String className = overrideNames ? CLASS_PREFIX + invokerName.substring(0, p) : CLASS_PREFIX + DEFAULT_CLASS; + if (MinimalValueTypes_1_0.DUMP_CLASS_FILES) { + // When DUMP_CLASS_FILES is true methodName will have a unique id + className = className + "_" + methodName; + } return MethodHandleBuilder.loadCode(Lookup.IMPL_LOOKUP.in(LambdaForm.class), className, methodName, invokerType.toMethodDescriptorString(), M -> new LambdaFormCodeBuilder(form, M), clazz -> InvokerBytecodeGenerator.resolveInvokerMember(clazz, methodName, invokerType), C -> new LambdaFormBuilder(C, form, invokerType).generateLambdaFormBody()); diff -r ff94d67133d3 src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java --- a/src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java Tue Jun 13 14:54:26 2017 -0700 +++ b/src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java Tue Jun 13 15:55:37 2017 -0700 @@ -24,20 +24,18 @@ */ package valhalla.shady; +import jdk.experimental.bytecode.BasicClassBuilder; +import jdk.internal.misc.Unsafe; +import sun.security.action.GetPropertyAction; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.security.AccessController; import java.security.ProtectionDomain; -import java.util.PropertyPermission; - -import jdk.experimental.bytecode.BasicClassBuilder; +import java.util.Properties; import static jdk.internal.org.objectweb.asm.Opcodes.*; -import jdk.internal.misc.Unsafe; -import sun.security.action.GetPropertyAction; - public class MinimalValueTypes_1_0 { public static final int V53_1 = 1 << 16 | 53; @@ -48,14 +46,14 @@ public static final String DERIVE_VALUE_TYPE_DESC = "Ljvm/internal/value/DeriveValueType;"; public static final String DERIVE_VT_CLASSNAME_POSTFIX = "$Value"; public static final int DERIVE_VT_CLASS_ACCESS = ACC_PUBLIC|ACC_SUPER|ACC_FINAL|ACC_VALUE|ACC_SYNTHETIC; - public static String DUMP_CLASS_FILES_DIR; + + public static final boolean DUMP_CLASS_FILES; static { - final String key = "valhalla.dumpProxyClasses"; - DUMP_CLASS_FILES_DIR = key == null ? null : - AccessController.doPrivileged( - new GetPropertyAction(key), null, - new PropertyPermission(key , "read")); + // Use same property as in j.l.invoke.MethodHandleStatics + Properties props = GetPropertyAction.privilegedGetProperties(); + DUMP_CLASS_FILES = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES")); } public static String getValueTypeClassName(ValueTypeDesc valueTypeDesc) { @@ -137,8 +135,27 @@ return newBytes; } + /** debugging flag for saving generated class files */ + private static final File DUMP_CLASS_FILES_DIR; + + static { + if (DUMP_CLASS_FILES) { + try { + File dumpDir = new File("DUMP_CLASS_FILES"); + if (!dumpDir.exists()) { + dumpDir.mkdirs(); + } + DUMP_CLASS_FILES_DIR = dumpDir; + } catch (Exception e) { + throw new InternalError(e); + } + } else { + DUMP_CLASS_FILES_DIR = null; + } + } + public static void maybeDump(final String className, final byte[] classFile) { - if (DUMP_CLASS_FILES_DIR != null) { + if (DUMP_CLASS_FILES) { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<>() { public Void run() { @@ -146,13 +163,14 @@ String dumpName = className; //dumpName = dumpName.replace('/', '-'); File dumpFile = new File(DUMP_CLASS_FILES_DIR, dumpName+".class"); + System.out.println("dump: " + dumpFile); dumpFile.getParentFile().mkdirs(); FileOutputStream file = new FileOutputStream(dumpFile); file.write(classFile); file.close(); return null; } catch (IOException ex) { - throw new IllegalStateException(ex); + throw new InternalError(ex); } } }); From maurizio.cimadamore at oracle.com Tue Jun 13 23:13:15 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 14 Jun 2017 00:13:15 +0100 Subject: RFR improving the dumping of class files In-Reply-To: <4D2A9334-C7FA-47C7-98B2-6FE2B1BAC58B@oracle.com> References: <4D2A9334-C7FA-47C7-98B2-6FE2B1BAC58B@oracle.com> Message-ID: Looks good Thanks Maurizio On 14/06/17 00:05, Paul Sandoz wrote: > The LambdaFormBuilder has the ability to dump class files but it overwrites previously generated files for the same invoker sub-name. > > - dumping uses the same property and technique as that for InvokerBytecodeGenerator. > > - anon Q-based LF classes are created under the class prefix "java/lang/invoke/LambdaForm$Value$?, sp L-based and Q-based LF byte codes are generated under the same directory. > > - when dumping the method name (which is unique for debugging, since dumping is considered debugging) is appended to the class name, making the files more identifiable (this is not something done for L-based LF classes, which i think we should change upstream). > > Paul. > > > diff -r ff94d67133d3 src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java > --- a/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java Tue Jun 13 14:54:26 2017 -0700 > +++ b/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java Tue Jun 13 15:55:37 2017 -0700 > @@ -56,10 +56,10 @@ > /** > * Utility class for spinning classfiles associated with lambda forms. > */ > -public class LambdaFormBuilder extends MethodHandleBuilder { > +class LambdaFormBuilder extends MethodHandleBuilder { > > private static final String OBJ = "java/lang/Object"; > - private static final String CLASS_PREFIX = "LambdaForm$"; > + private static final String CLASS_PREFIX = "java/lang/invoke/LambdaForm$Value$"; > private static final String DEFAULT_CLASS = "MH"; > private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";"; > > @@ -71,6 +71,10 @@ > String className = overrideNames ? > CLASS_PREFIX + invokerName.substring(0, p) : > CLASS_PREFIX + DEFAULT_CLASS; > + if (MinimalValueTypes_1_0.DUMP_CLASS_FILES) { > + // When DUMP_CLASS_FILES is true methodName will have a unique id > + className = className + "_" + methodName; > + } > return MethodHandleBuilder.loadCode(Lookup.IMPL_LOOKUP.in(LambdaForm.class), className, methodName, invokerType.toMethodDescriptorString(), > M -> new LambdaFormCodeBuilder(form, M), clazz -> InvokerBytecodeGenerator.resolveInvokerMember(clazz, methodName, invokerType), > C -> new LambdaFormBuilder(C, form, invokerType).generateLambdaFormBody()); > diff -r ff94d67133d3 src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java > --- a/src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java Tue Jun 13 14:54:26 2017 -0700 > +++ b/src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java Tue Jun 13 15:55:37 2017 -0700 > @@ -24,20 +24,18 @@ > */ > package valhalla.shady; > > +import jdk.experimental.bytecode.BasicClassBuilder; > +import jdk.internal.misc.Unsafe; > +import sun.security.action.GetPropertyAction; > + > import java.io.File; > import java.io.FileOutputStream; > import java.io.IOException; > -import java.security.AccessController; > import java.security.ProtectionDomain; > -import java.util.PropertyPermission; > - > -import jdk.experimental.bytecode.BasicClassBuilder; > +import java.util.Properties; > > import static jdk.internal.org.objectweb.asm.Opcodes.*; > > -import jdk.internal.misc.Unsafe; > -import sun.security.action.GetPropertyAction; > - > public class MinimalValueTypes_1_0 { > > public static final int V53_1 = 1 << 16 | 53; > @@ -48,14 +46,14 @@ > public static final String DERIVE_VALUE_TYPE_DESC = "Ljvm/internal/value/DeriveValueType;"; > public static final String DERIVE_VT_CLASSNAME_POSTFIX = "$Value"; > public static final int DERIVE_VT_CLASS_ACCESS = ACC_PUBLIC|ACC_SUPER|ACC_FINAL|ACC_VALUE|ACC_SYNTHETIC; > - public static String DUMP_CLASS_FILES_DIR; > + > + public static final boolean DUMP_CLASS_FILES; > > static { > - final String key = "valhalla.dumpProxyClasses"; > - DUMP_CLASS_FILES_DIR = key == null ? null : > - AccessController.doPrivileged( > - new GetPropertyAction(key), null, > - new PropertyPermission(key , "read")); > + // Use same property as in j.l.invoke.MethodHandleStatics > + Properties props = GetPropertyAction.privilegedGetProperties(); > + DUMP_CLASS_FILES = Boolean.parseBoolean( > + props.getProperty("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES")); > } > > public static String getValueTypeClassName(ValueTypeDesc valueTypeDesc) { > @@ -137,8 +135,27 @@ > return newBytes; > } > > + /** debugging flag for saving generated class files */ > + private static final File DUMP_CLASS_FILES_DIR; > + > + static { > + if (DUMP_CLASS_FILES) { > + try { > + File dumpDir = new File("DUMP_CLASS_FILES"); > + if (!dumpDir.exists()) { > + dumpDir.mkdirs(); > + } > + DUMP_CLASS_FILES_DIR = dumpDir; > + } catch (Exception e) { > + throw new InternalError(e); > + } > + } else { > + DUMP_CLASS_FILES_DIR = null; > + } > + } > + > public static void maybeDump(final String className, final byte[] classFile) { > - if (DUMP_CLASS_FILES_DIR != null) { > + if (DUMP_CLASS_FILES) { > java.security.AccessController.doPrivileged( > new java.security.PrivilegedAction<>() { > public Void run() { > @@ -146,13 +163,14 @@ > String dumpName = className; > //dumpName = dumpName.replace('/', '-'); > File dumpFile = new File(DUMP_CLASS_FILES_DIR, dumpName+".class"); > + System.out.println("dump: " + dumpFile); > dumpFile.getParentFile().mkdirs(); > FileOutputStream file = new FileOutputStream(dumpFile); > file.write(classFile); > file.close(); > return null; > } catch (IOException ex) { > - throw new IllegalStateException(ex); > + throw new InternalError(ex); > } > } > }); > From paul.sandoz at oracle.com Tue Jun 13 23:36:10 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 13 Jun 2017 16:36:10 -0700 Subject: couple questions on method handle combinators In-Reply-To: <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> Message-ID: In an attempt to simplify the test and to try and obtain invokeExact semantics for inlining i created a new test. This one crashes the VM :-) Paul. # Internal Error (/Users/sandoz/Projects/jdk10/valhalla/hotspot/src/share/vm/opto/type.cpp:2084), pid=59955, tid=26883 # assert(type != ciEnv::current()->___Value_klass()) failed: unsupported ... Current CompileTask: C2: 4213 353 % GWTTest::run_Q @ 4 (29 bytes) Stack: [0x000000011bbbd000,0x000000011bcbd000], sp=0x000000011bcb9d60, free space=1011k Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code) V [libjvm.dylib+0xc9ac54] VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x4d4 V [libjvm.dylib+0xc9b416] VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x4a V [libjvm.dylib+0x4cc1e1] report_vm_error(char const*, int, char const*, char const*, ...)+0xcd V [libjvm.dylib+0xc3fe07] TypeTuple::make_domain(ciInstanceKlass*, ciSignature*, bool)+0x307 V [libjvm.dylib+0xc48c5a] TypeFunc::make(ciMethod*)+0x52 V [libjvm.dylib+0x6520bd] GraphKit::round_double_arguments(ciMethod*)+0x1d V [libjvm.dylib+0x551a4c] Parse::do_call()+0x568 V [libjvm.dylib+0xac7f82] Parse::do_one_bytecode()+0xf4 V [libjvm.dylib+0xabb98f] Parse::do_one_block()+0x35f V [libjvm.dylib+0xaba470] Parse::do_all_blocks()+0x428 V [libjvm.dylib+0xab704c] Parse::Parse(JVMState*, ciMethod*, float)+0xa1e V [libjvm.dylib+0x350cfc] ParseGenerator::generate(JVMState*)+0xb6 V [libjvm.dylib+0x551bac] Parse::do_call()+0x6c8 V [libjvm.dylib+0xac7f82] Parse::do_one_bytecode()+0xf4 V [libjvm.dylib+0xabb98f] Parse::do_one_block()+0x35f V [libjvm.dylib+0xaba470] Parse::do_all_blocks()+0x428 V [libjvm.dylib+0xab704c] Parse::Parse(JVMState*, ciMethod*, float)+0xa1e V [libjvm.dylib+0x350cfc] ParseGenerator::generate(JVMState*)+0xb6 V [libjvm.dylib+0x551bac] Parse::do_call()+0x6c8 V [libjvm.dylib+0xac7f82] Parse::do_one_bytecode()+0xf4 V [libjvm.dylib+0xabb98f] Parse::do_one_block()+0x35f V [libjvm.dylib+0xaba470] Parse::do_all_blocks()+0x428 V [libjvm.dylib+0xab704c] Parse::Parse(JVMState*, ciMethod*, float)+0xa1e V [libjvm.dylib+0x350cfc] ParseGenerator::generate(JVMState*)+0xb6 V [libjvm.dylib+0x46554e] Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool, DirectiveSet*)+0x8c8 V [libjvm.dylib+0x46857b] Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool, DirectiveSet*)+0x31 V [libjvm.dylib+0x34f680] C2Compiler::compile_method(ciEnv*, ciMethod*, int, DirectiveSet*)+0x130 /* * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @run testng/othervm * -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true * -Dvalhalla.enablePoolPatches=true * -Xverify:none * -XX:-TieredCompilation * -XX:+EnableMVT * -XX:+ValueArrayFlatten * -XX:+ValueTypePassFieldsAsArgs * -XX:+ValueTypeReturnedAsFields * -XX:+VerifyAdapterSharing * -XX:+EnableValhalla * -XX:ValueArrayElemMaxFlatSize=-1 * -XX:ValueArrayElemMaxFlatOops=-1 * -XX:+FullGCALotWithValueTypes * GWTTest */ /* * -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions * -XX:-TieredCompilation * -XX:+EnableMVT * -XX:+ValueArrayFlatten * -XX:+ValueTypePassFieldsAsArgs * -XX:+ValueTypeReturnedAsFields * -XX:+VerifyAdapterSharing * -XX:+EnableValhalla * -XX:ValueArrayElemMaxFlatSize=-1 * -XX:ValueArrayElemMaxFlatOops=-1 * -XX:+FullGCALotWithValueTypes */ import jdk.experimental.value.ValueType; import org.testng.annotations.Test; import valhalla.shady.MinimalValueTypes_1_0; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Objects; public class GWTTest { @jvm.internal.value.DeriveValueType static final class V { final int x; final int y; public V(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; V v = (V) o; return x == v.x && y == v.y; } @Override public int hashCode() { return Objects.hash(x, y); } @Override public String toString() { final StringBuffer sb = new StringBuffer(this.getClass().getSimpleName()); sb.append("{"); sb.append("x=").append(x); sb.append(", y=").append(y); sb.append('}'); return sb.toString(); } } static final ValueType VT = ValueType.forClass(V.class); static final Class DVT; static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); static final V V1 = new V(1, 1); static final V V2 = new V(2, 2); static final MethodHandle Q_MH_GWT; static final MethodHandle L_MH_GWT; static { try { DVT = MinimalValueTypes_1_0.getValueTypeClass(V.class); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } try { MethodHandle v1 = LOOKUP.findStatic(GWTTest.class, "v1", MethodType.methodType(V.class)); MethodHandle v2 = LOOKUP.findStatic(GWTTest.class, "v2", MethodType.methodType(V.class)); MethodHandle test = LOOKUP.findStatic(GWTTest.class, "test", MethodType.methodType(boolean.class)); MethodHandle v_unbox = VT.unbox(); MethodHandle q_gwt = MethodHandles.guardWithTest( test, MethodHandles.filterReturnValue(v1, v_unbox), MethodHandles.filterReturnValue(v2, v_unbox) ); Q_MH_GWT = MethodHandles.filterReturnValue( q_gwt, VT.findGetter(LOOKUP, "x", int.class)); MethodHandle l_gwt = MethodHandles.guardWithTest( test, v1, v2 ); L_MH_GWT = MethodHandles.filterReturnValue( l_gwt, LOOKUP.findGetter(V.class, "x", int.class)); } catch (Throwable e) { throw new RuntimeException(e); } } static boolean test() { return false; } static V v1() { return V1; } static V v2() { return V2; } static int run_Q() throws Throwable { int sum = 0; for (int i = 0; i < 100_000; i++) { int v = (int) Q_MH_GWT.invokeExact(); sum += v; } return sum; } @Test public void testGWT_Q() throws Throwable { int r = run_Q(); System.out.println(r); } static int run_L() throws Throwable { int sum = 0; for (int i = 0; i < 100_000; i++) { int v = (int) L_MH_GWT.invokeExact(); sum += v; } return sum; } @Test public void testGWT_L() throws Throwable { int r = run_L(); System.out.println(r); } public static void main(String[] args) throws Throwable { GWTTest t = new GWTTest(); t.testGWT_L(); t.testGWT_Q(); } } From paul.sandoz at oracle.com Tue Jun 13 23:42:02 2017 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Tue, 13 Jun 2017 23:42:02 +0000 Subject: hg: valhalla/valhalla/jdk: Dump classes from LambdaFormBuilder is triggered using Message-ID: <201706132342.v5DNg2MF006355@aojmv0008.oracle.com> Changeset: 738587234617 Author: psandoz Date: 2017-06-13 16:40 -0700 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/738587234617 Dump classes from LambdaFormBuilder is triggered using MethodHandleStatics.DUMP_CLASS_FILES. Class names are extended by the LF invoker name (which should be unique) when debugging (dumping triggers debugging). ! src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java ! src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java From paul.sandoz at oracle.com Tue Jun 13 23:51:42 2017 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Tue, 13 Jun 2017 23:51:42 +0000 Subject: hg: valhalla/valhalla/jdk: Fix bug in ValueType.wither class name. Message-ID: <201706132351.v5DNpgPv013105@aojmv0008.oracle.com> Changeset: 1c84e48a3b95 Author: skuksenko Date: 2017-06-13 16:49 -0700 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/1c84e48a3b95 Fix bug in ValueType.wither class name. ! src/java.base/share/classes/jdk/experimental/value/ValueType.java From paul.sandoz at oracle.com Tue Jun 13 23:50:33 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 13 Jun 2017 16:50:33 -0700 Subject: hg: valhalla/valhalla/jdk: Add support for Q-types to lambda forms In-Reply-To: <59733b95-fc38-0ed8-5feb-b360596abdfb@oracle.com> References: <201706061144.v56Bi3F6023370@aojmv0008.oracle.com> <59733b95-fc38-0ed8-5feb-b360596abdfb@oracle.com> Message-ID: <3A7C7FAF-A09C-471E-BB55-46A032BCD1F5@oracle.com> Pushed. Paul. > On 13 Jun 2017, at 13:04, Sergey Kuksenko wrote: > > Maurizio, > > When you did that commit you accidentally rewrote previous commit which fixed names of generated classes. > That causes ValueType.getWither doesn't work with value types other than from default package. > > Your code (see method getWither): > > result = MethodHandleBuilder.loadCode(lookup, "wither" + sourceClass().getName() + ":" + name, ... > > Should be: > > result = MethodHandleBuilder.loadCode(boxLookup, mhName("wither$" + name) > > > > On 06/06/2017 04:44 AM, maurizio.cimadamore at oracle.com wrote: >> Changeset: 0cb6a562cbbf >> Author: mcimadamore >> Date: 2017-06-06 12:39 +0100 >> URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/0cb6a562cbbf >> >> Add support for Q-types to lambda forms >> Note: support is optional, and can be enabled using the flag: >> -Dvalhalla.enableValueLambdaForms=true >> >> ! src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java >> ! src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java >> ! src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java >> ! src/java.base/share/classes/java/lang/invoke/LambdaForm.java >> + src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >> ! src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java >> ! src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java >> ! src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >> ! src/java.base/share/classes/jdk/experimental/value/ValueType.java >> ! test/valhalla/mvt/MVTTest.java >> > > -- > Best regards, > Sergey Kuksenko > From zoltan.majo at oracle.com Wed Jun 14 10:55:04 2017 From: zoltan.majo at oracle.com (=?UTF-8?B?Wm9sdMOhbiBNYWrDsw==?=) Date: Wed, 14 Jun 2017 12:55:04 +0200 Subject: RFR (M): Add missing compiler checks Message-ID: <7e8c8c01-1d38-493d-dec8-a9eefa7abd52@oracle.com> Hi, please review the following change: http://cr.openjdk.java.net/~zmajo/valhalla/04.checks/webrev.00/ The change adds some (or hopefully all) checks that C2 currently does not generate but will most likely be required by the MVT specification. I tested the change with JPRT (x86_64), no failures have appeared. I'm currently running the hotspot/compiler JTREG tests locally. A few notes about the change: - Moving _element_klass from ObjArrayKlass to ArrayKlass is necessary because that way the klass of the array elements is found at the same offset in both ObjArrayKlass and ValueArrayKlass instances (and we need the offset to implement type checks). However, _element_klass is now present in TypeArrayKlass as well (where it is not needed). Maybe a better way to organize the class hierarchy would be to put _element_klass into a new common subclass X of [Obj|Value]ArrayClass; both X and TypeArrayKlass would then be direct subclasses of ArrayKlass. Maybe it's better to deal with this aspect once the we're closer to the final specification/design of MVT. - The change adds a type check to InterpreterRuntime::value_array_store. I assumed (and expect) vastore will behave similarly to aastore and requires the element type of src/dst to match. Please let me know if that is an incorrect assumption. - The bytecodes vdefault/vwithfield can throw an OutOfMemoryError if no space is available for allocation. With the current C2 implementation allocations can be delayed to a later point in the program (e.g., when a deoptimization happens). If no free memory is available at that point to allocate memory for a value type, the OOME will appear later than the vdefault/vwithfield bytecode that actually caused it. Tobias and I discussed about this aspect and it's likely that this is not a problem as re-allocation of scalar-replaced objects is similar and is also performed at deoptimization. However, more investigation is needed to confirm that. Thank you! Best regards, Zoltan From maurizio.cimadamore at oracle.com Wed Jun 14 11:16:51 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 14 Jun 2017 12:16:51 +0100 Subject: hg: valhalla/valhalla/jdk: Add support for Q-types to lambda forms In-Reply-To: <3A7C7FAF-A09C-471E-BB55-46A032BCD1F5@oracle.com> References: <201706061144.v56Bi3F6023370@aojmv0008.oracle.com> <59733b95-fc38-0ed8-5feb-b360596abdfb@oracle.com> <3A7C7FAF-A09C-471E-BB55-46A032BCD1F5@oracle.com> Message-ID: Thanks Maurizio On 14/06/17 00:50, Paul Sandoz wrote: > Pushed. > > Paul. > >> On 13 Jun 2017, at 13:04, Sergey Kuksenko wrote: >> >> Maurizio, >> >> When you did that commit you accidentally rewrote previous commit which fixed names of generated classes. >> That causes ValueType.getWither doesn't work with value types other than from default package. >> >> Your code (see method getWither): >> >> result = MethodHandleBuilder.loadCode(lookup, "wither" + sourceClass().getName() + ":" + name, ... >> >> Should be: >> >> result = MethodHandleBuilder.loadCode(boxLookup, mhName("wither$" + name) >> >> >> >> On 06/06/2017 04:44 AM, maurizio.cimadamore at oracle.com wrote: >>> Changeset: 0cb6a562cbbf >>> Author: mcimadamore >>> Date: 2017-06-06 12:39 +0100 >>> URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/0cb6a562cbbf >>> >>> Add support for Q-types to lambda forms >>> Note: support is optional, and can be enabled using the flag: >>> -Dvalhalla.enableValueLambdaForms=true >>> >>> ! src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java >>> ! src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java >>> ! src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java >>> ! src/java.base/share/classes/java/lang/invoke/LambdaForm.java >>> + src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >>> ! src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java >>> ! src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java >>> ! src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >>> ! src/java.base/share/classes/jdk/experimental/value/ValueType.java >>> ! test/valhalla/mvt/MVTTest.java >>> >> -- >> Best regards, >> Sergey Kuksenko >> From david.simms at oracle.com Wed Jun 14 11:53:42 2017 From: david.simms at oracle.com (David Simms) Date: Wed, 14 Jun 2017 13:53:42 +0200 Subject: RFR (M): Add missing compiler checks In-Reply-To: <7e8c8c01-1d38-493d-dec8-a9eefa7abd52@oracle.com> References: <7e8c8c01-1d38-493d-dec8-a9eefa7abd52@oracle.com> Message-ID: <6ee16239-a6cb-85a7-d6a6-65d8fdfb93c7@oracle.com> The changes to "src/share/vm/oops/*" and "src/share/vm/interpreter/interpreterRuntime.cpp" look good. One nit-pick is the use of C cast to "ValueKlass*" rather than "ValueKlass::cast()" like we generally do for Klass casting. The extra field in TypeArrayKlass is minimal, given the fixed number of types (even with multi-dim). Thanks for the extra klass check in vastore, btw ! Cheers /David Simms On 14/06/17 12:55, Zolt?n Maj? wrote: > Hi, > > > please review the following change: > http://cr.openjdk.java.net/~zmajo/valhalla/04.checks/webrev.00/ > > The change adds some (or hopefully all) checks that C2 currently does > not generate but will most likely be required by the MVT > specification. I tested the change with JPRT (x86_64), no failures > have appeared. I'm currently running the hotspot/compiler JTREG tests > locally. > > A few notes about the change: > > - Moving _element_klass from ObjArrayKlass to ArrayKlass is necessary > because that way the klass of the array elements is found at the same > offset in both ObjArrayKlass and ValueArrayKlass instances (and we > need the offset to implement type checks). However, _element_klass is > now present in TypeArrayKlass as well (where it is not needed). Maybe > a better way to organize the class hierarchy would be to put > _element_klass into a new common subclass X of [Obj|Value]ArrayClass; > both X and TypeArrayKlass would then be direct subclasses of > ArrayKlass. Maybe it's better to deal with this aspect once the we're > closer to the final specification/design of MVT. > > - The change adds a type check to > InterpreterRuntime::value_array_store. I assumed (and expect) vastore > will behave similarly to aastore and requires the element type of > src/dst to match. Please let me know if that is an incorrect assumption. > > - The bytecodes vdefault/vwithfield can throw an OutOfMemoryError if > no space is available for allocation. With the current C2 > implementation allocations can be delayed to a later point in the > program (e.g., when a deoptimization happens). If no free memory is > available at that point to allocate memory for a value type, the OOME > will appear later than the vdefault/vwithfield bytecode that actually > caused it. Tobias and I discussed about this aspect and it's likely > that this is not a problem as re-allocation of scalar-replaced objects > is similar and is also performed at deoptimization. However, more > investigation is needed to confirm that. > > Thank you! > > Best regards, > > > Zoltan > From tobias.hartmann at oracle.com Wed Jun 14 12:10:45 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Wed, 14 Jun 2017 14:10:45 +0200 Subject: RFR (M): Add missing compiler checks In-Reply-To: <7e8c8c01-1d38-493d-dec8-a9eefa7abd52@oracle.com> References: <7e8c8c01-1d38-493d-dec8-a9eefa7abd52@oracle.com> Message-ID: <5b55a814-e3a5-5c9f-96c6-ac6dfd46ae1b@oracle.com> Hi Zoltan, nice work! Here are some comments: - Why are the changes to bcEscapeAnalyzer.cpp necessary? - I don't like all the ValueKlass* casts. Couldn't we avoid them by making element_klass() virtual and returning ValueKlass* from ValueArrayKlass::element_klass() (covariant return)? Like this, we could also avoid the asserts in valueArrayKlass.hpp. - In parseHelper.cpp, why do we need a runtime check if we statically know that target_elem_klass != source_klass? - I think it would be good to add a test that mixes value type arrays with non value type stores (and the other way around) - Please add a comment to test83 and test84 Thanks, Tobias On 14.06.2017 12:55, Zolt?n Maj? wrote: > Hi, > > > please review the following change: > http://cr.openjdk.java.net/~zmajo/valhalla/04.checks/webrev.00/ > > The change adds some (or hopefully all) checks that C2 currently does not generate but will most likely be required by the MVT specification. I tested the change with JPRT (x86_64), no failures have appeared. I'm currently running the hotspot/compiler JTREG tests locally. > > A few notes about the change: > > - Moving _element_klass from ObjArrayKlass to ArrayKlass is necessary because that way the klass of the array elements is found at the same offset in both ObjArrayKlass and ValueArrayKlass instances (and we need the offset to implement type checks). However, _element_klass is now present in TypeArrayKlass as well (where it is not needed). Maybe a better way to organize the class hierarchy would be to put _element_klass into a new common subclass X of [Obj|Value]ArrayClass; both X and TypeArrayKlass would then be direct subclasses of ArrayKlass. Maybe it's better to deal with this aspect once the we're closer to the final specification/design of MVT. > > - The change adds a type check to InterpreterRuntime::value_array_store. I assumed (and expect) vastore will behave similarly to aastore and requires the element type of src/dst to match. Please let me know if that is an incorrect assumption. > > - The bytecodes vdefault/vwithfield can throw an OutOfMemoryError if no space is available for allocation. With the current C2 implementation allocations can be delayed to a later point in the program (e.g., when a deoptimization happens). If no free memory is available at that point to allocate memory for a value type, the OOME will appear later than the vdefault/vwithfield bytecode that actually caused it. Tobias and I discussed about this aspect and it's likely that this is not a problem as re-allocation of scalar-replaced objects is similar and is also performed at deoptimization. However, more investigation is needed to confirm that. > > Thank you! > > Best regards, > > > Zoltan > From rwestrel at redhat.com Wed Jun 14 13:53:37 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Wed, 14 Jun 2017 15:53:37 +0200 Subject: couple questions on method handle combinators In-Reply-To: <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> Message-ID: > The is due to the call to invoke, which performs an asType > transformation and thus the receiver is not constant. So it's effectively constant but the compiler can't see it? I had a patch that added profiling of that receiver value. It didn't seem to show any benefit at the time. I wonder it would make sense to experiment with something similar again. Roland. From zoltan.majo at oracle.com Wed Jun 14 15:16:48 2017 From: zoltan.majo at oracle.com (=?UTF-8?B?Wm9sdMOhbiBNYWrDsw==?=) Date: Wed, 14 Jun 2017 17:16:48 +0200 Subject: RFR (M): Add missing compiler checks In-Reply-To: <6ee16239-a6cb-85a7-d6a6-65d8fdfb93c7@oracle.com> References: <7e8c8c01-1d38-493d-dec8-a9eefa7abd52@oracle.com> <6ee16239-a6cb-85a7-d6a6-65d8fdfb93c7@oracle.com> Message-ID: <54f99fae-8dcc-c7f7-16f8-4a55f0fa0c7c@oracle.com> Hi, thank you for the review! On 06/14/2017 01:53 PM, David Simms wrote: > > The changes to "src/share/vm/oops/*" and > "src/share/vm/interpreter/interpreterRuntime.cpp" look good. > > One nit-pick is the use of C cast to "ValueKlass*" rather than > "ValueKlass::cast()" like we generally do for Klass casting. I changed element_klass to have covariant return types (as Tobias suggested). That removed the need for ValueKlass::cast()'s. > > The extra field in TypeArrayKlass is minimal, given the fixed number > of types (even with multi-dim). OK. > > Thanks for the extra klass check in vastore, btw ! Sure! I'll send the updated code in my reply to Tobias. Best regards, Zoltan > > Cheers > /David Simms > > > > On 14/06/17 12:55, Zolt?n Maj? wrote: >> Hi, >> >> >> please review the following change: >> http://cr.openjdk.java.net/~zmajo/valhalla/04.checks/webrev.00/ >> >> The change adds some (or hopefully all) checks that C2 currently does >> not generate but will most likely be required by the MVT >> specification. I tested the change with JPRT (x86_64), no failures >> have appeared. I'm currently running the hotspot/compiler JTREG tests >> locally. >> >> A few notes about the change: >> >> - Moving _element_klass from ObjArrayKlass to ArrayKlass is necessary >> because that way the klass of the array elements is found at the same >> offset in both ObjArrayKlass and ValueArrayKlass instances (and we >> need the offset to implement type checks). However, _element_klass is >> now present in TypeArrayKlass as well (where it is not needed). Maybe >> a better way to organize the class hierarchy would be to put >> _element_klass into a new common subclass X of [Obj|Value]ArrayClass; >> both X and TypeArrayKlass would then be direct subclasses of >> ArrayKlass. Maybe it's better to deal with this aspect once the we're >> closer to the final specification/design of MVT. >> >> - The change adds a type check to >> InterpreterRuntime::value_array_store. I assumed (and expect) vastore >> will behave similarly to aastore and requires the element type of >> src/dst to match. Please let me know if that is an incorrect assumption. >> >> - The bytecodes vdefault/vwithfield can throw an OutOfMemoryError if >> no space is available for allocation. With the current C2 >> implementation allocations can be delayed to a later point in the >> program (e.g., when a deoptimization happens). If no free memory is >> available at that point to allocate memory for a value type, the OOME >> will appear later than the vdefault/vwithfield bytecode that actually >> caused it. Tobias and I discussed about this aspect and it's likely >> that this is not a problem as re-allocation of scalar-replaced >> objects is similar and is also performed at deoptimization. However, >> more investigation is needed to confirm that. >> >> Thank you! >> >> Best regards, >> >> >> Zoltan >> > From zoltan.majo at oracle.com Wed Jun 14 15:37:04 2017 From: zoltan.majo at oracle.com (=?UTF-8?B?Wm9sdMOhbiBNYWrDsw==?=) Date: Wed, 14 Jun 2017 17:37:04 +0200 Subject: RFR (M): Add missing compiler checks In-Reply-To: <5b55a814-e3a5-5c9f-96c6-ac6dfd46ae1b@oracle.com> References: <7e8c8c01-1d38-493d-dec8-a9eefa7abd52@oracle.com> <5b55a814-e3a5-5c9f-96c6-ac6dfd46ae1b@oracle.com> Message-ID: Hi Tobias, thank you for the review! On 06/14/2017 02:10 PM, Tobias Hartmann wrote: > Hi Zoltan, > > nice work! Thank you. > > Here are some comments: > - Why are the changes to bcEscapeAnalyzer.cpp necessary? From a functional point of view, that change is not strictly necessary because T_VALUETYPE==T_OBJECT (that's the only difference between the handling of aastore and vastore). But maybe it's good to not use OBJECT in the code when we actually refer to a VT. I can also remove that change, if you want. > - I don't like all the ValueKlass* casts. Couldn't we avoid them by making element_klass() virtual and returning ValueKlass* from ValueArrayKlass::element_klass() (covariant return)? Like this, we could also avoid the asserts in valueArrayKlass.hpp. Thank you -- I did that and the code got simpler. > - In parseHelper.cpp, why do we need a runtime check if we statically know that target_elem_klass != source_klass? The two types may be unequal at compilation type but they can be equal at runtime. > - I think it would be good to add a test that mixes value type arrays with non value type stores (and the other way around) I tried (see, e.g., test85() below). Unfortunately, compilation fails. What I'm not sure about is whether the verifier should (and can) catch such issues or should we really handle it in the compiler. > - Please add a comment to test83 and test84 I did. Here is the updated code: http://cr.openjdk.java.net/~zmajo/valhalla/04.checks/webrev.01/ Testing is in progress. Best regards, Zoltan P.S.: Here is test85 I mentioned before: http://cr.openjdk.java.net/~zmajo/valhalla/04.checks/test85 > > Thanks, > Tobias > > On 14.06.2017 12:55, Zolt?n Maj? wrote: >> Hi, >> >> >> please review the following change: >> http://cr.openjdk.java.net/~zmajo/valhalla/04.checks/webrev.00/ >> >> The change adds some (or hopefully all) checks that C2 currently does not generate but will most likely be required by the MVT specification. I tested the change with JPRT (x86_64), no failures have appeared. I'm currently running the hotspot/compiler JTREG tests locally. >> >> A few notes about the change: >> >> - Moving _element_klass from ObjArrayKlass to ArrayKlass is necessary because that way the klass of the array elements is found at the same offset in both ObjArrayKlass and ValueArrayKlass instances (and we need the offset to implement type checks). However, _element_klass is now present in TypeArrayKlass as well (where it is not needed). Maybe a better way to organize the class hierarchy would be to put _element_klass into a new common subclass X of [Obj|Value]ArrayClass; both X and TypeArrayKlass would then be direct subclasses of ArrayKlass. Maybe it's better to deal with this aspect once the we're closer to the final specification/design of MVT. >> >> - The change adds a type check to InterpreterRuntime::value_array_store. I assumed (and expect) vastore will behave similarly to aastore and requires the element type of src/dst to match. Please let me know if that is an incorrect assumption. >> >> - The bytecodes vdefault/vwithfield can throw an OutOfMemoryError if no space is available for allocation. With the current C2 implementation allocations can be delayed to a later point in the program (e.g., when a deoptimization happens). If no free memory is available at that point to allocate memory for a value type, the OOME will appear later than the vdefault/vwithfield bytecode that actually caused it. Tobias and I discussed about this aspect and it's likely that this is not a problem as re-allocation of scalar-replaced objects is similar and is also performed at deoptimization. However, more investigation is needed to confirm that. >> >> Thank you! >> >> Best regards, >> >> >> Zoltan >> From paul.sandoz at oracle.com Wed Jun 14 16:57:11 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 14 Jun 2017 09:57:11 -0700 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> Message-ID: > On 14 Jun 2017, at 06:53, Roland Westrelin wrote: > > >> The is due to the call to invoke, which performs an asType >> transformation and thus the receiver is not constant. > > So it's effectively constant but the compiler can't see it? It?s ?effectively? constant from the perspective of the invoke call site (since the signature at the call site does not change). However, from the perspective of the method handle instance it is not constant, since the invoker or anyone else goes through an asType call and thus updates the ?memoized" field for the last cached transformed MH. Thinking some more about this. For the MH invokers (generic lambda form invoker) there might be something we can associate with the call site and use a stable lazy calculation. I wonder if we can adjust the appendix parameter to be a holder containing the call site method sig and stable field for the asTyped MH. Paul. > I had a > patch that added profiling of that receiver value. It didn't seem to > show any benefit at the time. I wonder it would make sense to experiment > with something similar again. > > Roland. From vladimir.x.ivanov at oracle.com Wed Jun 14 17:04:34 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 14 Jun 2017 20:04:34 +0300 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> Message-ID: <851f88f1-cb3a-9207-8d4f-f3efaaf2a0ac@oracle.com> >> The is due to the call to invoke, which performs an asType >> transformation and thus the receiver is not constant. > > So it's effectively constant but the compiler can't see it? I had a > patch that added profiling of that receiver value. It didn't seem to > show any benefit at the time. I wonder it would make sense to experiment > with something similar again. There's a simpler solution: since MH.asType() already uses 1-element cache [1], it should be enough to just mark MH.asTypeCache as @Stable. The problem with MH.asType() is more general: 1-element caching scheme doesn't scale for multiple MH.invoke() call sites with different signatures. Every cache miss requires a new method handle to be created. Best regards, Vladimir Ivanov [1] jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java: ... public abstract class MethodHandle { ... /*private*/ MethodHandle asTypeCache; ... public MethodHandle asType(MethodType newType) { // Fast path alternative to a heavyweight {@code asType} call. // Return 'this' if the conversion will be a no-op. if (newType == type) { return this; } // Return 'this.asTypeCache' if the conversion is already memoized. MethodHandle atc = asTypeCached(newType); if (atc != null) { return atc; } return asTypeUncached(newType); } private MethodHandle asTypeCached(MethodType newType) { MethodHandle atc = asTypeCache; if (atc != null && newType == atc.type) { return atc; } return null; } From paul.sandoz at oracle.com Wed Jun 14 17:27:10 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 14 Jun 2017 10:27:10 -0700 Subject: couple questions on method handle combinators In-Reply-To: <851f88f1-cb3a-9207-8d4f-f3efaaf2a0ac@oracle.com> References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> <851f88f1-cb3a-9207-8d4f-f3efaaf2a0ac@oracle.com> Message-ID: <220B001C-60BB-4878-B37C-47926EB4C6EF@oracle.com> > On 14 Jun 2017, at 10:04, Vladimir Ivanov wrote: > >>> The is due to the call to invoke, which performs an asType >>> transformation and thus the receiver is not constant. >> >> So it's effectively constant but the compiler can't see it? I had a >> patch that added profiling of that receiver value. It didn't seem to >> show any benefit at the time. I wonder it would make sense to experiment >> with something similar again. > > There's a simpler solution: since MH.asType() already uses 1-element cache [1], it should be enough to just mark MH.asTypeCache as @Stable. > Would not invalidate the contract of @Stable where the value changes at most once? thereby causes issues for already compiled methods treating that as a constant when other code updates the value via an asType call. i realize that we break similar rules for updating the LF, but that is a special case where we are in control where as we don?t control who calls MH.asType. Paul. > The problem with MH.asType() is more general: 1-element caching scheme doesn't scale for multiple MH.invoke() call sites with different signatures. Every cache miss requires a new method handle to be created. > > Best regards, > Vladimir Ivanov > > [1] jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java: > ... > public abstract class MethodHandle { > ... > /*private*/ MethodHandle asTypeCache; > ... > public MethodHandle asType(MethodType newType) { > // Fast path alternative to a heavyweight {@code asType} call. > // Return 'this' if the conversion will be a no-op. > if (newType == type) { > return this; > } > // Return 'this.asTypeCache' if the conversion is already memoized. > MethodHandle atc = asTypeCached(newType); > if (atc != null) { > return atc; > } > return asTypeUncached(newType); > } > > private MethodHandle asTypeCached(MethodType newType) { > MethodHandle atc = asTypeCache; > if (atc != null && newType == atc.type) { > return atc; > } > return null; > } From vladimir.x.ivanov at oracle.com Wed Jun 14 17:36:15 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 14 Jun 2017 20:36:15 +0300 Subject: couple questions on method handle combinators In-Reply-To: <220B001C-60BB-4878-B37C-47926EB4C6EF@oracle.com> References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> <851f88f1-cb3a-9207-8d4f-f3efaaf2a0ac@oracle.com> <220B001C-60BB-4878-B37C-47926EB4C6EF@oracle.com> Message-ID: >> >> There's a simpler solution: since MH.asType() already uses 1-element cache [1], it should be enough to just mark MH.asTypeCache as @Stable. >> > > Would not invalidate the contract of @Stable where the value changes at most once? thereby causes issues for already compiled methods treating that as a constant when other code updates the value via an asType call. > i realize that we break similar rules for updating the LF, but that is a special case where we are in control where as we don?t control who calls MH.asType. It does break @Stable contract, but the JVM doesn't forbid multiple updates to @Stable fields and it's a benign case: keeping a stale value "cached" in compiled code doesn't break asType() caching logic. (For user it looks like the cache is always stale and MH.asType() should be recomputed.) Best regards, Vladimir Ivanov >> The problem with MH.asType() is more general: 1-element caching scheme doesn't scale for multiple MH.invoke() call sites with different signatures. Every cache miss requires a new method handle to be created. >> >> Best regards, >> Vladimir Ivanov >> >> [1] jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java: >> ... >> public abstract class MethodHandle { >> ... >> /*private*/ MethodHandle asTypeCache; >> ... >> public MethodHandle asType(MethodType newType) { >> // Fast path alternative to a heavyweight {@code asType} call. >> // Return 'this' if the conversion will be a no-op. >> if (newType == type) { >> return this; >> } >> // Return 'this.asTypeCache' if the conversion is already memoized. >> MethodHandle atc = asTypeCached(newType); >> if (atc != null) { >> return atc; >> } >> return asTypeUncached(newType); >> } >> >> private MethodHandle asTypeCached(MethodType newType) { >> MethodHandle atc = asTypeCache; >> if (atc != null && newType == atc.type) { >> return atc; >> } >> return null; >> } > From vladimir.x.ivanov at oracle.com Wed Jun 14 17:39:01 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 14 Jun 2017 20:39:01 +0300 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> Message-ID: <23fb65dc-36f1-8606-4589-4f4160b1fbb0@oracle.com> >> (I'll happily leave your other inlining questions to people more >> knowledgeable in that area). > > I could have phrased that question better. Let me try to give some > context. For: > > MethodHandles.guardWithTest(test77_mh_test, test77_mh1, test77_mh2); > > AFAICT, the logic implemented by the lambda forms is: > > MethodHandle mh = selectAlternative(test77_mh_test, test77_mh1, test77_mh2); > mh.invoke(...); > > So mh can't be a constant at the invoke if test77_mh_test returns either > true and false. > > I suppose I expected something like: > > if (test77_mh_test.invoke()) { > test77_mh1.invoke(); > } else { > test77_mh2.invoke(); > } Yes, that's how compiled LambdaForm for GWT should look like in bytecode. InvokerBytecodeGenerator.emitSelectAlternative() translates: t2:I=MethodHandle.invokeBasic(...); t5:L=MethodHandleImpl.selectAlternative(t2:I,...); ... =MethodHandle.invokeBasic(...) into equivalent of if (testMH.invokeBasic(...)) { trueMH.invokeBasic(...); } else { falseMH.invokeBasic(...); } (It's a bit more complicated to enable sharing of LambdaForm instances for GWTs and per-GWT branch frequencies profiling.) Most likely, there's something missing for Q-typed shapes which disables SELECT_ALTERNATIVE intrinsic. (I saw that Paul has already started looking into the problem.) Best regards, Vladimir Ivanov > > in which case, at the invoke sites the method handles could be known. > > The reason I'm experimenting with guardWithTest is that I'd like the > lambda forms to follow a particular shape (to check if c2 can optimize > the handling of the method handle call return properly): > > if ( ) { > value_type_result = m1.invoke(); > } else { > value_type_result = m2.invoke(); > } > // value type result merged here > return value_type_result; > > The merge of 2 return values is what I'm interested in. With a loop I > expect I would get a similar pattern: > > value_type_result = init_mh.invoke(); > for(;;) { > value_type_result = body_mh.invoke(); // value type result merged here > } > return value_type_result; > > So I guess my question is: Is there no way to get guardWithTest to do > what I want? Other than with loops and guardWithTest, is there another > way to get a merge point with returned values from invokes? > > Roland. > From paul.sandoz at oracle.com Wed Jun 14 18:02:45 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 14 Jun 2017 11:02:45 -0700 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> <851f88f1-cb3a-9207-8d4f-f3efaaf2a0ac@oracle.com> <220B001C-60BB-4878-B37C-47926EB4C6EF@oracle.com> Message-ID: > On 14 Jun 2017, at 10:36, Vladimir Ivanov wrote: > >>> >>> There's a simpler solution: since MH.asType() already uses 1-element cache [1], it should be enough to just mark MH.asTypeCache as @Stable. >>> >> >> Would not invalidate the contract of @Stable where the value changes at most once? thereby causes issues for already compiled methods treating that as a constant when other code updates the value via an asType call. > >> i realize that we break similar rules for updating the LF, but that is a special case where we are in control where as we don?t control who calls MH.asType. > > It does break @Stable contract, but the JVM doesn't forbid multiple updates to @Stable fields and it's a benign case: keeping a stale value "cached" in compiled code doesn't break asType() caching logic. (For user it looks like the cache is always stale and MH.asType() should be recomputed.) > Just concerned that biasing to the first caller of asType may push the perf problem around. I have a hunch for generic invokers we could cache an asType equivalent result at the call site by stuffing into some stable field of an appendix holder. That?s more work though. Paul. From paul.sandoz at oracle.com Wed Jun 14 18:22:46 2017 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Wed, 14 Jun 2017 18:22:46 +0000 Subject: hg: valhalla/valhalla/jdk: Dumping class files generated from LambdaFormBuilder should generate Message-ID: <201706141822.v5EIMkuC018891@aojmv0008.oracle.com> Changeset: 661807c1bfd7 Author: psandoz Date: 2017-06-14 11:21 -0700 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/661807c1bfd7 Dumping class files generated from LambdaFormBuilder should generate debug-based names for CP patched entries. (Although as of yet i have not managed to induce such patching when it is enabled.) ! src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java From paul.sandoz at oracle.com Wed Jun 14 19:29:52 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 14 Jun 2017 12:29:52 -0700 Subject: vwithfield and ValueType.findWither Message-ID: Hi, There appears enough VM support to try out the vwithfield in MVT and simplify the current implementation. However, i am getting an IllegalAccessException from the VM, even though the class produced by MVT is anonymously defined with the DVT class as the host class (could be the VCC too?): > java.lang.IllegalAccessError: Update to non-static final field Point$Value.x attempted from a different class (Point_wither$x/467000451) than the field's declaring class Should the VM be delegating access control checking to the host class in this case? Separately, the ValueType.findWither code needs to update it?s own access control checks such that only a lookup with the correct permissions (from the class or via privateLookupIn) can produce a wither MH. Again, should permission be granted if the lookup class is VCC in addition to DVT? Thanks, Paul. From maurizio.cimadamore at oracle.com Wed Jun 14 21:15:55 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 14 Jun 2017 22:15:55 +0100 Subject: vwithfield and ValueType.findWither In-Reply-To: References: Message-ID: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> On 14/06/17 20:29, Paul Sandoz wrote: > Hi, > > There appears enough VM support to try out the vwithfield in MVT and simplify the current implementation. ValueType not using vwithfield is a deliberate move. vwithfield has some restrictions: the class doing vwithfield must be the same class as the owner of the field. In other words, it's mean to be used in the implementation of a value class, not as a general purpose opcode to set fields on values. This is why I settled on Unsafe. > > However, i am getting an IllegalAccessException from the VM, even though the class produced by MVT is anonymously defined with the DVT class as the host class (could be the VCC too?): > >> java.lang.IllegalAccessError: Update to non-static final field Point$Value.x attempted from a different class (Point_wither$x/467000451) than the field's declaring class That's what I'm talking about :-) > > Should the VM be delegating access control checking to the host class in this case? As I said, the check is deliberate I think. Perhaps we could workaround the check by picking the DVT as the host class and not the box class (as I think we do now). But I think ultimately we'd still probably attempt to do something that vwithfeld was not designed to do. > > Separately, the ValueType.findWither code needs to update it?s own access control checks such that only a lookup with the correct permissions (from the class or via privateLookupIn) can produce a wither MH. Again, should permission be granted if the lookup class is VCC in addition to DVT? I think ValueType.findWither != vwithfield. I don't think we want to many restrictions (other than the one that you can actually access the field) - otherwise people will be unable to create the values they want (note that DVTs cannot have methods, so they cannot expose factories!) Maurizio > > Thanks, > Paul. > > From maurizio.cimadamore at oracle.com Wed Jun 14 21:20:09 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 14 Jun 2017 22:20:09 +0100 Subject: vwithfield and ValueType.findWither In-Reply-To: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> Message-ID: On 14/06/17 22:15, Maurizio Cimadamore wrote: > I think ValueType.findWither != vwithfield. I don't think we want to > many restrictions (other than the one that you can actually access the > field) - otherwise people will be unable to create the values they > want (note that DVTs cannot have methods, so they cannot expose > factories!) Another possible story is that we always create values through the VCC constructor, and then unbox. If we think we're happy with that, that might be a fine choice too. Maurizio From paul.sandoz at oracle.com Wed Jun 14 21:30:01 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 14 Jun 2017 14:30:01 -0700 Subject: vwithfield and ValueType.findWither In-Reply-To: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> Message-ID: <41A9D038-EBD7-4AD1-B7C9-12B626BD3C6E@oracle.com> Thanks for the context, i was misled a little by a comment in the code :-) //Todo: when 'vwithfield' is ready, this handle could be greatly simplified Originally i was going to propose that we patch in an instance Unsafe to the CP then we don?t need layers of method handles with bound leading arguments, thus less ceremony. Regardless i think there might be a bug in the HS code not deferring to the host class for accessibility checks (and an open question whether the DVT and/or VCC can be used as the host class). With privateLookupIn i think a developer can get further than they could without it. But, i take your point on slightly different functionality, and on the creation of value types (not easy). Perhaps we should support both mechanisms? especially since much of what we do around value types is performance related. And on that note do we need a special MH constructor for a DVT? Paul. > On 14 Jun 2017, at 14:15, Maurizio Cimadamore wrote: > > > > On 14/06/17 20:29, Paul Sandoz wrote: >> Hi, >> >> There appears enough VM support to try out the vwithfield in MVT and simplify the current implementation. > ValueType not using vwithfield is a deliberate move. vwithfield has some restrictions: the class doing vwithfield must be the same class as the owner of the field. In other words, it's mean to be used in the implementation of a value class, not as a general purpose opcode to set fields on values. > > This is why I settled on Unsafe. >> >> However, i am getting an IllegalAccessException from the VM, even though the class produced by MVT is anonymously defined with the DVT class as the host class (could be the VCC too?): >> >>> java.lang.IllegalAccessError: Update to non-static final field Point$Value.x attempted from a different class (Point_wither$x/467000451) than the field's declaring class > That's what I'm talking about :-) >> >> Should the VM be delegating access control checking to the host class in this case? > As I said, the check is deliberate I think. Perhaps we could workaround the check by picking the DVT as the host class and not the box class (as I think we do now). But I think ultimately we'd still probably attempt to do something that vwithfeld was not designed to do. >> >> Separately, the ValueType.findWither code needs to update it?s own access control checks such that only a lookup with the correct permissions (from the class or via privateLookupIn) can produce a wither MH. Again, should permission be granted if the lookup class is VCC in addition to DVT? > I think ValueType.findWither != vwithfield. I don't think we want to many restrictions (other than the one that you can actually access the field) - otherwise people will be unable to create the values they want (note that DVTs cannot have methods, so they cannot expose factories!) > > Maurizio >> >> Thanks, >> Paul. >> >> > From maurizio.cimadamore at oracle.com Wed Jun 14 22:49:24 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 14 Jun 2017 23:49:24 +0100 Subject: vwithfield and ValueType.findWither In-Reply-To: <41A9D038-EBD7-4AD1-B7C9-12B626BD3C6E@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <41A9D038-EBD7-4AD1-B7C9-12B626BD3C6E@oracle.com> Message-ID: <6dee2a33-06a6-6b7d-1718-456a76b5e889@oracle.com> On 14/06/17 22:30, Paul Sandoz wrote: > Thanks for the context, i was misled a little by a comment in the code :-) > > //Todo: when 'vwithfield' is ready, this handle could be greatly simplified Heh - I wrote this when we didn't fully know what vwithfield was :-) > > Originally i was going to propose that we patch in an instance Unsafe to the CP then we don?t need layers of method handles with bound leading arguments, thus less ceremony. > > Regardless i think there might be a bug in the HS code not deferring to the host class for accessibility checks (and an open question whether the DVT and/or VCC can be used as the host class). Yep - I agree. > > With privateLookupIn i think a developer can get further than they could without it. But, i take your point on slightly different functionality, and on the creation of value types (not easy). Perhaps we should support both mechanisms? especially since much of what we do around value types is performance related. And on that note do we need a special MH constructor for a DVT? If we had a MH constructor, I think there could be a bigger argument that the findWither as implemented now is redundantly 'unsafe'. But at the same time, using the word 'constructor' and 'value' in the same sentence is gonna be odd too, as there's no constructor so to speak in the DVT, so it might suggest a mental model which is not really there... Maurizio > > Paul. > >> On 14 Jun 2017, at 14:15, Maurizio Cimadamore wrote: >> >> >> >> On 14/06/17 20:29, Paul Sandoz wrote: >>> Hi, >>> >>> There appears enough VM support to try out the vwithfield in MVT and simplify the current implementation. >> ValueType not using vwithfield is a deliberate move. vwithfield has some restrictions: the class doing vwithfield must be the same class as the owner of the field. In other words, it's mean to be used in the implementation of a value class, not as a general purpose opcode to set fields on values. >> >> This is why I settled on Unsafe. >>> However, i am getting an IllegalAccessException from the VM, even though the class produced by MVT is anonymously defined with the DVT class as the host class (could be the VCC too?): >>> >>>> java.lang.IllegalAccessError: Update to non-static final field Point$Value.x attempted from a different class (Point_wither$x/467000451) than the field's declaring class >> That's what I'm talking about :-) >>> Should the VM be delegating access control checking to the host class in this case? >> As I said, the check is deliberate I think. Perhaps we could workaround the check by picking the DVT as the host class and not the box class (as I think we do now). But I think ultimately we'd still probably attempt to do something that vwithfeld was not designed to do. >>> Separately, the ValueType.findWither code needs to update it?s own access control checks such that only a lookup with the correct permissions (from the class or via privateLookupIn) can produce a wither MH. Again, should permission be granted if the lookup class is VCC in addition to DVT? >> I think ValueType.findWither != vwithfield. I don't think we want to many restrictions (other than the one that you can actually access the field) - otherwise people will be unable to create the values they want (note that DVTs cannot have methods, so they cannot expose factories!) >> >> Maurizio >>> Thanks, >>> Paul. >>> >>> From john.r.rose at oracle.com Thu Jun 15 00:57:52 2017 From: john.r.rose at oracle.com (John Rose) Date: Wed, 14 Jun 2017 17:57:52 -0700 Subject: vwithfield and ValueType.findWither In-Reply-To: References: Message-ID: <36FB0DA4-EAFD-4444-9E4E-EA036E6EF88A@oracle.com> On Jun 14, 2017, at 12:29 PM, Paul Sandoz wrote: > > Again, should permission be granted if the lookup class is VCC in addition to DVT? Yes. Think "nestmates" even though that's a separate feature. Or if you like, think "we are trying to obscure the difference." From john.r.rose at oracle.com Thu Jun 15 08:46:54 2017 From: john.r.rose at oracle.com (John Rose) Date: Thu, 15 Jun 2017 01:46:54 -0700 Subject: vwithfield and ValueType.findWither In-Reply-To: References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> Message-ID: <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore wrote: > > Another possible story is that we always create values through the VCC constructor, and then unbox. If we think we're happy with that, that might be a fine choice too. That's not a bad story for the JIT with aggressive scalarization, and was my first idea about this, but it is painful in the interpreter. From maurizio.cimadamore at oracle.com Thu Jun 15 09:36:11 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 15 Jun 2017 10:36:11 +0100 Subject: vwithfield and ValueType.findWither In-Reply-To: <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> Message-ID: <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> On 15/06/17 09:46, John Rose wrote: > On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore wrote: >> Another possible story is that we always create values through the VCC constructor, and then unbox. If we think we're happy with that, that might be a fine choice too. > That's not a bad story for the JIT with aggressive scalarization, > and was my first idea about this, but it is painful in the interpreter. > In which ways it's bad for the interpreter? Note that the current implementation of the 'modified' findWither will do just that: * box incoming value * set field (with Unsafe.putXYZ) * unbox resulting reference back to a value So, it seems to me that, to set 5 fields, the above idiom will do box/unbox 5 times, while if we just create a VCC with the fields we want and then unbox, that's just one unboxing step. What am I missing? Maurizio From john.r.rose at oracle.com Thu Jun 15 09:47:04 2017 From: john.r.rose at oracle.com (John Rose) Date: Thu, 15 Jun 2017 02:47:04 -0700 Subject: vwithfield and ValueType.findWither In-Reply-To: <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> Message-ID: On Jun 15, 2017, at 2:36 AM, Maurizio Cimadamore wrote: > > On 15/06/17 09:46, John Rose wrote: >> On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore wrote: >>> Another possible story is that we always create values through the VCC constructor, and then unbox. If we think we're happy with that, that might be a fine choice too. >> That's not a bad story for the JIT with aggressive scalarization, >> and was my first idea about this, but it is painful in the interpreter. >> > In which ways it's bad for the interpreter? Note that the current implementation of the 'modified' findWither will do just that: > > * box incoming value > * set field (with Unsafe.putXYZ) > * unbox resulting reference back to a value > > So, it seems to me that, to set 5 fields, the above idiom will do box/unbox 5 times, while if we just create a VCC with the fields we want and then unbox, that's just one unboxing step. > > What am I missing? You're not missing anything. Making a VCC will be an easy thing to do, since the VCC will have lots of method machinery and (IIRC) even constructors. My concern is for other kinds of code, outside the VCC, which uses compositions containing withers to build values, using MH's. Recycling boxes is really treating them as local scratch buffers. Because object identity is stable, we can rely on the JVM not confusing side-effects to box objects (a rare win for object identity). And the JIT should elide the buffer (box object) using escape analysis. So all is good there. And the standard idiom a constructor on a POJO with final fields fits perfectly here, where the VCC is the POJO. (We can port such source code directly to the full value types world.) The fly in the ointment, I think, is that if you take one step away from the multi-use buffer, you find that you are composing wither MH's into a MH graph. Each wither will have to make its own buffer; there seems to be no way to encourage them to share. This means that the interpreter will see five separate heap allocations in your example. The JIT will see them too, and collapse them. The JIT would prefer that there is one shared box, just because code volume matters. From maurizio.cimadamore at oracle.com Thu Jun 15 09:56:36 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 15 Jun 2017 10:56:36 +0100 Subject: vwithfield and ValueType.findWither In-Reply-To: References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> Message-ID: <8948062c-1ef2-c7be-11aa-14d13924c1d3@oracle.com> On 15/06/17 10:47, John Rose wrote: > My concern is for other kinds of code, outside the VCC, which uses > compositions containing withers to build values, using MH's. This seems to suggest something similar to where Paul was going, I think - that is, findWither should _NOT_ be the vector for creating new DVT from scratch. In other words, we have two use cases: 1) I want to make a new DVT 2) I want to tweak an existing DVT I think it is fair to say that (1) should go through the POJO - as this is an operation that is likely to occur at the 'boundaries' (outside of the magic Q-MH world). And if advanced clients need low level access to tweak DVT fields, they can do so with a _real_ wither MH (not the mock one we expose now), which maybe savior devs could access using privateLookupIn as Paul suggested. What do you think? Maurizio From david.simms at oracle.com Thu Jun 15 13:13:02 2017 From: david.simms at oracle.com (david.simms at oracle.com) Date: Thu, 15 Jun 2017 13:13:02 +0000 Subject: hg: valhalla/valhalla: Copy of langtools combo testing lib, with set combinations support added Message-ID: <201706151313.v5FDD2ZA023933@aojmv0008.oracle.com> Changeset: 07d54d244d0f Author: dsimms Date: 2017-06-15 15:06 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/rev/07d54d244d0f Copy of langtools combo testing lib, with set combinations support added + test/lib/jdk/test/lib/combo/ComboInstance.java + test/lib/jdk/test/lib/combo/ComboParameter.java + test/lib/jdk/test/lib/combo/ComboTask.java + test/lib/jdk/test/lib/combo/ComboTestHelper.java + test/lib/jdk/test/lib/combo/ReusableContext.java From david.simms at oracle.com Thu Jun 15 13:13:12 2017 From: david.simms at oracle.com (david.simms at oracle.com) Date: Thu, 15 Jun 2017 13:13:12 +0000 Subject: hg: valhalla/valhalla/hotspot: Fixes: Removed duplicate byte size from ValueArrayKlass, avoid __Value on ObjArrayKlass, correct raw_value_byte_size Message-ID: <201706151313.v5FDDCAI024087@aojmv0008.oracle.com> Changeset: b1cf9cbe2ecb Author: dsimms Date: 2017-06-15 15:08 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/b1cf9cbe2ecb Fixes: Removed duplicate byte size from ValueArrayKlass, avoid __Value on ObjArrayKlass, correct raw_value_byte_size ! src/share/vm/interpreter/interpreterRuntime.cpp ! src/share/vm/oops/objArrayKlass.cpp ! src/share/vm/oops/valueArrayKlass.cpp ! src/share/vm/oops/valueKlass.cpp + test/runtime/valhalla/valuetypes/MVTCombo.java + test/runtime/valhalla/valuetypes/MVTComboDebugTier1.java + test/runtime/valhalla/valuetypes/MVTComboTier1.java From david.simms at oracle.com Thu Jun 15 13:23:08 2017 From: david.simms at oracle.com (david.simms at oracle.com) Date: Thu, 15 Jun 2017 13:23:08 +0000 Subject: hg: valhalla/valhalla/hotspot: Remove _element_value_store_size Message-ID: <201706151323.v5FDN9qT027860@aojmv0008.oracle.com> Changeset: 2ffa96111455 Author: dsimms Date: 2017-06-15 15:20 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/2ffa96111455 Remove _element_value_store_size ! src/share/vm/oops/valueArrayKlass.hpp From frederic.parain at oracle.com Thu Jun 15 14:06:46 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Thu, 15 Jun 2017 10:06:46 -0400 Subject: vwithfield and ValueType.findWither In-Reply-To: <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> Message-ID: <13f3ff1c-8e72-9cd2-19ef-77aa928124a3@oracle.com> On 06/15/2017 05:36 AM, Maurizio Cimadamore wrote: > > > On 15/06/17 09:46, John Rose wrote: >> On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore >> wrote: >>> Another possible story is that we always create values through the >>> VCC constructor, and then unbox. If we think we're happy with that, >>> that might be a fine choice too. >> That's not a bad story for the JIT with aggressive scalarization, >> and was my first idea about this, but it is painful in the interpreter. >> > In which ways it's bad for the interpreter? Note that the current > implementation of the 'modified' findWither will do just that: > > * box incoming value > * set field (with Unsafe.putXYZ) > * unbox resulting reference back to a value > > So, it seems to me that, to set 5 fields, the above idiom will do > box/unbox 5 times, while if we just create a VCC with the fields we want > and then unbox, that's just one unboxing step. > > What am I missing? With the vwithfield bytecode, the interpreter can avoid Java heap allocations, with the box/Unsafe/unbox it cannot. Just a performance/memory issue. Fred From paul.sandoz at oracle.com Thu Jun 15 17:26:45 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 15 Jun 2017 10:26:45 -0700 Subject: vwithfield and ValueType.findWither In-Reply-To: <8948062c-1ef2-c7be-11aa-14d13924c1d3@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> <8948062c-1ef2-c7be-11aa-14d13924c1d3@oracle.com> Message-ID: <980BBAB8-E896-451D-97F6-341A4A7CCB9D@oracle.com> > On 15 Jun 2017, at 02:56, Maurizio Cimadamore wrote: > > > > On 15/06/17 10:47, John Rose wrote: >> My concern is for other kinds of code, outside the VCC, which uses >> compositions containing withers to build values, using MH's. > This seems to suggest something similar to where Paul was going, I think - that is, findWither should _NOT_ be the vector for creating new DVT from scratch. In other words, we have two use cases: > > 1) I want to make a new DVT > 2) I want to tweak an existing DVT > > I think it is fair to say that (1) should go through the POJO - as this is an operation that is likely to occur at the 'boundaries' (outside of the magic Q-MH world). > > And if advanced clients need low level access to tweak DVT fields, they can do so with a _real_ wither MH (not the mock one we expose now), which maybe savior devs could access using privateLookupIn as Paul suggested. > If we resolve the host class accessibility issues i believe the findWither implementation can use vwithfield. The approach of box, update a field with unsafe (stomping on final and possibly private) fields and then unbox, is effectively similar to vwithfield (the box cannot be directly observed, perhaps just the shadows flickering on the wall when introspecting the VM). Currently findWither does not to throw an IllegalAccessException, so we could choose to go with that or decide to enforce it and require privayeLookupIn, separate from the implementation technique. In either implementation technique we bypass any constraints on state may be associated with a constructor on the VCC. Separately i think we should explore construction: 1) make a new DVT from a VCC constructor, by calling a VCC constructor and then unbox 2) make a new DVT from a VCC constructor, a DVT, a VCC field and it?s value, by extracting a state vector from the DVT, updating the state vector replacing one state element with that of the field value, calling the VCC constructor with the updated state vector, and then unbox. Paul. > What do you think? > > Maurizio From paul.sandoz at oracle.com Thu Jun 15 17:32:46 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 15 Jun 2017 10:32:46 -0700 Subject: vwithfield and ValueType.findWither In-Reply-To: <13f3ff1c-8e72-9cd2-19ef-77aa928124a3@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> <13f3ff1c-8e72-9cd2-19ef-77aa928124a3@oracle.com> Message-ID: <57FBA69F-ECDE-4B98-9111-AE4199D2C1D7@oracle.com> Hi Fred, Do you know where in the HotSpot code accessibility checks are performed for vwithfield? We need to fix those checks for Unsafe defined anonymous classes to defer to the host class (and if a suitable VCC or DVT then access should be granted). Paul. > On 15 Jun 2017, at 07:06, Frederic Parain wrote: > > > > On 06/15/2017 05:36 AM, Maurizio Cimadamore wrote: >> >> >> On 15/06/17 09:46, John Rose wrote: >>> On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore >>> wrote: >>>> Another possible story is that we always create values through the >>>> VCC constructor, and then unbox. If we think we're happy with that, >>>> that might be a fine choice too. >>> That's not a bad story for the JIT with aggressive scalarization, >>> and was my first idea about this, but it is painful in the interpreter. >>> >> In which ways it's bad for the interpreter? Note that the current >> implementation of the 'modified' findWither will do just that: >> >> * box incoming value >> * set field (with Unsafe.putXYZ) >> * unbox resulting reference back to a value >> >> So, it seems to me that, to set 5 fields, the above idiom will do >> box/unbox 5 times, while if we just create a VCC with the fields we want >> and then unbox, that's just one unboxing step. >> >> What am I missing? > > With the vwithfield bytecode, the interpreter can avoid Java heap > allocations, with the box/Unsafe/unbox it cannot. > > Just a performance/memory issue. > > Fred From martijnverburg at gmail.com Thu Jun 15 19:38:44 2017 From: martijnverburg at gmail.com (Martijn Verburg) Date: Thu, 15 Jun 2017 20:38:44 +0100 Subject: Seeking review and comments on R/W tags In-Reply-To: References: Message-ID: Hi John, Looks like some interesting research! I'll confess I haven't got the JVM knowledge to comment in depth apart from my earlier observations that this will need to be a patch against Java 10+ in order to be reviewed at the code level. I'm assuming that use of reflection or runtime bytecode modification could still 'break' the predicates here and I'd have a preference of not introducing further syntax to the Java developer (i.e. If a way could be found to do a majority of this via annotations then I think it would cause less friction). Please note I Am Not A JVM Expert (IANAJE), so take my comments with a large dose of salt. Cheers, Martijn On 16 May 2017 at 18:18, John Crowley wrote: > Hi All, > > I?m looking for some help to review a proposal. > > For a while now I?ve been working toward the goal of providing *declarative > immutability *in Java - by having Read/Write tags on variables, > references, methods, and generics*. *(Similar, but more extensive, than > the *const* keyword in some languages.) > > Things have progressed to the point that a few more (expert) eyes would be > appreciated to review and comment on whether this is feasible and desirable. > > A short summary follows, but everything is available here - > https://drive.google.com/open?id=0B9h3YMINZ271dWcyS1RjbEZLMHc > > > - A document with a complete description, > - A modified (Java 8) compiler which implements the initial portion of > the concept (the *Report Card* lists what is supported). > - A README file which describes where everything is on this drive. > > > A very condensed description ?. > > *The Problem* > *Variables* can be protected by making them *private* and using > *getters/setters* to control access - but at the cost of complexity, > additional code, and runtime overhead. > > *Object instances* are a more severe problem - once anyone has a > reference, they can modify any visible variable, and call mutating methods. > > When calling a *method* on an instance, the caller does not know if that > method mutates that instance (or some referenced instance). > > *The Proposal* > A set of single-character *tags* is proposed - W = writable, R = > read-only - that can be appended to variable definitions, types > (references), methods, and generics (more below). > > *Variable declarations *may have 2 tags - the first controls *outsiders* and > the second *the owner*. (The *owner* is defined as the innermost context > which declares the variable.) For example, > > public Date lastActivity:RW = new Date() > > specifies that the *owner *(the declaring class) may assign a new Date > instance to *lastActivity*, but no *outsider* may. Even stronger, > > public Date lastActivity:RR = new Date() > > specifies that neither an outsider nor the owner may change the Date > instance referenced by *lastActivity* (equivalent to the *final* keyword). > > The remaining problem is that anyone can change the semantic value by *lastActivity.setTime(?.). > *This can be controlled by tags on the *type* specification: > > public Date:RW lastActivity:RR = new Date() > > where the *Date:R* portion specifies that an *outsider* cannot modify any > visible variable in the *target instance* and can invoke only* read-only > methods* (myMethod:R). > > The *owner* may update the instance - presumably to update the timestamp > of the last activity processed. (The *owner* of an *instance* is the > context which instantiates that instance.) > > This is a strong API definition - *outsiders* know that they may create > and retain a local reference and it will always refer to the same instance, > and the *owner* has been able to make the information public with the > assurance that no one else can tamper. > > (Note that if the variable were *private* with a *getter*, then all *outsiders > *would have to invoke a method, and to be safe the *owner* must return a > *cloned* instance.) > > *Methods* and their *parameters* may also be tagged. *myMethod:R* specifies > that *myMethod* does not modify the instance (or any internally > referenced instance) - and this is validated by the compiler. *myMethod(Date:R > myParameter, ?) *considers the passed Date instance as read-only within > the method. If the method is tagged as R, then all parameters must also be > tagged as R (the compiler infers this for untagged parameters, an explicit > W tag is an error). > > Extending these tags to *generics* allows control at all levels of the > declaration. Assume that a *class Message?* exists, then > > List:RW > > specifies that *outsiders* may not modify the List (add/delete elements) > nor mutate any Message within the list. The *owner* may do both - e.g. > add new Messages to the List, update a Message when it is acknowledged, etc. > > A final tag of *P (= Pure)* may also be attached to a type declaration - > *Date:P* - and ensures that *no *mutable reference exists to this > instance - it will be immutable throughout the application. Important > information for any developer, and allows the compiler to utilize all > possible optimizations. > > As a last example, consider: > > public Map:RW> history:RR = new Map List> > > which is a (live) history of all of the Messages processed on a given day > (assumption: the HH:MM:SS.sss portion of the Date is zeroed). > > This tells any user that the Map is live, the key (Date) is Pure (good for > the key of a Map), and the List and Messages will be updated as events > occur. The *history* variable will always reference the same Map. The > compiler will flag any attempt by an outsider to modify anything at any > level, and will also flag an attempt by the owner to use a Date key which > is not immutable. (In a multi-threaded environment, synchronized versions > of Map, List, and Message would be necessary.) > > *Status* > The modified compiler enforces most of the above at compile time - so it > appears that implementation is feasible. > > Key questions remain where review by outside experts is needed: > > - Is the syntax complete? Unambiguous? > - Are the semantics complete? Are there reasonable coding paths which > lead to contradictions? Is there any path where a readonly tag can be > converted to a mutable tag? > - Is this useful to the developer? Does it produce more robust code? > Better APIs? Fewer LOC? Better runtime performance? > > > Thanks for your help, > > *John Crowley* > Westport, CT > 203-856-2396 > > > > > From tobias.hartmann at oracle.com Fri Jun 16 07:43:03 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Fri, 16 Jun 2017 09:43:03 +0200 Subject: RFR (M): Add missing compiler checks In-Reply-To: References: <7e8c8c01-1d38-493d-dec8-a9eefa7abd52@oracle.com> <5b55a814-e3a5-5c9f-96c6-ac6dfd46ae1b@oracle.com> Message-ID: <1549f371-1511-fce1-f601-6792d2e7e854@oracle.com> Hi Zoltan, On 14.06.2017 17:37, Zolt?n Maj? wrote: >> - Why are the changes to bcEscapeAnalyzer.cpp necessary? > > From a functional point of view, that change is not strictly necessary because T_VALUETYPE==T_OBJECT (that's the only difference between the handling of aastore and vastore). But maybe it's good to not use OBJECT in the code when we actually refer to a VT. I can also remove that change, if you want. Okay, I agree. >> - In parseHelper.cpp, why do we need a runtime check if we statically know that target_elem_klass != source_klass? > > The two types may be unequal at compilation type but they can be equal at runtime. Right, got it. >> - I think it would be good to add a test that mixes value type arrays with non value type stores (and the other way around) > I tried (see, e.g., test85() below). Unfortunately, compilation fails. What I'm not sure about is whether the verifier should (and can) catch such issues or should we really handle it in the compiler. I'm not sure either but we can fix this case later, if necessary. > Here is the updated code: > http://cr.openjdk.java.net/~zmajo/valhalla/04.checks/webrev.01/ Looks good! Thanks, Tobias From zoltan.majo at oracle.com Fri Jun 16 12:37:00 2017 From: zoltan.majo at oracle.com (=?UTF-8?B?Wm9sdMOhbiBNYWrDsw==?=) Date: Fri, 16 Jun 2017 14:37:00 +0200 Subject: RFR (M): Add missing compiler checks In-Reply-To: <1549f371-1511-fce1-f601-6792d2e7e854@oracle.com> References: <7e8c8c01-1d38-493d-dec8-a9eefa7abd52@oracle.com> <5b55a814-e3a5-5c9f-96c6-ac6dfd46ae1b@oracle.com> <1549f371-1511-fce1-f601-6792d2e7e854@oracle.com> Message-ID: Hi Tobias, On 06/16/2017 09:43 AM, Tobias Hartmann wrote: > [...] > I'm not sure either but we can fix this case later, if necessary. OK, but as we discussed in private, I'll add this issue to the list for later investigation / fixing. > >> Here is the updated code: >> http://cr.openjdk.java.net/~zmajo/valhalla/04.checks/webrev.01/ > Looks good! Thank you for the review! I merged my changes with the current state of the repository. For the record, here is the webrev (relative to that state): http://cr.openjdk.java.net/~zmajo/valhalla/04.checks/webrev.02/ I JPRT-tested the newest changes, all tests pass. I intend to push the changes later today. Best regards, Zoltan > > Thanks, > Tobias From jdcrowley at gmail.com Fri Jun 16 12:42:52 2017 From: jdcrowley at gmail.com (John Crowley) Date: Fri, 16 Jun 2017 08:42:52 -0400 Subject: Seeking review and comments on R/W tags In-Reply-To: References: Message-ID: Martjin, You are correct - this is not a security environment and can be "broken" by reflection or bytecode fiddling - in much the same way that reflection allows someone to reference a private variable. Can also be broken by tagging a method with F (forced read-only) and then mutating something - but at least here the compiler would issue a warning that the rules were violated. And a JNI native method tagged with an F is completely opaque to the compiler and can mangle anything. Also understand your reluctance to introduce more syntax into the language. The use of annotations was considered, but finally decided on the existing tags for the following reasons: All tags default to W and are optional - so existing Java source code, with no tags at all, will compile and execute the same as before, The R/W information has to be pervasive, so annotations would start to get very clumsy - e.g. @tags(:RR,myArray[:RR][:RW][:WW]) public Date myArray[][][] = ? vs public Date:RR myArray[:RR][:RW][] = ? IMHO the annotation approach requires some mental effort by the reader to match up the tags to the declaration. It would also be very easy for the developer to accidentally mis-match the R/W tags and the ultimate variable declaration (especially a maintenance developer less familiar with the original code). Consider the annotation that would be required for the example from the paper - Map:RW> Saving the R/W tags into the compiled class file by using the existing Signature entry seemed like the least invasive change, and again makes it obvious to anyone who runs javap to see the generated code. Thanks for your comments. The point of submitting this to valhalla was precisely to have some other (and more expert) eyes take a look! PS: The initial version of a presentation is now also on the shared drive - https://drive.google.com/open?id=0B9h3YMINZ271dWcyS1RjbEZLMHc Hope that it is somewhat understandable without a narration, but still WIP. Thanks, John Crowley Westport, CT 203-856-2396 > On Jun 15, 2017, at 3:38 PM, Martijn Verburg wrote: > > Hi John, > > Looks like some interesting research! I'll confess I haven't got the JVM knowledge to comment in depth apart from my earlier observations that this will need to be a patch against Java 10+ in order to be reviewed at the code level. > > I'm assuming that use of reflection or runtime bytecode modification could still 'break' the predicates here and I'd have a preference of not introducing further syntax to the Java developer (i.e. If a way could be found to do a majority of this via annotations then I think it would cause less friction). > > Please note I Am Not A JVM Expert (IANAJE), so take my comments with a large dose of salt. > > > > Cheers, > Martijn > > On 16 May 2017 at 18:18, John Crowley > wrote: > Hi All, > > I?m looking for some help to review a proposal. > > For a while now I?ve been working toward the goal of providing declarative immutability in Java - by having Read/Write tags on variables, references, methods, and generics. (Similar, but more extensive, than the const keyword in some languages.) > > Things have progressed to the point that a few more (expert) eyes would be appreciated to review and comment on whether this is feasible and desirable. > > A short summary follows, but everything is available here - https://drive.google.com/open?id=0B9h3YMINZ271dWcyS1RjbEZLMHc > > A document with a complete description, > A modified (Java 8) compiler which implements the initial portion of the concept (the Report Card lists what is supported). > A README file which describes where everything is on this drive. > > A very condensed description ?. > > The Problem > Variables can be protected by making them private and using getters/setters to control access - but at the cost of complexity, additional code, and runtime overhead. > > Object instances are a more severe problem - once anyone has a reference, they can modify any visible variable, and call mutating methods. > > When calling a method on an instance, the caller does not know if that method mutates that instance (or some referenced instance). > > The Proposal > A set of single-character tags is proposed - W = writable, R = read-only - that can be appended to variable definitions, types (references), methods, and generics (more below). > > Variable declarations may have 2 tags - the first controls outsiders and the second the owner. (The owner is defined as the innermost context which declares the variable.) For example, > > public Date lastActivity:RW = new Date() > > specifies that the owner (the declaring class) may assign a new Date instance to lastActivity, but no outsider may. Even stronger, > > public Date lastActivity:RR = new Date() > > specifies that neither an outsider nor the owner may change the Date instance referenced by lastActivity (equivalent to the final keyword). > > The remaining problem is that anyone can change the semantic value by lastActivity.setTime(?.). This can be controlled by tags on the type specification: > > public Date:RW lastActivity:RR = new Date() > > where the Date:R portion specifies that an outsider cannot modify any visible variable in the target instance and can invoke only read-only methods (myMethod:R). > > The owner may update the instance - presumably to update the timestamp of the last activity processed. (The owner of an instance is the context which instantiates that instance.) > > This is a strong API definition - outsiders know that they may create and retain a local reference and it will always refer to the same instance, and the owner has been able to make the information public with the assurance that no one else can tamper. > > (Note that if the variable were private with a getter, then all outsiders would have to invoke a method, and to be safe the owner must return a cloned instance.) > > Methods and their parameters may also be tagged. myMethod:R specifies that myMethod does not modify the instance (or any internally referenced instance) - and this is validated by the compiler. myMethod(Date:R myParameter, ?) considers the passed Date instance as read-only within the method. If the method is tagged as R, then all parameters must also be tagged as R (the compiler infers this for untagged parameters, an explicit W tag is an error). > > Extending these tags to generics allows control at all levels of the declaration. Assume that a class Message? exists, then > > List:RW > > specifies that outsiders may not modify the List (add/delete elements) nor mutate any Message within the list. The owner may do both - e.g. add new Messages to the List, update a Message when it is acknowledged, etc. > > A final tag of P (= Pure) may also be attached to a type declaration - Date:P - and ensures that no mutable reference exists to this instance - it will be immutable throughout the application. Important information for any developer, and allows the compiler to utilize all possible optimizations. > > As a last example, consider: > > public Map:RW> history:RR = new Map> > > which is a (live) history of all of the Messages processed on a given day (assumption: the HH:MM:SS.sss portion of the Date is zeroed). > > This tells any user that the Map is live, the key (Date) is Pure (good for the key of a Map), and the List and Messages will be updated as events occur. The history variable will always reference the same Map. The compiler will flag any attempt by an outsider to modify anything at any level, and will also flag an attempt by the owner to use a Date key which is not immutable. (In a multi-threaded environment, synchronized versions of Map, List, and Message would be necessary.) > > Status > The modified compiler enforces most of the above at compile time - so it appears that implementation is feasible. > > Key questions remain where review by outside experts is needed: > Is the syntax complete? Unambiguous? > Are the semantics complete? Are there reasonable coding paths which lead to contradictions? Is there any path where a readonly tag can be converted to a mutable tag? > Is this useful to the developer? Does it produce more robust code? Better APIs? Fewer LOC? Better runtime performance? > > Thanks for your help, > > John Crowley > Westport, CT > 203-856-2396 > > > > > From zoltan.majo at oracle.com Fri Jun 16 12:50:32 2017 From: zoltan.majo at oracle.com (zoltan.majo at oracle.com) Date: Fri, 16 Jun 2017 12:50:32 +0000 Subject: hg: valhalla/valhalla/hotspot: 8182374: Add missing compiler checks Message-ID: <201706161250.v5GCoWSh005524@aojmv0008.oracle.com> Changeset: 2aa797c929fc Author: zmajo Date: 2017-06-16 14:45 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/2aa797c929fc 8182374: Add missing compiler checks Summary: Add (some) missing compiler checks. Reviewed-by: thartmann ! src/share/vm/ci/bcEscapeAnalyzer.cpp ! src/share/vm/interpreter/interpreterRuntime.cpp ! src/share/vm/oops/arrayKlass.hpp ! src/share/vm/oops/objArrayKlass.hpp ! src/share/vm/oops/valueArrayKlass.cpp ! src/share/vm/oops/valueArrayKlass.hpp ! src/share/vm/opto/graphKit.cpp ! src/share/vm/opto/graphKit.hpp ! src/share/vm/opto/parse.hpp ! src/share/vm/opto/parse2.cpp ! src/share/vm/opto/parseHelper.cpp ! test/compiler/valhalla/valuetypes/ValueTypeTestBench.java From frederic.parain at oracle.com Fri Jun 16 14:22:37 2017 From: frederic.parain at oracle.com (frederic.parain at oracle.com) Date: Fri, 16 Jun 2017 14:22:37 +0000 Subject: hg: valhalla/valhalla/hotspot: 8182363: Clean up of VCC / DVT link in the JVM Message-ID: <201706161422.v5GEMcrP005388@aojmv0008.oracle.com> Changeset: f582fe5a3f5a Author: fparain Date: 2017-06-16 10:20 -0400 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/f582fe5a3f5a 8182363: Clean up of VCC / DVT link in the JVM ! src/share/vm/ci/ciInstanceKlass.cpp ! src/share/vm/ci/ciInstanceKlass.hpp ! src/share/vm/interpreter/interpreterRuntime.cpp ! src/share/vm/oops/instanceKlass.cpp ! src/share/vm/oops/instanceKlass.hpp ! src/share/vm/oops/instanceKlass.inline.hpp ! src/share/vm/oops/valueKlass.cpp ! src/share/vm/oops/valueKlass.hpp ! src/share/vm/opto/parse3.cpp ! src/share/vm/runtime/arguments.cpp From rwestrel at redhat.com Fri Jun 16 15:43:17 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Fri, 16 Jun 2017 17:43:17 +0200 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> Message-ID: > This one crashes the VM :-) Great that you're shaking out compiler bugs! Please continue! :-) I have a patch coming for that one. Roland. From rwestrel at redhat.com Fri Jun 16 15:57:33 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Fri, 16 Jun 2017 17:57:33 +0200 Subject: RFR: C2: fix call with __Value arguments Message-ID: http://cr.openjdk.java.net/~roland/valhalla/__Value_args_cast/webrev.00/ When inlining a method handler linker call, an argument at the call site can be __Value and the inlined method can be a specific value type. In that case, we have to create a ValueTypeNode from the value type reference. I suppose if we hit the opposite situation (call site's signature uses a specific value type, callee uses __Value) we need a reference to the value and have to store it to memory. This mirrors what happens without value types where C2 casts arguments. Roland. From rwestrel at redhat.com Fri Jun 16 16:02:34 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Fri, 16 Jun 2017 18:02:34 +0200 Subject: couple questions on method handle combinators In-Reply-To: <23fb65dc-36f1-8606-4589-4f4160b1fbb0@oracle.com> References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <23fb65dc-36f1-8606-4589-4f4160b1fbb0@oracle.com> Message-ID: > Most likely, there's something missing for Q-typed shapes which disables > SELECT_ALTERNATIVE intrinsic. Thanks Vladimir, Paul and Maurizio. As I understand, the code shape that I worry about can't be generated currently with GWT. I'll revisit that issue when GWT has improved. Do we expect to see a lot of uses of the loop method handle combinator with mvt? I wonder if it's worth looking into loop combinators more? Roland. From vladimir.x.ivanov at oracle.com Fri Jun 16 16:08:47 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Fri, 16 Jun 2017 19:08:47 +0300 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <23fb65dc-36f1-8606-4589-4f4160b1fbb0@oracle.com> Message-ID: <858f9632-432c-5beb-f7f4-d603c04a9c95@oracle.com> >> Most likely, there's something missing for Q-typed shapes which disables >> SELECT_ALTERNATIVE intrinsic. > > Thanks Vladimir, Paul and Maurizio. As I understand, the code shape that > I worry about can't be generated currently with GWT. I'll revisit that > issue when GWT has improved. > > Do we expect to see a lot of uses of the loop method handle combinator > with mvt? I wonder if it's worth looking into loop combinators more? I wouldn't expect "lots of uses", but method handle combinators (and newly introduced loop combinator in particular) are crucial for MVT-based Vector API implementation. Best regards, Vladimir Ivanov From vladimir.x.ivanov at oracle.com Fri Jun 16 16:46:55 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Fri, 16 Jun 2017 19:46:55 +0300 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> <851f88f1-cb3a-9207-8d4f-f3efaaf2a0ac@oracle.com> <220B001C-60BB-4878-B37C-47926EB4C6EF@oracle.com> Message-ID: >>> Would not invalidate the contract of @Stable where the value changes at most once? thereby causes issues for already compiled methods treating that as a constant when other code updates the value via an asType call. >> >>> i realize that we break similar rules for updating the LF, but that is a special case where we are in control where as we don?t control who calls MH.asType. >> >> It does break @Stable contract, but the JVM doesn't forbid multiple updates to @Stable fields and it's a benign case: keeping a stale value "cached" in compiled code doesn't break asType() caching logic. (For user it looks like the cache is always stale and MH.asType() should be recomputed.) >> > > Just concerned that biasing to the first caller of asType may push the perf problem around. It's not necessarily the first caller, but an interim cached value observed by a compiler once it tries to inline through a generic invoker on a constant method handle. > I have a hunch for generic invokers we could cache an asType equivalent result at the call site by stuffing into some stable field of an appendix holder. That?s more work though. I don't see how caching in appending can improve the situation. Method handle instance and a method type declared at call site are complementary and both are required for completing MH.asType() tranformation and performing generic invocation. Caching on method handle side favors constant method handles w/ a stable conversion (singe asType() conversion or multiple conversions w/ the same type). Caching on call site side (in appendix) favors call sites w/ a single receiver (MH), which JIT-compiler can't observe as a constant. Best regards, Vladimir Ivanov From sergey.kuksenko at oracle.com Fri Jun 16 23:13:26 2017 From: sergey.kuksenko at oracle.com (Sergey Kuksenko) Date: Fri, 16 Jun 2017 16:13:26 -0700 Subject: MH compilation is broken in valhalla(mvt branch) build Message-ID: Hi All, I found that in valhalla build (mvt branch) MH compilation is broken if MH is stored in non-final field. Cost of MH invocation is increased ~100x times. Benchmark sources and compiled jar file could be found: http://cr.openjdk.java.net/~skuksenko/valhalla/mh_issue/ Results: * on Java9 & Java8 Benchmark Mode Cnt Score Error Units XMH.walkFinal avgt 5 4.500 ? 0.276 ns/op XMH.walkNonFinal avgt 5 4.856 ? 0.011 ns/op * on MVT Benchmark Mode Cnt Score Error Units XMH.walkFinal avgt 5 4.406 ? 0.016 ns/op XMH.walkNonFinal avgt 5 457.484 ? 10.550 ns/op These benchmarks are Java8 compatible and doesn't contain any Q-types. Besides, Vladimir told me that: > I briefly looked into the benchmarks and it seems the difference is caused by a compiler bug: there are no compilations happening for stand-alone lambda forms with Q-types. > So, when inlining doesn't happen, the Q-typed LF code stays interpreted forever. Maybe that issues are related. Also I'd like to ask is infinite interpreting of Q-types LF code known behavior? If yes, are there any estimations when Q-types LF will be compiled? -- Best regards, Sergey Kuksenko From tobias.hartmann at oracle.com Mon Jun 19 05:59:08 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Mon, 19 Jun 2017 07:59:08 +0200 Subject: RFR: C2: fix call with __Value arguments In-Reply-To: References: Message-ID: <44b6c688-a91d-93a5-316c-d8a8c4913f14@oracle.com> Hi Roland, On 16.06.2017 17:57, Roland Westrelin wrote: > http://cr.openjdk.java.net/~roland/valhalla/__Value_args_cast/webrev.00/ This looks good to me but shouldn't we also cast the receiver? Were you able to write a test for this? If so, it would be good to add it to our test bench. > I suppose if we hit the opposite situation (call site's > signature uses a specific value type, callee uses __Value) we need a > reference to the value and have to store it to memory. This mirrors what > happens without value types where C2 casts arguments. Do you know how this can happen? Thanks, Tobias From david.simms at oracle.com Mon Jun 19 08:05:50 2017 From: david.simms at oracle.com (David Simms) Date: Mon, 19 Jun 2017 10:05:50 +0200 Subject: MH compilation is broken in valhalla(mvt branch) build In-Reply-To: References: Message-ID: <8e2a37c7-a6fa-7e3c-45e8-24d97cc267fe@oracle.com> Thanks for reporting this Sergey, I filed a "mvt" labelled bug for tracking: https://bugs.openjdk.java.net/browse/JDK-8182453 Cheers /David Simms On 17/06/17 01:13, Sergey Kuksenko wrote: > I found that in valhalla build (mvt branch) MH compilation is broken > if MH is stored in non-final field. Cost of MH invocation is increased > ~100x times. > > Benchmark sources and compiled jar file could be found: > http://cr.openjdk.java.net/~skuksenko/valhalla/mh_issue/ > > Results: > * on Java9 & Java8 > > Benchmark Mode Cnt Score Error Units > XMH.walkFinal avgt 5 4.500 ? 0.276 ns/op > XMH.walkNonFinal avgt 5 4.856 ? 0.011 ns/op > > * on MVT > Benchmark Mode Cnt Score Error Units > XMH.walkFinal avgt 5 4.406 ? 0.016 ns/op > XMH.walkNonFinal avgt 5 457.484 ? 10.550 ns/op > > These benchmarks are Java8 compatible and doesn't contain any Q-types. > > Besides, Vladimir told me that: > > > I briefly looked into the benchmarks and it seems the difference is > caused by a compiler bug: there are no compilations happening for > stand-alone lambda forms with Q-types. > > So, when inlining doesn't happen, the Q-typed LF code stays > interpreted forever. > > Maybe that issues are related. Also I'd like to ask is infinite > interpreting of Q-types LF code known behavior? If yes, are there any > estimations when Q-types LF will be compiled? From tobias.hartmann at oracle.com Mon Jun 19 08:12:59 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Mon, 19 Jun 2017 10:12:59 +0200 Subject: MH compilation is broken in valhalla(mvt branch) build In-Reply-To: <8e2a37c7-a6fa-7e3c-45e8-24d97cc267fe@oracle.com> References: <8e2a37c7-a6fa-7e3c-45e8-24d97cc267fe@oracle.com> Message-ID: <394459f0-d21b-a415-1c1b-555e14700118@oracle.com> Thanks Sergey, I'll have a look as soon as I'm freed up with from work. On 19.06.2017 10:05, David Simms wrote: > Thanks for reporting this Sergey, I filed a "mvt" labelled bug for tracking: > > https://bugs.openjdk.java.net/browse/JDK-8182453 For compiler triaging we need to set a fix version. Any updates on the mvt affects/fix version? Or should we just use 10 for now? Thanks, Tobias > On 17/06/17 01:13, Sergey Kuksenko wrote: >> I found that in valhalla build (mvt branch) MH compilation is broken if MH is stored in non-final field. Cost of MH invocation is increased ~100x times. >> >> Benchmark sources and compiled jar file could be found: >> http://cr.openjdk.java.net/~skuksenko/valhalla/mh_issue/ >> >> Results: >> * on Java9 & Java8 >> >> Benchmark Mode Cnt Score Error Units >> XMH.walkFinal avgt 5 4.500 ? 0.276 ns/op >> XMH.walkNonFinal avgt 5 4.856 ? 0.011 ns/op >> >> * on MVT >> Benchmark Mode Cnt Score Error Units >> XMH.walkFinal avgt 5 4.406 ? 0.016 ns/op >> XMH.walkNonFinal avgt 5 457.484 ? 10.550 ns/op >> >> These benchmarks are Java8 compatible and doesn't contain any Q-types. >> >> Besides, Vladimir told me that: >> >> > I briefly looked into the benchmarks and it seems the difference is caused by a compiler bug: there are no compilations happening for stand-alone lambda forms with Q-types. >> > So, when inlining doesn't happen, the Q-typed LF code stays interpreted forever. >> >> Maybe that issues are related. Also I'd like to ask is infinite interpreting of Q-types LF code known behavior? If yes, are there any estimations when Q-types LF will be compiled? > > From rwestrel at redhat.com Mon Jun 19 08:18:52 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Mon, 19 Jun 2017 10:18:52 +0200 Subject: MH compilation is broken in valhalla(mvt branch) build In-Reply-To: References: Message-ID: Hi Sergey, > I found that in valhalla build (mvt branch) MH compilation is broken if > MH is stored in non-final field. Cost of MH invocation is increased > ~100x times. Compilation of lambda forms as root of compilation is currently disabled. If we have a value type: class Point { double x; double y; } and some method is called: foo(Point p) when that method is JIT'ed, we use a special calling convention that doesn't pass a reference to p but the fields: foo(double x, double y) If foo is called with a method handle call and the method handle is not constant, foo won't be inlined in a caller, it will be called from a lambda form. That lambda form is specialized to the value type supertype so it's not aware that the value type argument is a Point. It passes a reference to a value type as an argument to foo but foo expects a pair of doubles. If the call is from an interpreted lambda form, the i2c takes care of loading the fields from the value type. If the call is from a compiled method, this would cause the compiled method foo to see garbage in x and y. The current workaround is to disable compilation of lambda forms. The correct fix I think is to have a special entry point in the compiled method. That this problem is indeed the root cause of what you're seeing can be verified by disabling the special calling convention with: -XX:-ValueTypePassFieldsAsArgs Roland. From david.simms at oracle.com Mon Jun 19 08:34:16 2017 From: david.simms at oracle.com (David Simms) Date: Mon, 19 Jun 2017 10:34:16 +0200 Subject: MH compilation is broken in valhalla(mvt branch) build In-Reply-To: <394459f0-d21b-a415-1c1b-555e14700118@oracle.com> References: <8e2a37c7-a6fa-7e3c-45e8-24d97cc267fe@oracle.com> <394459f0-d21b-a415-1c1b-555e14700118@oracle.com> Message-ID: <41438246-74ca-4fa9-87f5-e96ebec35b42@oracle.com> On 19/06/17 10:12, Tobias Hartmann wrote: > Thanks Sergey, I'll have a look as soon as I'm freed up with from work. > > On 19.06.2017 10:05, David Simms wrote: >> Thanks for reporting this Sergey, I filed a "mvt" labelled bug for tracking: >> >> https://bugs.openjdk.java.net/browse/JDK-8182453 > For compiler triaging we need to set a fix version. Any updates on the mvt affects/fix version? Or should we just use 10 for now? Yeap, 10, we'll probably set up something (and bulk update after the fact) when promoting EA builds... Cheers /D From david.simms at oracle.com Mon Jun 19 09:10:37 2017 From: david.simms at oracle.com (david.simms at oracle.com) Date: Mon, 19 Jun 2017 09:10:37 +0000 Subject: hg: valhalla/valhalla/jdk: defaultValueConstant() using vdefault Message-ID: <201706190910.v5J9Ac9n022800@aojmv0008.oracle.com> Changeset: e3e5af317626 Author: dsimms Date: 2017-06-19 11:07 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/e3e5af317626 defaultValueConstant() using vdefault ! src/java.base/share/classes/jdk/experimental/value/ValueType.java From david.simms at oracle.com Mon Jun 19 09:33:36 2017 From: david.simms at oracle.com (David Simms) Date: Mon, 19 Jun 2017 11:33:36 +0200 Subject: vwithfield and ValueType.findWither In-Reply-To: <57FBA69F-ECDE-4B98-9111-AE4199D2C1D7@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> <13f3ff1c-8e72-9cd2-19ef-77aa928124a3@oracle.com> <57FBA69F-ECDE-4B98-9111-AE4199D2C1D7@oracle.com> Message-ID: Re: "HotSpot code accessibility checks" I did play around with explicitly opening up access from the VCC: http://cr.openjdk.java.net/~dsimms/valhalla/vwithfield_access/webrev1/ (MethodHandleBuilder "vdefault" and "vwithfield" parts are already in) This code is specific to the VCC / DVT relationship, and was a bit of a hack to start the conversation some time back. We were happy living with the unsafe hack for the time being, but I would prefer to use stop using said work-around. I believe Dan's suggestion "Access restriction for vwithfield" on the design mail list is more practical (package private)...let's follow that conversation and get the JVMS definition right. Main points from previous discussions: * Original "vnew" proposal took all fields as stack args, all the time. o Hard to optimize, inefficient for value where most fields are "null/zero". o "vwithfield" easier to optimize (possible to elide COW semantics, efficiently change only required fields) * Allow the user-code to enforce invariant values o Able to implement "never publish (vastore, putfield) 'Foo' value with any zero fields" o Access restrictions from VCC or package private ? Recent changes to the ValueType API accepting MH lookup now gives a few more options to the user. /D On 15/06/17 19:32, Paul Sandoz wrote: > Hi Fred, > > Do you know where in the HotSpot code accessibility checks are performed for vwithfield? We need to fix those checks for Unsafe defined anonymous classes to defer to the host class (and if a suitable VCC or DVT then access should be granted). > > Paul. > >> On 15 Jun 2017, at 07:06, Frederic Parain wrote: >> >> >> >> On 06/15/2017 05:36 AM, Maurizio Cimadamore wrote: >>> >>> On 15/06/17 09:46, John Rose wrote: >>>> On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore >>>> wrote: >>>>> Another possible story is that we always create values through the >>>>> VCC constructor, and then unbox. If we think we're happy with that, >>>>> that might be a fine choice too. >>>> That's not a bad story for the JIT with aggressive scalarization, >>>> and was my first idea about this, but it is painful in the interpreter. >>>> >>> In which ways it's bad for the interpreter? Note that the current >>> implementation of the 'modified' findWither will do just that: >>> >>> * box incoming value >>> * set field (with Unsafe.putXYZ) >>> * unbox resulting reference back to a value >>> >>> So, it seems to me that, to set 5 fields, the above idiom will do >>> box/unbox 5 times, while if we just create a VCC with the fields we want >>> and then unbox, that's just one unboxing step. >>> >>> What am I missing? >> With the vwithfield bytecode, the interpreter can avoid Java heap >> allocations, with the box/Unsafe/unbox it cannot. >> >> Just a performance/memory issue. >> >> Fred From tobias.hartmann at oracle.com Mon Jun 19 12:46:01 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Mon, 19 Jun 2017 14:46:01 +0200 Subject: RFR(M): 8182471: [MVT] Eliminate redundant value type allocations Message-ID: Hi, please review the following patch: https://bugs.openjdk.java.net/browse/JDK-8182471 http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.20/ The optimization removes redundant value type allocations by searching for a dominating allocation and re-using it to replace the dominated allocation. This is done during loop optimizations because the GVN version of is_dominator() and also MemNode::all_controls_dominate() are not strong/good enough. To find candidate allocations, we now keep an edge from the ValueTypeNode to the AllocateNode (see ValueTypeNode::allocate()) and let GVN take care of merging identical value type nodes. In ValueTypeNode::remove_redundant_allocations() we then check for ValueTypeNodes with multiple AllocateNodes and eliminate redundant ones (see test85-86). I also added code to recognize cases when we copy a value type by "manually" loading its field values from memory. In this case, we can re-use the oop (see test87-90) and avoid allocations. In addition, I did some re-naming of ValueTypeNode methods. All JPRT tests pass. Best regards, Tobias From paul.sandoz at oracle.com Mon Jun 19 16:42:08 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 19 Jun 2017 09:42:08 -0700 Subject: vwithfield and ValueType.findWither In-Reply-To: References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> <13f3ff1c-8e72-9cd2-19ef-77aa928124a3@oracle.com> <57FBA69F-ECDE-4B98-9111-AE4199D2C1D7@oracle.com> Message-ID: <5E571F25-0138-43A2-9A4C-835EE9F4B2BF@oracle.com> Hi David, That is almost the same direction i was thinking about. Specifically, fix HS so that for an anon class accessibility check is deferred to the host class. As you point out findWither now accepts a lookup: public MethodHandle findWither(Lookup lookup, String name, Class type) throws NoSuchFieldException, IllegalAccessException { ? //force access-check lookup.findGetter(boxClass(), name, type); return result; } I am proposing that for findWither the developer pass a lookup created from MHs.privateLookupIn, thereby allowing to bypass the explicit access control checks in a controlled manner. IMO we don?t have to relax the access constraints on vwithfield. Separately we can improve the user experience by focusing on MHs for constructors. Paul. > On 19 Jun 2017, at 02:33, David Simms wrote: > > > Re: "HotSpot code accessibility checks" > > I did play around with explicitly opening up access from the VCC: > > http://cr.openjdk.java.net/~dsimms/valhalla/vwithfield_access/webrev1/ > > (MethodHandleBuilder "vdefault" and "vwithfield" parts are already in) > > This code is specific to the VCC / DVT relationship, and was a bit of a hack to start the conversation some time back. We were happy living with the unsafe hack for the time being, but I would prefer to use stop using said work-around. > > I believe Dan's suggestion "Access restriction for vwithfield" on the design mail list is more practical (package private)...let's follow that conversation and get the JVMS definition right. > > Main points from previous discussions: > > * Original "vnew" proposal took all fields as stack args, all the time. > o Hard to optimize, inefficient for value where most fields are > "null/zero". > o "vwithfield" easier to optimize (possible to elide COW > semantics, efficiently change only required fields) > * Allow the user-code to enforce invariant values > o Able to implement "never publish (vastore, putfield) 'Foo' value > with any zero fields" > o Access restrictions from VCC or package private ? > > Recent changes to the ValueType API accepting MH lookup now gives a few more options to the user. > > /D > > On 15/06/17 19:32, Paul Sandoz wrote: >> Hi Fred, >> >> Do you know where in the HotSpot code accessibility checks are performed for vwithfield? We need to fix those checks for Unsafe defined anonymous classes to defer to the host class (and if a suitable VCC or DVT then access should be granted). >> >> Paul. >> >>> On 15 Jun 2017, at 07:06, Frederic Parain wrote: >>> >>> >>> >>> On 06/15/2017 05:36 AM, Maurizio Cimadamore wrote: >>>> >>>> On 15/06/17 09:46, John Rose wrote: >>>>> On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore >>>>> wrote: >>>>>> Another possible story is that we always create values through the >>>>>> VCC constructor, and then unbox. If we think we're happy with that, >>>>>> that might be a fine choice too. >>>>> That's not a bad story for the JIT with aggressive scalarization, >>>>> and was my first idea about this, but it is painful in the interpreter. >>>>> >>>> In which ways it's bad for the interpreter? Note that the current >>>> implementation of the 'modified' findWither will do just that: >>>> >>>> * box incoming value >>>> * set field (with Unsafe.putXYZ) >>>> * unbox resulting reference back to a value >>>> >>>> So, it seems to me that, to set 5 fields, the above idiom will do >>>> box/unbox 5 times, while if we just create a VCC with the fields we want >>>> and then unbox, that's just one unboxing step. >>>> >>>> What am I missing? >>> With the vwithfield bytecode, the interpreter can avoid Java heap >>> allocations, with the box/Unsafe/unbox it cannot. >>> >>> Just a performance/memory issue. >>> >>> Fred > > From tobias.hartmann at oracle.com Tue Jun 20 10:56:42 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Tue, 20 Jun 2017 12:56:42 +0200 Subject: RFR(S): 8182585: [MVT] Reading an uninitialized static value type field should not throw a NPE Message-ID: Hi, please review the following patch: https://bugs.openjdk.java.net/browse/JDK-8182585 http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.21/ Static value type fields are not flattened but contain an oop to a Java heap allocated value type. If an uninitialized static value type field is read, we should not throw a NPE but return the default value type. I added a corresponding null check and an uncommon trap to handle initialization of the static field in the interpreter. This relies on the interpreter being patched as well (which is currently not the case). An alternative fix would be to just return the default value type (see also JDK-8182366). Roland, what do you think? Thanks, Tobias From tobias.hartmann at oracle.com Tue Jun 20 13:23:37 2017 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Tue, 20 Jun 2017 13:23:37 +0000 Subject: hg: valhalla/valhalla/hotspot: Added Xcomp to ValueOops test Message-ID: <201706201323.v5KDNbei019155@aojmv0008.oracle.com> Changeset: c6878e14a2df Author: thartmann Date: 2017-06-20 15:21 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/c6878e14a2df Added Xcomp to ValueOops test ! test/runtime/valhalla/valuetypes/ValueOops.java From rwestrel at redhat.com Tue Jun 20 16:25:22 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Tue, 20 Jun 2017 18:25:22 +0200 Subject: RFR: C2: fix call with __Value arguments In-Reply-To: <44b6c688-a91d-93a5-316c-d8a8c4913f14@oracle.com> References: <44b6c688-a91d-93a5-316c-d8a8c4913f14@oracle.com> Message-ID: Thanks for looking at this, Tobias. >> http://cr.openjdk.java.net/~roland/valhalla/__Value_args_cast/webrev.00/ > > This looks good to me but shouldn't we also cast the receiver? Then we would have a method on __Value that does something useful. We don't have any at this point AFAICT. > Were you able to write a test for this? If so, it would be good to add > it to our test bench. Here is a new webrev with a couple test cases: http://cr.openjdk.java.net/~roland/valhalla/__Value_args_cast/webrev.01/ I made another fix to type.cpp for a bug I found with the new tests. >> I suppose if we hit the opposite situation (call site's >> signature uses a specific value type, callee uses __Value) we need a >> reference to the value and have to store it to memory. This mirrors what >> happens without value types where C2 casts arguments. > > Do you know how this can happen? I'm not sure it can happen. I removed the code and replaced with an assert. Roland. From rwestrel at redhat.com Tue Jun 20 16:30:14 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Tue, 20 Jun 2017 18:30:14 +0200 Subject: RFR(S): 8182585: [MVT] Reading an uninitialized static value type field should not throw a NPE In-Reply-To: References: Message-ID: > https://bugs.openjdk.java.net/browse/JDK-8182585 > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.21/ > > Static value type fields are not flattened but contain an oop to a > Java heap allocated value type. If an uninitialized static value type > field is read, we should not throw a NPE but return the default value > type. I added a corresponding null check and an uncommon trap to > handle initialization of the static field in the interpreter. > > This relies on the interpreter being patched as well (which is > currently not the case). > > An alternative fix would be to just return the default value type (see > also JDK-8182366). Roland, what do you think? That looks good to me but it's unfortunate we have to add a runtime check. Roland. From tobias.hartmann at oracle.com Tue Jun 20 17:17:59 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Tue, 20 Jun 2017 19:17:59 +0200 Subject: RFR(S): 8182585: [MVT] Reading an uninitialized static value type field should not throw a NPE In-Reply-To: References: Message-ID: Hi Roland, thanks for the review! On 20.06.2017 18:30, Roland Westrelin wrote: > That looks good to me but it's unfortunate we have to add a runtime > check. Yes, we could check the static field value at compile time by accessing it through the Java mirror (similar to ciField::constant_value()) and only emit a runtime check if it's NULL. That assumes that once the field is non-NULL it will always stay non-NULL which should be guaranteed, right? Best regards, Tobias From frederic.parain at oracle.com Tue Jun 20 17:23:17 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Tue, 20 Jun 2017 13:23:17 -0400 Subject: RFR(S): 8182585: [MVT] Reading an uninitialized static value type field should not throw a NPE In-Reply-To: References: Message-ID: On 06/20/2017 01:17 PM, Tobias Hartmann wrote: > Hi Roland, > > thanks for the review! > > On 20.06.2017 18:30, Roland Westrelin wrote: >> That looks good to me but it's unfortunate we have to add a >> runtime check. > > Yes, we could check the static field value at compile time by > accessing it through the Java mirror (similar to > ciField::constant_value()) and only emit a runtime check if it's > NULL. That assumes that once the field is non-NULL it will always > stay non-NULL which should be guaranteed, right? Correct, because value types are non-nullable. Fred From rwestrel at redhat.com Tue Jun 20 19:32:54 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Tue, 20 Jun 2017 21:32:54 +0200 Subject: RFR: C2: fix call with __Value arguments In-Reply-To: References: <44b6c688-a91d-93a5-316c-d8a8c4913f14@oracle.com> Message-ID: > Then we would have a method on __Value that does something useful. We > don't have any at this point AFAICT. What I wrote above doesn't make much sense. Let's do that for the receiver too: http://cr.openjdk.java.net/~roland/valhalla/__Value_args_cast/webrev.02/ Roland. From mandy.chung at oracle.com Tue Jun 20 20:31:23 2017 From: mandy.chung at oracle.com (Mandy Chung) Date: Tue, 20 Jun 2017 13:31:23 -0700 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type Message-ID: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.00/index.html This patch changes Class::forName to not to return DVT classes and also disallows reflection API get members of a DVT class. ClassLoader::loadClass should probably be changed and I can fix that separately. I added a couple of new tests and also fix the MVT tests with GPL header rather than GPL+CP header. Mandy From maurizio.cimadamore at oracle.com Tue Jun 20 20:48:19 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 20 Jun 2017 21:48:19 +0100 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> Message-ID: Hi Mandy - overall looks very good. One question - is this code correct? public static Class loadValueTypeClass(Class vcc, String className) { 113 if (!isValueType(vcc)) { 114 throw new IllegalArgumentException(vcc.getName() + " is a derived value class"); 115 } 116 return JLA.loadValueTypeClass(vcc.getModule(), vcc.getClassLoader(), className); 117 } If so, doesn't that lead to contradiction when called from the one below: 90 public static Class getValueTypeClass(Class x) throws ClassNotFoundException { 91 if (isValueType(x)) { 92 throw new IllegalArgumentException("Expected Value Capable Class"); 93 } 94 return loadValueTypeClass(x, getValueTypeClassName(x.getName())); 95 } In other words, getValueTypeClass seems to test that the incoming class is a VCC, then passes it along to loadValueTypeClass, which seems to test the opposite condition. Am I missing something? Maurizio On 20/06/17 21:31, Mandy Chung wrote: > http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.00/index.html > > This patch changes Class::forName to not to return DVT classes > and also disallows reflection API get members of a DVT class. > ClassLoader::loadClass should probably be changed and I can > fix that separately. > > I added a couple of new tests and also fix the MVT tests with > GPL header rather than GPL+CP header. > > Mandy From frederic.parain at oracle.com Tue Jun 20 20:50:53 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Tue, 20 Jun 2017 16:50:53 -0400 Subject: RFR: Implement value type buffering for the interpreter Message-ID: <3B3BE56F-D7DC-4963-8C86-C7D205426367@oracle.com> Greetings, Here's a webrev implementing value type buffering for the interpreter. http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.01/ Buffering allows the interpreter to allocate values in a thread local buffer to avoid Java heap allocations. Memory recycling is performed on method exit and sometimes on backward branches. Format of buffered values is almost identical to the format of Java heap allocated values, so most code won't see any difference between a buffered value and a not buffered value. The only difference is in the first word of the header. Because of a change in GC closures in JDK10, the first word now stores a reference to the Java mirror of the value class in order to keep it alive. In JDK9, this operation was performed through the klass pointer in the header, but the GC team has removed this closure. Buffering can be monitored using NMT or a new diagnostic command. All tests pass and Sergey has already tested the patch with his benchmark (and reported several bugs that are now fixed, thank you Sergey). Unfortunately, the changeset also includes a number of fixes not related to buffering, like code clean up and access to uninitialized static value fields. Thanks, Fred From mandy.chung at oracle.com Tue Jun 20 21:50:34 2017 From: mandy.chung at oracle.com (Mandy Chung) Date: Tue, 20 Jun 2017 14:50:34 -0700 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> Message-ID: <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> > On Jun 20, 2017, at 1:48 PM, Maurizio Cimadamore wrote: > > Hi Mandy - overall looks very good. One question - is this code correct? > > public static Class loadValueTypeClass(Class vcc, String className) { > 113 if (!isValueType(vcc)) { > 114 throw new IllegalArgumentException(vcc.getName() + " is a derived value class"); > 115 } > 116 return JLA.loadValueTypeClass(vcc.getModule(), vcc.getClassLoader(), className); > 117 } > My bad! I added this last minute check that are in the progress of testing. It intends to do the same check as getValueTypeClass. if (isValueType(vcc)) { throw new IllegalArgumentException(vcc.getName() + " is a derived value class"); } I updated webrev.00 in place. Mandy From paul.sandoz at oracle.com Tue Jun 20 22:01:43 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 20 Jun 2017 15:01:43 -0700 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> Message-ID: <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> That explains why i could not see what Maurizio was observing :-) Looks good. Paul. > On 20 Jun 2017, at 14:50, Mandy Chung wrote: > > >> On Jun 20, 2017, at 1:48 PM, Maurizio Cimadamore wrote: >> >> Hi Mandy - overall looks very good. One question - is this code correct? >> >> public static Class loadValueTypeClass(Class vcc, String className) { >> 113 if (!isValueType(vcc)) { >> 114 throw new IllegalArgumentException(vcc.getName() + " is a derived value class"); >> 115 } >> 116 return JLA.loadValueTypeClass(vcc.getModule(), vcc.getClassLoader(), className); >> 117 } >> > > My bad! I added this last minute check that are in the progress of testing. > It intends to do the same check as getValueTypeClass. > > if (isValueType(vcc)) { > throw new IllegalArgumentException(vcc.getName() + " is a derived value class"); > } > > I updated webrev.00 in place. > > Mandy From mandy.chung at oracle.com Tue Jun 20 22:20:01 2017 From: mandy.chung at oracle.com (Mandy Chung) Date: Tue, 20 Jun 2017 15:20:01 -0700 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> Message-ID: <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> All MVT tests passed. Mandy > On Jun 20, 2017, at 3:01 PM, Paul Sandoz wrote: > > That explains why i could not see what Maurizio was observing :-) > > Looks good. > > Paul. > >> On 20 Jun 2017, at 14:50, Mandy Chung wrote: >> >> >>> On Jun 20, 2017, at 1:48 PM, Maurizio Cimadamore wrote: >>> >>> Hi Mandy - overall looks very good. One question - is this code correct? >>> >>> public static Class loadValueTypeClass(Class vcc, String className) { >>> 113 if (!isValueType(vcc)) { >>> 114 throw new IllegalArgumentException(vcc.getName() + " is a derived value class"); >>> 115 } >>> 116 return JLA.loadValueTypeClass(vcc.getModule(), vcc.getClassLoader(), className); >>> 117 } >>> >> >> My bad! I added this last minute check that are in the progress of testing. >> It intends to do the same check as getValueTypeClass. >> >> if (isValueType(vcc)) { >> throw new IllegalArgumentException(vcc.getName() + " is a derived value class"); >> } >> >> I updated webrev.00 in place. >> >> Mandy > From maurizio.cimadamore at oracle.com Tue Jun 20 23:19:27 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 21 Jun 2017 00:19:27 +0100 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> Message-ID: The new version looks good - I wonder if we should add a dual method called isValueCapable(Class) and use that for the assertion check? The method would look at the class, retrieve the @VCC annotation and return true if one such annotation exists. As things stand, it is possible to pass classes to the loadValueClassType that are not VCC but which fail to trigger the assertion check. Probably a nitpick - but since we're tweaking in this area... Cheers Maurizio On 20/06/17 23:20, Mandy Chung wrote: > All MVT tests passed. > > Mandy > >> On Jun 20, 2017, at 3:01 PM, Paul Sandoz wrote: >> >> That explains why i could not see what Maurizio was observing :-) >> >> Looks good. >> >> Paul. >> >>> On 20 Jun 2017, at 14:50, Mandy Chung wrote: >>> >>> >>>> On Jun 20, 2017, at 1:48 PM, Maurizio Cimadamore wrote: >>>> >>>> Hi Mandy - overall looks very good. One question - is this code correct? >>>> >>>> public static Class loadValueTypeClass(Class vcc, String className) { >>>> 113 if (!isValueType(vcc)) { >>>> 114 throw new IllegalArgumentException(vcc.getName() + " is a derived value class"); >>>> 115 } >>>> 116 return JLA.loadValueTypeClass(vcc.getModule(), vcc.getClassLoader(), className); >>>> 117 } >>>> >>> My bad! I added this last minute check that are in the progress of testing. >>> It intends to do the same check as getValueTypeClass. >>> >>> if (isValueType(vcc)) { >>> throw new IllegalArgumentException(vcc.getName() + " is a derived value class"); >>> } >>> >>> I updated webrev.00 in place. >>> >>> Mandy From paul.sandoz at oracle.com Wed Jun 21 00:12:35 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 20 Jun 2017 17:12:35 -0700 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <5CDB0FCE-4CDA-4FD9-91D6-1AABAC625373@oracle.com> <513198B9-D5F0-4F07-99B2-B8A5495D74D0@oracle.com> <454D9D3A-8504-43BD-BB6A-3CBB76E13FBE@oracle.com> Message-ID: <08702B7C-D1DE-4948-BFCD-8C06B4EB67E1@oracle.com> Apologies for the delay Java 9 and some other tasks took precedence. > On 16 Jun 2017, at 08:43, Roland Westrelin wrote: > > >> This one crashes the VM :-) > > Great that you're shaking out compiler bugs! Please continue! :-) > > I have a patch coming for that one. > Thanks. I tried the patch. It works. Here is the inlining trace for testGWT_Q: 4247 349 % GWTTest::run_Q @ 4 (29 bytes) @ 13 java.lang.invoke.LambdaForm$MH023/1793409602::invokeExact_MT000_LL_I (22 bytes) force inline by annotation @ 10 java.lang.invoke.Invokers::checkExactType (17 bytes) force inline by annotation @ 1 java.lang.invoke.MethodHandle::type (5 bytes) accessor @ 14 java.lang.invoke.Invokers::checkCustomized (23 bytes) force inline by annotation @ 1 java.lang.invoke.MethodHandleImpl::isCompileConstant (2 bytes) (intrinsic) @ 18 java.lang.invoke.LambdaForm$Value$MH_invoke007_L_I/1113882874::invoke007_L_I (111 bytes) force inline by annotation @ 49 java.lang.invoke.LambdaForm$DMH022/41422182::invokeStatic011_L_I (13 bytes) force inline by annotation @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) force inline by annotation @ 9 GWTTest::test (2 bytes) inline (hot) ! @ 61 java.lang.invoke.MethodHandleImpl::profileBoolean (34 bytes) (intrinsic) @ 76 java.lang.invoke.MethodHandleImpl::selectAlternative (8 bytes) inline (hot) @ 83 java.lang.invoke.LambdaForm$Value$MH_delegate003_L_Q/1689665807::delegate003_L_Q (13 bytes) force inline by annotation @ 4 java.lang.invoke.MethodHandleImpl$CountingWrapper::getTarget (5 bytes) accessor @ 9 java.lang.invoke.LambdaForm$Value$MH_invoke006_L_Q/750887502::invoke006_L_Q (39 bytes) force inline by annotation @ 15 java.lang.invoke.LambdaForm$DMH020/1291241230::invokeStatic010_L_L (13 bytes) force inline by annotation @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) force inline by annotation @ 9 GWTTest::v2 (4 bytes) inline (hot) @ 35 java.lang.invoke.LambdaForm$Value$DMH_invokeStatic014_LL_Q/973967552::invokeStatic014_LL_Q (14 bytes) force inline by annotation @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) force inline by annotation @ 10 GWTTest$V_unbox/53039101::GWTTest$V_unbox (5 bytes) inline (hot) @ 107 java.lang.invoke.LambdaForm$Value$DMH_invokeStatic016_LQ_I/1720437373::invokeStatic016_LQ_I (15 bytes) force inline by annotation @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) force inline by annotation @ 11 GWTTest$V_getter$x/1298010894::GWTTest$V_getter$x (6 bytes) inline (hot) Paul. From paul.sandoz at oracle.com Wed Jun 21 01:35:16 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 20 Jun 2017 18:35:16 -0700 Subject: vwithfield and ValueType.findWither In-Reply-To: <5E571F25-0138-43A2-9A4C-835EE9F4B2BF@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> <13f3ff1c-8e72-9cd2-19ef-77aa928124a3@oracle.com> <57FBA69F-ECDE-4B98-9111-AE4199D2C1D7@oracle.com> <5E571F25-0138-43A2-9A4C-835EE9F4B2BF@oracle.com> Message-ID: Below is a patch for the first stage. Loosening the check in HS and updating findWither to use vwithfield. A follow on patch will refine the access control checks in findWither and add more tests. Paul. jdk: diff -r e3e5af317626 src/java.base/share/classes/jdk/experimental/value/ValueType.java --- a/src/java.base/share/classes/jdk/experimental/value/ValueType.java Mon Jun 19 11:07:52 2017 +0200 +++ b/src/java.base/share/classes/jdk/experimental/value/ValueType.java Tue Jun 20 18:29:39 2017 -0700 @@ -274,33 +274,13 @@ ValueHandleKey key = ValueHandleKind.WITHER.key(List.of(name, type)); MethodHandle result = handleMap.get(key); if (result == null) { - MethodHandle mh = boxLookup.findGetter(boxClass(), name, type); - Field field = MethodHandles.reflectAs(Field.class, mh); - Class erasedType = type.isPrimitive() ? - type : Object.class; - Method unsafeMethod = Stream.of(UNSAFE.getClass().getDeclaredMethods()) - .filter(m -> m.getName().startsWith("put") && - Arrays.asList(m.getParameterTypes()).equals(Arrays.asList(Object.class, long.class, erasedType))) - .findFirst().get(); - long fieldOffset = UNSAFE.objectFieldOffset(field); - result = MethodHandleBuilder.loadCode(boxLookup, mhName("wither$" + name), MethodType.methodType(valueClass(), MethodHandle.class, valueClass(), type), - C -> { - C.withLocal("boxedVal", BytecodeDescriptor.unparse(boxClass())) - .load(1) - .vbox(boxClass()) - .store("boxedVal") - .load(0) - .load("boxedVal") - .const_(fieldOffset) - .load(2); - MethodType unsafeMT = MethodType.methodType(unsafeMethod.getReturnType(), unsafeMethod.getParameterTypes()); - C.invokevirtual(MethodHandle.class, "invokeExact", BytecodeDescriptor.unparse(unsafeMT), false) - .load("boxedVal") - .vunbox(valueClass()) - .vreturn(); - }).bindTo(MethodHandles.lookup().unreflect(unsafeMethod).bindTo(UNSAFE)); + String fieldType = BytecodeDescriptor.unparse(type); + + result = MethodHandleBuilder.loadCode(valueLookup, mhName("wither$" + name), MethodType.methodType(valueClass(), valueClass(), type), + C -> C.vload(0).load(1).vwithfield(valueClass(), name, fieldType).vreturn()); handleMap.put(key, result); } + // @@@ special access check for read/write access //force access-check lookup.findGetter(boxClass(), name, type); return result; hotspot: diff -r c6878e14a2df src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Tue Jun 20 15:21:26 2017 +0200 +++ b/src/share/vm/interpreter/linkResolver.cpp Tue Jun 20 18:31:01 2017 -0700 @@ -951,6 +951,22 @@ stringStream ss; if (sel_klass != current_klass) { + // For Minimal Value Types check if the current class is an anonymous + // class whose host class is the Derived Value Type class (selected class) + // or the Value Capable Class (VCC) + if (byte == Bytecodes::_vwithfield) { + assert(sel_klass->is_value(), "Expected Value Type"); + if (current_klass->is_instance_klass() && InstanceKlass::cast(current_klass)->is_anonymous()) { + Klass* host_class = InstanceKlass::cast(current_klass)->host_klass(); // Is host VCC of DVT ? + + if (host_class == sel_klass || // Is DVT + (host_class->is_instance_klass() && // Is VCC + InstanceKlass::cast(host_class)->get_vcc_klass() == sel_klass)) { + return; + } + } + } + ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(), current_klass->external_name()); > On 19 Jun 2017, at 09:42, Paul Sandoz wrote: > > Hi David, > > That is almost the same direction i was thinking about. Specifically, fix HS so that for an anon class accessibility check is deferred to the host class. > > As you point out findWither now accepts a lookup: > > public MethodHandle findWither(Lookup lookup, String name, Class type) throws NoSuchFieldException, IllegalAccessException { > ? > //force access-check > lookup.findGetter(boxClass(), name, type); > return result; > } > > I am proposing that for findWither the developer pass a lookup created from MHs.privateLookupIn, thereby allowing to bypass the explicit access control checks in a controlled manner. IMO we don?t have to relax the access constraints on vwithfield. > > Separately we can improve the user experience by focusing on MHs for constructors. > > Paul. > >> On 19 Jun 2017, at 02:33, David Simms wrote: >> >> >> Re: "HotSpot code accessibility checks" >> >> I did play around with explicitly opening up access from the VCC: >> >> http://cr.openjdk.java.net/~dsimms/valhalla/vwithfield_access/webrev1/ >> >> (MethodHandleBuilder "vdefault" and "vwithfield" parts are already in) >> >> This code is specific to the VCC / DVT relationship, and was a bit of a hack to start the conversation some time back. We were happy living with the unsafe hack for the time being, but I would prefer to use stop using said work-around. >> >> I believe Dan's suggestion "Access restriction for vwithfield" on the design mail list is more practical (package private)...let's follow that conversation and get the JVMS definition right. >> >> Main points from previous discussions: >> >> * Original "vnew" proposal took all fields as stack args, all the time. >> o Hard to optimize, inefficient for value where most fields are >> "null/zero". >> o "vwithfield" easier to optimize (possible to elide COW >> semantics, efficiently change only required fields) >> * Allow the user-code to enforce invariant values >> o Able to implement "never publish (vastore, putfield) 'Foo' value >> with any zero fields" >> o Access restrictions from VCC or package private ? >> >> Recent changes to the ValueType API accepting MH lookup now gives a few more options to the user. >> >> /D >> >> On 15/06/17 19:32, Paul Sandoz wrote: >>> Hi Fred, >>> >>> Do you know where in the HotSpot code accessibility checks are performed for vwithfield? We need to fix those checks for Unsafe defined anonymous classes to defer to the host class (and if a suitable VCC or DVT then access should be granted). >>> >>> Paul. >>> >>>> On 15 Jun 2017, at 07:06, Frederic Parain wrote: >>>> >>>> >>>> >>>> On 06/15/2017 05:36 AM, Maurizio Cimadamore wrote: >>>>> >>>>> On 15/06/17 09:46, John Rose wrote: >>>>>> On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore >>>>>> wrote: >>>>>>> Another possible story is that we always create values through the >>>>>>> VCC constructor, and then unbox. If we think we're happy with that, >>>>>>> that might be a fine choice too. >>>>>> That's not a bad story for the JIT with aggressive scalarization, >>>>>> and was my first idea about this, but it is painful in the interpreter. >>>>>> >>>>> In which ways it's bad for the interpreter? Note that the current >>>>> implementation of the 'modified' findWither will do just that: >>>>> >>>>> * box incoming value >>>>> * set field (with Unsafe.putXYZ) >>>>> * unbox resulting reference back to a value >>>>> >>>>> So, it seems to me that, to set 5 fields, the above idiom will do >>>>> box/unbox 5 times, while if we just create a VCC with the fields we want >>>>> and then unbox, that's just one unboxing step. >>>>> >>>>> What am I missing? >>>> With the vwithfield bytecode, the interpreter can avoid Java heap >>>> allocations, with the box/Unsafe/unbox it cannot. >>>> >>>> Just a performance/memory issue. >>>> >>>> Fred >> >> > From mandy.chung at oracle.com Wed Jun 21 02:26:28 2017 From: mandy.chung at oracle.com (Mandy Chung) Date: Tue, 20 Jun 2017 19:26:28 -0700 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> Message-ID: > On Jun 20, 2017, at 4:19 PM, Maurizio Cimadamore wrote: > > The new version looks good - I wonder if we should add a dual method called isValueCapable(Class) and use that for the assertion check? The method would look at the class, retrieve the @VCC annotation and return true if one such annotation exists. > > As things stand, it is possible to pass classes to the loadValueClassType that are not VCC but which fail to trigger the assertion check. > > Probably a nitpick - but since we're tweaking in this area? > I added the isValueCapable method and made further clean up that I think MinimalValueTypes_1_0 class is clearer. http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.01/index.html Mandy From tobias.hartmann at oracle.com Wed Jun 21 06:40:28 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Wed, 21 Jun 2017 08:40:28 +0200 Subject: RFR: C2: fix call with __Value arguments In-Reply-To: References: <44b6c688-a91d-93a5-316c-d8a8c4913f14@oracle.com> Message-ID: Hi Roland, On 20.06.2017 21:32, Roland Westrelin wrote: > http://cr.openjdk.java.net/~roland/valhalla/__Value_args_cast/webrev.02/ This looks good to me. Nice that you were able to write some tests. Just a minor comment (you don't need to send another webrev): In callGenerator.cpp: "need to a pointer to the value type" -> "need a pointer to the value type" We are now using JIRA bugs/enhancements for all MVT related work. I created JDK-8182633 [1] for this, please close with a changeset comment after you pushed this. Thanks, Tobias [1] https://bugs.openjdk.java.net/browse/JDK-8182633 From maurizio.cimadamore at oracle.com Wed Jun 21 08:25:48 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 21 Jun 2017 09:25:48 +0100 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> Message-ID: That's great - thanks Mandy. One last thing (which can also be addressed as a followup changeset) - it seems like the: MinimalValueTypes_1_0.classHasValueType method is basically just an heavy alias for the new 'isValueCapable' predicate - which also attempts to load the class. I wonder if we wouldn't be better off simply using the predicate, which seems less heavy as it doesn't strictly require generation/loading of DVT. Although I can imagine that if a client calls that method, he'll be interested in the DVT anyway. That said, from an API perspective, having one method instead of two slightly different one is better, so we should aim for it, I think. [but, as I said before, the changeset you have looks good enough to be pushed - so it's up to you whether you wanna try it now or later, ok? ] Thanks Maurizio On 21/06/17 03:26, Mandy Chung wrote: >> On Jun 20, 2017, at 4:19 PM, Maurizio Cimadamore wrote: >> >> The new version looks good - I wonder if we should add a dual method called isValueCapable(Class) and use that for the assertion check? The method would look at the class, retrieve the @VCC annotation and return true if one such annotation exists. >> >> As things stand, it is possible to pass classes to the loadValueClassType that are not VCC but which fail to trigger the assertion check. >> >> Probably a nitpick - but since we're tweaking in this area? >> > I added the isValueCapable method and made further clean up that I think > MinimalValueTypes_1_0 Valueclass is clearer. > > http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.01/index.html > > Mandy From tobias.hartmann at oracle.com Wed Jun 21 11:35:43 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Wed, 21 Jun 2017 13:35:43 +0200 Subject: RFR(S): 8182645: [MVT] VM crashes with -XX:+VerifyOops and -XX:+VerifyStack Message-ID: <0159ffee-dee8-2fdb-8d9b-194a80148a51@oracle.com> Hi, please review the following patch: https://bugs.openjdk.java.net/browse/JDK-8182645 http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.22/ If ValueTypeTestBench is executed with -XX:+VerifyStack the VM crashes with "assert(callee != __null) failed: must have attached method". This is because signatures like "([[[Qcompiler/valhalla/valuetypes/MyValue1;[J)V" are confused with a value type argument. I fixed the signature scanning code in CompiledMethod::preserve_callee_argument_oops() and SharedRuntime::find_callee_arguments(). I also noticed that VerifyStack serves the same purpose as FullGCALotWithValueTypes which I introduced to trigger stack scanning - so I removed it. If ValueTypeTestBench is executed with -XX:+VerifyOops we crash during adapter verification with "assert(shared_entry->compare_code(buf->code_begin(), buffer.insts_size())) failed: code must match". This is because we now emit MacroAssembler::store_heap_oop()-> MacroAssembler::verify_oop() in the c2i/i2c adapters which may confuse the verification code due to constant string addresses that differ. Thanks, Tobias From rwestrel at redhat.com Wed Jun 21 13:03:45 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Wed, 21 Jun 2017 15:03:45 +0200 Subject: RFR(S): 8182645: [MVT] VM crashes with -XX:+VerifyOops and -XX:+VerifyStack In-Reply-To: <0159ffee-dee8-2fdb-8d9b-194a80148a51@oracle.com> References: <0159ffee-dee8-2fdb-8d9b-194a80148a51@oracle.com> Message-ID: > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.22/ That looks good to me. Roland. From rwestrel at redhat.com Wed Jun 21 13:45:13 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Wed, 21 Jun 2017 15:45:13 +0200 Subject: RFR(M): 8182471: [MVT] Eliminate redundant value type allocations In-Reply-To: References: Message-ID: > please review the following patch: > https://bugs.openjdk.java.net/browse/JDK-8182471 > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.20/ > > The optimization removes redundant value type allocations by searching > for a dominating allocation and re-using it to replace the dominated > allocation. This is done during loop optimizations because the GVN > version of is_dominator() and also MemNode::all_controls_dominate() > are not strong/good enough. To find candidate allocations, we now keep > an edge from the ValueTypeNode to the AllocateNode (see > ValueTypeNode::allocate()) and let GVN take care of merging identical > value type nodes. In ValueTypeNode::remove_redundant_allocations() we > then check for ValueTypeNodes with multiple AllocateNodes and > eliminate redundant ones (see test85-86). > > I also added code to recognize cases when we copy a value type by > "manually" loading its field values from memory. In this case, we can > re-use the oop (see test87-90) and avoid allocations. Is this what this code does: 462 if (!is_allocated(phase)) { 463 // Check if this value type is loaded from memory 464 Node* base = is_loaded(phase, type()->is_valuetype()); 465 if (base != NULL) { 466 // Save the oop 467 set_oop(base); 468 assert(is_allocated(phase), "should now be allocated"); 469 } 470 } ? I suppose val77 in the test case should be renamed. When we discussed this privately, you said that before allocating we have a runtime test to verify the value was not yet allocated and that that runtime test got in the way of your optimization. Did you find a way around that problem? Roland. From tobias.hartmann at oracle.com Wed Jun 21 14:23:09 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Wed, 21 Jun 2017 16:23:09 +0200 Subject: RFR(S): 8182645: [MVT] VM crashes with -XX:+VerifyOops and -XX:+VerifyStack In-Reply-To: References: <0159ffee-dee8-2fdb-8d9b-194a80148a51@oracle.com> Message-ID: Thanks Roland! Best regards, Tobias On 21.06.2017 15:03, Roland Westrelin wrote: > >> http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.22/ > > That looks good to me. > > Roland. > From tobias.hartmann at oracle.com Wed Jun 21 14:31:11 2017 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Wed, 21 Jun 2017 14:31:11 +0000 Subject: hg: valhalla/valhalla/hotspot: 8182645: [MVT] VM crashes with -XX:+VerifyOops and -XX:+VerifyStack Message-ID: <201706211431.v5LEVBFM027384@aojmv0008.oracle.com> Changeset: bdd41f6084eb Author: thartmann Date: 2017-06-21 16:29 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/bdd41f6084eb 8182645: [MVT] VM crashes with -XX:+VerifyOops and -XX:+VerifyStack Summary: Fixed signature scanning and adapter sharing verification. Reviewed-by: roland ! src/cpu/x86/vm/macroAssembler_x86.cpp ! src/share/vm/code/compiledMethod.cpp ! src/share/vm/runtime/globals.hpp ! src/share/vm/runtime/sharedRuntime.cpp ! test/compiler/valhalla/valuetypes/ValueTypeTestBench.java From tobias.hartmann at oracle.com Wed Jun 21 15:01:09 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Wed, 21 Jun 2017 17:01:09 +0200 Subject: RFR(M): 8182471: [MVT] Eliminate redundant value type allocations In-Reply-To: References: Message-ID: <0b6ed52d-71ea-ee1e-36ff-a1e3785c77f0@oracle.com> Hi Roland, thanks for reviewing this! On 21.06.2017 15:45, Roland Westrelin wrote: >> I also added code to recognize cases when we copy a value type by >> "manually" loading its field values from memory. In this case, we can >> re-use the oop (see test87-90) and avoid allocations. > > Is this what this code does: > > 462 if (!is_allocated(phase)) { > 463 // Check if this value type is loaded from memory > 464 Node* base = is_loaded(phase, type()->is_valuetype()); > 465 if (base != NULL) { > 466 // Save the oop > 467 set_oop(base); > 468 assert(is_allocated(phase), "should now be allocated"); > 469 } > 470 } Yes, it checks if the input field values are field loads from the same base oop (with correct type and offset). If so, this oop is re-used and the value type does not need to be allocated. > I suppose val77 in the test case should be renamed. Right, I renamed it to 'staticVal3' and updated the webrev in-place. > When we discussed this privately, you said that before allocating we > have a runtime test to verify the value was not yet allocated and that > that runtime test got in the way of your optimization. Did you find a > way around that problem? Unfortunately, I don't remember the exact issue but I think the problem was not the runtime oop check but the dominator check not being able to determine domination of another allocation (that's what I meant by "the GVN version of is_dominator() and also MemNode::all_controls_dominate() are not strong/good enough"). The current version works well in all the cases I've tested. Thanks, Tobias From mandy.chung at oracle.com Wed Jun 21 15:56:23 2017 From: mandy.chung at oracle.com (Mandy Chung) Date: Wed, 21 Jun 2017 08:56:23 -0700 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> Message-ID: > On Jun 21, 2017, at 1:25 AM, Maurizio Cimadamore wrote: > > That's great - thanks Mandy. One last thing (which can also be addressed as a followup changeset) - it seems like the: > > MinimalValueTypes_1_0.classHasValueType > > method is basically just an heavy alias for the new 'isValueCapable' predicate - which also attempts to load the class. I wonder if we wouldn't be better off simply using the predicate, which seems less heavy as it doesn't strictly require generation/loading of DVT. Although I can imagine that if a client calls that method, he'll be interested in the DVT anyway. > I had similar question and wonder if this is needed at all. If one wants to load DVT, it can call getValueTypeClass instead. I think we should simply remove it. ValueType::classHasValueType is not used. Should this be replaced with isValueCapable? Is there a case no DVT defined for VCC (which would be the case classHasValueType would return false for VCC) but I suspect not? > That said, from an API perspective, having one method instead of two slightly different one is better, so we should aim for it, I think. > Agree. > [but, as I said before, the changeset you have looks good enough to be pushed - so it's up to you whether you wanna try it now or later, ok? ] > I will make this change once we agree what to do for ValueType::classHasValueType. I?ll be traveling to Hong Kong tomorrow. I don?t want to push something and not available. I may push next Monday. Mandy > Thanks > Maurizio > > > > On 21/06/17 03:26, Mandy Chung wrote: >>> On Jun 20, 2017, at 4:19 PM, Maurizio Cimadamore wrote: >>> >>> The new version looks good - I wonder if we should add a dual method called isValueCapable(Class) and use that for the assertion check? The method would look at the class, retrieve the @VCC annotation and return true if one such annotation exists. >>> >>> As things stand, it is possible to pass classes to the loadValueClassType that are not VCC but which fail to trigger the assertion check. >>> >>> Probably a nitpick - but since we're tweaking in this area? >>> >> I added the isValueCapable method and made further clean up that I think >> MinimalValueTypes_1_0 Valueclass is clearer. >> >> http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.01/index.html >> >> Mandy > From maurizio.cimadamore at oracle.com Wed Jun 21 16:44:36 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 21 Jun 2017 17:44:36 +0100 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> Message-ID: <5d6c06f9-6559-fa57-ea65-ec7d9634f62e@oracle.com> On 21/06/17 16:56, Mandy Chung wrote: >> On Jun 21, 2017, at 1:25 AM, Maurizio Cimadamore wrote: >> >> That's great - thanks Mandy. One last thing (which can also be addressed as a followup changeset) - it seems like the: >> >> MinimalValueTypes_1_0.classHasValueType >> >> method is basically just an heavy alias for the new 'isValueCapable' predicate - which also attempts to load the class. I wonder if we wouldn't be better off simply using the predicate, which seems less heavy as it doesn't strictly require generation/loading of DVT. Although I can imagine that if a client calls that method, he'll be interested in the DVT anyway. >> > I had similar question and wonder if this is needed at all. If one wants to load DVT, it can call getValueTypeClass instead. I think we should simply remove it. > > ValueType::classHasValueType is not used. Should this be replaced with isValueCapable? Is there a case no DVT defined for VCC (which would be the case classHasValueType would return false for VCC) but I suspect not? I believe ValueType is supposed to be a public API, while MinimalValueType_1_0 is not. So, maybe we should keep that one as a sort of reflective predicate. > > >> That said, from an API perspective, having one method instead of two slightly different one is better, so we should aim for it, I think. >> > Agree. > >> [but, as I said before, the changeset you have looks good enough to be pushed - so it's up to you whether you wanna try it now or later, ok? ] >> > I will make this change once we agree what to do for ValueType::classHasValueType. > > I?ll be traveling to Hong Kong tomorrow. I don?t want to push something and not available. I may push next Monday. Cool Thanks Maurizio > > Mandy > >> Thanks >> Maurizio >> >> >> >> On 21/06/17 03:26, Mandy Chung wrote: >>>> On Jun 20, 2017, at 4:19 PM, Maurizio Cimadamore wrote: >>>> >>>> The new version looks good - I wonder if we should add a dual method called isValueCapable(Class) and use that for the assertion check? The method would look at the class, retrieve the @VCC annotation and return true if one such annotation exists. >>>> >>>> As things stand, it is possible to pass classes to the loadValueClassType that are not VCC but which fail to trigger the assertion check. >>>> >>>> Probably a nitpick - but since we're tweaking in this area? >>>> >>> I added the isValueCapable method and made further clean up that I think >>> MinimalValueTypes_1_0 Valueclass is clearer. >>> >>> http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.01/index.html >>> >>> Mandy From paul.sandoz at oracle.com Wed Jun 21 17:08:30 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 21 Jun 2017 10:08:30 -0700 Subject: couple questions on method handle combinators In-Reply-To: References: <4907cae0-7948-05a6-4e2e-b274b0149da8@oracle.com> <23fb65dc-36f1-8606-4589-4f4160b1fbb0@oracle.com> Message-ID: > On 16 Jun 2017, at 09:02, Roland Westrelin wrote: > > >> Most likely, there's something missing for Q-typed shapes which disables >> SELECT_ALTERNATIVE intrinsic. > > Thanks Vladimir, Paul and Maurizio. As I understand, the code shape that > I worry about can't be generated currently with GWT. I'll revisit that > issue when GWT has improved. Even the GWT test i wrote that now works with you patch? > > Do we expect to see a lot of uses of the loop method handle combinator > with mvt? I wonder if it's worth looking into loop combinators more? > I expect loop combinators to be used more. This will require us to beef up the byte code generation to be on par with that for L shapes. However, in general i anticipate a combination of method handles and explicit code generation may be required by a developer. I sense it?s gonna be hard contain the value type energy within a method handle combinator container field. Those exotic value type particles are unstable and wanna collapse into their lower energy state boxes. Some code generation rods will help stabilise things. Paul. From mandy.chung at oracle.com Wed Jun 21 20:21:09 2017 From: mandy.chung at oracle.com (Mandy Chung) Date: Wed, 21 Jun 2017 13:21:09 -0700 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <5d6c06f9-6559-fa57-ea65-ec7d9634f62e@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> <5d6c06f9-6559-fa57-ea65-ec7d9634f62e@oracle.com> Message-ID: > On Jun 21, 2017, at 9:44 AM, Maurizio Cimadamore wrote: > > > On 21/06/17 16:56, Mandy Chung wrote: >> >> ValueType::classHasValueType is not used. Should this be replaced with isValueCapable? Is there a case no DVT defined for VCC (which would be the case classHasValueType would return false for VCC) but I suspect not? > I believe ValueType is supposed to be a public API, while MinimalValueType_1_0 is not. So, maybe we should keep that one as a sort of reflective predicate. I keep ValueType::classHasValueType the same behavior that loads DVT before returning. I suspect it may not be necessesary but we can re-examine that in the future. http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.02/ Changes w.r.t. webrev.01 1. Removed classHasValueType(Class) and getValueTypeClass(Class) which is only used by classHasValueType. 2. getValueCapableClass and getValueTypeClass no longer throws CNFE (it throws IAE if the given type is not DVT or VCC). MethodHandles is updated due to the removal of this checked exception. 3. I added valhalla/mvt to jdk_lang test group that makes it handy to do verification. thanks Mandy From maurizio.cimadamore at oracle.com Thu Jun 22 00:12:20 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 22 Jun 2017 01:12:20 +0100 Subject: RFR JDK-8182678: add javac and method handle support for mangled value class names in CONSTANT_ClassInfo Message-ID: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> Hi the following two patches: http://cr.openjdk.java.net/~mcimadamore/8182678_langtools/ http://cr.openjdk.java.net/~mcimadamore/8182678_jdk/ Add support for mangled value class names in ClassInfo for both javac and the bytecode API (used for MH spinning). The support is enabled with these two options: javac: -XDmangleClassInfo jdk: -Dvalhalla.mangleClassInfo=true I also added class reading support to javac - and that's always enabled. I verified that javap works as expected - since a ClassInfo is just a string, javap doesn't complain if there's an extra ';' prefix in there, so things looks good already. Cheers Maurizio From maurizio.cimadamore at oracle.com Thu Jun 22 00:23:16 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 22 Jun 2017 01:23:16 +0100 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> <5d6c06f9-6559-fa57-ea65-ec7d9634f62e@oracle.com> Message-ID: <0100337c-2e7f-b3ad-ca21-a62fdc42f3bc@oracle.com> I notice some asymmetry between the VCC and DVT cases. For VCC we have: * isValueCapable(Class) * getValueCapableClass(Class) For DVT we have * isValueType(Class) * getValueTypeClass(Class) * loadValueTypeClass(Class) There are two kind of inconsistencies at play here - one is a plain naming issue - the suffix Class is not using consistently in all the methods. The second inconsistency is that for a DVT we distinguish between get/load, while for VCC we do not. But it's a moot distinction, given that getValueTypeClass will always call loadValueTypeClass (and recheck same assertion). Maybe we should fuse those two methods? Cheers Maurizio On 21/06/17 21:21, Mandy Chung wrote: >> On Jun 21, 2017, at 9:44 AM, Maurizio Cimadamore wrote: >> >> >> On 21/06/17 16:56, Mandy Chung wrote: >>> ValueType::classHasValueType is not used. Should this be replaced with isValueCapable? Is there a case no DVT defined for VCC (which would be the case classHasValueType would return false for VCC) but I suspect not? >> I believe ValueType is supposed to be a public API, while MinimalValueType_1_0 is not. So, maybe we should keep that one as a sort of reflective predicate. > I keep ValueType::classHasValueType the same behavior that loads DVT before > returning. I suspect it may not be necessesary but we can re-examine that > in the future. > > http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.02/ > > Changes w.r.t. webrev.01 > 1. Removed classHasValueType(Class) and getValueTypeClass(Class) which > is only used by classHasValueType. > 2. getValueCapableClass and getValueTypeClass no longer throws CNFE > (it throws IAE if the given type is not DVT or VCC). MethodHandles is > updated due to the removal of this checked exception. > 3. I added valhalla/mvt to jdk_lang test group that makes it handy to do verification. > > thanks > Mandy From paul.sandoz at oracle.com Thu Jun 22 00:50:48 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 21 Jun 2017 17:50:48 -0700 Subject: vwithfield and ValueType.findWither In-Reply-To: References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> <13f3ff1c-8e72-9cd2-19ef-77aa928124a3@oracle.com> <57FBA69F-ECDE-4B98-9111-AE4199D2C1D7@oracle.com> <5E571F25-0138-43A2-9A4C-835EE9F4B2BF@oracle.com> Message-ID: <707D2356-DEC1-467C-8A04-6F5888F94E57@oracle.com> Here is webrev: http://cr.openjdk.java.net/~psandoz/valhalla/vwithfield/webrev/ Including more updates to HS and a test. Paul. > On 20 Jun 2017, at 18:35, Paul Sandoz wrote: > > Below is a patch for the first stage. Loosening the check in HS and updating findWither to use vwithfield. > > A follow on patch will refine the access control checks in findWither and add more tests. > > Paul. > > jdk: > diff -r e3e5af317626 src/java.base/share/classes/jdk/experimental/value/ValueType.java > --- a/src/java.base/share/classes/jdk/experimental/value/ValueType.java Mon Jun 19 11:07:52 2017 +0200 > +++ b/src/java.base/share/classes/jdk/experimental/value/ValueType.java Tue Jun 20 18:29:39 2017 -0700 > @@ -274,33 +274,13 @@ > ValueHandleKey key = ValueHandleKind.WITHER.key(List.of(name, type)); > MethodHandle result = handleMap.get(key); > if (result == null) { > - MethodHandle mh = boxLookup.findGetter(boxClass(), name, type); > - Field field = MethodHandles.reflectAs(Field.class, mh); > - Class erasedType = type.isPrimitive() ? > - type : Object.class; > - Method unsafeMethod = Stream.of(UNSAFE.getClass().getDeclaredMethods()) > - .filter(m -> m.getName().startsWith("put") && > - Arrays.asList(m.getParameterTypes()).equals(Arrays.asList(Object.class, long.class, erasedType))) > - .findFirst().get(); > - long fieldOffset = UNSAFE.objectFieldOffset(field); > - result = MethodHandleBuilder.loadCode(boxLookup, mhName("wither$" + name), MethodType.methodType(valueClass(), MethodHandle.class, valueClass(), type), > - C -> { > - C.withLocal("boxedVal", BytecodeDescriptor.unparse(boxClass())) > - .load(1) > - .vbox(boxClass()) > - .store("boxedVal") > - .load(0) > - .load("boxedVal") > - .const_(fieldOffset) > - .load(2); > - MethodType unsafeMT = MethodType.methodType(unsafeMethod.getReturnType(), unsafeMethod.getParameterTypes()); > - C.invokevirtual(MethodHandle.class, "invokeExact", BytecodeDescriptor.unparse(unsafeMT), false) > - .load("boxedVal") > - .vunbox(valueClass()) > - .vreturn(); > - }).bindTo(MethodHandles.lookup().unreflect(unsafeMethod).bindTo(UNSAFE)); > + String fieldType = BytecodeDescriptor.unparse(type); > + > + result = MethodHandleBuilder.loadCode(valueLookup, mhName("wither$" + name), MethodType.methodType(valueClass(), valueClass(), type), > + C -> C.vload(0).load(1).vwithfield(valueClass(), name, fieldType).vreturn()); > handleMap.put(key, result); > } > + // @@@ special access check for read/write access > //force access-check > lookup.findGetter(boxClass(), name, type); > return result; > > > hotspot: > diff -r c6878e14a2df src/share/vm/interpreter/linkResolver.cpp > --- a/src/share/vm/interpreter/linkResolver.cpp Tue Jun 20 15:21:26 2017 +0200 > +++ b/src/share/vm/interpreter/linkResolver.cpp Tue Jun 20 18:31:01 2017 -0700 > @@ -951,6 +951,22 @@ > stringStream ss; > > if (sel_klass != current_klass) { > + // For Minimal Value Types check if the current class is an anonymous > + // class whose host class is the Derived Value Type class (selected class) > + // or the Value Capable Class (VCC) > + if (byte == Bytecodes::_vwithfield) { > + assert(sel_klass->is_value(), "Expected Value Type"); > + if (current_klass->is_instance_klass() && InstanceKlass::cast(current_klass)->is_anonymous()) { > + Klass* host_class = InstanceKlass::cast(current_klass)->host_klass(); // Is host VCC of DVT ? > + > + if (host_class == sel_klass || // Is DVT > + (host_class->is_instance_klass() && // Is VCC > + InstanceKlass::cast(host_class)->get_vcc_klass() == sel_klass)) { > + return; > + } > + } > + } > + > ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class", > is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(), > current_klass->external_name()); > >> On 19 Jun 2017, at 09:42, Paul Sandoz wrote: >> >> Hi David, >> >> That is almost the same direction i was thinking about. Specifically, fix HS so that for an anon class accessibility check is deferred to the host class. >> >> As you point out findWither now accepts a lookup: >> >> public MethodHandle findWither(Lookup lookup, String name, Class type) throws NoSuchFieldException, IllegalAccessException { >> ? >> //force access-check >> lookup.findGetter(boxClass(), name, type); >> return result; >> } >> >> I am proposing that for findWither the developer pass a lookup created from MHs.privateLookupIn, thereby allowing to bypass the explicit access control checks in a controlled manner. IMO we don?t have to relax the access constraints on vwithfield. >> >> Separately we can improve the user experience by focusing on MHs for constructors. >> >> Paul. >> >>> On 19 Jun 2017, at 02:33, David Simms wrote: >>> >>> >>> Re: "HotSpot code accessibility checks" >>> >>> I did play around with explicitly opening up access from the VCC: >>> >>> http://cr.openjdk.java.net/~dsimms/valhalla/vwithfield_access/webrev1/ >>> >>> (MethodHandleBuilder "vdefault" and "vwithfield" parts are already in) >>> >>> This code is specific to the VCC / DVT relationship, and was a bit of a hack to start the conversation some time back. We were happy living with the unsafe hack for the time being, but I would prefer to use stop using said work-around. >>> >>> I believe Dan's suggestion "Access restriction for vwithfield" on the design mail list is more practical (package private)...let's follow that conversation and get the JVMS definition right. >>> >>> Main points from previous discussions: >>> >>> * Original "vnew" proposal took all fields as stack args, all the time. >>> o Hard to optimize, inefficient for value where most fields are >>> "null/zero". >>> o "vwithfield" easier to optimize (possible to elide COW >>> semantics, efficiently change only required fields) >>> * Allow the user-code to enforce invariant values >>> o Able to implement "never publish (vastore, putfield) 'Foo' value >>> with any zero fields" >>> o Access restrictions from VCC or package private ? >>> >>> Recent changes to the ValueType API accepting MH lookup now gives a few more options to the user. >>> >>> /D >>> >>> On 15/06/17 19:32, Paul Sandoz wrote: >>>> Hi Fred, >>>> >>>> Do you know where in the HotSpot code accessibility checks are performed for vwithfield? We need to fix those checks for Unsafe defined anonymous classes to defer to the host class (and if a suitable VCC or DVT then access should be granted). >>>> >>>> Paul. >>>> >>>>> On 15 Jun 2017, at 07:06, Frederic Parain wrote: >>>>> >>>>> >>>>> >>>>> On 06/15/2017 05:36 AM, Maurizio Cimadamore wrote: >>>>>> >>>>>> On 15/06/17 09:46, John Rose wrote: >>>>>>> On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore >>>>>>> wrote: >>>>>>>> Another possible story is that we always create values through the >>>>>>>> VCC constructor, and then unbox. If we think we're happy with that, >>>>>>>> that might be a fine choice too. >>>>>>> That's not a bad story for the JIT with aggressive scalarization, >>>>>>> and was my first idea about this, but it is painful in the interpreter. >>>>>>> >>>>>> In which ways it's bad for the interpreter? Note that the current >>>>>> implementation of the 'modified' findWither will do just that: >>>>>> >>>>>> * box incoming value >>>>>> * set field (with Unsafe.putXYZ) >>>>>> * unbox resulting reference back to a value >>>>>> >>>>>> So, it seems to me that, to set 5 fields, the above idiom will do >>>>>> box/unbox 5 times, while if we just create a VCC with the fields we want >>>>>> and then unbox, that's just one unboxing step. >>>>>> >>>>>> What am I missing? >>>>> With the vwithfield bytecode, the interpreter can avoid Java heap >>>>> allocations, with the box/Unsafe/unbox it cannot. >>>>> >>>>> Just a performance/memory issue. >>>>> >>>>> Fred >>> >>> >> > From paul.sandoz at oracle.com Thu Jun 22 01:22:01 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 21 Jun 2017 18:22:01 -0700 Subject: RFR JDK-8182678: add javac and method handle support for mangled value class names in CONSTANT_ClassInfo In-Reply-To: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> References: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> Message-ID: Looks good, although it would be nice if the javac and java properties were the same name as it?s hard to remember the plethora of such properties that are available. Paul. > On 21 Jun 2017, at 17:12, Maurizio Cimadamore wrote: > > Hi > the following two patches: > > http://cr.openjdk.java.net/~mcimadamore/8182678_langtools/ > http://cr.openjdk.java.net/~mcimadamore/8182678_jdk/ > > Add support for mangled value class names in ClassInfo for both javac and the bytecode API (used for MH spinning). > > The support is enabled with these two options: > > javac: -XDmangleClassInfo > > jdk: -Dvalhalla.mangleClassInfo=true > > > I also added class reading support to javac - and that's always enabled. > > I verified that javap works as expected - since a ClassInfo is just a string, javap doesn't complain if there's an extra ';' prefix in there, so things looks good already. > > Cheers > Maurizio > > From mandy.chung at oracle.com Thu Jun 22 02:21:37 2017 From: mandy.chung at oracle.com (Mandy Chung) Date: Wed, 21 Jun 2017 19:21:37 -0700 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <0100337c-2e7f-b3ad-ca21-a62fdc42f3bc@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> <5d6c06f9-6559-fa57-ea65-ec7d9634f62e@oracle.com> <0100337c-2e7f-b3ad-ca21-a62fdc42f3bc@oracle.com> Message-ID: > On Jun 21, 2017, at 5:23 PM, Maurizio Cimadamore wrote: > > I notice some asymmetry between the VCC and DVT cases. For VCC we have: > > * isValueCapable(Class) > * getValueCapableClass(Class) > > For DVT we have > > * isValueType(Class) > * getValueTypeClass(Class) > * loadValueTypeClass(Class) > > There are two kind of inconsistencies at play here - one is a plain naming issue - the suffix Class is not using consistently in all the methods. > I believe David was the author of the MinimalValueType_1_0 class and he might want to comment here. I haven?t read up the documents in details to determine the proper terminologies. But I have to admit that I was initially confused with isValueType that refers to DVT. I would suggest to rename 'ValueType? to ?DerivedValueType? and drop the suffix ?Class? from *ValueType* methods and rename ValueCapable to ValueCapableClass to match DVT and VCC. I don?t mind doing the renaming and I can follow up as a separate changeset. > The second inconsistency is that for a DVT we distinguish between get/load, while for VCC we do not. But it's a moot distinction, given that getValueTypeClass will always call loadValueTypeClass (and recheck same assertion). Maybe we should fuse those two methods? ValueType::arrayValueClass calls MinimalValueTypes_1_0::loadValueTypeClass to define an array of DVT. That?s why they are separate. I expect there are lot more cleanup to be done once I get familiar with the implementation. Mandy > > Cheers > Maurizio > > > > On 21/06/17 21:21, Mandy Chung wrote: >>> On Jun 21, 2017, at 9:44 AM, Maurizio Cimadamore wrote: >>> >>> >>> On 21/06/17 16:56, Mandy Chung wrote: >>>> ValueType::classHasValueType is not used. Should this be replaced with isValueCapable? Is there a case no DVT defined for VCC (which would be the case classHasValueType would return false for VCC) but I suspect not? >>> I believe ValueType is supposed to be a public API, while MinimalValueType_1_0 is not. So, maybe we should keep that one as a sort of reflective predicate. >> I keep ValueType::classHasValueType the same behavior that loads DVT before >> returning. I suspect it may not be necessesary but we can re-examine that >> in the future. >> >> http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.02/ >> >> Changes w.r.t. webrev.01 >> 1. Removed classHasValueType(Class) and getValueTypeClass(Class) which >> is only used by classHasValueType. >> 2. getValueCapableClass and getValueTypeClass no longer throws CNFE >> (it throws IAE if the given type is not DVT or VCC). MethodHandles is >> updated due to the removal of this checked exception. >> 3. I added valhalla/mvt to jdk_lang test group that makes it handy to do verification. >> >> thanks >> Mandy > From david.simms at oracle.com Thu Jun 22 09:52:26 2017 From: david.simms at oracle.com (David Simms) Date: Thu, 22 Jun 2017 11:52:26 +0200 Subject: vwithfield and ValueType.findWither In-Reply-To: <707D2356-DEC1-467C-8A04-6F5888F94E57@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> <13f3ff1c-8e72-9cd2-19ef-77aa928124a3@oracle.com> <57FBA69F-ECDE-4B98-9111-AE4199D2C1D7@oracle.com> <5E571F25-0138-43A2-9A4C-835EE9F4B2BF@oracle.com> <707D2356-DEC1-467C-8A04-6F5888F94E57@oracle.com> Message-ID: Looks good to me, special thanks for adding more testing, excellent. /David Simms On 22/06/17 02:50, Paul Sandoz wrote: > Here is webrev: > > http://cr.openjdk.java.net/~psandoz/valhalla/vwithfield/webrev/ > > > Including more updates to HS and a test. > > Paul. > >> On 20 Jun 2017, at 18:35, Paul Sandoz > > wrote: >> >> Below is a patch for the first stage. Loosening the check in HS and >> updating findWither to use vwithfield. >> >> A follow on patch will refine the access control checks in findWither >> and add more tests. >> >> Paul. >> >> jdk: >> diff -r e3e5af317626 >> src/java.base/share/classes/jdk/experimental/value/ValueType.java >> --- >> a/src/java.base/share/classes/jdk/experimental/value/ValueType.javaMon >> Jun 19 11:07:52 2017 +0200 >> +++ >> b/src/java.base/share/classes/jdk/experimental/value/ValueType.javaTue >> Jun 20 18:29:39 2017 -0700 >> @@ -274,33 +274,13 @@ >> ValueHandleKey key = ValueHandleKind.WITHER.key(List.of(name, >> type)); >> MethodHandle result = handleMap.get(key); >> if (result == null) { >> - MethodHandle mh = boxLookup.findGetter(boxClass(), name, >> type); >> - Field field = MethodHandles.reflectAs(Field.class, mh); >> - Class erasedType = type.isPrimitive() ? >> - type : Object.class; >> - Method unsafeMethod = >> Stream.of(UNSAFE.getClass().getDeclaredMethods()) >> - .filter(m -> m.getName().startsWith("put") && >> - >> Arrays.asList(m.getParameterTypes()).equals(Arrays.asList(Object.class, >> long.class, erasedType))) >> - .findFirst().get(); >> - long fieldOffset = UNSAFE.objectFieldOffset(field); >> - result = MethodHandleBuilder.loadCode(boxLookup, >> mhName("wither$" + name), MethodType.methodType(valueClass(), >> MethodHandle.class, valueClass(), type), >> - C -> { >> - C.withLocal("boxedVal", >> BytecodeDescriptor.unparse(boxClass())) >> - .load(1) >> - .vbox(boxClass()) >> - .store("boxedVal") >> - .load(0) >> - .load("boxedVal") >> - .const_(fieldOffset) >> - .load(2); >> - MethodType unsafeMT = >> MethodType.methodType(unsafeMethod.getReturnType(), >> unsafeMethod.getParameterTypes()); >> - C.invokevirtual(MethodHandle.class, >> "invokeExact", BytecodeDescriptor.unparse(unsafeMT), false) >> - .load("boxedVal") >> - .vunbox(valueClass()) >> - .vreturn(); >> - >> }).bindTo(MethodHandles.lookup().unreflect(unsafeMethod).bindTo(UNSAFE)); >> + String fieldType = BytecodeDescriptor.unparse(type); >> + >> + result = MethodHandleBuilder.loadCode(valueLookup, >> mhName("wither$" + name), MethodType.methodType(valueClass(), >> valueClass(), type), >> + C -> C.vload(0).load(1).vwithfield(valueClass(), >> name, fieldType).vreturn()); >> handleMap.put(key, result); >> } >> + // @@@ special access check for read/write access >> //force access-check >> lookup.findGetter(boxClass(), name, type); >> return result; >> >> >> hotspot: >> diff -r c6878e14a2df src/share/vm/interpreter/linkResolver.cpp >> --- a/src/share/vm/interpreter/linkResolver.cppTue Jun 20 15:21:26 >> 2017 +0200 >> +++ b/src/share/vm/interpreter/linkResolver.cppTue Jun 20 18:31:01 >> 2017 -0700 >> @@ -951,6 +951,22 @@ >> stringStream ss; >> >> if (sel_klass != current_klass) { >> + // For Minimal Value Types check if the current class is an >> anonymous >> + // class whose host class is the Derived Value Type class >> (selected class) >> + // or the Value Capable Class (VCC) >> + if (byte == Bytecodes::_vwithfield) { >> + assert(sel_klass->is_value(), "Expected Value Type"); >> + if (current_klass->is_instance_klass() && >> InstanceKlass::cast(current_klass)->is_anonymous()) { >> + Klass* host_class = >> InstanceKlass::cast(current_klass)->host_klass(); // Is host VCC of DVT ? >> + >> + if (host_class == sel_klass || // Is DVT >> + (host_class->is_instance_klass() && // Is VCC >> + InstanceKlass::cast(host_class)->get_vcc_klass() == >> sel_klass)) { >> + return; >> + } >> + } >> + } >> + >> ss.print("Update to %s final field %s.%s attempted from a >> different class (%s) than the field's declaring class", >> is_static ? "static" : "non-static", >> resolved_klass->external_name(), fd.name()->as_C_string(), >> current_klass->external_name()); >> >>> On 19 Jun 2017, at 09:42, Paul Sandoz >> > wrote: >>> >>> Hi David, >>> >>> That is almost the same direction i was thinking about. >>> Specifically, fix HS so that for an anon class accessibility check >>> is deferred to the host class. >>> >>> As you point out findWither now accepts a lookup: >>> >>> public MethodHandle findWither(Lookup lookup, String name, Class >>> type) throws NoSuchFieldException, IllegalAccessException { >>> ? >>> //force access-check >>> lookup.findGetter(boxClass(), name, type); >>> return result; >>> } >>> >>> I am proposing that for findWither the developer pass a lookup >>> created from MHs.privateLookupIn, thereby allowing to bypass the >>> explicit access control checks in a controlled manner. IMO we don?t >>> have to relax the access constraints on vwithfield. >>> >>> Separately we can improve the user experience by focusing on MHs for >>> constructors. >>> >>> Paul. >>> >>>> On 19 Jun 2017, at 02:33, David Simms >>> > wrote: >>>> >>>> >>>> Re: "HotSpot code accessibility checks" >>>> >>>> I did play around with explicitly opening up access from the VCC: >>>> >>>> http://cr.openjdk.java.net/~dsimms/valhalla/vwithfield_access/webrev1/ >>>> >>>> >>>> (MethodHandleBuilder "vdefault" and "vwithfield" parts are already in) >>>> >>>> This code is specific to the VCC / DVT relationship, and was a bit >>>> of a hack to start the conversation some time back. We were happy >>>> living with the unsafe hack for the time being, but I would prefer >>>> to use stop using said work-around. >>>> >>>> I believe Dan's suggestion "Access restriction for vwithfield" on >>>> the design mail list is more practical (package private)...let's >>>> follow that conversation and get the JVMS definition right. >>>> >>>> Main points from previous discussions: >>>> >>>> * Original "vnew" proposal took all fields as stack args, all the time. >>>> o Hard to optimize, inefficient for value where most fields are >>>> "null/zero". >>>> o "vwithfield" easier to optimize (possible to elide COW >>>> semantics, efficiently change only required fields) >>>> * Allow the user-code to enforce invariant values >>>> o Able to implement "never publish (vastore, putfield) 'Foo' value >>>> with any zero fields" >>>> o Access restrictions from VCC or package private ? >>>> >>>> Recent changes to the ValueType API accepting MH lookup now gives a >>>> few more options to the user. >>>> >>>> /D >>>> >>>> On 15/06/17 19:32, Paul Sandoz wrote: >>>>> Hi Fred, >>>>> >>>>> Do you know where in the HotSpot code accessibility checks are >>>>> performed for vwithfield? We need to fix those checks for Unsafe >>>>> defined anonymous classes to defer to the host class (and if a >>>>> suitable VCC or DVT then access should be granted). >>>>> >>>>> Paul. >>>>> >>>>>> On 15 Jun 2017, at 07:06, Frederic Parain >>>>>> wrote: >>>>>> >>>>>> >>>>>> >>>>>> On 06/15/2017 05:36 AM, Maurizio Cimadamore wrote: >>>>>>> >>>>>>> On 15/06/17 09:46, John Rose wrote: >>>>>>>> On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore >>>>>>>> wrote: >>>>>>>>> Another possible story is that we always create values through the >>>>>>>>> VCC constructor, and then unbox. If we think we're happy with >>>>>>>>> that, >>>>>>>>> that might be a fine choice too. >>>>>>>> That's not a bad story for the JIT with aggressive scalarization, >>>>>>>> and was my first idea about this, but it is painful in the >>>>>>>> interpreter. >>>>>>>> >>>>>>> In which ways it's bad for the interpreter? Note that the current >>>>>>> implementation of the 'modified' findWither will do just that: >>>>>>> >>>>>>> * box incoming value >>>>>>> * set field (with Unsafe.putXYZ) >>>>>>> * unbox resulting reference back to a value >>>>>>> >>>>>>> So, it seems to me that, to set 5 fields, the above idiom will do >>>>>>> box/unbox 5 times, while if we just create a VCC with the fields >>>>>>> we want >>>>>>> and then unbox, that's just one unboxing step. >>>>>>> >>>>>>> What am I missing? >>>>>> With the vwithfield bytecode, the interpreter can avoid Java heap >>>>>> allocations, with the box/Unsafe/unbox it cannot. >>>>>> >>>>>> Just a performance/memory issue. >>>>>> >>>>>> Fred >>>> >>>> >>> >> > From maurizio.cimadamore at oracle.com Thu Jun 22 11:27:07 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 22 Jun 2017 12:27:07 +0100 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> <5d6c06f9-6559-fa57-ea65-ec7d9634f62e@oracle.com> <0100337c-2e7f-b3ad-ca21-a62fdc42f3bc@oracle.com> Message-ID: <94b194e7-1cf3-99c6-5645-d54d238ecc75@oracle.com> On 22/06/17 03:21, Mandy Chung wrote: >> On Jun 21, 2017, at 5:23 PM, Maurizio Cimadamore wrote: >> >> I notice some asymmetry between the VCC and DVT cases. For VCC we have: >> >> * isValueCapable(Class) >> * getValueCapableClass(Class) >> >> For DVT we have >> >> * isValueType(Class) >> * getValueTypeClass(Class) >> * loadValueTypeClass(Class) >> >> There are two kind of inconsistencies at play here - one is a plain naming issue - the suffix Class is not using consistently in all the methods. >> > I believe David was the author of the MinimalValueType_1_0 class and he might want to comment here. I haven?t read up the documents in details to determine the proper terminologies. But I have to admit that I was initially confused with isValueType that refers to DVT. > > I would suggest to rename 'ValueType? to ?DerivedValueType? and drop the suffix ?Class? from *ValueType* methods and rename ValueCapable to ValueCapableClass to match DVT and VCC. I don?t mind doing the renaming and I can follow up as a separate changeset. > >> The second inconsistency is that for a DVT we distinguish between get/load, while for VCC we do not. But it's a moot distinction, given that getValueTypeClass will always call loadValueTypeClass (and recheck same assertion). Maybe we should fuse those two methods? > ValueType::arrayValueClass calls MinimalValueTypes_1_0::loadValueTypeClass to define an array of DVT. That?s why they are separate. > > I expect there are lot more cleanup to be done once I get familiar with the implementation. Ok - the changes you have now are good to go - I was just thinking loud looking at the method names. Cheers Maurizio > > Mandy > >> Cheers >> Maurizio >> >> >> >> On 21/06/17 21:21, Mandy Chung wrote: >>>> On Jun 21, 2017, at 9:44 AM, Maurizio Cimadamore wrote: >>>> >>>> >>>> On 21/06/17 16:56, Mandy Chung wrote: >>>>> ValueType::classHasValueType is not used. Should this be replaced with isValueCapable? Is there a case no DVT defined for VCC (which would be the case classHasValueType would return false for VCC) but I suspect not? >>>> I believe ValueType is supposed to be a public API, while MinimalValueType_1_0 is not. So, maybe we should keep that one as a sort of reflective predicate. >>> I keep ValueType::classHasValueType the same behavior that loads DVT before >>> returning. I suspect it may not be necessesary but we can re-examine that >>> in the future. >>> >>> http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.02/ >>> >>> Changes w.r.t. webrev.01 >>> 1. Removed classHasValueType(Class) and getValueTypeClass(Class) which >>> is only used by classHasValueType. >>> 2. getValueCapableClass and getValueTypeClass no longer throws CNFE >>> (it throws IAE if the given type is not DVT or VCC). MethodHandles is >>> updated due to the removal of this checked exception. >>> 3. I added valhalla/mvt to jdk_lang test group that makes it handy to do verification. >>> >>> thanks >>> Mandy From maurizio.cimadamore at oracle.com Thu Jun 22 11:35:29 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 22 Jun 2017 12:35:29 +0100 Subject: RFR JDK-8182678: add javac and method handle support for mangled value class names in CONSTANT_ClassInfo In-Reply-To: References: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> Message-ID: On 22/06/17 02:22, Paul Sandoz wrote: > Looks good, although it would be nice if the javac and java properties were the same name as it?s hard to remember the plethora of such properties that are available. Sure - note that I tried to use the same name - but the javac convention is not to use any qualified name for options, while it seems like all the MVT-related options in the JDK starts off with 'valhalla.' - which is why I landed there, as the option name is kind of the same (mangleClassInfo is contained in both), and the scheme is consistent with both javac and jdk unwritten rules. That said, if you think it's too confusing, I can change it no problem. Maurizio > > Paul. > >> On 21 Jun 2017, at 17:12, Maurizio Cimadamore wrote: >> >> Hi >> the following two patches: >> >> http://cr.openjdk.java.net/~mcimadamore/8182678_langtools/ >> http://cr.openjdk.java.net/~mcimadamore/8182678_jdk/ >> >> Add support for mangled value class names in ClassInfo for both javac and the bytecode API (used for MH spinning). >> >> The support is enabled with these two options: >> >> javac: -XDmangleClassInfo >> >> jdk: -Dvalhalla.mangleClassInfo=true >> >> >> I also added class reading support to javac - and that's always enabled. >> >> I verified that javap works as expected - since a ClassInfo is just a string, javap doesn't complain if there's an extra ';' prefix in there, so things looks good already. >> >> Cheers >> Maurizio >> >> From david.simms at oracle.com Thu Jun 22 12:09:27 2017 From: david.simms at oracle.com (David Simms) Date: Thu, 22 Jun 2017 14:09:27 +0200 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <94b194e7-1cf3-99c6-5645-d54d238ecc75@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <613EF204-FBC2-4086-B17D-A6B6433350F9@oracle.com> <198400F0-1995-48E3-A48B-FB28208538AF@oracle.com> <82591777-B7F5-4E70-9F53-524635A0C580@oracle.com> <5d6c06f9-6559-fa57-ea65-ec7d9634f62e@oracle.com> <0100337c-2e7f-b3ad-ca21-a62fdc42f3bc@oracle.com> <94b194e7-1cf3-99c6-5645-d54d238ecc75@oracle.com> Message-ID: On 22/06/17 13:27, Maurizio Cimadamore wrote: > > > On 22/06/17 03:21, Mandy Chung wrote: >>> On Jun 21, 2017, at 5:23 PM, Maurizio Cimadamore >>> wrote: >>> >>> I notice some asymmetry between the VCC and DVT cases. For VCC we have: >>> >>> * isValueCapable(Class) >>> * getValueCapableClass(Class) >>> >>> For DVT we have >>> >>> * isValueType(Class) >>> * getValueTypeClass(Class) >>> * loadValueTypeClass(Class) >>> >>> There are two kind of inconsistencies at play here - one is a plain >>> naming issue - the suffix Class is not using consistently in all the >>> methods. >>> >> I believe David was the author of the MinimalValueType_1_0 class and >> he might want to comment here. I haven?t read up the documents in >> details to determine the proper terminologies. But I have to admit >> that I was initially confused with isValueType that refers to DVT. I'm not picky about the names, I'd probably drop "Class" from the method name to be honest, seems redundant when the single arg are return are classes. The asymmetry came when I wanted to differentiate between "DVT" & "VCC" Class. "It felt weird" to write "ValueCapable" and not finish with Class (since we are so used to saying VCC). I'm not up on JDK naming conventions, feel free change it. Terminology in the draft JVMS (http://cr.openjdk.java.net/~dlsmith/values.html) work also differs from the Shady Values (http://cr.openjdk.java.net/~jrose/values/shady-values.html), i.e. "Derived Value Type" == "Direct Value Class Type"...so there's that. "Value Capable" and "Value Type" seem reasonable. Minor Comments: * Copyright year ValueType.java, MinimalValueTypes_1_0.java, TEST.groups and MVTTest.java * MinimalValueTypes_1_0.java:108 "already a derived value type" ? o "(!isValueCapable(vcc))" message might read " not a value capable class" ? Otherwise, the webrev looks good, much appreciated code-coverage in the added tests. Thanks for addressing the mess I left behind and lack of modules support. I assume both "make test" for "hotspot_valhalla" and "jdk_valhalla" pass ? Cheers /David Simms From maurizio.cimadamore at oracle.com Thu Jun 22 12:13:03 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 22 Jun 2017 13:13:03 +0100 Subject: vwithfield and ValueType.findWither In-Reply-To: References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> <13f3ff1c-8e72-9cd2-19ef-77aa928124a3@oracle.com> <57FBA69F-ECDE-4B98-9111-AE4199D2C1D7@oracle.com> <5E571F25-0138-43A2-9A4C-835EE9F4B2BF@oracle.com> <707D2356-DEC1-467C-8A04-6F5888F94E57@oracle.com> Message-ID: <67dd5ab3-7e3e-3ab3-4df4-1b682a3ceb0e@oracle.com> +1 Maurizio On 22/06/17 10:52, David Simms wrote: > > Looks good to me, special thanks for adding more testing, excellent. > > /David Simms > > > On 22/06/17 02:50, Paul Sandoz wrote: >> Here is webrev: >> >> http://cr.openjdk.java.net/~psandoz/valhalla/vwithfield/webrev/ >> >> >> Including more updates to HS and a test. >> >> Paul. >> >>> On 20 Jun 2017, at 18:35, Paul Sandoz >> > wrote: >>> >>> Below is a patch for the first stage. Loosening the check in HS and >>> updating findWither to use vwithfield. >>> >>> A follow on patch will refine the access control checks in >>> findWither and add more tests. >>> >>> Paul. >>> >>> jdk: >>> diff -r e3e5af317626 >>> src/java.base/share/classes/jdk/experimental/value/ValueType.java >>> --- >>> a/src/java.base/share/classes/jdk/experimental/value/ValueType.javaMon >>> Jun 19 11:07:52 2017 +0200 >>> +++ >>> b/src/java.base/share/classes/jdk/experimental/value/ValueType.javaTue >>> Jun 20 18:29:39 2017 -0700 >>> @@ -274,33 +274,13 @@ >>> ValueHandleKey key = >>> ValueHandleKind.WITHER.key(List.of(name, type)); >>> MethodHandle result = handleMap.get(key); >>> if (result == null) { >>> - MethodHandle mh = boxLookup.findGetter(boxClass(), >>> name, type); >>> - Field field = MethodHandles.reflectAs(Field.class, mh); >>> - Class erasedType = type.isPrimitive() ? >>> - type : Object.class; >>> - Method unsafeMethod = >>> Stream.of(UNSAFE.getClass().getDeclaredMethods()) >>> - .filter(m -> m.getName().startsWith("put") && >>> - >>> Arrays.asList(m.getParameterTypes()).equals(Arrays.asList(Object.class, >>> long.class, erasedType))) >>> - .findFirst().get(); >>> - long fieldOffset = UNSAFE.objectFieldOffset(field); >>> - result = MethodHandleBuilder.loadCode(boxLookup, >>> mhName("wither$" + name), MethodType.methodType(valueClass(), >>> MethodHandle.class, valueClass(), type), >>> - C -> { >>> - C.withLocal("boxedVal", >>> BytecodeDescriptor.unparse(boxClass())) >>> - .load(1) >>> - .vbox(boxClass()) >>> - .store("boxedVal") >>> - .load(0) >>> - .load("boxedVal") >>> - .const_(fieldOffset) >>> - .load(2); >>> - MethodType unsafeMT = >>> MethodType.methodType(unsafeMethod.getReturnType(), >>> unsafeMethod.getParameterTypes()); >>> - C.invokevirtual(MethodHandle.class, >>> "invokeExact", BytecodeDescriptor.unparse(unsafeMT), false) >>> - .load("boxedVal") >>> - .vunbox(valueClass()) >>> - .vreturn(); >>> - >>> }).bindTo(MethodHandles.lookup().unreflect(unsafeMethod).bindTo(UNSAFE)); >>> + String fieldType = BytecodeDescriptor.unparse(type); >>> + >>> + result = MethodHandleBuilder.loadCode(valueLookup, >>> mhName("wither$" + name), MethodType.methodType(valueClass(), >>> valueClass(), type), >>> + C -> >>> C.vload(0).load(1).vwithfield(valueClass(), name, >>> fieldType).vreturn()); >>> handleMap.put(key, result); >>> } >>> + // @@@ special access check for read/write access >>> //force access-check >>> lookup.findGetter(boxClass(), name, type); >>> return result; >>> >>> >>> hotspot: >>> diff -r c6878e14a2df src/share/vm/interpreter/linkResolver.cpp >>> --- a/src/share/vm/interpreter/linkResolver.cppTue Jun 20 15:21:26 >>> 2017 +0200 >>> +++ b/src/share/vm/interpreter/linkResolver.cppTue Jun 20 18:31:01 >>> 2017 -0700 >>> @@ -951,6 +951,22 @@ >>> stringStream ss; >>> >>> if (sel_klass != current_klass) { >>> + // For Minimal Value Types check if the current class is an >>> anonymous >>> + // class whose host class is the Derived Value Type class >>> (selected class) >>> + // or the Value Capable Class (VCC) >>> + if (byte == Bytecodes::_vwithfield) { >>> + assert(sel_klass->is_value(), "Expected Value Type"); >>> + if (current_klass->is_instance_klass() && >>> InstanceKlass::cast(current_klass)->is_anonymous()) { >>> + Klass* host_class = >>> InstanceKlass::cast(current_klass)->host_klass(); // Is host VCC of >>> DVT ? >>> + >>> + if (host_class == sel_klass || // Is DVT >>> + (host_class->is_instance_klass() && // Is VCC >>> + InstanceKlass::cast(host_class)->get_vcc_klass() == sel_klass)) { >>> + return; >>> + } >>> + } >>> + } >>> + >>> ss.print("Update to %s final field %s.%s attempted from a >>> different class (%s) than the field's declaring class", >>> is_static ? "static" : "non-static", >>> resolved_klass->external_name(), fd.name()->as_C_string(), >>> current_klass->external_name()); >>> >>>> On 19 Jun 2017, at 09:42, Paul Sandoz >>> > wrote: >>>> >>>> Hi David, >>>> >>>> That is almost the same direction i was thinking about. >>>> Specifically, fix HS so that for an anon class accessibility check >>>> is deferred to the host class. >>>> >>>> As you point out findWither now accepts a lookup: >>>> >>>> public MethodHandle findWither(Lookup lookup, String name, Class >>>> type) throws NoSuchFieldException, IllegalAccessException { >>>> ? >>>> //force access-check >>>> lookup.findGetter(boxClass(), name, type); >>>> return result; >>>> } >>>> >>>> I am proposing that for findWither the developer pass a lookup >>>> created from MHs.privateLookupIn, thereby allowing to bypass the >>>> explicit access control checks in a controlled manner. IMO we don?t >>>> have to relax the access constraints on vwithfield. >>>> >>>> Separately we can improve the user experience by focusing on MHs >>>> for constructors. >>>> >>>> Paul. >>>> >>>>> On 19 Jun 2017, at 02:33, David Simms >>>> > wrote: >>>>> >>>>> >>>>> Re: "HotSpot code accessibility checks" >>>>> >>>>> I did play around with explicitly opening up access from the VCC: >>>>> >>>>> http://cr.openjdk.java.net/~dsimms/valhalla/vwithfield_access/webrev1/ >>>>> >>>>> >>>>> (MethodHandleBuilder "vdefault" and "vwithfield" parts are already >>>>> in) >>>>> >>>>> This code is specific to the VCC / DVT relationship, and was a bit >>>>> of a hack to start the conversation some time back. We were happy >>>>> living with the unsafe hack for the time being, but I would prefer >>>>> to use stop using said work-around. >>>>> >>>>> I believe Dan's suggestion "Access restriction for vwithfield" on >>>>> the design mail list is more practical (package private)...let's >>>>> follow that conversation and get the JVMS definition right. >>>>> >>>>> Main points from previous discussions: >>>>> >>>>> * Original "vnew" proposal took all fields as stack args, all the >>>>> time. >>>>> o Hard to optimize, inefficient for value where most fields are >>>>> "null/zero". >>>>> o "vwithfield" easier to optimize (possible to elide COW >>>>> semantics, efficiently change only required fields) >>>>> * Allow the user-code to enforce invariant values >>>>> o Able to implement "never publish (vastore, putfield) 'Foo' value >>>>> with any zero fields" >>>>> o Access restrictions from VCC or package private ? >>>>> >>>>> Recent changes to the ValueType API accepting MH lookup now gives >>>>> a few more options to the user. >>>>> >>>>> /D >>>>> >>>>> On 15/06/17 19:32, Paul Sandoz wrote: >>>>>> Hi Fred, >>>>>> >>>>>> Do you know where in the HotSpot code accessibility checks are >>>>>> performed for vwithfield? We need to fix those checks for Unsafe >>>>>> defined anonymous classes to defer to the host class (and if a >>>>>> suitable VCC or DVT then access should be granted). >>>>>> >>>>>> Paul. >>>>>> >>>>>>> On 15 Jun 2017, at 07:06, Frederic Parain >>>>>>> wrote: >>>>>>> >>>>>>> >>>>>>> >>>>>>> On 06/15/2017 05:36 AM, Maurizio Cimadamore wrote: >>>>>>>> >>>>>>>> On 15/06/17 09:46, John Rose wrote: >>>>>>>>> On Jun 14, 2017, at 2:20 PM, Maurizio Cimadamore >>>>>>>>> wrote: >>>>>>>>>> Another possible story is that we always create values >>>>>>>>>> through the >>>>>>>>>> VCC constructor, and then unbox. If we think we're happy with >>>>>>>>>> that, >>>>>>>>>> that might be a fine choice too. >>>>>>>>> That's not a bad story for the JIT with aggressive scalarization, >>>>>>>>> and was my first idea about this, but it is painful in the >>>>>>>>> interpreter. >>>>>>>>> >>>>>>>> In which ways it's bad for the interpreter? Note that the current >>>>>>>> implementation of the 'modified' findWither will do just that: >>>>>>>> >>>>>>>> * box incoming value >>>>>>>> * set field (with Unsafe.putXYZ) >>>>>>>> * unbox resulting reference back to a value >>>>>>>> >>>>>>>> So, it seems to me that, to set 5 fields, the above idiom will do >>>>>>>> box/unbox 5 times, while if we just create a VCC with the >>>>>>>> fields we want >>>>>>>> and then unbox, that's just one unboxing step. >>>>>>>> >>>>>>>> What am I missing? >>>>>>> With the vwithfield bytecode, the interpreter can avoid Java heap >>>>>>> allocations, with the box/Unsafe/unbox it cannot. >>>>>>> >>>>>>> Just a performance/memory issue. >>>>>>> >>>>>>> Fred >>>>> >>>>> >>>> >>> >> > From tobias.hartmann at oracle.com Thu Jun 22 13:17:34 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Thu, 22 Jun 2017 15:17:34 +0200 Subject: RFR(S): 8182585: [MVT] Reading an uninitialized static value type field should not throw a NPE In-Reply-To: References: Message-ID: Hi, I'm now checking the static field contents at compile time and only emit a runtime null check if the field is null. I verified that this works with Fred's UninitializedValueFieldsTest [1]. If the static field access was already executed by the interpreter (and thus initialization happened), C2 does not emit a null check. I also changed the uncommon trap action to 'Action_maybe_recompile' such that the code gets a chance to be recompiled. I updated the webrev in place: http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.21/ Thanks, Tobias [1] http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.01/test/runtime/valhalla/valuetypes/UninitializedValueFieldsTest.java.html From maurizio.cimadamore at oracle.com Thu Jun 22 14:31:45 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 22 Jun 2017 15:31:45 +0100 Subject: RFR JDK-8182678: add javac and method handle support for mangled value class names in CONSTANT_ClassInfo In-Reply-To: References: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> Message-ID: I've uploaded new webrevs; the first fixes an issue with ClassReader - which should return a symbol, not a type, when reading a value type signature inside a ClassInfo: http://cr.openjdk.java.net/~mcimadamore/8182678_langtools_v2 The second does a little tweak to the bytecode API to add stackmap support http://cr.openjdk.java.net/~mcimadamore/8182678_jdk_v2 I did a bit of tests with stackmaps and Qtypes and it looks ok. The fact that values are encoded as 'weird' ClassInfo simplifies things considerably, as most of the infrastructure just works. Maurizio On 22/06/17 12:35, Maurizio Cimadamore wrote: > > > On 22/06/17 02:22, Paul Sandoz wrote: >> Looks good, although it would be nice if the javac and java >> properties were the same name as it?s hard to remember the plethora >> of such properties that are available. > Sure - note that I tried to use the same name - but the javac > convention is not to use any qualified name for options, while it > seems like all the MVT-related options in the JDK starts off with > 'valhalla.' - which is why I landed there, as the option name is kind > of the same (mangleClassInfo is contained in both), and the scheme is > consistent with both javac and jdk unwritten rules. > > That said, if you think it's too confusing, I can change it no problem. > > Maurizio > > >> >> Paul. >> >>> On 21 Jun 2017, at 17:12, Maurizio Cimadamore >>> wrote: >>> >>> Hi >>> the following two patches: >>> >>> http://cr.openjdk.java.net/~mcimadamore/8182678_langtools/ >>> http://cr.openjdk.java.net/~mcimadamore/8182678_jdk/ >>> >>> Add support for mangled value class names in ClassInfo for both >>> javac and the bytecode API (used for MH spinning). >>> >>> The support is enabled with these two options: >>> >>> javac: -XDmangleClassInfo >>> >>> jdk: -Dvalhalla.mangleClassInfo=true >>> >>> >>> I also added class reading support to javac - and that's always >>> enabled. >>> >>> I verified that javap works as expected - since a ClassInfo is just >>> a string, javap doesn't complain if there's an extra ';' prefix in >>> there, so things looks good already. >>> >>> Cheers >>> Maurizio >>> >>> > From tobias.hartmann at oracle.com Thu Jun 22 14:57:26 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Thu, 22 Jun 2017 16:57:26 +0200 Subject: MH compilation is broken in valhalla(mvt branch) build In-Reply-To: References: Message-ID: <553af40b-ebcd-174c-3a11-bc9d9ea3fc99@oracle.com> Hi, to mitigate the impact of this, we could only bail out if the compiled lambda form really contains a value type in it's signature: diff -r 67cdfd4b0995 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Tue Jun 20 11:18:10 2017 +0200 +++ b/src/share/vm/compiler/compileBroker.cpp Thu Jun 22 16:55:50 2017 +0200 @@ -1054,7 +1054,12 @@ // value type. If compiled as root of a compilation, C2 has no way // to know a value type is passed. if (ValueTypePassFieldsAsArgs && method->is_compiled_lambda_form()) { - return NULL; + ResourceMark rm; + for (SignatureStream ss(method->signature()); !ss.at_return_type(); ss.next()) { + if (ss.type() == T_VALUETYPE) { + return NULL; + } + } } // lock, make sure that the compilation Roland, what do you think? I'll look into a complete fix next. Best regards, Tobias On 19.06.2017 10:18, Roland Westrelin wrote: > > Hi Sergey, > >> I found that in valhalla build (mvt branch) MH compilation is broken if >> MH is stored in non-final field. Cost of MH invocation is increased >> ~100x times. > > Compilation of lambda forms as root of compilation is currently > disabled. > > If we have a value type: > > class Point { > double x; > double y; > } > > and some method is called: > > foo(Point p) > > when that method is JIT'ed, we use a special calling convention that > doesn't pass a reference to p but the fields: > > foo(double x, double y) > > If foo is called with a method handle call and the method handle is not > constant, foo won't be inlined in a caller, it will be called from a > lambda form. That lambda form is specialized to the value type supertype > so it's not aware that the value type argument is a Point. It passes a > reference to a value type as an argument to foo but foo expects a pair > of doubles. If the call is from an interpreted lambda form, the i2c > takes care of loading the fields from the value type. If the call is > from a compiled method, this would cause the compiled method foo to see > garbage in x and y. The current workaround is to disable compilation of > lambda forms. The correct fix I think is to have a special entry point > in the compiled method. > > That this problem is indeed the root cause of what you're seeing can be > verified by disabling the special calling convention with: > > -XX:-ValueTypePassFieldsAsArgs > > Roland. > From paul.sandoz at oracle.com Thu Jun 22 16:36:26 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 22 Jun 2017 09:36:26 -0700 Subject: RFR JDK-8182678: add javac and method handle support for mangled value class names in CONSTANT_ClassInfo In-Reply-To: References: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> Message-ID: > On 22 Jun 2017, at 04:35, Maurizio Cimadamore wrote: > > > > On 22/06/17 02:22, Paul Sandoz wrote: >> Looks good, although it would be nice if the javac and java properties were the same name as it?s hard to remember the plethora of such properties that are available. > Sure - note that I tried to use the same name - but the javac convention is not to use any qualified name for options, while it seems like all the MVT-related options in the JDK starts off with 'valhalla.' - which is why I landed there, as the option name is kind of the same (mangleClassInfo is contained in both), and the scheme is consistent with both javac and jdk unwritten rules. > > That said, if you think it's too confusing, I can change it no problem. > Thinking more, my objection is really that i don?t have a holistic view of all the possible flags for javac, and hotspot. It would be useful if we have a page somewhere listing all such flags with a small description. We cold use a dummy issue and edit the description? Paul. From paul.sandoz at oracle.com Thu Jun 22 16:38:39 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 22 Jun 2017 09:38:39 -0700 Subject: RFR JDK-8182678: add javac and method handle support for mangled value class names in CONSTANT_ClassInfo In-Reply-To: References: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> Message-ID: +1 Paul. > On 22 Jun 2017, at 07:31, Maurizio Cimadamore wrote: > > I've uploaded new webrevs; the first fixes an issue with ClassReader - which should return a symbol, not a type, when reading a value type signature inside a ClassInfo: > > http://cr.openjdk.java.net/~mcimadamore/8182678_langtools_v2 > > The second does a little tweak to the bytecode API to add stackmap support > > http://cr.openjdk.java.net/~mcimadamore/8182678_jdk_v2 > > > I did a bit of tests with stackmaps and Qtypes and it looks ok. The fact that values are encoded as 'weird' ClassInfo simplifies things considerably, as most of the infrastructure just works. > > Maurizio From maurizio.cimadamore at oracle.com Thu Jun 22 16:52:26 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 22 Jun 2017 17:52:26 +0100 Subject: RFR JDK-8182678: add javac and method handle support for mangled value class names in CONSTANT_ClassInfo In-Reply-To: References: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> Message-ID: <1cff887a-a11c-6679-d4b9-aed72ce964d1@oracle.com> On 22/06/17 17:36, Paul Sandoz wrote: >> On 22 Jun 2017, at 04:35, Maurizio Cimadamore wrote: >> >> >> >> On 22/06/17 02:22, Paul Sandoz wrote: >>> Looks good, although it would be nice if the javac and java properties were the same name as it?s hard to remember the plethora of such properties that are available. >> Sure - note that I tried to use the same name - but the javac convention is not to use any qualified name for options, while it seems like all the MVT-related options in the JDK starts off with 'valhalla.' - which is why I landed there, as the option name is kind of the same (mangleClassInfo is contained in both), and the scheme is consistent with both javac and jdk unwritten rules. >> >> That said, if you think it's too confusing, I can change it no problem. >> > Thinking more, my objection is really that i don?t have a holistic view of all the possible flags for javac, and hotspot. > > It would be useful if we have a page somewhere listing all such flags with a small description. We cold use a dummy issue and edit the description? Sounds like a good idea - flags always introduce a certain non-determinism to the dev experience; any attempt to keep them under check is welcome on my part ;-) Maurizio > > Paul. From maurizio.cimadamore at oracle.com Thu Jun 22 16:56:32 2017 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Thu, 22 Jun 2017 16:56:32 +0000 Subject: hg: valhalla/valhalla/langtools: 8182678: [MVT] add javac and method handle support for mangled value class names in CONSTANT_ClassInfo Message-ID: <201706221656.v5MGuWVg014831@aojmv0008.oracle.com> Changeset: 1b4102957644 Author: mcimadamore Date: 2017-06-22 17:54 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/1b4102957644 8182678: [MVT] add javac and method handle support for mangled value class names in CONSTANT_ClassInfo Summary: add ClassReader/Writer support for mangled class info entries (enabled with -XDmangleClassInfo) Reviewed-by: psandoz ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java From maurizio.cimadamore at oracle.com Thu Jun 22 16:57:47 2017 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Thu, 22 Jun 2017 16:57:47 +0000 Subject: hg: valhalla/valhalla/jdk: 8182678: [MVT] add javac and method handle support for mangled value class names in CONSTANT_ClassInfo Message-ID: <201706221657.v5MGvlQr015650@aojmv0008.oracle.com> Changeset: c44a771d3b1f Author: mcimadamore Date: 2017-06-22 17:55 +0100 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/c44a771d3b1f 8182678: [MVT] add javac and method handle support for mangled value class names in CONSTANT_ClassInfo Summary: add MethodHandleBuilder and bytecode API support for mangled value class names Reviewed-by: psandoz ! src/java.base/share/classes/jdk/experimental/bytecode/CodeBuilder.java ! src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java From maurizio.cimadamore at oracle.com Thu Jun 22 16:56:11 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 22 Jun 2017 17:56:11 +0100 Subject: RFR JDK-8182678: add javac and method handle support for mangled value class names in CONSTANT_ClassInfo In-Reply-To: References: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> Message-ID: <1fbeaa08-664e-c05d-80a8-5b5c5a753dc7@oracle.com> Thanks, pushed Maurizio On 22/06/17 17:38, Paul Sandoz wrote: > +1 > > Paul. > >> On 22 Jun 2017, at 07:31, Maurizio Cimadamore wrote: >> >> I've uploaded new webrevs; the first fixes an issue with ClassReader - which should return a symbol, not a type, when reading a value type signature inside a ClassInfo: >> >> http://cr.openjdk.java.net/~mcimadamore/8182678_langtools_v2 >> >> The second does a little tweak to the bytecode API to add stackmap support >> >> http://cr.openjdk.java.net/~mcimadamore/8182678_jdk_v2 >> >> >> I did a bit of tests with stackmaps and Qtypes and it looks ok. The fact that values are encoded as 'weird' ClassInfo simplifies things considerably, as most of the infrastructure just works. >> >> Maurizio From paul.sandoz at oracle.com Thu Jun 22 18:13:21 2017 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Thu, 22 Jun 2017 18:13:21 +0000 Subject: hg: valhalla/valhalla/hotspot: Enhance access control checks for anonymous classes Message-ID: <201706221813.v5MIDLNg020975@aojmv0008.oracle.com> Changeset: ed17a1f84391 Author: psandoz Date: 2017-06-22 11:04 -0700 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/ed17a1f84391 Enhance access control checks for anonymous classes such that if the host class is a VCC or DVT then vwithfield access to any fields of the DVT is permitted. ! src/share/vm/interpreter/linkResolver.cpp ! src/share/vm/oops/instanceKlass.hpp ! src/share/vm/runtime/reflection.cpp From paul.sandoz at oracle.com Thu Jun 22 18:13:28 2017 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Thu, 22 Jun 2017 18:13:28 +0000 Subject: hg: valhalla/valhalla/jdk: Update findWither to use vwithfield (with appropriate Message-ID: <201706221813.v5MIDSqi021125@aojmv0008.oracle.com> Changeset: d087da7feec9 Author: psandoz Date: 2017-06-22 11:04 -0700 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/d087da7feec9 Update findWither to use vwithfield (with appropriate updates to HotSpot for access control). ! src/java.base/share/classes/jdk/experimental/value/ValueType.java ! test/valhalla/mvt/PrivatePoint.java + test/valhalla/mvt/WithFieldTest.java From paul.sandoz at oracle.com Thu Jun 22 18:53:51 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 22 Jun 2017 11:53:51 -0700 Subject: vwithfield and ValueType.findWither In-Reply-To: <67dd5ab3-7e3e-3ab3-4df4-1b682a3ceb0e@oracle.com> References: <309da83d-9856-1ea1-120a-fb40e2e38cae@oracle.com> <6EDE8B81-A2EE-4735-A439-9C02F7080156@oracle.com> <0f62c48b-e29e-64bf-7993-889d4c2878f5@oracle.com> <13f3ff1c-8e72-9cd2-19ef-77aa928124a3@oracle.com> <57FBA69F-ECDE-4B98-9111-AE4199D2C1D7@oracle.com> <5E571F25-0138-43A2-9A4C-835EE9F4B2BF@oracle.com> <707D2356-DEC1-467C-8A04-6F5888F94E57@oracle.com> <67dd5ab3-7e3e-3ab3-4df4-1b682a3ceb0e@oracle.com> Message-ID: <20DE6968-1CE7-47D2-AF82-D38787E2577A@oracle.com> Thanks for both reviews. Next up is to evaluate the explicit access control check in findWither and then constructor-based MHs in ValueType. Paul. > On 22 Jun 2017, at 05:13, Maurizio Cimadamore wrote: > > +1 > > Maurizio > From paul.sandoz at oracle.com Thu Jun 22 19:18:12 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 22 Jun 2017 12:18:12 -0700 Subject: Unsafe value access Message-ID: Hi, To start working on VarHandle integration i first of all need unsafe access to values held within objects. For a most basic initial implementation we can use a global lock to preserve atomicity and memory ordering effects and defer the thinking about more sophisticated locking (seq locks etc), read-mody-write operations and other memory order effects to a another day. For these purposes we just require two methods: __Value getValue(Object base, long offset, Class vt) void putValue(Object base, long offset, Class vt, __Value v); I included Class parameter for the value type token. How feasible would it be to implement such methods? If people point me to the hotspot interpreter code for getfield/putfield implementations for values i might be able to make some progress. Once that is done we could then consider C1/C2 support. Thoughts? Thanks, Paul. From frederic.parain at oracle.com Thu Jun 22 19:28:22 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Thu, 22 Jun 2017 15:28:22 -0400 Subject: Unsafe value access In-Reply-To: References: Message-ID: <50293422-8F45-4A16-981E-C29A3A8F48BF@oracle.com> Paul, For the interpreter, the implementation of getfield/putfield for value fields is split between an assembly template and some runtime methods. The assembly template can be found in src/cpu/x86/vm/templateTable_x86.cpp, look for this method: void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc, bool is_vgetfield) The runtime support can be found in src/share/vm/interpreter/interpreterRuntime.cpp, look for methods InterpreterRuntime::qgetfield(JavaThread* thread, oopDesc* value, int offset) and InterpreterRuntime::qputfield(JavaThread* thread, oopDesc* obj, oopDesc* value, int offset). Mr Simms did a number of experiments at the beginning of the project to measure the cost of the different solutions to provide atomicity, I would recommend to sync with him. Regards, Fred > On Jun 22, 2017, at 15:18, Paul Sandoz wrote: > > Hi, > > To start working on VarHandle integration i first of all need unsafe access to values held within objects. For a most basic initial implementation we can use a global lock to preserve atomicity and memory ordering effects and defer the thinking about more sophisticated locking (seq locks etc), read-mody-write operations and other memory order effects to a another day. > > For these purposes we just require two methods: > > __Value getValue(Object base, long offset, Class vt) > > void putValue(Object base, long offset, Class vt, __Value v); > > I included Class parameter for the value type token. > > How feasible would it be to implement such methods? > > If people point me to the hotspot interpreter code for getfield/putfield implementations for values i might be able to make some progress. Once that is done we could then consider C1/C2 support. > > Thoughts? > > Thanks, > Paul. > > From paul.sandoz at oracle.com Thu Jun 22 21:28:27 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 22 Jun 2017 14:28:27 -0700 Subject: Unsafe value access In-Reply-To: <50293422-8F45-4A16-981E-C29A3A8F48BF@oracle.com> References: <50293422-8F45-4A16-981E-C29A3A8F48BF@oracle.com> Message-ID: <34CD3C93-516F-40A3-9A0F-482F70FF9F05@oracle.com> > On 22 Jun 2017, at 12:28, Frederic Parain wrote: > > Paul, > > For the interpreter, the implementation of getfield/putfield for value fields is split > between an assembly template and some runtime methods. > > The assembly template can be found in src/cpu/x86/vm/templateTable_x86.cpp, > look for this method: > > void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc, bool is_vgetfield) > > The runtime support can be found in src/share/vm/interpreter/interpreterRuntime.cpp, > look for methods InterpreterRuntime::qgetfield(JavaThread* thread, oopDesc* value, int offset) > and InterpreterRuntime::qputfield(JavaThread* thread, oopDesc* obj, oopDesc* value, int offset). > Thanks, i will take a look. > Mr Simms did a number of experiments at the beginning of the project to measure > the cost of the different solutions to provide atomicity, I would recommend to sync > with him. > We have already had some initial conversations. Paul. From paul.sandoz at oracle.com Thu Jun 22 23:41:12 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 22 Jun 2017 16:41:12 -0700 Subject: RFR findWither with access checks Message-ID: http://cr.openjdk.java.net/~psandoz/valhalla/findWither-access/webrev/ Updates findWither to grant access if the lookup class is VCC or DVT with private access. Paul. From maurizio.cimadamore at oracle.com Thu Jun 22 23:51:14 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 23 Jun 2017 00:51:14 +0100 Subject: RFR findWither with access checks In-Reply-To: References: Message-ID: <8bf13241-a042-6fcd-a38a-2c21717d8a40@oracle.com> Looks good. One question - does the lookup have to come necessarily from 'privateLookupIn' to have the isPrivate() bit set? What if the wither handle is used from a method of the VCC itself? In that case it should probably work - even if the lookup is obtained in the standard fashion (MethodHandles.lookup()) ? Thanks Maurizio On 23/06/17 00:41, Paul Sandoz wrote: > http://cr.openjdk.java.net/~psandoz/valhalla/findWither-access/webrev/ > > Updates findWither to grant access if the lookup class is VCC or DVT with private access. > > Paul. From paul.sandoz at oracle.com Fri Jun 23 00:01:23 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 22 Jun 2017 17:01:23 -0700 Subject: RFR findWither with access checks In-Reply-To: <8bf13241-a042-6fcd-a38a-2c21717d8a40@oracle.com> References: <8bf13241-a042-6fcd-a38a-2c21717d8a40@oracle.com> Message-ID: > On 22 Jun 2017, at 16:51, Maurizio Cimadamore wrote: > > Looks good. > > One question - does the lookup have to come necessarily from 'privateLookupIn' to have the isPrivate() bit set? What if the wither handle is used from a method of the VCC itself? In that case it should probably work - even if the lookup is obtained in the standard fashion (MethodHandles.lookup()) ? > Correct, i tweaked the test: public void testWither() throws Throwable { testWither(Point.lookup()); testWither(MethodHandles.privateLookupIn(VT.boxClass(), LOOKUP)); testWither(MethodHandles.privateLookupIn(VT.valueClass(), LOOKUP)); } webrev updated in place. Paul. > Thanks > Maurizio > > > On 23/06/17 00:41, Paul Sandoz wrote: >> http://cr.openjdk.java.net/~psandoz/valhalla/findWither-access/webrev/ >> >> Updates findWither to grant access if the lookup class is VCC or DVT with private access. >> >> Paul. > From maurizio.cimadamore at oracle.com Fri Jun 23 00:29:14 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 23 Jun 2017 01:29:14 +0100 Subject: RFR findWither with access checks In-Reply-To: References: <8bf13241-a042-6fcd-a38a-2c21717d8a40@oracle.com> Message-ID: Looks good - thanks Maurizio On 23/06/17 01:01, Paul Sandoz wrote: >> On 22 Jun 2017, at 16:51, Maurizio Cimadamore wrote: >> >> Looks good. >> >> One question - does the lookup have to come necessarily from 'privateLookupIn' to have the isPrivate() bit set? What if the wither handle is used from a method of the VCC itself? In that case it should probably work - even if the lookup is obtained in the standard fashion (MethodHandles.lookup()) ? >> > Correct, i tweaked the test: > > public void testWither() throws Throwable { > testWither(Point.lookup()); > testWither(MethodHandles.privateLookupIn(VT.boxClass(), LOOKUP)); > testWither(MethodHandles.privateLookupIn(VT.valueClass(), LOOKUP)); > } > > webrev updated in place. > > Paul. > > >> Thanks >> Maurizio >> >> >> On 23/06/17 00:41, Paul Sandoz wrote: >>> http://cr.openjdk.java.net/~psandoz/valhalla/findWither-access/webrev/ >>> >>> Updates findWither to grant access if the lookup class is VCC or DVT with private access. >>> >>> Paul. From paul.sandoz at oracle.com Fri Jun 23 00:50:38 2017 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Fri, 23 Jun 2017 00:50:38 +0000 Subject: hg: valhalla/valhalla/jdk: Access control checks in findWither. Message-ID: <201706230050.v5N0ocu4019853@aojmv0008.oracle.com> Changeset: 058c0fc12a36 Author: psandoz Date: 2017-06-22 17:48 -0700 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/058c0fc12a36 Access control checks in findWither. ! src/java.base/share/classes/jdk/experimental/value/ValueType.java ! test/valhalla/mvt/MVTAccessCheck.java ! test/valhalla/mvt/MVTTest.java ! test/valhalla/mvt/Point.java From rwestrel at redhat.com Fri Jun 23 08:29:47 2017 From: rwestrel at redhat.com (rwestrel at redhat.com) Date: Fri, 23 Jun 2017 08:29:47 +0000 Subject: hg: valhalla/valhalla/hotspot: 8182633: [MVT] Fix method handle linker call with __Value arguments Message-ID: <201706230829.v5N8TmAf003624@aojmv0008.oracle.com> Changeset: 2552e5001a5d Author: roland Date: 2017-06-22 21:32 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/2552e5001a5d 8182633: [MVT] Fix method handle linker call with __Value arguments Reviewed-by: thartmann ! src/share/vm/opto/callGenerator.cpp ! src/share/vm/opto/graphKit.cpp ! src/share/vm/opto/type.cpp ! test/compiler/valhalla/valuetypes/ValueTypeTestBench.java From rwestrel at redhat.com Fri Jun 23 08:45:36 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Fri, 23 Jun 2017 10:45:36 +0200 Subject: RFR: C2: fix call with __Value arguments In-Reply-To: References: <44b6c688-a91d-93a5-316c-d8a8c4913f14@oracle.com> Message-ID: > Just a minor comment (you don't need to send another webrev): > In callGenerator.cpp: "need to a pointer to the value type" -> "need a pointer to the value type" > > We are now using JIRA bugs/enhancements for all MVT related work. I > created JDK-8182633 [1] for this, please close with a changeset > comment after you pushed this. Done. Thanks, Tobias. Roland. From rwestrel at redhat.com Fri Jun 23 08:51:06 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Fri, 23 Jun 2017 10:51:06 +0200 Subject: RFR(S): 8182585: [MVT] Reading an uninitialized static value type field should not throw a NPE In-Reply-To: References: Message-ID: > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.21/ Looks good to me. Roland. From tobias.hartmann at oracle.com Fri Jun 23 08:53:59 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Fri, 23 Jun 2017 10:53:59 +0200 Subject: RFR(S): 8182585: [MVT] Reading an uninitialized static value type field should not throw a NPE In-Reply-To: References: Message-ID: <9ced4f47-0548-c39f-4895-08f61824b5b9@oracle.com> Thanks Roland. Best regards, Tobias On 23.06.2017 10:51, Roland Westrelin wrote: > >> http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.21/ > > Looks good to me. > > Roland. > From rwestrel at redhat.com Fri Jun 23 09:13:57 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Fri, 23 Jun 2017 11:13:57 +0200 Subject: RFR(M): 8182471: [MVT] Eliminate redundant value type allocations In-Reply-To: References: Message-ID: > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.20/ callnode.hpp 849 fields[ValueNode] = Type::TOP; Type::TOP is strange here. Type::BOTTOM instead? Shouldn't remove_redundant_allocations() be called from split_if_with_blocks_post instead? As it is, you're potentially disconnecting the allocation and split_if_with_blocks_pre will try to follow its uses so wouldn't it stop halfway through the graph? Why do you need the dead_allocations list in ValueTypeNode::remove_redundant_allocations()? Roland. From tobias.hartmann at oracle.com Fri Jun 23 09:32:24 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Fri, 23 Jun 2017 11:32:24 +0200 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> Message-ID: <30b607de-c95c-536e-912e-edfa90b2b199@oracle.com> Hi Mandy, as I mentioned off-thread, this change breaks the ValueTypeTestBench.java because we rely on MyValue1.class.getDeclaredMethods() [1] to be able to access the declared methods of a value type and set compilation and inlining rules via the Whitebox API. This is crucial for the tests to work. In this case the value type is not derived but it's an VVT declared with "__ByValue". This change also breaks the ValueTypeArray.java test with: Caused by: java.lang.ClassNotFoundException: [Qruntime.valhalla.valuetypes.Point; is a derived value class at java.base/java.lang.Class.forName(Class.java:293) at runtime.valhalla.valuetypes.ValueTypeArray.testClassForName(ValueTypeArray.java:62) Because the test does Class.forName("[Qruntime.valhalla.valuetypes.Point;"). And DeriveValueTypeCreation.java and VboxUnbox.java fail with: java.lang.InternalError: runtime.valhalla.valuetypes.ValueCapableClass$Value not a value type at java.base/java.lang.System$2.loadValueTypeClass(System.java:2174) at java.base/valhalla.shady.MinimalValueTypes_1_0.loadValueTypeClass(MinimalValueTypes_1_0.java:110) at java.base/valhalla.shady.MinimalValueTypes_1_0.getValueTypeClass(MinimalValueTypes_1_0.java:103) at java.base/jdk.experimental.value.ValueType.forClass(ValueType.java:152) at runtime.valhalla.valuetypes.VboxUnbox.testCorrectBoxing(VboxUnbox.java:47) at runtime.valhalla.valuetypes.VboxUnbox.main(VboxUnbox.java:41) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:563) at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:115) at java.base/java.lang.Thread.run(Thread.java:844) This is a problem with the C2 intrinsic for java.lang.Class::isAssignableFrom which does not work properly with value types. I'll work on a fix. As temporary workaround you can use -XX:DisableIntrinsic=_isAssignableFrom. Best regards, Tobias [1] http://hg.openjdk.java.net/valhalla/valhalla/hotspot/file/2552e5001a5d/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java#l2650 On 20.06.2017 22:31, Mandy Chung wrote: > http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.00/index.html > > This patch changes Class::forName to not to return DVT classes > and also disallows reflection API get members of a DVT class. > ClassLoader::loadClass should probably be changed and I can > fix that separately. > > I added a couple of new tests and also fix the MVT tests with > GPL header rather than GPL+CP header. > > Mandy > From tobias.hartmann at oracle.com Fri Jun 23 09:53:10 2017 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Fri, 23 Jun 2017 09:53:10 +0000 Subject: hg: valhalla/valhalla/hotspot: 8182585: [MVT] Reading an uninitialized static value type field should not throw a NPE Message-ID: <201706230953.v5N9rAHC002671@aojmv0008.oracle.com> Changeset: 963eefaa54a1 Author: thartmann Date: 2017-06-23 11:14 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/963eefaa54a1 8182585: [MVT] Reading an uninitialized static value type field should not throw a NPE Summary: Trap to interpreter if uninitialized static value type field is read. Reviewed-by: roland ! src/share/vm/opto/graphKit.cpp ! src/share/vm/opto/parse3.cpp From maurizio.cimadamore at oracle.com Fri Jun 23 10:15:02 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 23 Jun 2017 11:15:02 +0100 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <30b607de-c95c-536e-912e-edfa90b2b199@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <30b607de-c95c-536e-912e-edfa90b2b199@oracle.com> Message-ID: On 23/06/17 10:32, Tobias Hartmann wrote: > Hi Mandy, > > as I mentioned off-thread, this change breaks the ValueTypeTestBench.java because we rely on MyValue1.class.getDeclaredMethods() [1] to be able to access the declared methods of a value type and set compilation and inlining rules via the Whitebox API. This is crucial for the tests to work. In this case the value type is not derived but it's an VVT declared with "__ByValue". I'd say we should add a flag to allow reflection on value types - but at some point those tests would have to be translated to use VCC/DVT (in which case you can do reflection fine by looking at the VCC). Maurizio > > This change also breaks the ValueTypeArray.java test with: > Caused by: java.lang.ClassNotFoundException: [Qruntime.valhalla.valuetypes.Point; is a derived value class > at java.base/java.lang.Class.forName(Class.java:293) > at runtime.valhalla.valuetypes.ValueTypeArray.testClassForName(ValueTypeArray.java:62) > Because the test does Class.forName("[Qruntime.valhalla.valuetypes.Point;"). > > And DeriveValueTypeCreation.java and VboxUnbox.java fail with: > java.lang.InternalError: runtime.valhalla.valuetypes.ValueCapableClass$Value not a value type > at java.base/java.lang.System$2.loadValueTypeClass(System.java:2174) > at java.base/valhalla.shady.MinimalValueTypes_1_0.loadValueTypeClass(MinimalValueTypes_1_0.java:110) > at java.base/valhalla.shady.MinimalValueTypes_1_0.getValueTypeClass(MinimalValueTypes_1_0.java:103) > at java.base/jdk.experimental.value.ValueType.forClass(ValueType.java:152) > at runtime.valhalla.valuetypes.VboxUnbox.testCorrectBoxing(VboxUnbox.java:47) > at runtime.valhalla.valuetypes.VboxUnbox.main(VboxUnbox.java:41) > at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) > at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) > at java.base/java.lang.reflect.Method.invoke(Method.java:563) > at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:115) > at java.base/java.lang.Thread.run(Thread.java:844) > > This is a problem with the C2 intrinsic for java.lang.Class::isAssignableFrom which does not work properly with value types. I'll work on a fix. As temporary workaround you can use -XX:DisableIntrinsic=_isAssignableFrom. > > Best regards, > Tobias > > [1] http://hg.openjdk.java.net/valhalla/valhalla/hotspot/file/2552e5001a5d/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java#l2650 > > On 20.06.2017 22:31, Mandy Chung wrote: >> http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.00/index.html >> >> This patch changes Class::forName to not to return DVT classes >> and also disallows reflection API get members of a DVT class. >> ClassLoader::loadClass should probably be changed and I can >> fix that separately. >> >> I added a couple of new tests and also fix the MVT tests with >> GPL header rather than GPL+CP header. >> >> Mandy >> From rwestrel at redhat.com Fri Jun 23 13:29:18 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Fri, 23 Jun 2017 15:29:18 +0200 Subject: MH compilation is broken in valhalla(mvt branch) build In-Reply-To: <553af40b-ebcd-174c-3a11-bc9d9ea3fc99@oracle.com> References: <553af40b-ebcd-174c-3a11-bc9d9ea3fc99@oracle.com> Message-ID: > to mitigate the impact of this, we could only bail out if the compiled lambda form really contains a value type in it's signature: > > diff -r 67cdfd4b0995 src/share/vm/compiler/compileBroker.cpp > --- a/src/share/vm/compiler/compileBroker.cpp Tue Jun 20 11:18:10 2017 +0200 > +++ b/src/share/vm/compiler/compileBroker.cpp Thu Jun 22 16:55:50 2017 +0200 > @@ -1054,7 +1054,12 @@ > // value type. If compiled as root of a compilation, C2 has no way > // to know a value type is passed. > if (ValueTypePassFieldsAsArgs && method->is_compiled_lambda_form()) { > - return NULL; > + ResourceMark rm; > + for (SignatureStream ss(method->signature()); !ss.at_return_type(); ss.next()) { > + if (ss.type() == T_VALUETYPE) { > + return NULL; > + } > + } > } > > // lock, make sure that the compilation > > Roland, what do you think? That sounds like a good idea. Roland. From paul.sandoz at oracle.com Fri Jun 23 17:15:42 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 23 Jun 2017 10:15:42 -0700 Subject: RFR JDK-8182678: add javac and method handle support for mangled value class names in CONSTANT_ClassInfo In-Reply-To: <1cff887a-a11c-6679-d4b9-aed72ce964d1@oracle.com> References: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> <1cff887a-a11c-6679-d4b9-aed72ce964d1@oracle.com> Message-ID: > On 22 Jun 2017, at 09:52, Maurizio Cimadamore wrote: > > > > On 22/06/17 17:36, Paul Sandoz wrote: >>> On 22 Jun 2017, at 04:35, Maurizio Cimadamore wrote: >>> >>> >>> >>> On 22/06/17 02:22, Paul Sandoz wrote: >>>> Looks good, although it would be nice if the javac and java properties were the same name as it?s hard to remember the plethora of such properties that are available. >>> Sure - note that I tried to use the same name - but the javac convention is not to use any qualified name for options, while it seems like all the MVT-related options in the JDK starts off with 'valhalla.' - which is why I landed there, as the option name is kind of the same (mangleClassInfo is contained in both), and the scheme is consistent with both javac and jdk unwritten rules. >>> >>> That said, if you think it's too confusing, I can change it no problem. >>> >> Thinking more, my objection is really that i don?t have a holistic view of all the possible flags for javac, and hotspot. >> >> It would be useful if we have a page somewhere listing all such flags with a small description. We cold use a dummy issue and edit the description? > Sounds like a good idea - flags always introduce a certain non-determinism to the dev experience; any attempt to keep them under check is welcome on my part ;-) > I?ll start another thread on this. Paul. From paul.sandoz at oracle.com Fri Jun 23 17:55:56 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 23 Jun 2017 10:55:56 -0700 Subject: Wiki page for command line options Message-ID: <2745BDFF-3DE5-4594-885E-E88C69F825AA@oracle.com> Hi, See here: https://wiki.openjdk.java.net/display/valhalla/Minimal+Value+Types+and+Valhalla+value+types+command+line+options Anyone with an author role can edit, please do so to edit or fill out the options and descriptions, or send me text and i will update. Especially useful would be to note any restrictions when enabled or for the default (such as that recently for inlining of non-constant MHs). Paul. From karen.kinnear at oracle.com Fri Jun 23 19:48:17 2017 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Fri, 23 Jun 2017 15:48:17 -0400 Subject: RFR: Implement value type buffering for the interpreter In-Reply-To: <3B3BE56F-D7DC-4963-8C86-C7D205426367@oracle.com> References: <3B3BE56F-D7DC-4963-8C86-C7D205426367@oracle.com> Message-ID: <75092770-336E-4936-B534-BBD4027A38F0@oracle.com> Frederic, This looks excellent, thank you for doing this so carefully. And thank you for the cleanups and diagnostic information. I had a few minor questions/comments. I do not need to see any updates - feel free to check this in with or without changes. questions/comments: 1. VTBuffer::allocate_vt_chunk line 98 comment - could you possibly change "Done with _pool_lock" to "Hold _pool_lock"? "Done with" could be translated as you have completed using the _pool_lock. 2. I could use help understanding the JDK10 change to root walking that meant that you needed to store the java_mirror in the mark word. Is there a bugid or comments in the source that I could read up on this? Is the intent here that it is faster to just read the mirror than to follow the valueKlass field to retrieve the mirror? So this is a memory/GC pause time tradeoff and today we have that memory available? It looks like the existing OopClosure is still being passed the reference heap address not the mirror for non-buffered types - or did I read this incorrectly? 3. InterpreterRuntime::vwithfield line 254 I didn't understand why this wasn't a CHECK_0)? 4. mutexLocker.cpp, instanceKlass.cpp and oopMapCAche.cpp - these locks changed to not look for safepoint Do we need these changes in hs10? 5. UninitializedValueFieldsTest Why did you disable -Xcomp ? thanks, Karen > On Jun 20, 2017, at 4:50 PM, Frederic Parain wrote: > > Greetings, > > Here's a webrev implementing value type buffering for the interpreter. > > http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.01/ > > Buffering allows the interpreter to allocate values in a thread local > buffer to avoid Java heap allocations. Memory recycling is performed > on method exit and sometimes on backward branches. > > Format of buffered values is almost identical to the format of > Java heap allocated values, so most code won't see any difference > between a buffered value and a not buffered value. The only difference > is in the first word of the header. Because of a change in GC closures > in JDK10, the first word now stores a reference to the Java mirror > of the value class in order to keep it alive. In JDK9, this operation > was performed through the klass pointer in the header, but the GC > team has removed this closure. > > Buffering can be monitored using NMT or a new diagnostic command. > > All tests pass and Sergey has already tested the patch with his > benchmark (and reported several bugs that are now fixed, thank > you Sergey). > > Unfortunately, the changeset also includes a number of fixes not > related to buffering, like code clean up and access to uninitialized > static value fields. > > Thanks, > > Fred From frederic.parain at oracle.com Fri Jun 23 20:29:45 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Fri, 23 Jun 2017 16:29:45 -0400 Subject: RFR: Implement value type buffering for the interpreter In-Reply-To: <75092770-336E-4936-B534-BBD4027A38F0@oracle.com> References: <3B3BE56F-D7DC-4963-8C86-C7D205426367@oracle.com> <75092770-336E-4936-B534-BBD4027A38F0@oracle.com> Message-ID: <7C0EB2EF-5519-4D1E-9C25-E1A2DEA0D932@oracle.com> Karen, Thank you for the review. My answers are in-lined below. > On Jun 23, 2017, at 15:48, Karen Kinnear wrote: > > Frederic, > > This looks excellent, thank you for doing this so carefully. And thank you > for the cleanups and diagnostic information. > > I had a few minor questions/comments. I do not need to see any updates - feel > free to check this in with or without changes. > > questions/comments: > 1. VTBuffer::allocate_vt_chunk > line 98 comment - could you possibly change "Done with _pool_lock" to > "Hold _pool_lock"? > "Done with" could be translated as you have completed using the _pool_lock. Fixed. > > 2. I could use help understanding the JDK10 change to root walking > that meant that you needed to store the java_mirror in the mark word. > Is there a bugid or comments in the source that I could read up on this? > Is the intent here that it is faster to just read the mirror than to > follow the valueKlass field to retrieve the mirror? So this is a memory/GC pause > time tradeoff and today we have that memory available? The change has been tracked with CR: https://bugs.openjdk.java.net/browse/JDK-8154580 > It looks like the existing OopClosure is still being passed the reference heap address not > the mirror for non-buffered types - or did I read this incorrectly? Correct, the behavior for heap-allocated values is the same as for objects. > > 3. InterpreterRuntime::vwithfield line 254 > I didn't understand why this wasn't a CHECK_0)? I?m not sure about this one. The assembly part of the bytecode is supposed to use the value to cleanup the stack, but because an exception is thrown, I don?t know how it is handled (before it was returning zero and nothing broke). I still have to learn the details of the exception throwing code. > > 4. mutexLocker.cpp, instanceKlass.cpp and oopMapCAche.cpp - these locks changed to not look for safepoint > Do we need these changes in hs10? Yes, absolutely, otherwise a GC could happen during a phase of the buffer recycling where values are being relocated. I?ve tried this change on a JDK10 repo, run several tests suites, and seen no failures. I?ve discussed this change with Coleen, and she thinks it is fine too. > 5. UninitializedValueFieldsTest > Why did you disable -Xcomp ? > The code to handle uninitialized static field in the JIT was not available when I?ve generated the webrev. Tobias has just pushed the missing code, so I can re-enable the -Xcomp case. Regards, Fred > >> On Jun 20, 2017, at 4:50 PM, Frederic Parain wrote: >> >> Greetings, >> >> Here's a webrev implementing value type buffering for the interpreter. >> >> http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.01/ >> >> Buffering allows the interpreter to allocate values in a thread local >> buffer to avoid Java heap allocations. Memory recycling is performed >> on method exit and sometimes on backward branches. >> >> Format of buffered values is almost identical to the format of >> Java heap allocated values, so most code won't see any difference >> between a buffered value and a not buffered value. The only difference >> is in the first word of the header. Because of a change in GC closures >> in JDK10, the first word now stores a reference to the Java mirror >> of the value class in order to keep it alive. In JDK9, this operation >> was performed through the klass pointer in the header, but the GC >> team has removed this closure. >> >> Buffering can be monitored using NMT or a new diagnostic command. >> >> All tests pass and Sergey has already tested the patch with his >> benchmark (and reported several bugs that are now fixed, thank >> you Sergey). >> >> Unfortunately, the changeset also includes a number of fixes not >> related to buffering, like code clean up and access to uninitialized >> static value fields. >> >> Thanks, >> >> Fred > From maurizio.cimadamore at oracle.com Fri Jun 23 20:49:54 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 23 Jun 2017 21:49:54 +0100 Subject: Wiki page for command line options In-Reply-To: <2745BDFF-3DE5-4594-885E-E88C69F825AA@oracle.com> References: <2745BDFF-3DE5-4594-885E-E88C69F825AA@oracle.com> Message-ID: <27b78caa-f8da-efde-2632-84b25acf3cb0@oracle.com> Thanks - I've added a short description of the checks performed by javac when the Xlint:values option is enabled. Maurizio On 23/06/17 18:55, Paul Sandoz wrote: > Hi, > > See here: > > https://wiki.openjdk.java.net/display/valhalla/Minimal+Value+Types+and+Valhalla+value+types+command+line+options > > Anyone with an author role can edit, please do so to edit or fill out the options and descriptions, or send me text and i will update. Especially useful would be to note any restrictions when enabled or for the default (such as that recently for inlining of non-constant MHs). > > Paul. From paul.sandoz at oracle.com Fri Jun 23 22:17:53 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 23 Jun 2017 15:17:53 -0700 Subject: ValueType.findConstructor Message-ID: Hi, This adds a findConstructor method to ValueType: http://cr.openjdk.java.net/~psandoz/valhalla/find-constructor/webrev/ ? Next steps are to investigate re-construction: taking an existing value, one or more explicit component values, and constructing a new value by merging the implicit components of the existing value and the explicit component values. It?s a bit like one or more vwithfield calls but would go through a constructor and perform argument checks etc. The tricky aspect is reliably extracting out the component values and in a known order so they can be passed as arguments to the VCC constructor. For MVT i think we can define something useful even if it is a little fragile, so was to make construction easier. (There are also potential short-cuts if there is no explicit constructor and fields are either initialized to default or some other values, as i think vnew could be used directly for construction). Paul. From mandy.chung at oracle.com Fri Jun 23 22:49:47 2017 From: mandy.chung at oracle.com (Mandy Chung) Date: Sat, 24 Jun 2017 06:49:47 +0800 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <30b607de-c95c-536e-912e-edfa90b2b199@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <30b607de-c95c-536e-912e-edfa90b2b199@oracle.com> Message-ID: <31F14FEF-EF8F-4918-948B-0D2C2E3A1229@oracle.com> Hi Tobias, Thanks for looking into the issues. > On Jun 23, 2017, at 5:32 PM, Tobias Hartmann wrote: > > Hi Mandy, > > as I mentioned off-thread, this change breaks the ValueTypeTestBench.java because we rely on MyValue1.class.getDeclaredMethods() [1] to be able to access the declared methods of a value type and set compilation and inlining rules via the Whitebox API. This is crucial for the tests to work. In this case the value type is not derived but it's an VVT declared with "__ByValue?. I add a property ?jdk.lang.reflect.DVT? to allow reflection on DVT, as Maurizio suggests. When ValueTypeTestBench.java is converted to use VCC/DVT and do reflection on VCC, we should remove this property. > This change also breaks the ValueTypeArray.java test with: > Caused by: java.lang.ClassNotFoundException: [Qruntime.valhalla.valuetypes.Point; is a derived value class > at java.base/java.lang.Class.forName(Class.java:293) > This attempts to load DVT array class. Can the test use ValueType::arrayValueClass? I comment out testClassForName test case. Do you mind updating the test to use ValueType::arrayValueClass instead? > This is a problem with the C2 intrinsic for java.lang.Class::isAssignableFrom which does not work properly with value types. I'll work on a fix. As temporary workaround you can use -XX:DisableIntrinsic=_isAssignableFrom. > Another workaround is to check for ACC_VALUE for now and avoid calling isAssignableFrom until this issue is fixed. Here is the updated webrev: http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8181425/webrev.03/ Mandy From maurizio.cimadamore at oracle.com Fri Jun 23 23:31:18 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Sat, 24 Jun 2017 00:31:18 +0100 Subject: ValueType.findConstructor In-Reply-To: References: Message-ID: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> Maybe a naive question - but do you need method handle builder (and extra bytecode spinning) for constructor? Can't we combine the result of findConstructor on the boxed class with the vunbox MH? Maurizio On 23/06/17 23:17, Paul Sandoz wrote: > Hi, > > This adds a findConstructor method to ValueType: > > http://cr.openjdk.java.net/~psandoz/valhalla/find-constructor/webrev/ > > ? > > Next steps are to investigate re-construction: taking an existing value, one or more explicit component values, and constructing a new value by merging the implicit components of the existing value and the explicit component values. It?s a bit like one or more vwithfield calls but would go through a constructor and perform argument checks etc. > > The tricky aspect is reliably extracting out the component values and in a known order so they can be passed as arguments to the VCC constructor. > > For MVT i think we can define something useful even if it is a little fragile, so was to make construction easier. > > (There are also potential short-cuts if there is no explicit constructor and fields are either initialized to default or some other values, as i think vnew could be used directly for construction). > > Paul. From maurizio.cimadamore at oracle.com Fri Jun 23 23:32:30 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Sat, 24 Jun 2017 00:32:30 +0100 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <31F14FEF-EF8F-4918-948B-0D2C2E3A1229@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <30b607de-c95c-536e-912e-edfa90b2b199@oracle.com> <31F14FEF-EF8F-4918-948B-0D2C2E3A1229@oracle.com> Message-ID: <6ddda554-cf98-7c1e-b42b-a761a937d6ac@oracle.com> On 23/06/17 23:49, Mandy Chung wrote: > I add a property ?jdk.lang.reflect.DVT? to allow reflection on DVT, > as Maurizio suggests. When ValueTypeTestBench.java is converted to > use VCC/DVT and do reflection on VCC, we should remove this property Please don't forget to add this property here: https://wiki.openjdk.java.net/display/valhalla/Minimal+Value+Types+and+Valhalla+value+types+command+line+options (if you have not done so already) Maurizio From john.r.rose at oracle.com Sat Jun 24 00:37:59 2017 From: john.r.rose at oracle.com (John Rose) Date: Fri, 23 Jun 2017 17:37:59 -0700 Subject: RFR JDK-8182678: add javac and method handle support for mangled value class names in CONSTANT_ClassInfo In-Reply-To: References: <07e554a3-c5ee-c8cb-c692-45cf66da665d@oracle.com> Message-ID: On Jun 22, 2017, at 7:31 AM, Maurizio Cimadamore wrote: > > The fact that values are encoded as 'weird' ClassInfo simplifies things considerably, as most of the infrastructure just works. The changes for ;Qv; are surprisingly local. Fingers crossed that the JVM changes are simple too. ? John From john.r.rose at oracle.com Sat Jun 24 00:39:29 2017 From: john.r.rose at oracle.com (John Rose) Date: Fri, 23 Jun 2017 17:39:29 -0700 Subject: ValueType.findConstructor In-Reply-To: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> References: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> Message-ID: On Jun 23, 2017, at 4:31 PM, Maurizio Cimadamore wrote: > > Maybe a naive question - but do you need method handle builder (and extra bytecode spinning) for constructor? Can't we combine the result of findConstructor on the boxed class with the vunbox MH? It's certainly worth a try in the first cut. If the JIT fails to EA away the box, we have ways to make it comply. Longer term, we want a box-free way to manage this. ? John From david.simms at oracle.com Mon Jun 26 09:05:20 2017 From: david.simms at oracle.com (David Simms) Date: Mon, 26 Jun 2017 11:05:20 +0200 Subject: Unsafe value access In-Reply-To: References: Message-ID: Just summarize previous conversations: * Small values are "naturally atomic" (e.g. under 8 byte on x86_64), and the VM should strive to keep them so. * For payloads over this natural h/w size, instruction latencies for atomic load/store overheads are an order of magnitude higher than the actual load/store, the closer to the largest h/w load/store size you come. o Therefore the current "default" for VM value type load/store is currently *not atomic*. o Even when operations are not atomic, the VM and API built over, shall make every effort not to "shear" the component primitive and object reference fields (I.e. field aligned storage). * VarHandle API is of course free to implement its "AccessMode". o This will also be a great place to add experiments in evaluating atomic access costs. * Future design work of value types may specify atomic access at call-site or more generally for the type itself. /David Simms On 22/06/17 21:18, Paul Sandoz wrote: > Hi, > > To start working on VarHandle integration i first of all need unsafe access to values held within objects. For a most basic initial implementation we can use a global lock to preserve atomicity and memory ordering effects and defer the thinking about more sophisticated locking (seq locks etc), read-mody-write operations and other memory order effects to a another day. > > For these purposes we just require two methods: > > __Value getValue(Object base, long offset, Class vt) > > void putValue(Object base, long offset, Class vt, __Value v); > > I included Class parameter for the value type token. > > How feasible would it be to implement such methods? > > If people point me to the hotspot interpreter code for getfield/putfield implementations for values i might be able to make some progress. Once that is done we could then consider C1/C2 support. > > Thoughts? > > Thanks, > Paul. > > From tobias.hartmann at oracle.com Mon Jun 26 10:18:24 2017 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Mon, 26 Jun 2017 10:18:24 +0000 Subject: hg: valhalla/valhalla/hotspot: 8182453: [MVT] Method Handle compilation broken (even without value types) Message-ID: <201706261018.v5QAIO75022178@aojmv0008.oracle.com> Changeset: c0febf8d6eee Author: thartmann Date: 2017-06-26 12:13 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/c0febf8d6eee 8182453: [MVT] Method Handle compilation broken (even without value types) Summary: Only disable lambda form compilation if arguments contain value type. Reviewed-by: roland ! src/share/vm/compiler/compileBroker.cpp From tobias.hartmann at oracle.com Mon Jun 26 10:53:00 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Mon, 26 Jun 2017 12:53:00 +0200 Subject: RFR(M): 8182471: [MVT] Eliminate redundant value type allocations In-Reply-To: References: Message-ID: <3e7f7493-5bd4-aa4d-47d0-2eb314a5a73e@oracle.com> Hi Roland, On 23.06.2017 11:13, Roland Westrelin wrote: > callnode.hpp > > 849 fields[ValueNode] = Type::TOP; > > Type::TOP is strange here. Type::BOTTOM instead? Right, I changed it to BOTTOM. > Shouldn't remove_redundant_allocations() be called from > split_if_with_blocks_post instead? As it is, you're potentially > disconnecting the allocation and split_if_with_blocks_pre will try to > follow its uses so wouldn't it stop halfway through the graph? Yes, you are right. I moved the code to split_if_with_blocks_post(). > Why do you need the dead_allocations list in > ValueTypeNode::remove_redundant_allocations()? That's necessary to not corrupt the DUIterator_Fast which "Allows deletion from the out array only at the current point" but replacing an AllocateNode may cut off multiple edges from the ValueTypesNode (debug information edges). Updated webrev: http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.20/ Thanks, Tobias From rwestrel at redhat.com Mon Jun 26 11:27:35 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Mon, 26 Jun 2017 13:27:35 +0200 Subject: RFR(M): 8182471: [MVT] Eliminate redundant value type allocations In-Reply-To: <3e7f7493-5bd4-aa4d-47d0-2eb314a5a73e@oracle.com> References: <3e7f7493-5bd4-aa4d-47d0-2eb314a5a73e@oracle.com> Message-ID: > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.20/ That looks good to me. Roland. From tobias.hartmann at oracle.com Mon Jun 26 11:46:14 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Mon, 26 Jun 2017 13:46:14 +0200 Subject: RFR(M): 8182471: [MVT] Eliminate redundant value type allocations In-Reply-To: References: <3e7f7493-5bd4-aa4d-47d0-2eb314a5a73e@oracle.com> Message-ID: Thanks Roland. Best regards, Tobias On 26.06.2017 13:27, Roland Westrelin wrote: > >> http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.20/ > > That looks good to me. > > Roland. > From tobias.hartmann at oracle.com Mon Jun 26 12:09:12 2017 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Mon, 26 Jun 2017 12:09:12 +0000 Subject: hg: valhalla/valhalla/hotspot: 8182471: [MVT] Eliminate redundant value type allocations Message-ID: <201706261209.v5QC9CtW010626@aojmv0008.oracle.com> Changeset: 5f124977ad2c Author: thartmann Date: 2017-06-26 14:07 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/5f124977ad2c 8182471: [MVT] Eliminate redundant value type allocations Summary: Avoid redundant value type allocations if an existing (allocated) value type is copied. Reviewed-by: roland ! src/share/vm/opto/callGenerator.cpp ! src/share/vm/opto/callnode.cpp ! src/share/vm/opto/callnode.hpp ! src/share/vm/opto/doCall.cpp ! src/share/vm/opto/graphKit.cpp ! src/share/vm/opto/graphKit.hpp ! src/share/vm/opto/loopopts.cpp ! src/share/vm/opto/parse1.cpp ! src/share/vm/opto/parse2.cpp ! src/share/vm/opto/parse3.cpp ! src/share/vm/opto/valuetypenode.cpp ! src/share/vm/opto/valuetypenode.hpp ! test/compiler/valhalla/valuetypes/ValueTypeTestBench.java From tobias.hartmann at oracle.com Mon Jun 26 12:33:07 2017 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Mon, 26 Jun 2017 12:33:07 +0000 Subject: hg: valhalla/valhalla/hotspot: TypeValueTypePtr::NOTNULL should be available with EnableMVT Message-ID: <201706261233.v5QCX7vE018095@aojmv0008.oracle.com> Changeset: e1a373e5766e Author: thartmann Date: 2017-06-26 14:31 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/e1a373e5766e TypeValueTypePtr::NOTNULL should be available with EnableMVT ! src/share/vm/opto/type.cpp From tobias.hartmann at oracle.com Mon Jun 26 12:32:51 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Mon, 26 Jun 2017 14:32:51 +0200 Subject: hg: valhalla/valhalla/hotspot: TypeValueTypePtr::NOTNULL should be available with EnableMVT In-Reply-To: <201706261233.v5QCX7vE018095@aojmv0008.oracle.com> References: <201706261233.v5QCX7vE018095@aojmv0008.oracle.com> Message-ID: Hi, my recent change [1] triggered this problem with the runtime/valhalla/valuetypes/VboxUnbox.java test because if EnableMVT=true and EnableValhalla=false, TypeNarrowKlass::NULL_PTR is NULL although it's used by OptoRuntime::store_value_type_fields_Type() for multiple value return [2]. Best regards, Tobias [1] http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/c0febf8d6eee [2] http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/4cd1b06ce224 On 26.06.2017 14:33, tobias.hartmann at oracle.com wrote: > Changeset: e1a373e5766e > Author: thartmann > Date: 2017-06-26 14:31 +0200 > URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/e1a373e5766e > > TypeValueTypePtr::NOTNULL should be available with EnableMVT > > ! src/share/vm/opto/type.cpp > From tobias.hartmann at oracle.com Mon Jun 26 13:54:02 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Mon, 26 Jun 2017 15:54:02 +0200 Subject: RFR JDK-8181425: Reflection API defend against issues with internal VM derived value type In-Reply-To: <31F14FEF-EF8F-4918-948B-0D2C2E3A1229@oracle.com> References: <14418A5B-B3A1-451E-89D2-783F784FE5E7@oracle.com> <30b607de-c95c-536e-912e-edfa90b2b199@oracle.com> <31F14FEF-EF8F-4918-948B-0D2C2E3A1229@oracle.com> Message-ID: Hi Mandy, On 24.06.2017 00:49, Mandy Chung wrote: > I add a property ?jdk.lang.reflect.DVT? to allow reflection on DVT, > as Maurizio suggests. When ValueTypeTestBench.java is converted to > use VCC/DVT and do reflection on VCC, we should remove this property. That looks good to me. > This attempts to load DVT array class. Can the test use ValueType::arrayValueClass? I comment out testClassForName test case. > Do you mind updating the test to use ValueType::arrayValueClass instead? I think the runtime folks should look at this because they own that test but I'm fine with temporarily disabling this part. > Another workaround is to check for ACC_VALUE for now and avoid > calling isAssignableFrom until this issue is fixed. Okay, thanks. The C2 fix for the intrinsic is non-trivial. I'll file a separate bug and will add a regression test with the fix. Best regards, Tobias From david.simms at oracle.com Mon Jun 26 14:04:26 2017 From: david.simms at oracle.com (David Simms) Date: Mon, 26 Jun 2017 16:04:26 +0200 Subject: RFR: Implement value type buffering for the interpreter In-Reply-To: <3B3BE56F-D7DC-4963-8C86-C7D205426367@oracle.com> References: <3B3BE56F-D7DC-4963-8C86-C7D205426367@oracle.com> Message-ID: Kudos on the loop testing, like the targeted testing . Good work on the static init fixes and testing. Minor comments: * globals.hpp:4097 "sizeof(long long)", is at least 64bits, but not fixed size: do you mean BytesPerLong or longSize ? * ValueTypesBufferMaxMemory=128, global fixed limit o "doesn't feel right", but I admit to not having a better answer. Needs more user testing: TODO, we did talk off list about this, discussed combination of global + per-thread options. o Should "Global VTBuffer Pool statistics" include a failure statistic to help with performance evaluation/tuning ? * vtBuffer.hpp:40 "_index;" - I can guess what all the other fields are at a glance, but a short comment here would be nice I was wondering if "InterpreterFrameClosure" changes didn't trigger a problem in the ValueOops whitebox testing (frame oop maps)...that test feels a little on the fragile side. Looks good, nice work, long live Value Type TLGC :-) /David Simms On 20/06/17 22:50, Frederic Parain wrote: > Greetings, > > Here's a webrev implementing value type buffering for the interpreter. > > http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.01/ > > Buffering allows the interpreter to allocate values in a thread local > buffer to avoid Java heap allocations. Memory recycling is performed > on method exit and sometimes on backward branches. > > Format of buffered values is almost identical to the format of > Java heap allocated values, so most code won't see any difference > between a buffered value and a not buffered value. The only difference > is in the first word of the header. Because of a change in GC closures > in JDK10, the first word now stores a reference to the Java mirror > of the value class in order to keep it alive. In JDK9, this operation > was performed through the klass pointer in the header, but the GC > team has removed this closure. > > Buffering can be monitored using NMT or a new diagnostic command. > > All tests pass and Sergey has already tested the patch with his > benchmark (and reported several bugs that are now fixed, thank > you Sergey). > > Unfortunately, the changeset also includes a number of fixes not > related to buffering, like code clean up and access to uninitialized > static value fields. > > Thanks, > > Fred From frederic.parain at oracle.com Mon Jun 26 14:40:12 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Mon, 26 Jun 2017 10:40:12 -0400 Subject: RFR: Implement value type buffering for the interpreter In-Reply-To: References: <3B3BE56F-D7DC-4963-8C86-C7D205426367@oracle.com> Message-ID: <74e220bc-18ad-83b0-22e0-88a9a3129fba@oracle.com> Mr Simms, Thank you for the review. See my answers in-lined below. On 06/26/2017 10:04 AM, David Simms wrote: > > Kudos on the loop testing, like the targeted testing . Good work on the > static init fixes and testing. > > Minor comments: > > * globals.hpp:4097 "sizeof(long long)", is at least 64bits, but not > fixed size: do you mean BytesPerLong or longSize ? Changed to BytesPerLong. Eventually, this parameter would become a per-platform parameter, to take into account the instruction capabilities of each CPU. > * ValueTypesBufferMaxMemory=128, global fixed limit > o "doesn't feel right", but I admit to not having a better answer. > Needs more user testing: TODO, we did talk off list about this, > discussed combination of global + per-thread options. I've delayed this work to push the VT buffering ASAP. Among the TODO list, I'd like to re-write the backend allocator to avoid fragmenting the memory. I'd like to implement the global/local limits we have discussed, but I need more usage data to tune them. > o Should "Global VTBuffer Pool statistics" include a failure > statistic to help with performance evaluation/tuning ? Nice suggestion. A global allocating failure counter could help detecting too small global buffer size. In addition, a per-thread allocation failure counter could help detecting unbalanced use of the global buffer memory. I'll implement it this week. > * vtBuffer.hpp:40 "_index;" - I can guess what all the other fields > are at a glance, but a short comment here would be nice Each thread builds its own linked list of VTBufferChunk. Having an index in each chunk indicating its position in the list enables optimizations when comparing the addresses of two buffered values (because buffer chunks are not contiguous, addresses cannot be compared directly). I'll add a comment about that. > I was wondering if "InterpreterFrameClosure" changes didn't trigger a > problem in the ValueOops whitebox testing (frame oop maps)...that test > feels a little on the fragile side. The modification of the InterpreterFrameClosure changes the way references to values are handled, but the oopmap themselves are not changed. Do you think this would cause an issue? Thanks, Fred > > On 20/06/17 22:50, Frederic Parain wrote: >> Greetings, >> >> Here's a webrev implementing value type buffering for the interpreter. >> >> http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.01/ >> >> Buffering allows the interpreter to allocate values in a thread local >> buffer to avoid Java heap allocations. Memory recycling is performed >> on method exit and sometimes on backward branches. >> >> Format of buffered values is almost identical to the format of >> Java heap allocated values, so most code won't see any difference >> between a buffered value and a not buffered value. The only difference >> is in the first word of the header. Because of a change in GC closures >> in JDK10, the first word now stores a reference to the Java mirror >> of the value class in order to keep it alive. In JDK9, this operation >> was performed through the klass pointer in the header, but the GC >> team has removed this closure. >> >> Buffering can be monitored using NMT or a new diagnostic command. >> >> All tests pass and Sergey has already tested the patch with his >> benchmark (and reported several bugs that are now fixed, thank >> you Sergey). >> >> Unfortunately, the changeset also includes a number of fixes not >> related to buffering, like code clean up and access to uninitialized >> static value fields. >> >> Thanks, >> >> Fred > > From tobias.hartmann at oracle.com Mon Jun 26 14:34:00 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Mon, 26 Jun 2017 16:34:00 +0200 Subject: RFR(S): 8182867: [MVT] Escape analysis does not support value type return with reference field Message-ID: <12a8b421-877c-6c79-1487-bb18e24193a1@oracle.com> Hi, please review the following patch: https://bugs.openjdk.java.net/browse/JDK-8182867 http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.23/ Escape analysis fails with "missing allocation reference path" if a value type is returned as fields and contains a reference field. This is because the reference field value may be an allocation which is then connected to the ReturnNode. Fixed by adding a case for Op_Return and checking if we really return a value type with a reference field. Thanks, Tobias From rwestrel at redhat.com Mon Jun 26 14:37:01 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Mon, 26 Jun 2017 16:37:01 +0200 Subject: RFR(S): 8182867: [MVT] Escape analysis does not support value type return with reference field In-Reply-To: <12a8b421-877c-6c79-1487-bb18e24193a1@oracle.com> References: <12a8b421-877c-6c79-1487-bb18e24193a1@oracle.com> Message-ID: > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.23/ Looks good to me. Roland. From mandy.chung at oracle.com Mon Jun 26 14:44:44 2017 From: mandy.chung at oracle.com (mandy.chung at oracle.com) Date: Mon, 26 Jun 2017 14:44:44 +0000 Subject: hg: valhalla/valhalla/jdk: 8181425: Reflection API defend against issues with internal VM derived value type Message-ID: <201706261444.v5QEiifM028610@aojmv0008.oracle.com> Changeset: 3e8e22f687fc Author: mchung Date: 2017-06-26 22:40 +0800 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/3e8e22f687fc 8181425: Reflection API defend against issues with internal VM derived value type Reviewed-by: mcimadamore, psandoz, dsimms, thartmann ! src/java.base/share/classes/java/lang/Class.java ! src/java.base/share/classes/java/lang/System.java ! src/java.base/share/classes/java/lang/invoke/MethodHandles.java ! src/java.base/share/classes/jdk/experimental/value/ValueType.java ! src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java ! src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java ! test/TEST.groups + test/valhalla/mvt/MVTReflectionTest.java ! test/valhalla/mvt/MVTTest.java + test/valhalla/mvt/modules/Driver.java + test/valhalla/mvt/modules/m/module-info.java + test/valhalla/mvt/modules/m/p/Main.java + test/valhalla/mvt/modules/m/p/internal/Point.java From tobias.hartmann at oracle.com Mon Jun 26 14:43:17 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Mon, 26 Jun 2017 16:43:17 +0200 Subject: RFR(S): 8182867: [MVT] Escape analysis does not support value type return with reference field In-Reply-To: References: <12a8b421-877c-6c79-1487-bb18e24193a1@oracle.com> Message-ID: <4656d3b2-d255-e6e0-2749-84026cb7542e@oracle.com> On 26.06.2017 16:37, Roland Westrelin wrote: >> http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.23/ > > Looks good to me. Thanks Roland. Best regards, Tobias From mandy.chung at oracle.com Mon Jun 26 14:45:08 2017 From: mandy.chung at oracle.com (mandy.chung at oracle.com) Date: Mon, 26 Jun 2017 14:45:08 +0000 Subject: hg: valhalla/valhalla/hotspot: 8181425: Reflection API defend against issues with internal VM derived value type Message-ID: <201706261445.v5QEj8a3028833@aojmv0008.oracle.com> Changeset: 7dc3edf441c6 Author: mchung Date: 2017-06-26 22:41 +0800 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/7dc3edf441c6 8181425: Reflection API defend against issues with internal VM derived value type Reviewed-by: mcimadamore, psandoz, dsimms, thartmann ! test/compiler/valhalla/valuetypes/ValueTypeTestBench.java ! test/runtime/valhalla/valuetypes/ValueTypeArray.java From tobias.hartmann at oracle.com Mon Jun 26 14:47:32 2017 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Mon, 26 Jun 2017 14:47:32 +0000 Subject: hg: valhalla/valhalla/hotspot: 8182867: [MVT] Escape analysis does not support value type return with reference field Message-ID: <201706261447.v5QElXYK000223@aojmv0008.oracle.com> Changeset: 0da062c2ad24 Author: thartmann Date: 2017-06-26 16:45 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/0da062c2ad24 8182867: [MVT] Escape analysis does not support value type return with reference field Summary: Escape analysis needs to handle value types being returned as fields. Reviewed-by: roland ! src/share/vm/ci/ciValueKlass.cpp ! src/share/vm/ci/ciValueKlass.hpp ! src/share/vm/opto/escape.cpp From frederic.parain at oracle.com Mon Jun 26 17:11:39 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Mon, 26 Jun 2017 13:11:39 -0400 Subject: RFR: Implement value type buffering for the interpreter In-Reply-To: <74e220bc-18ad-83b0-22e0-88a9a3129fba@oracle.com> References: <3B3BE56F-D7DC-4963-8C86-C7D205426367@oracle.com> <74e220bc-18ad-83b0-22e0-88a9a3129fba@oracle.com> Message-ID: Here's a new webrev: http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.02/index.html Changes: - fix parameter default value in global.hpp - add comment about VTBufferChunk fields in vtBuffer.hpp - add two new counters to track failed chunk allocations Thanks, Fred On 06/26/2017 10:40 AM, Frederic Parain wrote: > Mr Simms, > > Thank you for the review. > See my answers in-lined below. > > On 06/26/2017 10:04 AM, David Simms wrote: >> >> Kudos on the loop testing, like the targeted testing . Good work on >> the static init fixes and testing. >> >> Minor comments: >> >> * globals.hpp:4097 "sizeof(long long)", is at least 64bits, but not >> fixed size: do you mean BytesPerLong or longSize ? > > Changed to BytesPerLong. > Eventually, this parameter would become a per-platform parameter, to > take into account the instruction capabilities of each CPU. > >> * ValueTypesBufferMaxMemory=128, global fixed limit >> o "doesn't feel right", but I admit to not having a better answer. >> Needs more user testing: TODO, we did talk off list about this, >> discussed combination of global + per-thread options. > > I've delayed this work to push the VT buffering ASAP. > Among the TODO list, I'd like to re-write the backend allocator to > avoid fragmenting the memory. I'd like to implement the global/local > limits we have discussed, but I need more usage data to tune them. > >> o Should "Global VTBuffer Pool statistics" include a failure >> statistic to help with performance evaluation/tuning ? > > Nice suggestion. > A global allocating failure counter could help detecting too small > global buffer size. > In addition, a per-thread allocation failure counter could help > detecting unbalanced use of the global buffer memory. > I'll implement it this week. > >> * vtBuffer.hpp:40 "_index;" - I can guess what all the other fields >> are at a glance, but a short comment here would be nice > > Each thread builds its own linked list of VTBufferChunk. Having an > index in each chunk indicating its position in the list enables > optimizations when comparing the addresses of two buffered values > (because buffer chunks are not contiguous, addresses cannot be > compared directly). > I'll add a comment about that. > >> I was wondering if "InterpreterFrameClosure" changes didn't trigger a >> problem in the ValueOops whitebox testing (frame oop maps)...that test >> feels a little on the fragile side. > > The modification of the InterpreterFrameClosure changes the way > references to values are handled, but the oopmap themselves are > not changed. Do you think this would cause an issue? > > Thanks, > > Fred > >> >> On 20/06/17 22:50, Frederic Parain wrote: >>> Greetings, >>> >>> Here's a webrev implementing value type buffering for the interpreter. >>> >>> http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.01/ >>> >>> Buffering allows the interpreter to allocate values in a thread local >>> buffer to avoid Java heap allocations. Memory recycling is performed >>> on method exit and sometimes on backward branches. >>> >>> Format of buffered values is almost identical to the format of >>> Java heap allocated values, so most code won't see any difference >>> between a buffered value and a not buffered value. The only difference >>> is in the first word of the header. Because of a change in GC closures >>> in JDK10, the first word now stores a reference to the Java mirror >>> of the value class in order to keep it alive. In JDK9, this operation >>> was performed through the klass pointer in the header, but the GC >>> team has removed this closure. >>> >>> Buffering can be monitored using NMT or a new diagnostic command. >>> >>> All tests pass and Sergey has already tested the patch with his >>> benchmark (and reported several bugs that are now fixed, thank >>> you Sergey). >>> >>> Unfortunately, the changeset also includes a number of fixes not >>> related to buffering, like code clean up and access to uninitialized >>> static value fields. >>> >>> Thanks, >>> >>> Fred >> >> From paul.sandoz at oracle.com Mon Jun 26 17:46:48 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 26 Jun 2017 10:46:48 -0700 Subject: ValueType.findConstructor In-Reply-To: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> References: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> Message-ID: <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> Hi Maurizio, It?s not naive, that code reflected a reduction on some hacking in an attempt to also explore construction with a default constructor (there is also a disconnect here between the VCC with a constructor and using vdefault with DVT). I think we should keep the constructor method and implement it as you suggest with a combinator. I?ll send out a simplified webrev. Separately, in my enthusiasm i may be going down a rabbit hole regarding re-construction, arguably it?s not in the spirit of minimal. Still at some point i think we should explore this notion of a more extensible wither for value types (but it also seems application to ref/data classes too). Paul. > On 23 Jun 2017, at 16:31, Maurizio Cimadamore wrote: > > Maybe a naive question - but do you need method handle builder (and extra bytecode spinning) for constructor? Can't we combine the result of findConstructor on the boxed class with the vunbox MH? > > Maurizio > > > On 23/06/17 23:17, Paul Sandoz wrote: >> Hi, >> >> This adds a findConstructor method to ValueType: >> >> http://cr.openjdk.java.net/~psandoz/valhalla/find-constructor/webrev/ >> >> ? >> >> Next steps are to investigate re-construction: taking an existing value, one or more explicit component values, and constructing a new value by merging the implicit components of the existing value and the explicit component values. It?s a bit like one or more vwithfield calls but would go through a constructor and perform argument checks etc. >> >> The tricky aspect is reliably extracting out the component values and in a known order so they can be passed as arguments to the VCC constructor. >> >> For MVT i think we can define something useful even if it is a little fragile, so was to make construction easier. >> >> (There are also potential short-cuts if there is no explicit constructor and fields are either initialized to default or some other values, as i think vnew could be used directly for construction). >> >> Paul. > From john.r.rose at oracle.com Mon Jun 26 18:08:52 2017 From: john.r.rose at oracle.com (John Rose) Date: Mon, 26 Jun 2017 11:08:52 -0700 Subject: ValueType.findConstructor In-Reply-To: <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> References: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> Message-ID: <25181831-0216-4513-8DF7-FC1E3A92E3CB@oracle.com> On Jun 26, 2017, at 10:46 AM, Paul Sandoz wrote: > > Separately, in my enthusiasm i may be going down a rabbit hole regarding re-construction, arguably it?s not in the spirit of minimal. Still at some point i think we should explore this notion of a more extensible wither for value types (but it also seems application to ref/data classes too). FTR, more on reconstrucors: https://bugs.openjdk.java.net/browse/JDK-8182843 In that document, reconstructor is mostly a language-level concept with small tweaks at the VM level (to make slightly less unique). So, yes, it isn't part of MVT. I think what you've found is that method handle combinators are a place where we can experiment with the use of reconstructors, before language changes. But that's not MVT either, I think. Another thing we have learned about value types is that they don't really have an method; they have factories. We'll *need* that concept for value types, and it will turn out to be *useful* for object types. So at some point we'll have to coin a name that is the factory version of , perhaps something like , , , , etc. Again, none of the above is minimal, unless and except it somehow gets MVT out the door faster. ? John From paul.sandoz at oracle.com Mon Jun 26 18:43:47 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 26 Jun 2017 11:43:47 -0700 Subject: ValueType.findConstructor In-Reply-To: <25181831-0216-4513-8DF7-FC1E3A92E3CB@oracle.com> References: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> <25181831-0216-4513-8DF7-FC1E3A92E3CB@oracle.com> Message-ID: <37A6A8E5-9A51-4FE9-B15A-E1247E9D0B9A@oracle.com> > On 26 Jun 2017, at 11:08, John Rose wrote: > > On Jun 26, 2017, at 10:46 AM, Paul Sandoz > wrote: >> >> Separately, in my enthusiasm i may be going down a rabbit hole regarding re-construction, arguably it?s not in the spirit of minimal. Still at some point i think we should explore this notion of a more extensible wither for value types (but it also seems application to ref/data classes too). > > FTR, more on reconstrucors: https://bugs.openjdk.java.net/browse/JDK-8182843 > > In that document, reconstructor is mostly a language-level concept with small > tweaks at the VM level (to make slightly less unique). So, yes, it isn't part of MVT. > Thanks. > I think what you've found is that method handle combinators are a place where we > can experiment with the use of reconstructors, before language changes. Yes, in this regard i was thinking it was a subset of the extractor and pattern matching problem e.g. a theoretical source equivalent of: Point p = ... if (p match Point(x, _, z)) return new Point(z, another_y , x) else throw new Error() > But that's > not MVT either, I think. > Agreed. Paul. > Another thing we have learned about value types is that they don't really have > an method; they have factories. We'll *need* that concept for value types, > and it will turn out to be *useful* for object types. So at some point we'll have > to coin a name that is the factory version of , perhaps something like , > , , , etc. > > Again, none of the above is minimal, unless and except it somehow gets MVT > out the door faster. > > ? John From john.r.rose at oracle.com Mon Jun 26 18:46:18 2017 From: john.r.rose at oracle.com (John Rose) Date: Mon, 26 Jun 2017 11:46:18 -0700 Subject: Unsafe value access In-Reply-To: References: Message-ID: <6C321294-DD1B-4D79-93FF-098C1E0F4A10@oracle.com> On Jun 26, 2017, at 2:05 AM, David Simms wrote: > > Just summarize previous conversations: > > * Small values are "naturally atomic" (e.g. under 8 byte on x86_64), > and the VM should strive to keep them so. > * For payloads over this natural h/w size, instruction latencies for > atomic load/store overheads are an order of magnitude higher than > the actual load/store, the closer to the largest h/w load/store size > you come. > o Therefore the current "default" for VM value type load/store is > currently *not atomic*. > o Even when operations are not atomic, the VM and API built over, > shall make every effort not to "shear" the component primitive > and object reference fields (I.e. field aligned storage). > * VarHandle API is of course free to implement its "AccessMode". > o This will also be a great place to add experiments in evaluating > atomic access costs. > * Future design work of value types may specify atomic access at > call-site or more generally for the type itself. Good summary. I'd only add: * atomicity will probably be necessary to enforce security in some cases (This gives cover for keeping atomicity in the story even though the tradeoffs seem to be wretched.) From john.r.rose at oracle.com Mon Jun 26 19:08:18 2017 From: john.r.rose at oracle.com (John Rose) Date: Mon, 26 Jun 2017 12:08:18 -0700 Subject: ValueType.findConstructor In-Reply-To: <37A6A8E5-9A51-4FE9-B15A-E1247E9D0B9A@oracle.com> References: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> <25181831-0216-4513-8DF7-FC1E3A92E3CB@oracle.com> <37A6A8E5-9A51-4FE9-B15A-E1247E9D0B9A@oracle.com> Message-ID: On Jun 26, 2017, at 11:43 AM, Paul Sandoz wrote: > > Point p = ... > if (p match Point(x, _, z)) > return new Point(z, another_y , x) > else > throw new Error() If you mean to swap z and x in the reconstruction, it's a good example of an ad hoc reconstruction which is more than just a "wither". This makes me think there should be a warning issued by the compiler if you choose a name for a component of a match result which conflicts with the name advertised by the constructor. So "p match Point(z, y, x)" would get a warning on the first and third arguments, if the constructor were "Point(x, y, z)" and Point actually had those names as part of its API. From paul.sandoz at oracle.com Mon Jun 26 21:23:28 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 26 Jun 2017 14:23:28 -0700 Subject: ValueType.findConstructor In-Reply-To: <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> References: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> Message-ID: <5D972EED-CE02-466E-9BCE-46A4DC9EC31B@oracle.com> Updated: http://cr.openjdk.java.net/~psandoz/valhalla/find-constructor/webrev/ Paul. > On 26 Jun 2017, at 10:46, Paul Sandoz wrote: > > Hi Maurizio, > > It?s not naive, that code reflected a reduction on some hacking in an attempt to also explore construction with a default constructor (there is also a disconnect here between the VCC with a constructor and using vdefault with DVT). I think we should keep the constructor method and implement it as you suggest with a combinator. I?ll send out a simplified webrev. > > Separately, in my enthusiasm i may be going down a rabbit hole regarding re-construction, arguably it?s not in the spirit of minimal. Still at some point i think we should explore this notion of a more extensible wither for value types (but it also seems application to ref/data classes too). > > Paul. > >> On 23 Jun 2017, at 16:31, Maurizio Cimadamore wrote: >> >> Maybe a naive question - but do you need method handle builder (and extra bytecode spinning) for constructor? Can't we combine the result of findConstructor on the boxed class with the vunbox MH? >> >> Maurizio From paul.sandoz at oracle.com Mon Jun 26 21:28:19 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 26 Jun 2017 14:28:19 -0700 Subject: ValueType.findConstructor In-Reply-To: References: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> <25181831-0216-4513-8DF7-FC1E3A92E3CB@oracle.com> <37A6A8E5-9A51-4FE9-B15A-E1247E9D0B9A@oracle.com> Message-ID: <1E026D66-11F1-4DCF-AAB0-EFE66CCDCD4F@oracle.com> > On 26 Jun 2017, at 12:08, John Rose wrote: > > On Jun 26, 2017, at 11:43 AM, Paul Sandoz > wrote: >> >> Point p = ... >> if (p match Point(x, _, z)) >> return new Point(z, another_y , x) >> else >> throw new Error() > > If you mean to swap z and x in the reconstruction, > it's a good example of an ad hoc reconstruction which > is more than just a "wither?. Yes, i was combining some argument shuffling and replacement, perhaps the example should of been: Point p = ... if (p match Point(x, _, _)) return new Point(x, another_y , another_z) else throw new Error() Paul. > > This makes me think there should be a warning > issued by the compiler if you choose a name for > a component of a match result which conflicts > with the name advertised by the constructor. > So "p match Point(z, y, x)" would get a warning > on the first and third arguments, if the constructor > were "Point(x, y, z)" and Point actually had those > names as part of its API. > From maurizio.cimadamore at oracle.com Mon Jun 26 23:24:02 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 27 Jun 2017 00:24:02 +0100 Subject: ValueType.findConstructor In-Reply-To: <5D972EED-CE02-466E-9BCE-46A4DC9EC31B@oracle.com> References: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> <5D972EED-CE02-466E-9BCE-46A4DC9EC31B@oracle.com> Message-ID: <80d599f8-12e3-1ed1-6e87-4074e4f1d3c5@oracle.com> Looks good - I noted you have removed the caching - that's probably ok since unbox is cached anyway, but dunno if filterReturnValue is costly (does that go through lambda form editor?) - and whether it would make sense to cache that too. Maurizio On 26/06/17 22:23, Paul Sandoz wrote: > Updated: > > http://cr.openjdk.java.net/~psandoz/valhalla/find-constructor/webrev/ > > > Paul. > >> On 26 Jun 2017, at 10:46, Paul Sandoz > > wrote: >> >> Hi Maurizio, >> >> It?s not naive, that code reflected a reduction on some hacking in an >> attempt to also explore construction with a default constructor >> (there is also a disconnect here between the VCC with a constructor >> and using vdefault with DVT). I think we should keep the constructor >> method and implement it as you suggest with a combinator. I?ll send >> out a simplified webrev. >> >> Separately, in my enthusiasm i may be going down a rabbit hole >> regarding re-construction, arguably it?s not in the spirit of >> minimal. Still at some point i think we should explore this notion of >> a more extensible wither for value types (but it also seems >> application to ref/data classes too). >> >> Paul. >> >>> On 23 Jun 2017, at 16:31, Maurizio Cimadamore >>> >> > wrote: >>> >>> Maybe a naive question - but do you need method handle builder (and >>> extra bytecode spinning) for constructor? Can't we combine the >>> result of findConstructor on the boxed class with the vunbox MH? >>> >>> Maurizio > From tobias.hartmann at oracle.com Tue Jun 27 10:49:42 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Tue, 27 Jun 2017 12:49:42 +0200 Subject: RFR(S): 8182868: [MVT] Crash during call resolution with "fatal error: bad call: invokehandle" Message-ID: <88a4d420-1c1c-735c-c28a-fe94c1c92331@oracle.com> Hi, please review the following patch: https://bugs.openjdk.java.net/browse/JDK-8182868 http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.24/ Problem 1: We crash while resolving an invokehandle call because the code does not expect an attached method for this bytecode. I modified the code to ignore the attached method in this case because we only need it for the GC code in CompiledMethod::preserve_callee_argument_oops() and not for the resolution. Problem 2: We fail with "assert(signature != __null) failed: signature is null" in CompiledMethod::preserve_callee_argument_oops() because the callee takes a value type argument but the adapter does not contain the extended signature. This is because we pass __Value as oop and adapter generation therefore does not save the extended signature. I changed set_arguments_for_java_call() to only attach the method if we really pass the value type as fields and also adjusted the code in preserve_callee_argument_oops() to handle the case where the is no attached callee method. Thanks, Tobias From tobias.hartmann at oracle.com Tue Jun 27 11:00:49 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Tue, 27 Jun 2017 13:00:49 +0200 Subject: RFR(S): 8182995: [MVT] Assert failure "value type should be loaded" Message-ID: <8c2b4f3a-2a57-dada-59ec-d338e9fe9e56@oracle.com> Hi, please review the following patch: https://bugs.openjdk.java.net/browse/JDK-8182995 http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.25/ Problem 1: We crash with an assert while emitting code for loading a value type because ValueTypeNode::is_loaded() does not work with __Value. I changed the implementation together with ciValueKlass.cpp and type.cpp to support the empty __Value value type. Problem 2: We crash with "modified node was not processed by IGVN.transform_old()" because ValueTypeNode::Ideal() may modify the ValueTypeNode but still return NULL. Problem 3: The !is_allocated assert in ValueTypeNode::make() for loading a flattened value type is too strong. If we load a flattened value type from a value type array and the array load goes away during gvn.transform() leaving a load from a non-flattened representation (that was used to initialize that array element), the ValueTypeNode::Ideal() optimization may re-use that oop and the returned value type is indeed allocated. Thanks, Tobias From rwestrel at redhat.com Tue Jun 27 11:02:39 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Tue, 27 Jun 2017 13:02:39 +0200 Subject: RFR(S): 8182868: [MVT] Crash during call resolution with "fatal error: bad call: invokehandle" In-Reply-To: <88a4d420-1c1c-735c-c28a-fe94c1c92331@oracle.com> References: <88a4d420-1c1c-735c-c28a-fe94c1c92331@oracle.com> Message-ID: > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.24/ That looks reasonable to me. Roland. From rwestrel at redhat.com Tue Jun 27 11:04:57 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Tue, 27 Jun 2017 13:04:57 +0200 Subject: RFR(S): 8182995: [MVT] Assert failure "value type should be loaded" In-Reply-To: <8c2b4f3a-2a57-dada-59ec-d338e9fe9e56@oracle.com> References: <8c2b4f3a-2a57-dada-59ec-d338e9fe9e56@oracle.com> Message-ID: > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.25/ Looks reasonable too. Roland. From tobias.hartmann at oracle.com Tue Jun 27 11:05:39 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Tue, 27 Jun 2017 13:05:39 +0200 Subject: RFR(S): 8182995: [MVT] Assert failure "value type should be loaded" In-Reply-To: References: <8c2b4f3a-2a57-dada-59ec-d338e9fe9e56@oracle.com> Message-ID: Thanks for the review, Roland! Best regards, Tobias On 27.06.2017 13:04, Roland Westrelin wrote: > >> http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.25/ > > Looks reasonable too. > > Roland. > From tobias.hartmann at oracle.com Tue Jun 27 11:05:43 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Tue, 27 Jun 2017 13:05:43 +0200 Subject: RFR(S): 8182868: [MVT] Crash during call resolution with "fatal error: bad call: invokehandle" In-Reply-To: References: <88a4d420-1c1c-735c-c28a-fe94c1c92331@oracle.com> Message-ID: <369db81a-7efa-6618-02dc-e4fe47381217@oracle.com> Thanks for the review, Roland! Best regards, Tobias On 27.06.2017 13:02, Roland Westrelin wrote: > >> http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.24/ > > That looks reasonable to me. > > Roland. > From tobias.hartmann at oracle.com Tue Jun 27 11:25:47 2017 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Tue, 27 Jun 2017 11:25:47 +0000 Subject: hg: valhalla/valhalla/hotspot: 2 new changesets Message-ID: <201706271125.v5RBPlTK025371@aojmv0008.oracle.com> Changeset: 1d2c10364440 Author: thartmann Date: 2017-06-27 11:12 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/1d2c10364440 8182868: [MVT] Crash during call resolution with "fatal error: bad call: invokehandle" Reviewed-by: roland ! src/share/vm/code/compiledMethod.cpp ! src/share/vm/opto/graphKit.cpp ! src/share/vm/runtime/sharedRuntime.cpp Changeset: 5ff8426dfa49 Author: thartmann Date: 2017-06-27 12:50 +0200 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/5ff8426dfa49 8182995: [MVT] Assert failure "value type should be loaded" Reviewed-by: roland ! src/share/vm/ci/ciValueKlass.cpp ! src/share/vm/opto/type.cpp ! src/share/vm/opto/valuetypenode.cpp From paul.sandoz at oracle.com Tue Jun 27 14:57:44 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 27 Jun 2017 07:57:44 -0700 Subject: Unsafe value access In-Reply-To: <50293422-8F45-4A16-981E-C29A3A8F48BF@oracle.com> References: <50293422-8F45-4A16-981E-C29A3A8F48BF@oracle.com> Message-ID: Hi Fred, I am running into a crash that i think is related to returning a __Value from a JNI method. Say i have the simplest of methods, an identity function: public native __Value getValueIdentity(__Value o); Implementing that in unsafe.cpp: UNSAFE_ENTRY(jobject, Unsafe_GetValueIdentity(JNIEnv *env, jobject unsafe, jobject jbase)) { return jbase; } UNSAFE_END And calling from Java i get a crash, after calling the call of the Java method but AFAICT before the next Java expression/statement is executed, i think in generated stub code trying to handle the returned value: # Internal Error (/Users/sandoz/Projects/jdk10/valhalla/hotspot/src/share/vm/runtime/mutex.cpp:1384), pid=75592, tid=5123 # assert((!thread->is_Java_thread() || ((JavaThread *)thread)->thread_state() == _thread_in_vm) || rank() == Mutex::special) failed: wrong thread state for using locks ... V [libjvm.dylib+0xc9e274] VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x4d4 V [libjvm.dylib+0xc9ea36] VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x4a V [libjvm.dylib+0x4cc421] report_vm_error(char const*, int, char const*, char const*, ...)+0xcd V [libjvm.dylib+0xa45f8b] Monitor::check_prelock_state(Thread*)+0x67 V [libjvm.dylib+0xa45c39] Monitor::lock(Thread*)+0x97 V [libjvm.dylib+0xbf4b4a] SystemDictionary::add_loader_constraint(Symbol*, Handle, Handle, Thread*)+0x138 V [libjvm.dylib+0xbf4ec0] SystemDictionary::check_signature_loaders(Symbol*, Handle, Handle, bool, Thread*)+0xde V [libjvm.dylib+0x8e45eb] LinkResolver::check_method_loader_constraints(LinkInfo const&, methodHandle const&, char const*, Thread*)+0x283 V [libjvm.dylib+0x8e3c07] LinkResolver::resolve_method(LinkInfo const&, Bytecodes::Code, Thread*)+0x48f V [libjvm.dylib+0x8e3752] LinkResolver::resolve_method_statically(Bytecodes::Code, constantPoolHandle const&, int, Thread*)+0x210 V [libjvm.dylib+0x28ee39] Bytecode_invoke::static_target(Thread*)+0x7b V [libjvm.dylib+0xb666a2] SharedRuntime::store_value_type_fields_to_buf(JavaThread*, long)+0x1b2 v ~RuntimeStub::store_value_type_fields_to_buf j UnsafeTest.main([Ljava/lang/String;)V+40 Any clues to what is going on or how to further debug? Paul. > On 22 Jun 2017, at 12:28, Frederic Parain wrote: > > Paul, > > For the interpreter, the implementation of getfield/putfield for value fields is split > between an assembly template and some runtime methods. > > The assembly template can be found in src/cpu/x86/vm/templateTable_x86.cpp, > look for this method: > > void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc, bool is_vgetfield) > > The runtime support can be found in src/share/vm/interpreter/interpreterRuntime.cpp, > look for methods InterpreterRuntime::qgetfield(JavaThread* thread, oopDesc* value, int offset) > and InterpreterRuntime::qputfield(JavaThread* thread, oopDesc* obj, oopDesc* value, int offset). > > Mr Simms did a number of experiments at the beginning of the project to measure > the cost of the different solutions to provide atomicity, I would recommend to sync > with him. > > Regards, > > Fred > > >> On Jun 22, 2017, at 15:18, Paul Sandoz wrote: >> >> Hi, >> >> To start working on VarHandle integration i first of all need unsafe access to values held within objects. For a most basic initial implementation we can use a global lock to preserve atomicity and memory ordering effects and defer the thinking about more sophisticated locking (seq locks etc), read-mody-write operations and other memory order effects to a another day. >> >> For these purposes we just require two methods: >> >> __Value getValue(Object base, long offset, Class vt) >> >> void putValue(Object base, long offset, Class vt, __Value v); >> >> I included Class parameter for the value type token. >> >> How feasible would it be to implement such methods? >> >> If people point me to the hotspot interpreter code for getfield/putfield implementations for values i might be able to make some progress. Once that is done we could then consider C1/C2 support. >> >> Thoughts? >> >> Thanks, >> Paul. >> >> > From frederic.parain at oracle.com Tue Jun 27 15:36:36 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Tue, 27 Jun 2017 11:36:36 -0400 Subject: Unsafe value access In-Reply-To: References: <50293422-8F45-4A16-981E-C29A3A8F48BF@oracle.com> Message-ID: <343b5484-af52-4940-8760-bf3e3efdc383@oracle.com> Paul, This looks like an issue with the calling convention returning values in registers. The store_value_type_fields_to_buf stub is trying the reconstruct a value types from fields in registers, it calls into the runtime without changing the thread state (which remains _thread_in_Java) and the method in sharedRuntime then tries to lock the SystemDictionary which causes the assertion failure. You can try -XX:-ValueTypeReturnedAsFields to test if this is effectively the return convention that causes the issue. If this is the case, I'd recommend to contact Roland, as the author of the calling/returning convention, he knows all the details of this code. Regards, Fred On 06/27/2017 10:57 AM, Paul Sandoz wrote: > Hi Fred, > > I am running into a crash that i think is related to returning a __Value from a JNI method. > > Say i have the simplest of methods, an identity function: > > public native __Value getValueIdentity(__Value o); > > Implementing that in unsafe.cpp: > > UNSAFE_ENTRY(jobject, Unsafe_GetValueIdentity(JNIEnv *env, jobject unsafe, jobject jbase)) { > return jbase; > } UNSAFE_END > > And calling from Java i get a crash, after calling the call of the Java method but AFAICT before the next Java expression/statement is executed, i think in generated stub code trying to handle the returned value: > > # Internal Error (/Users/sandoz/Projects/jdk10/valhalla/hotspot/src/share/vm/runtime/mutex.cpp:1384), pid=75592, tid=5123 > # assert((!thread->is_Java_thread() || ((JavaThread *)thread)->thread_state() == _thread_in_vm) || rank() == Mutex::special) failed: wrong thread state for using locks > ... > V [libjvm.dylib+0xc9e274] VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x4d4 > V [libjvm.dylib+0xc9ea36] VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x4a > V [libjvm.dylib+0x4cc421] report_vm_error(char const*, int, char const*, char const*, ...)+0xcd > V [libjvm.dylib+0xa45f8b] Monitor::check_prelock_state(Thread*)+0x67 > V [libjvm.dylib+0xa45c39] Monitor::lock(Thread*)+0x97 > V [libjvm.dylib+0xbf4b4a] SystemDictionary::add_loader_constraint(Symbol*, Handle, Handle, Thread*)+0x138 > V [libjvm.dylib+0xbf4ec0] SystemDictionary::check_signature_loaders(Symbol*, Handle, Handle, bool, Thread*)+0xde > V [libjvm.dylib+0x8e45eb] LinkResolver::check_method_loader_constraints(LinkInfo const&, methodHandle const&, char const*, Thread*)+0x283 > V [libjvm.dylib+0x8e3c07] LinkResolver::resolve_method(LinkInfo const&, Bytecodes::Code, Thread*)+0x48f > V [libjvm.dylib+0x8e3752] LinkResolver::resolve_method_statically(Bytecodes::Code, constantPoolHandle const&, int, Thread*)+0x210 > V [libjvm.dylib+0x28ee39] Bytecode_invoke::static_target(Thread*)+0x7b > V [libjvm.dylib+0xb666a2] SharedRuntime::store_value_type_fields_to_buf(JavaThread*, long)+0x1b2 > v ~RuntimeStub::store_value_type_fields_to_buf > j UnsafeTest.main([Ljava/lang/String;)V+40 > > Any clues to what is going on or how to further debug? > > Paul. > >> On 22 Jun 2017, at 12:28, Frederic Parain wrote: >> >> Paul, >> >> For the interpreter, the implementation of getfield/putfield for value fields is split >> between an assembly template and some runtime methods. >> >> The assembly template can be found in src/cpu/x86/vm/templateTable_x86.cpp, >> look for this method: >> >> void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc, bool is_vgetfield) >> >> The runtime support can be found in src/share/vm/interpreter/interpreterRuntime.cpp, >> look for methods InterpreterRuntime::qgetfield(JavaThread* thread, oopDesc* value, int offset) >> and InterpreterRuntime::qputfield(JavaThread* thread, oopDesc* obj, oopDesc* value, int offset). >> >> Mr Simms did a number of experiments at the beginning of the project to measure >> the cost of the different solutions to provide atomicity, I would recommend to sync >> with him. >> >> Regards, >> >> Fred >> >> >>> On Jun 22, 2017, at 15:18, Paul Sandoz wrote: >>> >>> Hi, >>> >>> To start working on VarHandle integration i first of all need unsafe access to values held within objects. For a most basic initial implementation we can use a global lock to preserve atomicity and memory ordering effects and defer the thinking about more sophisticated locking (seq locks etc), read-mody-write operations and other memory order effects to a another day. >>> >>> For these purposes we just require two methods: >>> >>> __Value getValue(Object base, long offset, Class vt) >>> >>> void putValue(Object base, long offset, Class vt, __Value v); >>> >>> I included Class parameter for the value type token. >>> >>> How feasible would it be to implement such methods? >>> >>> If people point me to the hotspot interpreter code for getfield/putfield implementations for values i might be able to make some progress. Once that is done we could then consider C1/C2 support. >>> >>> Thoughts? >>> >>> Thanks, >>> Paul. >>> >>> >> > From paul.sandoz at oracle.com Tue Jun 27 16:47:23 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 27 Jun 2017 09:47:23 -0700 Subject: Unsafe value access In-Reply-To: <343b5484-af52-4940-8760-bf3e3efdc383@oracle.com> References: <50293422-8F45-4A16-981E-C29A3A8F48BF@oracle.com> <343b5484-af52-4940-8760-bf3e3efdc383@oracle.com> Message-ID: Thanks, Ah ValueTypeReturnedAsFields is enabled by default! i was playing around with that. Roland, if you need a test case i can send you something. Using -XX:-ValueTypeReturnedAsFields got me further, i have this for Unsafe.getValue: UNSAFE_ENTRY(jobject, Unsafe_GetValue(JNIEnv *env, jobject unsafe, jobject jbase, jlong offset)) { oop base = JNIHandles::resolve(jbase); Handle base_h(THREAD, base); // is this necessary? InstanceKlass* base_klass = InstanceKlass::cast(base->klass()); fieldDescriptor fd; base_klass->find_field_from_offset(offset, false, &fd); Klass* field_k = base_klass->get_value_field_klass(fd.index()); ValueKlass* field_vklass = ValueKlass::cast(field_k); // allocate instance instanceOop res = field_vklass->allocate_instance(CHECK_NULL); // copy value int size = field_vklass->layout_helper_size_in_bytes(field_vklass->layout_helper()); // redundant? field_vklass->value_store( ((char*)(oopDesc*)base_h()) + offset, // offset in memory from base to the exploded value components ((char*)(oopDesc*)res) + field_vklass->first_field_offset(), true, false); ((instanceOopDesc*)res)->print(); return JNIHandles::make_local(env, res); } UNSAFE_END The print verifies the value is being copied in the instanceOop ?buffer". But the value returned in Java is null. Same applies for the identity function i showed previously. Paul. P.S. do you use lldb on a mac, if so how does not enable the debugger to get access to the HS sources. Perhaps i need to enable a full debug build? > On 27 Jun 2017, at 08:36, Frederic Parain wrote: > > Paul, > > This looks like an issue with the calling convention returning values > in registers. The store_value_type_fields_to_buf stub is trying the > reconstruct a value types from fields in registers, it calls into > the runtime without changing the thread state (which remains > _thread_in_Java) and the method in sharedRuntime then tries to > lock the SystemDictionary which causes the assertion failure. > > You can try -XX:-ValueTypeReturnedAsFields to test if this is > effectively the return convention that causes the issue. > > If this is the case, I'd recommend to contact Roland, as the > author of the calling/returning convention, he knows all the > details of this code. > > Regards, > > Fred > > On 06/27/2017 10:57 AM, Paul Sandoz wrote: >> Hi Fred, >> I am running into a crash that i think is related to returning a __Value from a JNI method. >> Say i have the simplest of methods, an identity function: >> public native __Value getValueIdentity(__Value o); >> Implementing that in unsafe.cpp: >> UNSAFE_ENTRY(jobject, Unsafe_GetValueIdentity(JNIEnv *env, jobject unsafe, jobject jbase)) { >> return jbase; >> } UNSAFE_END >> And calling from Java i get a crash, after calling the call of the Java method but AFAICT before the next Java expression/statement is executed, i think in generated stub code trying to handle the returned value: >> # Internal Error (/Users/sandoz/Projects/jdk10/valhalla/hotspot/src/share/vm/runtime/mutex.cpp:1384), pid=75592, tid=5123 >> # assert((!thread->is_Java_thread() || ((JavaThread *)thread)->thread_state() == _thread_in_vm) || rank() == Mutex::special) failed: wrong thread state for using locks >> ... >> V [libjvm.dylib+0xc9e274] VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x4d4 >> V [libjvm.dylib+0xc9ea36] VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x4a >> V [libjvm.dylib+0x4cc421] report_vm_error(char const*, int, char const*, char const*, ...)+0xcd >> V [libjvm.dylib+0xa45f8b] Monitor::check_prelock_state(Thread*)+0x67 >> V [libjvm.dylib+0xa45c39] Monitor::lock(Thread*)+0x97 >> V [libjvm.dylib+0xbf4b4a] SystemDictionary::add_loader_constraint(Symbol*, Handle, Handle, Thread*)+0x138 >> V [libjvm.dylib+0xbf4ec0] SystemDictionary::check_signature_loaders(Symbol*, Handle, Handle, bool, Thread*)+0xde >> V [libjvm.dylib+0x8e45eb] LinkResolver::check_method_loader_constraints(LinkInfo const&, methodHandle const&, char const*, Thread*)+0x283 >> V [libjvm.dylib+0x8e3c07] LinkResolver::resolve_method(LinkInfo const&, Bytecodes::Code, Thread*)+0x48f >> V [libjvm.dylib+0x8e3752] LinkResolver::resolve_method_statically(Bytecodes::Code, constantPoolHandle const&, int, Thread*)+0x210 >> V [libjvm.dylib+0x28ee39] Bytecode_invoke::static_target(Thread*)+0x7b >> V [libjvm.dylib+0xb666a2] SharedRuntime::store_value_type_fields_to_buf(JavaThread*, long)+0x1b2 >> v ~RuntimeStub::store_value_type_fields_to_buf >> j UnsafeTest.main([Ljava/lang/String;)V+40 >> Any clues to what is going on or how to further debug? >> Paul. >>> On 22 Jun 2017, at 12:28, Frederic Parain wrote: >>> >>> Paul, >>> >>> For the interpreter, the implementation of getfield/putfield for value fields is split >>> between an assembly template and some runtime methods. >>> >>> The assembly template can be found in src/cpu/x86/vm/templateTable_x86.cpp, >>> look for this method: >>> >>> void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc, bool is_vgetfield) >>> >>> The runtime support can be found in src/share/vm/interpreter/interpreterRuntime.cpp, >>> look for methods InterpreterRuntime::qgetfield(JavaThread* thread, oopDesc* value, int offset) >>> and InterpreterRuntime::qputfield(JavaThread* thread, oopDesc* obj, oopDesc* value, int offset). >>> >>> Mr Simms did a number of experiments at the beginning of the project to measure >>> the cost of the different solutions to provide atomicity, I would recommend to sync >>> with him. >>> >>> Regards, >>> >>> Fred >>> >>> >>>> On Jun 22, 2017, at 15:18, Paul Sandoz wrote: >>>> >>>> Hi, >>>> >>>> To start working on VarHandle integration i first of all need unsafe access to values held within objects. For a most basic initial implementation we can use a global lock to preserve atomicity and memory ordering effects and defer the thinking about more sophisticated locking (seq locks etc), read-mody-write operations and other memory order effects to a another day. >>>> >>>> For these purposes we just require two methods: >>>> >>>> __Value getValue(Object base, long offset, Class vt) >>>> >>>> void putValue(Object base, long offset, Class vt, __Value v); >>>> >>>> I included Class parameter for the value type token. >>>> >>>> How feasible would it be to implement such methods? >>>> >>>> If people point me to the hotspot interpreter code for getfield/putfield implementations for values i might be able to make some progress. Once that is done we could then consider C1/C2 support. >>>> >>>> Thoughts? >>>> >>>> Thanks, >>>> Paul. >>>> >>>> >>> From paul.sandoz at oracle.com Tue Jun 27 23:30:30 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 27 Jun 2017 16:30:30 -0700 Subject: ValueType.findConstructor In-Reply-To: <80d599f8-12e3-1ed1-6e87-4074e4f1d3c5@oracle.com> References: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> <5D972EED-CE02-466E-9BCE-46A4DC9EC31B@oracle.com> <80d599f8-12e3-1ed1-6e87-4074e4f1d3c5@oracle.com> Message-ID: <2694A0FE-0FE6-498C-8290-2C062DCC43F0@oracle.com> > On 26 Jun 2017, at 16:24, Maurizio Cimadamore wrote: > > Looks good - I noted you have removed the caching - that's probably ok since unbox is cached anyway, but dunno if filterReturnValue is costly (does that go through lambda form editor?) - and whether it would make sense to cache that too. > > I did some checking. It looks ok, the filterReturnValue does go through the editor, and two method handles such as say: MethodHandle mh1 = VT_Interval.findConstructor(MethodHandles.lookup(), MethodType.methodType(void.class, int.class, int.class)); MethodHandle mh2 = VT_Interval.findConstructor(MethodHandles.lookup(), MethodType.methodType(void.class, int.class, int.class)); will share the same lambda form even though the MH instances are different. Paul. From maurizio.cimadamore at oracle.com Tue Jun 27 23:34:19 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 28 Jun 2017 00:34:19 +0100 Subject: ValueType.findConstructor In-Reply-To: <2694A0FE-0FE6-498C-8290-2C062DCC43F0@oracle.com> References: <5e32bb7c-89dc-3d82-7820-4bb64df25dfe@oracle.com> <12D5718E-74C7-44B7-8140-1166D53D5562@oracle.com> <5D972EED-CE02-466E-9BCE-46A4DC9EC31B@oracle.com> <80d599f8-12e3-1ed1-6e87-4074e4f1d3c5@oracle.com> <2694A0FE-0FE6-498C-8290-2C062DCC43F0@oracle.com> Message-ID: <5bac4c7f-8769-1e45-02f3-17bfa0b4aa5b@oracle.com> OK - approved! Thanks for checking. Maurizio On 28/06/17 00:30, Paul Sandoz wrote: >> On 26 Jun 2017, at 16:24, Maurizio Cimadamore wrote: >> >> Looks good - I noted you have removed the caching - that's probably ok since unbox is cached anyway, but dunno if filterReturnValue is costly (does that go through lambda form editor?) - and whether it would make sense to cache that too. >> >> > I did some checking. It looks ok, the filterReturnValue does go through the editor, and two method handles such as say: > > MethodHandle mh1 = VT_Interval.findConstructor(MethodHandles.lookup(), > MethodType.methodType(void.class, int.class, int.class)); > > MethodHandle mh2 = VT_Interval.findConstructor(MethodHandles.lookup(), > MethodType.methodType(void.class, int.class, int.class)); > > will share the same lambda form even though the MH instances are different. > > Paul. > From mandy.chung at oracle.com Wed Jun 28 08:40:44 2017 From: mandy.chung at oracle.com (mandy.chung at oracle.com) Date: Wed, 28 Jun 2017 08:40:44 +0000 Subject: hg: valhalla/valhalla/jdk: Class::isValueClass tests if a subclass of __Value to resolve test regression Message-ID: <201706280840.v5S8eigr015027@aojmv0008.oracle.com> Changeset: 70a69cb96df6 Author: mchung Date: 2017-06-28 16:38 +0800 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/70a69cb96df6 Class::isValueClass tests if a subclass of __Value to resolve test regression ! src/java.base/share/classes/java/lang/Class.java From mandy.chung at oracle.com Wed Jun 28 08:40:53 2017 From: mandy.chung at oracle.com (mandy.chung at oracle.com) Date: Wed, 28 Jun 2017 08:40:53 +0000 Subject: hg: valhalla/valhalla/hotspot: Class::isValueClass tests if a subclass of __Value to resolve test regression Message-ID: <201706280840.v5S8er9n015178@aojmv0008.oracle.com> Changeset: 641b106d1560 Author: mchung Date: 2017-06-28 16:38 +0800 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/641b106d1560 Class::isValueClass tests if a subclass of __Value to resolve test regression ! test/runtime/valhalla/valuetypes/DeriveValueTypeCreation.java ! test/runtime/valhalla/valuetypes/MVTComboTier1.java ! test/runtime/valhalla/valuetypes/ValueOops.java ! test/runtime/valhalla/valuetypes/VboxUnbox.java From vladimir.x.ivanov at oracle.com Wed Jun 28 13:17:01 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 28 Jun 2017 16:17:01 +0300 Subject: MVT-based vectors: first stab Message-ID: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> Hi, I started playing with MVT-based vectors recently and want to share my experience so far. For the first step, I decided to avoid specific treatment of super-longs (Long2/4/8) in the JVM we have in Panama and just mark them as VCCs for now: @DeriveValueType final class Long2 { public final long lo, hi; } As a test case I chose sum of array elements: long sum(QLong2[] va) { QLong2 v = QLong2.default; // (0,0) for (int i = 0; i < va.length; i++) { QLong2 vi = va[i]; v = QLong2(v.lo + vi.lo, v.hi + vi.hi); } return v.lo + v.hi; } Here are the changes: http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/ SUMMARY & RESULTS I hit some bugs along the way and had to extend the code for Q-types in some places to get decent code shape generated. (I'll shepherd the fixes in the repo separately.) I ended up with the following generated code: http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log Unfortunately, there are still 2 allocations left in the generated code (out of 5 initially). C2 can't scalarize the accumulator (v) inside the loop and has to put updated components (lo & hi) in allocated heap buffer on every iteration over the array (generated code [1], C2 EA output [2]). GORY DETAILS hotspot/src/share/vm/opto/type.cpp * Type::get_typeflow_type() doesn't distinguish between TypeValueTypePtr & TypeValueType jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java * introduced some LF intrinsics, e.g. LOOP and SELECT_ALTERNATIVE; * had to workaround control flow-related bugs in the bytecode library (jdk.experimental.bytecode): broken JVM state after goto_() (see FIXME marks in the code); * fixed 2-slot types support: wrong local indexes were used jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java * MHI.unboxResultHandle misses unboxing step for Q-types jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java * had to add a specialization for arraylength on Q-typed array, because C2 can't handle arraylength Object[] when Q[] instance is on stack; jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: * changes required to workaround goto_() bug * fixed CP patching support jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java * fixed CP patching support hotspot/src/share/vm/memory/metachunk.hpp hotspot/src/share/vm/oops/method.hpp Fix optimized JVM build. Best regards, Vladimir Ivanov [1] http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log ;; B7: # B8 <- B9 top-of-loop mov %r9,0x10(%rsp) mov 0x8(%rsp),%r11d ;; B8: # B16 B9 <- B6 B7 Loop: B8-B7 inner mov %r11d,0x8(%rsp) movabs $0x7c0060420,%rsi ; {metadata('valhalla/vector/Long2$Value')} ... callq 0x0000000117579820 ; {runtime_call _new_instance_Java} ;; B9: # B7 B10 <- B8 mov %rax,%r9 mov 0x10(%rsp),%r11 mov 0x10(%r11),%r10 mov 0x18(%r11),%r11 movslq %ebp,%r8 shl $0x4,%r8 mov (%rsp),%rcx mov 0x18(%rcx,%r8,1),%rax mov 0x10(%rcx,%r8,1),%r8 ;*vaload add %r11,%rax ;*ladd mov %rax,0x18(%r9) add %r10,%r8 ;*ladd mov %r8,0x10(%r9) inc %ebp ;*iadd cmp 0x8(%rsp),%ebp jl ;*if_icmpge [2] Pruned EA output (full output in the log) ======== Connection graph for valhalla.vector.VectorTest::sumArrayL2 JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F 1579F [ 1259 1264 532 1525 ]] 1247 Allocate LocalVar [ 1247P [ 1264 ]] 1259 Proj ... #5 LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]] 1264 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]] 1136 Allocate LocalVar [ 1136P [ 1153 ]] 1148 Proj ... #5 LocalVar [ 1148 1136P [ 1154b ]] 1153 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull JavaObject NoEscape(NoEscape) [ [ 1053 ]] 1041 Allocate LocalVar [ 1041P [ ]] 1053 Proj ... #5 JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]] 633 Allocate LocalVar [ 633P [ 650 ]] 645 Proj ... #5 LocalVar [ 645 633P [ 653b 651b ]] 650 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 324 532 1525 ]] 307 Allocate LocalVar [ 307P [ 324 ]] 319 Proj ... #5 LocalVar [ 319 307P [ 532 1525 ]] 324 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull Scalar 1153 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull ++++ Eliminated: 1136 Allocate Scalar 1041 Allocate ... ++++ Eliminated: 1041 Allocate Scalar 650 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull ++++ Eliminated: 633 Allocate From tobias.hartmann at oracle.com Wed Jun 28 13:35:46 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Wed, 28 Jun 2017 15:35:46 +0200 Subject: MVT-based vectors: first stab In-Reply-To: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> Message-ID: Hi Vladimir, thanks a lot for the nice summary! I think it would makes sense to file enhancements/bugs for the individual issues. On 28.06.2017 15:17, Vladimir Ivanov wrote: > I hit some bugs along the way I had a closer look and (as you already figured out) one problem is that typeflow analysis incorrectly sets the type of a PhiNode to TypeValueType instead of TypeValueTypePtr for __Value. When inlining a method handle intrinsic in CallGenerator::for_method_handle_inline() we should cast all arguments to their actual types but we miss the PhiNode because it's already of TypeValueType: t: arg_type: valuetype[0]:{empty} sig_type: valuetype* valhalla/vector/Long2$Value:NotNull arg: 659 Phi === 652 _ 626 [[ 616 662 678 680 684 730 760 785 790 793 837 867 874 889 891 894 ]] #valuetype[0]:{empty} !jvms: 1310540333::invoke @ bci:170 858242339::invokeExact_MT @ bci:19 VectorTest::acc @ bci:4 VectorTest::main @ bci:69 We then fail in Parse::do_vunbox because the input node is a Phi (and not a ValueTypeNode). I think in addition to the fix in type.cpp, we should add this assert to catch such problems in the future: --- old/src/share/vm/opto/callGenerator.cpp 2017-06-28 15:25:40.812039870 +0200 +++ new/src/share/vm/opto/callGenerator.cpp 2017-06-28 15:25:40.720039875 +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)) { I'll take the chance to look at the method handle implementation in a bit more detail and try to come up with a regression test for this to extend our ValueTypesTestBench. Best regards, Tobias From maurizio.cimadamore at oracle.com Wed Jun 28 14:08:13 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 28 Jun 2017 15:08:13 +0100 Subject: MVT-based vectors: first stab In-Reply-To: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> Message-ID: <9f97d3e7-6ee9-2438-cbc9-747d185eb685@oracle.com> Great work Vlad; I have two questions before I dive in more details * why did you need to handle arrayLength() specially? Since an array is a reference, shouldn't it work already? * Can you explain me exactly what you were trying to achieve with state.push/state.pop in the intrinsic generation? Typically the state is updated through opcodes - so, assuming you are generating bytecodes that make sense, you should not need this - unless there are bugs in the code builder (which is possible!) Maurizio On 28/06/17 14:17, Vladimir Ivanov wrote: > Hi, > > I started playing with MVT-based vectors recently and want to share my > experience so far. > > For the first step, I decided to avoid specific treatment of > super-longs (Long2/4/8) in the JVM we have in Panama and just mark > them as VCCs for now: > @DeriveValueType > final class Long2 { public final long lo, hi; } > > As a test case I chose sum of array elements: > > long sum(QLong2[] va) { > QLong2 v = QLong2.default; // (0,0) > for (int i = 0; i < va.length; i++) { > QLong2 vi = va[i]; > v = QLong2(v.lo + vi.lo, v.hi + vi.hi); > } > return v.lo + v.hi; > } > > Here are the changes: > http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/ > > SUMMARY & RESULTS > > I hit some bugs along the way and had to extend the code for Q-types > in some places to get decent code shape generated. (I'll shepherd the > fixes in the repo separately.) I ended up with the following generated > code: > > http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log > > Unfortunately, there are still 2 allocations left in the generated > code (out of 5 initially). C2 can't scalarize the accumulator (v) > inside the loop and has to put updated components (lo & hi) in > allocated heap buffer on every iteration over the array (generated > code [1], C2 EA output [2]). > > > GORY DETAILS > > hotspot/src/share/vm/opto/type.cpp > > * Type::get_typeflow_type() doesn't distinguish between > TypeValueTypePtr & TypeValueType > > > jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java > > * introduced some LF intrinsics, e.g. LOOP and SELECT_ALTERNATIVE; > > * had to workaround control flow-related bugs in the bytecode > library (jdk.experimental.bytecode): broken JVM state after goto_() > (see FIXME marks in the code); > > * fixed 2-slot types support: wrong local indexes were used > > > > jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java > > * MHI.unboxResultHandle misses unboxing step for Q-types > > > jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java > jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java > > * had to add a specialization for arraylength on Q-typed array, > because C2 can't handle arraylength Object[] when Q[] instance is on > stack; > > > jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: > > > * changes required to workaround goto_() bug > > * fixed CP patching support > > > jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java > > > * fixed CP patching support > > > hotspot/src/share/vm/memory/metachunk.hpp > hotspot/src/share/vm/oops/method.hpp > Fix optimized JVM build. > > Best regards, > Vladimir Ivanov > > [1] > http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log > > ;; B7: # B8 <- B9 top-of-loop > > mov %r9,0x10(%rsp) > mov 0x8(%rsp),%r11d > > ;; B8: # B16 B9 <- B6 B7 Loop: B8-B7 inner > > mov %r11d,0x8(%rsp) > movabs $0x7c0060420,%rsi ; {metadata('valhalla/vector/Long2$Value')} > ... > callq 0x0000000117579820 ; {runtime_call _new_instance_Java} > > ;; B9: # B7 B10 <- B8 > > mov %rax,%r9 > mov 0x10(%rsp),%r11 > mov 0x10(%r11),%r10 > mov 0x18(%r11),%r11 > movslq %ebp,%r8 > shl $0x4,%r8 > mov (%rsp),%rcx > mov 0x18(%rcx,%r8,1),%rax > mov 0x10(%rcx,%r8,1),%r8 ;*vaload > add %r11,%rax ;*ladd > mov %rax,0x18(%r9) > add %r10,%r8 ;*ladd > mov %r8,0x10(%r9) > inc %ebp ;*iadd > cmp 0x8(%rsp),%ebp > jl ;*if_icmpge > > [2] Pruned EA output (full output in the log) > ======== Connection graph for valhalla.vector.VectorTest::sumArrayL2 > JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F 1579F > [ 1259 1264 532 1525 ]] 1247 Allocate > LocalVar [ 1247P [ 1264 ]] 1259 Proj ... #5 > LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]] 1264 CheckCastPP ... > #valuetype* valhalla/vector/Long2$Value:NotNull > LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... > #valuetype* valhalla/vector/Long2$Value:NotNull > LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... > #valuetype* valhalla/vector/Long2$Value:NotNull > > JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]] 1136 Allocate > LocalVar [ 1136P [ 1153 ]] 1148 Proj ... #5 > LocalVar [ 1148 1136P [ 1154b ]] 1153 CheckCastPP ... #valuetype* > valhalla/vector/Long2$Value:NotNull > > JavaObject NoEscape(NoEscape) [ [ 1053 ]] 1041 Allocate > LocalVar [ 1041P [ ]] 1053 Proj ... #5 > > JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]] 633 Allocate > LocalVar [ 633P [ 650 ]] 645 Proj ... #5 > LocalVar [ 645 633P [ 653b 651b ]] 650 CheckCastPP ... > #valuetype* valhalla/vector/Long2$Value:NotNull > > JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 324 > 532 1525 ]] 307 Allocate > LocalVar [ 307P [ 324 ]] 319 Proj ... #5 > LocalVar [ 319 307P [ 532 1525 ]] 324 CheckCastPP ... > #valuetype* valhalla/vector/Long2$Value:NotNull > LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... > #valuetype* valhalla/vector/Long2$Value:NotNull > LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... > #valuetype* valhalla/vector/Long2$Value:NotNull > > Scalar 1153 CheckCastPP ... #valuetype* > valhalla/vector/Long2$Value:NotNull > ++++ Eliminated: 1136 Allocate > Scalar 1041 Allocate ... > ++++ Eliminated: 1041 Allocate > Scalar 650 CheckCastPP ... #valuetype* > valhalla/vector/Long2$Value:NotNull > ++++ Eliminated: 633 Allocate From vladimir.x.ivanov at oracle.com Wed Jun 28 14:36:45 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 28 Jun 2017 17:36:45 +0300 Subject: MVT-based vectors: first stab In-Reply-To: <9f97d3e7-6ee9-2438-cbc9-747d185eb685@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> <9f97d3e7-6ee9-2438-cbc9-747d185eb685@oracle.com> Message-ID: <44ed7e9d-41df-7a1f-1f2b-2ed69535579e@oracle.com> On 6/28/17 5:08 PM, Maurizio Cimadamore wrote: > Great work Vlad; I have two questions before I dive in more details > > * why did you need to handle arrayLength() specially? Since an array is > a reference, shouldn't it work already? It's a workaround for C2 crashes I observed when working with arraylength method handle on Q-typed arrays. The problem for the compiler is that the implementation uses ArrayAccessor.lengthL(Object[]), so on bytecode level there's a conflict between declared & actual type (DVT[] doesn't extend Object[]). IMO the proper fix would be to have "erased" version for such cases (or replace all primitive array specializations with a single "erased" version): static int lengthL(java.lang.Object); 0: aload_0 1: arraylength 2: ireturn But it can't be expressed in Java language and requires bytecode generation. > * Can you explain me exactly what you were trying to achieve with > state.push/state.pop in the intrinsic generation? Typically the state is > updated through opcodes - so, assuming you are generating bytecodes that > make sense, you should not need this - unless there are bugs in the code > builder (which is possible!) The following sequence usually hits the bug in the code builder: builder.goto_("l1"); builder.label("l2"); goto_() doesn't wipe the state, but the state at l2 doesn't relate to the state when jumping to l1. It usually manifests as stack depth or type mismatches when trying to merge the states in builder.label(). Best regards, Vladimir Ivanov > On 28/06/17 14:17, Vladimir Ivanov wrote: >> Hi, >> >> I started playing with MVT-based vectors recently and want to share my >> experience so far. >> >> For the first step, I decided to avoid specific treatment of >> super-longs (Long2/4/8) in the JVM we have in Panama and just mark >> them as VCCs for now: >> @DeriveValueType >> final class Long2 { public final long lo, hi; } >> >> As a test case I chose sum of array elements: >> >> long sum(QLong2[] va) { >> QLong2 v = QLong2.default; // (0,0) >> for (int i = 0; i < va.length; i++) { >> QLong2 vi = va[i]; >> v = QLong2(v.lo + vi.lo, v.hi + vi.hi); >> } >> return v.lo + v.hi; >> } >> >> Here are the changes: >> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/ >> >> SUMMARY & RESULTS >> >> I hit some bugs along the way and had to extend the code for Q-types >> in some places to get decent code shape generated. (I'll shepherd the >> fixes in the repo separately.) I ended up with the following generated >> code: >> >> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >> >> Unfortunately, there are still 2 allocations left in the generated >> code (out of 5 initially). C2 can't scalarize the accumulator (v) >> inside the loop and has to put updated components (lo & hi) in >> allocated heap buffer on every iteration over the array (generated >> code [1], C2 EA output [2]). >> >> >> GORY DETAILS >> >> hotspot/src/share/vm/opto/type.cpp >> >> * Type::get_typeflow_type() doesn't distinguish between >> TypeValueTypePtr & TypeValueType >> >> >> jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >> >> * introduced some LF intrinsics, e.g. LOOP and SELECT_ALTERNATIVE; >> >> * had to workaround control flow-related bugs in the bytecode >> library (jdk.experimental.bytecode): broken JVM state after goto_() >> (see FIXME marks in the code); >> >> * fixed 2-slot types support: wrong local indexes were used >> >> >> >> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java >> >> * MHI.unboxResultHandle misses unboxing step for Q-types >> >> >> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java >> jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java >> >> * had to add a specialization for arraylength on Q-typed array, >> because C2 can't handle arraylength Object[] when Q[] instance is on >> stack; >> >> >> jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: >> >> >> * changes required to workaround goto_() bug >> >> * fixed CP patching support >> >> >> jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >> >> >> * fixed CP patching support >> >> >> hotspot/src/share/vm/memory/metachunk.hpp >> hotspot/src/share/vm/oops/method.hpp >> Fix optimized JVM build. >> >> Best regards, >> Vladimir Ivanov >> >> [1] >> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >> >> ;; B7: # B8 <- B9 top-of-loop >> >> mov %r9,0x10(%rsp) >> mov 0x8(%rsp),%r11d >> >> ;; B8: # B16 B9 <- B6 B7 Loop: B8-B7 inner >> >> mov %r11d,0x8(%rsp) >> movabs $0x7c0060420,%rsi ; {metadata('valhalla/vector/Long2$Value')} >> ... >> callq 0x0000000117579820 ; {runtime_call _new_instance_Java} >> >> ;; B9: # B7 B10 <- B8 >> >> mov %rax,%r9 >> mov 0x10(%rsp),%r11 >> mov 0x10(%r11),%r10 >> mov 0x18(%r11),%r11 >> movslq %ebp,%r8 >> shl $0x4,%r8 >> mov (%rsp),%rcx >> mov 0x18(%rcx,%r8,1),%rax >> mov 0x10(%rcx,%r8,1),%r8 ;*vaload >> add %r11,%rax ;*ladd >> mov %rax,0x18(%r9) >> add %r10,%r8 ;*ladd >> mov %r8,0x10(%r9) >> inc %ebp ;*iadd >> cmp 0x8(%rsp),%ebp >> jl ;*if_icmpge >> >> [2] Pruned EA output (full output in the log) >> ======== Connection graph for valhalla.vector.VectorTest::sumArrayL2 >> JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F 1579F >> [ 1259 1264 532 1525 ]] 1247 Allocate >> LocalVar [ 1247P [ 1264 ]] 1259 Proj ... #5 >> LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]] 1264 CheckCastPP ... >> #valuetype* valhalla/vector/Long2$Value:NotNull >> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >> #valuetype* valhalla/vector/Long2$Value:NotNull >> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >> #valuetype* valhalla/vector/Long2$Value:NotNull >> >> JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]] 1136 Allocate >> LocalVar [ 1136P [ 1153 ]] 1148 Proj ... #5 >> LocalVar [ 1148 1136P [ 1154b ]] 1153 CheckCastPP ... #valuetype* >> valhalla/vector/Long2$Value:NotNull >> >> JavaObject NoEscape(NoEscape) [ [ 1053 ]] 1041 Allocate >> LocalVar [ 1041P [ ]] 1053 Proj ... #5 >> >> JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]] 633 Allocate >> LocalVar [ 633P [ 650 ]] 645 Proj ... #5 >> LocalVar [ 645 633P [ 653b 651b ]] 650 CheckCastPP ... >> #valuetype* valhalla/vector/Long2$Value:NotNull >> >> JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 324 >> 532 1525 ]] 307 Allocate >> LocalVar [ 307P [ 324 ]] 319 Proj ... #5 >> LocalVar [ 319 307P [ 532 1525 ]] 324 CheckCastPP ... >> #valuetype* valhalla/vector/Long2$Value:NotNull >> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >> #valuetype* valhalla/vector/Long2$Value:NotNull >> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >> #valuetype* valhalla/vector/Long2$Value:NotNull >> >> Scalar 1153 CheckCastPP ... #valuetype* >> valhalla/vector/Long2$Value:NotNull >> ++++ Eliminated: 1136 Allocate >> Scalar 1041 Allocate ... >> ++++ Eliminated: 1041 Allocate >> Scalar 650 CheckCastPP ... #valuetype* >> valhalla/vector/Long2$Value:NotNull >> ++++ Eliminated: 633 Allocate > From vladimir.x.ivanov at oracle.com Wed Jun 28 14:40:09 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 28 Jun 2017 17:40:09 +0300 Subject: MVT-based vectors: first stab In-Reply-To: References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> Message-ID: <0b5cac76-fa12-bc8b-b674-4e1cce18350b@oracle.com> > thanks a lot for the nice summary! I think it would makes sense to file enhancements/bugs for the individual issues. Sure, I'll take care of that. >> I hit some bugs along the way > > I had a closer look and (as you already figured out) one problem is that typeflow analysis incorrectly sets the type of a PhiNode to TypeValueType instead of TypeValueTypePtr for __Value. When inlining a method handle intrinsic in CallGenerator::for_method_handle_inline() we should cast all arguments to their actual types but we miss the PhiNode because it's already of TypeValueType: > > t: > arg_type: valuetype[0]:{empty} > sig_type: valuetype* valhalla/vector/Long2$Value:NotNull > arg: 659 Phi === 652 _ 626 [[ 616 662 678 680 684 730 760 785 790 793 837 867 874 889 891 894 ]] #valuetype[0]:{empty} !jvms: 1310540333::invoke @ bci:170 858242339::invokeExact_MT @ bci:19 VectorTest::acc @ bci:4 VectorTest::main @ bci:69 > > We then fail in Parse::do_vunbox because the input node is a Phi (and not a ValueTypeNode). > > I think in addition to the fix in type.cpp, we should add this assert to catch such problems in the future: Looks reasonable. > > --- old/src/share/vm/opto/callGenerator.cpp 2017-06-28 15:25:40.812039870 +0200 > +++ new/src/share/vm/opto/callGenerator.cpp 2017-06-28 15:25:40.720039875 +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)) { > > I'll take the chance to look at the method handle implementation in a bit more detail and try to come up with a regression test for this to extend our ValueTypesTestBench. Thanks! Best regards, Vladimir Ivanov From maurizio.cimadamore at oracle.com Wed Jun 28 15:00:31 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 28 Jun 2017 16:00:31 +0100 Subject: MVT-based vectors: first stab In-Reply-To: <44ed7e9d-41df-7a1f-1f2b-2ed69535579e@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> <9f97d3e7-6ee9-2438-cbc9-747d185eb685@oracle.com> <44ed7e9d-41df-7a1f-1f2b-2ed69535579e@oracle.com> Message-ID: <06886e2d-ae0e-5e5a-7b89-1e86c0d44b72@oracle.com> On 28/06/17 15:36, Vladimir Ivanov wrote: > > > On 6/28/17 5:08 PM, Maurizio Cimadamore wrote: >> Great work Vlad; I have two questions before I dive in more details >> >> * why did you need to handle arrayLength() specially? Since an array >> is a reference, shouldn't it work already? > > It's a workaround for C2 crashes I observed when working with > arraylength method handle on Q-typed arrays. The problem for the > compiler is that the implementation uses > ArrayAccessor.lengthL(Object[]), so on bytecode level there's a > conflict between declared & actual type (DVT[] doesn't extend Object[]). > > IMO the proper fix would be to have "erased" version for such cases > (or replace all primitive array specializations with a single "erased" > version): > > static int lengthL(java.lang.Object); > 0: aload_0 > 1: arraylength > 2: ireturn > > But it can't be expressed in Java language and requires bytecode > generation. OK - in other words, we need to specialize array length, because of the missing subtyping edge. Ugh. > >> * Can you explain me exactly what you were trying to achieve with >> state.push/state.pop in the intrinsic generation? Typically the state >> is updated through opcodes - so, assuming you are generating >> bytecodes that make sense, you should not need this - unless there >> are bugs in the code builder (which is possible!) > > The following sequence usually hits the bug in the code builder: > builder.goto_("l1"); > builder.label("l2"); > > goto_() doesn't wipe the state, but the state at l2 doesn't relate to > the state when jumping to l1. It usually manifests as stack depth or > type mismatches when trying to merge the states in builder.label(). I see - that's a well-known issue - the builder currently doesn't handle reachability. In your case, the builder should realize that code after 'goto' is dead, so it should just try to merge an empty state with the state of the code that is jumping to "l2" (of course this assumes that there's no other subsequent backward jump to "l2" otherwise the simple stackmap analysis implemented here would fail and you'll need some fix point calculation a la ASM). Maurizio > > Best regards, > Vladimir Ivanov > >> On 28/06/17 14:17, Vladimir Ivanov wrote: >>> Hi, >>> >>> I started playing with MVT-based vectors recently and want to share >>> my experience so far. >>> >>> For the first step, I decided to avoid specific treatment of >>> super-longs (Long2/4/8) in the JVM we have in Panama and just mark >>> them as VCCs for now: >>> @DeriveValueType >>> final class Long2 { public final long lo, hi; } >>> >>> As a test case I chose sum of array elements: >>> >>> long sum(QLong2[] va) { >>> QLong2 v = QLong2.default; // (0,0) >>> for (int i = 0; i < va.length; i++) { >>> QLong2 vi = va[i]; >>> v = QLong2(v.lo + vi.lo, v.hi + vi.hi); >>> } >>> return v.lo + v.hi; >>> } >>> >>> Here are the changes: >>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/ >>> >>> SUMMARY & RESULTS >>> >>> I hit some bugs along the way and had to extend the code for Q-types >>> in some places to get decent code shape generated. (I'll shepherd >>> the fixes in the repo separately.) I ended up with the following >>> generated code: >>> >>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >>> >>> >>> Unfortunately, there are still 2 allocations left in the generated >>> code (out of 5 initially). C2 can't scalarize the accumulator (v) >>> inside the loop and has to put updated components (lo & hi) in >>> allocated heap buffer on every iteration over the array (generated >>> code [1], C2 EA output [2]). >>> >>> >>> GORY DETAILS >>> >>> hotspot/src/share/vm/opto/type.cpp >>> >>> * Type::get_typeflow_type() doesn't distinguish between >>> TypeValueTypePtr & TypeValueType >>> >>> >>> jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >>> >>> * introduced some LF intrinsics, e.g. LOOP and SELECT_ALTERNATIVE; >>> >>> * had to workaround control flow-related bugs in the bytecode >>> library (jdk.experimental.bytecode): broken JVM state after goto_() >>> (see FIXME marks in the code); >>> >>> * fixed 2-slot types support: wrong local indexes were used >>> >>> >>> >>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java >>> >>> * MHI.unboxResultHandle misses unboxing step for Q-types >>> >>> >>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java >>> jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java >>> >>> * had to add a specialization for arraylength on Q-typed array, >>> because C2 can't handle arraylength Object[] when Q[] instance is on >>> stack; >>> >>> >>> jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: >>> >>> >>> * changes required to workaround goto_() bug >>> >>> * fixed CP patching support >>> >>> >>> jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >>> >>> >>> * fixed CP patching support >>> >>> >>> hotspot/src/share/vm/memory/metachunk.hpp >>> hotspot/src/share/vm/oops/method.hpp >>> Fix optimized JVM build. >>> >>> Best regards, >>> Vladimir Ivanov >>> >>> [1] >>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >>> >>> >>> ;; B7: # B8 <- B9 top-of-loop >>> >>> mov %r9,0x10(%rsp) >>> mov 0x8(%rsp),%r11d >>> >>> ;; B8: # B16 B9 <- B6 B7 Loop: B8-B7 inner >>> >>> mov %r11d,0x8(%rsp) >>> movabs $0x7c0060420,%rsi ; {metadata('valhalla/vector/Long2$Value')} >>> ... >>> callq 0x0000000117579820 ; {runtime_call _new_instance_Java} >>> >>> ;; B9: # B7 B10 <- B8 >>> >>> mov %rax,%r9 >>> mov 0x10(%rsp),%r11 >>> mov 0x10(%r11),%r10 >>> mov 0x18(%r11),%r11 >>> movslq %ebp,%r8 >>> shl $0x4,%r8 >>> mov (%rsp),%rcx >>> mov 0x18(%rcx,%r8,1),%rax >>> mov 0x10(%rcx,%r8,1),%r8 ;*vaload >>> add %r11,%rax ;*ladd >>> mov %rax,0x18(%r9) >>> add %r10,%r8 ;*ladd >>> mov %r8,0x10(%r9) >>> inc %ebp ;*iadd >>> cmp 0x8(%rsp),%ebp >>> jl ;*if_icmpge >>> >>> [2] Pruned EA output (full output in the log) >>> ======== Connection graph for valhalla.vector.VectorTest::sumArrayL2 >>> JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F >>> 1579F [ 1259 1264 532 1525 ]] 1247 Allocate >>> LocalVar [ 1247P [ 1264 ]] 1259 Proj ... #5 >>> LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]] 1264 CheckCastPP >>> ... #valuetype* valhalla/vector/Long2$Value:NotNull >>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >>> #valuetype* valhalla/vector/Long2$Value:NotNull >>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >>> #valuetype* valhalla/vector/Long2$Value:NotNull >>> >>> JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]] 1136 Allocate >>> LocalVar [ 1136P [ 1153 ]] 1148 Proj ... #5 >>> LocalVar [ 1148 1136P [ 1154b ]] 1153 CheckCastPP ... >>> #valuetype* valhalla/vector/Long2$Value:NotNull >>> >>> JavaObject NoEscape(NoEscape) [ [ 1053 ]] 1041 Allocate >>> LocalVar [ 1041P [ ]] 1053 Proj ... #5 >>> >>> JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]] 633 Allocate >>> LocalVar [ 633P [ 650 ]] 645 Proj ... #5 >>> LocalVar [ 645 633P [ 653b 651b ]] 650 CheckCastPP ... >>> #valuetype* valhalla/vector/Long2$Value:NotNull >>> >>> JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 324 >>> 532 1525 ]] 307 Allocate >>> LocalVar [ 307P [ 324 ]] 319 Proj ... #5 >>> LocalVar [ 319 307P [ 532 1525 ]] 324 CheckCastPP ... >>> #valuetype* valhalla/vector/Long2$Value:NotNull >>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >>> #valuetype* valhalla/vector/Long2$Value:NotNull >>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >>> #valuetype* valhalla/vector/Long2$Value:NotNull >>> >>> Scalar 1153 CheckCastPP ... #valuetype* >>> valhalla/vector/Long2$Value:NotNull >>> ++++ Eliminated: 1136 Allocate >>> Scalar 1041 Allocate ... >>> ++++ Eliminated: 1041 Allocate >>> Scalar 650 CheckCastPP ... #valuetype* >>> valhalla/vector/Long2$Value:NotNull >>> ++++ Eliminated: 633 Allocate >> From vladimir.x.ivanov at oracle.com Wed Jun 28 15:20:50 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 28 Jun 2017 18:20:50 +0300 Subject: MVT-based vectors: first stab In-Reply-To: <06886e2d-ae0e-5e5a-7b89-1e86c0d44b72@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> <9f97d3e7-6ee9-2438-cbc9-747d185eb685@oracle.com> <44ed7e9d-41df-7a1f-1f2b-2ed69535579e@oracle.com> <06886e2d-ae0e-5e5a-7b89-1e86c0d44b72@oracle.com> Message-ID: <429ce897-92ae-bc22-943f-884ccc2d4476@oracle.com> Best regards, Vladimir Ivanov On 6/28/17 6:00 PM, Maurizio Cimadamore wrote: > > > On 28/06/17 15:36, Vladimir Ivanov wrote: >> >> >> On 6/28/17 5:08 PM, Maurizio Cimadamore wrote: >>> Great work Vlad; I have two questions before I dive in more details >>> >>> * why did you need to handle arrayLength() specially? Since an array >>> is a reference, shouldn't it work already? >> >> It's a workaround for C2 crashes I observed when working with >> arraylength method handle on Q-typed arrays. The problem for the >> compiler is that the implementation uses >> ArrayAccessor.lengthL(Object[]), so on bytecode level there's a >> conflict between declared & actual type (DVT[] doesn't extend Object[]). >> >> IMO the proper fix would be to have "erased" version for such cases >> (or replace all primitive array specializations with a single "erased" >> version): >> >> static int lengthL(java.lang.Object); >> 0: aload_0 >> 1: arraylength >> 2: ireturn >> >> But it can't be expressed in Java language and requires bytecode >> generation. > OK - in other words, we need to specialize array length, because of the > missing subtyping edge. Ugh. Yes. Moreover, I've just checked and the verifier complains about non-array types on stack for arraylength instruction. Caused by: java.lang.VerifyError: Bad type on operand stack in arraylength Exception Details: Location: Test.length(Ljava/lang/Object;)I @1: arraylength Reason: Invalid type: 'java/lang/Object' (current frame, stack[0]) Current Frame: bci: @1 flags: { } locals: { 'java/lang/Object' } stack: { 'java/lang/Object' } So, it seems longer term the only alternative to specialization is Unsafe. >>> * Can you explain me exactly what you were trying to achieve with >>> state.push/state.pop in the intrinsic generation? Typically the state >>> is updated through opcodes - so, assuming you are generating >>> bytecodes that make sense, you should not need this - unless there >>> are bugs in the code builder (which is possible!) >> >> The following sequence usually hits the bug in the code builder: >> builder.goto_("l1"); >> builder.label("l2"); >> >> goto_() doesn't wipe the state, but the state at l2 doesn't relate to >> the state when jumping to l1. It usually manifests as stack depth or >> type mismatches when trying to merge the states in builder.label(). > I see - that's a well-known issue - the builder currently doesn't handle > reachability. In your case, the builder should realize that code after > 'goto' is dead, so it should just try to merge an empty state with the > state of the code that is jumping to "l2" (of course this assumes that > there's no other subsequent backward jump to "l2" otherwise the simple > stackmap analysis implemented here would fail and you'll need some fix > point calculation a la ASM). Yeah, backward jumps cause issues to one-pass solutions. Best regards, Vladimir Ivanov >>> On 28/06/17 14:17, Vladimir Ivanov wrote: >>>> Hi, >>>> >>>> I started playing with MVT-based vectors recently and want to share >>>> my experience so far. >>>> >>>> For the first step, I decided to avoid specific treatment of >>>> super-longs (Long2/4/8) in the JVM we have in Panama and just mark >>>> them as VCCs for now: >>>> @DeriveValueType >>>> final class Long2 { public final long lo, hi; } >>>> >>>> As a test case I chose sum of array elements: >>>> >>>> long sum(QLong2[] va) { >>>> QLong2 v = QLong2.default; // (0,0) >>>> for (int i = 0; i < va.length; i++) { >>>> QLong2 vi = va[i]; >>>> v = QLong2(v.lo + vi.lo, v.hi + vi.hi); >>>> } >>>> return v.lo + v.hi; >>>> } >>>> >>>> Here are the changes: >>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/ >>>> >>>> SUMMARY & RESULTS >>>> >>>> I hit some bugs along the way and had to extend the code for Q-types >>>> in some places to get decent code shape generated. (I'll shepherd >>>> the fixes in the repo separately.) I ended up with the following >>>> generated code: >>>> >>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >>>> >>>> >>>> Unfortunately, there are still 2 allocations left in the generated >>>> code (out of 5 initially). C2 can't scalarize the accumulator (v) >>>> inside the loop and has to put updated components (lo & hi) in >>>> allocated heap buffer on every iteration over the array (generated >>>> code [1], C2 EA output [2]). >>>> >>>> >>>> GORY DETAILS >>>> >>>> hotspot/src/share/vm/opto/type.cpp >>>> >>>> * Type::get_typeflow_type() doesn't distinguish between >>>> TypeValueTypePtr & TypeValueType >>>> >>>> >>>> jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >>>> >>>> * introduced some LF intrinsics, e.g. LOOP and SELECT_ALTERNATIVE; >>>> >>>> * had to workaround control flow-related bugs in the bytecode >>>> library (jdk.experimental.bytecode): broken JVM state after goto_() >>>> (see FIXME marks in the code); >>>> >>>> * fixed 2-slot types support: wrong local indexes were used >>>> >>>> >>>> >>>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java >>>> >>>> * MHI.unboxResultHandle misses unboxing step for Q-types >>>> >>>> >>>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java >>>> jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java >>>> >>>> * had to add a specialization for arraylength on Q-typed array, >>>> because C2 can't handle arraylength Object[] when Q[] instance is on >>>> stack; >>>> >>>> >>>> jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: >>>> >>>> >>>> * changes required to workaround goto_() bug >>>> >>>> * fixed CP patching support >>>> >>>> >>>> jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >>>> >>>> >>>> * fixed CP patching support >>>> >>>> >>>> hotspot/src/share/vm/memory/metachunk.hpp >>>> hotspot/src/share/vm/oops/method.hpp >>>> Fix optimized JVM build. >>>> >>>> Best regards, >>>> Vladimir Ivanov >>>> >>>> [1] >>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >>>> >>>> >>>> ;; B7: # B8 <- B9 top-of-loop >>>> >>>> mov %r9,0x10(%rsp) >>>> mov 0x8(%rsp),%r11d >>>> >>>> ;; B8: # B16 B9 <- B6 B7 Loop: B8-B7 inner >>>> >>>> mov %r11d,0x8(%rsp) >>>> movabs $0x7c0060420,%rsi ; {metadata('valhalla/vector/Long2$Value')} >>>> ... >>>> callq 0x0000000117579820 ; {runtime_call _new_instance_Java} >>>> >>>> ;; B9: # B7 B10 <- B8 >>>> >>>> mov %rax,%r9 >>>> mov 0x10(%rsp),%r11 >>>> mov 0x10(%r11),%r10 >>>> mov 0x18(%r11),%r11 >>>> movslq %ebp,%r8 >>>> shl $0x4,%r8 >>>> mov (%rsp),%rcx >>>> mov 0x18(%rcx,%r8,1),%rax >>>> mov 0x10(%rcx,%r8,1),%r8 ;*vaload >>>> add %r11,%rax ;*ladd >>>> mov %rax,0x18(%r9) >>>> add %r10,%r8 ;*ladd >>>> mov %r8,0x10(%r9) >>>> inc %ebp ;*iadd >>>> cmp 0x8(%rsp),%ebp >>>> jl ;*if_icmpge >>>> >>>> [2] Pruned EA output (full output in the log) >>>> ======== Connection graph for valhalla.vector.VectorTest::sumArrayL2 >>>> JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F >>>> 1579F [ 1259 1264 532 1525 ]] 1247 Allocate >>>> LocalVar [ 1247P [ 1264 ]] 1259 Proj ... #5 >>>> LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]] 1264 CheckCastPP >>>> ... #valuetype* valhalla/vector/Long2$Value:NotNull >>>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>> >>>> JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]] 1136 Allocate >>>> LocalVar [ 1136P [ 1153 ]] 1148 Proj ... #5 >>>> LocalVar [ 1148 1136P [ 1154b ]] 1153 CheckCastPP ... >>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>> >>>> JavaObject NoEscape(NoEscape) [ [ 1053 ]] 1041 Allocate >>>> LocalVar [ 1041P [ ]] 1053 Proj ... #5 >>>> >>>> JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]] 633 Allocate >>>> LocalVar [ 633P [ 650 ]] 645 Proj ... #5 >>>> LocalVar [ 645 633P [ 653b 651b ]] 650 CheckCastPP ... >>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>> >>>> JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 324 >>>> 532 1525 ]] 307 Allocate >>>> LocalVar [ 307P [ 324 ]] 319 Proj ... #5 >>>> LocalVar [ 319 307P [ 532 1525 ]] 324 CheckCastPP ... >>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>> >>>> Scalar 1153 CheckCastPP ... #valuetype* >>>> valhalla/vector/Long2$Value:NotNull >>>> ++++ Eliminated: 1136 Allocate >>>> Scalar 1041 Allocate ... >>>> ++++ Eliminated: 1041 Allocate >>>> Scalar 650 CheckCastPP ... #valuetype* >>>> valhalla/vector/Long2$Value:NotNull >>>> ++++ Eliminated: 633 Allocate >>> > From paul.sandoz at oracle.com Wed Jun 28 15:57:37 2017 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Wed, 28 Jun 2017 15:57:37 +0000 Subject: hg: valhalla/valhalla/jdk: Add findConstructor. Calls constructor on VCC and then unboxes to DVT. Message-ID: <201706281557.v5SFvbHZ023549@aojmv0008.oracle.com> Changeset: 0a380619091c Author: psandoz Date: 2017-06-27 22:25 -0700 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/0a380619091c Add findConstructor. Calls constructor on VCC and then unboxes to DVT. ! src/java.base/share/classes/jdk/experimental/value/ValueType.java + test/valhalla/mvt/ConstructorTest.java + test/valhalla/mvt/Interval.java From paul.sandoz at oracle.com Wed Jun 28 15:59:28 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 28 Jun 2017 08:59:28 -0700 Subject: MVT-based vectors: first stab In-Reply-To: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> Message-ID: <68D2BD61-F45B-41E9-84CC-CD1D2DBBD0DA@oracle.com> Hi Vladimir, Nice work. I notice for the factory you are chaining a sequence of findWithers (vwithfield), one for each field. I am guessing if you construct via the VCC and then unbox that might cause issues with temporary boxing? I think it would be useful to add that functionality to ValueType (with the caveat as with findWither that the VCC constructor is bypassed, which works fine for ?vanilla? VCCs that just put fields and have no constraints). If necessary we could spin specific byte code using the builder to reduce the LF and invocation ceremony. Paul. > On 28 Jun 2017, at 06:17, Vladimir Ivanov wrote: > > Hi, > > I started playing with MVT-based vectors recently and want to share my experience so far. > > For the first step, I decided to avoid specific treatment of super-longs (Long2/4/8) in the JVM we have in Panama and just mark them as VCCs for now: > @DeriveValueType > final class Long2 { public final long lo, hi; } > > As a test case I chose sum of array elements: > > long sum(QLong2[] va) { > QLong2 v = QLong2.default; // (0,0) > for (int i = 0; i < va.length; i++) { > QLong2 vi = va[i]; > v = QLong2(v.lo + vi.lo, v.hi + vi.hi); > } > return v.lo + v.hi; > } > > Here are the changes: > http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/ > > SUMMARY & RESULTS > > I hit some bugs along the way and had to extend the code for Q-types in some places to get decent code shape generated. (I'll shepherd the fixes in the repo separately.) I ended up with the following generated code: > > http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log > > Unfortunately, there are still 2 allocations left in the generated code (out of 5 initially). C2 can't scalarize the accumulator (v) inside the loop and has to put updated components (lo & hi) in allocated heap buffer on every iteration over the array (generated code [1], C2 EA output [2]). > > > GORY DETAILS > > hotspot/src/share/vm/opto/type.cpp > > * Type::get_typeflow_type() doesn't distinguish between TypeValueTypePtr & TypeValueType > > > jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java > > * introduced some LF intrinsics, e.g. LOOP and SELECT_ALTERNATIVE; > > * had to workaround control flow-related bugs in the bytecode library (jdk.experimental.bytecode): broken JVM state after goto_() (see FIXME marks in the code); > > * fixed 2-slot types support: wrong local indexes were used > > > jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java > > * MHI.unboxResultHandle misses unboxing step for Q-types > > > jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java > jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java > > * had to add a specialization for arraylength on Q-typed array, because C2 can't handle arraylength Object[] when Q[] instance is on stack; > > jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: > > * changes required to workaround goto_() bug > > * fixed CP patching support > > > jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java > > * fixed CP patching support > > > hotspot/src/share/vm/memory/metachunk.hpp > hotspot/src/share/vm/oops/method.hpp > Fix optimized JVM build. > > Best regards, > Vladimir Ivanov > > [1] http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log > > ;; B7: # B8 <- B9 top-of-loop > > mov %r9,0x10(%rsp) > mov 0x8(%rsp),%r11d > > ;; B8: # B16 B9 <- B6 B7 Loop: B8-B7 inner > > mov %r11d,0x8(%rsp) > movabs $0x7c0060420,%rsi ; {metadata('valhalla/vector/Long2$Value')} > ... > callq 0x0000000117579820 ; {runtime_call _new_instance_Java} > > ;; B9: # B7 B10 <- B8 > > mov %rax,%r9 > mov 0x10(%rsp),%r11 > mov 0x10(%r11),%r10 > mov 0x18(%r11),%r11 > movslq %ebp,%r8 > shl $0x4,%r8 > mov (%rsp),%rcx > mov 0x18(%rcx,%r8,1),%rax > mov 0x10(%rcx,%r8,1),%r8 ;*vaload > add %r11,%rax ;*ladd > mov %rax,0x18(%r9) > add %r10,%r8 ;*ladd > mov %r8,0x10(%r9) > inc %ebp ;*iadd > cmp 0x8(%rsp),%ebp > jl ;*if_icmpge > > [2] Pruned EA output (full output in the log) > ======== Connection graph for valhalla.vector.VectorTest::sumArrayL2 > JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F 1579F [ 1259 1264 532 1525 ]] 1247 Allocate > LocalVar [ 1247P [ 1264 ]] 1259 Proj ... #5 > LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]] 1264 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull > LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull > LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull > > JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]] 1136 Allocate > LocalVar [ 1136P [ 1153 ]] 1148 Proj ... #5 > LocalVar [ 1148 1136P [ 1154b ]] 1153 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull > > JavaObject NoEscape(NoEscape) [ [ 1053 ]] 1041 Allocate > LocalVar [ 1041P [ ]] 1053 Proj ... #5 > > JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]] 633 Allocate > LocalVar [ 633P [ 650 ]] 645 Proj ... #5 > LocalVar [ 645 633P [ 653b 651b ]] 650 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull > > JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 324 532 1525 ]] 307 Allocate > LocalVar [ 307P [ 324 ]] 319 Proj ... #5 > LocalVar [ 319 307P [ 532 1525 ]] 324 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull > LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull > LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull > > Scalar 1153 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull > ++++ Eliminated: 1136 Allocate > Scalar 1041 Allocate ... > ++++ Eliminated: 1041 Allocate > Scalar 650 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull > ++++ Eliminated: 633 Allocate From vladimir.x.ivanov at oracle.com Wed Jun 28 16:03:11 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 28 Jun 2017 19:03:11 +0300 Subject: MVT-based vectors: first stab In-Reply-To: References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> Message-ID: > thanks a lot for the nice summary! I think it would makes sense to file enhancements/bugs for the individual issues. FYI here's the list of issues: RFEs https://bugs.openjdk.java.net/browse/JDK-8183130 core-libs/j.l.i [MVT] Implement intrinsics for Q-typed LambdaForms https://bugs.openjdk.java.net/browse/JDK-8183137 hotspot/compiler [MVT] C2 doesn't eliminate redundant value type allocations inside loops Bugs https://bugs.openjdk.java.net/browse/JDK-8183129 hotspot/compiler [MVT] Type::get_typeflow_type() doesn't distinguish between TypeValueTypePtr & TypeValueType https://bugs.openjdk.java.net/browse/JDK-8183131 core-libs/j.l.i [MVT] 2-slot type (long & double) support is broken in LambdaFormBuilder https://bugs.openjdk.java.net/browse/JDK-8183132 core-libs/j.l.i [MVT] MHI.unboxResultHandle misses unboxing step for Q-types https://bugs.openjdk.java.net/browse/JDK-8183133 core-libs/j.l.i [MVT] Arraylength method handle on Q-typed array shouldn't use ArrayAccessor.lengthL(Object[]) https://bugs.openjdk.java.net/browse/JDK-8183135 core-libs/j.l.i [MVT] Code builder doesn't fully support constant pool patching https://bugs.openjdk.java.net/browse/JDK-8183138 core-libs/j.l.i Code Builder: Problems with handling complex control flow Best regards, Vladimir Ivanov > On 28.06.2017 15:17, Vladimir Ivanov wrote: >> I hit some bugs along the way > > I had a closer look and (as you already figured out) one problem is that typeflow analysis incorrectly sets the type of a PhiNode to TypeValueType instead of TypeValueTypePtr for __Value. When inlining a method handle intrinsic in CallGenerator::for_method_handle_inline() we should cast all arguments to their actual types but we miss the PhiNode because it's already of TypeValueType: > > t: > arg_type: valuetype[0]:{empty} > sig_type: valuetype* valhalla/vector/Long2$Value:NotNull > arg: 659 Phi === 652 _ 626 [[ 616 662 678 680 684 730 760 785 790 793 837 867 874 889 891 894 ]] #valuetype[0]:{empty} !jvms: 1310540333::invoke @ bci:170 858242339::invokeExact_MT @ bci:19 VectorTest::acc @ bci:4 VectorTest::main @ bci:69 > > We then fail in Parse::do_vunbox because the input node is a Phi (and not a ValueTypeNode). > > I think in addition to the fix in type.cpp, we should add this assert to catch such problems in the future: > > --- old/src/share/vm/opto/callGenerator.cpp 2017-06-28 15:25:40.812039870 +0200 > +++ new/src/share/vm/opto/callGenerator.cpp 2017-06-28 15:25:40.720039875 +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)) { > > I'll take the chance to look at the method handle implementation in a bit more detail and try to come up with a regression test for this to extend our ValueTypesTestBench. > > Best regards, > Tobias > From maurizio.cimadamore at oracle.com Wed Jun 28 16:07:50 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 28 Jun 2017 17:07:50 +0100 Subject: MVT-based vectors: first stab In-Reply-To: <429ce897-92ae-bc22-943f-884ccc2d4476@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> <9f97d3e7-6ee9-2438-cbc9-747d185eb685@oracle.com> <44ed7e9d-41df-7a1f-1f2b-2ed69535579e@oracle.com> <06886e2d-ae0e-5e5a-7b89-1e86c0d44b72@oracle.com> <429ce897-92ae-bc22-943f-884ccc2d4476@oracle.com> Message-ID: <4306034a-d879-af16-eb92-91425abc3502@oracle.com> Could you please try this patch and tell me if that helps for the liveness trouble? Cheers Maurizio On 28/06/17 16:20, Vladimir Ivanov wrote: > > > Best regards, > Vladimir Ivanov > > On 6/28/17 6:00 PM, Maurizio Cimadamore wrote: >> >> >> On 28/06/17 15:36, Vladimir Ivanov wrote: >>> >>> >>> On 6/28/17 5:08 PM, Maurizio Cimadamore wrote: >>>> Great work Vlad; I have two questions before I dive in more details >>>> >>>> * why did you need to handle arrayLength() specially? Since an >>>> array is a reference, shouldn't it work already? >>> >>> It's a workaround for C2 crashes I observed when working with >>> arraylength method handle on Q-typed arrays. The problem for the >>> compiler is that the implementation uses >>> ArrayAccessor.lengthL(Object[]), so on bytecode level there's a >>> conflict between declared & actual type (DVT[] doesn't extend >>> Object[]). >>> >>> IMO the proper fix would be to have "erased" version for such cases >>> (or replace all primitive array specializations with a single >>> "erased" version): >>> >>> static int lengthL(java.lang.Object); >>> 0: aload_0 >>> 1: arraylength >>> 2: ireturn >>> >>> But it can't be expressed in Java language and requires bytecode >>> generation. >> OK - in other words, we need to specialize array length, because of >> the missing subtyping edge. Ugh. > > Yes. Moreover, I've just checked and the verifier complains about > non-array types on stack for arraylength instruction. > > Caused by: java.lang.VerifyError: Bad type on operand stack in > arraylength > Exception Details: > Location: > Test.length(Ljava/lang/Object;)I @1: arraylength > Reason: > Invalid type: 'java/lang/Object' (current frame, stack[0]) > Current Frame: > bci: @1 > flags: { } > locals: { 'java/lang/Object' } > stack: { 'java/lang/Object' } > > So, it seems longer term the only alternative to specialization is > Unsafe. > >>>> * Can you explain me exactly what you were trying to achieve with >>>> state.push/state.pop in the intrinsic generation? Typically the >>>> state is updated through opcodes - so, assuming you are generating >>>> bytecodes that make sense, you should not need this - unless there >>>> are bugs in the code builder (which is possible!) >>> >>> The following sequence usually hits the bug in the code builder: >>> builder.goto_("l1"); >>> builder.label("l2"); >>> >>> goto_() doesn't wipe the state, but the state at l2 doesn't relate >>> to the state when jumping to l1. It usually manifests as stack depth >>> or type mismatches when trying to merge the states in builder.label(). >> I see - that's a well-known issue - the builder currently doesn't >> handle reachability. In your case, the builder should realize that >> code after 'goto' is dead, so it should just try to merge an empty >> state with the state of the code that is jumping to "l2" (of course >> this assumes that there's no other subsequent backward jump to "l2" >> otherwise the simple stackmap analysis implemented here would fail >> and you'll need some fix point calculation a la ASM). > > Yeah, backward jumps cause issues to one-pass solutions. > > Best regards, > Vladimir Ivanov > >>>> On 28/06/17 14:17, Vladimir Ivanov wrote: >>>>> Hi, >>>>> >>>>> I started playing with MVT-based vectors recently and want to >>>>> share my experience so far. >>>>> >>>>> For the first step, I decided to avoid specific treatment of >>>>> super-longs (Long2/4/8) in the JVM we have in Panama and just mark >>>>> them as VCCs for now: >>>>> @DeriveValueType >>>>> final class Long2 { public final long lo, hi; } >>>>> >>>>> As a test case I chose sum of array elements: >>>>> >>>>> long sum(QLong2[] va) { >>>>> QLong2 v = QLong2.default; // (0,0) >>>>> for (int i = 0; i < va.length; i++) { >>>>> QLong2 vi = va[i]; >>>>> v = QLong2(v.lo + vi.lo, v.hi + vi.hi); >>>>> } >>>>> return v.lo + v.hi; >>>>> } >>>>> >>>>> Here are the changes: >>>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/ >>>>> >>>>> SUMMARY & RESULTS >>>>> >>>>> I hit some bugs along the way and had to extend the code for >>>>> Q-types in some places to get decent code shape generated. (I'll >>>>> shepherd the fixes in the repo separately.) I ended up with the >>>>> following generated code: >>>>> >>>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >>>>> >>>>> >>>>> Unfortunately, there are still 2 allocations left in the generated >>>>> code (out of 5 initially). C2 can't scalarize the accumulator (v) >>>>> inside the loop and has to put updated components (lo & hi) in >>>>> allocated heap buffer on every iteration over the array (generated >>>>> code [1], C2 EA output [2]). >>>>> >>>>> >>>>> GORY DETAILS >>>>> >>>>> hotspot/src/share/vm/opto/type.cpp >>>>> >>>>> * Type::get_typeflow_type() doesn't distinguish between >>>>> TypeValueTypePtr & TypeValueType >>>>> >>>>> >>>>> jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >>>>> >>>>> >>>>> * introduced some LF intrinsics, e.g. LOOP and >>>>> SELECT_ALTERNATIVE; >>>>> >>>>> * had to workaround control flow-related bugs in the bytecode >>>>> library (jdk.experimental.bytecode): broken JVM state after >>>>> goto_() (see FIXME marks in the code); >>>>> >>>>> * fixed 2-slot types support: wrong local indexes were used >>>>> >>>>> >>>>> >>>>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java >>>>> >>>>> >>>>> * MHI.unboxResultHandle misses unboxing step for Q-types >>>>> >>>>> >>>>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java >>>>> jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java >>>>> >>>>> * had to add a specialization for arraylength on Q-typed >>>>> array, because C2 can't handle arraylength Object[] when Q[] >>>>> instance is on stack; >>>>> >>>>> >>>>> jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: >>>>> >>>>> >>>>> * changes required to workaround goto_() bug >>>>> >>>>> * fixed CP patching support >>>>> >>>>> >>>>> jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >>>>> >>>>> >>>>> * fixed CP patching support >>>>> >>>>> >>>>> hotspot/src/share/vm/memory/metachunk.hpp >>>>> hotspot/src/share/vm/oops/method.hpp >>>>> Fix optimized JVM build. >>>>> >>>>> Best regards, >>>>> Vladimir Ivanov >>>>> >>>>> [1] >>>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >>>>> >>>>> >>>>> ;; B7: # B8 <- B9 top-of-loop >>>>> >>>>> mov %r9,0x10(%rsp) >>>>> mov 0x8(%rsp),%r11d >>>>> >>>>> ;; B8: # B16 B9 <- B6 B7 Loop: B8-B7 inner >>>>> >>>>> mov %r11d,0x8(%rsp) >>>>> movabs $0x7c0060420,%rsi ; {metadata('valhalla/vector/Long2$Value')} >>>>> ... >>>>> callq 0x0000000117579820 ; {runtime_call _new_instance_Java} >>>>> >>>>> ;; B9: # B7 B10 <- B8 >>>>> >>>>> mov %rax,%r9 >>>>> mov 0x10(%rsp),%r11 >>>>> mov 0x10(%r11),%r10 >>>>> mov 0x18(%r11),%r11 >>>>> movslq %ebp,%r8 >>>>> shl $0x4,%r8 >>>>> mov (%rsp),%rcx >>>>> mov 0x18(%rcx,%r8,1),%rax >>>>> mov 0x10(%rcx,%r8,1),%r8 ;*vaload >>>>> add %r11,%rax ;*ladd >>>>> mov %rax,0x18(%r9) >>>>> add %r10,%r8 ;*ladd >>>>> mov %r8,0x10(%r9) >>>>> inc %ebp ;*iadd >>>>> cmp 0x8(%rsp),%ebp >>>>> jl ;*if_icmpge >>>>> >>>>> [2] Pruned EA output (full output in the log) >>>>> ======== Connection graph for valhalla.vector.VectorTest::sumArrayL2 >>>>> JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F >>>>> 1579F [ 1259 1264 532 1525 ]] 1247 Allocate >>>>> LocalVar [ 1247P [ 1264 ]] 1259 Proj ... #5 >>>>> LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]] 1264 CheckCastPP >>>>> ... #valuetype* valhalla/vector/Long2$Value:NotNull >>>>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>> >>>>> JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]] 1136 Allocate >>>>> LocalVar [ 1136P [ 1153 ]] 1148 Proj ... #5 >>>>> LocalVar [ 1148 1136P [ 1154b ]] 1153 CheckCastPP ... >>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>> >>>>> JavaObject NoEscape(NoEscape) [ [ 1053 ]] 1041 Allocate >>>>> LocalVar [ 1041P [ ]] 1053 Proj ... #5 >>>>> >>>>> JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]] 633 Allocate >>>>> LocalVar [ 633P [ 650 ]] 645 Proj ... #5 >>>>> LocalVar [ 645 633P [ 653b 651b ]] 650 CheckCastPP ... >>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>> >>>>> JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 >>>>> 324 532 1525 ]] 307 Allocate >>>>> LocalVar [ 307P [ 324 ]] 319 Proj ... #5 >>>>> LocalVar [ 319 307P [ 532 1525 ]] 324 CheckCastPP ... >>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>> >>>>> Scalar 1153 CheckCastPP ... #valuetype* >>>>> valhalla/vector/Long2$Value:NotNull >>>>> ++++ Eliminated: 1136 Allocate >>>>> Scalar 1041 Allocate ... >>>>> ++++ Eliminated: 1041 Allocate >>>>> Scalar 650 CheckCastPP ... #valuetype* >>>>> valhalla/vector/Long2$Value:NotNull >>>>> ++++ Eliminated: 633 Allocate >>>> >> -------------- next part -------------- A non-text attachment was scrubbed... Name: liveness.patch Type: text/x-patch Size: 1068 bytes Desc: not available URL: From vladimir.x.ivanov at oracle.com Wed Jun 28 16:17:50 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 28 Jun 2017 19:17:50 +0300 Subject: MVT-based vectors: first stab In-Reply-To: <68D2BD61-F45B-41E9-84CC-CD1D2DBBD0DA@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> <68D2BD61-F45B-41E9-84CC-CD1D2DBBD0DA@oracle.com> Message-ID: <69135ad7-5b43-2768-ee84-7a38ee30bbaa@oracle.com> > Nice work. > > I notice for the factory you are chaining a sequence of findWithers (vwithfield), one for each field. I am guessing if you construct via the VCC and then unbox that might cause issues with temporary boxing? Yes, I deliberately tried to avoid any unnecessary boxing to make JIT-compiler life easier. The main question I had when starting the experiment was is it possible to completely avoid/eliminate boxing/buffering in generated code. Because absence of boxing/buffering operations in generated code is crucial for vectors. > I think it would be useful to add that functionality to ValueType (with the caveat as with findWither that the VCC constructor is bypassed, which works fine for ?vanilla? VCCs that just put fields and have no constraints). If necessary we could spin specific byte code using the builder to reduce the LF and invocation ceremony. Yes, it looks like a good candidate for inclusion. Method handle chain is quite complex, so it'll definitely benefit from specialized bytecode (vdefault; vwithfield DVT.f1; ...; vwithfield DVT.fn; vreturn;) Best regards, Vladimir Ivanov > > Paul. > > > >> On 28 Jun 2017, at 06:17, Vladimir Ivanov wrote: >> >> Hi, >> >> I started playing with MVT-based vectors recently and want to share my experience so far. >> >> For the first step, I decided to avoid specific treatment of super-longs (Long2/4/8) in the JVM we have in Panama and just mark them as VCCs for now: >> @DeriveValueType >> final class Long2 { public final long lo, hi; } >> >> As a test case I chose sum of array elements: >> >> long sum(QLong2[] va) { >> QLong2 v = QLong2.default; // (0,0) >> for (int i = 0; i < va.length; i++) { >> QLong2 vi = va[i]; >> v = QLong2(v.lo + vi.lo, v.hi + vi.hi); >> } >> return v.lo + v.hi; >> } >> >> Here are the changes: >> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/ >> >> SUMMARY & RESULTS >> >> I hit some bugs along the way and had to extend the code for Q-types in some places to get decent code shape generated. (I'll shepherd the fixes in the repo separately.) I ended up with the following generated code: >> >> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >> >> Unfortunately, there are still 2 allocations left in the generated code (out of 5 initially). C2 can't scalarize the accumulator (v) inside the loop and has to put updated components (lo & hi) in allocated heap buffer on every iteration over the array (generated code [1], C2 EA output [2]). >> >> >> GORY DETAILS >> >> hotspot/src/share/vm/opto/type.cpp >> >> * Type::get_typeflow_type() doesn't distinguish between TypeValueTypePtr & TypeValueType >> >> >> jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >> >> * introduced some LF intrinsics, e.g. LOOP and SELECT_ALTERNATIVE; >> >> * had to workaround control flow-related bugs in the bytecode library (jdk.experimental.bytecode): broken JVM state after goto_() (see FIXME marks in the code); >> >> * fixed 2-slot types support: wrong local indexes were used >> >> >> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java >> >> * MHI.unboxResultHandle misses unboxing step for Q-types >> >> >> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java >> jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java >> >> * had to add a specialization for arraylength on Q-typed array, because C2 can't handle arraylength Object[] when Q[] instance is on stack; >> >> jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: >> >> * changes required to workaround goto_() bug >> >> * fixed CP patching support >> >> >> jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >> >> * fixed CP patching support >> >> >> hotspot/src/share/vm/memory/metachunk.hpp >> hotspot/src/share/vm/oops/method.hpp >> Fix optimized JVM build. >> >> Best regards, >> Vladimir Ivanov >> >> [1] http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >> >> ;; B7: # B8 <- B9 top-of-loop >> >> mov %r9,0x10(%rsp) >> mov 0x8(%rsp),%r11d >> >> ;; B8: # B16 B9 <- B6 B7 Loop: B8-B7 inner >> >> mov %r11d,0x8(%rsp) >> movabs $0x7c0060420,%rsi ; {metadata('valhalla/vector/Long2$Value')} >> ... >> callq 0x0000000117579820 ; {runtime_call _new_instance_Java} >> >> ;; B9: # B7 B10 <- B8 >> >> mov %rax,%r9 >> mov 0x10(%rsp),%r11 >> mov 0x10(%r11),%r10 >> mov 0x18(%r11),%r11 >> movslq %ebp,%r8 >> shl $0x4,%r8 >> mov (%rsp),%rcx >> mov 0x18(%rcx,%r8,1),%rax >> mov 0x10(%rcx,%r8,1),%r8 ;*vaload >> add %r11,%rax ;*ladd >> mov %rax,0x18(%r9) >> add %r10,%r8 ;*ladd >> mov %r8,0x10(%r9) >> inc %ebp ;*iadd >> cmp 0x8(%rsp),%ebp >> jl ;*if_icmpge >> >> [2] Pruned EA output (full output in the log) >> ======== Connection graph for valhalla.vector.VectorTest::sumArrayL2 >> JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F 1579F [ 1259 1264 532 1525 ]] 1247 Allocate >> LocalVar [ 1247P [ 1264 ]] 1259 Proj ... #5 >> LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]] 1264 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull >> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull >> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull >> >> JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]] 1136 Allocate >> LocalVar [ 1136P [ 1153 ]] 1148 Proj ... #5 >> LocalVar [ 1148 1136P [ 1154b ]] 1153 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull >> >> JavaObject NoEscape(NoEscape) [ [ 1053 ]] 1041 Allocate >> LocalVar [ 1041P [ ]] 1053 Proj ... #5 >> >> JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]] 633 Allocate >> LocalVar [ 633P [ 650 ]] 645 Proj ... #5 >> LocalVar [ 645 633P [ 653b 651b ]] 650 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull >> >> JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 324 532 1525 ]] 307 Allocate >> LocalVar [ 307P [ 324 ]] 319 Proj ... #5 >> LocalVar [ 319 307P [ 532 1525 ]] 324 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull >> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull >> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... #valuetype* valhalla/vector/Long2$Value:NotNull >> >> Scalar 1153 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull >> ++++ Eliminated: 1136 Allocate >> Scalar 1041 Allocate ... >> ++++ Eliminated: 1041 Allocate >> Scalar 650 CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull >> ++++ Eliminated: 633 Allocate > From paul.sandoz at oracle.com Wed Jun 28 16:34:37 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 28 Jun 2017 09:34:37 -0700 Subject: MVT-based vectors: first stab In-Reply-To: <69135ad7-5b43-2768-ee84-7a38ee30bbaa@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> <68D2BD61-F45B-41E9-84CC-CD1D2DBBD0DA@oracle.com> <69135ad7-5b43-2768-ee84-7a38ee30bbaa@oracle.com> Message-ID: <2BC0F5A3-6F47-4BEC-9342-0E6B2F701896@oracle.com> > On 28 Jun 2017, at 09:17, Vladimir Ivanov wrote: > >> Nice work. >> I notice for the factory you are chaining a sequence of findWithers (vwithfield), one for each field. I am guessing if you construct via the VCC and then unbox that might cause issues with temporary boxing? > > Yes, I deliberately tried to avoid any unnecessary boxing to make JIT-compiler life easier. The main question I had when starting the experiment was is it possible to completely avoid/eliminate boxing/buffering in generated code. Because absence of boxing/buffering operations in generated code is crucial for vectors. > >> I think it would be useful to add that functionality to ValueType (with the caveat as with findWither that the VCC constructor is bypassed, which works fine for ?vanilla? VCCs that just put fields and have no constraints). If necessary we could spin specific byte code using the builder to reduce the LF and invocation ceremony. > > Yes, it looks like a good candidate for inclusion. Method handle chain is quite complex, so it'll definitely benefit from specialized bytecode (vdefault; vwithfield DVT.f1; ...; vwithfield DVT.fn; vreturn;) > Ok, if that does not interfere with what you are doing i can log an issue and implement/test that. Paul. From vladimir.x.ivanov at oracle.com Wed Jun 28 16:37:34 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 28 Jun 2017 19:37:34 +0300 Subject: MVT-based vectors: first stab In-Reply-To: <2BC0F5A3-6F47-4BEC-9342-0E6B2F701896@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> <68D2BD61-F45B-41E9-84CC-CD1D2DBBD0DA@oracle.com> <69135ad7-5b43-2768-ee84-7a38ee30bbaa@oracle.com> <2BC0F5A3-6F47-4BEC-9342-0E6B2F701896@oracle.com> Message-ID: >>> I think it would be useful to add that functionality to ValueType (with the caveat as with findWither that the VCC constructor is bypassed, which works fine for ?vanilla? VCCs that just put fields and have no constraints). If necessary we could spin specific byte code using the builder to reduce the LF and invocation ceremony. >> >> Yes, it looks like a good candidate for inclusion. Method handle chain is quite complex, so it'll definitely benefit from specialized bytecode (vdefault; vwithfield DVT.f1; ...; vwithfield DVT.fn; vreturn;) >> > > Ok, if that does not interfere with what you are doing i can log an issue and implement/test that. Sure, feel free to take care of it! Best regards, Vladimir Ivanov From vladimir.x.ivanov at oracle.com Wed Jun 28 16:44:42 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 28 Jun 2017 19:44:42 +0300 Subject: MVT-based vectors: first stab In-Reply-To: <4306034a-d879-af16-eb92-91425abc3502@oracle.com> References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> <9f97d3e7-6ee9-2438-cbc9-747d185eb685@oracle.com> <44ed7e9d-41df-7a1f-1f2b-2ed69535579e@oracle.com> <06886e2d-ae0e-5e5a-7b89-1e86c0d44b72@oracle.com> <429ce897-92ae-bc22-943f-884ccc2d4476@oracle.com> <4306034a-d879-af16-eb92-91425abc3502@oracle.com> Message-ID: Yes, the patch fixes the bug I hit in GWT & loop intrinsics. Thanks! Best regards, Vladimir Ivanov On 6/28/17 7:07 PM, Maurizio Cimadamore wrote: > Could you please try this patch and tell me if that helps for the > liveness trouble? > > Cheers > Maurizio > > > On 28/06/17 16:20, Vladimir Ivanov wrote: >> >> >> Best regards, >> Vladimir Ivanov >> >> On 6/28/17 6:00 PM, Maurizio Cimadamore wrote: >>> >>> >>> On 28/06/17 15:36, Vladimir Ivanov wrote: >>>> >>>> >>>> On 6/28/17 5:08 PM, Maurizio Cimadamore wrote: >>>>> Great work Vlad; I have two questions before I dive in more details >>>>> >>>>> * why did you need to handle arrayLength() specially? Since an >>>>> array is a reference, shouldn't it work already? >>>> >>>> It's a workaround for C2 crashes I observed when working with >>>> arraylength method handle on Q-typed arrays. The problem for the >>>> compiler is that the implementation uses >>>> ArrayAccessor.lengthL(Object[]), so on bytecode level there's a >>>> conflict between declared & actual type (DVT[] doesn't extend >>>> Object[]). >>>> >>>> IMO the proper fix would be to have "erased" version for such cases >>>> (or replace all primitive array specializations with a single >>>> "erased" version): >>>> >>>> static int lengthL(java.lang.Object); >>>> 0: aload_0 >>>> 1: arraylength >>>> 2: ireturn >>>> >>>> But it can't be expressed in Java language and requires bytecode >>>> generation. >>> OK - in other words, we need to specialize array length, because of >>> the missing subtyping edge. Ugh. >> >> Yes. Moreover, I've just checked and the verifier complains about >> non-array types on stack for arraylength instruction. >> >> Caused by: java.lang.VerifyError: Bad type on operand stack in >> arraylength >> Exception Details: >> Location: >> Test.length(Ljava/lang/Object;)I @1: arraylength >> Reason: >> Invalid type: 'java/lang/Object' (current frame, stack[0]) >> Current Frame: >> bci: @1 >> flags: { } >> locals: { 'java/lang/Object' } >> stack: { 'java/lang/Object' } >> >> So, it seems longer term the only alternative to specialization is >> Unsafe. >> >>>>> * Can you explain me exactly what you were trying to achieve with >>>>> state.push/state.pop in the intrinsic generation? Typically the >>>>> state is updated through opcodes - so, assuming you are generating >>>>> bytecodes that make sense, you should not need this - unless there >>>>> are bugs in the code builder (which is possible!) >>>> >>>> The following sequence usually hits the bug in the code builder: >>>> builder.goto_("l1"); >>>> builder.label("l2"); >>>> >>>> goto_() doesn't wipe the state, but the state at l2 doesn't relate >>>> to the state when jumping to l1. It usually manifests as stack depth >>>> or type mismatches when trying to merge the states in builder.label(). >>> I see - that's a well-known issue - the builder currently doesn't >>> handle reachability. In your case, the builder should realize that >>> code after 'goto' is dead, so it should just try to merge an empty >>> state with the state of the code that is jumping to "l2" (of course >>> this assumes that there's no other subsequent backward jump to "l2" >>> otherwise the simple stackmap analysis implemented here would fail >>> and you'll need some fix point calculation a la ASM). >> >> Yeah, backward jumps cause issues to one-pass solutions. >> >> Best regards, >> Vladimir Ivanov >> >>>>> On 28/06/17 14:17, Vladimir Ivanov wrote: >>>>>> Hi, >>>>>> >>>>>> I started playing with MVT-based vectors recently and want to >>>>>> share my experience so far. >>>>>> >>>>>> For the first step, I decided to avoid specific treatment of >>>>>> super-longs (Long2/4/8) in the JVM we have in Panama and just mark >>>>>> them as VCCs for now: >>>>>> @DeriveValueType >>>>>> final class Long2 { public final long lo, hi; } >>>>>> >>>>>> As a test case I chose sum of array elements: >>>>>> >>>>>> long sum(QLong2[] va) { >>>>>> QLong2 v = QLong2.default; // (0,0) >>>>>> for (int i = 0; i < va.length; i++) { >>>>>> QLong2 vi = va[i]; >>>>>> v = QLong2(v.lo + vi.lo, v.hi + vi.hi); >>>>>> } >>>>>> return v.lo + v.hi; >>>>>> } >>>>>> >>>>>> Here are the changes: >>>>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/ >>>>>> >>>>>> SUMMARY & RESULTS >>>>>> >>>>>> I hit some bugs along the way and had to extend the code for >>>>>> Q-types in some places to get decent code shape generated. (I'll >>>>>> shepherd the fixes in the repo separately.) I ended up with the >>>>>> following generated code: >>>>>> >>>>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >>>>>> >>>>>> >>>>>> Unfortunately, there are still 2 allocations left in the generated >>>>>> code (out of 5 initially). C2 can't scalarize the accumulator (v) >>>>>> inside the loop and has to put updated components (lo & hi) in >>>>>> allocated heap buffer on every iteration over the array (generated >>>>>> code [1], C2 EA output [2]). >>>>>> >>>>>> >>>>>> GORY DETAILS >>>>>> >>>>>> hotspot/src/share/vm/opto/type.cpp >>>>>> >>>>>> * Type::get_typeflow_type() doesn't distinguish between >>>>>> TypeValueTypePtr & TypeValueType >>>>>> >>>>>> >>>>>> jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >>>>>> >>>>>> >>>>>> * introduced some LF intrinsics, e.g. LOOP and >>>>>> SELECT_ALTERNATIVE; >>>>>> >>>>>> * had to workaround control flow-related bugs in the bytecode >>>>>> library (jdk.experimental.bytecode): broken JVM state after >>>>>> goto_() (see FIXME marks in the code); >>>>>> >>>>>> * fixed 2-slot types support: wrong local indexes were used >>>>>> >>>>>> >>>>>> >>>>>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java >>>>>> >>>>>> >>>>>> * MHI.unboxResultHandle misses unboxing step for Q-types >>>>>> >>>>>> >>>>>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java >>>>>> jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java >>>>>> >>>>>> * had to add a specialization for arraylength on Q-typed >>>>>> array, because C2 can't handle arraylength Object[] when Q[] >>>>>> instance is on stack; >>>>>> >>>>>> >>>>>> jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: >>>>>> >>>>>> >>>>>> * changes required to workaround goto_() bug >>>>>> >>>>>> * fixed CP patching support >>>>>> >>>>>> >>>>>> jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >>>>>> >>>>>> >>>>>> * fixed CP patching support >>>>>> >>>>>> >>>>>> hotspot/src/share/vm/memory/metachunk.hpp >>>>>> hotspot/src/share/vm/oops/method.hpp >>>>>> Fix optimized JVM build. >>>>>> >>>>>> Best regards, >>>>>> Vladimir Ivanov >>>>>> >>>>>> [1] >>>>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >>>>>> >>>>>> >>>>>> ;; B7: # B8 <- B9 top-of-loop >>>>>> >>>>>> mov %r9,0x10(%rsp) >>>>>> mov 0x8(%rsp),%r11d >>>>>> >>>>>> ;; B8: # B16 B9 <- B6 B7 Loop: B8-B7 inner >>>>>> >>>>>> mov %r11d,0x8(%rsp) >>>>>> movabs $0x7c0060420,%rsi ; {metadata('valhalla/vector/Long2$Value')} >>>>>> ... >>>>>> callq 0x0000000117579820 ; {runtime_call _new_instance_Java} >>>>>> >>>>>> ;; B9: # B7 B10 <- B8 >>>>>> >>>>>> mov %rax,%r9 >>>>>> mov 0x10(%rsp),%r11 >>>>>> mov 0x10(%r11),%r10 >>>>>> mov 0x18(%r11),%r11 >>>>>> movslq %ebp,%r8 >>>>>> shl $0x4,%r8 >>>>>> mov (%rsp),%rcx >>>>>> mov 0x18(%rcx,%r8,1),%rax >>>>>> mov 0x10(%rcx,%r8,1),%r8 ;*vaload >>>>>> add %r11,%rax ;*ladd >>>>>> mov %rax,0x18(%r9) >>>>>> add %r10,%r8 ;*ladd >>>>>> mov %r8,0x10(%r9) >>>>>> inc %ebp ;*iadd >>>>>> cmp 0x8(%rsp),%ebp >>>>>> jl ;*if_icmpge >>>>>> >>>>>> [2] Pruned EA output (full output in the log) >>>>>> ======== Connection graph for valhalla.vector.VectorTest::sumArrayL2 >>>>>> JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F >>>>>> 1579F [ 1259 1264 532 1525 ]] 1247 Allocate >>>>>> LocalVar [ 1247P [ 1264 ]] 1259 Proj ... #5 >>>>>> LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]] 1264 CheckCastPP >>>>>> ... #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>> >>>>>> JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]] 1136 Allocate >>>>>> LocalVar [ 1136P [ 1153 ]] 1148 Proj ... #5 >>>>>> LocalVar [ 1148 1136P [ 1154b ]] 1153 CheckCastPP ... >>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>> >>>>>> JavaObject NoEscape(NoEscape) [ [ 1053 ]] 1041 Allocate >>>>>> LocalVar [ 1041P [ ]] 1053 Proj ... #5 >>>>>> >>>>>> JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]] 633 Allocate >>>>>> LocalVar [ 633P [ 650 ]] 645 Proj ... #5 >>>>>> LocalVar [ 645 633P [ 653b 651b ]] 650 CheckCastPP ... >>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>> >>>>>> JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 >>>>>> 324 532 1525 ]] 307 Allocate >>>>>> LocalVar [ 307P [ 324 ]] 319 Proj ... #5 >>>>>> LocalVar [ 319 307P [ 532 1525 ]] 324 CheckCastPP ... >>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>> >>>>>> Scalar 1153 CheckCastPP ... #valuetype* >>>>>> valhalla/vector/Long2$Value:NotNull >>>>>> ++++ Eliminated: 1136 Allocate >>>>>> Scalar 1041 Allocate ... >>>>>> ++++ Eliminated: 1041 Allocate >>>>>> Scalar 650 CheckCastPP ... #valuetype* >>>>>> valhalla/vector/Long2$Value:NotNull >>>>>> ++++ Eliminated: 633 Allocate >>>>> >>> > From maurizio.cimadamore at oracle.com Wed Jun 28 17:10:25 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 28 Jun 2017 18:10:25 +0100 Subject: MVT-based vectors: first stab In-Reply-To: References: <2d2c6eef-f78a-2f68-9f82-2b4b10bb4d0b@oracle.com> <9f97d3e7-6ee9-2438-cbc9-747d185eb685@oracle.com> <44ed7e9d-41df-7a1f-1f2b-2ed69535579e@oracle.com> <06886e2d-ae0e-5e5a-7b89-1e86c0d44b72@oracle.com> <429ce897-92ae-bc22-943f-884ccc2d4476@oracle.com> <4306034a-d879-af16-eb92-91425abc3502@oracle.com> Message-ID: <922baab6-11d6-21fa-3ee7-ee007e00e64b@oracle.com> Cool! Feel free to include it in your MVT patch - so that we can avoid granting access to TypedCodeBuilder.state Maurizio On 28/06/17 17:44, Vladimir Ivanov wrote: > Yes, the patch fixes the bug I hit in GWT & loop intrinsics. Thanks! > > Best regards, > Vladimir Ivanov > > On 6/28/17 7:07 PM, Maurizio Cimadamore wrote: >> Could you please try this patch and tell me if that helps for the >> liveness trouble? >> >> Cheers >> Maurizio >> >> >> On 28/06/17 16:20, Vladimir Ivanov wrote: >>> >>> >>> Best regards, >>> Vladimir Ivanov >>> >>> On 6/28/17 6:00 PM, Maurizio Cimadamore wrote: >>>> >>>> >>>> On 28/06/17 15:36, Vladimir Ivanov wrote: >>>>> >>>>> >>>>> On 6/28/17 5:08 PM, Maurizio Cimadamore wrote: >>>>>> Great work Vlad; I have two questions before I dive in more details >>>>>> >>>>>> * why did you need to handle arrayLength() specially? Since an >>>>>> array is a reference, shouldn't it work already? >>>>> >>>>> It's a workaround for C2 crashes I observed when working with >>>>> arraylength method handle on Q-typed arrays. The problem for the >>>>> compiler is that the implementation uses >>>>> ArrayAccessor.lengthL(Object[]), so on bytecode level there's a >>>>> conflict between declared & actual type (DVT[] doesn't extend >>>>> Object[]). >>>>> >>>>> IMO the proper fix would be to have "erased" version for such >>>>> cases (or replace all primitive array specializations with a >>>>> single "erased" version): >>>>> >>>>> static int lengthL(java.lang.Object); >>>>> 0: aload_0 >>>>> 1: arraylength >>>>> 2: ireturn >>>>> >>>>> But it can't be expressed in Java language and requires bytecode >>>>> generation. >>>> OK - in other words, we need to specialize array length, because of >>>> the missing subtyping edge. Ugh. >>> >>> Yes. Moreover, I've just checked and the verifier complains about >>> non-array types on stack for arraylength instruction. >>> >>> Caused by: java.lang.VerifyError: Bad type on operand stack in >>> arraylength >>> Exception Details: >>> Location: >>> Test.length(Ljava/lang/Object;)I @1: arraylength >>> Reason: >>> Invalid type: 'java/lang/Object' (current frame, stack[0]) >>> Current Frame: >>> bci: @1 >>> flags: { } >>> locals: { 'java/lang/Object' } >>> stack: { 'java/lang/Object' } >>> >>> So, it seems longer term the only alternative to specialization is >>> Unsafe. >>> >>>>>> * Can you explain me exactly what you were trying to achieve with >>>>>> state.push/state.pop in the intrinsic generation? Typically the >>>>>> state is updated through opcodes - so, assuming you are >>>>>> generating bytecodes that make sense, you should not need this - >>>>>> unless there are bugs in the code builder (which is possible!) >>>>> >>>>> The following sequence usually hits the bug in the code builder: >>>>> builder.goto_("l1"); >>>>> builder.label("l2"); >>>>> >>>>> goto_() doesn't wipe the state, but the state at l2 doesn't relate >>>>> to the state when jumping to l1. It usually manifests as stack >>>>> depth or type mismatches when trying to merge the states in >>>>> builder.label(). >>>> I see - that's a well-known issue - the builder currently doesn't >>>> handle reachability. In your case, the builder should realize that >>>> code after 'goto' is dead, so it should just try to merge an empty >>>> state with the state of the code that is jumping to "l2" (of course >>>> this assumes that there's no other subsequent backward jump to "l2" >>>> otherwise the simple stackmap analysis implemented here would fail >>>> and you'll need some fix point calculation a la ASM). >>> >>> Yeah, backward jumps cause issues to one-pass solutions. >>> >>> Best regards, >>> Vladimir Ivanov >>> >>>>>> On 28/06/17 14:17, Vladimir Ivanov wrote: >>>>>>> Hi, >>>>>>> >>>>>>> I started playing with MVT-based vectors recently and want to >>>>>>> share my experience so far. >>>>>>> >>>>>>> For the first step, I decided to avoid specific treatment of >>>>>>> super-longs (Long2/4/8) in the JVM we have in Panama and just >>>>>>> mark them as VCCs for now: >>>>>>> @DeriveValueType >>>>>>> final class Long2 { public final long lo, hi; } >>>>>>> >>>>>>> As a test case I chose sum of array elements: >>>>>>> >>>>>>> long sum(QLong2[] va) { >>>>>>> QLong2 v = QLong2.default; // (0,0) >>>>>>> for (int i = 0; i < va.length; i++) { >>>>>>> QLong2 vi = va[i]; >>>>>>> v = QLong2(v.lo + vi.lo, v.hi + vi.hi); >>>>>>> } >>>>>>> return v.lo + v.hi; >>>>>>> } >>>>>>> >>>>>>> Here are the changes: >>>>>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/ >>>>>>> >>>>>>> >>>>>>> SUMMARY & RESULTS >>>>>>> >>>>>>> I hit some bugs along the way and had to extend the code for >>>>>>> Q-types in some places to get decent code shape generated. (I'll >>>>>>> shepherd the fixes in the repo separately.) I ended up with the >>>>>>> following generated code: >>>>>>> >>>>>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >>>>>>> >>>>>>> >>>>>>> Unfortunately, there are still 2 allocations left in the >>>>>>> generated code (out of 5 initially). C2 can't scalarize the >>>>>>> accumulator (v) inside the loop and has to put updated >>>>>>> components (lo & hi) in allocated heap buffer on every iteration >>>>>>> over the array (generated code [1], C2 EA output [2]). >>>>>>> >>>>>>> >>>>>>> GORY DETAILS >>>>>>> >>>>>>> hotspot/src/share/vm/opto/type.cpp >>>>>>> >>>>>>> * Type::get_typeflow_type() doesn't distinguish between >>>>>>> TypeValueTypePtr & TypeValueType >>>>>>> >>>>>>> >>>>>>> jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java >>>>>>> >>>>>>> >>>>>>> * introduced some LF intrinsics, e.g. LOOP and >>>>>>> SELECT_ALTERNATIVE; >>>>>>> >>>>>>> * had to workaround control flow-related bugs in the >>>>>>> bytecode library (jdk.experimental.bytecode): broken JVM state >>>>>>> after goto_() (see FIXME marks in the code); >>>>>>> >>>>>>> * fixed 2-slot types support: wrong local indexes were used >>>>>>> >>>>>>> >>>>>>> >>>>>>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java >>>>>>> >>>>>>> >>>>>>> * MHI.unboxResultHandle misses unboxing step for Q-types >>>>>>> >>>>>>> >>>>>>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java >>>>>>> jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java >>>>>>> >>>>>>> >>>>>>> * had to add a specialization for arraylength on Q-typed >>>>>>> array, because C2 can't handle arraylength Object[] when Q[] >>>>>>> instance is on stack; >>>>>>> >>>>>>> >>>>>>> jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: >>>>>>> >>>>>>> >>>>>>> * changes required to workaround goto_() bug >>>>>>> >>>>>>> * fixed CP patching support >>>>>>> >>>>>>> >>>>>>> jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java >>>>>>> >>>>>>> >>>>>>> * fixed CP patching support >>>>>>> >>>>>>> >>>>>>> hotspot/src/share/vm/memory/metachunk.hpp >>>>>>> hotspot/src/share/vm/oops/method.hpp >>>>>>> Fix optimized JVM build. >>>>>>> >>>>>>> Best regards, >>>>>>> Vladimir Ivanov >>>>>>> >>>>>>> [1] >>>>>>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log >>>>>>> >>>>>>> >>>>>>> ;; B7: # B8 <- B9 top-of-loop >>>>>>> >>>>>>> mov %r9,0x10(%rsp) >>>>>>> mov 0x8(%rsp),%r11d >>>>>>> >>>>>>> ;; B8: # B16 B9 <- B6 B7 Loop: B8-B7 inner >>>>>>> >>>>>>> mov %r11d,0x8(%rsp) >>>>>>> movabs $0x7c0060420,%rsi ; >>>>>>> {metadata('valhalla/vector/Long2$Value')} >>>>>>> ... >>>>>>> callq 0x0000000117579820 ; {runtime_call _new_instance_Java} >>>>>>> >>>>>>> ;; B9: # B7 B10 <- B8 >>>>>>> >>>>>>> mov %rax,%r9 >>>>>>> mov 0x10(%rsp),%r11 >>>>>>> mov 0x10(%r11),%r10 >>>>>>> mov 0x18(%r11),%r11 >>>>>>> movslq %ebp,%r8 >>>>>>> shl $0x4,%r8 >>>>>>> mov (%rsp),%rcx >>>>>>> mov 0x18(%rcx,%r8,1),%rax >>>>>>> mov 0x10(%rcx,%r8,1),%r8 ;*vaload >>>>>>> add %r11,%rax ;*ladd >>>>>>> mov %rax,0x18(%r9) >>>>>>> add %r10,%r8 ;*ladd >>>>>>> mov %r8,0x10(%r9) >>>>>>> inc %ebp ;*iadd >>>>>>> cmp 0x8(%rsp),%ebp >>>>>>> jl ;*if_icmpge >>>>>>> >>>>>>> [2] Pruned EA output (full output in the log) >>>>>>> ======== Connection graph for >>>>>>> valhalla.vector.VectorTest::sumArrayL2 >>>>>>> JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F >>>>>>> 1579F [ 1259 1264 532 1525 ]] 1247 Allocate >>>>>>> LocalVar [ 1247P [ 1264 ]] 1259 Proj ... #5 >>>>>>> LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]] 1264 >>>>>>> CheckCastPP ... #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >>>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >>>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>>> >>>>>>> JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]] 1136 Allocate >>>>>>> LocalVar [ 1136P [ 1153 ]] 1148 Proj ... #5 >>>>>>> LocalVar [ 1148 1136P [ 1154b ]] 1153 CheckCastPP ... >>>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>>> >>>>>>> JavaObject NoEscape(NoEscape) [ [ 1053 ]] 1041 Allocate >>>>>>> LocalVar [ 1041P [ ]] 1053 Proj ... #5 >>>>>>> >>>>>>> JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]] 633 Allocate >>>>>>> LocalVar [ 633P [ 650 ]] 645 Proj ... #5 >>>>>>> LocalVar [ 645 633P [ 653b 651b ]] 650 CheckCastPP ... >>>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>>> >>>>>>> JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 >>>>>>> 324 532 1525 ]] 307 Allocate >>>>>>> LocalVar [ 307P [ 324 ]] 319 Proj ... #5 >>>>>>> LocalVar [ 319 307P [ 532 1525 ]] 324 CheckCastPP ... >>>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]] 532 Phi ... >>>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]] 1525 Phi ... >>>>>>> #valuetype* valhalla/vector/Long2$Value:NotNull >>>>>>> >>>>>>> Scalar 1153 CheckCastPP ... #valuetype* >>>>>>> valhalla/vector/Long2$Value:NotNull >>>>>>> ++++ Eliminated: 1136 Allocate >>>>>>> Scalar 1041 Allocate ... >>>>>>> ++++ Eliminated: 1041 Allocate >>>>>>> Scalar 650 CheckCastPP ... #valuetype* >>>>>>> valhalla/vector/Long2$Value:NotNull >>>>>>> ++++ Eliminated: 633 Allocate >>>>>> >>>> >> From david.simms at oracle.com Thu Jun 29 08:58:36 2017 From: david.simms at oracle.com (David Simms) Date: Thu, 29 Jun 2017 10:58:36 +0200 Subject: RFR(S) 8182473: Optimize value type layout to max alignment of fields Message-ID: <885783bb-bdf2-355b-2760-113a0a2ec694@oracle.com> Hi all, Request for review: RFE: https://bugs.openjdk.java.net/browse/JDK-8182473 Webrev: http://cr.openjdk.java.net/~dsimms/valhalla/8182473/webrev0/ Here is a patch to remove the fixed "jlong" alignment from laying out values within object and values. The value type oop base offset remains aligned to "jlong", since "value type oops" are temporary holders, there is no real memory savings to be made otherwise. That is to say published values types in object fields are now no longer padded if no padding is required. Otherwise field layout will now try to coerce "small" value types (allocation type sized under NONSTATIC_DOUBLE) into one of other allocation types (NONSTATIC_BYTE, NONSTATIC_SHORT, NONSTATIC_WORD or NONSTATIC_OOP). The rest are laid out at the end of the instance jlong aligned as before (but these are variable jlong aligned size). Added basic sanity tests for layout involving value types. Generated layout combination testing needed when/if MVT users are enabled to declare value type fields in classes. JPRT, hotspot_tier1, and jdk_valhalla_mvt tests pass. /David Simms From tobias.hartmann at oracle.com Thu Jun 29 09:55:12 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Thu, 29 Jun 2017 11:55:12 +0200 Subject: RFR(S): 8183129: [MVT] Type::get_typeflow_type() doesn't distinguish between TypeValueTypePtr & TypeValueType Message-ID: Hi, please review the following patch: https://bugs.openjdk.java.net/browse/JDK-8183129 http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.26/ We crash during parsing due to mixing TypeValueType and TypeValueTypePtr. The problem is that typeflow analysis incorrectly sets the type of a PhiNode to TypeValueType instead of TypeValueTypePtr for a __Value argument used in a lambda form. When inlining a method handle intrinsic in CallGenerator::for_method_handle_inline() we should cast all arguments to their actual types but we miss the PhiNode because it's already of TypeValueType. We then fail in Parse::do_vunbox() because the input node is a Phi (and not a ValueTypeNode). We may also fail with a typesystem assert. I fixed typeflow analysis and added a regression test that triggers these problems by using MethodHandles.guardWithTest to merge __Value from two branches. I also added an assert to catch these problems earlier. This depends on the SELECT_ALTERNATIVE intrinsic (GWT) being implemented in the value type LambdaFormBuilder [1]. Thanks to Vladimir Ivanov for reporting this bug and finding the root cause! Best regards, Tobias [1] http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/jdk/webrev/ From vladimir.x.ivanov at oracle.com Thu Jun 29 11:46:59 2017 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Thu, 29 Jun 2017 14:46:59 +0300 Subject: RFR(S): 8183129: [MVT] Type::get_typeflow_type() doesn't distinguish between TypeValueTypePtr & TypeValueType In-Reply-To: References: Message-ID: <3a7e1e16-1904-c92f-641a-848a896e2771@oracle.com> Looks good. Best regards, Vladimir Ivanov On 6/29/17 12:55 PM, Tobias Hartmann wrote: > Hi, > > please review the following patch: > https://bugs.openjdk.java.net/browse/JDK-8183129 > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.26/ > > We crash during parsing due to mixing TypeValueType and TypeValueTypePtr. The problem is that typeflow analysis incorrectly sets the type of a PhiNode to TypeValueType instead of TypeValueTypePtr for a __Value argument used in a lambda form. When inlining a method handle intrinsic in CallGenerator::for_method_handle_inline() we should cast all arguments to their actual types but we miss the PhiNode because it's already of TypeValueType. We then fail in Parse::do_vunbox() because the input node is a Phi (and not a ValueTypeNode). We may also fail with a typesystem assert. > > I fixed typeflow analysis and added a regression test that triggers these problems by using MethodHandles.guardWithTest to merge __Value from two branches. I also added an assert to catch these problems earlier. This depends on the SELECT_ALTERNATIVE intrinsic (GWT) being implemented in the value type LambdaFormBuilder [1]. > > Thanks to Vladimir Ivanov for reporting this bug and finding the root cause! > > Best regards, > Tobias > > [1] http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/jdk/webrev/ > From tobias.hartmann at oracle.com Thu Jun 29 11:49:05 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Thu, 29 Jun 2017 13:49:05 +0200 Subject: RFR(S): 8183129: [MVT] Type::get_typeflow_type() doesn't distinguish between TypeValueTypePtr & TypeValueType In-Reply-To: <3a7e1e16-1904-c92f-641a-848a896e2771@oracle.com> References: <3a7e1e16-1904-c92f-641a-848a896e2771@oracle.com> Message-ID: <000e13f5-bc3f-d53b-6496-15fbf8ebb1d3@oracle.com> Thanks Vladimir. Best regards, Tobias On 29.06.2017 13:46, Vladimir Ivanov wrote: > Looks good. > > Best regards, > Vladimir Ivanov > > On 6/29/17 12:55 PM, Tobias Hartmann wrote: >> Hi, >> >> please review the following patch: >> https://bugs.openjdk.java.net/browse/JDK-8183129 >> http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.26/ >> >> We crash during parsing due to mixing TypeValueType and TypeValueTypePtr. The problem is that typeflow analysis incorrectly sets the type of a PhiNode to TypeValueType instead of TypeValueTypePtr for a __Value argument used in a lambda form. When inlining a method handle intrinsic in CallGenerator::for_method_handle_inline() we should cast all arguments to their actual types but we miss the PhiNode because it's already of TypeValueType. We then fail in Parse::do_vunbox() because the input node is a Phi (and not a ValueTypeNode). We may also fail with a typesystem assert. >> >> I fixed typeflow analysis and added a regression test that triggers these problems by using MethodHandles.guardWithTest to merge __Value from two branches. I also added an assert to catch these problems earlier. This depends on the SELECT_ALTERNATIVE intrinsic (GWT) being implemented in the value type LambdaFormBuilder [1]. >> >> Thanks to Vladimir Ivanov for reporting this bug and finding the root cause! >> >> Best regards, >> Tobias >> >> [1] http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/jdk/webrev/ >> From rwestrel at redhat.com Thu Jun 29 11:59:09 2017 From: rwestrel at redhat.com (Roland Westrelin) Date: Thu, 29 Jun 2017 13:59:09 +0200 Subject: RFR(S): 8183129: [MVT] Type::get_typeflow_type() doesn't distinguish between TypeValueTypePtr & TypeValueType In-Reply-To: References: Message-ID: > http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.26/ Look good to me. Roland. From tobias.hartmann at oracle.com Thu Jun 29 12:01:45 2017 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Thu, 29 Jun 2017 14:01:45 +0200 Subject: RFR(S): 8183129: [MVT] Type::get_typeflow_type() doesn't distinguish between TypeValueTypePtr & TypeValueType In-Reply-To: References: Message-ID: <0041569b-8fd5-c210-f9ef-a3d2cd76bd8b@oracle.com> Thanks Roland. Best regards, Tobias On 29.06.2017 13:59, Roland Westrelin wrote: > >> http://cr.openjdk.java.net/~thartmann/valhalla/vt_prototype/webrev.26/ > > Look good to me. > > Roland. > From david.simms at oracle.com Thu Jun 29 13:02:37 2017 From: david.simms at oracle.com (David Simms) Date: Thu, 29 Jun 2017 15:02:37 +0200 Subject: RFR: Implement value type buffering for the interpreter In-Reply-To: References: <3B3BE56F-D7DC-4963-8C86-C7D205426367@oracle.com> <74e220bc-18ad-83b0-22e0-88a9a3129fba@oracle.com> Message-ID: Brilliant, great work on the comments ! Push it ! /Mr. Simms On 26/06/17 19:11, Frederic Parain wrote: > Here's a new webrev: > > http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.02/index.html > > Changes: > > - fix parameter default value in global.hpp > - add comment about VTBufferChunk fields in vtBuffer.hpp > - add two new counters to track failed chunk allocations > > Thanks, > > Fred > > On 06/26/2017 10:40 AM, Frederic Parain wrote: >> Mr Simms, >> >> Thank you for the review. >> See my answers in-lined below. >> >> On 06/26/2017 10:04 AM, David Simms wrote: >>> >>> Kudos on the loop testing, like the targeted testing . Good work on >>> the static init fixes and testing. >>> >>> Minor comments: >>> >>> * globals.hpp:4097 "sizeof(long long)", is at least 64bits, but not >>> fixed size: do you mean BytesPerLong or longSize ? >> >> Changed to BytesPerLong. >> Eventually, this parameter would become a per-platform parameter, to >> take into account the instruction capabilities of each CPU. >> >>> * ValueTypesBufferMaxMemory=128, global fixed limit >>> o "doesn't feel right", but I admit to not having a better >>> answer. >>> Needs more user testing: TODO, we did talk off list about this, >>> discussed combination of global + per-thread options. >> >> I've delayed this work to push the VT buffering ASAP. >> Among the TODO list, I'd like to re-write the backend allocator to >> avoid fragmenting the memory. I'd like to implement the global/local >> limits we have discussed, but I need more usage data to tune them. >> >>> o Should "Global VTBuffer Pool statistics" include a failure >>> statistic to help with performance evaluation/tuning ? >> >> Nice suggestion. >> A global allocating failure counter could help detecting too small >> global buffer size. >> In addition, a per-thread allocation failure counter could help >> detecting unbalanced use of the global buffer memory. >> I'll implement it this week. >> >>> * vtBuffer.hpp:40 "_index;" - I can guess what all the other fields >>> are at a glance, but a short comment here would be nice >> >> Each thread builds its own linked list of VTBufferChunk. Having an >> index in each chunk indicating its position in the list enables >> optimizations when comparing the addresses of two buffered values >> (because buffer chunks are not contiguous, addresses cannot be >> compared directly). >> I'll add a comment about that. >> >>> I was wondering if "InterpreterFrameClosure" changes didn't trigger >>> a problem in the ValueOops whitebox testing (frame oop maps)...that >>> test feels a little on the fragile side. >> >> The modification of the InterpreterFrameClosure changes the way >> references to values are handled, but the oopmap themselves are >> not changed. Do you think this would cause an issue? >> >> Thanks, >> >> Fred >> >>> >>> On 20/06/17 22:50, Frederic Parain wrote: >>>> Greetings, >>>> >>>> Here's a webrev implementing value type buffering for the interpreter. >>>> >>>> http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.01/ >>>> >>>> Buffering allows the interpreter to allocate values in a thread local >>>> buffer to avoid Java heap allocations. Memory recycling is performed >>>> on method exit and sometimes on backward branches. >>>> >>>> Format of buffered values is almost identical to the format of >>>> Java heap allocated values, so most code won't see any difference >>>> between a buffered value and a not buffered value. The only difference >>>> is in the first word of the header. Because of a change in GC closures >>>> in JDK10, the first word now stores a reference to the Java mirror >>>> of the value class in order to keep it alive. In JDK9, this operation >>>> was performed through the klass pointer in the header, but the GC >>>> team has removed this closure. >>>> >>>> Buffering can be monitored using NMT or a new diagnostic command. >>>> >>>> All tests pass and Sergey has already tested the patch with his >>>> benchmark (and reported several bugs that are now fixed, thank >>>> you Sergey). >>>> >>>> Unfortunately, the changeset also includes a number of fixes not >>>> related to buffering, like code clean up and access to uninitialized >>>> static value fields. >>>> >>>> Thanks, >>>> >>>> Fred >>> >>> From frederic.parain at oracle.com Thu Jun 29 13:04:50 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Thu, 29 Jun 2017 09:04:50 -0400 Subject: RFR: Implement value type buffering for the interpreter In-Reply-To: References: <3B3BE56F-D7DC-4963-8C86-C7D205426367@oracle.com> <74e220bc-18ad-83b0-22e0-88a9a3129fba@oracle.com> Message-ID: <0C64D4D5-70BE-4052-9C6E-D0CEAC3C1495@oracle.com> Thank you! Fred > On Jun 29, 2017, at 09:02, David Simms wrote: > > > Brilliant, great work on the comments ! > > Push it ! > > /Mr. Simms > > > On 26/06/17 19:11, Frederic Parain wrote: >> Here's a new webrev: >> >> http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.02/index.html >> >> Changes: >> >> - fix parameter default value in global.hpp >> - add comment about VTBufferChunk fields in vtBuffer.hpp >> - add two new counters to track failed chunk allocations >> >> Thanks, >> >> Fred >> >> On 06/26/2017 10:40 AM, Frederic Parain wrote: >>> Mr Simms, >>> >>> Thank you for the review. >>> See my answers in-lined below. >>> >>> On 06/26/2017 10:04 AM, David Simms wrote: >>>> >>>> Kudos on the loop testing, like the targeted testing . Good work on the static init fixes and testing. >>>> >>>> Minor comments: >>>> >>>> * globals.hpp:4097 "sizeof(long long)", is at least 64bits, but not >>>> fixed size: do you mean BytesPerLong or longSize ? >>> >>> Changed to BytesPerLong. >>> Eventually, this parameter would become a per-platform parameter, to >>> take into account the instruction capabilities of each CPU. >>> >>>> * ValueTypesBufferMaxMemory=128, global fixed limit >>>> o "doesn't feel right", but I admit to not having a better answer. >>>> Needs more user testing: TODO, we did talk off list about this, >>>> discussed combination of global + per-thread options. >>> >>> I've delayed this work to push the VT buffering ASAP. >>> Among the TODO list, I'd like to re-write the backend allocator to >>> avoid fragmenting the memory. I'd like to implement the global/local >>> limits we have discussed, but I need more usage data to tune them. >>> >>>> o Should "Global VTBuffer Pool statistics" include a failure >>>> statistic to help with performance evaluation/tuning ? >>> >>> Nice suggestion. >>> A global allocating failure counter could help detecting too small >>> global buffer size. >>> In addition, a per-thread allocation failure counter could help >>> detecting unbalanced use of the global buffer memory. >>> I'll implement it this week. >>> >>>> * vtBuffer.hpp:40 "_index;" - I can guess what all the other fields >>>> are at a glance, but a short comment here would be nice >>> >>> Each thread builds its own linked list of VTBufferChunk. Having an >>> index in each chunk indicating its position in the list enables >>> optimizations when comparing the addresses of two buffered values >>> (because buffer chunks are not contiguous, addresses cannot be >>> compared directly). >>> I'll add a comment about that. >>> >>>> I was wondering if "InterpreterFrameClosure" changes didn't trigger a problem in the ValueOops whitebox testing (frame oop maps)...that test feels a little on the fragile side. >>> >>> The modification of the InterpreterFrameClosure changes the way >>> references to values are handled, but the oopmap themselves are >>> not changed. Do you think this would cause an issue? >>> >>> Thanks, >>> >>> Fred >>> >>>> >>>> On 20/06/17 22:50, Frederic Parain wrote: >>>>> Greetings, >>>>> >>>>> Here's a webrev implementing value type buffering for the interpreter. >>>>> >>>>> http://cr.openjdk.java.net/~fparain/vt-buffering/webrev.01/ >>>>> >>>>> Buffering allows the interpreter to allocate values in a thread local >>>>> buffer to avoid Java heap allocations. Memory recycling is performed >>>>> on method exit and sometimes on backward branches. >>>>> >>>>> Format of buffered values is almost identical to the format of >>>>> Java heap allocated values, so most code won't see any difference >>>>> between a buffered value and a not buffered value. The only difference >>>>> is in the first word of the header. Because of a change in GC closures >>>>> in JDK10, the first word now stores a reference to the Java mirror >>>>> of the value class in order to keep it alive. In JDK9, this operation >>>>> was performed through the klass pointer in the header, but the GC >>>>> team has removed this closure. >>>>> >>>>> Buffering can be monitored using NMT or a new diagnostic command. >>>>> >>>>> All tests pass and Sergey has already tested the patch with his >>>>> benchmark (and reported several bugs that are now fixed, thank >>>>> you Sergey). >>>>> >>>>> Unfortunately, the changeset also includes a number of fixes not >>>>> related to buffering, like code clean up and access to uninitialized >>>>> static value fields. >>>>> >>>>> Thanks, >>>>> >>>>> Fred >>>> >>>> > From frederic.parain at oracle.com Thu Jun 29 13:32:11 2017 From: frederic.parain at oracle.com (frederic.parain at oracle.com) Date: Thu, 29 Jun 2017 13:32:11 +0000 Subject: hg: valhalla/valhalla/hotspot: Value types off-heap buffering for the interpreter Message-ID: <201706291332.v5TDWBjl002804@aojmv0008.oracle.com> Changeset: 823e229a1ee5 Author: fparain Date: 2017-06-29 09:35 -0400 URL: http://hg.openjdk.java.net/valhalla/valhalla/hotspot/rev/823e229a1ee5 Value types off-heap buffering for the interpreter ! src/cpu/x86/vm/frame_x86.cpp ! src/cpu/x86/vm/frame_x86.hpp ! src/cpu/x86/vm/frame_x86.inline.hpp ! src/cpu/x86/vm/interp_masm_x86.cpp ! src/cpu/x86/vm/stubGenerator_x86_64.cpp ! src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp ! src/cpu/x86/vm/templateTable_x86.cpp ! src/share/vm/classfile/classFileParser.cpp ! src/share/vm/interpreter/interpreterRuntime.cpp ! src/share/vm/interpreter/interpreterRuntime.hpp ! src/share/vm/interpreter/oopMapCache.cpp ! src/share/vm/logging/logTag.hpp ! src/share/vm/memory/allocation.hpp ! src/share/vm/memory/allocation.inline.hpp ! src/share/vm/memory/iterator.hpp + src/share/vm/memory/vtBuffer.cpp + src/share/vm/memory/vtBuffer.hpp ! src/share/vm/oops/instanceKlass.cpp ! src/share/vm/oops/instanceKlass.hpp ! src/share/vm/oops/method.cpp ! src/share/vm/oops/method.hpp ! src/share/vm/oops/oop.inline.hpp ! src/share/vm/oops/valueKlass.cpp ! src/share/vm/oops/valueKlass.hpp ! src/share/vm/runtime/frame.cpp ! src/share/vm/runtime/frame.hpp ! src/share/vm/runtime/globals.hpp ! src/share/vm/runtime/handles.cpp ! src/share/vm/runtime/mutexLocker.cpp ! src/share/vm/runtime/sharedRuntime.cpp ! src/share/vm/runtime/thread.cpp ! src/share/vm/runtime/thread.hpp ! src/share/vm/runtime/vframeArray.cpp ! src/share/vm/runtime/vm_operations.cpp ! src/share/vm/runtime/vm_operations.hpp ! src/share/vm/services/diagnosticCommand.cpp ! src/share/vm/services/diagnosticCommand.hpp ! src/share/vm/services/nmtCommon.cpp + test/runtime/valhalla/valuetypes/UninitializedValueFieldsTest.java + test/runtime/valhalla/valuetypes/VTBufferTest.java + test/runtime/valhalla/valuetypes/ValueTypeGenerator.java ! test/runtime/valhalla/valuetypes/ValueTypeGetField.java From frederic.parain at oracle.com Thu Jun 29 16:45:36 2017 From: frederic.parain at oracle.com (Frederic Parain) Date: Thu, 29 Jun 2017 12:45:36 -0400 Subject: RFR(S) 8182473: Optimize value type layout to max alignment of fields In-Reply-To: <885783bb-bdf2-355b-2760-113a0a2ec694@oracle.com> References: <885783bb-bdf2-355b-2760-113a0a2ec694@oracle.com> Message-ID: <1473EE93-BA1F-47ED-B610-D9F5B801265B@oracle.com> Mr Simms, I?ve run the ValueTypeCreation test with -XX:+PrintValueLayout to see the layout of the different value types. Here?s the output: java.lang.__Value: field layout @ 16 --- instance fields start --- @ 16 --- instance fields end --- @ 16 --- instance ends --- @112 --- static fields start --- @112 --- static fields end --- OopMapBlocks: 0 / 0 runtime.valhalla.valuetypes.Point: field layout @ 16 --- instance fields start --- @ 16 "x" I @ 20 "y" I @ 24 --- instance fields end --- @ 24 --- instance ends --- @112 --- static fields start --- @112 --- static fields end --- OopMapBlocks: 0 / 0 runtime.valhalla.valuetypes.Long8Value: field layout @ 16 --- instance fields start --- @ 16 "longField1" J @ 24 "longField2" J @ 32 "longField3" J @ 40 "longField4" J @ 48 "longField5" J @ 56 "longField6" J @ 64 "longField7" J @ 72 "longField8" J @ 80 --- instance fields end --- @ 80 --- instance ends --- @112 --- static fields start --- @112 --- static fields end --- OopMapBlocks: 0 / 0 runtime.valhalla.valuetypes.Person: field layout @ 16 --- instance fields start --- @ 16 "id" I @ 20 "firstName" Ljava.lang.String; @ 24 "lastName" Ljava.lang.String; @ 32 --- instance fields end --- @ 32 --- instance ends --- @112 --- static fields start --- @112 --- static fields end --- OopMapBlocks: 1 / 2 Offset: 20 - 24 Count: 2 runtime.valhalla.valuetypes.ValueTypeCreation$SmallEmbed: field layout @ 16 --- instance fields start --- @ 16 "a" B @ 17 "b" B @ 20 --- instance fields end --- @ 24 --- instance ends --- @112 --- static fields start --- @112 --- static fields end --- OopMapBlocks: 0 / 0 runtime.valhalla.valuetypes.ValueTypeCreation$Composition: field layout @ 16 --- instance fields start --- @ 16 "a" S @ 18 "se" Qruntime.valhalla.valuetypes.ValueTypeCreation$SmallEmbed; @ 24 "long8Value" Qruntime.valhalla.valuetypes.Long8Value; @ 88 "person" Qruntime.valhalla.valuetypes.Person; @104 --- instance fields end --- @104 --- instance ends --- @112 --- static fields start --- @112 --- static fields end --- OopMapBlocks: 1 / 1 Offset: 92 - 96 Count: 2 runtime.valhalla.valuetypes.ValueTypeCreation$ValueHolder: field layout @ 12 --- instance fields start --- @ 16 "a" S @ 12 "b" I @ 18 "small" Qruntime.valhalla.valuetypes.ValueTypeCreation$SmallEmbed; @ 24 "comp" Qruntime.valhalla.valuetypes.ValueTypeCreation$Composition; @112 --- instance fields end --- @112 --- instance ends --- @112 --- static fields start --- @112 --- static fields end --- OopMapBlocks: 1 / 1 Offset: 100 -104 Count: 2 The layout of value type runtime.valhalla.valuetypes.Person doesn?t look optimal: it looks like there?s a gap between the end of the last field, lastName, which has a size of 4 bytes, and the end of the instance field area. I don?t know of this issue comes from your changes or if it was already there before, but as you?re working on the layout_fields() method, could you look at this issue? Thank you, Fred > On Jun 29, 2017, at 04:58, David Simms wrote: > > Hi all, > > Request for review: > > RFE: https://bugs.openjdk.java.net/browse/JDK-8182473 > > Webrev: http://cr.openjdk.java.net/~dsimms/valhalla/8182473/webrev0/ > > Here is a patch to remove the fixed "jlong" alignment from laying out values within object and values. > > The value type oop base offset remains aligned to "jlong", since "value type oops" are temporary holders, there is no real memory savings to be made otherwise. That is to say published values types in object fields are now no longer padded if no padding is required. > > Otherwise field layout will now try to coerce "small" value types (allocation type sized under NONSTATIC_DOUBLE) into one of other allocation types (NONSTATIC_BYTE, NONSTATIC_SHORT, NONSTATIC_WORD or NONSTATIC_OOP). The rest are laid out at the end of the instance jlong aligned as before (but these are variable jlong aligned size). > > Added basic sanity tests for layout involving value types. Generated layout combination testing needed when/if MVT users are enabled to declare value type fields in classes. > > JPRT, hotspot_tier1, and jdk_valhalla_mvt tests pass. > > /David Simms > From forax at univ-mlv.fr Thu Jun 29 19:05:44 2017 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 29 Jun 2017 21:05:44 +0200 (CEST) Subject: Integration of ASM 7 into the MVT In-Reply-To: <1816425461.3647817.1498310839354.JavaMail.zimbra@u-pem.fr> References: <1816425461.3647817.1498310839354.JavaMail.zimbra@u-pem.fr> Message-ID: <518013426.2484447.1498763144154.JavaMail.zimbra@u-pem.fr> (moving this discussion to valhalla-dev because it's not spec related) So after discussing with Maurizio in private, the plan is to do something perhaps less ambitious than what i was proposing :) The version that the jdk uses is ASM 5.1 with a specific modification in order to recognize the constant pool constants related to the module descriptor. Moving to ASM 7 is stricly not required to support the new v-opcodes, it can be done as a special branch compatible with ASM 5 with two caveats, in ASM 5.2 we have modified some pseudo opcodes that ASM uses internally and because those are opcodes, this work need to be integrated before introducing the new v-opcodes, then in order to avoid to have two heads, the patch that introduces the constant pool constants related to the module support can be removed and replaced by the code from ASM 6 that also allows the support of module. So i hope to soon propose a patch of the valhalla code that refactor the code of the JDK (apart from the ASM classes, i think the change should only modify the class jdk.internal.module.ClassFileAttributes, the package jdk.internal.module is nicely compartmentalized thanks to Alan Bateman) to align it with ASM without needing to migrate the JDK to ASM 6. Once this groundwork is done, introducing the v-opcodes can be done using the same code in the JDK and in ASM 7, so early adopters can use ASM 7 in their project knowing that the JDK will share the same code and that modifications will be synchronous between the two projects. regards, R?mi ----- Mail original ----- > De: "Remi Forax" > ?: valhalla-spec-experts at openjdk.java.net > Envoy?: Samedi 24 Juin 2017 15:27:19 > Objet: Integration of ASM 7 into the MVT > Hi all, > re-reading the spec, > http://cr.openjdk.java.net/~dlsmith/values.html > i've remarked that it seems that the spec is a forked from the JVMS 8 and not > JVMS 9. > > I'm planning to create an alpha release of ASM 7 by forking ASM 6 that does > already implement the JVMS 9 (from the Java Platform Module Spec), > i hope this is not an issue. > > Thinking a little more about that, there is an issue with integrating ASM 7 into > the valhalla repository, currently the code inside the JDK relies on ASM 5.1 > and not ASM 6. > The difference between ASM 6 and ASM 5 is that in ASM 5, the attribute "Module" > is seen as an unknown attribute so ASM ask the user code to provide a > description of the attribute, in ASM 6, ASM recognizes the attribute "Module" > and redirect all the info to a specific ModuleVisitor, so before to be able to > use ASM 7 with the new v-opcodes inside the JDK, i think that the JDK sources > has to be updated to use ASM 6 first. > > regards, > R?mi From maurizio.cimadamore at oracle.com Thu Jun 29 21:52:42 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 29 Jun 2017 22:52:42 +0100 Subject: Integration of ASM 7 into the MVT In-Reply-To: <518013426.2484447.1498763144154.JavaMail.zimbra@u-pem.fr> References: <1816425461.3647817.1498310839354.JavaMail.zimbra@u-pem.fr> <518013426.2484447.1498763144154.JavaMail.zimbra@u-pem.fr> Message-ID: <66411fd3-9e1d-41af-9e31-85680126ed3f@oracle.com> Sounds great - many thanks! Maurizio On 29/06/17 20:05, Remi Forax wrote: > (moving this discussion to valhalla-dev because it's not spec related) > > So after discussing with Maurizio in private, > the plan is to do something perhaps less ambitious than what i was proposing :) > > The version that the jdk uses is ASM 5.1 with a specific modification in order to recognize the constant pool constants related to the module descriptor. > Moving to ASM 7 is stricly not required to support the new v-opcodes, it can be done as a special branch compatible with ASM 5 with two caveats, > in ASM 5.2 we have modified some pseudo opcodes that ASM uses internally and because those are opcodes, this work need to be integrated before introducing the new v-opcodes, then in order to avoid to have two heads, the patch that introduces the constant pool constants related to the module support can be removed and replaced by the code from ASM 6 that also allows the support of module. > > So i hope to soon propose a patch of the valhalla code that refactor the code of the JDK (apart from the ASM classes, i think the change should only modify the class jdk.internal.module.ClassFileAttributes, the package jdk.internal.module is nicely compartmentalized thanks to Alan Bateman) to align it with ASM without needing to migrate the JDK to ASM 6. > > Once this groundwork is done, introducing the v-opcodes can be done using the same code in the JDK and in ASM 7, so early adopters can use ASM 7 in their project knowing that the JDK will share the same code and that modifications will be synchronous between the two projects. > > regards, > R?mi > > ----- Mail original ----- >> De: "Remi Forax" >> ?: valhalla-spec-experts at openjdk.java.net >> Envoy?: Samedi 24 Juin 2017 15:27:19 >> Objet: Integration of ASM 7 into the MVT >> Hi all, >> re-reading the spec, >> http://cr.openjdk.java.net/~dlsmith/values.html >> i've remarked that it seems that the spec is a forked from the JVMS 8 and not >> JVMS 9. >> >> I'm planning to create an alpha release of ASM 7 by forking ASM 6 that does >> already implement the JVMS 9 (from the Java Platform Module Spec), >> i hope this is not an issue. >> >> Thinking a little more about that, there is an issue with integrating ASM 7 into >> the valhalla repository, currently the code inside the JDK relies on ASM 5.1 >> and not ASM 6. >> The difference between ASM 6 and ASM 5 is that in ASM 5, the attribute "Module" >> is seen as an unknown attribute so ASM ask the user code to provide a >> description of the attribute, in ASM 6, ASM recognizes the attribute "Module" >> and redirect all the info to a specific ModuleVisitor, so before to be able to >> use ASM 7 with the new v-opcodes inside the JDK, i think that the JDK sources >> has to be updated to use ASM 6 first. >> >> regards, >> R?mi From paul.sandoz at oracle.com Fri Jun 30 00:42:06 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 29 Jun 2017 17:42:06 -0700 Subject: RFR 8183146 [MVT] Create composed vwithfield constructor Message-ID: Hi, Please review the following: http://cr.openjdk.java.net/~psandoz/valhalla/c-wither/webrev/ This adds a method, named unrefllectWithers for want of a better name, that given a number of fields can produce a method handle that applies vwithfield, in order with each Field. SO it should produce some tight byte code for the production of values, which then can be optimized by the JIT (e.g. if a default value is obtained and all fields are updated then the JIT could optimize away the zeroing associated with vdefault). This method is quite general, depending on the arguments passed in, it can reduce to an identity function, findWither, or defaultValueConstant, which suggests the latter two could defer to this method. Rather than accepting an array of Field[] it should perhaps be a LinkedHashMap>, or two distinct arrays of the same size, String[] and Class[]. In any case we need a way for the caller to specify the set of fields in a defined order. Paul. From maurizio.cimadamore at oracle.com Fri Jun 30 10:20:01 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 30 Jun 2017 11:20:01 +0100 Subject: RFR 8183146 [MVT] Create composed vwithfield constructor In-Reply-To: References: Message-ID: Looks good. I think even this could be expressed with a combinator; you need to walk field in reverse and repeatedly call mh = collectArguments(mh, 0, withfield). At the end of the process you get some MH whose type is QT1T2T3...Tn, where T1, T2, T3 ... Tn are the types of the fields. Now, if 'fromDefault' is set, you do another collectArgumemts(mh, 0, defaultConstantValue). If it is not set, you just leave the MH as is. That said, I have little clue as to what it's best for the VM to optimize - I suspect the combinator based one generates plenty of LFs under the hood, so might be more problematic than a single monolithic method? Maurizio On 30/06/17 01:42, Paul Sandoz wrote: > Hi, > > Please review the following: > > http://cr.openjdk.java.net/~psandoz/valhalla/c-wither/webrev/ > > This adds a method, named unrefllectWithers for want of a better name, that given a number of fields can produce a method handle that applies vwithfield, in order with each Field. SO it should produce some tight byte code for the production of values, which then can be optimized by the JIT (e.g. if a default value is obtained and all fields are updated then the JIT could optimize away the zeroing associated with vdefault). > > This method is quite general, depending on the arguments passed in, it can reduce to an identity function, findWither, or defaultValueConstant, which suggests the latter two could defer to this method. > > Rather than accepting an array of Field[] it should perhaps be a LinkedHashMap>, or two distinct arrays of the same size, String[] and Class[]. In any case we need a way for the caller to specify the set of fields in a defined order. > > Paul. > > From forax at univ-mlv.fr Fri Jun 30 11:15:08 2017 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 30 Jun 2017 13:15:08 +0200 (CEST) Subject: RFR 8183146 [MVT] Create composed vwithfield constructor In-Reply-To: References: Message-ID: <493648191.2847566.1498821308433.JavaMail.zimbra@u-pem.fr> Hi Paul, ----- Mail original ----- > De: "Paul Sandoz" > ?: "valhalla-dev" > Envoy?: Vendredi 30 Juin 2017 02:42:06 > Objet: RFR 8183146 [MVT] Create composed vwithfield constructor > Hi, > > Please review the following: > > http://cr.openjdk.java.net/~psandoz/valhalla/c-wither/webrev/ I think the doc comment should be // (F1, ..., Fn)Q, if fromDefault == true // (Q, F1, ..., Fn)Q, if fromDefault == false because the return value is a specific Q-type. and the last parameter types should be a varargs (Field... instead of a Field[]). > > This adds a method, named unrefllectWithers for want of a better name, that > given a number of fields can produce a method handle that applies vwithfield, > in order with each Field. SO it should produce some tight byte code for the > production of values, which then can be optimized by the JIT (e.g. if a default > value is obtained and all fields are updated then the JIT could optimize away > the zeroing associated with vdefault). given that you can bind the result of vdefault, i'm not sure you need the boolean fromDefault. > > This method is quite general, depending on the arguments passed in, it can > reduce to an identity function, findWither, or defaultValueConstant, which > suggests the latter two could defer to this method. > > Rather than accepting an array of Field[] it should perhaps be a > LinkedHashMap>, or two distinct arrays of the same size, > String[] and Class[]. In any case we need a way for the caller to specify the > set of fields in a defined order. This method is the underlying method you need to implement chip pattern matching extractor, (i'm sure i'm not the only one to have thought about that :) ) for that use case, the values will comes as fields from a call to getDeclaredFields() (with a permutation in between). > > Paul. R?mi From maurizio.cimadamore at oracle.com Fri Jun 30 15:16:30 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 30 Jun 2017 16:16:30 +0100 Subject: RFR 8183290: [MVT] ClassInfo mangling doesn't work on DVT Message-ID: <86861da8-d9b5-2e7f-e713-da829426c557@oracle.com> Hi, this is a simple fix for a bug uncovered by Lois: name mangling of ClassInfo doesn't work on DVT generation. That's because that code doesn't use MethodHandleBuilder. I've consolidated the code a bit - now mangling happens in MinimalValueTypes_1_0 (static method), and MethodHandleBuilder just calls that. This allows for dealing with runtime properties only in one place. http://cr.openjdk.java.net/~mcimadamore/8183290/ Cheers Maurizio From maurizio.cimadamore at oracle.com Fri Jun 30 15:56:18 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 30 Jun 2017 16:56:18 +0100 Subject: not enough space for interpreter generation Message-ID: <0aa0b893-6d89-b5b1-df0f-3fbf64cbb572@oracle.com> Hi, I'm running into this: https://bugs.openjdk.java.net/browse/JDK-8166317 when debugging code - is there any workaround? (even a patch would be fine) Thanks Maurizio From maurizio.cimadamore at oracle.com Fri Jun 30 15:58:04 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 30 Jun 2017 16:58:04 +0100 Subject: not enough space for interpreter generation In-Reply-To: <0aa0b893-6d89-b5b1-df0f-3fbf64cbb572@oracle.com> References: <0aa0b893-6d89-b5b1-df0f-3fbf64cbb572@oracle.com> Message-ID: <852b3aea-4acf-41ac-4a4d-2a3974790f92@oracle.com> NMV - found it: // Size of interpreter code. Increase if too small. Interpreter will // fail with a guarantee ("not enough space for interpreter generation"); // if too small. // Run with +PrintInterpreter to get the VM to print out the size. // Max size with JVMTI int TemplateInterpreter::InterpreterCodeSize = 300 * 1024; Maurizio On 30/06/17 16:56, Maurizio Cimadamore wrote: > Hi, > I'm running into this: > > https://bugs.openjdk.java.net/browse/JDK-8166317 > > when debugging code - is there any workaround? (even a patch would be > fine) > > Thanks > Maurizio > > From paul.sandoz at oracle.com Fri Jun 30 16:15:18 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 30 Jun 2017 09:15:18 -0700 Subject: RFR 8183146 [MVT] Create composed vwithfield constructor In-Reply-To: References: Message-ID: <8B2D5B06-C251-4695-88ED-177DF4773C10@oracle.com> > On 30 Jun 2017, at 03:20, Maurizio Cimadamore wrote: > > Looks good. > Thanks. > I think even this could be expressed with a combinator; you need to walk field in reverse and repeatedly call mh = collectArguments(mh, 0, withfield). At the end of the process you get some MH whose type is QT1T2T3...Tn, where T1, T2, T3 ... Tn are the types of the fields. Now, if 'fromDefault' is set, you do another collectArgumemts(mh, 0, defaultConstantValue). If it is not set, you just leave the MH as is. > It?s possible to do that, as Vladimir did in his recent patch. I was concerned that we may have a limited budget for LFs and it would be better for the developer to spend that budget on their own combinators. > That said, I have little clue as to what it's best for the VM to optimize - I suspect the combinator based one generates plenty of LFs under the hood, so might be more problematic than a single monolithic method? > Yes, the VM is remarkably effective at folding away the MH invocations but in this case i think we can help with more focused code (a bit like the existing intrinsics already do, and i wonder if later on we could make intrinsic the wither functionality). Paul. From paul.sandoz at oracle.com Fri Jun 30 16:26:22 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 30 Jun 2017 09:26:22 -0700 Subject: RFR 8183146 [MVT] Create composed vwithfield constructor In-Reply-To: <493648191.2847566.1498821308433.JavaMail.zimbra@u-pem.fr> References: <493648191.2847566.1498821308433.JavaMail.zimbra@u-pem.fr> Message-ID: <0C168C0C-7273-439F-B2E9-DD8CBE10A278@oracle.com> > On 30 Jun 2017, at 04:15, Remi Forax wrote: > > Hi Paul, > > ----- Mail original ----- >> De: "Paul Sandoz" >> ?: "valhalla-dev" >> Envoy?: Vendredi 30 Juin 2017 02:42:06 >> Objet: RFR 8183146 [MVT] Create composed vwithfield constructor > >> Hi, >> >> Please review the following: >> >> http://cr.openjdk.java.net/~psandoz/valhalla/c-wither/webrev/ > > > I think the doc comment should be > > // (F1, ..., Fn)Q, if fromDefault == true > // (Q, F1, ..., Fn)Q, if fromDefault == false > > because the return value is a specific Q-type. > Ok. > and the last parameter types should be a varargs (Field... instead of a Field[]). > Ok. >> >> This adds a method, named unrefllectWithers for want of a better name, that >> given a number of fields can produce a method handle that applies vwithfield, >> in order with each Field. SO it should produce some tight byte code for the >> production of values, which then can be optimized by the JIT (e.g. if a default >> value is obtained and all fields are updated then the JIT could optimize away >> the zeroing associated with vdefault). > > given that you can bind the result of vdefault, i'm not sure you need the boolean fromDefault. > I don?t wanna box the result of vdefault in a bound method handle, there are certainly other ways (like with collectArguments used in the test), but i want the byte code to be really ?tight? so the VM can optimize the vdefault + vwithfield* pattern really well. >> >> This method is quite general, depending on the arguments passed in, it can >> reduce to an identity function, findWither, or defaultValueConstant, which >> suggests the latter two could defer to this method. >> >> Rather than accepting an array of Field[] it should perhaps be a >> LinkedHashMap>, or two distinct arrays of the same size, >> String[] and Class[]. In any case we need a way for the caller to specify the >> set of fields in a defined order. > > This method is the underlying method you need to implement chip pattern matching extractor, > (i'm sure i'm not the only one to have thought about that :) ) > for that use case, the values will comes as fields from a call to getDeclaredFields() (with a permutation in between). > Good point. Paul. From paul.sandoz at oracle.com Fri Jun 30 21:35:56 2017 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 30 Jun 2017 14:35:56 -0700 Subject: RFR 8183290: [MVT] ClassInfo mangling doesn't work on DVT In-Reply-To: <86861da8-d9b5-2e7f-e713-da829426c557@oracle.com> References: <86861da8-d9b5-2e7f-e713-da829426c557@oracle.com> Message-ID: <1E51BFDD-ACB1-4508-B78B-969931D0E6A7@oracle.com> +1 Paul. > On 30 Jun 2017, at 08:16, Maurizio Cimadamore wrote: > > Hi, > this is a simple fix for a bug uncovered by Lois: name mangling of ClassInfo doesn't work on DVT generation. That's because that code doesn't use MethodHandleBuilder. > > I've consolidated the code a bit - now mangling happens in MinimalValueTypes_1_0 (static method), and MethodHandleBuilder just calls that. This allows for dealing with runtime properties only in one place. > > http://cr.openjdk.java.net/~mcimadamore/8183290/ > > Cheers > Maurizio > From paul.sandoz at oracle.com Fri Jun 30 22:42:09 2017 From: paul.sandoz at oracle.com (paul.sandoz at oracle.com) Date: Fri, 30 Jun 2017 22:42:09 +0000 Subject: hg: valhalla/valhalla/jdk: Unreflect on an array of Field of a VCC to, in order, Message-ID: <201706302242.v5UMg975006164@aojmv0008.oracle.com> Changeset: c5e50d0c07b7 Author: psandoz Date: 2017-06-30 14:27 -0700 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/c5e50d0c07b7 Unreflect on an array of Field of a VCC to, in order, apply vwithfield to each Field with a given value. The initial value can either be the default or passed in as the first argument. ! src/java.base/share/classes/jdk/experimental/value/ValueType.java + test/valhalla/mvt/UnreflectWithersTest.java