From tobias.hartmann at oracle.com Thu Apr 1 07:25:52 2021 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Thu, 1 Apr 2021 09:25:52 +0200 Subject: Question about tearing and buffered primitive classes In-Reply-To: <85sg4csz3r.fsf@nicgas01-pc.shanghai.arm.com> References: <85sg4csz3r.fsf@nicgas01-pc.shanghai.arm.com> Message-ID: Hi Nick, Thanks for looking into this! On 30.03.21 12:41, Nick Gasson wrote: > However based on my reading of the description in JDK-8237741 [1] this > should only be necessary when the object is passed by invisible > reference, not when it's actually flattened. In Tobias' fix for > JDK-8238780 [2] a store-store barrier was added to C2's > InlineTypeBaseNode::buffer() but I can't see where the equivalent > "buffering" happens in C1. C2 does aggressive scalarization and therefore needs to buffer at various places when a reference is required. C1 buffers only after reading from a flat representation, for example in GraphBuilder::access_field (see NewInlineTypeInstance -> copy_inline_content). That said, I'm wondering if a store-store barrier is needed there as well. > Furthermore I don't understand why we can't instead rely on the barrier > that gets added before returning from a constructor that writes final > fields? AIUI a primitive class's fields are always final and `this' > can't escape its constructor so the effect should be the same as putting > a barrier after each intermediate allocation inside the constructor. > > GraphBuilder::withfield() calls set_wrote_final() which is used for this > purpose *but* in GraphBuilder::method_return() we don't set need_mem_bar > because method()->is_object_constructor() is false for primitive class > constructors. So a different patch that also fixes this test case is: Yes, I think this is the correct fix: > diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp > index ead767f596d7..ac7e4ce5f06d 100644 > --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp > +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp > @@ -1617,7 +1617,7 @@ void GraphBuilder::method_return(Value x, bool ignore_return) { > > // The conditions for a memory barrier are described in Parse::do_exits(). > bool need_mem_bar = false; > - if (method()->is_object_constructor() && > + if ((method()->is_object_constructor() || method()->is_static_init_factory()) && > (scope()->wrote_final() || > (AlwaysSafeConstructors && scope()->wrote_fields()) || > (support_IRIW_for_not_multiple_copy_atomic_cpu && scope()->wrote_volatile()))) { The is_static_init_factory check is simply missing there. Best regards, Tobias From sadayapalam at openjdk.java.net Thu Apr 1 07:54:29 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Thu, 1 Apr 2021 07:54:29 GMT Subject: [lworld] RFR: 8264216: [lworld] unknown.Class.default gives misleading compilation error [v2] In-Reply-To: <4If7lnUu6w6t8qkC7WImgBDWPdK4JVWLv2SWvCb_8_0=.c9583a58-9828-496f-8189-1d8037af953d@github.com> References: <4If7lnUu6w6t8qkC7WImgBDWPdK4JVWLv2SWvCb_8_0=.c9583a58-9828-496f-8189-1d8037af953d@github.com> Message-ID: On Wed, 31 Mar 2021 13:13:50 GMT, Jesper Steen M?ller wrote: >> Make the compilation error for `somepkgname.UnknownClass.default` as informative as `UnknownClass.default`. > > Jesper Steen M?ller has updated the pull request incrementally with one additional commit since the last revision: > > Address review comments Changes look good. Thanks Jesper! ------------- Marked as reviewed by sadayapalam (Committer). PR: https://git.openjdk.java.net/valhalla/pull/372 From nick.gasson at arm.com Thu Apr 1 07:54:29 2021 From: nick.gasson at arm.com (Nick Gasson) Date: Thu, 01 Apr 2021 15:54:29 +0800 Subject: Question about tearing and buffered primitive classes In-Reply-To: References: <85sg4csz3r.fsf@nicgas01-pc.shanghai.arm.com> Message-ID: <85pmzesami.fsf@nicgas01-pc.shanghai.arm.com> Hi Tobias, Thanks for the feedback. On 01/04/21 15:25 pm, Tobias Hartmann wrote: > > Yes, I think this is the correct fix: > >> diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp >> index ead767f596d7..ac7e4ce5f06d 100644 >> --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp >> +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp >> @@ -1617,7 +1617,7 @@ void GraphBuilder::method_return(Value x, bool ignore_return) { >> >> // The conditions for a memory barrier are described in Parse::do_exits(). >> bool need_mem_bar = false; >> - if (method()->is_object_constructor() && >> + if ((method()->is_object_constructor() || method()->is_static_init_factory()) && >> (scope()->wrote_final() || >> (AlwaysSafeConstructors && scope()->wrote_fields()) || >> (support_IRIW_for_not_multiple_copy_atomic_cpu && scope()->wrote_volatile()))) { > > The is_static_init_factory check is simply missing there. > I'll make a PR for this shortly. Do you think C2's Parse::do_exits() needs the same fix? At the moment it only checks is_object_constructor_or_class_initializer(). (Is there a reason C1 doesn't insert the barrier for class initialisers?) -- Thanks, Nick From sadayapalam at openjdk.java.net Thu Apr 1 08:28:01 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Thu, 1 Apr 2021 08:28:01 GMT Subject: git: openjdk/valhalla: lworld: 8264216: [lworld] unknown.Class.default gives misleading compilation error Message-ID: <5d616ce1-e14f-40e2-b5fa-fa5068af58d0@openjdk.org> Changeset: 28a4ec02 Author: Jesper Steen M?ller Committer: Srikanth Adayapalam Date: 2021-04-01 08:27:37 +0000 URL: https://git.openjdk.java.net/valhalla/commit/28a4ec02 8264216: [lworld] unknown.Class.default gives misleading compilation error Reviewed-by: sadayapalam ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java + test/langtools/tools/javac/valhalla/lworld-values/UnknownTypeDefault.java + test/langtools/tools/javac/valhalla/lworld-values/UnknownTypeDefault.out From jespersm at openjdk.java.net Thu Apr 1 08:30:40 2021 From: jespersm at openjdk.java.net (Jesper Steen =?UTF-8?B?TcO4bGxlcg==?=) Date: Thu, 1 Apr 2021 08:30:40 GMT Subject: [lworld] Integrated: 8264216: [lworld] unknown.Class.default gives misleading compilation error In-Reply-To: References: Message-ID: On Fri, 26 Mar 2021 07:49:37 GMT, Jesper Steen M?ller wrote: > Make the compilation error for `somepkgname.UnknownClass.default` as informative as `UnknownClass.default`. This pull request has now been integrated. Changeset: 28a4ec02 Author: Jesper Steen M?ller Committer: Srikanth Adayapalam URL: https://git.openjdk.java.net/valhalla/commit/28a4ec02 Stats: 24 lines in 3 files changed: 22 ins; 0 del; 2 mod 8264216: [lworld] unknown.Class.default gives misleading compilation error Reviewed-by: sadayapalam ------------- PR: https://git.openjdk.java.net/valhalla/pull/372 From ngasson at openjdk.java.net Thu Apr 1 10:14:51 2021 From: ngasson at openjdk.java.net (Nick Gasson) Date: Thu, 1 Apr 2021 10:14:51 GMT Subject: [lworld] RFR: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 Message-ID: We see failures like this on AArch64 when MyValue.incrementAndCheck() is compiled with C1: java.lang.RuntimeException: Inconsistent field values: expected 0 to equal 675128 at jdk.test.lib.Asserts.fail(Asserts.java:594) at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) at jdk.test.lib.Asserts.assertEQ(Asserts.java:178) at compiler.valhalla.inlinetypes.MyValue.incrementAndCheck(TestBufferTearing.java:81) at compiler.valhalla.inlinetypes.TestBufferTearing$Runner.run(TestBufferTearing.java:124) The barrier that is usually inserted on return from a method that wrote final fields should be sufficient to prevent another thread seeing the zero-initialised intermediate state. However this barrier isn't inserted at the moment because method()->is_object_constructor() is false for primitive class constructors. C2 has a similar guard around the memory barrier in Parse::do_exits(). I'm not sure if that needs amending as well but I've not seen any failures due to it. ------------- Commit messages: - 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 Changes: https://git.openjdk.java.net/valhalla/pull/376/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=376&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8264414 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.java.net/valhalla/pull/376.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/376/head:pull/376 PR: https://git.openjdk.java.net/valhalla/pull/376 From tobias.hartmann at oracle.com Thu Apr 1 12:43:25 2021 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Thu, 1 Apr 2021 14:43:25 +0200 Subject: [External] : Re: Question about tearing and buffered primitive classes In-Reply-To: <85pmzesami.fsf@nicgas01-pc.shanghai.arm.com> References: <85sg4csz3r.fsf@nicgas01-pc.shanghai.arm.com> <85pmzesami.fsf@nicgas01-pc.shanghai.arm.com> Message-ID: <00236352-54da-b461-1018-433fea3acb84@oracle.com> On 01.04.21 09:54, Nick Gasson wrote: > I'll make a PR for this shortly. Do you think C2's Parse::do_exits() > needs the same fix? At the moment it only checks > is_object_constructor_or_class_initializer(). I don't think that's required for C2 because we add a barrier whenever we buffer a primitive class. > (Is there a reason C1 doesn't insert the barrier for class initialisers?) That's a good question. I'm not sure but it's the same in mainline. Best regards, Tobias From thartmann at openjdk.java.net Thu Apr 1 12:55:39 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Thu, 1 Apr 2021 12:55:39 GMT Subject: [lworld] RFR: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 In-Reply-To: References: Message-ID: On Thu, 1 Apr 2021 10:08:45 GMT, Nick Gasson wrote: > We see failures like this on AArch64 when MyValue.incrementAndCheck() is > compiled with C1: > > java.lang.RuntimeException: Inconsistent field values: expected 0 to equal 675128 > at jdk.test.lib.Asserts.fail(Asserts.java:594) > at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) > at jdk.test.lib.Asserts.assertEQ(Asserts.java:178) > at compiler.valhalla.inlinetypes.MyValue.incrementAndCheck(TestBufferTearing.java:81) > at compiler.valhalla.inlinetypes.TestBufferTearing$Runner.run(TestBufferTearing.java:124) > > The barrier that is usually inserted on return from a method that wrote > final fields should be sufficient to prevent another thread seeing the > zero-initialised intermediate state. However this barrier isn't > inserted at the moment because method()->is_object_constructor() is > false for primitive class constructors. > > C2 has a similar guard around the memory barrier in Parse::do_exits(). > I'm not sure if that needs amending as well but I've not seen any > failures due to it. Hi Nick, I think we also need a barrier in `GraphBuilder::access_field` when loading from a flattened field and in `GraphBuilder::load_indexed` (the initialization code is emitted in `LIRGenerator::access_flattened_array`) when loading from a flattened array. It would be good to have tests that triggers this. Best regards, Tobias ------------- PR: https://git.openjdk.java.net/valhalla/pull/376 From mcimadamore at openjdk.java.net Thu Apr 1 15:55:38 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Thu, 1 Apr 2021 15:55:38 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol In-Reply-To: References: Message-ID: On Wed, 31 Mar 2021 12:32:04 GMT, Srikanth Adayapalam wrote: > This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. This seems like a good cleanup overall. IMHO the issues can be bucketized as follows: * some more experiment is required to see if we can avoid changing asSuper too much * there is a bigger issue (which we'll have to confront with, sooner or later, because of specialization) regarding type erasure kicking in too early, and subsequent pipeline steps only dealing with symbol (not type) info Since the approach moves things in the way generic types are modeled, I'm not surprised to see some of the issues I had to face when writing a backend for the specializer compiler pop back here. I'd say, for now, let's try to deal with the first bullet (which is localized with these changes), and let's come back (in a separate PR) with some workaround for the second bullet (perhaps borrowing some old valhalla code?). src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2202: > 2200: * @param s a type > 2201: */ > 2202: public Type asSuper(Type t, Type s) { A possible approach here (discussed offline) would be to leave asSuper as it is today - e.g. assume that asSuper speaks about "extends/implements" clause, and deal with .ref vs. .val mismatches at the callsite (if possible) - e.g. in Types::isSubtypes. src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2572: > 2570: public Type visitClassType(ClassType t, Boolean recurse) { > 2571: // erasure(projection(primitive)) = projection(erasure(primitive)) > 2572: Type erased = eraseClassType(t, recurse); Random non-code comment: this seems a case of erasure applied to early. The first time that happens in lworld, but in the old branch which featured generic specializations, at some point we decided to postpone type erasure, as we needed sharp generic types during code gen. This smells like more of the same - e.g. having to fight with erasure so that the info that we care about is preserved in some form. src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java line 552: > 550: > 551: case ';': { // end > 552: name = names.fromUtf(signatureBuffer, This is another bit which might get simpler if we end up generating only a single .class. src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java line 1540: > 1538: > 1539: // where > 1540: private static ClassSymbol getReferenceProjection(ClassSymbol c) { Maybe one day we will be able to remove this... ------------- PR: https://git.openjdk.java.net/valhalla/pull/375 From mcimadamore at openjdk.java.net Thu Apr 1 15:55:39 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Thu, 1 Apr 2021 15:55:39 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol In-Reply-To: References: Message-ID: On Thu, 1 Apr 2021 15:36:05 GMT, Maurizio Cimadamore wrote: >> This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2572: > >> 2570: public Type visitClassType(ClassType t, Boolean recurse) { >> 2571: // erasure(projection(primitive)) = projection(erasure(primitive)) >> 2572: Type erased = eraseClassType(t, recurse); > > Random non-code comment: this seems a case of erasure applied to early. The first time that happens in lworld, but in the old branch which featured generic specializations, at some point we decided to postpone type erasure, as we needed sharp generic types during code gen. This smells like more of the same - e.g. having to fight with erasure so that the info that we care about is preserved in some form. There is also the issue that, no matter how delayed erasure is, at the moment we need to generate two different class artifacts, so, at some point the symbol duality is going to pop back up; that's understandable - hopefully we'll come up with a strategy which doesn't require javac to generate two artifacts - at which point javac can simply insert conversions when going from L to Q - and mostly be done with it (of course to generate such conversions it will need access to full type info - see above). ------------- PR: https://git.openjdk.java.net/valhalla/pull/375 From mcimadamore at openjdk.java.net Thu Apr 1 15:55:40 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Thu, 1 Apr 2021 15:55:40 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol In-Reply-To: References: Message-ID: <_xclMgfi5gzm1iZu2kD2IwKgjMOTcXcU-IOGFpVOJ0E=.55da3e90-8ada-41b2-9b32-0f565c7629c2@github.com> On Wed, 31 Mar 2021 12:44:17 GMT, Srikanth Adayapalam wrote: >> This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java line 373: > >> 371: JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field), >> 372: sym.name, >> 373: make.QualIdent(lambdaType.getReturnType().tsym).setType(lambdaType.getReturnType()), > > Discussion item:This spot indicates one of the pain points in the new approach, There are lots of places where we construct fresh AST nodes from a symbol and in the process decorate the AST's type from what we see in the symbol. This is not a problem for parameterized types because the type arguments are erased by TransTypes anyway. But with Foo.ref and Foo.val sharing the same symbol, we will loose reference "projection'ness". I would like to discuss if there are mechanical ways to detect and prevent such loss of type information. ATM, I am dependent on tests breaking to expose such problems and this is dependent heavily on coverage and coverage is still in infancy Again, my test here is this: suppose that here we weren't talking about Point.ref/Point.val - but, instead of List vs. List. Would anything be different? I don't think so. What you are observing is the result of a "wrong" assumption made by the code - or, rather, an assumption that "used to" be true, but is no longer. That is, this code (and code like this spread all over javac) assumes that we can safely ignore type info once we're past the frontend, as code generation is only expressed in terms of erased types (which are also the types attached to the symbol). This assumption is starting to crumble now, and will come crashing down when specialized generics are introduced. So I see this as technical debt (e.g. javac throwing aways types and dealing with symbols too early) as opposed to a specific limitation of the patch proposed in this PR. To get a cleaner fix, we should fix the underlying problem (eager erasure). ------------- PR: https://git.openjdk.java.net/valhalla/pull/375 From sadayapalam at openjdk.java.net Mon Apr 5 05:14:30 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Mon, 5 Apr 2021 05:14:30 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v2] In-Reply-To: References: Message-ID: > This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. Srikanth Adayapalam has updated the pull request incrementally with one additional commit since the last revision: 8264216: [lworld] unknown.Class.default gives misleading compilation error Reviewed-by: sadayapalam ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/375/files - new: https://git.openjdk.java.net/valhalla/pull/375/files/406f61e6..725652b8 Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=01 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=00-01 Stats: 24 lines in 3 files changed: 22 ins; 0 del; 2 mod Patch: https://git.openjdk.java.net/valhalla/pull/375.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/375/head:pull/375 PR: https://git.openjdk.java.net/valhalla/pull/375 From sadayapalam at openjdk.java.net Mon Apr 5 05:42:54 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Mon, 5 Apr 2021 05:42:54 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v3] In-Reply-To: References: Message-ID: > This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. Srikanth Adayapalam has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/375/files - new: https://git.openjdk.java.net/valhalla/pull/375/files/725652b8..406f61e6 Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=02 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=01-02 Stats: 24 lines in 3 files changed: 0 ins; 22 del; 2 mod Patch: https://git.openjdk.java.net/valhalla/pull/375.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/375/head:pull/375 PR: https://git.openjdk.java.net/valhalla/pull/375 From sadayapalam at openjdk.java.net Mon Apr 5 05:48:12 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Mon, 5 Apr 2021 05:48:12 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v4] In-Reply-To: References: Message-ID: > This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. Srikanth Adayapalam has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains seven additional commits since the last revision: - Merge branch 'lworld' into JDK-8244227 - Various changes to handle projections sharing a symbol/not having their own symbols - Introducce another variant of Types.asSuper to operate on Type's so as not to confuse reference projection types with value projection types in a world where they share the same symbol. - Nestmates and innerclasses attribute generation, classfile creation, signature management ... - Genesis, construction, preservation and propagation of reference projection type - Get out of the business of having to maintain the doppleganger symbol in sync with original - In diagnostics and debug strings while mentioning projection types, use .ref/.val rather than $ref/$val ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/375/files - new: https://git.openjdk.java.net/valhalla/pull/375/files/406f61e6..42fefb15 Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=03 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=02-03 Stats: 24 lines in 3 files changed: 22 ins; 0 del; 2 mod Patch: https://git.openjdk.java.net/valhalla/pull/375.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/375/head:pull/375 PR: https://git.openjdk.java.net/valhalla/pull/375 From thartmann at openjdk.java.net Tue Apr 6 12:45:53 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Tue, 6 Apr 2021 12:45:53 GMT Subject: [lworld] RFR: 8264586: [lworld] C2 compilation fails due to infinite loop in PhaseIterGVN::optimize Message-ID: The problem is an `InlineTypePtrNode` that becomes dead after CCP removes a redundant null check and then keeps several other nodes alive. Since we don't run any loop opts anymore after CCP, the dead subgraph is not removed and the dead nodes are also not re-processed by `PhaseCCP::transform_once` to update their bottom types. As a result, two `LoadNodes` only used by a `ValueTypePtrNode` end up with types that are inconsistent with their bottom types and are re-enqueued for IGVN indefinitely by this code: https://github.com/openjdk/valhalla/blob/28a4ec0249fd86fe17f2b816c6f5f8eed31abfeb/src/hotspot/share/opto/memnode.cpp#L352-L358 I think we should aggressively remove `InlineTypePtrNodes` if they are no longer needed to keep track of the individual field values. I've added an Ideal transformation to take care of that. The patch also includes a fix for an unrelated "Control flow was added although the intrinsic bailed out" failure and some cleanup/refactoring. Thanks, Tobias ------------- Commit messages: - 8264586: [lworld] C2 compilation fails due to infinite loop in PhaseIterGVN::optimize Changes: https://git.openjdk.java.net/valhalla/pull/377/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=377&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8264586 Stats: 66 lines in 6 files changed: 55 ins; 8 del; 3 mod Patch: https://git.openjdk.java.net/valhalla/pull/377.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/377/head:pull/377 PR: https://git.openjdk.java.net/valhalla/pull/377 From thartmann at openjdk.java.net Tue Apr 6 14:34:34 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Tue, 6 Apr 2021 14:34:34 GMT Subject: [lworld] Integrated: 8264586: [lworld] C2 compilation fails due to infinite loop in PhaseIterGVN::optimize In-Reply-To: References: Message-ID: On Tue, 6 Apr 2021 12:39:58 GMT, Tobias Hartmann wrote: > The problem is an `InlineTypePtrNode` that becomes dead after CCP removes a redundant null check and then keeps several other nodes alive. Since we don't run any loop opts anymore after CCP, the dead subgraph is not removed and the dead nodes are also not re-processed by `PhaseCCP::transform_once` to update their bottom types. As a result, two `LoadNodes` only used by a `ValueTypePtrNode` end up with types that are inconsistent with their bottom types and are re-enqueued for IGVN indefinitely by this code: > https://github.com/openjdk/valhalla/blob/28a4ec0249fd86fe17f2b816c6f5f8eed31abfeb/src/hotspot/share/opto/memnode.cpp#L352-L358 > > I think we should aggressively remove `InlineTypePtrNodes` if they are no longer needed to keep track of the individual field values. I've added an Ideal transformation to take care of that. > > The patch also includes a fix for an unrelated "Control flow was added although the intrinsic bailed out" failure and some cleanup/refactoring. > > Thanks, > Tobias This pull request has now been integrated. Changeset: 937f9b34 Author: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/937f9b34 Stats: 66 lines in 6 files changed: 55 ins; 8 del; 3 mod 8264586: [lworld] C2 compilation fails due to infinite loop in PhaseIterGVN::optimize ------------- PR: https://git.openjdk.java.net/valhalla/pull/377 From thartmann at openjdk.java.net Wed Apr 7 13:20:16 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Wed, 7 Apr 2021 13:20:16 GMT Subject: [lworld] RFR: 8264085: [lworld] C2 compilation fails with assert "inline type should be loaded" Message-ID: We hit an assert because C2 fails to replace a load from a non-flattened, empty inline type field by the default oop. Thanks, Tobias ------------- Commit messages: - added comment - 8264085: [lworld] C2 compilation fails with assert "inline type should be loaded" Changes: https://git.openjdk.java.net/valhalla/pull/378/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=378&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8264085 Stats: 35 lines in 2 files changed: 21 ins; 1 del; 13 mod Patch: https://git.openjdk.java.net/valhalla/pull/378.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/378/head:pull/378 PR: https://git.openjdk.java.net/valhalla/pull/378 From thartmann at openjdk.java.net Wed Apr 7 15:20:29 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Wed, 7 Apr 2021 15:20:29 GMT Subject: [lworld] Integrated: 8264085: [lworld] C2 compilation fails with assert "inline type should be loaded" In-Reply-To: References: Message-ID: On Wed, 7 Apr 2021 13:14:08 GMT, Tobias Hartmann wrote: > We hit an assert because C2 fails to replace a load from a non-flattened, empty inline type field by the default oop. > > Thanks, > Tobias This pull request has now been integrated. Changeset: f816f294 Author: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/f816f294 Stats: 35 lines in 2 files changed: 21 ins; 1 del; 13 mod 8264085: [lworld] C2 compilation fails with assert "inline type should be loaded" ------------- PR: https://git.openjdk.java.net/valhalla/pull/378 From sadayapalam at openjdk.java.net Thu Apr 8 06:57:15 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Thu, 8 Apr 2021 06:57:15 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v3] In-Reply-To: References: Message-ID: On Thu, 1 Apr 2021 15:32:54 GMT, Maurizio Cimadamore wrote: >> Srikanth Adayapalam has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2202: > >> 2200: * @param s a type >> 2201: */ >> 2202: public Type asSuper(Type t, Type s) { > > A possible approach here (discussed offline) would be to leave asSuper as it is today - e.g. assume that asSuper speaks about "extends/implements" clause, and deal with .ref vs. .val mismatches at the callsite (if possible) - e.g. in Types::isSubtypes. Yes, I'll pursue what you outline in upcoming commits ------------- PR: https://git.openjdk.java.net/valhalla/pull/375 From sadayapalam at openjdk.java.net Thu Apr 8 06:57:15 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Thu, 8 Apr 2021 06:57:15 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v4] In-Reply-To: <_xclMgfi5gzm1iZu2kD2IwKgjMOTcXcU-IOGFpVOJ0E=.55da3e90-8ada-41b2-9b32-0f565c7629c2@github.com> References: <_xclMgfi5gzm1iZu2kD2IwKgjMOTcXcU-IOGFpVOJ0E=.55da3e90-8ada-41b2-9b32-0f565c7629c2@github.com> Message-ID: On Thu, 1 Apr 2021 15:43:22 GMT, Maurizio Cimadamore wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java line 373: >> >>> 371: JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field), >>> 372: sym.name, >>> 373: make.QualIdent(lambdaType.getReturnType().tsym).setType(lambdaType.getReturnType()), >> >> Discussion item:This spot indicates one of the pain points in the new approach, There are lots of places where we construct fresh AST nodes from a symbol and in the process decorate the AST's type from what we see in the symbol. This is not a problem for parameterized types because the type arguments are erased by TransTypes anyway. But with Foo.ref and Foo.val sharing the same symbol, we will loose reference "projection'ness". I would like to discuss if there are mechanical ways to detect and prevent such loss of type information. ATM, I am dependent on tests breaking to expose such problems and this is dependent heavily on coverage and coverage is still in infancy > > Again, my test here is this: suppose that here we weren't talking about Point.ref/Point.val - but, instead of List vs. List. Would anything be different? I don't think so. What you are observing is the result of a "wrong" assumption made by the code - or, rather, an assumption that "used to" be true, but is no longer. That is, this code (and code like this spread all over javac) assumes that we can safely ignore type info once we're past the frontend, as code generation is only expressed in terms of erased types (which are also the types attached to the symbol). This assumption is starting to crumble now, and will come crashing down when specialized generics are introduced. So I see this as technical debt (e.g. javac throwing aways types and dealing with symbols too early) as opposed to a specific limitation of the patch proposed in this PR. To get a cleaner fix, we should fix the underlying problem (eager erasure). I agree with your observation that "this as technical debt (e.g. javac throwing aways types and dealing with symbols too early) as opposed to a specific limitation of the patch proposed in this PR. To get a cleaner fix, we should fix the underlying problem (eager erasure)." So what call out as the problem inherent in the new approach is but one instance of the larger problem that will occur in other contexts. I agree with your suggestion elsewhere that this could be handled on a PR of its own. ------------- PR: https://git.openjdk.java.net/valhalla/pull/375 From ngasson at openjdk.java.net Thu Apr 8 08:09:14 2021 From: ngasson at openjdk.java.net (Nick Gasson) Date: Thu, 8 Apr 2021 08:09:14 GMT Subject: [lworld] RFR: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 In-Reply-To: References: Message-ID: On Thu, 1 Apr 2021 12:52:07 GMT, Tobias Hartmann wrote: >> We see failures like this on AArch64 when MyValue.incrementAndCheck() is >> compiled with C1: >> >> java.lang.RuntimeException: Inconsistent field values: expected 0 to equal 675128 >> at jdk.test.lib.Asserts.fail(Asserts.java:594) >> at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) >> at jdk.test.lib.Asserts.assertEQ(Asserts.java:178) >> at compiler.valhalla.inlinetypes.MyValue.incrementAndCheck(TestBufferTearing.java:81) >> at compiler.valhalla.inlinetypes.TestBufferTearing$Runner.run(TestBufferTearing.java:124) >> >> The barrier that is usually inserted on return from a method that wrote >> final fields should be sufficient to prevent another thread seeing the >> zero-initialised intermediate state. However this barrier isn't >> inserted at the moment because method()->is_object_constructor() is >> false for primitive class constructors. >> >> C2 has a similar guard around the memory barrier in Parse::do_exits(). >> I'm not sure if that needs amending as well but I've not seen any >> failures due to it. > > Hi Nick, > > I think we also need a barrier in `GraphBuilder::access_field` when loading from a flattened field and in `GraphBuilder::load_indexed` (the initialization code is emitted in `LIRGenerator::access_flattened_array`) when loading from a flattened array. > > It would be good to have tests that triggers this. > > Best regards, > Tobias So I've managed to generate the following test which triggers this: public class BarrierTest { public static Point[] points = new Point[1]; static volatile boolean running = true; public static void writePoint(int i) { Rect r = new Rect(new Point(i, i), new Point(i + 1, i + 1)); points[0] = r.a; // Load from flattened field here } private static void checkMissingBarrier() { while (running) { // Should not see zero-initialised object here if (points[0].x == 0 || points[0].y == 0) throw new IllegalStateException(); } } public static void main(String[] args) throws InterruptedException { points[0] = new Point(1, 1); Thread[] threads = new Thread[10]; for (int i = 0; i < 10; i++) { threads[i] = new Thread(BarrierTest::checkMissingBarrier); threads[i].start(); } for (int i = 2; i < 1_000_000; i++) writePoint(i); running = false; for (int i = 0; i < 10; i++) threads[i].join(); } } Where `Rect` and `Point` are primitive classes with the obvious definition. Then `checkMissingBarrier()` will throw an exception if run with `-XX:InlineFieldMaxFlatSize=-1 -XX:FlatArrayElementMaxSize=0 -XX:TieredStopAtLevel=1`. The field access `r.a` creates an on-heap copy of the flattened field and then stores that reference into the `points` array (which can't be flattened because `FlatArrayElementMaxSize=0`). Without a memory barrier after copying the flattened field contents in `GraphBuilder::access_field` another thread can read through that reference and see the zero-initialised memory. I'm not sure if there's an easier way of triggering this without having mis-matched InlineFieldMaxFlatSize and FlatArrayElementMaxSize? To see this I think we need to read from a flattened field and then store into a non-flattened field of the same type that's accessible by another thread. ------------- PR: https://git.openjdk.java.net/valhalla/pull/376 From sadayapalam at openjdk.java.net Thu Apr 8 08:09:14 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Thu, 8 Apr 2021 08:09:14 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v5] In-Reply-To: References: Message-ID: > This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. Srikanth Adayapalam has updated the pull request incrementally with two additional commits since the last revision: - Where possible prefer Types.isSubtype over Types.asSuper for loss less subtyping determination; Merge Two flavors of Types.asSuper into one; Make sure to switch to projection types for sucessful hierarchy lookup via asSuper - Reverse all changes made to Types.asSuper both at definition site and call sites. ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/375/files - new: https://git.openjdk.java.net/valhalla/pull/375/files/42fefb15..14e36283 Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=04 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=03-04 Stats: 314 lines in 16 files changed: 235 ins; 31 del; 48 mod Patch: https://git.openjdk.java.net/valhalla/pull/375.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/375/head:pull/375 PR: https://git.openjdk.java.net/valhalla/pull/375 From sadayapalam at openjdk.java.net Thu Apr 8 08:12:42 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Thu, 8 Apr 2021 08:12:42 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v3] In-Reply-To: References: Message-ID: On Thu, 1 Apr 2021 15:52:40 GMT, Maurizio Cimadamore wrote: >> Srikanth Adayapalam has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. > > This seems like a good cleanup overall. IMHO the issues can be bucketized as follows: > > * some more experiment is required to see if we can avoid changing asSuper too much > * there is code which will be simplified if we come to a point where javac can let go of generating two classes instead of one. > * there is a bigger issue (which we'll have to confront with, sooner or later, because of specialization) regarding type erasure kicking in too early, and subsequent pipeline steps only dealing with symbol (not type) info > > Since the approach moves things in the way generic types are modeled, I'm not surprised to see some of the issues I had to face when writing a backend for the specializer compiler pop back here. I'd say, for now, let's try to deal with the first bullet (which is localized with these changes), and let's come back (in a separate PR) with some workaround for the last bullet (perhaps borrowing some old valhalla code?). Hello Maurzio, Please take another look. I have reverted all the earlier changes to asSuper per suggestion and transformed calls to asSuper into isSubtype calls where possible (This is not always possible - see the elaborate javadoc comment attached to Types.asSuper - in fact starting the review there would be a good thing) There are still a few calls to asSuper that are not studied through the lens of the twin hazards - these are calls from Types itself and Infer.java - outside of these two files I have studied all call sites of asSuper and suitably amended them and added tests to guard against any regressions and prove the need for and correctness of the transformation. I decided to defer the study of these remaining call sites to the pre-existing ticket JDK-8244712 - Javac should switch to reference projection before walking type hierarchy. (This ticket would include analysis of not only the remaining asSuper calls, but also isSubtype calls) Of the two commits (ignoring the merge related ones), one of them is simply a revert of earlier change for asSuper and can be ignored. Let me know if you see any further issues that block integration. Thanks! ------------- PR: https://git.openjdk.java.net/valhalla/pull/375 From sadayapalam at openjdk.java.net Thu Apr 8 08:15:44 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Thu, 8 Apr 2021 08:15:44 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v6] In-Reply-To: References: Message-ID: <9LFjkEAAheZkm9Gq8RsOepyFeiKaR61vS8egeceX-MA=.5ac212fc-9721-4c20-b63c-7f64b143ad33@github.com> > This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. Srikanth Adayapalam has updated the pull request incrementally with one additional commit since the last revision: Fix white space problems ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/375/files - new: https://git.openjdk.java.net/valhalla/pull/375/files/14e36283..c2f4f478 Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=05 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=04-05 Stats: 16 lines in 1 file changed: 0 ins; 0 del; 16 mod Patch: https://git.openjdk.java.net/valhalla/pull/375.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/375/head:pull/375 PR: https://git.openjdk.java.net/valhalla/pull/375 From mcimadamore at openjdk.java.net Thu Apr 8 11:25:33 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Thu, 8 Apr 2021 11:25:33 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v5] In-Reply-To: References: Message-ID: On Thu, 8 Apr 2021 08:09:14 GMT, Srikanth Adayapalam wrote: >> This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. > > Srikanth Adayapalam has updated the pull request incrementally with two additional commits since the last revision: > > - Where possible prefer Types.isSubtype over Types.asSuper for loss less subtyping determination; Merge Two flavors of Types.asSuper into one; Make sure to switch to projection types for sucessful hierarchy lookup via asSuper > - Reverse all changes made to Types.asSuper both at definition site and call sites. In general, it looks good. I have two main comments: * consider using reference projection always when doing asSuper (e.g. adding that projection inside asSuper, directly) * I believe the patch is replacing too many use sites with subtyping. There are several checks where we want to assert that T is an instance of C, where C can be AutoCloseable, Iterable, Serializable. It is not clear to me as to why we'd want these replaced with subtyping - in the sense that here we seem to be asking about a propoerty of the primitive class _declaration_ rather than the particular projection we happen to have on hand. src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java line 2045: > 2043: // check for a direct implementation > 2044: if (other.isOverridableIn((TypeSymbol)owner) && > 2045: types.isSubtype(owner.type, other.owner.type) && This seems inconsistent with what has been done below (see other comment) src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java line 2114: > 2112: // check for a direct implementation > 2113: if (other.isOverridableIn((TypeSymbol)owner) && > 2114: types.asSuper(owner.type.referenceProjectionOrSelf(), other.owner) != null) { So, for source ovrride we use `asSuper`, but for binary override we use `isSubtype`. Shouldn't we use asSuper in both cases here? Overriding is typically a business between class declarations, so symbols should be good? Or can you envision a case where you want to check if a method on Foo.val overrides something on a Foo.ref and you want to say "no" there? In other words, I think the check here is meant to say: make sure that the owner of the method symbols are related by subclassing - which seems to call for asSuper. src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2209: > 2207: * > 2208: * 1. Since Foo.ref and Foo.val share the same symbol, that of Foo.class, a call to > 2209: * asSuper(Foo.ref.type, Foo.val.type.tsym) would return non-null. This is NOT correct I don't think I agree with the spirit of this comment :-) There is only one symbol, so Foo.val.type.tsym == Foo. So: asSuper(Foo.ref.type, Foo.val.type.tsym) == asSuper(Foo.ref.type, Foo) == true This is not different from when you have: asSuper(ListOfString.type, ListOfInteger.type.tsym) != null I think the real issue here, is that we can't rely on "asSuper" for code generation, because, really, this routine isn't sharp enough. In the case of Gen::visitTypeCast, the issue is that we have to decide whether a checkcast should be emitted or not; we typically do that by comparing symbols. That strategy here is simply insufficient - as the symbols are the same - just the types will be different. This will be, again, the case when we will face a cast from List to List - these two types will have same symbol, but different representation in the classfile, so a checkcast will be needed there. src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2223: > 2221: * isSubType(ArrayList.type, List.type) is false;) So care needs to be exercised. > 2222: * > 2223: * 2. Given a primitive class Foo, a call to asSuper(Foo.type, SuperclassOfFoo.tsym) and/or Question here: is Foo.type refusing to play because the "default" semantics attached to Foo.type is the one of the "value projection" ? If so, then I agree with the fix (e.g. using reference projection or self). Also, given where the model is, I don't think this is an "hack" or a "workaround" - it's basically a requirement: inheritance info lives on the .ref side of the fence. In fact, so much so that I'll raise: shouldn't this call to "refProjectionOrSelf" be part of asSuper? If asSuper is always use to check for inheritance relationship, isn't it always the case that you want the reference projection to be used? (and then, if a callsite ends up with too lose a semantics, maybe that's a sign that using asSuper there was the wrong choice?) src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java line 1919: > 1917: void checkAutoCloseable(DiagnosticPosition pos, Env env, Type resource) { > 1918: if (!resource.isErroneous() && > 1919: types.isSubtype(resource.referenceProjectionOrSelf(), syms.autoCloseableType) && I think this wants asSuper? You are projecting anyway. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 2698: > 2696: checkCompatibleConcretes(pos, c); > 2697: > 2698: boolean implementsIdentityObject = types.isSubtype(c.referenceProjectionOrSelf(), syms.identityObjectType); Not sure you need full blown subtyping here. You are just asking: is this thing derived from "identityObject" - in all these cases asSuper is what you want. Same for AutoCloseable checks. Iterable, ... src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java line 1862: > 1860: return true; > 1861: } > 1862: return types.isSubtype(tree.target, syms.serializableType); That's another "is this a subclass of XYZ" check - asSuper is fine here (with ref projection). src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java line 1725: > 1723: private JCStatement makeResourceCloseInvocation(JCExpression resource) { > 1724: // convert to AutoCloseable if needed > 1725: if (!types.isSubtype(resource.type.referenceProjectionOrSelf(), syms.autoCloseableType)) { asSuper? src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java line 2279: > 2277: !types.isSameType(tree.expr.type, tree.clazz.type) && > 2278: (!tree.clazz.type.isReferenceProjection() || !types.isSameType(tree.clazz.type.valueProjection(), tree.expr.type)) && > 2279: !types.isSubtype(tree.expr.type, tree.clazz.type)) { This is, I think, the main place, where isSubtype is truly necessary. ------------- PR: https://git.openjdk.java.net/valhalla/pull/375 From sadayapalam at openjdk.java.net Thu Apr 8 11:50:33 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Thu, 8 Apr 2021 11:50:33 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v5] In-Reply-To: References: Message-ID: On Thu, 8 Apr 2021 11:22:50 GMT, Maurizio Cimadamore wrote: > In general, it looks good. I have three main comments: > > * the refProjectionOrSelf trick is a good one, I believe > * consider using reference projection always when doing asSuper (e.g. adding that projection inside asSuper, directly) Will experiment with this and report back. This could minimize code changes. > * I believe the patch is replacing too many use sites with subtyping. There are several checks where we want to assert that T is an instance of C, where C can be AutoCloseable, Iterable, Serializable. It is not clear to me as to why we'd want these replaced with subtyping - in the sense that here we seem to be asking about a propoerty of the primitive class _declaration_ rather than the particular projection we happen to have on hand. Possible. The rule of thumb I used for changing calls to asSuper into isSubtype was simply, whether (a) the call site is interested in the return value of asSuper as opoosed to just checking whether it is null or not and (b) whether generic class symbol could be passed in as the second argument to original asSuper call and if so retain it as asSuper itself. So it is likely more sites are changed than strictly necessary. The way I see it some of the overeaget changes to isSubtype result in equivalent semantics with no regression. Still it is worth minimizing ripples and for that reason I will attempt to restore these. > > Note that, as we're exploring new territory, it is very possible that I have overlooked some underlying issue here - but thanks for taking the time to guide me through all the problems! I am grappling with similar challenges. I.e clearly characterizing which calls involve hazards of which kind. This involves reasoning about every site. > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java line 2045: > >> 2043: // check for a direct implementation >> 2044: if (other.isOverridableIn((TypeSymbol)owner) && >> 2045: types.isSubtype(owner.type, other.owner.type) && > > This seems inconsistent with what has been done below (see other comment) Good point. > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java line 2114: > >> 2112: // check for a direct implementation >> 2113: if (other.isOverridableIn((TypeSymbol)owner) && >> 2114: types.asSuper(owner.type.referenceProjectionOrSelf(), other.owner) != null) { > > So, for source ovrride we use `asSuper`, but for binary override we use `isSubtype`. Shouldn't we use asSuper in both cases here? Overriding is typically a business between class declarations, so symbols should be good? Or can you envision a case where you want to check if a method on Foo.val overrides something on a Foo.ref and you want to say "no" there? In other words, I think the check here is meant to say: make sure that the owner of the method symbols are related by subclassing - which seems to call for asSuper. Agreed. > I don't think I agree with the spirit of this comment :-) > Indeed, it is stronger than it ought to be. It should say it may not be always what is desired at call site. > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2223: > >> 2221: * isSubType(ArrayList.type, List.type) is false;) So care needs to be exercised. >> 2222: * >> 2223: * 2. Given a primitive class Foo, a call to asSuper(Foo.type, SuperclassOfFoo.tsym) and/or > > Question here: is Foo.type refusing to play because the "default" semantics attached to Foo.type is the one of the "value projection" ? If so, then I agree with the fix (e.g. using reference projection or self). Also, given where the model is, I don't think this is an "hack" or a "workaround" - it's basically a requirement: inheritance info lives on the .ref side of the fence. > > In fact, so much so that I'll raise: shouldn't this call to "refProjectionOrSelf" be part of asSuper? If asSuper is always use to check for inheritance relationship, isn't it always the case that you want the reference projection to be used? (and then, if a callsite ends up with too lose a semantics, maybe that's a sign that using asSuper there was the wrong choice?) Plausible, will experiment. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 2698: > >> 2696: checkCompatibleConcretes(pos, c); >> 2697: >> 2698: boolean implementsIdentityObject = types.isSubtype(c.referenceProjectionOrSelf(), syms.identityObjectType); > > Not sure you need full blown subtyping here. You are just asking: is this thing derived from "identityObject" - in all these cases asSuper is what you want. Same for AutoCloseable checks. Iterable, ... OK > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java line 1862: > >> 1860: return true; >> 1861: } >> 1862: return types.isSubtype(tree.target, syms.serializableType); > > That's another "is this a subclass of XYZ" check - asSuper is fine here (with ref projection). OK > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java line 1725: > >> 1723: private JCStatement makeResourceCloseInvocation(JCExpression resource) { >> 1724: // convert to AutoCloseable if needed >> 1725: if (!types.isSubtype(resource.type.referenceProjectionOrSelf(), syms.autoCloseableType)) { > > asSuper? OK ------------- PR: https://git.openjdk.java.net/valhalla/pull/375 From sadayapalam at openjdk.java.net Thu Apr 8 15:01:53 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Thu, 8 Apr 2021 15:01:53 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v7] In-Reply-To: References: Message-ID: > This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. Srikanth Adayapalam has updated the pull request incrementally with one additional commit since the last revision: Revert overeager conversion of asSuper calls into isSubtype calls as when the goal is instanceof determination, the former is good enough. ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/375/files - new: https://git.openjdk.java.net/valhalla/pull/375/files/c2f4f478..c976027d Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=06 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=375&range=05-06 Stats: 15 lines in 7 files changed: 3 ins; 0 del; 12 mod Patch: https://git.openjdk.java.net/valhalla/pull/375.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/375/head:pull/375 PR: https://git.openjdk.java.net/valhalla/pull/375 From sadayapalam at openjdk.java.net Thu Apr 8 15:05:36 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Thu, 8 Apr 2021 15:05:36 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v5] In-Reply-To: References: Message-ID: On Thu, 8 Apr 2021 11:40:58 GMT, Srikanth Adayapalam wrote: >> In general, it looks good. I have three main comments: >> * the refProjectionOrSelf trick is a good one, I believe >> * consider using reference projection always when doing asSuper (e.g. adding that projection inside asSuper, directly) >> * I believe the patch is replacing too many use sites with subtyping. There are several checks where we want to assert that T is an instance of C, where C can be AutoCloseable, Iterable, Serializable. It is not clear to me as to why we'd want these replaced with subtyping - in the sense that here we seem to be asking about a propoerty of the primitive class _declaration_ rather than the particular projection we happen to have on hand. >> >> Note that, as we're exploring new territory, it is very possible that I have overlooked some underlying issue here - but thanks for taking the time to guide me through all the problems! > >> In general, it looks good. I have three main comments: >> >> * the refProjectionOrSelf trick is a good one, I believe >> * consider using reference projection always when doing asSuper (e.g. adding that projection inside asSuper, directly) > > Will experiment with this and report back. This could minimize code changes. > >> * I believe the patch is replacing too many use sites with subtyping. There are several checks where we want to assert that T is an instance of C, where C can be AutoCloseable, Iterable, Serializable. It is not clear to me as to why we'd want these replaced with subtyping - in the sense that here we seem to be asking about a propoerty of the primitive class _declaration_ rather than the particular projection we happen to have on hand. > > Possible. The rule of thumb I used for changing calls to asSuper into isSubtype was simply, whether (a) the call site is interested in the return value of asSuper as opoosed to just checking whether it is null or not and (b) whether generic class symbol could be passed in as the second argument to original asSuper call and if so retain it as asSuper itself. > > So it is likely more sites are changed than strictly necessary. The way I see it some of the overeaget changes to isSubtype result in equivalent semantics with no regression. Still it is worth minimizing ripples and for that reason I will attempt to restore these. > >> >> Note that, as we're exploring new territory, it is very possible that I have overlooked some underlying issue here - but thanks for taking the time to guide me through all the problems! > > I am grappling with similar challenges. I.e clearly characterizing which calls involve hazards of which kind. This involves reasoning about every site. I pushed a commit accommodating two review comments: 1. asSuper calls at various places employed for the purpose of instanceof determination can be left alone. 2. Javadoc comment attached to asSuper is stronger than it ought to be and asserts something that is not quite true. The third suggestion around asSuper internally coercing its argument into reference projection is something that will be taken up in a subsequent PR for JDK-8244712 @Maurizio, I'll proceed with integration if you give a quick glance through over the latest commit and approve. TIA ------------- PR: https://git.openjdk.java.net/valhalla/pull/375 From mcimadamore at openjdk.java.net Thu Apr 8 16:00:30 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Thu, 8 Apr 2021 16:00:30 GMT Subject: [lworld] RFR: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol [v7] In-Reply-To: References: Message-ID: On Thu, 8 Apr 2021 15:01:53 GMT, Srikanth Adayapalam wrote: >> This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. > > Srikanth Adayapalam has updated the pull request incrementally with one additional commit since the last revision: > > Revert overeager conversion of asSuper calls into isSubtype calls as when the goal is instanceof determination, the former is good enough. Looks good - thanks for following up! ------------- Marked as reviewed by mcimadamore (Committer). PR: https://git.openjdk.java.net/valhalla/pull/375 From sadayapalam at openjdk.java.net Fri Apr 9 01:04:36 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Fri, 9 Apr 2021 01:04:36 GMT Subject: [lworld] Integrated: 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol In-Reply-To: References: Message-ID: On Wed, 31 Mar 2021 12:32:04 GMT, Srikanth Adayapalam wrote: > This PR overhauls the existing implementation/representation of reference projection types and the inline types so that both share the same underlying symbol, much like how an infinite family of parameterized types that originate from the same generic type are modelled using the same underlying symbol. This pull request has now been integrated. Changeset: c68ce892 Author: Srikanth Adayapalam URL: https://git.openjdk.java.net/valhalla/commit/c68ce892 Stats: 788 lines in 33 files changed: 404 ins; 257 del; 127 mod 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol Reviewed-by: mcimadamore ------------- PR: https://git.openjdk.java.net/valhalla/pull/375 From ngasson at openjdk.java.net Fri Apr 9 06:33:18 2021 From: ngasson at openjdk.java.net (Nick Gasson) Date: Fri, 9 Apr 2021 06:33:18 GMT Subject: [lworld] RFR: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 [v2] In-Reply-To: References: Message-ID: > We see failures like this on AArch64 when MyValue.incrementAndCheck() is > compiled with C1: > > java.lang.RuntimeException: Inconsistent field values: expected 0 to equal 675128 > at jdk.test.lib.Asserts.fail(Asserts.java:594) > at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) > at jdk.test.lib.Asserts.assertEQ(Asserts.java:178) > at compiler.valhalla.inlinetypes.MyValue.incrementAndCheck(TestBufferTearing.java:81) > at compiler.valhalla.inlinetypes.TestBufferTearing$Runner.run(TestBufferTearing.java:124) > > The barrier that is usually inserted on return from a method that wrote > final fields should be sufficient to prevent another thread seeing the > zero-initialised intermediate state. However this barrier isn't > inserted at the moment because method()->is_object_constructor() is > false for primitive class constructors. > > C2 has a similar guard around the memory barrier in Parse::do_exits(). > I'm not sure if that needs amending as well but I've not seen any > failures due to it. Nick Gasson has updated the pull request incrementally with one additional commit since the last revision: Two more missing membars ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/376/files - new: https://git.openjdk.java.net/valhalla/pull/376/files/afed1e02..ed4c8bd2 Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=376&range=01 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=376&range=00-01 Stats: 122 lines in 2 files changed: 122 ins; 0 del; 0 mod Patch: https://git.openjdk.java.net/valhalla/pull/376.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/376/head:pull/376 PR: https://git.openjdk.java.net/valhalla/pull/376 From ngasson at openjdk.java.net Fri Apr 9 06:42:29 2021 From: ngasson at openjdk.java.net (Nick Gasson) Date: Fri, 9 Apr 2021 06:42:29 GMT Subject: [lworld] RFR: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 In-Reply-To: References: Message-ID: On Thu, 1 Apr 2021 12:52:07 GMT, Tobias Hartmann wrote: >> We see failures like this on AArch64 when MyValue.incrementAndCheck() is >> compiled with C1: >> >> java.lang.RuntimeException: Inconsistent field values: expected 0 to equal 675128 >> at jdk.test.lib.Asserts.fail(Asserts.java:594) >> at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) >> at jdk.test.lib.Asserts.assertEQ(Asserts.java:178) >> at compiler.valhalla.inlinetypes.MyValue.incrementAndCheck(TestBufferTearing.java:81) >> at compiler.valhalla.inlinetypes.TestBufferTearing$Runner.run(TestBufferTearing.java:124) >> >> The barrier that is usually inserted on return from a method that wrote >> final fields should be sufficient to prevent another thread seeing the >> zero-initialised intermediate state. However this barrier isn't >> inserted at the moment because method()->is_object_constructor() is >> false for primitive class constructors. >> >> C2 has a similar guard around the memory barrier in Parse::do_exits(). >> I'm not sure if that needs amending as well but I've not seen any >> failures due to it. > > Hi Nick, > > I think we also need a barrier in `GraphBuilder::access_field` when loading from a flattened field and in `GraphBuilder::load_indexed` (the initialization code is emitted in `LIRGenerator::access_flattened_array`) when loading from a flattened array. > > It would be good to have tests that triggers this. > > Best regards, > Tobias @TobiHartmann I've added the two missing membars and a test. ------------- PR: https://git.openjdk.java.net/valhalla/pull/376 From thartmann at openjdk.java.net Fri Apr 9 09:52:28 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Fri, 9 Apr 2021 09:52:28 GMT Subject: [lworld] RFR: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 [v2] In-Reply-To: References: Message-ID: On Fri, 9 Apr 2021 06:33:18 GMT, Nick Gasson wrote: >> We see failures like this on AArch64 when MyValue.incrementAndCheck() is >> compiled with C1: >> >> java.lang.RuntimeException: Inconsistent field values: expected 0 to equal 675128 >> at jdk.test.lib.Asserts.fail(Asserts.java:594) >> at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) >> at jdk.test.lib.Asserts.assertEQ(Asserts.java:178) >> at compiler.valhalla.inlinetypes.MyValue.incrementAndCheck(TestBufferTearing.java:81) >> at compiler.valhalla.inlinetypes.TestBufferTearing$Runner.run(TestBufferTearing.java:124) >> >> The barrier that is usually inserted on return from a method that wrote >> final fields should be sufficient to prevent another thread seeing the >> zero-initialised intermediate state. However this barrier isn't >> inserted at the moment because method()->is_object_constructor() is >> false for primitive class constructors. >> >> C2 has a similar guard around the memory barrier in Parse::do_exits(). >> I'm not sure if that needs amending as well but I've not seen any >> failures due to it. > > Nick Gasson has updated the pull request incrementally with one additional commit since the last revision: > > Two more missing membars Very nice that you were able to come up with a regression test! Regarding the combination of `InlineFieldMaxFlatSize` and `FlatArrayElementMaxSize`, couldn't you achieve the same result by using an Object or Interface array/field to prevent flattening? The fix looks good to me but I think we also need membars in `GraphBuilder::access_field` (there are two places where we create a buffer via `new NewInlineTypeInstance`). Would be great if you could add a regression test for that as well. ------------- PR: https://git.openjdk.java.net/valhalla/pull/376 From thartmann at openjdk.java.net Fri Apr 9 11:22:43 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Fri, 9 Apr 2021 11:22:43 GMT Subject: [lworld] Integrated: 8264978: [lworld] Various small code cleanups Message-ID: <91gu-9NtQgn40vmOvcQPtmd0LIiN7xtzwXebZyjlT4A=.a99d5529-070c-4099-ac06-909ed744982f@github.com> Some minor cleanups and removal of dead code. Thanks, Tobias ------------- Commit messages: - 8264978: [lworld] Various small code cleanups Changes: https://git.openjdk.java.net/valhalla/pull/379/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=379&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8264978 Stats: 81 lines in 16 files changed: 12 ins; 32 del; 37 mod Patch: https://git.openjdk.java.net/valhalla/pull/379.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/379/head:pull/379 PR: https://git.openjdk.java.net/valhalla/pull/379 From thartmann at openjdk.java.net Fri Apr 9 11:22:43 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Fri, 9 Apr 2021 11:22:43 GMT Subject: [lworld] Integrated: 8264978: [lworld] Various small code cleanups In-Reply-To: <91gu-9NtQgn40vmOvcQPtmd0LIiN7xtzwXebZyjlT4A=.a99d5529-070c-4099-ac06-909ed744982f@github.com> References: <91gu-9NtQgn40vmOvcQPtmd0LIiN7xtzwXebZyjlT4A=.a99d5529-070c-4099-ac06-909ed744982f@github.com> Message-ID: On Fri, 9 Apr 2021 11:13:52 GMT, Tobias Hartmann wrote: > Some minor cleanups and removal of dead code. > > Thanks, > Tobias This pull request has now been integrated. Changeset: f3950adb Author: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/f3950adb Stats: 81 lines in 16 files changed: 12 ins; 32 del; 37 mod 8264978: [lworld] Various small code cleanups ------------- PR: https://git.openjdk.java.net/valhalla/pull/379 From sadayapalam at openjdk.java.net Fri Apr 9 11:51:00 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Fri, 9 Apr 2021 11:51:00 GMT Subject: [lworld] Integrated: 8264977: [lworld] A primitive class field by name val confuses javac Message-ID: More robust handling of .ref/.val tokens even as we wait for JDK-8244229 for the full solution ------------- Commit messages: - 8264977: A primitive class field by name val confuses javac Changes: https://git.openjdk.java.net/valhalla/pull/380/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=380&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8264977 Stats: 117 lines in 4 files changed: 116 ins; 0 del; 1 mod Patch: https://git.openjdk.java.net/valhalla/pull/380.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/380/head:pull/380 PR: https://git.openjdk.java.net/valhalla/pull/380 From sadayapalam at openjdk.java.net Fri Apr 9 11:51:01 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Fri, 9 Apr 2021 11:51:01 GMT Subject: [lworld] Integrated: 8264977: [lworld] A primitive class field by name val confuses javac In-Reply-To: References: Message-ID: On Fri, 9 Apr 2021 11:43:27 GMT, Srikanth Adayapalam wrote: > More robust handling of .ref/.val tokens even as we wait for JDK-8244229 for the full solution This pull request has now been integrated. Changeset: 571322ea Author: Srikanth Adayapalam URL: https://git.openjdk.java.net/valhalla/commit/571322ea Stats: 117 lines in 4 files changed: 116 ins; 0 del; 1 mod 8264977: [lworld] A primitive class field by name val confuses javac ------------- PR: https://git.openjdk.java.net/valhalla/pull/380 From ngasson at openjdk.java.net Mon Apr 12 09:51:42 2021 From: ngasson at openjdk.java.net (Nick Gasson) Date: Mon, 12 Apr 2021 09:51:42 GMT Subject: [lworld] RFR: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 [v3] In-Reply-To: References: Message-ID: > We see failures like this on AArch64 when MyValue.incrementAndCheck() is > compiled with C1: > > java.lang.RuntimeException: Inconsistent field values: expected 0 to equal 675128 > at jdk.test.lib.Asserts.fail(Asserts.java:594) > at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) > at jdk.test.lib.Asserts.assertEQ(Asserts.java:178) > at compiler.valhalla.inlinetypes.MyValue.incrementAndCheck(TestBufferTearing.java:81) > at compiler.valhalla.inlinetypes.TestBufferTearing$Runner.run(TestBufferTearing.java:124) > > The barrier that is usually inserted on return from a method that wrote > final fields should be sufficient to prevent another thread seeing the > zero-initialised intermediate state. However this barrier isn't > inserted at the moment because method()->is_object_constructor() is > false for primitive class constructors. > > C2 has a similar guard around the memory barrier in Parse::do_exits(). > I'm not sure if that needs amending as well but I've not seen any > failures due to it. Nick Gasson has updated the pull request incrementally with one additional commit since the last revision: Add extra missing membar and simplify test ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/376/files - new: https://git.openjdk.java.net/valhalla/pull/376/files/ed4c8bd2..0e41b24a Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=376&range=02 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=376&range=01-02 Stats: 49 lines in 3 files changed: 23 ins; 8 del; 18 mod Patch: https://git.openjdk.java.net/valhalla/pull/376.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/376/head:pull/376 PR: https://git.openjdk.java.net/valhalla/pull/376 From ngasson at openjdk.java.net Mon Apr 12 09:59:02 2021 From: ngasson at openjdk.java.net (Nick Gasson) Date: Mon, 12 Apr 2021 09:59:02 GMT Subject: [lworld] RFR: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 [v2] In-Reply-To: References: Message-ID: On Fri, 9 Apr 2021 09:49:45 GMT, Tobias Hartmann wrote: > > Regarding the combination of `InlineFieldMaxFlatSize` and `FlatArrayElementMaxSize`, couldn't you achieve the same result by using an Object or Interface array/field to prevent flattening? Yes that's much simpler, thanks. > > The fix looks good to me but I think we also need membars in `GraphBuilder::access_field` (there are two places where we create a buffer via `new NewInlineTypeInstance`). Would be great if you could add a regression test for that as well. Yes there's also the case for the "delayed" load-indexed as in `array[n].field`. I saw that before but for some reason thought it didn't need the membar. I've added a test for that too so all three cases fail without the corresponding membar. While I was testing that I found it would fail occasionally before while `writeRefs()` was running in the interpreter before C1 compiled it. So I think there's also a missing membar at the end of `InterpreterMacroAssembler::read_inlined_field()` which I've added (not necessary for x86). ------------- PR: https://git.openjdk.java.net/valhalla/pull/376 From thartmann at openjdk.java.net Mon Apr 12 12:05:06 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Mon, 12 Apr 2021 12:05:06 GMT Subject: [lworld] RFR: 8264895: [lworld] assert(!InstanceKlass::cast(receiver_klass)->is_not_initialized()) failed: receiver_klass must be initialized Message-ID: We hit an assert during call resolution of C1 compiled code because the receiver klass is not linked/initialized. This can happen because C1 compiled code does not initialize the inline class at defaultvalue and call resolution does not expect uninitialized klasses (for non-inline classes, the receiver is either null or initialized). The fix is to deoptimize at defaultvalue for now and add support for runtime patching later with [JDK-8265067](https://bugs.openjdk.java.net/browse/JDK-8265067). Thanks, Tobias ------------- Commit messages: - 8264895: [lworld] assert(\!InstanceKlass::cast(receiver_klass)->is_not_initialized()) failed: receiver_klass must be initialized Changes: https://git.openjdk.java.net/valhalla/pull/382/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=382&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8264895 Stats: 51 lines in 2 files changed: 49 ins; 0 del; 2 mod Patch: https://git.openjdk.java.net/valhalla/pull/382.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/382/head:pull/382 PR: https://git.openjdk.java.net/valhalla/pull/382 From thartmann at openjdk.java.net Mon Apr 12 12:12:53 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Mon, 12 Apr 2021 12:12:53 GMT Subject: [lworld] RFR: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 [v3] In-Reply-To: References: Message-ID: <1xBgXF33rYRLk-HGJ-ySvsr30cWshShh3hH8Ao3YSl0=.1a1c92c9-1e39-45c3-a528-7d4e2b147836@github.com> On Mon, 12 Apr 2021 09:51:42 GMT, Nick Gasson wrote: >> We see failures like this on AArch64 when MyValue.incrementAndCheck() is >> compiled with C1: >> >> java.lang.RuntimeException: Inconsistent field values: expected 0 to equal 675128 >> at jdk.test.lib.Asserts.fail(Asserts.java:594) >> at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) >> at jdk.test.lib.Asserts.assertEQ(Asserts.java:178) >> at compiler.valhalla.inlinetypes.MyValue.incrementAndCheck(TestBufferTearing.java:81) >> at compiler.valhalla.inlinetypes.TestBufferTearing$Runner.run(TestBufferTearing.java:124) >> >> The barrier that is usually inserted on return from a method that wrote >> final fields should be sufficient to prevent another thread seeing the >> zero-initialised intermediate state. However this barrier isn't >> inserted at the moment because method()->is_object_constructor() is >> false for primitive class constructors. >> >> C2 has a similar guard around the memory barrier in Parse::do_exits(). >> I'm not sure if that needs amending as well but I've not seen any >> failures due to it. > > Nick Gasson has updated the pull request incrementally with one additional commit since the last revision: > > Add extra missing membar and simplify test Very nice. The compiler changes look good to me! @fparain could you take a look at the interpreter changes? ------------- Marked as reviewed by thartmann (Committer). PR: https://git.openjdk.java.net/valhalla/pull/376 From fparain at openjdk.java.net Mon Apr 12 12:20:47 2021 From: fparain at openjdk.java.net (Frederic Parain) Date: Mon, 12 Apr 2021 12:20:47 GMT Subject: [lworld] RFR: 8264895: [lworld] assert(!InstanceKlass::cast(receiver_klass)->is_not_initialized()) failed: receiver_klass must be initialized In-Reply-To: References: Message-ID: On Mon, 12 Apr 2021 11:58:50 GMT, Tobias Hartmann wrote: > We hit an assert during call resolution of C1 compiled code because the receiver klass is not linked/initialized. This can happen because C1 compiled code does not initialize the inline class at defaultvalue and call resolution does not expect uninitialized klasses (for non-inline classes, the receiver is either null or initialized). > > The fix is to deoptimize at defaultvalue for now and add support for runtime patching later with [JDK-8265067](https://bugs.openjdk.java.net/browse/JDK-8265067). > > Thanks, > Tobias Looks good to me. Fred ------------- Marked as reviewed by fparain (Committer). PR: https://git.openjdk.java.net/valhalla/pull/382 From thartmann at openjdk.java.net Mon Apr 12 12:29:53 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Mon, 12 Apr 2021 12:29:53 GMT Subject: [lworld] RFR: 8264895: [lworld] assert(!InstanceKlass::cast(receiver_klass)->is_not_initialized()) failed: receiver_klass must be initialized In-Reply-To: References: Message-ID: On Mon, 12 Apr 2021 11:58:50 GMT, Tobias Hartmann wrote: > We hit an assert during call resolution of C1 compiled code because the receiver klass is not linked/initialized. This can happen because C1 compiled code does not initialize the inline class at defaultvalue and call resolution does not expect uninitialized klasses (for non-inline classes, the receiver is either null or initialized). > > The fix is to deoptimize at defaultvalue for now and add support for runtime patching later with [JDK-8265067](https://bugs.openjdk.java.net/browse/JDK-8265067). > > Thanks, > Tobias Thanks Fred! ------------- PR: https://git.openjdk.java.net/valhalla/pull/382 From thartmann at openjdk.java.net Mon Apr 12 13:12:03 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Mon, 12 Apr 2021 13:12:03 GMT Subject: [lworld] Integrated: 8264895: [lworld] assert(!InstanceKlass::cast(receiver_klass)->is_not_initialized()) failed: receiver_klass must be initialized In-Reply-To: References: Message-ID: On Mon, 12 Apr 2021 11:58:50 GMT, Tobias Hartmann wrote: > We hit an assert during call resolution of C1 compiled code because the receiver klass is not linked/initialized. This can happen because C1 compiled code does not initialize the inline class at defaultvalue and call resolution does not expect uninitialized klasses (for non-inline classes, the receiver is either null or initialized). > > The fix is to deoptimize at defaultvalue for now and add support for runtime patching later with [JDK-8265067](https://bugs.openjdk.java.net/browse/JDK-8265067). > > Thanks, > Tobias This pull request has now been integrated. Changeset: 4f889591 Author: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/4f889591 Stats: 51 lines in 2 files changed: 49 ins; 0 del; 2 mod 8264895: [lworld] assert(!InstanceKlass::cast(receiver_klass)->is_not_initialized()) failed: receiver_klass must be initialized Reviewed-by: fparain ------------- PR: https://git.openjdk.java.net/valhalla/pull/382 From thartmann at openjdk.java.net Tue Apr 13 09:29:25 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Tue, 13 Apr 2021 09:29:25 GMT Subject: [lworld] RFR: 8265118: [lworld] C1 should optimize inline type checkcasts Message-ID: C1's `Canonicalizer::do_CheckCast` should optimize casts to inline klasses when types are known. I've added an additional test for null casts and fixed (unrelated) `TestFieldTypeMismatch.java` which was part of the wrong package. Thanks, Tobias ------------- Commit messages: - 8265118: [lworld] C1 should optimize inline type checkcasts Changes: https://git.openjdk.java.net/valhalla/pull/383/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=383&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8265118 Stats: 32 lines in 5 files changed: 18 ins; 2 del; 12 mod Patch: https://git.openjdk.java.net/valhalla/pull/383.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/383/head:pull/383 PR: https://git.openjdk.java.net/valhalla/pull/383 From fparain at openjdk.java.net Tue Apr 13 12:16:18 2021 From: fparain at openjdk.java.net (Frederic Parain) Date: Tue, 13 Apr 2021 12:16:18 GMT Subject: [lworld] RFR: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 [v3] In-Reply-To: References: Message-ID: On Mon, 12 Apr 2021 09:51:42 GMT, Nick Gasson wrote: >> We see failures like this on AArch64 when MyValue.incrementAndCheck() is >> compiled with C1: >> >> java.lang.RuntimeException: Inconsistent field values: expected 0 to equal 675128 >> at jdk.test.lib.Asserts.fail(Asserts.java:594) >> at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) >> at jdk.test.lib.Asserts.assertEQ(Asserts.java:178) >> at compiler.valhalla.inlinetypes.MyValue.incrementAndCheck(TestBufferTearing.java:81) >> at compiler.valhalla.inlinetypes.TestBufferTearing$Runner.run(TestBufferTearing.java:124) >> >> The barrier that is usually inserted on return from a method that wrote >> final fields should be sufficient to prevent another thread seeing the >> zero-initialised intermediate state. However this barrier isn't >> inserted at the moment because method()->is_object_constructor() is >> false for primitive class constructors. >> >> C2 has a similar guard around the memory barrier in Parse::do_exits(). >> I'm not sure if that needs amending as well but I've not seen any >> failures due to it. > > Nick Gasson has updated the pull request incrementally with one additional commit since the last revision: > > Add extra missing membar and simplify test Looks good to me. Thank you for finding and fixing it! Fred ------------- Marked as reviewed by fparain (Committer). PR: https://git.openjdk.java.net/valhalla/pull/376 From fparain at openjdk.java.net Tue Apr 13 17:03:27 2021 From: fparain at openjdk.java.net (Frederic Parain) Date: Tue, 13 Apr 2021 17:03:27 GMT Subject: [lworld] RFR: 8265118: [lworld] C1 should optimize inline type checkcasts In-Reply-To: References: Message-ID: On Tue, 13 Apr 2021 09:24:35 GMT, Tobias Hartmann wrote: > C1's `Canonicalizer::do_CheckCast` should optimize casts to inline klasses when types are known. > > I've added an additional test for null casts and fixed (unrelated) `TestFieldTypeMismatch.java` which was part of the wrong package. > > Thanks, > Tobias Looks good to me. Fred ------------- Marked as reviewed by fparain (Committer). PR: https://git.openjdk.java.net/valhalla/pull/383 From thartmann at openjdk.java.net Wed Apr 14 06:23:24 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Wed, 14 Apr 2021 06:23:24 GMT Subject: [lworld] RFR: 8265118: [lworld] C1 should optimize inline type checkcasts In-Reply-To: References: Message-ID: On Tue, 13 Apr 2021 09:24:35 GMT, Tobias Hartmann wrote: > C1's `Canonicalizer::do_CheckCast` should optimize casts to inline klasses when types are known. > > I've added an additional test for null casts and fixed (unrelated) `TestFieldTypeMismatch.java` which was part of the wrong package. > > Thanks, > Tobias Thanks for the review, Fred! ------------- PR: https://git.openjdk.java.net/valhalla/pull/383 From thartmann at openjdk.java.net Wed Apr 14 06:23:25 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Wed, 14 Apr 2021 06:23:25 GMT Subject: [lworld] Integrated: 8265118: [lworld] C1 should optimize inline type checkcasts In-Reply-To: References: Message-ID: <69PH7z6aJvJcEmVMcbrSMgjV8n8yC7c0WxoHp80gF0c=.5f00075c-357f-45a9-96ed-36a1e59ecfcc@github.com> On Tue, 13 Apr 2021 09:24:35 GMT, Tobias Hartmann wrote: > C1's `Canonicalizer::do_CheckCast` should optimize casts to inline klasses when types are known. > > I've added an additional test for null casts and fixed (unrelated) `TestFieldTypeMismatch.java` which was part of the wrong package. > > Thanks, > Tobias This pull request has now been integrated. Changeset: e9c78ce4 Author: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/e9c78ce4 Stats: 32 lines in 5 files changed: 18 ins; 2 del; 12 mod 8265118: [lworld] C1 should optimize inline type checkcasts Reviewed-by: fparain ------------- PR: https://git.openjdk.java.net/valhalla/pull/383 From ngasson at openjdk.java.net Wed Apr 14 08:49:29 2021 From: ngasson at openjdk.java.net (Nick Gasson) Date: Wed, 14 Apr 2021 08:49:29 GMT Subject: [lworld] RFR: 8265184: [lworld] [AArch64] Broken fast class init barrier for static calls in c2i adapter Message-ID: The tier1 test runtime/clinit/ClassInitBarrier.java fails on the lworld branch on AArch64. The particular case that fails is calling a static native method `A.staticN()` which should block in the c2i adapter until class A's initialisation is complete but doesn't. The check for a static method is backwards: the class initialisation barrier code is executed when the method is *not* static (ANDS will set the EQ flag if the result is zero). I'm not sure why it's like this but fast class initialisation for AArch64 was added after the original lworld port which also touches generate_i2c2i_adapters so maybe something got messed up in the merge. Fix by making the code the same as mainline. ------------- Commit messages: - 8265184: [lworld] [AArch64] Broken fast class init barrier for static calls in c2i adapter Changes: https://git.openjdk.java.net/valhalla/pull/384/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=384&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8265184 Stats: 12 lines in 1 file changed: 1 ins; 5 del; 6 mod Patch: https://git.openjdk.java.net/valhalla/pull/384.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/384/head:pull/384 PR: https://git.openjdk.java.net/valhalla/pull/384 From thartmann at openjdk.java.net Wed Apr 14 12:00:16 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Wed, 14 Apr 2021 12:00:16 GMT Subject: [lworld] RFR: 8265184: [lworld] [AArch64] Broken fast class init barrier for static calls in c2i adapter In-Reply-To: References: Message-ID: On Wed, 14 Apr 2021 08:44:34 GMT, Nick Gasson wrote: > The tier1 test runtime/clinit/ClassInitBarrier.java fails on the lworld > branch on AArch64. The particular case that fails is calling a static > native method `A.staticN()` which should block in the c2i adapter until > class A's initialisation is complete but doesn't. > > The check for a static method is backwards: the class initialisation > barrier code is executed when the method is *not* static (ANDS will set > the EQ flag if the result is zero). I'm not sure why it's like this but > fast class initialisation for AArch64 was added after the original > lworld port which also touches generate_i2c2i_adapters so maybe > something got messed up in the merge. > > Fix by making the code the same as mainline. Looks good to me! I think the fix for [JDK-8230962](https://bugs.openjdk.java.net/browse/JDK-8230962) broke this. ------------- Marked as reviewed by thartmann (Committer). PR: https://git.openjdk.java.net/valhalla/pull/384 From yyang at openjdk.java.net Thu Apr 15 03:03:50 2021 From: yyang at openjdk.java.net (Yi Yang) Date: Thu, 15 Apr 2021 03:03:50 GMT Subject: [lworld] RFR: 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return Message-ID: Try to reuse existing BarrierSetC2::obj_allocate functionality for PhaseMacroExpand::expand_mh_intrinsic_return. Testing: x86_64 + linux+ slowdebug/release [x] test/hotspot/jtreg/runtime/valhalla [x] test/hotspot/jtreg/compiler/valhalla Thanks! Yang ------------- Commit messages: - trailing whitespace - reuse obj_allocate PhaseMacroExpand::expand_mh_intrinsic_return Changes: https://git.openjdk.java.net/valhalla/pull/385/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=385&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8264897 Stats: 104 lines in 1 file changed: 26 ins; 43 del; 35 mod Patch: https://git.openjdk.java.net/valhalla/pull/385.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/385/head:pull/385 PR: https://git.openjdk.java.net/valhalla/pull/385 From ngasson at openjdk.java.net Thu Apr 15 05:04:47 2021 From: ngasson at openjdk.java.net (Nick Gasson) Date: Thu, 15 Apr 2021 05:04:47 GMT Subject: [lworld] RFR: 8265184: [lworld] [AArch64] Broken fast class init barrier for static calls in c2i adapter In-Reply-To: References: Message-ID: On Wed, 14 Apr 2021 11:57:24 GMT, Tobias Hartmann wrote: >> The tier1 test runtime/clinit/ClassInitBarrier.java fails on the lworld >> branch on AArch64. The particular case that fails is calling a static >> native method `A.staticN()` which should block in the c2i adapter until >> class A's initialisation is complete but doesn't. >> >> The check for a static method is backwards: the class initialisation >> barrier code is executed when the method is *not* static (ANDS will set >> the EQ flag if the result is zero). I'm not sure why it's like this but >> fast class initialisation for AArch64 was added after the original >> lworld port which also touches generate_i2c2i_adapters so maybe >> something got messed up in the merge. >> >> Fix by making the code the same as mainline. > > Looks good to me! I think the fix for [JDK-8230962](https://bugs.openjdk.java.net/browse/JDK-8230962) broke this. Thanks for the review @TobiHartmann . Would you mind sponsoring this one and #376 ? ------------- PR: https://git.openjdk.java.net/valhalla/pull/384 From ngasson at openjdk.java.net Thu Apr 15 06:29:51 2021 From: ngasson at openjdk.java.net (Nick Gasson) Date: Thu, 15 Apr 2021 06:29:51 GMT Subject: [lworld] Integrated: 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 In-Reply-To: References: Message-ID: On Thu, 1 Apr 2021 10:08:45 GMT, Nick Gasson wrote: > We see failures like this on AArch64 when MyValue.incrementAndCheck() is > compiled with C1: > > java.lang.RuntimeException: Inconsistent field values: expected 0 to equal 675128 > at jdk.test.lib.Asserts.fail(Asserts.java:594) > at jdk.test.lib.Asserts.assertEquals(Asserts.java:205) > at jdk.test.lib.Asserts.assertEQ(Asserts.java:178) > at compiler.valhalla.inlinetypes.MyValue.incrementAndCheck(TestBufferTearing.java:81) > at compiler.valhalla.inlinetypes.TestBufferTearing$Runner.run(TestBufferTearing.java:124) > > The barrier that is usually inserted on return from a method that wrote > final fields should be sufficient to prevent another thread seeing the > zero-initialised intermediate state. However this barrier isn't > inserted at the moment because method()->is_object_constructor() is > false for primitive class constructors. > > C2 has a similar guard around the memory barrier in Parse::do_exits(). > I'm not sure if that needs amending as well but I've not seen any > failures due to it. This pull request has now been integrated. Changeset: 2e6c276a Author: Nick Gasson Committer: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/2e6c276a Stats: 138 lines in 3 files changed: 137 ins; 0 del; 1 mod 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 Reviewed-by: thartmann, fparain ------------- PR: https://git.openjdk.java.net/valhalla/pull/376 From thartmann at openjdk.java.net Thu Apr 15 06:31:42 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Thu, 15 Apr 2021 06:31:42 GMT Subject: [lworld] RFR: 8265184: [lworld] [AArch64] Broken fast class init barrier for static calls in c2i adapter In-Reply-To: References: Message-ID: <8hEANpuAMSwuZ7GRF65i6BlEvxWL0EHlE2OwiDH6tSs=.a6632504-8fae-477e-8e8c-af3e5e9d7a99@github.com> On Wed, 14 Apr 2021 08:44:34 GMT, Nick Gasson wrote: > The tier1 test runtime/clinit/ClassInitBarrier.java fails on the lworld > branch on AArch64. The particular case that fails is calling a static > native method `A.staticN()` which should block in the c2i adapter until > class A's initialisation is complete but doesn't. > > The check for a static method is backwards: the class initialisation > barrier code is executed when the method is *not* static (ANDS will set > the EQ flag if the result is zero). I'm not sure why it's like this but > fast class initialisation for AArch64 was added after the original > lworld port which also touches generate_i2c2i_adapters so maybe > something got messed up in the merge. > > Fix by making the code the same as mainline. Sure! ------------- PR: https://git.openjdk.java.net/valhalla/pull/384 From ngasson at openjdk.java.net Thu Apr 15 06:31:42 2021 From: ngasson at openjdk.java.net (Nick Gasson) Date: Thu, 15 Apr 2021 06:31:42 GMT Subject: [lworld] Integrated: 8265184: [lworld] [AArch64] Broken fast class init barrier for static calls in c2i adapter In-Reply-To: References: Message-ID: On Wed, 14 Apr 2021 08:44:34 GMT, Nick Gasson wrote: > The tier1 test runtime/clinit/ClassInitBarrier.java fails on the lworld > branch on AArch64. The particular case that fails is calling a static > native method `A.staticN()` which should block in the c2i adapter until > class A's initialisation is complete but doesn't. > > The check for a static method is backwards: the class initialisation > barrier code is executed when the method is *not* static (ANDS will set > the EQ flag if the result is zero). I'm not sure why it's like this but > fast class initialisation for AArch64 was added after the original > lworld port which also touches generate_i2c2i_adapters so maybe > something got messed up in the merge. > > Fix by making the code the same as mainline. This pull request has now been integrated. Changeset: 301de8d1 Author: Nick Gasson Committer: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/301de8d1 Stats: 12 lines in 1 file changed: 1 ins; 5 del; 6 mod 8265184: [lworld] [AArch64] Broken fast class init barrier for static calls in c2i adapter Reviewed-by: thartmann ------------- PR: https://git.openjdk.java.net/valhalla/pull/384 From thartmann at openjdk.java.net Fri Apr 16 06:37:59 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Fri, 16 Apr 2021 06:37:59 GMT Subject: [lworld] RFR: 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return In-Reply-To: References: Message-ID: On Thu, 15 Apr 2021 02:55:25 GMT, Yi Yang wrote: > Try to reuse existing BarrierSetC2::obj_allocate functionality for PhaseMacroExpand::expand_mh_intrinsic_return. > > Testing: x86_64 + linux+ slowdebug/release > [x] test/hotspot/jtreg/runtime/valhalla > [x] test/hotspot/jtreg/compiler/valhalla > > Thanks, > Yang Nice cleanup! I've added some minor comments, otherwise looks good to me. src/hotspot/share/opto/macro.cpp line 2745: > 2743: > 2744: // Try to allocate a new buffered inline instance either from TLAB or eden space > 2745: Node* needgc_ctrl; // needgc means slowcase, i.e. allocation failed Should be initialized to `NULL`. src/hotspot/share/opto/macro.cpp line 2824: > 2822: if (domain->field_at(i) == Type::HALF) { > 2823: slow_call->init_req(i, top()); > 2824: if (alloc_in_place) handler_call->init_req(i+1, top()); Please use parentheses for the if body. Same below. src/hotspot/share/opto/macro.cpp line 2838: > 2836: Node* fast_ctl; > 2837: Node* fast_res; > 2838: MergeMemNode* fast_mem; Should be initialized to `NULL`. src/hotspot/share/opto/macro.cpp line 2848: > 2846: } > 2847: > 2848: Node* r = new RegionNode(alloc_in_place ? 4: 3); Whitespace missing, should be `? 4 : 3` src/hotspot/share/opto/macro.cpp line 3239: > 3237: case Node::Class_FlatArrayCheck: > 3238: expand_flatarraycheck_node(n->as_FlatArrayCheck()); > 3239: assert(C->macro_count() == (old_macro_count - 1), "expansion must have deleted one node from macro list"); Why did you delete these asserts? ------------- Marked as reviewed by thartmann (Committer). PR: https://git.openjdk.java.net/valhalla/pull/385 From yyang at openjdk.java.net Fri Apr 16 08:36:54 2021 From: yyang at openjdk.java.net (Yi Yang) Date: Fri, 16 Apr 2021 08:36:54 GMT Subject: [lworld] RFR: 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return In-Reply-To: References: Message-ID: On Thu, 15 Apr 2021 02:55:25 GMT, Yi Yang wrote: > Try to reuse existing BarrierSetC2::obj_allocate functionality for PhaseMacroExpand::expand_mh_intrinsic_return. > > Testing: x86_64 + linux+ slowdebug/release > [x] test/hotspot/jtreg/runtime/valhalla > [x] test/hotspot/jtreg/compiler/valhalla > > Thanks, > Yang Thank you Tobias! Sorry for so many nits, I will check them more carefully in later PRs. Best Regards, Yang ------------- PR: https://git.openjdk.java.net/valhalla/pull/385 From yyang at openjdk.java.net Fri Apr 16 08:41:57 2021 From: yyang at openjdk.java.net (Yi Yang) Date: Fri, 16 Apr 2021 08:41:57 GMT Subject: [lworld] RFR: 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return In-Reply-To: References: Message-ID: <7DX-vy-2dUvFnpPTCyYt0azHfkfKV3dxHVL4_tfzcCY=.8e2b4b9e-b7fc-4ab3-a7e3-6286f4ed21d7@github.com> On Fri, 16 Apr 2021 06:23:09 GMT, Tobias Hartmann wrote: >> Try to reuse existing BarrierSetC2::obj_allocate functionality for PhaseMacroExpand::expand_mh_intrinsic_return. >> >> Testing: x86_64 + linux+ slowdebug/release >> [x] test/hotspot/jtreg/runtime/valhalla >> [x] test/hotspot/jtreg/compiler/valhalla >> >> Thanks, >> Yang > > src/hotspot/share/opto/macro.cpp line 3239: > >> 3237: case Node::Class_FlatArrayCheck: >> 3238: expand_flatarraycheck_node(n->as_FlatArrayCheck()); >> 3239: assert(C->macro_count() == (old_macro_count - 1), "expansion must have deleted one node from macro list"); > > Why did you delete these asserts? It seems the checking happens nevertheless right after switch: https://github.com/openjdk/valhalla/blob/5e88e8a08c4532840c66177e0032953ba6e2956c/src/hotspot/share/opto/macro.cpp#L3220-L3227 ------------- PR: https://git.openjdk.java.net/valhalla/pull/385 From sadayapalam at openjdk.java.net Fri Apr 16 12:19:13 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Fri, 16 Apr 2021 12:19:13 GMT Subject: [lworld] RFR: 8244313: [lworld] Evolve javac's code generation to match scheme documented in SoV Message-ID: Generate code according to the scheme outlined in the Members section of https://cr.openjdk.java.net/~briangoetz/valhalla/sov/04-translation.html ------------- Commit messages: - 8244313: Evolve javac's code generation to match scheme documented in SoV Changes: https://git.openjdk.java.net/valhalla/pull/386/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=386&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8244313 Stats: 258 lines in 12 files changed: 147 ins; 41 del; 70 mod Patch: https://git.openjdk.java.net/valhalla/pull/386.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/386/head:pull/386 PR: https://git.openjdk.java.net/valhalla/pull/386 From sadayapalam at openjdk.java.net Fri Apr 16 12:23:49 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Fri, 16 Apr 2021 12:23:49 GMT Subject: [lworld] RFR: 8244313: [lworld] Evolve javac's code generation to match scheme documented in SoV In-Reply-To: References: Message-ID: On Fri, 16 Apr 2021 12:12:32 GMT, Srikanth Adayapalam wrote: > Generate code according to the scheme outlined in the Members section of https://cr.openjdk.java.net/~briangoetz/valhalla/sov/04-translation.html Hotspot compiler folk, This change set is failing a bunch of tests compiler/valhalla/inlinetypes. I believe this is due to problems in the hotspot compiler. Analysis here: 1. These three tests generate SIGSEGV: - TestBasicFunctionality.java - TestC2CCalls.java - TestLWorld.java 2. These two tests trigger a RuntimeException: Unexpected compilation level for ... - TestCallingConvention.java - TestOnStackReplacement.java 3. This test generates a CCE in compiled code, bytecode looks reasonable: - TestCallingConventionC1.java 4. This test triggers a runtime assertion: "RuntimeException: assertEquals: expected [compiler.valhalla.inlinetypes.TestNullableArrays$Complex re=291.0 im=291.0] to equal [compiler.valhalla.inlinetypes.TestNullableArrays$Complex re=291.0 im=169653.0]" - TestNullableArrays.java Thanks for looking into these. If you can provide a fix in time, I can include it in the integration. ------------- PR: https://git.openjdk.java.net/valhalla/pull/386 From sadayapalam at openjdk.java.net Fri Apr 16 12:31:45 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Fri, 16 Apr 2021 12:31:45 GMT Subject: [lworld] RFR: 8244313: [lworld] Evolve javac's code generation to match scheme documented in SoV In-Reply-To: References: Message-ID: On Fri, 16 Apr 2021 12:12:32 GMT, Srikanth Adayapalam wrote: > Generate code according to the scheme outlined in the Members section of https://cr.openjdk.java.net/~briangoetz/valhalla/sov/04-translation.html hotspot-runtime folks, This patch is failing one test: runtime/valhalla/inlinetypes/CircularityTest.java, I think under the code generation scheme outlined in https://cr.openjdk.java.net/~briangoetz/valhalla/sov/04-translation.html, this test's expectation of a circularity being found is not valid per a cursory glance, Thanks for looking into it - If you can provide a fix in time, I can include it in the integration. JDK corelibs folks, This patch is failing two tests that make a bad assumption that were only true because javac was not following the recommended code generation scheme outlined in the Members section of https://cr.openjdk.java.net/~briangoetz/valhalla/sov/04-translation.html Thanks for looking into it - If you can provide a fix in time, I can include it in the integration. ------------- PR: https://git.openjdk.java.net/valhalla/pull/386 From mcimadamore at openjdk.java.net Fri Apr 16 16:41:06 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Fri, 16 Apr 2021 16:41:06 GMT Subject: [lworld] RFR: 8244313: [lworld] Evolve javac's code generation to match scheme documented in SoV In-Reply-To: References: Message-ID: On Fri, 16 Apr 2021 12:12:32 GMT, Srikanth Adayapalam wrote: > Generate code according to the scheme outlined in the Members section of https://cr.openjdk.java.net/~briangoetz/valhalla/sov/04-translation.html I have some question regarding constant pool switching src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java line 546: > 544: } > 545: > 546: void switchPool() { Can you explain the rationale behind going down this path, instead of creating a new pool? E.g. could we call ClassWriter.writeClass on two symbols, instead of having a single call generate two things by using this constant pool switching? It feels like I'm missing something here... ------------- PR: https://git.openjdk.java.net/valhalla/pull/386 From mchung at openjdk.java.net Fri Apr 16 20:28:23 2021 From: mchung at openjdk.java.net (Mandy Chung) Date: Fri, 16 Apr 2021 20:28:23 GMT Subject: [lworld] RFR: JDK-8265376: Prepare for javac change to do the member translation as described in SoV Message-ID: This updates `test/jdk/valhalla/valuetypes/QTypeDescriptorTest.java` and `test/jdk/valhalla/valuetypes/Reflection.java` tests to prepare for the javac change to do the member translation as described in SoV (JDK-8244313). It also fixes a bug in `Class::referenceType` to return this class if it's an identity class. This was uncovered by this test change. ------------- Commit messages: - JDK-8265376: Prepare for javac change to do the member translation as described in SoV Changes: https://git.openjdk.java.net/valhalla/pull/387/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=387&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8265376 Stats: 109 lines in 3 files changed: 91 ins; 1 del; 17 mod Patch: https://git.openjdk.java.net/valhalla/pull/387.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/387/head:pull/387 PR: https://git.openjdk.java.net/valhalla/pull/387 From sadayapalam at openjdk.java.net Fri Apr 16 20:46:52 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Fri, 16 Apr 2021 20:46:52 GMT Subject: [lworld] RFR: JDK-8265376: Prepare for javac change to do the member translation as described in SoV In-Reply-To: References: Message-ID: <5O6kDuk5dJetPosbdTpbSo9ErDTVQZMbljfGQqSS9CY=.d319b31c-5b11-4fbf-8db1-3128f03c65a4@github.com> On Fri, 16 Apr 2021 20:19:35 GMT, Mandy Chung wrote: > This updates `test/jdk/valhalla/valuetypes/QTypeDescriptorTest.java` and > `test/jdk/valhalla/valuetypes/Reflection.java` tests to prepare for the javac > change to do the member translation as described in SoV (JDK-8244313). > > It also fixes a bug in `Class::referenceType` to return this class if it's an > identity class. This was uncovered by this test change. There is some debate whether we should go ahead with integrating with https://github.com/openjdk/valhalla/pull/386 at all, this is being discussed (we may want to double down on the explorations for a single class file for primitive classes instead). Stay tuned. Thanks for quickly preparing the fix all the same!. ------------- PR: https://git.openjdk.java.net/valhalla/pull/387 From mchung at openjdk.java.net Fri Apr 16 22:08:51 2021 From: mchung at openjdk.java.net (Mandy Chung) Date: Fri, 16 Apr 2021 22:08:51 GMT Subject: [lworld] RFR: JDK-8265376: Prepare for javac change to do the member translation as described in SoV In-Reply-To: References: Message-ID: On Fri, 16 Apr 2021 20:19:35 GMT, Mandy Chung wrote: > This updates `test/jdk/valhalla/valuetypes/QTypeDescriptorTest.java` and > `test/jdk/valhalla/valuetypes/Reflection.java` tests to prepare for the javac > change to do the member translation as described in SoV (JDK-8244313). > > It also fixes a bug in `Class::referenceType` to return this class if it's an > identity class. This was uncovered by this test change. This change is independent with the fix for JDK-8244313. JDK-8244313 will still have to update these 2 tests (uncomment the lines marked with TODO comments). ------------- PR: https://git.openjdk.java.net/valhalla/pull/387 From sadayapalam at openjdk.java.net Sat Apr 17 01:33:49 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Sat, 17 Apr 2021 01:33:49 GMT Subject: [lworld] RFR: JDK-8265376: Prepare for javac change to do the member translation as described in SoV In-Reply-To: References: Message-ID: On Fri, 16 Apr 2021 22:05:58 GMT, Mandy Chung wrote: > This change is independent with the fix for JDK-8244313. JDK-8244313 will still have to update these 2 tests (uncomment the lines marked with TODO comments). I see, that is great then :) Thanks Mandy! ------------- PR: https://git.openjdk.java.net/valhalla/pull/387 From yyang at openjdk.java.net Mon Apr 19 02:54:22 2021 From: yyang at openjdk.java.net (Yi Yang) Date: Mon, 19 Apr 2021 02:54:22 GMT Subject: [lworld] RFR: 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return [v2] In-Reply-To: References: Message-ID: <474s6lfuMaaLXw2e4T31qwF0W5F_ZVWlzv_XMmm36zQ=.2982622c-7054-44ca-b572-0be28aeb62b9@github.com> > Try to reuse existing BarrierSetC2::obj_allocate functionality for PhaseMacroExpand::expand_mh_intrinsic_return. > > Testing: x86_64 + linux+ slowdebug/release > [x] test/hotspot/jtreg/runtime/valhalla > [x] test/hotspot/jtreg/compiler/valhalla > > Thanks, > Yang Yi Yang has updated the pull request incrementally with two additional commits since the last revision: - more cleanup - eliminate nits ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/385/files - new: https://git.openjdk.java.net/valhalla/pull/385/files/5e88e8a0..863e3504 Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=385&range=01 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=385&range=00-01 Stats: 16 lines in 1 file changed: 6 ins; 0 del; 10 mod Patch: https://git.openjdk.java.net/valhalla/pull/385.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/385/head:pull/385 PR: https://git.openjdk.java.net/valhalla/pull/385 From sadayapalam at openjdk.java.net Mon Apr 19 06:19:59 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Mon, 19 Apr 2021 06:19:59 GMT Subject: [lworld] RFR: 8244313: [lworld] Evolve javac's code generation to match scheme documented in SoV In-Reply-To: References: Message-ID: On Fri, 16 Apr 2021 12:12:32 GMT, Srikanth Adayapalam wrote: > Generate code according to the scheme outlined in the Members section of https://cr.openjdk.java.net/~briangoetz/valhalla/sov/04-translation.html The comment in com.sun.tools.javac.jvm.ClassWriter#writeClassFile poolWriter.writePool(out); poolWriter.reset(); // to save space misstates what we are doing there IMO :) ------------- PR: https://git.openjdk.java.net/valhalla/pull/386 From sadayapalam at openjdk.java.net Mon Apr 19 06:20:00 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Mon, 19 Apr 2021 06:20:00 GMT Subject: [lworld] RFR: 8244313: [lworld] Evolve javac's code generation to match scheme documented in SoV In-Reply-To: References: Message-ID: On Fri, 16 Apr 2021 16:37:12 GMT, Maurizio Cimadamore wrote: >> Generate code according to the scheme outlined in the Members section of https://cr.openjdk.java.net/~briangoetz/valhalla/sov/04-translation.html > > src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java line 546: > >> 544: } >> 545: >> 546: void switchPool() { > > Can you explain the rationale behind going down this path, instead of creating a new pool? E.g. could we call ClassWriter.writeClass on two symbols, instead of having a single call generate two things by using this constant pool switching? It feels like I'm missing something here... Obviously, different approaches possible. I am documenting my chain of thoughts/observations here: - Each invocation of the javac compiler, gets a single ClassWriter instance and a single instance of the byte code generator Gen. - The single instance of the code generator Gen instantiates a single instance of the PoolWriter - The Pool writer manages all the state associated with the constant pool - Given a single invocation of the compiler may call for compiling numerous classes and generating numerous class files, and since each class file has its own constant pool, as each JCClassDecl advances through Gen and gets written out into a class file, the ClassWriter calls PoolWriter.reset() after finished with a writing out a class file. This is so as to allow for the slate to be wiped clean in preparation for the next JCClassDecl being fed to Gen. It is conceivable that we could have bifurcated the the primitive class source declaration into two completely different ASTs, one rooted at a JCClassDecl for the value projection class and another rooted at a at a JCClassDecl for the reference projection class, each with its own members according the members sorting algorithm outlined in SoV4 and inject them into the pipeline at the suitable stage. Each JCClassDecl advances through the byte code generator Gen and the ClassWriter on its own, gets its own pool and gets written out on its own in this block in com.sun.tools.javac.main.JavaCompiler#genCode JavaFileObject genCode(Env env, JCClassDecl cdef) throws IOException { try { if (gen.genClass(env, cdef) && (errorCount() == 0)) return writer.writeClass(cdef.sym); } catch (ClassWriter.PoolOverflow ex) { log.error(cdef.pos(), Errors.LimitPool); } catch (ClassWriter.StringOverflow ex) { log.error(cdef.pos(), Errors.LimitStringOverflow(ex.value.substring(0, 20))); } catch (CompletionFailure ex) { chk.completionError(cdef.pos(), ex); } return null; } Which approach is better may boil down to a matter of taste. I found it extremely simple and straightforward to enhance the PoolWriter to operate on bipartite pools. ------------- PR: https://git.openjdk.java.net/valhalla/pull/386 From mcimadamore at openjdk.java.net Mon Apr 19 10:22:12 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Mon, 19 Apr 2021 10:22:12 GMT Subject: [lworld] RFR: 8244313: [lworld] Evolve javac's code generation to match scheme documented in SoV In-Reply-To: References: Message-ID: On Mon, 19 Apr 2021 06:14:43 GMT, Srikanth Adayapalam wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java line 546: >> >>> 544: } >>> 545: >>> 546: void switchPool() { >> >> Can you explain the rationale behind going down this path, instead of creating a new pool? E.g. could we call ClassWriter.writeClass on two symbols, instead of having a single call generate two things by using this constant pool switching? It feels like I'm missing something here... > > Obviously, different approaches possible. > > I am documenting my chain of thoughts/observations here: > > - Each invocation of the javac compiler, gets a single ClassWriter instance and a single instance of the byte code generator Gen. > - The single instance of the code generator Gen instantiates a single instance of the PoolWriter > - The Pool writer manages all the state associated with the constant pool > - Given a single invocation of the compiler may call for compiling numerous classes and generating numerous class files, and since each class file has its own constant pool, as each JCClassDecl advances through Gen and gets written out into a class file, the ClassWriter calls PoolWriter.reset() after finished with a writing out a class file. This is so as to allow for the slate to be wiped clean in preparation for the next JCClassDecl being fed to Gen. > > It is conceivable that we could have bifurcated the the primitive class source declaration into two completely different ASTs, one rooted at a JCClassDecl for the value projection class and another rooted at a at a JCClassDecl for the reference projection class, each with its own members according the members sorting algorithm outlined in SoV4 and inject them into the pipeline at the suitable stage. Each JCClassDecl advances through the byte code generator Gen and the ClassWriter on its own, gets its own pool and gets written out on its own in this block in com.sun.tools.javac.main.JavaCompiler#genCode > > > JavaFileObject genCode(Env env, JCClassDecl cdef) throws IOException { > try { > if (gen.genClass(env, cdef) && (errorCount() == 0)) > return writer.writeClass(cdef.sym); > } catch (ClassWriter.PoolOverflow ex) { > log.error(cdef.pos(), Errors.LimitPool); > } catch (ClassWriter.StringOverflow ex) { > log.error(cdef.pos(), > Errors.LimitStringOverflow(ex.value.substring(0, 20))); > } catch (CompletionFailure ex) { > chk.completionError(cdef.pos(), ex); > } > return null; > } > > The three abstractions involved i.e Gen, PoolWriter and ClassWriter each is "aware" of the fact that a single JCClassDecl that is advancing through the pipeline is going to be bifurcated down the road at the deep end and handshake with each other to achieve this end goal. > > Alternate implementations where one or more these abstractions are completely oblivious to the bifurcation taking place are possible. > > Which approach is better may boil down to a matter of taste. I found it extremely simple and straightforward to enhance the PoolWriter to operate on bipartite pool by having each of these three abstractions be "clued into the goings on". Trying to understand - is switchPool called only once? If so, can't we replace switchPool by simply creating a new PoolWriter? I know that, up to now, we had only one instance of PW, but of the various abstractions, PW seems the one that is more amenable in terms of spawning new instances? ------------- PR: https://git.openjdk.java.net/valhalla/pull/386 From mcimadamore at openjdk.java.net Mon Apr 19 10:26:59 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Mon, 19 Apr 2021 10:26:59 GMT Subject: [lworld] RFR: 8244313: [lworld] Evolve javac's code generation to match scheme documented in SoV In-Reply-To: References: Message-ID: On Mon, 19 Apr 2021 10:18:44 GMT, Maurizio Cimadamore wrote: >> Obviously, different approaches possible. >> >> I am documenting my chain of thoughts/observations here: >> >> - Each invocation of the javac compiler, gets a single ClassWriter instance and a single instance of the byte code generator Gen. >> - The single instance of the code generator Gen instantiates a single instance of the PoolWriter >> - The Pool writer manages all the state associated with the constant pool >> - Given a single invocation of the compiler may call for compiling numerous classes and generating numerous class files, and since each class file has its own constant pool, as each JCClassDecl advances through Gen and gets written out into a class file, the ClassWriter calls PoolWriter.reset() after finished with a writing out a class file. This is so as to allow for the slate to be wiped clean in preparation for the next JCClassDecl being fed to Gen. >> >> It is conceivable that we could have bifurcated the the primitive class source declaration into two completely different ASTs, one rooted at a JCClassDecl for the value projection class and another rooted at a at a JCClassDecl for the reference projection class, each with its own members according the members sorting algorithm outlined in SoV4 and inject them into the pipeline at the suitable stage. Each JCClassDecl advances through the byte code generator Gen and the ClassWriter on its own, gets its own pool and gets written out on its own in this block in com.sun.tools.javac.main.JavaCompiler#genCode >> >> >> JavaFileObject genCode(Env env, JCClassDecl cdef) throws IOException { >> try { >> if (gen.genClass(env, cdef) && (errorCount() == 0)) >> return writer.writeClass(cdef.sym); >> } catch (ClassWriter.PoolOverflow ex) { >> log.error(cdef.pos(), Errors.LimitPool); >> } catch (ClassWriter.StringOverflow ex) { >> log.error(cdef.pos(), >> Errors.LimitStringOverflow(ex.value.substring(0, 20))); >> } catch (CompletionFailure ex) { >> chk.completionError(cdef.pos(), ex); >> } >> return null; >> } >> >> The three abstractions involved i.e Gen, PoolWriter and ClassWriter each is "aware" of the fact that a single JCClassDecl that is advancing through the pipeline is going to be bifurcated down the road at the deep end and handshake with each other to achieve this end goal. >> >> Alternate implementations where one or more these abstractions are completely oblivious to the bifurcation taking place are possible. >> >> Which approach is better may boil down to a matter of taste. I found it extremely simple and straightforward to enhance the PoolWriter to operate on bipartite pool by having each of these three abstractions be "clued into the goings on". > > Trying to understand - is switchPool called only once? > If so, can't we replace switchPool by simply creating a new PoolWriter? I know that, up to now, we had only one instance of PW, but of the various abstractions, PW seems the one that is more amenable in terms of spawning new instances? Ok, I see - switch pool is also called from ClassWriter whenever we need to add a new symbol to the pool and we see that the symbol belongs to a different projection. I guess the approach that seems intuitively more natural to me (as it requires less modifiable state) is one where we create _two_ ClassWriter instances for the same symbol/AST - but one on the reference projection polarity, the other on the inline polarity. Symbols that do not belong to the correct polarity are just skipped. I agree that splitting JCClassDecl seems like overkill for this. ------------- PR: https://git.openjdk.java.net/valhalla/pull/386 From mcimadamore at openjdk.java.net Mon Apr 19 10:31:54 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Mon, 19 Apr 2021 10:31:54 GMT Subject: [lworld] RFR: 8244313: [lworld] Evolve javac's code generation to match scheme documented in SoV In-Reply-To: References: Message-ID: On Mon, 19 Apr 2021 10:22:45 GMT, Maurizio Cimadamore wrote: >> Trying to understand - is switchPool called only once? >> If so, can't we replace switchPool by simply creating a new PoolWriter? I know that, up to now, we had only one instance of PW, but of the various abstractions, PW seems the one that is more amenable in terms of spawning new instances? > > Ok, I see - switch pool is also called from ClassWriter whenever we need to add a new symbol to the pool and we see that the symbol belongs to a different projection. > > I guess the approach that seems intuitively more natural to me (as it requires less modifiable state) is one where we create _two_ ClassWriter instances for the same symbol/AST - but one on the reference projection polarity, the other on the inline polarity. Symbols that do not belong to the correct polarity are just skipped. > > I agree that splitting JCClassDecl seems like overkill for this. I now see where my "intuitive" idea falls apart: Gen is doing some of the work which causes entries to be written to the pool (e.g. visitMethod). E.g. by the time we get to ClassWriter, the pool is already partially written. This is probably what motivated the split at that level. So, I agree, it's either current approach, with mutable pool writer, or one where we have two JCClassDecl (and two Gen passes). Ugh. ------------- PR: https://git.openjdk.java.net/valhalla/pull/386 From jdk at fiolino.de Tue Apr 20 13:29:21 2021 From: jdk at fiolino.de (Michael Kuhlmann) Date: Tue, 20 Apr 2021 15:29:21 +0200 Subject: New candidate JEP: 401: Primitive Objects (Preview) In-Reply-To: <20210317214943.085423DBBFE@eggemoggin.niobe.net> References: <20210317214943.085423DBBFE@eggemoggin.niobe.net> Message-ID: <196cc359-14f3-59d5-b0ba-69f47a8647b7@fiolino.de> Hi, sorry to coming back to this topic after more than a month, but I thought about it several times and want to share my thoughts. Maybe the ideas are long discussed already and nobody wants to read about it any more, but I looked in the archives and didn't find anything, so I'll give it a try. If it's a stupid idea, just let me know, I can live with that. I'm not a contributor, but I'm using Java for more than twenty years, since Java 1.1 precisely. I really love the idea of having primitive classes, that would be amazing! I'm just concerned that we won't make the best use out of it, especially because of compatibility reasons, and I was wondering if this can be achieved with a simple design change. The problems I'm seeing: * Primitive classes behave very different from standard object classes, but users don't immediately see this. You have to look into the definition to know whether an instance variable of SomeType will be initialized with null or a default value. * The suffixes .ref and .val don't fit into our concept of class names, they look ugly and can easily be mixed up * That we have to introduce .rel just for the existing classes is even worse * Existing classes like Optional will be mostly used in their original form. That's unfortunate, not that much for performance reasons but rather because such a value should never be null, so it could make most use out of this concept. * There's already the discussion to delay the implementation of typical primitive classes. Raffaelo proposed to invent classes Decimal64 and Decimal128, but it will not be added before this JEP is going live to avoid the need of the ugly compatibility hack. * We have to treat the seven existing primitive types in a very special way. People are already used to the idea that normal classes start with an uppercase character, but primitives are in lowercase characters. The predecessor language Oak even defined string as a primitive type. So why not picking up this idea and forcing all future primitive types to start with lowercase characters as well? Java has been very concrete in style guides but very relaxed in enforcing them in the past. You can define a class named 'integer' without problems. I would see this as a design bug and would rather enforce some stricter rules. So we could make it mandatory to have all primitive class names start with a lowercase character, more concrete to a character that can be converted to an uppercase character. Instead of creating a twin class names 'someClass.ref' what is proposed in the JEP, the reference class could be named like the primitive class just starting with the uppercase character. So if you define a primitive class 'someType', you immediately have a reference type 'SomeType' defined as well. Existing classes can be directly converted to primitive classes without breaking backwards compatibility. For instance, Optional would be declared as a primitive class 'optional', and existing code would still refer to the reference type 'Optional'. No special treatment of existing classes! Also Raffaelo can already add Decimal64 and Decimal128 to the JDK. Once this JEP is live, he only has to change the 'final' modifier to 'primitive' and make the 'D' in the class name lowercase. That's it! This is even more important for libraries who want to stay compatible for existing JDK releases and want to make use of this feature only later. There are some more benefits: * Primitive types are immediately identifiable by their class name * No ugly suffixes! * The naming fits very well into the existing primitives. long, float, boolean etc. already match with their wrapper classes Long, Float, Boolean. Only int and char have to be defined as aliases, as already proposed in the JEP. (I know that these primitives still need special handling under the hood, but I assume it won't be bigger than in the proposed solution, and for users it doesn't matter.) So in summary, I think it would improve readability and even more compatibility. Maybe I missed something, but wouldn't this make sense? On 3/17/21 10:49 PM, mark.reinhold at oracle.com wrote: > https://openjdk.java.net/jeps/401 > > Summary: Enhance the Java object model with user-declared primitive > objects, which are class instances that lack object identity > and can be stored and passed directly, without object headers or > indirections. This is a preview language and VM feature. > > - Mark > From thartmann at openjdk.java.net Tue Apr 20 13:37:17 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Tue, 20 Apr 2021 13:37:17 GMT Subject: git: openjdk/valhalla: lworld: 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return Message-ID: <562f8094-31ef-4484-9cb9-0cadade36c0b@openjdk.org> Changeset: feedec1c Author: Yi Yang Committer: Tobias Hartmann Date: 2021-04-20 13:36:51 +0000 URL: https://git.openjdk.java.net/valhalla/commit/feedec1c 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return Reviewed-by: thartmann ! src/hotspot/share/opto/macro.cpp From thartmann at openjdk.java.net Tue Apr 20 13:39:47 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Tue, 20 Apr 2021 13:39:47 GMT Subject: [lworld] RFR: 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return [v2] In-Reply-To: <7DX-vy-2dUvFnpPTCyYt0azHfkfKV3dxHVL4_tfzcCY=.8e2b4b9e-b7fc-4ab3-a7e3-6286f4ed21d7@github.com> References: <7DX-vy-2dUvFnpPTCyYt0azHfkfKV3dxHVL4_tfzcCY=.8e2b4b9e-b7fc-4ab3-a7e3-6286f4ed21d7@github.com> Message-ID: On Fri, 16 Apr 2021 08:38:58 GMT, Yi Yang wrote: >> src/hotspot/share/opto/macro.cpp line 3239: >> >>> 3237: case Node::Class_FlatArrayCheck: >>> 3238: expand_flatarraycheck_node(n->as_FlatArrayCheck()); >>> 3239: assert(C->macro_count() == (old_macro_count - 1), "expansion must have deleted one node from macro list"); >> >> Why did you delete these asserts? > > It seems the checking happens nevertheless right after switch: > > https://github.com/openjdk/valhalla/blob/5e88e8a08c4532840c66177e0032953ba6e2956c/src/hotspot/share/opto/macro.cpp#L3220-L3227 Right, good catch! ------------- PR: https://git.openjdk.java.net/valhalla/pull/385 From yyang at openjdk.java.net Tue Apr 20 13:39:49 2021 From: yyang at openjdk.java.net (Yi Yang) Date: Tue, 20 Apr 2021 13:39:49 GMT Subject: [lworld] Integrated: 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return In-Reply-To: References: Message-ID: On Thu, 15 Apr 2021 02:55:25 GMT, Yi Yang wrote: > Try to reuse existing BarrierSetC2::obj_allocate functionality for PhaseMacroExpand::expand_mh_intrinsic_return. > > Testing: x86_64 + linux+ slowdebug/release > [x] test/hotspot/jtreg/runtime/valhalla > [x] test/hotspot/jtreg/compiler/valhalla > > Thanks, > Yang This pull request has now been integrated. Changeset: feedec1c Author: Yi Yang Committer: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/feedec1c Stats: 112 lines in 1 file changed: 34 ins; 45 del; 33 mod 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return Reviewed-by: thartmann ------------- PR: https://git.openjdk.java.net/valhalla/pull/385 From brian.goetz at oracle.com Tue Apr 20 14:33:41 2021 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 20 Apr 2021 10:33:41 -0400 Subject: New candidate JEP: 401: Primitive Objects (Preview) In-Reply-To: <196cc359-14f3-59d5-b0ba-69f47a8647b7@fiolino.de> References: <20210317214943.085423DBBFE@eggemoggin.niobe.net> <196cc359-14f3-59d5-b0ba-69f47a8647b7@fiolino.de> Message-ID: <3b36aa11-636d-8650-c7da-8bf13f985f46@oracle.com> Thanks for these thoughts. You may, or may not, find it comforting to know that all these concerns -- and the syntactic "hack" you propose -- have been considered extensively prior to settling on this design.? While it's not intrinsically a terrible idea, it's not as powerful as it first appears, and the problems that you are concerned about loom much larger when contemplating this big change than they are likely to actually be once you start using them. The main question you are addressing is: primitive classes are different, so should they look different?? It is a very natural temptation to want the new features to StAnD OuT and LooK D!FFeR3nt; these things are new and we are worried users will be confused.? (See https://www.thefeedbackloop.xyz/stroustrups-rule-and-layering-over-time/ for a more detailed description of this common phenomena.) Indeed, the original strawman syntax of lambdas was LOUD -- the first proposal used `#(int x, int y)(x * y)`.? When we changed this to `(x, y) -> x*y`, people first complained "that's too subtle!"? But it took all of about five minutes to get over this, and looking back to the original syntax, it feels like a hammer blow to the head.? "I'M NEW AND DIFFERENT", it shouts! Your proposal seems to be to continue using lower-case identifiers for primitive classes, and the leading-upper-case version for their reference projection.? This has been made before.? It has some apparent upsides, as you propose, but also some downsides. First, it takes decades of naming conventions and throws them out the window.? Previously, lower-case identifiers are either keywords (drawn from a fixed list, which includes `int` and friends) or variable/method names; type names (except for the ones which are keywords) begin with an upper case.? This proposal spills type names into the identifier space, meaning that we have lost valuable clues for both types and variable/method names.? This creates new problems as it attempts to solve others. Second, it creates an uncomfortable coupling between two identifiers, whose names are only related through an ad-hoc (and latin-centric) mechanism, upper-casing the first letter.? Where is the definition of `Point`?? Having it be in `primitive class point { }` is confusing.? The language and JVM have gone to great lengths to avoid making such couplings in the past. Third, it doesn't really solve all the problems you think it does; your point about Optional works exactly the same way under this proposal (you have to stick with non-flat `Optional` in existing APIs, and switch to `optional` to flatten where you can) as it does under the current plan (switch to `Optional.val` to flatten where you can.) Fourth, while this reduces the chance that a user will mistake a primitive class instance for a reference class instance, the cost of this is that APIs become, from the perspective of many users, gratuitously inconsistent.? Having some classes called "account" and others called "AccountGroup" will also be a persistent irritant. Fifth, using naming like this asks users to remember the identity-primitive polarity of every identifier if they want to get the benefits of flattening, and if they don't, they'll get the worst of both worlds.? Since `Point` is a valid type name, users are more likely to type `Point` when they mean `point` (or worse, do so inconsistently), and not get the runtime behavior they expect.? Freely mixing `point` and `Point` in programs is allowable, but creates potential performance issues and null injection issues at the boundaries.? If the boundary is small and well-defined (existing APIs that have been compatibly migrated), that's acceptable; if the boundary is pervasive and complex, this might be worse than nothing. So, this proposal is one that I put in the category of "seems attractive at first" (it was attractive to us, at first, too), but I don't think it is in the long-term best interests of the language. More comments inline. On 4/20/2021 9:29 AM, Michael Kuhlmann wrote: > Hi, > > sorry to coming back to this topic after more than a month, but I > thought about it several times and want to share my thoughts. Maybe > the ideas are long discussed already and nobody wants to read about it > any more, but I looked in the archives and didn't find anything, so > I'll give it a try. If it's a stupid idea, just let me know, I can > live with that. > > I'm not a contributor, but I'm using Java for more than twenty years, > since Java 1.1 precisely. I really love the idea of having primitive > classes, that would be amazing! I'm just concerned that we won't make > the best use out of it, especially because of compatibility reasons, > and I was wondering if this can be achieved with a simple design change. > > The problems I'm seeing: > * Primitive classes behave very different from standard object > classes, but users don't immediately see this. You have to look into > the definition to know whether an instance variable of SomeType will > be initialized with null or a default value. This is true, but relying on uninitialized variables isn't a particularly great idea either way (and the language doesn't even let you do this for locals.)?? This point, though, embodies a hard choice: are users better served by presenting all user-written abstractions the same way, or by having a mandatory syntactic designation for classes that have a certain runtime behavior?? For reasons above, I don't think users are well served by this (well-intentioned!) suggestion. > * The suffixes .ref and .val don't fit into our concept of class > names, they look ugly and can easily be mixed up I'm really glad you brought this up, because it's a common misperception. The docs on Valhalla feature .val and .ref prominently, because this is a critical piece of making the whole fit together and proving that we can solve the problems that Valhalla set out to solve.? But it is easy to jump from there to the assumption that users will be dealing with .ref and .val as often as C programmers have to deal with the difference between X and *X.? This is totally not the case! It has been a central design requirement to ensure that the use of .ref and .val are minimized; in most normal situations, they will never appear.? Motivating use cases for explicit .ref are: ?- When you explicitly do not want flattening, generally for memory consumption management.? This is an advanced use case for performance weenies. ?- When you want to support type circularity (e.g., a linked list node that points to the next node.)? Generally a low-level implementation concern. ?- (Later on) When you want to express generics _without_ specialization (List).? This is analogous to the "no flattening" case above, for the same reasons. Motivating use cases for .val are: ?- When you are using a migrated class and want to get flattening. This is a pure optimization; you can always use the unadorned class name here, you just don't get flattening. These all have to do with micro-performance adjustments. Additionally, users may choose to use P.ref to get "nullable primitives"; they may also figure into the story for "no good default", but this is not yet clear. (In an earlier version, `P.ref` was called `P.box`.) So: ?- Ugly: Ugly is in the eye of the beholder, but such opinions are (a) not universal and (b) not always permanent.? (The lambda syntax we have now was called ugly when it was first proposed.) ?- Don't fit: They don't fit because our mental model does not yet have a concept of "two ways to represent the same value".? That's the real challenge, not the syntax. ?- Easily mixed up: I don't think this will be the case in practice. > * That we have to introduce .rel just for the existing classes is even > worse Not sure what this point is about.? There's no `.rel`, and if you mean `.ref`, I'm not sure what you mean. > * Existing classes like Optional will be mostly used in their original > form. That's unfortunate, not that much for performance reasons but > rather because such a value should never be null, so it could make > most use out of this concept. Yes, but this is "glass 99% full."? In the early years of this project, people said we were insane to even consider trying to compatibly migrate Optional.? "It's impossible!? Just leave it be!"?? (These gave way to complaints about the complexity of migration, which is where we are now.)? I think the solution we have represents a dramatically-better-than-expected outcome; the alternate is almost certainly "sorry, Optional was born an identity class, and so it stays." The syntactic hack of "colonize `optional` as the new name" is just a different spelling of `Optional.val`; everything else about this is the same. > * There's already the discussion to delay the implementation of > typical primitive classes. Raffaelo proposed to invent classes > Decimal64 and Decimal128, but it will not be added before this JEP is > going live to avoid the need of the ugly compatibility hack. Same is true here; if we had Decimal64 now, regardless of how we spell it, it would be nullable, and then if we migrated it in-place, it would be an incompatible change for existing clients of `decimal64`.? In this case, this proposal does not improve compatibility, it just moves the breakage around. (General lesson: no matter how hard you think migration compatibility is, its harder.) > * We have to treat the seven existing primitive types in a very > special way. Not as special as "very" implies, but ... again, I think this is glass 1% empty.? Again, in the early days, it was considered unthinkable that we would be able to compatibly migrate `int` to be an object, but here we are.? Yes, there are some legacy considerations, but they are fewer than you probably think.? The main one is the most superficial -- that its name is spelled differently, and its box has an ad-hoc name too.? (But even this is half hidden behind the fact that you can spell `Integer` as `int.ref` if you like.)? The other is that you can't synchronize on Integer any more -- but if this is the biggest compatibility sin we've committed, then we've hit this out of the park. What other "very special" considerations are you worried about? > People are already used to the idea that normal classes start with an > uppercase character, but primitives are in lowercase characters. The > predecessor language Oak even defined string as a primitive type. So > why not picking up this idea and forcing all future primitive types to > start with lowercase characters as well? > > Java has been very concrete in style guides but very relaxed in > enforcing them in the past. You can define a class named 'integer' > without problems. I would see this as a design bug and would rather > enforce some stricter rules. > > So we could make it mandatory to have all primitive class names start > with a lowercase character, more concrete to a character that can be > converted to an uppercase character. Instead of creating a twin class > names 'someClass.ref' what is proposed in the JEP, the reference class > could be named like the primitive class just starting with the > uppercase character. For the reasons above, this seems like a small change but it ripples in unexpected ways, and not all the advantages actually work as they might first appear. The reality is that the visible warts of this proposal come, in no small part, from the desire for compatible migration for existing identity classes.? For example, we could have just said "Optional is frozen in time forever", and we might have been able to banish `.val` from the vocabulary, and then perhaps found another spelling for `.ref`.? But, is that the world we want to live in?? If we accept that compatible migration is a worthwhile goal, and "old optional" and "new optional" have any difference in semantics, there have to be two names, and the existing uses have to get the old name, since its burned into classfiles (`java/util/Optional;`). Should we just give up on compatible migration? The real shame is that the only difference in semantics that we can't paper over is nullability (and for Optional, this is adding insult to injury because the Whole Point of Optional is to not use null.)? If we could, then we wouldn't have to pick another name, and there would be different options available to us.? The pain of null keeps on giving. From john.r.rose at oracle.com Tue Apr 20 17:17:25 2021 From: john.r.rose at oracle.com (John Rose) Date: Tue, 20 Apr 2021 17:17:25 +0000 Subject: null hygiene of Q-types: are we safe yet? Message-ID: <1015EC7B-F64E-4AA4-8528-6C35B1B6E84E@oracle.com> The current Valhalla JVM prototype allows `CONSTANT_Class[QFoo;]` as well as `CONSTANT_Class{Foo]`. It consults the Q-vs-non-Q distinction by means of a bit-field in the CP, called `JVM_CONSTANT_QDescBit` (0x80), which is adjoined bitwise to the `CONSTANT_Class` tag value (0x07). The same information is redundantly encoded in the CP by always recording the original symbol of a `CONSTANT_Class` item even after resolution; if it is of the form ?Q?;? then that provides the same information as the QDescBit. One use of the QDescBit is to gate the selection of ref-mirror vs. val-mirror (the Q-mirror is the val-mirror). The ?Q bit? is also used in `StackMapReader::parse_verification_type`, to decide which ?flavor? of class type to hand to the verifier. (It consults CP::klass_name_at and then Symbol::is_Q_signature, not the QDescBit. Perhaps this should be cleaned up one way or the other, to use a common convention for detecting Q-ness.) The `checkcast` bytecode excludes `null` when it sees `QDescBit` set, whether the CP entry is resolved or not. This preserves null-hygiene within Q-types. (I do have some quibbles with the exact semantics of the bytecode, mainly related to future-proofing. Specifically, I think a `null` query should be specified to perform class loading, even though, today, the answer is no longer in question at that point. Should `instanceof` do a similar trick? No, `null` could be a valid inline value some day, but you still cannot tell which class of `null` it is: all `nulls` look the same.) The verifier makes a distinction between Q-types and non-Q-types, loading Q-descriptors with a special verification type (`VT::inline_type`) in `SMR::parse_verification_type` as noted above. The verifier generally keeps references and inlines separate. This has the effect of keeping `null`-dirty L-types from contaminating Q-types during verification. `VT::is_ref_assignable_from_inline_type` allows a Q-type to promote to its own regular L-type (ref-type) or those of any of its supers (including Object). There is no implicit ?demotion? from a regular L-type down to a Q-type, in the verifier; this must always be done (as with `null`) using `checkcast QFoo;`. We want null-safety of Q-types to be strong enough so that when the interpreter runs Q-values through Q-descriptors of method arguments, nulls have already been excluded before (or during) method entry. By the time the JIT kicks in (either C1 or C2) we need Q-types to participate in scalarized calling conventions (for compiled-to-compiled code). This doesn?t work well if there are wandering nulls that show up for Q-values at method entry. In particular, it?s not good enough to catch nulls _later than method entry_ in the interpreter, but _during method entry_ when the code compiles. And the above scheme does seem satisfy these goals. For bytecode behaviors that are simpler than method argument passing we might assist the verifier (as needed) by adding implicit `null` checks where Q-descriptors appear, for storing into flattened fields, or returning a Q-value from a method. (We will need to revisit the problem of applying extra checks to method arguments when we do specialized generics, because any of the arguments to a generic method, and/or a method of a generic class or interface, might be contextually specialized. So we haven?t completely escaped from the complexity of per-argument checks in the interpreter. I do think these per-arguments checks can be safely done on method entry, in most cases, which localizes the complexity somewhat.) I think all of the above is pretty null-safe. So, where are the remaining ?cracks in the armor?? From jdk at fiolino.de Tue Apr 20 17:34:35 2021 From: jdk at fiolino.de (Michael Kuhlmann) Date: Tue, 20 Apr 2021 19:34:35 +0200 Subject: New candidate JEP: 401: Primitive Objects (Preview) In-Reply-To: <3b36aa11-636d-8650-c7da-8bf13f985f46@oracle.com> References: <20210317214943.085423DBBFE@eggemoggin.niobe.net> <196cc359-14f3-59d5-b0ba-69f47a8647b7@fiolino.de> <3b36aa11-636d-8650-c7da-8bf13f985f46@oracle.com> Message-ID: Hi Brian, thank you so much for the detailed answer! I understand that the case was already discussed in the very beginning. I was expecting this but wanted to understand the reasoning behind, so your explanation helped a lot. I don't want to open the whole discussion again, but since you gave such a detailed explanation, I want to answer them and share my motivation a bit further. Even though it's clear it won't change anything in the current proposal, it stays as it is, and I'm fine with it - at the end it's just another proposal from my side, nothing more. Please see my comments inline. On 4/20/21 4:33 PM, Brian Goetz wrote: > The main question you are addressing is: primitive classes are > different, so should they look different?? It is a very natural > temptation to want the new features to StAnD OuT and LooK D!FFeR3nt; > these things are new and we are worried users will be confused.? (See > https://www.thefeedbackloop.xyz/stroustrups-rule-and-layering-over-time/ > for a more detailed description of this common phenomena.) Indeed, the > original strawman syntax of lambdas was LOUD -- the first proposal used > `#(int x, int y)(x * y)`.? When we changed this to `(x, y) -> x*y`, > people first complained "that's too subtle!"? But it took all of about > five minutes to get over this, and looking back to the original syntax, > it feels like a hammer blow to the head.? "I'M NEW AND DIFFERENT", it > shouts! Yes, I think they should look different. Not too much, sure, but I wouldn't mind marking them a bit with a different naming scheme. Let me add that I don't think that primitive classes will be a frequent case for a standard developer. 98% of Java developers will probably never be tempted to ever write their own primitive classes. I see this as a feature only for some rather low-level types, like Optional or some of the java.util.time classes. I can hardly imagine much more, even including all the standard frameworks - only some mathematical libraries and some internal classes in collection frameworks will make use of it. Or the disruptor framework. But there the benefit is huge! So I don't think we'll be flooded with thousands of primitive classes looking different in the near future. Honestly I think even Point is not the best example. If you deal with image or 3D vector processing, having a lot of point and color elements in rather low level code, it might make sense to have this data in a condensed form using primitive classes, but if you model geometrical objects such as points, circles and rectangles, I would go for the standard reference types (or records probably). One side note, I sometimes find it confusing that enums look the same as normal domain classes, where they are often mixed upon. You can't instantiate them, they're usually immutable, you might want to compare them by identity. Good that normal IDEs render them with a different icon, but that doesn't help within Java code. I would not propose to have a different naming style for enums, at the end they're still relatively normal Java classes. But since primitive classes are even more different, and also much less frequent, it could justify a different naming style. But at the end, it's a matter of opinion, and I understand your concerns against such an "awkward look" for primitive class names. > > Your proposal seems to be to continue using lower-case identifiers for > primitive classes, and the leading-upper-case version for their > reference projection.? This has been made before.? It has some apparent > upsides, as you propose, but also some downsides. > > First, it takes decades of naming conventions and throws them out the > window.? Previously, lower-case identifiers are either keywords (drawn > from a fixed list, which includes `int` and friends) or variable/method > names; type names (except for the ones which are keywords) begin with an > upper case.? This proposal spills type names into the identifier space, > meaning that we have lost valuable clues for both types and > variable/method names.? This creates new problems as it attempts to > solve others. I agree, this is a downside. But you could argue that current primitive classes already are defined like this, they are types starting with a lowercase character, as method or variable names. That all primitive names are also listed as reserved keywords doesn't change much, it's more a language spec detail. And I wouldn't have come up with a proposal that is contrary to the standard naming conventions if the whole JEP wouldn't be already kind of revolutionary. Having all current classes automatically implement some marker interface is definitely something very new and unexpected, so I thought all gates are open already. ;) > > Second, it creates an uncomfortable coupling between two identifiers, > whose names are only related through an ad-hoc (and latin-centric) > mechanism, upper-casing the first letter.? Where is the definition of > `Point`?? Having it be in `primitive class point { }` is confusing.? The > language and JVM have gone to great lengths to avoid making such > couplings in the past. The latin centric mechanism is indeed something I was thinking about as well. (But honestly, if you define the chinese class ?, and refer to the reference type, then ?.ref also looks very latin-centric.) You could also ask, where is the class definition of Point.ref? Is Point the package name and ref the class name? But agreed, this argument still is more against the lowercase proposal. > > Third, it doesn't really solve all the problems you think it does; your > point about Optional works exactly the same way under this proposal (you > have to stick with non-flat `Optional` in existing APIs, and switch to > `optional` to flatten where you can) as it does under the current plan > (switch to `Optional.val` to flatten where you can.) That is true. But in future code, I assume it will be much less likely that interface designers will declare the return type with the concatenated name monster 'Optional.val' that with a lowercase type 'optional'. And it even reads nice: 'optional' looks like an optional String, as if optional with be a modifier like volatile. Of course, that's just my personal preference. > > Fourth, while this reduces the chance that a user will mistake a > primitive class instance for a reference class instance, the cost of > this is that APIs become, from the perspective of many users, > gratuitously inconsistent.? Having some classes called "account" and > others called "AccountGroup" will also be a persistent irritant. You will find examples where this is true, but I don't buy this one. ;) I can't imagine why someone would want to declare the domain class 'Account' as primitive? Especially when other classes in the same model are not. If someone is mixing primitive and reference types in the same model together, then he or she is doing something very wrong. I would be curious if there is a useful real life example for such a use case, but I can't find one. And even if they do so: It's not much better with the current proposal. If you ask the account for its groups, you get instances of AccountGroup, but if you ask the group for its accounts, you get instances of Account.ref. That's also irritant. > > Fifth, using naming like this asks users to remember the > identity-primitive polarity of every identifier if they want to get the > benefits of flattening, and if they don't, they'll get the worst of both > worlds.? Since `Point` is a valid type name, users are more likely to > type `Point` when they mean `point` (or worse, do so inconsistently), > and not get the runtime behavior they expect.? Freely mixing `point` and > `Point` in programs is allowable, but creates potential performance > issues and null injection issues at the boundaries.? If the boundary is > small and well-defined (existing APIs that have been compatibly > migrated), that's acceptable; if the boundary is pervasive and complex, > this might be worse than nothing. That's a valid point. (Point, hehe.) But as said, I would anyway not recommend to use primitive types for domain classes, but only low level types as Instant for example. You can still mix up Instant and instant, but people who do this are often those who anyway already mix up int and Integer or Long and long. > > So, this proposal is one that I put in the category of "seems attractive > at first" (it was attractive to us, at first, too), but I don't think it > is in the long-term best interests of the language. > > More comments inline. Thanks again, I'll comment them as well. > > On 4/20/2021 9:29 AM, Michael Kuhlmann wrote: >> The problems I'm seeing: >> * Primitive classes behave very different from standard object >> classes, but users don't immediately see this. You have to look into >> the definition to know whether an instance variable of SomeType will >> be initialized with null or a default value. > > This is true, but relying on uninitialized variables isn't a > particularly great idea either way (and the language doesn't even let > you do this for locals.)?? This point, though, embodies a hard choice: > are users better served by presenting all user-written abstractions the > same way, or by having a mandatory syntactic designation for classes > that have a certain runtime behavior?? For reasons above, I don't think > users are well served by this (well-intentioned!) suggestion. Hmh, depends. I agree relying on uninitialized variables isn't a great idea, but people do that. They know when the variable is of type int, it's initialized to zero, but if it's of type Point, they might wonder why it's set to (0,0), something like the upper left corner of the screen. Again, it's a matter of opinion. > >> * The suffixes .ref and .val don't fit into our concept of class >> names, they look ugly and can easily be mixed up > > I'm really glad you brought this up, because it's a common misperception. > > [Some good context here] Thanks for the insight. And to be honest, I have no concerns against the .ref suffix; one would rarely explicitly use the reference type when the value type could also be used, and if so, it's perhaps a good idea to mark this more prominent. Also primitive types will rarely be used in standard collections, I assume. So an argument for the suffix style. what I find sad is that we're in the need for the .val suffix. But that better explained in the next section. > >> * That we have to introduce .rel just for the existing classes is even >> worse > > Not sure what this point is about.? There's no `.rel`, and if you mean > `.ref`, I'm not sure what you mean. Yeah, my bad, here I already mixed those two up. Or I types too fast. I meant the .val suffix, and that's AFAIU only introduced for the existing classes. So in future we'll have two different naming schemas for the same concept: * Existing classes can be addressed using Instant for the reference type, and Instant.val for the value type * New classes can be addressed using Point.ref for the reference type and Point for the value type. So there are two distinct naming schemas for the same kind of reference/value pairs. The only difference is that the one class was introduced before the JEP, and the second one after that. And for libraries who want to stay compatible with older JDKs, but eventually want to make use of this feature in future releases, it's even more complicated. I was trying to find a solution to get around with this. To make use of your metaphor, if the glass is 90% full, but we can fill it up to 100% without additional overhead, it would be even better. > >> * Existing classes like Optional will be mostly used in their original >> form. That's unfortunate, not that much for performance reasons but >> rather because such a value should never be null, so it could make >> most use out of this concept. > > Yes, but this is "glass 99% full."? In the early years of this project, > people said we were insane to even consider trying to compatibly migrate > Optional.? "It's impossible!? Just leave it be!"?? (These gave way to > complaints about the complexity of migration, which is where we are > now.)? I think the solution we have represents a > dramatically-better-than-expected outcome; the alternate is almost > certainly "sorry, Optional was born an identity class, and so it stays." > > The syntactic hack of "colonize `optional` as the new name" is just a > different spelling of `Optional.val`; everything else about this is the > same. True, at the end it's just a naming concept, but at least a consistent one for old and new classes. (But I generally agree to your arguments, and thank you for the insights into the evaluation of these concepts.) > >> * We have to treat the seven existing primitive types in a very >> special way. > > Not as special as "very" implies, but ... again, I think this is glass > 1% empty.? Again, in the early days, it was considered unthinkable that > we would be able to compatibly migrate `int` to be an object, but here > we are.? Yes, there are some legacy considerations, but they are fewer > than you probably think.? The main one is the most superficial -- that > its name is spelled differently, and its box has an ad-hoc name too. > (But even this is half hidden behind the fact that you can spell > `Integer` as `int.ref` if you like.)? The other is that you can't > synchronize on Integer any more -- but if this is the biggest > compatibility sin we've committed, then we've hit this out of the park. > > What other "very special" considerations are you worried about? I wonder if we can get around of all these inconsistencies. Not only between legacy code and post-JEP401-code, but also between core primitives and new ones. If there wouldn't be a 'float' primitive yet, we would call the class Float and the boxed type Float.ref. Or if it would've been introduced a bit earlier, it would have been Float.val and Float. But it's not, the primitive name if float and the boxed type Float, just as in my proposal. What I read is that you plan to define aliases for, e.g., float that refers to Float.val. This wouldn't be necessary if the naming scheme would already cover the existing pattern of primitive types. Except int and char which are falling out a bit. So the idea is avoiding three different naming schemes for the same concept. And if someone want to invent a type for imaginary numbers, they can call the class imaginary, the boxed type is Imaginary, and it fits very well into the existing primitive types. It just feels similar. > >> People are already used to the idea that normal classes start with an >> uppercase character, but primitives are in lowercase characters. The >> predecessor language Oak even defined string as a primitive type. So >> why not picking up this idea and forcing all future primitive types to >> start with lowercase characters as well? >> >> Java has been very concrete in style guides but very relaxed in >> enforcing them in the past. You can define a class named 'integer' >> without problems. I would see this as a design bug and would rather >> enforce some stricter rules. >> >> So we could make it mandatory to have all primitive class names start >> with a lowercase character, more concrete to a character that can be >> converted to an uppercase character. Instead of creating a twin class >> names 'someClass.ref' what is proposed in the JEP, the reference class >> could be named like the primitive class just starting with the >> uppercase character. > > For the reasons above, this seems like a small change but it ripples in > unexpected ways, and not all the advantages actually work as they might > first appear. > > > The reality is that the visible warts of this proposal come, in no small > part, from the desire for compatible migration for existing identity > classes.? For example, we could have just said "Optional is frozen in > time forever", and we might have been able to banish `.val` from the > vocabulary, and then perhaps found another spelling for `.ref`.? But, is > that the world we want to live in?? If we accept that compatible > migration is a worthwhile goal, and "old optional" and "new optional" > have any difference in semantics, there have to be two names, and the > existing uses have to get the old name, since its burned into classfiles > (`java/util/Optional;`). Should we just give up on compatible migration? > > The real shame is that the only difference in semantics that we can't > paper over is nullability (and for Optional, this is adding insult to > injury because the Whole Point of Optional is to not use null.)? If we > could, then we wouldn't have to pick another name, and there would be > different options available to us.? The pain of null keeps on giving. > That is so true, and I agre completely. Thank you very much for the detailed explanation. I see that we'll be using .val and .ref in future, and I agree that there will be only few cases where it's really needed. > From brian.goetz at oracle.com Tue Apr 20 18:46:57 2021 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 20 Apr 2021 14:46:57 -0400 Subject: [External] : Re: New candidate JEP: 401: Primitive Objects (Preview) In-Reply-To: References: <20210317214943.085423DBBFE@eggemoggin.niobe.net> <196cc359-14f3-59d5-b0ba-69f47a8647b7@fiolino.de> <3b36aa11-636d-8650-c7da-8bf13f985f46@oracle.com> Message-ID: <5490afee-88fd-0476-7367-68f1cf5f9878@oracle.com> > Let me add that I don't think that primitive classes will be a > frequent case for a standard developer. 98% of Java developers will > probably never be tempted to ever write their own primitive classes. I > see this as a feature only for some rather low-level types, like > Optional or some of the java.util.time classes. I can hardly imagine > much more, even including all the standard frameworks - only some > mathematical libraries and some internal classes in collection > frameworks will make use of it. Or the disruptor framework. But there > the benefit is huge! I hope this will be true, but I'm also aware that developers don't always do what you expect them to.? Developers can be inordinately attracted to "performance" features; if some blog author says "primitive classes are faster" (which surely will happen), that may motivate a lot of developers using them, even when they shouldn't, at least for the first few years until more universally-accepted "best practices" emerge. > But at the end, it's a matter of opinion, and I understand your > concerns against such an "awkward look" for primitive class names. FWIW, in the early days of OO languages, we saw a lot of conventions like "interface names begin with `I`" and "field names begin with `f_`.? I'm glad that burned itself out before Java came along. Also FWIW, one of the considerations when choosing this was: in the difference between "Point by value" and "Point by reference", which is more important to readers, Point-ness, or val/ref-ness?? We deemed it to be the data type, which is why that comes first and the carrier marking, if any, comes last. > >> >> Fourth, while this reduces the chance that a user will mistake a >> primitive class instance for a reference class instance, the cost of >> this is that APIs become, from the perspective of many users, >> gratuitously inconsistent.? Having some classes called "account" and >> others called "AccountGroup" will also be a persistent irritant. > > You will find examples where this is true, but I don't buy this one. > ;) I can't imagine why someone would want to declare the domain class > 'Account' as primitive? Especially when other classes in the same > model are not. If someone is mixing primitive and reference types in > the same model together, then he or she is doing something very wrong. > I would be curious if there is a useful real life example for such a > use case, but I can't find one. I think it goes back to the "performance is (over)important" thing. I can easily imagine developers will declare the classes that can be primitives, as primitives, only using identity where they need to. Whether this is good or bad is another question, but I suspect it will happen.? (We see this today with enums and records; where people can use the more restricted form, they do, because of the benefits.? We see this as normal, in part because we've set up enums and records as "just being classes".) > And even if they do so: It's not much better with the current > proposal. If you ask the account for its groups, you get instances of > AccountGroup, but if you ask the group for its accounts, you get > instances of Account.ref. That's also irritant. No, that's not right.? If I have: ??? Point.val p1 = ... ??? Point.ref p2 = p1 then `p1 == p2` and `p1.getClass() == p2.getClass()`.? The ref/val is just the "envelope"; the enclosed object is the same either way. > >> >>> * The suffixes .ref and .val don't fit into our concept of class >>> names, they look ugly and can easily be mixed up >> >> I'm really glad you brought this up, because it's a common >> misperception. >> >> [Some good context here] > > Thanks for the insight. And to be honest, I have no concerns against > the .ref suffix; one would rarely explicitly use the reference type > when the value type could also be used, and if so, it's perhaps a good > idea to mark this more prominent. Also primitive types will rarely be > used in standard collections, I assume. So an argument for the suffix > style. > > what I find sad is that we're in the need for the .val suffix. But > that better explained in the next section. Yes, I am sad too!? But realistically, this _will_ be rare, because relatively few classes will get migrated.? (Probably 90% of the pain will be with Optional.)? But there's a principle here, too: make the migrated classes carry the cost of migration, so that all-new code doesn't have to.? In the all-new-code world, you never say .val except in very strange circumstances. > So there are two distinct naming schemas for the same kind of > reference/value pairs. The only difference is that the one class was > introduced before the JEP, and the second one after that. Close -- the difference is that the class was _migrated to a primitive class_.? One can imagine classes being born identity classes after this JEP, and still migrating.? Not all classes will migrate on a special Migration Day.? But yes, your point stands, if the class was born differently, it gets the reversed naming convention.? Still, most of the time, in either case, you can just say Optional, and the system will do something reasonable.? Only in the conjunction of (a) migrated types and (b) performance-obsession will you tune the envelope of each declaration explicitly. > If there wouldn't be a 'float' primitive yet, we would call the class > Float and the boxed type Float.ref. Or if it would've been introduced > a bit earlier, it would have been Float.val and Float. But it's not, > the primitive name if float and the boxed type Float, just as in my > proposal. > > What I read is that you plan to define aliases for, e.g., float that > refers to Float.val. This wouldn't be necessary if the naming scheme > would already cover the existing pattern of primitive types. Except > int and char which are falling out a bit. > > So the idea is avoiding three different naming schemes for the same > concept. > > And if someone want to invent a type for imaginary numbers, they can > call the class imaginary, the boxed type is Imaginary, and it fits > very well into the existing primitive types. It just feels similar. This is the subject of JEP 402.? Currently we have eight primitive / box pairs (of which two have the unfortunate characteristic that the name is not even the same modulo case of the first character, Integer and Character.)? The plan is to: ?- migrate the box classes to primitive classes; ?- define int.ref to mean Integer; ?- define Integer.val to mean int. This way, the only special thing is that these legacy classes have ad-hoc aliases; int and Integer.val are the same type, and int.ref and Integer are the same type.? Clearly we can't get rid of these names, they're too pervasive, but we can tame them a bit. Cheers, -Brian From dsimms at openjdk.java.net Wed Apr 21 05:56:35 2021 From: dsimms at openjdk.java.net (David Simms) Date: Wed, 21 Apr 2021 05:56:35 GMT Subject: [lworld] RFR: 8265615: [lworld] docs-jdk-api-javadoc target fails with un-escaped angle bracket Message-ID: Escape code ------------- Commit messages: - 8265615: [lworld] docs-jdk-api-javadoc target fails with un-escaped angle bracket Changes: https://git.openjdk.java.net/valhalla/pull/388/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=388&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8265615 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.java.net/valhalla/pull/388.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/388/head:pull/388 PR: https://git.openjdk.java.net/valhalla/pull/388 From jdk at fiolino.de Wed Apr 21 06:12:05 2021 From: jdk at fiolino.de (Michael Kuhlmann) Date: Wed, 21 Apr 2021 08:12:05 +0200 Subject: [External] : Re: New candidate JEP: 401: Primitive Objects (Preview) In-Reply-To: <5490afee-88fd-0476-7367-68f1cf5f9878@oracle.com> References: <20210317214943.085423DBBFE@eggemoggin.niobe.net> <196cc359-14f3-59d5-b0ba-69f47a8647b7@fiolino.de> <3b36aa11-636d-8650-c7da-8bf13f985f46@oracle.com> <5490afee-88fd-0476-7367-68f1cf5f9878@oracle.com> Message-ID: On 4/20/21 8:46 PM, Brian Goetz wrote: > > >> Let me add that I don't think that primitive classes will be a >> frequent case for a standard developer. 98% of Java developers will >> probably never be tempted to ever write their own primitive classes. I >> see this as a feature only for some rather low-level types, like >> Optional or some of the java.util.time classes. I can hardly imagine >> much more, even including all the standard frameworks - only some >> mathematical libraries and some internal classes in collection >> frameworks will make use of it. Or the disruptor framework. But there >> the benefit is huge! > > I hope this will be true, but I'm also aware that developers don't > always do what you expect them to.? Developers can be inordinately > attracted to "performance" features; if some blog author says "primitive > classes are faster" (which surely will happen), that may motivate a lot > of developers using them, even when they shouldn't, at least for the > first few years until more universally-accepted "best practices" emerge. Hey, that would be a good argument for having a different naming convention, so that developers immediately see "wow, the class looks different, shall I really use that concept for my Customer domain class?" :D Okay, I'll be quiet already... > >> But at the end, it's a matter of opinion, and I understand your >> concerns against such an "awkward look" for primitive class names. > > FWIW, in the early days of OO languages, we saw a lot of conventions > like "interface names begin with `I`" and "field names begin with `f_`. > I'm glad that burned itself out before Java came along. Oh, that was even long after Java was invented. In OSGi/SWT/RCP programming it is still standard to mark all interfaces with an 'I' as the first character. And even worse, there's a Checkstyle rule to enforce that all abstract classes start with 'Abstract'. I never understood why someone should do this. > > Also FWIW, one of the considerations when choosing this was: in the > difference between "Point by value" and "Point by reference", which is > more important to readers, Point-ness, or val/ref-ness?? We deemed it to > be the data type, which is why that comes first and the carrier marking, > if any, comes last. I agree, when it comes to the semantics of, for instance, the java.util.time classes, it shouldn't make a difference that Instant is a primitive type and TimeZone is not. On the other hand, something like an Optional should anyway not treated as an independent object. It's rather annotating some field or return type as being optional. There it makes sense to have an exceptional naming. But this isn't really an argument for my proposal because developers are still free to give their primitive classes lowercased names when it makes sense. >> And even if they do so: It's not much better with the current >> proposal. If you ask the account for its groups, you get instances of >> AccountGroup, but if you ask the group for its accounts, you get >> instances of Account.ref. That's also irritant. > > No, that's not right.? If I have: > > ??? Point.val p1 = ... > ??? Point.ref p2 = p1 > > then `p1 == p2` and `p1.getClass() == p2.getClass()`.? The ref/val is > just the "envelope"; the enclosed object is the same either way. Oh, I missed this. I was assuming it's like the difference between boxed and unboxed types as of now. I should read the JEPs 401 and 402 more carefully. Thanks for the clarification! From dsimms at openjdk.java.net Wed Apr 21 06:14:25 2021 From: dsimms at openjdk.java.net (David Simms) Date: Wed, 21 Apr 2021 06:14:25 GMT Subject: [lworld] Integrated: 8265615: [lworld] docs-jdk-api-javadoc target fails with un-escaped angle bracket In-Reply-To: References: Message-ID: On Wed, 21 Apr 2021 05:50:40 GMT, David Simms wrote: > Escape code This pull request has now been integrated. Changeset: 983744f3 Author: David Simms URL: https://git.openjdk.java.net/valhalla/commit/983744f3 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod 8265615: [lworld] docs-jdk-api-javadoc target fails with un-escaped angle bracket ------------- PR: https://git.openjdk.java.net/valhalla/pull/388 From frederic.parain at oracle.com Wed Apr 21 12:40:48 2021 From: frederic.parain at oracle.com (Frederic Parain) Date: Wed, 21 Apr 2021 12:40:48 +0000 Subject: null hygiene of Q-types: are we safe yet? In-Reply-To: <1015EC7B-F64E-4AA4-8528-6C35B1B6E84E@oracle.com> References: <1015EC7B-F64E-4AA4-8528-6C35B1B6E84E@oracle.com> Message-ID: > On Apr 20, 2021, at 1:17 PM, John Rose wrote: > > The current Valhalla JVM prototype allows `CONSTANT_Class[QFoo;]` as > well as `CONSTANT_Class{Foo]`. > > It consults the Q-vs-non-Q distinction by means of a bit-field in the > CP, called `JVM_CONSTANT_QDescBit` (0x80), which is adjoined bitwise > to the `CONSTANT_Class` tag value (0x07). > > The same information is redundantly encoded in the CP by always > recording the original symbol of a `CONSTANT_Class` item even after > resolution; if it is of the form ?Q?;? then that provides the same > information as the QDescBit. The QDescBit is only used by the interpreter, to avoid having to do navigate through the CP, retrieving the class name entry, then the Symbol and then to parse the first character of the char array inside. Testing a bit in the tag is way simpler when writing assembly code. The rest of the VM is is using is_Q_signature() instead. > > One use of the QDescBit is to gate the selection of ref-mirror > vs. val-mirror (the Q-mirror is the val-mirror). Not really. First of all, by ?mirror? I assume you?re speaking about the VM metadata (InstanceKlass/InlineKlass) because the VM doesn?t use the Java mirrors. The current model is LPoint$ref;/QPoint$val; so there?s no need to look at the Q marker. Point$ref has its own metadata (an InstanceKlass instance) and Point$val has also its own metadata (an InlineKlass instance). Most of the VM just passes a Klass* or an InstanceKlass* to indicate which projection is being used. Before this model, we already had a L/Q model with two signatures but a single metadata for both projection. The QDescBit dates was implemented at this time, when we had to add side channels to carry the L/Q distinction alongside the Klass*. When model has been changed to LPoint$ref;/QPoint$val; this code was still working and was kept in place. With the return if the L/Q model, we are already in the process of adding back the side channels. Being lazy on the implementation of the interpreter means the QDescBit will retrieve its original purpose. > > The ?Q bit? is also used in `StackMapReader::parse_verification_type`, > to decide which ?flavor? of class type to hand to the verifier. (It > consults CP::klass_name_at and then Symbol::is_Q_signature, not the > QDescBit. Perhaps this should be cleaned up one way or the other, to > use a common convention for detecting Q-ness.) > > The `checkcast` bytecode excludes `null` when it sees `QDescBit` set, > whether the CP entry is resolved or not. This preserves null-hygiene > within Q-types. > > (I do have some quibbles with the exact semantics of the bytecode, > mainly related to future-proofing. Specifically, I think a `null` > query should be specified to perform class loading, even though, > today, the answer is no longer in question at that point. Should > `instanceof` do a similar trick? No, `null` could be a valid inline > value some day, but you still cannot tell which class of `null` it is: > all `nulls` look the same.) The current semantic of a Q-descriptor in the VM is ?null free primitive class?, and according to the extended semantic of checkcast, if the ToS is the null reference, an exception will be thrown for any checkcast which has a Q-signature in argument, so there?s currently no need to load the class. With the change in the semantic of the Q-descriptor, class loading will become necessary (but this is not the current model yet). > > The verifier makes a distinction between Q-types and non-Q-types, > loading Q-descriptors with a special verification type > (`VT::inline_type`) in `SMR::parse_verification_type` as noted above. > The verifier generally keeps references and inlines separate. This > has the effect of keeping `null`-dirty L-types from contaminating > Q-types during verification. > > `VT::is_ref_assignable_from_inline_type` allows a Q-type to promote to > its own regular L-type (ref-type) or those of any of its supers > (including Object). There is no implicit ?demotion? from a regular > L-type down to a Q-type, in the verifier; this must always be done (as > with `null`) using `checkcast QFoo;`. > > We want null-safety of Q-types to be strong enough so that when the > interpreter runs Q-values through Q-descriptors of method arguments, > nulls have already been excluded before (or during) method entry. By > the time the JIT kicks in (either C1 or C2) we need Q-types to > participate in scalarized calling conventions (for > compiled-to-compiled code). Just a note here: C1 doesn?t use scalarized arguments, only C2 does. The only place where C1, and the interpreter, scalarize a primitive object is when returning a non-null primitive object, because they don?t know if the caller was a C2 compiled method or not and there?s no adapters on return. So they both conservatively scalarize the return value and pass it in registers alongside with a reference to the heap allocated version. > This doesn?t work well if there are > wandering nulls that show up for Q-values at method entry. In > particular, it?s not good enough to catch nulls _later than method > entry_ in the interpreter, but _during method entry_ when the code > compiles. And the above scheme does seem satisfy these goals. > > For bytecode behaviors that are simpler than method argument passing > we might assist the verifier (as needed) by adding implicit `null` > checks where Q-descriptors appear, for storing into flattened fields, > or returning a Q-value from a method. > > (We will need to revisit the problem of applying extra checks to > method arguments when we do specialized generics, because any of the > arguments to a generic method, and/or a method of a generic class or > interface, might be contextually specialized. So we haven?t > completely escaped from the complexity of per-argument checks > in the interpreter. I do think these per-arguments checks can > be safely done on method entry, in most cases, which localizes > the complexity somewhat.) This is another problem to be addressed for generic specialization. We might have options to consider like generating small entry point stubs at specialization time that the interpreter could use before jumping to its regular entry point. Those stubs would have all the required checks applied to the right arguments on stack, avoiding the complex logic to retrieve each individual check and the position of the corresponding argument on the stack. > > I think all of the above is pretty null-safe. So, where are the > remaining ?cracks in the armor?? We had a robust null-safe environment thanks to the verifier and the semantic of the Q-descriptor meaning null-free primitive class. We were concerned with the modification of the semantic, not meaning null-free anymore, but load-and-look (with no details about what to look for or what would be the outcome of doing it). Loosing this verifiable null-free property would have forced the VM to do costly null-checks on many locations, including invocation points. Your Monday?s proposal that the Q-descriptor, when applied to primitive classes, would still mean null-free restores this verifiable property. The verifier would not directly look for null pollution, but would ensure that any conversion to a Q-marked-primitive-class will go through a checkcast which will prevent any null reference to leak into the null-free space we are relying on. Harold and I discussed this model and we are confident the verifier will be able to continue to guarantee null-safety for primitive classes. Fred From thartmann at openjdk.java.net Thu Apr 22 07:33:32 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Thu, 22 Apr 2021 07:33:32 GMT Subject: [lworld] RFR: Merge jdk Message-ID: Merging master -> lworld. Follow-up bugs: https://bugs.openjdk.java.net/browse/JDK-8265719 https://bugs.openjdk.java.net/browse/JDK-8265725 https://bugs.openjdk.java.net/browse/JDK-8265720 https://bugs.openjdk.java.net/browse/JDK-8265726 ------------- Commit messages: - Merge jdk - 8265421: java/lang/String/StringRepeat.java test is missing a memory requirement - 8265106: IGV: Enforce en-US locale while parsing ideal graph - 8265483: All-caps ?JAVA? in the top navigation bar - 8265411: Avoid unnecessary Method::init_intrinsic_id calls - 8264983: Add gtest for JDK-8264008 - 8261779: JCK test api/javax_crypto/EncryptedPrivateKeyInfo/Ctor4.html is failing with assertion error when assertions enabled - 8261183: Follow on to Make lists of normal filenames - 8258457: testlibrary_tests/ctw/JarDirTest.java fails with InvalidPathException on windows - 8261392: Exclude testlibrary_tests/ctw/JarDirTest.java - ... and 623 more: https://git.openjdk.java.net/valhalla/compare/983744f3...5c956d1e The webrevs contain the adjustments done while merging with regards to each parent branch: - lworld: https://webrevs.openjdk.java.net/?repo=valhalla&pr=389&range=00.0 - jdk: https://webrevs.openjdk.java.net/?repo=valhalla&pr=389&range=00.1 Changes: https://git.openjdk.java.net/valhalla/pull/389/files Stats: 167511 lines in 5223 files changed: 99203 ins; 49676 del; 18632 mod Patch: https://git.openjdk.java.net/valhalla/pull/389.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/389/head:pull/389 PR: https://git.openjdk.java.net/valhalla/pull/389 From thartmann at openjdk.java.net Thu Apr 22 09:26:49 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Thu, 22 Apr 2021 09:26:49 GMT Subject: [lworld] RFR: Merge jdk [v2] In-Reply-To: References: Message-ID: <05MH2Xt8JJN-GG1ah6Ry_IMx-m7gsqcrQaCk4xT-9PU=.caa3d27b-94c2-4309-aa14-7afee0e824cf@github.com> > Merging master -> lworld. > > Follow-up bugs: > https://bugs.openjdk.java.net/browse/JDK-8265719 > https://bugs.openjdk.java.net/browse/JDK-8265725 > https://bugs.openjdk.java.net/browse/JDK-8265720 > https://bugs.openjdk.java.net/browse/JDK-8265726 Tobias Hartmann has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 1138 commits: - Merge jdk - 8265615: [lworld] docs-jdk-api-javadoc target fails with un-escaped angle bracket - 8264897: [lworld] C2: Use BarrierSetC2::obj_allocate to buffer inline type in PhaseMacroExpand::expand_mh_intrinsic_return Reviewed-by: thartmann - 8265184: [lworld] [AArch64] Broken fast class init barrier for static calls in c2i adapter Reviewed-by: thartmann - 8264414: [lworld] [AArch64] TestBufferTearing.java fails with C1 Reviewed-by: thartmann, fparain - 8265118: [lworld] C1 should optimize inline type checkcasts Reviewed-by: fparain - 8264895: [lworld] assert(!InstanceKlass::cast(receiver_klass)->is_not_initialized()) failed: receiver_klass must be initialized Reviewed-by: fparain - 8264977: [lworld] A primitive class field by name val confuses javac - 8264978: [lworld] Various small code cleanups - 8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol Reviewed-by: mcimadamore - ... and 1128 more: https://git.openjdk.java.net/valhalla/compare/7146104f...5c956d1e ------------- Changes: https://git.openjdk.java.net/valhalla/pull/389/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=389&range=01 Stats: 146739 lines in 1337 files changed: 139848 ins; 2116 del; 4775 mod Patch: https://git.openjdk.java.net/valhalla/pull/389.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/389/head:pull/389 PR: https://git.openjdk.java.net/valhalla/pull/389 From thartmann at openjdk.java.net Thu Apr 22 09:26:55 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Thu, 22 Apr 2021 09:26:55 GMT Subject: [lworld] Integrated: Merge jdk In-Reply-To: References: Message-ID: On Thu, 22 Apr 2021 07:25:03 GMT, Tobias Hartmann wrote: > Merging master -> lworld. > > Follow-up bugs: > https://bugs.openjdk.java.net/browse/JDK-8265719 > https://bugs.openjdk.java.net/browse/JDK-8265725 > https://bugs.openjdk.java.net/browse/JDK-8265720 > https://bugs.openjdk.java.net/browse/JDK-8265726 This pull request has now been integrated. Changeset: 55029d86 Author: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/55029d86 Stats: 167511 lines in 5223 files changed: 99203 ins; 49676 del; 18632 mod Merge jdk ------------- PR: https://git.openjdk.java.net/valhalla/pull/389 From thartmann at openjdk.java.net Thu Apr 22 11:57:01 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Thu, 22 Apr 2021 11:57:01 GMT Subject: [lworld] RFR: 8265748: [lworld] C2 compilation fails with "Not a Long" assert during matching Message-ID: Added missing `_word_copy` variants of ClearArray match rules after merging [JDK-8262355](https://bugs.openjdk.java.net/browse/JDK-8262355) into Valhalla. Tested on AVX 3 machine. Best regards, Tobias ------------- Commit messages: - 8265748: [lworld] C2 compilation fails with 'Not a Long' assert during matching Changes: https://git.openjdk.java.net/valhalla/pull/390/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=390&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8265748 Stats: 143 lines in 1 file changed: 115 ins; 2 del; 26 mod Patch: https://git.openjdk.java.net/valhalla/pull/390.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/390/head:pull/390 PR: https://git.openjdk.java.net/valhalla/pull/390 From thartmann at openjdk.java.net Thu Apr 22 12:33:45 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Thu, 22 Apr 2021 12:33:45 GMT Subject: [lworld] Integrated: 8265748: [lworld] C2 compilation fails with "Not a Long" assert during matching In-Reply-To: References: Message-ID: On Thu, 22 Apr 2021 11:41:06 GMT, Tobias Hartmann wrote: > Added missing `_word_copy` variants of ClearArray match rules after merging [JDK-8262355](https://bugs.openjdk.java.net/browse/JDK-8262355) into Valhalla. Tested on AVX 3 machine. > > Best regards, > Tobias This pull request has now been integrated. Changeset: 9e9e9531 Author: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/9e9e9531 Stats: 143 lines in 1 file changed: 115 ins; 2 del; 26 mod 8265748: [lworld] C2 compilation fails with "Not a Long" assert during matching ------------- PR: https://git.openjdk.java.net/valhalla/pull/390 From rriggs at openjdk.java.net Thu Apr 22 19:30:43 2021 From: rriggs at openjdk.java.net (Roger Riggs) Date: Thu, 22 Apr 2021 19:30:43 GMT Subject: [lworld] RFR: JDK-8265376: Prepare for javac change to do the member translation as described in SoV In-Reply-To: References: Message-ID: On Fri, 16 Apr 2021 20:19:35 GMT, Mandy Chung wrote: > This updates `test/jdk/valhalla/valuetypes/QTypeDescriptorTest.java` and > `test/jdk/valhalla/valuetypes/Reflection.java` tests to prepare for the javac > change to do the member translation as described in SoV (JDK-8244313). > > It also fixes a bug in `Class::referenceType` to return this class if it's an > identity class. This was uncovered by this test change. Marked as reviewed by rriggs (Committer). ------------- PR: https://git.openjdk.java.net/valhalla/pull/387 From mchung at openjdk.java.net Thu Apr 22 21:44:34 2021 From: mchung at openjdk.java.net (Mandy Chung) Date: Thu, 22 Apr 2021 21:44:34 GMT Subject: [lworld] Integrated: JDK-8265376: Prepare for javac change to do the member translation as described in SoV In-Reply-To: References: Message-ID: On Fri, 16 Apr 2021 20:19:35 GMT, Mandy Chung wrote: > This updates `test/jdk/valhalla/valuetypes/QTypeDescriptorTest.java` and > `test/jdk/valhalla/valuetypes/Reflection.java` tests to prepare for the javac > change to do the member translation as described in SoV (JDK-8244313). > > It also fixes a bug in `Class::referenceType` to return this class if it's an > identity class. This was uncovered by this test change. This pull request has now been integrated. Changeset: b65c2b1e Author: Mandy Chung URL: https://git.openjdk.java.net/valhalla/commit/b65c2b1e Stats: 109 lines in 3 files changed: 91 ins; 1 del; 17 mod 8265376: Prepare for javac change to do the member translation as described in SoV Reviewed-by: rriggs ------------- PR: https://git.openjdk.java.net/valhalla/pull/387 From thartmann at openjdk.java.net Fri Apr 23 11:38:07 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Fri, 23 Apr 2021 11:38:07 GMT Subject: [lworld] RFR: 8265726: [lworld] C2 compilation fails with assert "uses must be dominated by definitions" Message-ID: We hit an assert during `PhaseCFG` because the Phi input to a CatchNode does not dominate. The problem is in `PhaseMacroExpand::expand_mh_intrinsic_return` where we rewire projection nodes to merge the state of the slow call in. Here's the `invokeBasic` call before macro expansion: ![BeforeMacroExpand](https://user-images.githubusercontent.com/5312595/115862604-9b8e9700-a434-11eb-862f-eee42bcf0504.png) And after macro expansion: ![AfterMacroExpand](https://user-images.githubusercontent.com/5312595/115862618-a1847800-a434-11eb-8bd1-fa01d5f518fc.png) The input of the CatchNode was accidentally replaced by the Phi merging the exception IO from both calls. The fix is to re-connect the CatchNode. Thanks, Tobias ------------- Commit messages: - 8265726: [lworld] C2 compilation fails with assert 'uses must be dominated by definitions' Changes: https://git.openjdk.java.net/valhalla/pull/391/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=391&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8265726 Stats: 6 lines in 2 files changed: 3 ins; 3 del; 0 mod Patch: https://git.openjdk.java.net/valhalla/pull/391.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/391/head:pull/391 PR: https://git.openjdk.java.net/valhalla/pull/391 From vromero at openjdk.java.net Fri Apr 23 14:31:25 2021 From: vromero at openjdk.java.net (Vicente Romero) Date: Fri, 23 Apr 2021 14:31:25 GMT Subject: Integrated: Refresh universal-type-var branch Message-ID: Refresh universal-type-var branch ------------- Commit messages: - 8265376: Prepare for javac change to do the member translation as described in SoV - 8265748: [lworld] C2 compilation fails with "Not a Long" assert during matching - Merge jdk - 8265421: java/lang/String/StringRepeat.java test is missing a memory requirement - 8265106: IGV: Enforce en-US locale while parsing ideal graph - 8265483: All-caps ?JAVA? in the top navigation bar - 8265411: Avoid unnecessary Method::init_intrinsic_id calls - 8264983: Add gtest for JDK-8264008 - 8261779: JCK test api/javax_crypto/EncryptedPrivateKeyInfo/Ctor4.html is failing with assertion error when assertions enabled - 8261183: Follow on to Make lists of normal filenames - ... and 640 more: https://git.openjdk.java.net/valhalla/compare/94c281e2...b65c2b1e Changes: https://git.openjdk.java.net/valhalla/pull/392/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=392&range=00 Stats: 169463 lines in 5281 files changed: 100512 ins; 50055 del; 18896 mod Patch: https://git.openjdk.java.net/valhalla/pull/392.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/392/head:pull/392 PR: https://git.openjdk.java.net/valhalla/pull/392 From mcimadamore at openjdk.java.net Fri Apr 23 14:31:25 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Fri, 23 Apr 2021 14:31:25 GMT Subject: Integrated: Refresh universal-type-var branch In-Reply-To: References: Message-ID: On Fri, 23 Apr 2021 14:07:13 GMT, Vicente Romero wrote: > Refresh universal-type-var branch Looks good (well, looks as bad as any merge :-) ) Marked as reviewed by mcimadamore (Committer). ------------- Marked as reviewed by mcimadamore (Committer). PR: https://git.openjdk.java.net/valhalla/pull/392 From vromero at openjdk.java.net Fri Apr 23 14:31:30 2021 From: vromero at openjdk.java.net (Vicente Romero) Date: Fri, 23 Apr 2021 14:31:30 GMT Subject: Integrated: Refresh universal-type-var branch In-Reply-To: References: Message-ID: On Fri, 23 Apr 2021 14:07:13 GMT, Vicente Romero wrote: > Refresh universal-type-var branch This pull request has now been integrated. Changeset: 80ed0648 Author: Vicente Romero URL: https://git.openjdk.java.net/valhalla/commit/80ed0648 Stats: 169463 lines in 5281 files changed: 100512 ins; 50055 del; 18896 mod Refresh universal-type-var branch Reviewed-by: mcimadamore ------------- PR: https://git.openjdk.java.net/valhalla/pull/392 From thartmann at openjdk.java.net Mon Apr 26 09:45:00 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Mon, 26 Apr 2021 09:45:00 GMT Subject: [lworld] RFR: 8265726: [lworld] C2 compilation fails with assert "uses must be dominated by definitions" [v2] In-Reply-To: References: Message-ID: <812ewAfHYgvBvi2xIRlxJi7hY9NazGnow-4tY3ziR8E=.b47b4693-47d1-47c6-84ab-e8a57397c7bc@github.com> > We hit an assert during `PhaseCFG` because the Phi input to a CatchNode does not dominate. The problem is in `PhaseMacroExpand::expand_mh_intrinsic_return` where we rewire projection nodes to merge the state of the slow call in. > > Here's the `invokeBasic` call before macro expansion: > ![BeforeMacroExpand](https://user-images.githubusercontent.com/5312595/115862604-9b8e9700-a434-11eb-862f-eee42bcf0504.png) > And after macro expansion: > ![AfterMacroExpand](https://user-images.githubusercontent.com/5312595/115862618-a1847800-a434-11eb-8bd1-fa01d5f518fc.png) > The input of the CatchNode was accidentally replaced by the Phi merging the exception IO from both calls. > > The fix is to re-connect the CatchNode. > > Thanks, > Tobias Tobias Hartmann has updated the pull request incrementally with one additional commit since the last revision: Do not hoist constant loads with MachConstantBaseNode input ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/391/files - new: https://git.openjdk.java.net/valhalla/pull/391/files/1bc32600..a75a6678 Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=391&range=01 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=391&range=00-01 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.java.net/valhalla/pull/391.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/391/head:pull/391 PR: https://git.openjdk.java.net/valhalla/pull/391 From thartmann at openjdk.java.net Mon Apr 26 11:13:35 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Mon, 26 Apr 2021 11:13:35 GMT Subject: [lworld] Integrated: 8265726: [lworld] C2 compilation fails with assert "uses must be dominated by definitions" In-Reply-To: References: Message-ID: On Fri, 23 Apr 2021 11:32:57 GMT, Tobias Hartmann wrote: > We hit an assert during `PhaseCFG` because the Phi input to a CatchNode does not dominate. The problem is in `PhaseMacroExpand::expand_mh_intrinsic_return` where we rewire projection nodes to merge the state of the slow call in. > > Here's the `invokeBasic` call before macro expansion: > ![BeforeMacroExpand](https://user-images.githubusercontent.com/5312595/115862604-9b8e9700-a434-11eb-862f-eee42bcf0504.png) > And after macro expansion: > ![AfterMacroExpand](https://user-images.githubusercontent.com/5312595/115862618-a1847800-a434-11eb-8bd1-fa01d5f518fc.png) > The input of the CatchNode was accidentally replaced by the Phi merging the exception IO from both calls. > > The fix is to re-connect the CatchNode. > > Thanks, > Tobias This pull request has now been integrated. Changeset: 8dc4430d Author: Tobias Hartmann URL: https://git.openjdk.java.net/valhalla/commit/8dc4430d Stats: 7 lines in 3 files changed: 3 ins; 3 del; 1 mod 8265726: [lworld] C2 compilation fails with assert "uses must be dominated by definitions" ------------- PR: https://git.openjdk.java.net/valhalla/pull/391 From dsimms at openjdk.java.net Mon Apr 26 11:39:46 2021 From: dsimms at openjdk.java.net (David Simms) Date: Mon, 26 Apr 2021 11:39:46 GMT Subject: RFR: Merge lworld Message-ID: Merge branch 'lworld' into species_merge_lworld_17_19 # Conflicts: # src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java ------------- Commit messages: - Merge branch 'lworld' into species_merge_lworld_17_19 - 8265376: Prepare for javac change to do the member translation as described in SoV - 8265748: [lworld] C2 compilation fails with "Not a Long" assert during matching - Merge jdk - 8265421: java/lang/String/StringRepeat.java test is missing a memory requirement - 8265106: IGV: Enforce en-US locale while parsing ideal graph - 8265483: All-caps ?JAVA? in the top navigation bar - 8265411: Avoid unnecessary Method::init_intrinsic_id calls - 8264983: Add gtest for JDK-8264008 - 8261779: JCK test api/javax_crypto/EncryptedPrivateKeyInfo/Ctor4.html is failing with assertion error when assertions enabled - ... and 758 more: https://git.openjdk.java.net/valhalla/compare/0e836e2e...4dcd0488 The webrevs contain the adjustments done while merging with regards to each parent branch: - species: https://webrevs.openjdk.java.net/?repo=valhalla&pr=393&range=00.0 - lworld: https://webrevs.openjdk.java.net/?repo=valhalla&pr=393&range=00.1 Changes: https://git.openjdk.java.net/valhalla/pull/393/files Stats: 181138 lines in 5510 files changed: 106971 ins; 53347 del; 20820 mod Patch: https://git.openjdk.java.net/valhalla/pull/393.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/393/head:pull/393 PR: https://git.openjdk.java.net/valhalla/pull/393 From dsimms at openjdk.java.net Mon Apr 26 11:46:10 2021 From: dsimms at openjdk.java.net (David Simms) Date: Mon, 26 Apr 2021 11:46:10 GMT Subject: RFR: Merge lworld [v2] In-Reply-To: References: Message-ID: > Merge branch 'lworld' into species_merge_lworld_17_19 > # Conflicts: > # src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java David Simms has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains three commits: - Merge branch 'lworld' into species_merge_lworld_17_19 # Conflicts: # src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java - javac support for Parametric VM, first stab Reviewed-by: mcimadamore - Merge lworld Merge tag 'jdk-17+12' ------------- Changes: https://git.openjdk.java.net/valhalla/pull/393/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=393&range=01 Stats: 767 lines in 24 files changed: 759 ins; 2 del; 6 mod Patch: https://git.openjdk.java.net/valhalla/pull/393.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/393/head:pull/393 PR: https://git.openjdk.java.net/valhalla/pull/393 From dsimms at openjdk.java.net Mon Apr 26 11:46:16 2021 From: dsimms at openjdk.java.net (David Simms) Date: Mon, 26 Apr 2021 11:46:16 GMT Subject: Integrated: Merge lworld In-Reply-To: References: Message-ID: On Mon, 26 Apr 2021 11:32:41 GMT, David Simms wrote: > Merge branch 'lworld' into species_merge_lworld_17_19 > # Conflicts: > # src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java This pull request has now been integrated. Changeset: 23d0a07e Author: David Simms URL: https://git.openjdk.java.net/valhalla/commit/23d0a07e Stats: 181138 lines in 5510 files changed: 106971 ins; 53347 del; 20820 mod Merge lworld Merge up to jdk-17+19 ------------- PR: https://git.openjdk.java.net/valhalla/pull/393 From vromero at openjdk.java.net Tue Apr 27 06:20:38 2021 From: vromero at openjdk.java.net (Vicente Romero) Date: Tue, 27 Apr 2021 06:20:38 GMT Subject: Integrated: Refresh universal-type-var branch [v2] In-Reply-To: References: Message-ID: > Refresh universal-type-var branch Vicente Romero has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/392/files - new: https://git.openjdk.java.net/valhalla/pull/392/files/b65c2b1e..b65c2b1e Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=392&range=01 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=392&range=00-01 Stats: 0 lines in 0 files changed: 0 ins; 0 del; 0 mod Patch: https://git.openjdk.java.net/valhalla/pull/392.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/392/head:pull/392 PR: https://git.openjdk.java.net/valhalla/pull/392 From david.simms at oracle.com Tue Apr 27 06:36:15 2021 From: david.simms at oracle.com (David Simms) Date: Tue, 27 Apr 2021 08:36:15 +0200 Subject: universal-tvars branch recreated, please *delete from your personal fork* and local checkout Message-ID: <0409ce7f-db02-e2ac-b591-629c99304696@oracle.com> Greetings, Due to a botched merge pull request being published on https://github.com/openjdk/valhalla/tree/universal-tvars , I have recreated the branch. Personal forks: This may cause "git skara sync" to fail updating "universal-tvars", please remove it thus (assuming "origin" is remote name of you personal fork): ? git push -d origin universal-tvars Local checkout: if you have a local copy of universal-tvars, remove and grab it again: ? git branch -D universal-tvars ? git checkout --track origin/universal-tvars Sorry for any inconvenience. /David Simms From sadayapalam at openjdk.java.net Tue Apr 27 08:52:08 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Tue, 27 Apr 2021 08:52:08 GMT Subject: [lworld] RFR: 8265423: [lworld] Provide experimental support for generating a single class file per primitive class Message-ID: Use -XDunifiedValRefClass option to javac to get unified class file generation for primitive classes. Note: Javac will require some tweaks to consume such files, this is WIP. ------------- Commit messages: - 8265423: [lworld] Provide experimental support for generating a single class file per primitive class Changes: https://git.openjdk.java.net/valhalla/pull/394/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=394&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8265423 Stats: 49 lines in 7 files changed: 28 ins; 1 del; 20 mod Patch: https://git.openjdk.java.net/valhalla/pull/394.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/394/head:pull/394 PR: https://git.openjdk.java.net/valhalla/pull/394 From mcimadamore at openjdk.java.net Tue Apr 27 12:24:57 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Tue, 27 Apr 2021 12:24:57 GMT Subject: [lworld] RFR: 8265423: [lworld] Provide experimental support for generating a single class file per primitive class In-Reply-To: References: Message-ID: On Tue, 27 Apr 2021 08:45:18 GMT, Srikanth Adayapalam wrote: > Use -XDunifiedValRefClass option to javac to get unified class file generation for primitive classes. Note: Javac will require some tweaks to consume such files, this is WIP. src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java line 2690: > 2688: if (referenceProjection != null) { > 2689: if (referenceProjection.name != names.ref && referenceProjection.owner.kind == PCK) { > 2690: referenceProjection.complete(); This change seems sneaky - what caused it? src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java line 848: > 846: databuf.appendChar(flags); > 847: icCount++; > 848: if (inner.isPrimitiveClass() && types.splitPrimitiveClass) { the test `sym.isPrimitiveClass() && types.splitPrimitiveClass` is so common which I think would be better refactored into a separate predicate, to make the code clearer. e.g. `Symbol.isSplitPrimitiveClass(Types)` ------------- PR: https://git.openjdk.java.net/valhalla/pull/394 From sadayapalam at openjdk.java.net Tue Apr 27 12:46:48 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Tue, 27 Apr 2021 12:46:48 GMT Subject: [lworld] RFR: 8265423: [lworld] Provide experimental support for generating a single class file per primitive class In-Reply-To: References: Message-ID: On Tue, 27 Apr 2021 12:22:13 GMT, Maurizio Cimadamore wrote: >> Use -XDunifiedValRefClass option to javac to get unified class file generation for primitive classes. Note: Javac will require some tweaks to consume such files, this is WIP. > > src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java line 2690: > >> 2688: if (referenceProjection != null) { >> 2689: if (referenceProjection.name != names.ref && referenceProjection.owner.kind == PCK) { >> 2690: referenceProjection.complete(); > > This change seems sneaky - what caused it? Indeed. I should push this as a separate change set. I discovered this bug while working on the now aborted attempt to evolve the code generation scheme to match SoV4. The right way to internalize the class is by calling complete() on the symbol and not by directly calling readClassFileInternal(). Doing the latter, could result in com.sun.tools.javac.code.ClassFinder#fillIn(com.sun.tools.javac.code.Symbol.ClassSymbol) from being re-entered resulting in an assertion failure. This change is not required for the present feature, but is a crucial fix that should be made independently. > src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java line 848: > >> 846: databuf.appendChar(flags); >> 847: icCount++; >> 848: if (inner.isPrimitiveClass() && types.splitPrimitiveClass) { > > the test `sym.isPrimitiveClass() && types.splitPrimitiveClass` is so common which I think would be better refactored into a separate predicate, to make the code clearer. > > e.g. `Symbol.isSplitPrimitiveClass(Types)` Thanks, I will take a look ------------- PR: https://git.openjdk.java.net/valhalla/pull/394 From sadayapalam at openjdk.java.net Tue Apr 27 12:46:49 2021 From: sadayapalam at openjdk.java.net (Srikanth Adayapalam) Date: Tue, 27 Apr 2021 12:46:49 GMT Subject: [lworld] RFR: 8265423: [lworld] Provide experimental support for generating a single class file per primitive class In-Reply-To: References: Message-ID: On Tue, 27 Apr 2021 12:40:27 GMT, Srikanth Adayapalam wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java line 2690: >> >>> 2688: if (referenceProjection != null) { >>> 2689: if (referenceProjection.name != names.ref && referenceProjection.owner.kind == PCK) { >>> 2690: referenceProjection.complete(); >> >> This change seems sneaky - what caused it? > > Indeed. I should push this as a separate change set. I discovered this bug while working on the now aborted attempt to evolve the code generation scheme to match SoV4. The right way to internalize the class is by calling complete() on the symbol and not by directly calling readClassFileInternal(). Doing the latter, could result in com.sun.tools.javac.code.ClassFinder#fillIn(com.sun.tools.javac.code.Symbol.ClassSymbol) from being re-entered resulting in an assertion failure. > > This change is not required for the present feature, but is a crucial fix that should be made independently. (As I was studying the code that merges the projections back to see what changes I should make for the unified class model, I remembered that bug fix from that aborted work) ------------- PR: https://git.openjdk.java.net/valhalla/pull/394 From mcimadamore at openjdk.java.net Tue Apr 27 13:59:54 2021 From: mcimadamore at openjdk.java.net (Maurizio Cimadamore) Date: Tue, 27 Apr 2021 13:59:54 GMT Subject: [lworld] RFR: 8265423: [lworld] Provide experimental support for generating a single class file per primitive class In-Reply-To: References: Message-ID: On Tue, 27 Apr 2021 12:43:53 GMT, Srikanth Adayapalam wrote: >> Indeed. I should push this as a separate change set. I discovered this bug while working on the now aborted attempt to evolve the code generation scheme to match SoV4. The right way to internalize the class is by calling complete() on the symbol and not by directly calling readClassFileInternal(). Doing the latter, could result in com.sun.tools.javac.code.ClassFinder#fillIn(com.sun.tools.javac.code.Symbol.ClassSymbol) from being re-entered resulting in an assertion failure. >> >> This change is not required for the present feature, but is a crucial fix that should be made independently. > > (As I was studying the code that merges the projections back to see what changes I should make for the unified class model, I remembered that bug fix from that aborted work) I'm fine with keeping the change here if that's easier - I just wanted to make sure I understood where this was coming from as it looked an odd change given what of the rest of the code is doing. Thanks for the explanation. ------------- PR: https://git.openjdk.java.net/valhalla/pull/394 From fparain at openjdk.java.net Wed Apr 28 18:45:40 2021 From: fparain at openjdk.java.net (Frederic Parain) Date: Wed, 28 Apr 2021 18:45:40 GMT Subject: [lworld] RFR: 8266086: [lworld][lw3] C1 produces incorrect code when GlobalValueNumbering is used Message-ID: <-rvv2S7AjtQ0FofpxuBcWmfVXEB88g8Mge6ZnWGByKo=.adc60363-423c-4eb2-9a84-827408171051@github.com> Please review this fix in C1 GlobalValueNumbering. The problem is that C1 doesn't track that a flattened field has been updated when it writes the individual values of this flattened field. The proposed fix is to record the enclosing flattened field with the StoreField node of each individual field, and use this information when the GlobalValueNumbering processes those nodes to kill the flattened field in the ValueMap. Tested locally (Linux 64) with hotspot_valhalla (including new unit test) and jdk_valhalla test suites. Thank you, Fred ------------- Commit messages: - Fix C1 GlobalValueNumbering for flattened fields Changes: https://git.openjdk.java.net/valhalla/pull/395/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=395&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8266086 Stats: 85 lines in 6 files changed: 80 ins; 0 del; 5 mod Patch: https://git.openjdk.java.net/valhalla/pull/395.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/395/head:pull/395 PR: https://git.openjdk.java.net/valhalla/pull/395 From thartmann at openjdk.java.net Thu Apr 29 10:17:12 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Thu, 29 Apr 2021 10:17:12 GMT Subject: [lworld] RFR: 8266086: [lworld][lw3] C1 produces incorrect code when GlobalValueNumbering is used In-Reply-To: <-rvv2S7AjtQ0FofpxuBcWmfVXEB88g8Mge6ZnWGByKo=.adc60363-423c-4eb2-9a84-827408171051@github.com> References: <-rvv2S7AjtQ0FofpxuBcWmfVXEB88g8Mge6ZnWGByKo=.adc60363-423c-4eb2-9a84-827408171051@github.com> Message-ID: <1Q00jJHgn6FC_OFXD2RJvrlWRItbnLTGS-Ss2Oo9SbI=.442f8b38-08a0-4377-880e-022aa6eae0ce@github.com> On Wed, 28 Apr 2021 18:28:38 GMT, Frederic Parain wrote: > Please review this fix in C1 GlobalValueNumbering. > The problem is that C1 doesn't track that a flattened field has been updated when it writes the individual values of this flattened field. The proposed fix is to record the enclosing flattened field with the StoreField node of each individual field, and use this information when the GlobalValueNumbering processes those nodes to kill the flattened field in the ValueMap. > > Tested locally (Linux 64) with hotspot_valhalla (including new unit test) and jdk_valhalla test suites. > > Thank you, > > Fred Good catch! I've added some comments. src/hotspot/share/c1/c1_ValueMap.hpp line 152: > 150: kill_field(x->field(), x->needs_patching()); > 151: if (x->enclosing_field() != NULL) { > 152: kill_field(x->enclosing_field(), true); Why do you need `all_offsets == true`? The offset of the enclosing field should always be known, right? test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1ValueNumbering.java line 2: > 1: /* > 2: * Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved. Copyright should be 2021. test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1ValueNumbering.java line 32: > 30: * @test > 31: * @summary Test value numbering behaves correctly with flattened fields > 32: * @library /testlibrary /test/lib /compiler/whitebox / Whitebox is not used. test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1ValueNumbering.java line 33: > 31: * @summary Test value numbering behaves correctly with flattened fields > 32: * @library /testlibrary /test/lib /compiler/whitebox / > 33: * @compile TestC1ValueNumbering.java Not required. test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1ValueNumbering.java line 34: > 32: * @library /testlibrary /test/lib /compiler/whitebox / > 33: * @compile TestC1ValueNumbering.java > 34: * @run main/othervm -Xcomp -XX:TieredStopAtLevel=1 -ea -XX:+UseGlobalValueNumbering `UseGlobalValueNumbering` is true by default. test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1ValueNumbering.java line 40: > 38: > 39: public class TestC1ValueNumbering { > 40: static primitive class Point { 4x whitespace indentation should be used for Java code. ------------- PR: https://git.openjdk.java.net/valhalla/pull/395 From fparain at openjdk.java.net Thu Apr 29 14:14:33 2021 From: fparain at openjdk.java.net (Frederic Parain) Date: Thu, 29 Apr 2021 14:14:33 GMT Subject: [lworld] RFR: 8266086: [lworld][lw3] C1 produces incorrect code when GlobalValueNumbering is used [v2] In-Reply-To: <-rvv2S7AjtQ0FofpxuBcWmfVXEB88g8Mge6ZnWGByKo=.adc60363-423c-4eb2-9a84-827408171051@github.com> References: <-rvv2S7AjtQ0FofpxuBcWmfVXEB88g8Mge6ZnWGByKo=.adc60363-423c-4eb2-9a84-827408171051@github.com> Message-ID: > Please review this fix in C1 GlobalValueNumbering. > The problem is that C1 doesn't track that a flattened field has been updated when it writes the individual values of this flattened field. The proposed fix is to record the enclosing flattened field with the StoreField node of each individual field, and use this information when the GlobalValueNumbering processes those nodes to kill the flattened field in the ValueMap. > > Tested locally (Linux 64) with hotspot_valhalla (including new unit test) and jdk_valhalla test suites. > > Thank you, > > Fred Frederic Parain has updated the pull request incrementally with one additional commit since the last revision: Fixes after initial review ------------- Changes: - all: https://git.openjdk.java.net/valhalla/pull/395/files - new: https://git.openjdk.java.net/valhalla/pull/395/files/c2ba4baf..a7eb39ae Webrevs: - full: https://webrevs.openjdk.java.net/?repo=valhalla&pr=395&range=01 - incr: https://webrevs.openjdk.java.net/?repo=valhalla&pr=395&range=00-01 Stats: 37 lines in 2 files changed: 5 ins; 6 del; 26 mod Patch: https://git.openjdk.java.net/valhalla/pull/395.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/395/head:pull/395 PR: https://git.openjdk.java.net/valhalla/pull/395 From fparain at openjdk.java.net Thu Apr 29 14:19:16 2021 From: fparain at openjdk.java.net (Frederic Parain) Date: Thu, 29 Apr 2021 14:19:16 GMT Subject: [lworld] RFR: 8266086: [lworld][lw3] C1 produces incorrect code when GlobalValueNumbering is used [v2] In-Reply-To: References: <-rvv2S7AjtQ0FofpxuBcWmfVXEB88g8Mge6ZnWGByKo=.adc60363-423c-4eb2-9a84-827408171051@github.com> Message-ID: On Thu, 29 Apr 2021 14:14:33 GMT, Frederic Parain wrote: >> Please review this fix in C1 GlobalValueNumbering. >> The problem is that C1 doesn't track that a flattened field has been updated when it writes the individual values of this flattened field. The proposed fix is to record the enclosing flattened field with the StoreField node of each individual field, and use this information when the GlobalValueNumbering processes those nodes to kill the flattened field in the ValueMap. >> >> Tested locally (Linux 64) with hotspot_valhalla (including new unit test) and jdk_valhalla test suites. >> >> Thank you, >> >> Fred > > Frederic Parain has updated the pull request incrementally with one additional commit since the last revision: > > Fixes after initial review Hi Tobias, Thank you for the review. Most of the issues you spotted have been fixed on the latest commit. Regarding the `all_offset == true` issue, it is needed to invalidate all field entries in the ValueMap. We would like to only invalidate the entries of the nested fields related to the flattened field. But there's no infrastructure yet to easily identity which fields are related to a given flattened field. So the conservative approach is to invalidate all field entries. Regards, Fred ------------- PR: https://git.openjdk.java.net/valhalla/pull/395 From thartmann at openjdk.java.net Thu Apr 29 14:23:10 2021 From: thartmann at openjdk.java.net (Tobias Hartmann) Date: Thu, 29 Apr 2021 14:23:10 GMT Subject: [lworld] RFR: 8266086: [lworld][lw3] C1 produces incorrect code when GlobalValueNumbering is used [v2] In-Reply-To: References: <-rvv2S7AjtQ0FofpxuBcWmfVXEB88g8Mge6ZnWGByKo=.adc60363-423c-4eb2-9a84-827408171051@github.com> Message-ID: <6UkZbuwllSHbM2J-SfPUgqeodCwnZbXzIvXIMdPhxyI=.3000e9ba-347a-485f-a35f-45e199e544ee@github.com> On Thu, 29 Apr 2021 14:14:33 GMT, Frederic Parain wrote: >> Please review this fix in C1 GlobalValueNumbering. >> The problem is that C1 doesn't track that a flattened field has been updated when it writes the individual values of this flattened field. The proposed fix is to record the enclosing flattened field with the StoreField node of each individual field, and use this information when the GlobalValueNumbering processes those nodes to kill the flattened field in the ValueMap. >> >> Tested locally (Linux 64) with hotspot_valhalla (including new unit test) and jdk_valhalla test suites. >> >> Thank you, >> >> Fred > > Frederic Parain has updated the pull request incrementally with one additional commit since the last revision: > > Fixes after initial review Thanks for updating, looks good to me! Best regards, Tobias ------------- Marked as reviewed by thartmann (Committer). PR: https://git.openjdk.java.net/valhalla/pull/395 From fparain at openjdk.java.net Thu Apr 29 14:27:11 2021 From: fparain at openjdk.java.net (Frederic Parain) Date: Thu, 29 Apr 2021 14:27:11 GMT Subject: [lworld] Integrated: 8266086: [lworld][lw3] C1 produces incorrect code when GlobalValueNumbering is used In-Reply-To: <-rvv2S7AjtQ0FofpxuBcWmfVXEB88g8Mge6ZnWGByKo=.adc60363-423c-4eb2-9a84-827408171051@github.com> References: <-rvv2S7AjtQ0FofpxuBcWmfVXEB88g8Mge6ZnWGByKo=.adc60363-423c-4eb2-9a84-827408171051@github.com> Message-ID: <8fEl0RC1yK-7FhDbx-re5CSYU_D92V2y3hdNm9IsZus=.8b3a8dd3-8368-4d19-95da-fe8426f4484e@github.com> On Wed, 28 Apr 2021 18:28:38 GMT, Frederic Parain wrote: > Please review this fix in C1 GlobalValueNumbering. > The problem is that C1 doesn't track that a flattened field has been updated when it writes the individual values of this flattened field. The proposed fix is to record the enclosing flattened field with the StoreField node of each individual field, and use this information when the GlobalValueNumbering processes those nodes to kill the flattened field in the ValueMap. > > Tested locally (Linux 64) with hotspot_valhalla (including new unit test) and jdk_valhalla test suites. > > Thank you, > > Fred This pull request has now been integrated. Changeset: a7ab3bb2 Author: Frederic Parain URL: https://git.openjdk.java.net/valhalla/commit/a7ab3bb259501864500e5648b5a44c740e800ef0 Stats: 85 lines in 6 files changed: 79 ins; 0 del; 6 mod 8266086: [lworld][lw3] C1 produces incorrect code when GlobalValueNumbering is used Reviewed-by: thartmann ------------- PR: https://git.openjdk.java.net/valhalla/pull/395 From fparain at openjdk.java.net Thu Apr 29 20:49:31 2021 From: fparain at openjdk.java.net (Frederic Parain) Date: Thu, 29 Apr 2021 20:49:31 GMT Subject: [lworld] RFR: 8266324: [lworld] [lw3] Component type of arrays of primitive objects incorrectly loaded at link timeFix earger loading for arrays Message-ID: <2xI1nsp0s4rgjan9Wag_wu5evDYrpiRdEpPb0_1zxus=.1d1707b6-79da-4ee4-929e-5d0cda3c9fae@github.com> Small fix to prevent the VM from loading component types of arrays of primitive objects at link time. ------------- Commit messages: - Fix earger loading for arrays Changes: https://git.openjdk.java.net/valhalla/pull/396/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=396&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8266324 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.java.net/valhalla/pull/396.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/396/head:pull/396 PR: https://git.openjdk.java.net/valhalla/pull/396 From fparain at openjdk.java.net Fri Apr 30 12:32:37 2021 From: fparain at openjdk.java.net (Frederic Parain) Date: Fri, 30 Apr 2021 12:32:37 GMT Subject: [lworld] RFR: 8266361: [lworld] [lw3] Experimental JNI APIs to access flattened arrays should be removed Message-ID: Removing experimental JNI APIs for flattened arrays in preparation of the integration of the Valhalla code into the mainline. Regards, Fred ------------- Commit messages: - Remove experimental JNI APIs for flattened arrays Changes: https://git.openjdk.java.net/valhalla/pull/398/files Webrev: https://webrevs.openjdk.java.net/?repo=valhalla&pr=398&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8266361 Stats: 1997 lines in 10 files changed: 0 ins; 1996 del; 1 mod Patch: https://git.openjdk.java.net/valhalla/pull/398.diff Fetch: git fetch https://git.openjdk.java.net/valhalla pull/398/head:pull/398 PR: https://git.openjdk.java.net/valhalla/pull/398