From uberto.gama at gmail.com Thu Aug 1 08:14:11 2019 From: uberto.gama at gmail.com (Uberto Barbini) Date: Thu, 1 Aug 2019 09:14:11 +0100 Subject: flattening a String? In-Reply-To: References: Message-ID: A correction on my post: Using bytes instead of char (which of course are 16bits) the memory allocation is exactly as expected. I've also realized that Valhalla does some kind of data alignment when creating an array of inline types so if an object is more than 16bytes it will allocate 32 bytes and if more than 32 bytes it allocates 64 bytes for object. The main question remains, is there a to represent a flattenable array of a fixed size? thank you very much Uberto On Wed, 31 Jul 2019 at 23:04, Uberto Barbini wrote: > > Hi, > I've converted my examples from LW1 to LW2 and I've played a bit. > Thanks for all the good work! > > One thing that bothered me is that all examples were just using > numbers, so I've done some experiments to save a String of a fixed > length (a reasonable compromise for high performance) in an inline > type. > This would allow to use them in more use cases including FIX records etc. > > So far the best I managed is just having a bunch of char fields and > mapping them to and from a String. > The code is not nice but it works and it should be fast (I've not > measured anything yet). > > Of course, there are many limitations (Unicode and strings longer than > 16 chars :)) but the main issue now is that looking at the memory > footprint, it seems that it takes 4 bytes for each char, is that > correct? > > I can imagine using int instead to store 4 chars in a more compact way > but I wonder if it is possible to do better than this, either now or > in the future (flattened arrays of fixed size)? > > > Thank you very much > > Uberto > > > > > inline public class User { > > public final int yearOfBirth; > > private final SixteenCharString name; > > public User(String name, int yearOfBirth) { > this.yearOfBirth = yearOfBirth; > this.name = new SixteenCharString(name); > } > > public String getName(){ > return name.getValue(); > } > > } > > > > > > inline public class SixteenCharString { > private final char c0; > private final char c1; > private final char c2; > private final char c3; > private final char c4; > private final char c5; > private final char c6; > private final char c7; > private final char c8; > private final char c9; > private final char cA; > private final char cB; > private final char cC; > private final char cD; > private final char cE; > private final char cF; > > public SixteenCharString(String value){ > char[] padded = (value + " ").toCharArray(); > int index =0; > c0 = padded[index++]; > c1 = padded[index++]; > c2 = padded[index++]; > c3 = padded[index++]; > c4 = padded[index++]; > c5 = padded[index++]; > c6 = padded[index++]; > c7 = padded[index++]; > c8 = padded[index++]; > c9 = padded[index++]; > cA = padded[index++]; > cB = padded[index++]; > cC = padded[index++]; > cD = padded[index++]; > cE = padded[index++]; > cF = padded[index++]; > } > > public String getValue(){ > char[] padded = new char[16]; > int index =0; > padded[index++] = c0; > padded[index++] = c1; > padded[index++] = c2; > padded[index++] = c3; > padded[index++] = c4; > padded[index++] = c5; > padded[index++] = c6; > padded[index++] = c7; > padded[index++] = c8; > padded[index++] = c9; > padded[index++] = cA; > padded[index++] = cB; > padded[index++] = cC; > padded[index++] = cD; > padded[index++] = cE; > padded[index++] = cF; > return new String(padded).trim(); > } > } From kustos at gmx.net Sun Aug 4 21:44:07 2019 From: kustos at gmx.net (Philippe Marschall) Date: Sun, 4 Aug 2019 23:44:07 +0200 Subject: Struggling with Valhalla conversion of library Message-ID: Hi As you published the LW2 prototype I thought I tried to convert one of my libraries [1] to Valhalla and see how it goes. Right now I'm struggling with generics. Some context about the library. The library implements a range tree that allows to map a range of keys to a single value. Eg. {[100,199] -> "1", [200,299] -> "2"}. The library should support both inline and reference types as keys and values. The potential for inline classes is limited as the tree nodes are mutable and recursive. There are however two good candidates, the range class and an unsigned 96bit integer class (called U96) that is provided for convenience. The unsigned 96bit integer class was easy to convert. I had to change it to implements Comparable. I am not yet sure how I want to treat null / 0. But there are two cases where I struggled. First, I have an interface public interface AdjacencyTester { boolean areAdjacent(T low, T high); } I want to implement this for the unsigned 96bit integer class (called U96). Right know in Java 8 this is implemented as public static AdjacencyTester adjacencyTester() { return (low, high) -> { // lambda body }; } Simply converting this to public static AdjacencyTester adjacencyTester() { return (low, high) -> { // lambda body }; } did not work, I got com/github/marschall/rangetree/key/U96.java:[51,12] incompatible types: incompatible parameter types in lambda expression Converting it to an anonymous inner class worked public static AdjacencyTester adjacencyTester() { return new AdjacencyTester() { public boolean areAdjacent(U96? low, U96? high) { // method body } }; } Using U96? as types for the lambda arguments did not compile public static AdjacencyTester adjacencyTester() { return (U96? low, U96? high) -> { // lambda body }; } Compilation failure: /src/main/java/com/github/marschall/rangetree/key/U96.java:[51,16] ')' expected src/main/java/com/github/marschall/rangetree/key/U96.java:[51,21] : expected src/main/java/com/github/marschall/rangetree/key/U96.java:[51,32] ';' expected Second I have a simple Range class which is supposed to hold both reference and inline types. That was easy to convert but integrating into my existing interfaces failed. public inline class Range { private E low; private E high; In my RangeMap interface I have #computeIfAbsent similar to the one from Map. V computeIfAbsent(K key, Function, ? extends V>> mappingFunction) src/main/java/com/github/marschall/rangetree/RangeMap.java:[52,59] unexpected type [ERROR] required: reference [ERROR] found: com.github.marschall.rangetree.Range I tried to switch to Range but that did not help. You can find the code and building instructions here [2] [1] https://github.com/marschall/range-tree [2] https://github.com/marschall/range-tree/tree/valhalla Cheers Philippe From frederic.parain at oracle.com Mon Aug 5 15:10:05 2019 From: frederic.parain at oracle.com (Frederic Parain) Date: Mon, 5 Aug 2019 11:10:05 -0400 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: <41E17BB7-8567-4270-BDC2-B11DA91A41DF@oracle.com> References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <41E17BB7-8567-4270-BDC2-B11DA91A41DF@oracle.com> Message-ID: Brian, I?ve investigated the creation of JFR events to report field layout decisions, but there?s a big problem. Layouts have variable sizes (number of fields being controlled class definitions), and there?s no support in the JVM for JFR events with a variable size. I?ve discussed the issue with Markus. There?s a way to declare and fire JFR events with variable sizes with Java code, but no such feature is planned for the JVM (and even if it is, it will probably a JNI wrapper around the Java code doing it). The problem is that layouts are computed very early in the JVM startup (the first class to be loaded, java/lang/String, has fields!), and at this stage, there isn?t enough classes initialized to execute JFR code. Another solution would be to have a fixed size JFR event, and to encode all the layout information in a single string. But 1) it won?t be easily readable by humans, and 2) it would require specific supports in tools to parse and represent layout information. I?m investigating if putting the layout information in the general logging framework would make sense. But once again, the nicest way to represent a layout requires multiple consecutive lines of text, and I have to figure out how it is possible to have this format guaranteed. Regards, Fred > On Jul 19, 2019, at 11:32, Brian Goetz wrote: > > Great to see support for making it easier to inspect what decisions the VM is actually making here. Rather than a DCMD, did you consider using JFR events to log these decisions, now that JFR is universally available? > >> On Jul 19, 2019, at 11:26 AM, Frederic Parain wrote: >> >> This changeset also includes some options and DCMD to ease inspection >> of layouts, especially when flattenable fields are involved. > From forax at univ-mlv.fr Mon Aug 5 18:26:17 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Mon, 5 Aug 2019 20:26:17 +0200 (CEST) Subject: flattening a String? In-Reply-To: References: Message-ID: <1519568925.150865.1565029577853.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Uberto Barbini" > ?: "valhalla-dev" > Envoy?: Jeudi 1 Ao?t 2019 10:14:11 > Objet: Re: flattening a String? Hi Uberto, > A correction on my post: > Using bytes instead of char (which of course are 16bits) the memory > allocation is exactly as expected. > I've also realized that Valhalla does some kind of data alignment when > creating an array of inline types so if an object is more than 16bytes > it will allocate 32 bytes and if more than 32 bytes it allocates 64 > bytes for object. yes, the alignment is not valhalla specific, all fields in classical objects are also aligned, it's due to the fact that most of the CPU requires ints to be aligned to 32bits, double to 64bits when reading/writing them in RAM. For inline types, the current implementation may allocate an inline class in RAM in the interpreter until the code is JITed and array of inline class always lies in RAM (see below), so inline class fields layout as the same restriction as classical class field layout. > > The main question remains, is there a to represent a flattenable array > of a fixed size? no, array are always reference. There is a proposal to introduce more exotic kind of arrays known as Array 2.0, but we are now focused on delivering inline types first. > > > thank you very much > > Uberto regards, R?mi > > On Wed, 31 Jul 2019 at 23:04, Uberto Barbini wrote: >> >> Hi, >> I've converted my examples from LW1 to LW2 and I've played a bit. >> Thanks for all the good work! >> >> One thing that bothered me is that all examples were just using >> numbers, so I've done some experiments to save a String of a fixed >> length (a reasonable compromise for high performance) in an inline >> type. >> This would allow to use them in more use cases including FIX records etc. >> >> So far the best I managed is just having a bunch of char fields and >> mapping them to and from a String. >> The code is not nice but it works and it should be fast (I've not >> measured anything yet). >> >> Of course, there are many limitations (Unicode and strings longer than >> 16 chars :)) but the main issue now is that looking at the memory >> footprint, it seems that it takes 4 bytes for each char, is that >> correct? >> >> I can imagine using int instead to store 4 chars in a more compact way >> but I wonder if it is possible to do better than this, either now or >> in the future (flattened arrays of fixed size)? >> >> >> Thank you very much >> >> Uberto >> >> >> >> >> inline public class User { >> >> public final int yearOfBirth; >> >> private final SixteenCharString name; >> >> public User(String name, int yearOfBirth) { >> this.yearOfBirth = yearOfBirth; >> this.name = new SixteenCharString(name); >> } >> >> public String getName(){ >> return name.getValue(); >> } >> >> } >> >> >> >> >> >> inline public class SixteenCharString { >> private final char c0; >> private final char c1; >> private final char c2; >> private final char c3; >> private final char c4; >> private final char c5; >> private final char c6; >> private final char c7; >> private final char c8; >> private final char c9; >> private final char cA; >> private final char cB; >> private final char cC; >> private final char cD; >> private final char cE; >> private final char cF; >> >> public SixteenCharString(String value){ >> char[] padded = (value + " ").toCharArray(); >> int index =0; >> c0 = padded[index++]; >> c1 = padded[index++]; >> c2 = padded[index++]; >> c3 = padded[index++]; >> c4 = padded[index++]; >> c5 = padded[index++]; >> c6 = padded[index++]; >> c7 = padded[index++]; >> c8 = padded[index++]; >> c9 = padded[index++]; >> cA = padded[index++]; >> cB = padded[index++]; >> cC = padded[index++]; >> cD = padded[index++]; >> cE = padded[index++]; >> cF = padded[index++]; >> } >> >> public String getValue(){ >> char[] padded = new char[16]; >> int index =0; >> padded[index++] = c0; >> padded[index++] = c1; >> padded[index++] = c2; >> padded[index++] = c3; >> padded[index++] = c4; >> padded[index++] = c5; >> padded[index++] = c6; >> padded[index++] = c7; >> padded[index++] = c8; >> padded[index++] = c9; >> padded[index++] = cA; >> padded[index++] = cB; >> padded[index++] = cC; >> padded[index++] = cD; >> padded[index++] = cE; >> padded[index++] = cF; >> return new String(padded).trim(); >> } > > } From john.r.rose at oracle.com Mon Aug 5 22:19:59 2019 From: john.r.rose at oracle.com (John Rose) Date: Mon, 5 Aug 2019 15:19:59 -0700 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <41E17BB7-8567-4270-BDC2-B11DA91A41DF@oracle.com> Message-ID: <6EA12E39-32C9-405A-87AB-85DB35BCA2EF@oracle.com> On Aug 5, 2019, at 8:10 AM, Frederic Parain wrote: > > I?ve investigated the creation of JFR events to report field layout decisions, > but there?s a big problem. Layouts have variable sizes (number of fields being > controlled class definitions), and there?s no support in the JVM for JFR events > with a variable size. > > I?ve discussed the issue with Markus. There?s a way to declare and fire JFR events > with variable sizes with Java code, but no such feature is planned for the JVM > (and even if it is, it will probably a JNI wrapper around the Java code doing it). > The problem is that layouts are computed very early in the JVM startup (the first > class to be loaded, java/lang/String, has fields!), and at this stage, there isn?t > enough classes initialized to execute JFR code. > > Another solution would be to have a fixed size JFR event, and to encode all the > layout information in a single string. But 1) it won?t be easily readable by humans, > and 2) it would require specific supports in tools to parse and represent layout > information. > > I?m investigating if putting the layout information in the general logging framework > would make sense. But once again, the nicest way to represent a layout requires > multiple consecutive lines of text, and I have to figure out how it is possible > to have this format guaranteed. There?s a database-flavored way to do this also: Issue one event for the layout as a whole, and associate it with an ID number N. Then, for each field (or hole?) in the layout, issue another separate event, mentioning the original ID number N. (The database angle is that a client can form up the variable-sized answer by joining on N.) Perhaps JFR events already have an intrinsic ID number, in which case the pattern gets simpler. In general it would be nice if there were a way to cluster JFR events, even into large multi-level clusters like today?s LogCompilation task reports. From dms at samersoff.net Tue Aug 6 13:52:10 2019 From: dms at samersoff.net (Dmitry Samersoff) Date: Tue, 6 Aug 2019 16:52:10 +0300 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> Message-ID: <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> Hello Frederic, General comment: I'm not sure we should have and maintain UseNewLayout flag. What is the reason to keep old layout? Is there any code that rely on it? classFileParser.cpp: 5975: ValueKlass::cast(ik)->set_first_field_offset(_first_field_offset); Where the value of _first_field_offset is initialized? heapInspection.cpp: 736 and below: Should we add const here? 741 AccessFlags access_flags() { return _access_flags; } Could we use const AccessFlags& access_flags() { return _access_flags; } here? 749 Please make it const char * and remove further casts 766, 775 and few locations below. You may consider to create a proxy inside FieldDesc and replace fd.access_flags().is_static() to fd.is_static() for better readability. instanceKlass.cpp 1130 set_value_field_klass called before the check at l.1132 Is it correct? Should we turn the check to assert? valueKlass.cpp 52 please, add else here to improve readability. Could we move it to the header? Non inlined first_field_offset that just a call to inlined get_first_field_offset looks a bit odd to me. Regards, -Dmitry\S On 19.07.19 18:26, Frederic Parain wrote: > Greetings, > > This is the initial request for review for a new code to layout fields. > The current code to compute field layouts is especially ugly and > not fitted to efficiently flatten inline classes. > > This changeset is an almost complete overhaul of the field layout code, > with a new framework to compute layouts and two different allocation > strategies (one for identity classes and one for inline classes). > > CR: https://bugs.openjdk.java.net/browse/JDK-8228441 > Webrev: http://cr.openjdk.java.net/~fparain/layout/webrev.00/ > > This changeset also includes some options and DCMD to ease inspection > of layouts, especially when flattenable fields are involved. > > The changeset doesn?t remove the old layout code, meaning that either > the old code or the new code can be used (controlled by VM flag). > > This code passed tiers 1 to 3 on Valhalla supported platforms. > Some failures have been identified in higher tiers with some @Contended > tests, but they are due to test bugs (tests making relying on wrong > assumptions about field layouts). > > The code contains a lot of comments about the new framework and the > different allocation strategies. Feel free to complain if comments > are not clear enough or if some code need more comments. > > Regarding the huge size of this changeset, and people being in summer > vacation, I?m not planning to push this code in the short term. > > Thank you, > > Fred > From dms at samersoff.net Tue Aug 6 15:50:56 2019 From: dms at samersoff.net (Dmitry Samersoff) Date: Tue, 6 Aug 2019 18:50:56 +0300 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> Message-ID: Hello Frederic, Continuation ... fieldLayoutBuilder.hpp: Please review const keyword usage across this class e.g. 80 RawBlock* prev_field() const { return _prev_field; } probably should be const RawBlock* prev_field() const { return _prev_field; } There are couple of more places with the same question below. 76, 77 Default value of alignment parameter for two constructors is different (1, -1) 77 Default value for size and alignment will trigger an assert. Please consider refactoring of constructors. Default Initialization of parameters with invalid values might lead to cryptic errors. fieldLayoutBuilder.cpp: 35 This version of constructor missed assert of size. It's better to move all parameters related code (assert and assignment) to start of constructor. 198 It might be better to check just for EMPTY || RESERVED, or use a bitmask 211 Debugging leftover? 469 Space missed within assert. This code will add new contended group for any non-existent value of g. It's contradict with semantic assumed to get_*. You may consider to split it to two different functions - one for the cases when we expect new contended group and other one for cases where we should access existing groups only. Or at least to rename it to something like get_or_add_contended_group. 561, 641 Does it duplicate similar code within ValueKlass, if not - could we move it there? 771, 791 extra const probably not necessary here 765, 785 Code looks very similar. Could we move it to a separate function? Regards, -Dmitry\S On 06.08.19 16:52, Dmitry Samersoff wrote: > Hello Frederic, > > General comment: > > I'm not sure we should have and maintain UseNewLayout flag. What is > the reason to keep old layout? Is there any code that rely on it? > > > classFileParser.cpp: > > 5975: > ValueKlass::cast(ik)->set_first_field_offset(_first_field_offset); > > Where the value of _first_field_offset is initialized? > > heapInspection.cpp: > > 736 and below: Should we add const here? > > 741 AccessFlags access_flags() { return _access_flags; } > > Could we use > const AccessFlags& access_flags() { return _access_flags; } > here? > > 749 Please make it const char * and remove further casts > > > 766, 775 and few locations below. > > You may consider to create a proxy inside FieldDesc > and replace fd.access_flags().is_static() to fd.is_static() > for better readability. > > instanceKlass.cpp > > 1130 set_value_field_klass called before the check at l.1132 > > Is it correct? Should we turn the check to assert? > > valueKlass.cpp > > 52 please, add else here to improve readability. > > Could we move it to the header? Non inlined first_field_offset that just > a call to inlined get_first_field_offset looks a bit odd to me. > > > Regards, > > -Dmitry\S > > > > On 19.07.19 18:26, Frederic Parain wrote: >> Greetings, >> >> This is the initial request for review for a new code to layout fields. >> The current code to compute field layouts is especially ugly and >> not fitted to efficiently flatten inline classes. >> >> This changeset is an almost complete overhaul of the field layout code, >> with a new framework to compute layouts and two different allocation >> strategies (one for identity classes and one for inline classes). >> >> CR: https://bugs.openjdk.java.net/browse/JDK-8228441 >> Webrev: http://cr.openjdk.java.net/~fparain/layout/webrev.00/ >> >> This changeset also includes some options and DCMD to ease inspection >> of layouts, especially when flattenable fields are involved. >> >> The changeset doesn?t remove the old layout code, meaning that either >> the old code or the new code can be used (controlled by VM flag). >> >> This code passed tiers 1 to 3 on Valhalla supported platforms. >> Some failures have been identified in higher tiers with some @Contended >> tests, but they are due to test bugs (tests making relying on wrong >> assumptions about field layouts). >> >> The code contains a lot of comments about the new framework and the >> different allocation strategies. Feel free to complain if comments >> are not clear enough or if some code need more comments. >> >> Regarding the huge size of this changeset, and people being in summer >> vacation, I?m not planning to push this code in the short term. >> >> Thank you, >> >> Fred >> From frederic.parain at oracle.com Tue Aug 6 19:47:12 2019 From: frederic.parain at oracle.com (Frederic Parain) Date: Tue, 6 Aug 2019 15:47:12 -0400 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> Message-ID: <646D1461-DC45-4DA5-92D6-1C4AE1B254CD@oracle.com> Hi Dmitry, Thank you for reviewing this huge patch! > On Aug 6, 2019, at 09:52, Dmitry Samersoff wrote: > > Hello Frederic, > > General comment: > > I'm not sure we should have and maintain UseNewLayout flag. What is > the reason to keep old layout? Is there any code that rely on it? The hope is that the old code can be completely removed. However, this is a huge change, so it is kept as a fallback for now. Coleen has asked that the new layout code would be ported to the main line before the Valhalla integration. So I?ve also a port for JDK14 in progress (with more features, the ones not important for project Valhalla), so I?m trying to stabilize both patches at the same time. But field layout has not been changed for so long, that any change can have unexpected consequences. Some codes have very strong assumptions about layout that are in fact just accidental properties of the old code. Enabling some optimizations just breaks these codes, or reveal some bugs (I found a memory corruption in the StackWalking code, unnoticed with old layouts, breaking the StalkWaking code if the layout is slightly different). So, I?d like to keep the old code as a backup for a little while, then remove it. If it causes to much burden for you, let me know. > classFileParser.cpp: > > 5975: > ValueKlass::cast(ik)->set_first_field_offset(_first_field_offset); > > Where the value of _first_field_offset is initialized? This value, which exists only for inline classes, is initialized in FieldLayoutBuilder::compute_inline_class_layout(TRAPS): 738 _first_field_offset = _layout->start()->offset(); > > heapInspection.cpp: > > 736 and below: Should we add const here? Done > > 741 AccessFlags access_flags() { return _access_flags; } > > Could we use > const AccessFlags& access_flags() { return _access_flags; } > here? Done > 749 Please make it const char * and remove further casts Done (Sorry for the ugly code). > > 766, 775 and few locations below. > > You may consider to create a proxy inside FieldDesc > and replace fd.access_flags().is_static() to fd.is_static() > for better readability. > line 766, fd is a FieldStream, not a FieldDesc, I?m not sure it worth adding the proxy. But a proxy has been added to FieldDesc for is_flattenable(). > instanceKlass.cpp > > 1130 set_value_field_klass called before the check at l.1132 > > Is it correct? Should we turn the check to assert? The check is required to deal with separate compilation issues. If class C has a field of type V, V is an inline class when C is compiled, but then V is changed to be a regular class and is recompiled, the JVM has to detect the mismatch and must reject the class with an ICCE. Calling set_value_field_klass() before the check is not really an issue, if the field?s class is not an inline class, the whole class will be rejected and the stored value will never be used. The call to set_value_field_klass() could be moved after the check, but it would require to test this->get_value_field_klass_or_null(fs.index()) one more time (because set_value_field_klass() must be call twice). > > valueKlass.cpp > > 52 please, add else here to improve readability. > > Could we move it to the header? Non inlined first_field_offset that just > a call to inlined get_first_field_offset looks a bit odd to me. I?ve slightly refactored the code, and added a comment to simplify this code ever more once the old layout code is removed. I?ll include changes from your second e-mail before publishing a new webrev. Thank you, Fred > > > Regards, > > -Dmitry\S > > > > On 19.07.19 18:26, Frederic Parain wrote: >> Greetings, >> >> This is the initial request for review for a new code to layout fields. >> The current code to compute field layouts is especially ugly and >> not fitted to efficiently flatten inline classes. >> >> This changeset is an almost complete overhaul of the field layout code, >> with a new framework to compute layouts and two different allocation >> strategies (one for identity classes and one for inline classes). >> >> CR: https://bugs.openjdk.java.net/browse/JDK-8228441 >> Webrev: http://cr.openjdk.java.net/~fparain/layout/webrev.00/ >> >> This changeset also includes some options and DCMD to ease inspection >> of layouts, especially when flattenable fields are involved. >> >> The changeset doesn?t remove the old layout code, meaning that either >> the old code or the new code can be used (controlled by VM flag). >> >> This code passed tiers 1 to 3 on Valhalla supported platforms. >> Some failures have been identified in higher tiers with some @Contended >> tests, but they are due to test bugs (tests making relying on wrong >> assumptions about field layouts). >> >> The code contains a lot of comments about the new framework and the >> different allocation strategies. Feel free to complain if comments >> are not clear enough or if some code need more comments. >> >> Regarding the huge size of this changeset, and people being in summer >> vacation, I?m not planning to push this code in the short term. >> >> Thank you, >> >> Fred >> From srikanth.adayapalam at oracle.com Wed Aug 7 04:21:25 2019 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Wed, 7 Aug 2019 09:51:25 +0530 Subject: Struggling with Valhalla conversion of library In-Reply-To: References: Message-ID: <31b5aabf-c724-1192-0df3-0142084c3770@oracle.com> Hi Philippe, Thanks for the report. Yes you have discovered a bug in javac's handling of ? in the context of lambdas. This came in from another source too - I am investigating a fix. Stay tuned. Srikanth On 05/08/19 3:14 AM, Philippe Marschall wrote: > Hi > > As you published the LW2 prototype I thought I tried to convert one of > my libraries [1] to Valhalla and see how it goes. Right now I'm > struggling with generics. > > Some context about the library. The library implements a range tree that > allows to map a range of keys to a single value. Eg. {[100,199] -> "1", > [200,299] -> "2"}. The library should support both inline and reference > types as keys and values. > The potential for inline classes is limited as the tree nodes are > mutable and recursive. There are however two good candidates, the range > class and an unsigned 96bit integer class (called U96) that is provided > for convenience. > > The unsigned 96bit integer class? was easy to convert. I had to change > it to implements Comparable. I am not yet sure how I want to treat > null / 0. > But there are two cases where I struggled. > > First, I have an interface > > public interface AdjacencyTester { > > ? boolean areAdjacent(T low, T high); > > } > > I want to implement this for the unsigned 96bit integer class (called > U96). Right know in Java 8 this is implemented as > > ? public static AdjacencyTester adjacencyTester() { > ??? return (low, high) -> { > ????? // lambda body > ??? }; > ? } > > Simply converting this to > > ? public static AdjacencyTester adjacencyTester() { > ??? return (low, high) -> { > ????? // lambda body > ??? }; > ? } > > did not work, I got > > com/github/marschall/rangetree/key/U96.java:[51,12] incompatible types: > incompatible parameter types in lambda expression > > Converting it to an anonymous inner class worked > > ? public static AdjacencyTester adjacencyTester() { > ??? return new AdjacencyTester() { > ????? public boolean areAdjacent(U96? low, U96? high) { > ??????? // method body > ????? } > ??? }; > > ? } > > Using U96? as types for the lambda arguments did not compile > > ? public static AdjacencyTester adjacencyTester() { > ??? return (U96? low, U96? high) -> { > ????? // lambda body > ??? }; > ? } > > Compilation failure: > /src/main/java/com/github/marschall/rangetree/key/U96.java:[51,16] ')' > expected > src/main/java/com/github/marschall/rangetree/key/U96.java:[51,21] : > expected > src/main/java/com/github/marschall/rangetree/key/U96.java:[51,32] ';' > expected > > Second I have a simple Range class which is supposed to hold both > reference and inline types. That was easy to convert but integrating > into my existing interfaces failed. > > public inline class Range { > > ? private E low; > ? private E high; > > In my RangeMap interface I have #computeIfAbsent similar to the one from > Map. > > V computeIfAbsent(K key, Function, ? > extends V>> mappingFunction) > > src/main/java/com/github/marschall/rangetree/RangeMap.java:[52,59] > unexpected type > [ERROR]?? required: reference > [ERROR]?? found:??? com.github.marschall.rangetree.Range > > I tried to switch to > Range > > but that did not help. > > You can find the code and building instructions here [2] > > ?[1] https://github.com/marschall/range-tree > ?[2] https://github.com/marschall/range-tree/tree/valhalla > > Cheers > Philippe From dms at samersoff.net Wed Aug 7 14:27:29 2019 From: dms at samersoff.net (Dmitry Samersoff) Date: Wed, 7 Aug 2019 17:27:29 +0300 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: <646D1461-DC45-4DA5-92D6-1C4AE1B254CD@oracle.com> References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> <646D1461-DC45-4DA5-92D6-1C4AE1B254CD@oracle.com> Message-ID: <35ba2593-eb7e-ecb2-7372-b8530514387d@samersoff.net> Hello Frederic, > So, I?d like to keep the old code as a backup for a little while, > then remove it. > If it causes to much burden for you, let me know. It doesn't case any burden for me, so feel free to keep this flag. > I?ve slightly refactored the code, and added a comment to simplify > this code ever more once the old layout code is removed. > > I?ll include changes from your second e-mail before publishing a > new webrev. Ok. This large and nice work really appreciated. -Dmitry On 06.08.19 22:47, Frederic Parain wrote: > Hi Dmitry, > > Thank you for reviewing this huge patch! > >> On Aug 6, 2019, at 09:52, Dmitry Samersoff wrote: >> >> Hello Frederic, >> >> General comment: >> >> I'm not sure we should have and maintain UseNewLayout flag. What is >> the reason to keep old layout? Is there any code that rely on it? > > The hope is that the old code can be completely removed. > However, this is a huge change, so it is kept as a fallback for now. > > Coleen has asked that the new layout code would be ported to the main line > before the Valhalla integration. So I?ve also a port for JDK14 in progress > (with more features, the ones not important for project Valhalla), so I?m > trying to stabilize both patches at the same time. > But field layout has not been changed for so long, that any change can have > unexpected consequences. Some codes have very strong assumptions about layout > that are in fact just accidental properties of the old code. Enabling some > optimizations just breaks these codes, or reveal some bugs (I found a memory > corruption in the StackWalking code, unnoticed with old layouts, breaking the > StalkWaking code if the layout is slightly different). > > So, I?d like to keep the old code as a backup for a little while, then remove it. > If it causes to much burden for you, let me know. > >> classFileParser.cpp: >> >> 5975: >> ValueKlass::cast(ik)->set_first_field_offset(_first_field_offset); >> >> Where the value of _first_field_offset is initialized? > > This value, which exists only for inline classes, is initialized in > FieldLayoutBuilder::compute_inline_class_layout(TRAPS): > > 738 _first_field_offset = _layout->start()->offset(); > >> >> heapInspection.cpp: >> >> 736 and below: Should we add const here? > > Done > >> >> 741 AccessFlags access_flags() { return _access_flags; } >> >> Could we use >> const AccessFlags& access_flags() { return _access_flags; } >> here? > > Done > >> 749 Please make it const char * and remove further casts > > Done (Sorry for the ugly code). > >> >> 766, 775 and few locations below. >> >> You may consider to create a proxy inside FieldDesc >> and replace fd.access_flags().is_static() to fd.is_static() >> for better readability. >> > > line 766, fd is a FieldStream, not a FieldDesc, I?m not sure it worth > adding the proxy. > But a proxy has been added to FieldDesc for is_flattenable(). > > >> instanceKlass.cpp >> >> 1130 set_value_field_klass called before the check at l.1132 >> >> Is it correct? Should we turn the check to assert? > > The check is required to deal with separate compilation issues. > If class C has a field of type V, V is an inline class when C > is compiled, but then V is changed to be a regular class and > is recompiled, the JVM has to detect the mismatch and must > reject the class with an ICCE. > > Calling set_value_field_klass() before the check is not really > an issue, if the field?s class is not an inline class, the > whole class will be rejected and the stored value will never > be used. > > The call to set_value_field_klass() could be moved after the > check, but it would require to test this->get_value_field_klass_or_null(fs.index()) > one more time (because set_value_field_klass() must be call twice). > >> >> valueKlass.cpp >> >> 52 please, add else here to improve readability. >> >> Could we move it to the header? Non inlined first_field_offset that just >> a call to inlined get_first_field_offset looks a bit odd to me. > > I?ve slightly refactored the code, and added a comment to simplify > this code ever more once the old layout code is removed. > > I?ll include changes from your second e-mail before publishing a > new webrev. > > Thank you, > > Fred > > >> >> >> Regards, >> >> -Dmitry\S >> >> >> >> On 19.07.19 18:26, Frederic Parain wrote: >>> Greetings, >>> >>> This is the initial request for review for a new code to layout fields. >>> The current code to compute field layouts is especially ugly and >>> not fitted to efficiently flatten inline classes. >>> >>> This changeset is an almost complete overhaul of the field layout code, >>> with a new framework to compute layouts and two different allocation >>> strategies (one for identity classes and one for inline classes). >>> >>> CR: https://bugs.openjdk.java.net/browse/JDK-8228441 >>> Webrev: http://cr.openjdk.java.net/~fparain/layout/webrev.00/ >>> >>> This changeset also includes some options and DCMD to ease inspection >>> of layouts, especially when flattenable fields are involved. >>> >>> The changeset doesn?t remove the old layout code, meaning that either >>> the old code or the new code can be used (controlled by VM flag). >>> >>> This code passed tiers 1 to 3 on Valhalla supported platforms. >>> Some failures have been identified in higher tiers with some @Contended >>> tests, but they are due to test bugs (tests making relying on wrong >>> assumptions about field layouts). >>> >>> The code contains a lot of comments about the new framework and the >>> different allocation strategies. Feel free to complain if comments >>> are not clear enough or if some code need more comments. >>> >>> Regarding the huge size of this changeset, and people being in summer >>> vacation, I?m not planning to push this code in the short term. >>> >>> Thank you, >>> >>> Fred >>> > From frederic.parain at oracle.com Wed Aug 7 18:00:36 2019 From: frederic.parain at oracle.com (Frederic Parain) Date: Wed, 7 Aug 2019 14:00:36 -0400 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> Message-ID: <3911E46C-2180-4657-B577-656C161E6051@oracle.com> Hi Dmitry, Thank you for this detailed review. My answers are inlined below. > On Aug 6, 2019, at 11:50, Dmitry Samersoff wrote: > > Hello Frederic, > > Continuation ... > > fieldLayoutBuilder.hpp: > > Please review const keyword usage across this class > > e.g. > > 80 RawBlock* prev_field() const { return _prev_field; } > > probably should be > > const RawBlock* prev_field() const { return _prev_field; } > > There are couple of more places with the same question below. A design choice was to minimize the number of dynamic allocations, which explains why RawBlock has so many fields and pointers, to be used in the different data structures: field lists, layouts, etc. The counterpart of having few allocations is that RawBlock is mutated a lot, making use of const return values not a good fit for this code. For instance, changing next_block() to const RawBlock* next_block() would cause an issue with statements like this one: b->next_block()->set_prev_block(empty); because set_prev_block() is not an const method. > > > 76, 77 Default value of alignment parameter for two constructors is > different (1, -1) > > 77 Default value for size and alignment will trigger an assert. > > Please consider refactoring of constructors. Default Initialization of > parameters with invalid values might lead to cryptic errors. Constructors have been cleaned up, all default values have been removed. > > fieldLayoutBuilder.cpp: > > 35 This version of constructor missed assert of size. Fixed (slightly modified handling of static fields to avoid 0 sized RawBlocks). > > It's better to move all parameters related code (assert and assignment) > to start of constructor. Fixed > > 198 It might be better to check just for EMPTY || RESERVED, > or use a bitmask > I realized this code was dead, I?ve removed it. > 211 Debugging leftover? As written, paranoid check :-) removed. > > 469 Space missed within assert. Fixed > > This code will add new contended group for any non-existent value of g. > It's contradict with semantic assumed to get_*. > > You may consider to split it to two different functions - one for the > cases when we expect new contended group and other one for cases where > we should access existing groups only. Or at least to rename it to > something like get_or_add_contended_group. > Method is renamed (I want to keep the logic in the method to keep the sorting methods simpler). > 561, 641 > > Does it duplicate similar code within ValueKlass, if not - could we move > it there? I?d like to keep the two codes separated. They are similar today, but we could realize that decisions to flatten or not might not the the same when the container is an identity class or an inline class. For instance, flattening a field in an inline class could grow its size to the point where the inline class itself would not be a candidate for flattening, a concern which doesn?t exist for identity classes. > > 771, 791 extra const probably not necessary here Removed > > 765, 785 > > Code looks very similar. Could we move it to a separate function? Code has been refactored. The new webrev is available here: http://cr.openjdk.java.net/~fparain/layout/webrev.01/ The current plan is to push the code optimizing inline classes to the Valhalla repository without waiting for the mainline version to be finalized. After the mainline version has been integrated, I?ll port the differences to the Valhalla repository. Thank you, Fred > > > Regards, > -Dmitry\S > > > On 06.08.19 16:52, Dmitry Samersoff wrote: >> Hello Frederic, >> >> General comment: >> >> I'm not sure we should have and maintain UseNewLayout flag. What is >> the reason to keep old layout? Is there any code that rely on it? >> >> >> classFileParser.cpp: >> >> 5975: >> ValueKlass::cast(ik)->set_first_field_offset(_first_field_offset); >> >> Where the value of _first_field_offset is initialized? >> >> heapInspection.cpp: >> >> 736 and below: Should we add const here? >> >> 741 AccessFlags access_flags() { return _access_flags; } >> >> Could we use >> const AccessFlags& access_flags() { return _access_flags; } >> here? >> >> 749 Please make it const char * and remove further casts >> >> >> 766, 775 and few locations below. >> >> You may consider to create a proxy inside FieldDesc >> and replace fd.access_flags().is_static() to fd.is_static() >> for better readability. >> >> instanceKlass.cpp >> >> 1130 set_value_field_klass called before the check at l.1132 >> >> Is it correct? Should we turn the check to assert? >> >> valueKlass.cpp >> >> 52 please, add else here to improve readability. >> >> Could we move it to the header? Non inlined first_field_offset that just >> a call to inlined get_first_field_offset looks a bit odd to me. >> >> >> Regards, >> >> -Dmitry\S >> >> >> >> On 19.07.19 18:26, Frederic Parain wrote: >>> Greetings, >>> >>> This is the initial request for review for a new code to layout fields. >>> The current code to compute field layouts is especially ugly and >>> not fitted to efficiently flatten inline classes. >>> >>> This changeset is an almost complete overhaul of the field layout code, >>> with a new framework to compute layouts and two different allocation >>> strategies (one for identity classes and one for inline classes). >>> >>> CR: https://bugs.openjdk.java.net/browse/JDK-8228441 >>> Webrev: http://cr.openjdk.java.net/~fparain/layout/webrev.00/ >>> >>> This changeset also includes some options and DCMD to ease inspection >>> of layouts, especially when flattenable fields are involved. >>> >>> The changeset doesn?t remove the old layout code, meaning that either >>> the old code or the new code can be used (controlled by VM flag). >>> >>> This code passed tiers 1 to 3 on Valhalla supported platforms. >>> Some failures have been identified in higher tiers with some @Contended >>> tests, but they are due to test bugs (tests making relying on wrong >>> assumptions about field layouts). >>> >>> The code contains a lot of comments about the new framework and the >>> different allocation strategies. Feel free to complain if comments >>> are not clear enough or if some code need more comments. >>> >>> Regarding the huge size of this changeset, and people being in summer >>> vacation, I?m not planning to push this code in the short term. >>> >>> Thank you, >>> >>> Fred >>> From frederic.parain at oracle.com Wed Aug 7 20:18:28 2019 From: frederic.parain at oracle.com (Frederic Parain) Date: Wed, 7 Aug 2019 16:18:28 -0400 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: <6EA12E39-32C9-405A-87AB-85DB35BCA2EF@oracle.com> References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <41E17BB7-8567-4270-BDC2-B11DA91A41DF@oracle.com> <6EA12E39-32C9-405A-87AB-85DB35BCA2EF@oracle.com> Message-ID: > On Aug 5, 2019, at 18:19, John Rose wrote: > > On Aug 5, 2019, at 8:10 AM, Frederic Parain wrote: >> >> I?ve investigated the creation of JFR events to report field layout decisions, >> but there?s a big problem. Layouts have variable sizes (number of fields being >> controlled class definitions), and there?s no support in the JVM for JFR events >> with a variable size. >> >> I?ve discussed the issue with Markus. There?s a way to declare and fire JFR events >> with variable sizes with Java code, but no such feature is planned for the JVM >> (and even if it is, it will probably a JNI wrapper around the Java code doing it). >> The problem is that layouts are computed very early in the JVM startup (the first >> class to be loaded, java/lang/String, has fields!), and at this stage, there isn?t >> enough classes initialized to execute JFR code. >> >> Another solution would be to have a fixed size JFR event, and to encode all the >> layout information in a single string. But 1) it won?t be easily readable by humans, >> and 2) it would require specific supports in tools to parse and represent layout >> information. >> >> I?m investigating if putting the layout information in the general logging framework >> would make sense. But once again, the nicest way to represent a layout requires >> multiple consecutive lines of text, and I have to figure out how it is possible >> to have this format guaranteed. > > There?s a database-flavored way to do this also: > > Issue one event for the layout as a whole, and associate it with an ID number N. > > Then, for each field (or hole?) in the layout, issue another separate event, mentioning the original ID number N. > > (The database angle is that a client can form up the variable-sized answer by joining on N.) > > Perhaps JFR events already have an intrinsic ID number, in which case the pattern gets simpler. > > In general it would be nice if there were a way to cluster JFR events, even into large multi-level clusters like today?s LogCompilation task reports. > Thank you for this suggestion. This is something that could be implemented easily in the JVM. However, I?m concerned about the usability on the user side. Without a proper support on the client side, users are likely to be overwhelmed by thousands or tens of thousands of events, and it would be a real challenge to reconstruct the layout of each class. I?ll discuss with Markus if there?s some ways to help reconstruct the information on the client side. Fred From tobias.hartmann at oracle.com Thu Aug 8 13:32:32 2019 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Thu, 08 Aug 2019 13:32:32 +0000 Subject: hg: valhalla/valhalla: 8229288: [lworld] C2 should not clear storage property bits if comparing to non-inline array klass Message-ID: <201908081332.x78DWXgr021678@aojmv0008.oracle.com> Changeset: f0f5751f8239 Author: thartmann Date: 2019-08-08 15:32 +0200 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/f0f5751f8239 8229288: [lworld] C2 should not clear storage property bits if comparing to non-inline array klass ! src/hotspot/share/ci/ciKlass.hpp ! src/hotspot/share/ci/ciObjArrayKlass.hpp ! src/hotspot/share/ci/ciTypeArrayKlass.hpp ! src/hotspot/share/ci/ciValueArrayKlass.hpp ! src/hotspot/share/opto/compile.cpp ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestLWorld.java ! test/hotspot/jtreg/compiler/valhalla/valuetypes/ValueTypeTest.java From tobias.hartmann at oracle.com Fri Aug 9 06:52:54 2019 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Fri, 09 Aug 2019 06:52:54 +0000 Subject: hg: valhalla/valhalla: 8227387: [lworld] TestLWorld fails with assert(\!is_always_locked()) failed: invariant. Message-ID: <201908090652.x796qtRI003925@aojmv0008.oracle.com> Changeset: 7bddf30fe530 Author: thartmann Date: 2019-08-09 08:52 +0200 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/7bddf30fe530 8227387: [lworld] TestLWorld fails with assert(\!is_always_locked()) failed: invariant. ! src/hotspot/share/opto/callnode.cpp ! src/hotspot/share/opto/escape.cpp ! src/hotspot/share/opto/macro.cpp From tobias.hartmann at oracle.com Fri Aug 9 09:10:35 2019 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Fri, 09 Aug 2019 09:10:35 +0000 Subject: hg: valhalla/valhalla: 8228693: [lworld] C2 treats static nullable inline type fields as never-null when initialized at compile time Message-ID: <201908090910.x799AaGl021917@aojmv0008.oracle.com> Changeset: 001a0187778a Author: thartmann Date: 2019-08-09 10:49 +0200 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/001a0187778a 8228693: [lworld] C2 treats static nullable inline type fields as never-null when initialized at compile time ! src/hotspot/share/opto/parse3.cpp ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestNullableValueTypes.java ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestWithfieldC1.java From dms at samersoff.net Mon Aug 12 12:14:20 2019 From: dms at samersoff.net (Dmitry Samersoff) Date: Mon, 12 Aug 2019 15:14:20 +0300 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: <35ba2593-eb7e-ecb2-7372-b8530514387d@samersoff.net> References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> <646D1461-DC45-4DA5-92D6-1C4AE1B254CD@oracle.com> <35ba2593-eb7e-ecb2-7372-b8530514387d@samersoff.net> Message-ID: Hello Frederic, The code looks good to me. fieldLayoutBuilder.cpp:35 this version of constructor missed size > 0 assert, I'm not sure it's really important but it's better to keep it uniform. >> 561, 641 >> >> Does it duplicate similar code within ValueKlass, if not - could we >> move it there? > I?d like to keep the two codes separated. > They are similar today, but we could realize that decisions to flatten > or not might not the the same when the container is an identity class > or an inline class. Sorry to disagree with you here. I would prefer to have all "is_flattened" logic in a single place. I.e., if in the future this logic will differ from the default one, it is better to keep it inside ValueKlass with a clear path choice, like is_flattened(bool class_is_inline) Otherwise, it becomes difficult to understand what the command line options (e.g. ValueFieldMaxFlatSize == 0) affect. -Dmitry On 07.08.19 17:27, Dmitry Samersoff wrote: > Hello Frederic, > >> So, I?d like to keep the old code as a backup for a little while, >> then remove it. >> If it causes to much burden for you, let me know. > > It doesn't case any burden for me, so feel free to keep this flag. > >> I?ve slightly refactored the code, and added a comment to simplify >> this code ever more once the old layout code is removed. >> >> I?ll include changes from your second e-mail before publishing a >> new webrev. > > Ok. > > This large and nice work really appreciated. > > -Dmitry > > On 06.08.19 22:47, Frederic Parain wrote: >> Hi Dmitry, >> >> Thank you for reviewing this huge patch! >> >>> On Aug 6, 2019, at 09:52, Dmitry Samersoff wrote: >>> >>> Hello Frederic, >>> >>> General comment: >>> >>> I'm not sure we should have and maintain UseNewLayout flag. What is >>> the reason to keep old layout? Is there any code that rely on it? >> >> The hope is that the old code can be completely removed. >> However, this is a huge change, so it is kept as a fallback for now. >> >> Coleen has asked that the new layout code would be ported to the main line >> before the Valhalla integration. So I?ve also a port for JDK14 in progress >> (with more features, the ones not important for project Valhalla), so I?m >> trying to stabilize both patches at the same time. >> But field layout has not been changed for so long, that any change can have >> unexpected consequences. Some codes have very strong assumptions about layout >> that are in fact just accidental properties of the old code. Enabling some >> optimizations just breaks these codes, or reveal some bugs (I found a memory >> corruption in the StackWalking code, unnoticed with old layouts, breaking the >> StalkWaking code if the layout is slightly different). >> >> So, I?d like to keep the old code as a backup for a little while, then remove it. >> If it causes to much burden for you, let me know. >> >>> classFileParser.cpp: >>> >>> 5975: >>> ValueKlass::cast(ik)->set_first_field_offset(_first_field_offset); >>> >>> Where the value of _first_field_offset is initialized? >> >> This value, which exists only for inline classes, is initialized in >> FieldLayoutBuilder::compute_inline_class_layout(TRAPS): >> >> 738 _first_field_offset = _layout->start()->offset(); >> >>> >>> heapInspection.cpp: >>> >>> 736 and below: Should we add const here? >> >> Done >> >>> >>> 741 AccessFlags access_flags() { return _access_flags; } >>> >>> Could we use >>> const AccessFlags& access_flags() { return _access_flags; } >>> here? >> >> Done >> >>> 749 Please make it const char * and remove further casts >> >> Done (Sorry for the ugly code). >> >>> >>> 766, 775 and few locations below. >>> >>> You may consider to create a proxy inside FieldDesc >>> and replace fd.access_flags().is_static() to fd.is_static() >>> for better readability. >>> >> >> line 766, fd is a FieldStream, not a FieldDesc, I?m not sure it worth >> adding the proxy. >> But a proxy has been added to FieldDesc for is_flattenable(). >> >> >>> instanceKlass.cpp >>> >>> 1130 set_value_field_klass called before the check at l.1132 >>> >>> Is it correct? Should we turn the check to assert? >> >> The check is required to deal with separate compilation issues. >> If class C has a field of type V, V is an inline class when C >> is compiled, but then V is changed to be a regular class and >> is recompiled, the JVM has to detect the mismatch and must >> reject the class with an ICCE. >> >> Calling set_value_field_klass() before the check is not really >> an issue, if the field?s class is not an inline class, the >> whole class will be rejected and the stored value will never >> be used. >> >> The call to set_value_field_klass() could be moved after the >> check, but it would require to test this->get_value_field_klass_or_null(fs.index()) >> one more time (because set_value_field_klass() must be call twice). >> >>> >>> valueKlass.cpp >>> >>> 52 please, add else here to improve readability. >>> >>> Could we move it to the header? Non inlined first_field_offset that just >>> a call to inlined get_first_field_offset looks a bit odd to me. >> >> I?ve slightly refactored the code, and added a comment to simplify >> this code ever more once the old layout code is removed. >> >> I?ll include changes from your second e-mail before publishing a >> new webrev. >> >> Thank you, >> >> Fred >> >> >>> >>> >>> Regards, >>> >>> -Dmitry\S >>> >>> >>> >>> On 19.07.19 18:26, Frederic Parain wrote: >>>> Greetings, >>>> >>>> This is the initial request for review for a new code to layout fields. >>>> The current code to compute field layouts is especially ugly and >>>> not fitted to efficiently flatten inline classes. >>>> >>>> This changeset is an almost complete overhaul of the field layout code, >>>> with a new framework to compute layouts and two different allocation >>>> strategies (one for identity classes and one for inline classes). >>>> >>>> CR: https://bugs.openjdk.java.net/browse/JDK-8228441 >>>> Webrev: http://cr.openjdk.java.net/~fparain/layout/webrev.00/ >>>> >>>> This changeset also includes some options and DCMD to ease inspection >>>> of layouts, especially when flattenable fields are involved. >>>> >>>> The changeset doesn?t remove the old layout code, meaning that either >>>> the old code or the new code can be used (controlled by VM flag). >>>> >>>> This code passed tiers 1 to 3 on Valhalla supported platforms. >>>> Some failures have been identified in higher tiers with some @Contended >>>> tests, but they are due to test bugs (tests making relying on wrong >>>> assumptions about field layouts). >>>> >>>> The code contains a lot of comments about the new framework and the >>>> different allocation strategies. Feel free to complain if comments >>>> are not clear enough or if some code need more comments. >>>> >>>> Regarding the huge size of this changeset, and people being in summer >>>> vacation, I?m not planning to push this code in the short term. >>>> >>>> Thank you, >>>> >>>> Fred >>>> >> From scolebourne at joda.org Mon Aug 12 16:27:15 2019 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 12 Aug 2019 17:27:15 +0100 Subject: Equality for values -- new analysis, same conclusion In-Reply-To: <131B9329-ECE7-46BE-909F-AC88421FF6CB@oracle.com> References: <90C17B62-5968-4352-825E-4F1EFAC81052@oracle.com> <131B9329-ECE7-46BE-909F-AC88421FF6CB@oracle.com> Message-ID: This mail continues a thread at valhalla-spec-experts. Firstly, I think the new direction of "values are objects" and using names/eclairs seems worth exploring and I don't have much to add (although I'm not looking forward to an alternate name or a default value for LocalDate). I did want to comment on the == discussion however. Based on my understanding, the SAME== definition looks highly undesirable to be associated with a language-level operator. Imagine I have a value type that contains two ints - SAME== works fine. But as soon as I add a String to the value type it returns the "wrong" answer as it only compares the identity of the String. I can understand how such a definition might be appealing to the JVM, or to very specialist high performance code, but it seems completely unsuited to be the general definition of == in the language. (Yes it is strictly substitutable, but that property is only useful in narrow use cases like IdentityHashMap - most user code wants to compare the string content, not it's identity). I find myself mostly in agreement with Remi - in principle, the current == operator at the language level needs to die and be removed - it is a mistake of history. As such, I think it is perfectly reasonable for it to return false for values during any deprecation period. Theoretically, it also seems feasible for the JVM to convert acmp to Objects.substitutabilityEquals when loading bytecode that was compiled using a pre-valhalla JDK. This could free up == at the langauge-level for a better use in the future. What I'd really like to see is some serious brain-power applied to the question of how to get from where we are today to a world where there is an operator for .equals() for all types (Objects and values). I don't overly mind if this is `a == b`, `a.=b` , `a EQ b`, `a equals b` or something else. Accepting that the historic meaning of the == operator was a mistake that needs to die seems like an important first step to solving the bigger problem. thanks Stephen On Sat, 10 Aug 2019 at 19:58, John Rose wrote: > > Good analysis. I?m going to comment in part because I want us to be especially clear about definitions. I also have a few additions, naturally. At the end I try to distill our options down to 3 or 4 cases, A/B/C/D. > > On Aug 9, 2019, at 8:46 AM, Brian Goetz wrote: > > > > Time to take another look at equality, now that we?ve simplified away the LFoo/QFoo distinction. This mail focuses on the language notion of equality (==) only. > > Something implicit in this analysis is that there are really only two possible syntactic occurrences of operator== as it relates to an inline type: the statically typed and the dynamically typed. We are calling them V== and Object==; sometimes we say val==, ref==, etc. By context V is either a specific inline type, or else is a stand-in for all inline types, in a statement that applies to them all. I suppose val== is clearer than V== in the latter case, so I?ll say val== when I?m talking about all inline types. > > The term Object== is unambiguous, as the occurrence of operator== when at least one operand is a non-inline, non-primitive type, such as an interface. > > When we talk about generics we might say T==, where T stands for some type parameter, but I think that?s a trap, because we immediately have to say whether we are talking about erased vs. specialized generics, and also it?s conceivable that the bound type of T might affect the interpretation of the operator== sign. > > So, there are two kinds of dynamically typed code: (1) code which works on values under a top type, either Object or an Interface (or some other abstract type, if we go there), and (2) code which works on values under some type variable T *where T is erased not specialized*. There are two kinds of statically typed code: (3) code which works on values under their own type V, and (4) code which uses a type variable T bound to V *using specialization*. Today we work with all types but (4), which comes in with specialized generics. > > It?s a good simplifying assumption that operator== means one thing in both dynamic cases, and the other thing in both static cases. We could try to weasel in a difference between (1) and (2), but that spoils a refactoring which replaces T by a subtype of its bound. Same point for (3) and (4). I hope it?s not necessary to go there, even though we are in a tight spot. > > If we buy the above classifications, then we are really talking about static== and dynamic==, under the guise of val== and Object==. This is useful to remember when we go back and think about primitive prim== (int==, float==, etc.) which are similar to val== but, naturally, have to differ in various details due to 25-year-old decisions. > > (It?s not premature for me to mention primitives at this point, since they are one of the two design centers in the normative slogan, ?codes like a class, works like an int?. More in a bit.) > > > Let?s start with the simplest case, the ==(V,V) operator. There is a range of possible interpretations: > > > > - Not allowed; the compiler treats == as not applicable to operands of type V. (Note that since V <: Object, == may still be called upon to have an opinion about two Vs whose static types are Object or interface.) > > - Allowed, but always false. (This appeals to a concept of ?aggressive reboxing?, where a value is reboxed between every pair of byte codes.) > > - Weak substitutability. This is where we make a ?good faith? attempt to treat equal points as equal, but there are cases (such as those where a value hides behind an Object/interface) where two otherwise equal objects might report not equal. This would have to appeal to some notion of invisible boxing, where sometimes two boxes for the same value are not equal. > > - Substitutability. This is where we extend == field wise over the fields of the object, potentially recursively. > > Let me venture to give some very specific names to these operations, at the risk of derailing the discussion into bikeshed painting. > > "ID==" > Objects.identityEquals(o1, o2) - Returns true if o1 and o2 both have the same object identity, or if o1 and o2 are both null. Returns false for non-identity objects, even if o1 SAME== o2. > > Then we also have Objects.hasIdentity(o) -> o != null && identityEquals(o, o); (Cf. Math.isNaN for the x==x move.) > > ?SAME==" > Objects.substitutabilityEquals(o1, o2) - Returns true if and only if o1 and o2 are substitutable for each other. Either Objects.identityEquals or else both are the same inline type V with recursively ?SAME==? fields. (In the recursion step, ?SAME==? applies to primitives in the same way that Object.equals applies to their wrappers. Since arrays have object identity, there?s no recursion into arrays.) > > Since ID== and SAME== differ only for inline types, they mean the same thing in today?s Java, but differ in Valhalla. > > ?FAST==" > Unsafe.fastEqualsCheck(o1, o2) - Must return false if SAME== would return false. May return false even if SAME== would return true. Attempts to return true when it can do so efficiently, on a best efforts basis. JITs may transform to more or less sensitive tests, or even to constant false, based on optimization context. The typical implementation is raw pointer comparison, which is very fast, but sometimes fails to detect identical inline values buffered in different places. > > There?s no need for FAST== today, since ID== is very fast. If ID== gets slower maybe we want FAST== as a backup. > > These ?==? operations are not syntactic but semantic, hence the different (upper-case) notation. The syntax operators val==, Object== have to be associated with one of those semantic operations. > > > As noted above, we don?t only have to define ==V, but ==Object when there may be a value hiding behind the object. It might be acceptable, though clearly weird, for two values that are ==V to not be ==Object when viewed as Objects. However, the only way this might make sense to users is if this were appealing to a boxing conversion, and its hard to say there?s a boxing conversion from V to Object when V <: Object. There is a gravitational force that says that if two values are V==, then they should still be == when viewed as Object or Comparable. > > > > Let?s take a look at the use cases for Object==. > > > > - Direct identity comparison. This is used for objects that are known to be interned (such as interned strings or Enum constants), as well as algorithms that want to compare objects by identity. such as IdentityHashMap. (When the operands are of generic (T) or dynamic (Object) type, the ?Interned? case is less credible, but the other cases are still credible.) > > Under the assumption that all operands are identity-objects, ID== and SAME== produce the same results and can be replaced secretly by FAST== (if the JIT can speculate or prove that assumption). > > If the JIT can?t tell what?s going on, then both ID== and SAME== work the same, since the slow path of SAME== never gets executed. There?s a small runtime cost for detecting non-ID objects (inlines). > > > - As a fast path for deeper equality comparisons (a == b || a.equals(b)), since the contract of equals() requires that == objects are equals(). > > This is what I call L.I.F.E., the Legacy Idiom For Equality. ID== is good here too. FAST== would be fine here, and a JIT could perform that strength reduction if it notices that the == expression is post-dominated by Object.equals (on the false path). I think that?s usually detectable. > > If we define Object== as SAME==, then the optimization challenge becomes urgent, since the user has written the moral equivalent of ?v.equals(v2) || v.equals(v2)? which appears to duplicate effort. Oops. But the same optimization as for ID== applies: Strength-reduce the first part of L.I.F.E. to FAST== (and maybe then to constant false, FALSE==). In that case, the equals call can happen even if the two inputs are SAME==, so the JIT would have to ensue that this is a valid transform: The V.equals method must not have side effects and must only consult fields of V (and recursive uses of SAME== or other safe equals methods) to make its decisions. This requires putting constraints on certain equals methods, which we could do either by fiat or by analysis. Either way, we should do it. > > > - In comparing references against null. > > This is easy to optimize to FAST==, since the JIT almost certainly can see the null. > > (So FAST== wins a lot in these cases, but it can do so secretly, without the user mentioning Unsafe methods, or burning the FAST== semantics into a public spec.) > > > - In comparing references against a known sentinel value, such as a value already observed, or a sentinel value provided by the user. > > This can be optimized if something is statically known about the sentinel. If it is ID-laden, then FAST== is sufficient. If the sentinel is a known inline type, then it?s an instanceof check plus a monomorphic SAME== (for a particular V). If the sentinel is of unknown type, then polymorphic techniques can reduce the cost, but it?s potentially an expensive SAME==, if that?s the semantics we demand. > > So this scenario splits into a statically-known sentinel and a statically-unknown one. (Maybe Brian only meant the statically-known case. But the other shows up too. More in a second.) > > > When generics are specialized, T== will specialize too, so when T specializes to a value, we will get V==, and when T is erased, we will get Object==. > > For an erased generic, the cases above come into play, since it?s really just another instance of dynamic code. > > OK, so Object== has three candidates: FAST==, ID==, SAME==. > > SAME== cleanly extends the notion of ?is the same object? to non-identity objects, using the concept of substitutability. I think we?d prefer that outcome. > > (Note: The term ?same? is the relevant term in the JLS and JVMS today, applying a substitutability test to both primitives and identity-laden objects. ?Substitutable? means the same thing as ?same? but with more syllables. Sometimes you want more syllables, sometimes fewer.) > > FAST== would inject a lot of uncertainty into Java semantics, so I say let?s leave it to JITs as a secret weapon. > > ID== is plausible: It is optimizable in the same places SAME== can be optimized, and its slow path is still fast. But it creates strange behaviors, such as ?x != x?. > > SAME== is often optimizable to FAST==. In a few cases we?d reach the slow path and see a performance drop, in code that works like this: > > boolean goofyNonLifeContains(List xs, Object x) { for (var x1 : xs) if (x1 == x) return true; return false; } > > (Note: This is non-LIFE code. ArrayList.contains can optimize SAME== and ID== to FAST==, by leaning on the semantics of the Object.equals call in the LIFE.) > > Here we don?t know what x is, necessarily, and so if we say that Object== must translate to SAME==, we have an optimization challenge. The code will probably try to speculate that x is an ID-object (or null) and run a special loop that lowers SAME== to FAST==, with another copy of the loop that ?knows? x is an inline object. Some library code may adapt to this new reality manually the way it does with null today (see ArrayList::indexOf for an example). Or not: Code with a proper LIFE can rely on the JIT to clean things up. > > I think that *only these cases* of variable sentinels or algorithms involving ?raw? pointers compares will put demands on Object== that might discourage us from what we know we should do, which is define Object== as SAME==. > > I think it?s worth it. I hope I won?t eat my words, with angry customers showing us their code falling into the slow path of SAME== on some miserably polymorphic code. Let?s watch for this? The fallback position would ID==. > > (Note: We haven?t said anything yet about val==. We are about to.) > > > Suptyping is a powerful constraint; it says that a value is-a Object. While it is theoretically possible to say that v1==v2 does not imply that ((Object)v1 == (Object) v2), I think we?ll have a very hard time suggesting this with a straight face. (If, instead, the conversion from value to Object were a straight boxing conversion, this would become credible.) Which says to me that if we define == on values at all, then it must be consistent with == on object or interface types. > > It?s not just theory, it?s practice, so maybe this is overstating this case, a little. IDEs guide users away from the second expression (for many types, like String and Integer), offering to replace it with a call to v1.equals(v2). In the presence of primitives (the ?works like an int? half of values), the above implication is routinely false for values outside of the valueOf cache (abs(v) > 256). So there?s no code base out there that does the ?cast to object and compare? trick for ?works like an int? types, today. > > For today's ?codes like a class? entities, what you say is 100% true. And the non-boxing relation V <: Object is on the ?like a class? side of the ledger. Still, I think we could do the above with a straight face if it was part of a user model that split the difference between int and class, making clear which aspects of V are ?like an int? and which ?like a class?. See more thoughts below. > > > Similarly, the fact that we want to migrate erased generics to specialized, where T== will degenerate to V== on specialization, suggests that having Object== and V== be consistent is a strong normalizing force. > > I think the root phenomenon here is that dynamic code and static code with similar syntax should have similar semantics. This link is made in the ways Brian points out: On the ?codes like a class? side of the design, V <: Object entails that expressions valid under the higher type should be valid under the lower type also. And migration from erased to specialized also moves code from Object down to some specific V, where it should have the same meaning. > > So Object== (the friend of dynamic code, at the top of the type hierarchy) should do the same as little val== (as viewed in static code). > > On the other hand, V must also ?work like an int?. And int== is not the same as Integer== (hence Brian?s note that boxing gives us some extra wiggle room in our design). > > (I should also point out that int+ is not the same as Object+. We shouldn?t expect that migration to specialized expressions involving obj+obj to work without a hitch. So op== isn?t unique in threatening automagic migration of generics.) > > > Having == not be allowed on values at all would surely be strange, since == is (mostly) a substitutibilty test on primitives, and values are supposed to ?work like an int.? And, even if we disallowed == on values, one could always cast the value to an Object, and compare them. While this is not an outright indefensible position, it is going to be an uncomfortable one. > > The goal is surely to find the least uncomfortable position, and I expect discomfort on operator== no matter what. (I?ll explain why in a moment.) > > I do think we we could defend a *temporary* ban on val== until we gain more data, to confirm SAME== or some other option. > > I also think, in any case, we want a named method like v.isSame(v1), to make it clear that a full SAME== test is intended. People could use that instead of == while we evaluated our options further. > > > OTOH, I think we are close, now, to being able to make a solid decision. > > > Having V== always be false still does not seem like something we can offer with a straight face, again, citing ?works like an int.? > > Designer: ?See, for consistency with Object==, we define val== as ID==.? > User: ?You mean, you *know* it?s an identity-free type and you are looking for its *object identity*??? > Designer: ?It seemed like a consistent thing to do. Let me get back to you?? > > (Java has lots of precedent for statically rejecting stupid expressions, like ((String)x) instanceof Integer. Using ID== to compare non-id objects is deeply stupid, so should be rejected.) > > > Having V== be ?weak substitutability? is possible, but I don?t think it would make the VM people happy anyway. Most values won?t require recursive comparisons (since most fields of value types will be statically typed as primitives, refs, or values), but much of the cost is in having the split at all. > > Yep. And the JIT can get most of the benefit of explicit FAST== secretly, by strength reduction in common cases. > > > Note too that treating == as substitutibility means use cases such as IdentityHashMap will just work as expected, with no modification for a value-full world. > > That?s a nice point. The effect of SAME== (with a suitable System.identityHashCode) is to make every distinct inline value appear to be interned to unique object identity, as long as you don?t look too closely (e.g., by synchronizing). > > > So if V <: Object, it feels we are still being ?boxed? into the corner that == is a substitutability test. But, in generic / dynamically typed code, we are likely to discourage broad use of Object==, since the most common case (fast path comparison) is no long as fast as it once was. > > Generally speaking, I agree we should write up some warnings about Object==. Happily, the JIT?s secret use of FAST== is a safety net for customers that ignore our warnings. And simple stuff like ?x == null? or ?x == y || x.equals(y)? won?t lose performance, given some L.I.F.E. support in the JIT. > > As far as Object== goes in today?s usages, ID== would be an acceptable alternative to SAME==, since the two differ only for value types. But (as Brian says) if Object== is bound to ID==, and val== *must not* be bound to ID==, then we have a schism between static and dynamic views of every V. This schism would be painful. What would it gain? We would avoid running the slow path of SAME==, which is the cost that ID== doesn?t have. But I think I?ve shown that this slow path is not a risk for most uses of Object==. > > So, ID== doesn?t buy much over SAME==, and therefore Object== and val== don?t need a schism. But if I?m wrong, and we need to fall back to ID==, then we will want to reconsider making a schism between dynamic and static views. > > > We have a few other options to mitigate the performance concerns here: > > > > - Live with legacy ACMP anomalies; > > I.e., don?t change ACMP, so it turns out to be FAST==, or change it to ID== but not SAME==. > > This play makes ACMP into a third independent design point, besides Object== and val==, and makes it differ from both. > > Currently, Object== compiles to ACMP, so this would suggest that ACMP should be upgraded to the new behavior of Object==, which is SAME== (or as a fallback ID==). But Object== could compile to a method call, if we want to decouple ACMP from Object==. > > > - Re-explore a boxing relationship between V and Object. > > This is a different take on ?codes like a class, works like an int?. (More below.) > > > If we say that == is substitutability, we still have the option to translate == to something other than ACMP. Which means that existing binaries (and likely, binaries recompiled with ?source 8) will still use ACMP. If we give ACMP the ?false if value? interpretation, then existing classifies (which mostly use == as a fast-path check) will still work, as those tests should be backed up with .equals(), though they may suffer performance changes on recompilation. This is an uncomfortable compromise, but is worth considering. Down this route, ACMP has a much narrower portfolio, as we would not use it in translating most Object== unless we were sure we were dealing with identityful types. > > I like the idea of limiting the use of ACMP to ID==, *if it pays off*. > > Or, we could deprecate and remove ACMP, in favor of method intrinsics for ID== and SAME==. > > We could keep ACMP as FAST==, period. But I think that?s too unpredictable; ID== looks safer to me even for legacy code. As noted above, the JIT will often strength-reduce ACMP to FAST==, if it can prove the move is valid. So there?s little upside to mandating FAST== in the JVMS. > > So the good candidates for ACMP are SAME== and ID==. > > I think maybe we want performance runs on a JVM which is configured with a switch to bind ACMP to SAME== and ID==, and see what is the downside for SAME==. Surely it?s very small today, since inline instances are not yet common. We can run artificial workloads with a number of inline types flowing through generic code. (In fact, we already have started such analyses, IIRC.) > > > The alternate route to preserving a narrower definition of == is to say that _at the language level_, values are not subtypes of Object. Then, we can credibly say that the eclair companion type is the box, and there is a boxing conversion between V and I (putting the cream in the eclair is like putting it in a box.) This may seem like a huge step backwards, but it actually is a consistent world, and in this world, boxing is a super-lightweight operation. The main concern here is that when a user assigns a value to an object/interface type, and then invokes Object.getClass(), they will see the value class ? which perhaps we can present as ?the runtime box is so light that you can?t even see it.? > > So, this a bold move, which changes the balance between ?codes like a class? and ?works like an int?. > > In fact I am convinced that the tension between those two propositions is where all of our discomfort comes from (about == and many things). The question about val== vs. Object== stresses precisely those points where int and Object have incompatible protocols. Our thesis requires us to split the difference between Object== and int== in order to assign a meaning to val== that is compatible enough with both sides. > > How do we split the difference? Do we align closely with ?codes like a class?, avoiding schism between val== and Object==? Or do we align closely with ?works like an int?, and embrace boxing as a transform that allows such as schism? Is there a third way that makes obvious sense for inline types (even int, eventually)? I think we should shoot for a third way, if we can find one. That seems to offer the best security against importing the limitations of the past into the future. > > > Where this world runs into more trouble is with specialized generics; we?d like to treat specialized Foo as being generic in ?T extends Object?, which subsumes values. This complicates things like bound computation and type inference, and also makes invoking Object methods trickier, since we have to do some sort of reasoning by parts (which we did in M3, but didn?t like it.) > > Yikes, I don?t understand these particular issues fully, but they sound scary. > > Part of the job of splitting the difference between int-nature and Object-nature involves deciding what to do with box/unbox conversions (which are part of int-nature). The ?gravity? of the situation prompts us to click into a tight orbit around either ?boxes and unboxes like an int? or ?subtypes Object like a class?. Maybe there?s a halfway (Lagrange) point out there somewhere, such as ?unboxes like an int and subtypes Object like a class?, where unboxing artifacts show up (as a special form of cast) but not boxing artifacts. Such a new point would compromise the user models of int and Object. We?ve looked hard for such a thing with not much luck on the problem of operator==, but I think it?s worth trying a little longer to come up with it. (Especially if it could make sense of float==, but I?m not holding my breath for that. See below for more thoughts about float==.) > > Looking very closely at the current cycle of int-box-Integer-unbox-int, maybe we can limit the irregularities (the schism mentioned above) in some way that allows us to ?blame? them on the unbox step. After all, the ?codes like a class? part only implies one direction of type conversion, from some V to Object or V.Box (the eclair interface). Going the other way, from V.Box to V, is a pure ?works like an int? move, since Java does not allow implicit down-casting, only unboxing conversions. And we can view V.Box-to-V as an unbox *as well as* (or maybe *instead of*) a down-cast. > > Does this buy us anything? Consider the parallel case of Integer (motivated by ?works like an int?): > > Integer == Integer => ID== > int == Integer => SAME== > Integer == int => SAME== > int == int => SAME== > > (Here, I?m relying on the fact that int== is an instance of SAME==. That?s true except for float== and double==.) > > This suggests a new category of syntactic context for operator==, V.Box. So we have val==, val.box==, and Object==. For int, SAME== makes sense for all of them, although we might want to back off Object== to ID== (see above). Since val.box <: Object, we might expect that operator== must be the same for both, *but no*. The operator== for the box is referred to the prim== for the primitive, if at least one primitive is present. It looks like our job got more complicated. And the gravitational attraction between val== and Object== is more entangled. > > What is the place (in the above setup) of a schism between val== and Object==? It would be that two ID-types (Integer, Object, V.Box) compared with operator== would bind to Object==, hence SAME== (or ID== as a backup). A mix of V-types and ID-types (or pure V-types) would bind to V==, hence SAME== (and *not* ID==). > > The relation V <: V.Box preserves the SAME== semantics of V as long as any given v1==v2 has at least one ?witness? of V (not V.Box). The relation V.Box preserves the SAME== semantics of V, unless we have to back down to ID== (for reasons discussed above). > > The choice of val== vs. Object== is uncomfortable here, but it?s a feature of today?s language. Clearly we wish to improve it, but we are not mandated to fix it, under the slogan ?codes like a class works like an int?, which simply requires us to make a new compromise between existing compromises. > > So I?ll repeat that SAME== saves us a lot of trouble, since it is already compatible with prim== and Object== (except for float== and double==). If we can use SAME== (except for double== and float==) we win. > > If we are forced to back down to ID== (as a binding for Object==), then where and how do we transition from ID== (as Object==) to SAME== (as val==)? I would say that a reasonable level of discomfort would be to emulate today?s rules about X==Y: > > - If either X or Y is an inline type (or primitive) then use val== which is SAME== (or prim==, which is usually SAME==). > - If either X or Y is a super of V.Box (such as Object) then use Object== which is ID== (as a fallback). > - if both X and Y are V.Box then also use Object== (today?s rule!) > > So, today?s Integer, applied to operator==, does not always fall up to Object==. Sometimes it falls down to int==, if an int witness is present. If we replicate that rule for inlines, we obtain an uncomfortable mix between ?codes like a class? (can jump up to Object) and ?works like an int? (can unbox down to a primitive, which is not like an Object). > > If we don?t want to replicate that model, we have to create a new one and sell *that* to users. So my point here, I guess, is that if we move towards a ?box-centric? design for separating val== from Object==, as Brian suggests, there are still shades of gray between V and Object (namely V.Box). > > > tl;dr: if we want a unified type system where values are objects, then I think we have to take the obvious semantics for ==, and if we want to reduce the runtime impact on _old_ binaries, we should consider whether giving older binaries older semantics, and taking the discontinuity as the cost of unification. > > So far we have avoided the vexed issue of float== and double==, which is yet another kind of equality. *If* we were to somehow nullify the gravitational entanglement of val== with Object==, and define val==(x,y) as something different from Object==(x,y) (i.e., (Object)x==(Object)y), *then* we could safely define val== in a way that can extend to cover float== (which isn?t even an equality comparison, since it isn?t reflexive on NaN). *But* the costs of this are (1) not being able to define any val== until we have an operator overloading story, *and* (2) having a permanent schism between Object== and V== for many V types, not just float and double. > > Personally, I think the cost seems high for this. But, it provides (to me) a slight hint that we could *delay* defining val==, forcing early access users to say what they mean, using a method call to compare their values in statically typed code, while we consider the matter further. This is a toe-dip into the waters of Brian?s "Re-explore a boxing relationship between V and Object? but without going all the way in. > > To summarize, I see three stable positions: > > A. Make Object== and val== bind to SAME==, using JIT optimizations to the hilt. (At this point, bind ACMP to SAME== also.) Then only float== and double== are outliers to be dealt with later using ad hoc rules. > > B. Make Object== be SAME== and val== be an overloaded operator, usually SAME== (except for float, double, and IEEE-like user types). Overloading can be introduced later; we start by hardwiring val== as SAME== but plan to unlock it to users. > > C. Make Object== be ID== and val== be an overloaded operator as in B. This is motivated as a fall-back from B, if we get evidence that the slow path of SAME== is burdensome for dynamic code. > > In *all cases* we need named entry points for SAME== and ID== (not FAST==) so users can say what they mean. I think SAME== should have bindings for both Object (dynamic typing) and every V (static typing). > > We can choose A and later extend it to B. > > In addition, there is a fourth unstable position which may be temporarily desirable: > > D. Do not define val== as yet, but rather supply symbolic methods for ID== and SAME==. Let users say what they mean. Define Object== as ID== or even FAST== (undefined result) as a temporary measure. See what users say, and adjust the model accordingly to one of A or B above. > > We can choose D and later extend it to any of A, B, or C. > > This was very long; I hope it helps. > > ? John > From brian.goetz at oracle.com Mon Aug 12 18:23:15 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 12 Aug 2019 14:23:15 -0400 Subject: Equality for values -- new analysis, same conclusion In-Reply-To: References: <90C17B62-5968-4352-825E-4F1EFAC81052@oracle.com> <131B9329-ECE7-46BE-909F-AC88421FF6CB@oracle.com> Message-ID: <5c698159-6bc9-12f0-e117-7d3c2f44faaa@oracle.com> > This mail continues a thread at valhalla-spec-experts. Party foul!? There is a reason there are separate lists, and forking a thread from -experts to the -dev list -- especially one in such active discussion -- is not consistent with the charter, or spirit, of the -dev lists.? Please, let the experts do their work.? We do it in the open, but having concurrent discussions on both lists is value-destroying.? When things appear to have settled, it might be more acceptable to weigh in like this on the -dev list, but still should be done with care. > Firstly, I think the new direction of "values are objects" and using > names/eclairs seems worth exploring and I don't have much to add > (although I'm not looking forward to an alternate name or a default > value for LocalDate). I share your concern about the migration strategy.? Significant effort and resources were spent exploring whether in-place migration was practical, though, and it seems to be the consensus that the complexity costs of doing so outweight the (obviously significant) benefits.? So, while we didn't come up with the answer you (or I) wanted, I'll take that as a "thank you for trying really hard." > I find myself mostly in agreement with Remi - in principle, the > current == operator at the language level needs to die and be removed > - it is a mistake of history. Not surprising; you usually come down on the side of "X was a mistake, let's get rid of it" in these discussions.? But, not all users are as eager to ditch their intuition, even if the new intuition is in some sense "better".?? Regardless, such didactic statements of "X is a mistake of history" are generally not helpful, because they prevent us from exploring the entire space, which often leads to creating constraints that leave us with bad choices elsewhere, so these things need to be considered holistically.? "I don't like how X was done in the past, this is our chance to fix it" is frequently a siren song.? (In fact, the reason we didn't see some of these simplifications sooner is that we assumed "in-place migration" to be a requirement, which in turn made it harder to see the costs.? Lesson learned, hopefully.) > What I'd really like to see is some serious brain-power applied to the > question of how to get from where we are today to a world where there > is an operator for .equals() for all types (Objects and values). I get why you want this, and I'm not hostile to the idea, but this is a separable (and by comparison, trivial) problem.? It is infinitely more important to define consistent and stable foundations for the basic underpinnings of the language and JVM, so we're focusing on that now. From ioi.lam at oracle.com Tue Aug 13 03:50:23 2019 From: ioi.lam at oracle.com (Ioi Lam) Date: Mon, 12 Aug 2019 20:50:23 -0700 Subject: RFR 8229382 [lworld][c1] TestLWorld.java crashes with -XX:+UseSerialGC Message-ID: <973dbe8b-b58c-e7db-014a-6646e71ba745@oracle.com> https://bugs.openjdk.java.net/browse/JDK-8229382 http://cr.openjdk.java.net/~iklam/valhalla/8229382-c1-dont-cache-constants-in-conditional-code.v01/ Background ---------- When c1_LIRGenerator.cpp translates the HIR of a basic block to LIR, and it loads a constant C into a virtual register R, it assumes that this must happen for all possible paths through this basic block. Thus, it uses a cache of {constant} -> {register} to avoid loading the same constant C again in the same basic block. See LIRGenerator::load_constant(). However, when translating aastore, we end up having code like this: ?0x7f46c544a260: test $0x1,%bl??????????? ; is this array flattened? ?0x7f46c544a263: jne 0x7f46c544a376?? ? ? ; call store_flattened_array ?.... ?0x7f46c544a28b: mov $0x7f03335dc000,%rsi ; card_table_base ?0x7f46c544a295: movb $0x0,(%rax,%rsi,1)? ; mark card table so the constant card_table_base is stored into %rsi only if the array is not flattened. When a subsequent aastore is translated, we mistakenly assume that %rsi already contains the desired value. The code will crash when using %rsi to mark the card table. Fix --- The fix is to avoid caching constants used in conditionally executed LIR. I also added assertions so we don't call LIRItem::load_item() while generating conditionally executed LIR. Otherwise we will create {Value} -> {LIR_Opr} mappings (i.e., from HIR values to LIR virtual registers) that are not always valid. I looked at every line of "__ branch_destination" added by the valhalla code and hopefully have caught all the bugs introduced by me. Thanks - Ioi From frederic.parain at oracle.com Tue Aug 13 19:42:50 2019 From: frederic.parain at oracle.com (Frederic Parain) Date: Tue, 13 Aug 2019 15:42:50 -0400 Subject: RFR: 8229372: Static inline fields should allow circularity. Message-ID: <13B5C3C0-B21D-401A-A5A8-B8D648BF0018@oracle.com> Greeting, Here?s a changeset to relax the circularity rules for static fields. The handling of erroneous situations is not great, but relaxing rules could allow explorations at the language level. Error handling would have to be fixed later (it requires to store the error on first initialization failure, in order to throw exactly the same error on further attempts to initialize the field). CR: https://bugs.openjdk.java.net/browse/JDK-8229372 Webrev: http://cr.openjdk.java.net/~fparain/statics2/webrev.00/index.html Thank you, Fred From tobias.hartmann at oracle.com Wed Aug 14 05:59:42 2019 From: tobias.hartmann at oracle.com (Tobias Hartmann) Date: Wed, 14 Aug 2019 07:59:42 +0200 Subject: RFR 8229382 [lworld][c1] TestLWorld.java crashes with -XX:+UseSerialGC In-Reply-To: <973dbe8b-b58c-e7db-014a-6646e71ba745@oracle.com> References: <973dbe8b-b58c-e7db-014a-6646e71ba745@oracle.com> Message-ID: Hi Ioi, good catch! Looks good to me. Thanks, Tobias On 13.08.19 05:50, Ioi Lam wrote: > https://bugs.openjdk.java.net/browse/JDK-8229382 > http://cr.openjdk.java.net/~iklam/valhalla/8229382-c1-dont-cache-constants-in-conditional-code.v01/ > > Background > ---------- > > When c1_LIRGenerator.cpp translates the HIR of a basic block to LIR, and it > loads a constant C into a virtual register R, it assumes that this must happen > for all possible paths through this basic block. Thus, it uses a cache > of {constant} -> {register} to avoid loading the same constant C again > in the same basic block. See LIRGenerator::load_constant(). > > However, when translating aastore, we end up having code like this: > > ?0x7f46c544a260: test $0x1,%bl??????????? ; is this array flattened? > ?0x7f46c544a263: jne 0x7f46c544a376?? ? ? ; call store_flattened_array > ?.... > ?0x7f46c544a28b: mov $0x7f03335dc000,%rsi ; card_table_base > ?0x7f46c544a295: movb $0x0,(%rax,%rsi,1)? ; mark card table > > so the constant card_table_base is stored into %rsi only if the array > is not flattened. > > When a subsequent aastore is translated, we mistakenly assume that > %rsi already contains the desired value. The code will crash when > using %rsi to mark the card table. > > > Fix > --- > > The fix is to avoid caching constants used in conditionally executed LIR. > > I also added assertions so we don't call LIRItem::load_item() while > generating conditionally executed LIR. Otherwise we will create > {Value} -> {LIR_Opr} mappings (i.e., from HIR values to LIR virtual > registers) that are not always valid. > > I looked at every line of "__ branch_destination" added by the > valhalla code and hopefully have caught all the bugs introduced by me. > > Thanks > - Ioi > From ioi.lam at oracle.com Wed Aug 14 06:10:01 2019 From: ioi.lam at oracle.com (Ioi Lam) Date: Tue, 13 Aug 2019 23:10:01 -0700 Subject: RFR 8229382 [lworld][c1] TestLWorld.java crashes with -XX:+UseSerialGC In-Reply-To: References: <973dbe8b-b58c-e7db-014a-6646e71ba745@oracle.com> Message-ID: <34346406-ff66-b756-22e8-1e6c9fe80b9e@oracle.com> Hi Tobias, Thanks for the review. I found a bug in the patch. LIRGenerator::load_constant() should look like this: ??? if (!in_conditional_code()) { ? ? ? _constants.append(c); + ? ? _reg_for_constants.append(result); ??? } -?? _reg_for_constants.append(result); Now all valhalla tests passed with C1 and -XX:+UseSerialGC. I will do more testing before pushing. Thanks - Ioi On 8/13/19 10:59 PM, Tobias Hartmann wrote: > Hi Ioi, > > good catch! Looks good to me. > > Thanks, > Tobias > > On 13.08.19 05:50, Ioi Lam wrote: >> https://bugs.openjdk.java.net/browse/JDK-8229382 >> http://cr.openjdk.java.net/~iklam/valhalla/8229382-c1-dont-cache-constants-in-conditional-code.v01/ >> >> Background >> ---------- >> >> When c1_LIRGenerator.cpp translates the HIR of a basic block to LIR, and it >> loads a constant C into a virtual register R, it assumes that this must happen >> for all possible paths through this basic block. Thus, it uses a cache >> of {constant} -> {register} to avoid loading the same constant C again >> in the same basic block. See LIRGenerator::load_constant(). >> >> However, when translating aastore, we end up having code like this: >> >> ?0x7f46c544a260: test $0x1,%bl??????????? ; is this array flattened? >> ?0x7f46c544a263: jne 0x7f46c544a376?? ? ? ; call store_flattened_array >> ?.... >> ?0x7f46c544a28b: mov $0x7f03335dc000,%rsi ; card_table_base >> ?0x7f46c544a295: movb $0x0,(%rax,%rsi,1)? ; mark card table >> >> so the constant card_table_base is stored into %rsi only if the array >> is not flattened. >> >> When a subsequent aastore is translated, we mistakenly assume that >> %rsi already contains the desired value. The code will crash when >> using %rsi to mark the card table. >> >> >> Fix >> --- >> >> The fix is to avoid caching constants used in conditionally executed LIR. >> >> I also added assertions so we don't call LIRItem::load_item() while >> generating conditionally executed LIR. Otherwise we will create >> {Value} -> {LIR_Opr} mappings (i.e., from HIR values to LIR virtual >> registers) that are not always valid. >> >> I looked at every line of "__ branch_destination" added by the >> valhalla code and hopefully have caught all the bugs introduced by me. >> >> Thanks >> - Ioi >> From srikanth.adayapalam at oracle.com Wed Aug 14 08:33:27 2019 From: srikanth.adayapalam at oracle.com (srikanth.adayapalam at oracle.com) Date: Wed, 14 Aug 2019 08:33:27 +0000 Subject: hg: valhalla/valhalla: 8229537: [lworld] Poor interaction between explicit lambda parameters and nullable projection types. Message-ID: <201908140833.x7E8XSED021448@aojmv0008.oracle.com> Changeset: 7ec951ef532d Author: sadayapalam Date: 2019-08-14 14:03 +0530 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d 8229537: [lworld] Poor interaction between explicit lambda parameters and nullable projection types. ! src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java + test/langtools/tools/javac/valhalla/lworld-values/ExplicitLambdaWithNullableTypes.java + test/langtools/tools/javac/valhalla/lworld-values/ExplicitLambdaWithNullableTypes2.java + test/langtools/tools/javac/valhalla/lworld-values/ExplicitLambdaWithNullableTypes3.java + test/langtools/tools/javac/valhalla/lworld-values/ExplicitLambdaWithNullableTypes3.out From srikanth.adayapalam at oracle.com Wed Aug 14 08:45:26 2019 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Wed, 14 Aug 2019 14:15:26 +0530 Subject: Can't make simple Streams over indirect projects work In-Reply-To: References: Message-ID: <030e9ee6-2c77-b643-4fe6-c08fdb8e85dc@oracle.com> Hello Ben, With this push: http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d for https://bugs.openjdk.java.net/browse/JDK-8229537, I believe the code snippet below compiles fine (once suitable imports are typed in) However, this program fails at runtime with "Exception in thread "main" java.lang.ClassCircularityError: OptionalInt" - this circularity error is a bogus error that is being addressed as we speak by the good folks at the VM team. See https://mail.openjdk.java.net/pipermail/valhalla-dev/2019-August/006229.html which initiates a review of a fix for https://bugs.openjdk.java.net/browse/JDK-8229372. In the meantime, you can easily workaround the circularity problem by manually constant propagating OptionalInt.default into the only place OptionalInt.EMPTY is used. You may want to peruse the tests I have added here, http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d Thanks! Srikanth On 28/07/19 6:44 PM, Ben Evans wrote: > Hi, > > I'm probably missing something really obvious, but I've been playing > with this code for several days and can't find my bug. > > Given an inline class defined like this: > > public inline class OptionalInt { > private static final OptionalInt EMPTY = OptionalInt.default; > > private boolean isPresent = false; > private int v = 0; > > public static OptionalInt empty() { > return EMPTY; > } > > public static OptionalInt of(int val) { > OptionalInt self = OptionalInt.default; > self = __WithField(self.v, val); > self = __WithField(self.isPresent, true); > return self; > } > > public int getAsInt() { > if (!isPresent) > throw new NoSuchElementException("No value present"); > > return v; > } > > public boolean isPresent() { > return isPresent; > } > > public void ifPresent(IntConsumer consumer) { > if (isPresent) > consumer.accept(v); > } > > public int orElse(int other) { > return isPresent ? v : other; > } > } > > and some code that attempts to use it like this: > > public final class Main4 { > public static void main(String[] args) { > List opts = new ArrayList<>(); > for (int i=0; i < 5; i++) { > opts.add(OptionalInt.of(i)); > opts.add(OptionalInt.empty()); > opts.add(null); > } > > Integer total = opts.stream() > .map((OptionalInt? o) -> { > if (o == null) > return 0; > > OptionalInt op = (OptionalInt)o; > return op.orElse(0); > }) > .reduce(0, (x, y) -> x + y); > > System.out.println("Total: "+ total); > } > } > > Then javac barfs like this: > > bevans$ javac -XDallowWithFieldOperator -XDallowGenericsOverValues > javamag/Main4.java > > javamag/Main4.java:15: error: ')' expected > .map((OptionalInt? o) -> { > ^ > javamag/Main4.java:15: error: : expected > .map((OptionalInt? o) -> { > ^ > javamag/Main4.java:15: error: ';' expected > .map((OptionalInt? o) -> { > ^ > javamag/Main4.java:20: error: illegal start of expression\ > }) > ^ > 4 errors > > Could some kind person put me out of my misery and tell me what I'm > doing wrong here, and what the proper way to express this should be? > > Thanks, > > Ben From srikanth.adayapalam at oracle.com Wed Aug 14 08:51:09 2019 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Wed, 14 Aug 2019 14:21:09 +0530 Subject: Can't make simple Streams over indirect projects work In-Reply-To: References: Message-ID: On 28/07/19 8:02 PM, Ben Evans wrote: > On Sun, 28 Jul 2019 at 13:22, Brian Goetz wrote: >> This is not related to your streams issue, but don?t use __WithField, write a regular ctor. WF is there for testing and will go away. > OK! > >> Try rewriting your stream with all explicit types, including generic withesses, >> To rule out type inference issues. > This code: > > Stream soi = opts.stream(); > ToIntFunction f = (OptionalInt? o) -> { > if (o == null) return 0; > OptionalInt op = (OptionalInt)o; > return op.orElse(0); > }; > IntStream sint = soi.mapToInt(f); > int total = sint.reduce(0, (x, y) -> x + y); > > fails with: > > bevans$ javac -XDallowWithFieldOperator -XDallowGenericsOverValues > javamag/Main4.java > javamag/Main4.java:18: error: ')' expected > ToIntFunction f = (OptionalInt? o) -> { > ^ > javamag/Main4.java:18: error: : expected > ToIntFunction f = (OptionalInt? o) -> { > ^ > 2 errors I believe the code snippet above compiles fine after this push: http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d while the one below still fails to compile. I am looking into whether that is reasonable behavior or not. I hope this unblocks you enough to continue your experiments. Much appreciate the defect reports and your continued testing. Thanks! Srikanth > whereas the type-inferred form: > > Stream soi = opts.stream(); > ToIntFunction f = o -> { > if (o == null) return 0; > OptionalInt op = (OptionalInt)o; > return op.orElse(0); > }; > IntStream sint = soi.mapToInt(f); > int total = sint.reduce(0, (x, y) -> x + y); > > fails with this: > > bevans$ javac -XDallowWithFieldOperator -XDallowGenericsOverValues > javamag/Main4.java > javamag/Main4.java:19: error: incomparable types: OptionalInt and > if (o == null) return 0; > ^ > javamag/Main4.java:18: error: incompatible types: incompatible > parameter types in lambda expression > ToIntFunction f = o -> { > ^ > 2 errors > > Thanks, > > Ben From srikanth.adayapalam at oracle.com Wed Aug 14 10:41:56 2019 From: srikanth.adayapalam at oracle.com (srikanth.adayapalam at oracle.com) Date: Wed, 14 Aug 2019 10:41:56 +0000 Subject: hg: valhalla/valhalla: 8229700: [lworld] Incorrect lambda implicit parameter type inference in the presence of nullable projection types Message-ID: <201908141041.x7EAfvac006237@aojmv0008.oracle.com> Changeset: 332773949385 Author: sadayapalam Date: 2019-08-14 16:11 +0530 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/332773949385 8229700: [lworld] Incorrect lambda implicit parameter type inference in the presence of nullable projection types ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java ! test/langtools/tools/javac/valhalla/lworld-values/ExplicitLambdaWithNullableTypes3.java - test/langtools/tools/javac/valhalla/lworld-values/ExplicitLambdaWithNullableTypes3.out From srikanth.adayapalam at oracle.com Wed Aug 14 10:48:46 2019 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Wed, 14 Aug 2019 16:18:46 +0530 Subject: Can't make simple Streams over indirect projects work In-Reply-To: References: Message-ID: On 14/08/19 2:21 PM, Srikanth wrote: [...] > I believe the code snippet above compiles fine after this push: > http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d > > while the one below still fails to compile. I am looking into whether > that is reasonable behavior or not. With the push http://hg.openjdk.java.net/valhalla/valhalla/rev/332773949385 for https://bugs.openjdk.java.net/browse/JDK-8229700, the code snippet below compiles too. Thanks for the report and continued testing/experimenting with Valhalla. Srikanth > > I hope this unblocks you enough to continue your experiments. > > Much appreciate the defect reports and your continued testing. > > Thanks! > Srikanth >> whereas the type-inferred form: >> >> Stream soi = opts.stream(); >> ToIntFunction f = o -> { >> ???? if (o == null) return 0; >> ???? OptionalInt op = (OptionalInt)o; >> ???? return op.orElse(0); >> }; >> IntStream sint = soi.mapToInt(f); >> int total = sint.reduce(0, (x, y) -> x + y); >> >> fails with this: >> >> bevans$ javac -XDallowWithFieldOperator -XDallowGenericsOverValues >> javamag/Main4.java >> javamag/Main4.java:19: error: incomparable types: OptionalInt and >> ???????????? if (o == null) return 0; >> ?????????????????? ^ >> javamag/Main4.java:18: error: incompatible types: incompatible >> parameter types in lambda expression >> ???????? ToIntFunction f = o -> { >> ???????????????????????????????????????? ^ >> 2 errors >> >> Thanks, >> >> Ben > From david.simms at oracle.com Wed Aug 14 12:59:51 2019 From: david.simms at oracle.com (David Simms) Date: Wed, 14 Aug 2019 14:59:51 +0200 Subject: RFR: 8229372: Static inline fields should allow circularity. In-Reply-To: <13B5C3C0-B21D-401A-A5A8-B8D648BF0018@oracle.com> References: <13B5C3C0-B21D-401A-A5A8-B8D648BF0018@oracle.com> Message-ID: <355381ff-bd25-ee9b-1eb0-165e4ad21f73@oracle.com> All in all it looks good... I did need to re-read the code back (a second time) from src/hotspot/share/interpreter/interpreterRuntime.cpp:400, the point was the CHECK macros as per the intro comment should throw and the fatal not be reached. fatal() message says this. Cheer, thanks for the fix Frederic ! On 2019-08-13 21:42, Frederic Parain wrote: > Greeting, > > Here?s a changeset to relax the circularity rules > for static fields. > > The handling of erroneous situations is not great, > but relaxing rules could allow explorations at > the language level. Error handling would have to > be fixed later (it requires to store the error on > first initialization failure, in order to throw exactly > the same error on further attempts to initialize the field). > > CR: https://bugs.openjdk.java.net/browse/JDK-8229372 > > Webrev: http://cr.openjdk.java.net/~fparain/statics2/webrev.00/index.html > > Thank you, > > Fred From david.simms at oracle.com Wed Aug 14 13:07:10 2019 From: david.simms at oracle.com (David Simms) Date: Wed, 14 Aug 2019 15:07:10 +0200 Subject: LW2 EA binaries refreshed with latest fixes this Friday Message-ID: <355aad28-94df-d632-3d3c-d66bee5c4c3f@oracle.com> Just wanted to drop a quick thanks to folks for finding bugs and helping bring about fixes in the LW2 prototype. We appreciate your efforts in trying out the LW2 prototype. Don't be shy with feedback ! There is a a plan to refresh the LW2 EA binaries this Friday, with all the latest bug fixes. /David SImms From tobias.hartmann at oracle.com Wed Aug 14 14:01:34 2019 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Wed, 14 Aug 2019 14:01:34 +0000 Subject: hg: valhalla/valhalla: 8229443: [lworld] Missing anti-dependency between loads and stores from flattened array Message-ID: <201908141401.x7EE1aZ0009820@aojmv0008.oracle.com> Changeset: d4012b801ae3 Author: thartmann Date: 2019-08-14 16:01 +0200 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/d4012b801ae3 8229443: [lworld] Missing anti-dependency between loads and stores from flattened array ! src/hotspot/share/opto/compile.cpp ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestArrays.java From benjamin.john.evans at gmail.com Wed Aug 14 14:13:24 2019 From: benjamin.john.evans at gmail.com (Ben Evans) Date: Wed, 14 Aug 2019 16:13:24 +0200 Subject: Can't make simple Streams over indirect projects work In-Reply-To: <030e9ee6-2c77-b643-4fe6-c08fdb8e85dc@oracle.com> References: <030e9ee6-2c77-b643-4fe6-c08fdb8e85dc@oracle.com> Message-ID: Thanks Srikanth. I can confirm that this does indeed fix my examples. However, when I try to generalise this to deal with optional values of reference type, then while this compiles: public inline class Optional { private T value; @SuppressWarnings("unchecked") public static Optional empty() { return (Optional) Optional.default; } private Optional(T value) { this.value = value; } public static Optional of(T value) { if (value == null) return empty(); return new Optional(value); } public T get() { if (value == null) throw new NoSuchElementException("No value present"); return value; } public boolean isPresent() { return value != null; } public T orElse(T other) { return value != null ? value : other; } public Optional map(Function mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else return Optional.of(mapper.apply(value)); } @Override public String toString() { return value != null ? String.format("Optional[%s]", value) : "Optional.empty"; } } all my attempts to use it, eg. via code like this: List> opts = new ArrayList<>(); for (int i=0; i < 5; i++) { Optional oi = Optional.of(i); opts.add((Optional?)oi); Optional oe = Optional.empty(); opts.add((Optional?)oe); } Integer total = opts.stream() .map((Optional? o) -> { Optional op = (Optional)o; return op.orElse(0); }) .reduce(0, (x, y) -> x + y); System.out.println("Total: "+ total); fail to compile. Have I misunderstood something here? Is Optional? a valid type, and should it be possible to project the inline type Optional to it? Thanks, Ben On Wed, 14 Aug 2019 at 10:46, Srikanth wrote: > > Hello Ben, > > With this push: > http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d for > https://bugs.openjdk.java.net/browse/JDK-8229537, I believe the code > snippet below > compiles fine (once suitable imports are typed in) > > However, this program fails at runtime with "Exception in thread "main" > java.lang.ClassCircularityError: OptionalInt" - this circularity error > is a bogus error that is being addressed as we speak by the good folks > at the VM team. > > See > https://mail.openjdk.java.net/pipermail/valhalla-dev/2019-August/006229.html > which initiates a review of a fix for > https://bugs.openjdk.java.net/browse/JDK-8229372. > > In the meantime, you can easily workaround the circularity problem by > manually constant propagating OptionalInt.default into the only place > OptionalInt.EMPTY is used. > > You may want to peruse the tests I have added here, > http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d > > Thanks! > Srikanth > > On 28/07/19 6:44 PM, Ben Evans wrote: > > Hi, > > > > I'm probably missing something really obvious, but I've been playing > > with this code for several days and can't find my bug. > > > > Given an inline class defined like this: > > > > public inline class OptionalInt { > > private static final OptionalInt EMPTY = OptionalInt.default; > > > > private boolean isPresent = false; > > private int v = 0; > > > > public static OptionalInt empty() { > > return EMPTY; > > } > > > > public static OptionalInt of(int val) { > > OptionalInt self = OptionalInt.default; > > self = __WithField(self.v, val); > > self = __WithField(self.isPresent, true); > > return self; > > } > > > > public int getAsInt() { > > if (!isPresent) > > throw new NoSuchElementException("No value present"); > > > > return v; > > } > > > > public boolean isPresent() { > > return isPresent; > > } > > > > public void ifPresent(IntConsumer consumer) { > > if (isPresent) > > consumer.accept(v); > > } > > > > public int orElse(int other) { > > return isPresent ? v : other; > > } > > } > > > > and some code that attempts to use it like this: > > > > public final class Main4 { > > public static void main(String[] args) { > > List opts = new ArrayList<>(); > > for (int i=0; i < 5; i++) { > > opts.add(OptionalInt.of(i)); > > opts.add(OptionalInt.empty()); > > opts.add(null); > > } > > > > Integer total = opts.stream() > > .map((OptionalInt? o) -> { > > if (o == null) > > return 0; > > > > OptionalInt op = (OptionalInt)o; > > return op.orElse(0); > > }) > > .reduce(0, (x, y) -> x + y); > > > > System.out.println("Total: "+ total); > > } > > } > > > > Then javac barfs like this: > > > > bevans$ javac -XDallowWithFieldOperator -XDallowGenericsOverValues > > javamag/Main4.java > > > > javamag/Main4.java:15: error: ')' expected > > .map((OptionalInt? o) -> { > > ^ > > javamag/Main4.java:15: error: : expected > > .map((OptionalInt? o) -> { > > ^ > > javamag/Main4.java:15: error: ';' expected > > .map((OptionalInt? o) -> { > > ^ > > javamag/Main4.java:20: error: illegal start of expression\ > > }) > > ^ > > 4 errors > > > > Could some kind person put me out of my misery and tell me what I'm > > doing wrong here, and what the proper way to express this should be? > > > > Thanks, > > > > Ben > From srikanth.adayapalam at oracle.com Wed Aug 14 14:33:46 2019 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Wed, 14 Aug 2019 20:03:46 +0530 Subject: Can't make simple Streams over indirect projects work In-Reply-To: References: <030e9ee6-2c77-b643-4fe6-c08fdb8e85dc@oracle.com> Message-ID: <3ea05bbe-4e03-8297-9bbd-b78f91ec62d7@oracle.com> Thanks Ben, I will study this and get back soon (tomorrow is a holiday in my location, so by Friday) Srikanth On 14/08/19 7:43 PM, Ben Evans wrote: > Thanks Srikanth. > > I can confirm that this does indeed fix my examples. > > However, when I try to generalise this to deal with optional values of > reference type, then while this compiles: > > public inline class Optional { > private T value; > > @SuppressWarnings("unchecked") > public static Optional empty() { > return (Optional) Optional.default; > } > > private Optional(T value) { > this.value = value; > } > > public static Optional of(T value) { > if (value == null) > return empty(); > return new Optional(value); > } > > public T get() { > if (value == null) > throw new NoSuchElementException("No value present"); > return value; > } > > public boolean isPresent() { > return value != null; > } > > public T orElse(T other) { > return value != null ? value : other; > } > > public Optional map(Function mapper) { > Objects.requireNonNull(mapper); > if (!isPresent()) > return empty(); > else > return Optional.of(mapper.apply(value)); > } > > @Override > public String toString() { > return value != null > ? String.format("Optional[%s]", value) > : "Optional.empty"; > } > } > > all my attempts to use it, eg. via code like this: > > List> opts = new ArrayList<>(); > for (int i=0; i < 5; i++) { > Optional oi = Optional.of(i); > opts.add((Optional?)oi); > Optional oe = Optional.empty(); > opts.add((Optional?)oe); > } > Integer total = opts.stream() > .map((Optional? o) -> { > Optional op = (Optional)o; > return op.orElse(0); > }) > .reduce(0, (x, y) -> x + y); > > System.out.println("Total: "+ total); > > fail to compile. > > Have I misunderstood something here? Is Optional? a valid > type, and should it be possible to project the inline type > Optional to it? > > Thanks, > > Ben > > > On Wed, 14 Aug 2019 at 10:46, Srikanth wrote: >> Hello Ben, >> >> With this push: >> http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d for >> https://bugs.openjdk.java.net/browse/JDK-8229537, I believe the code >> snippet below >> compiles fine (once suitable imports are typed in) >> >> However, this program fails at runtime with "Exception in thread "main" >> java.lang.ClassCircularityError: OptionalInt" - this circularity error >> is a bogus error that is being addressed as we speak by the good folks >> at the VM team. >> >> See >> https://mail.openjdk.java.net/pipermail/valhalla-dev/2019-August/006229.html >> which initiates a review of a fix for >> https://bugs.openjdk.java.net/browse/JDK-8229372. >> >> In the meantime, you can easily workaround the circularity problem by >> manually constant propagating OptionalInt.default into the only place >> OptionalInt.EMPTY is used. >> >> You may want to peruse the tests I have added here, >> http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d >> >> Thanks! >> Srikanth >> >> On 28/07/19 6:44 PM, Ben Evans wrote: >>> Hi, >>> >>> I'm probably missing something really obvious, but I've been playing >>> with this code for several days and can't find my bug. >>> >>> Given an inline class defined like this: >>> >>> public inline class OptionalInt { >>> private static final OptionalInt EMPTY = OptionalInt.default; >>> >>> private boolean isPresent = false; >>> private int v = 0; >>> >>> public static OptionalInt empty() { >>> return EMPTY; >>> } >>> >>> public static OptionalInt of(int val) { >>> OptionalInt self = OptionalInt.default; >>> self = __WithField(self.v, val); >>> self = __WithField(self.isPresent, true); >>> return self; >>> } >>> >>> public int getAsInt() { >>> if (!isPresent) >>> throw new NoSuchElementException("No value present"); >>> >>> return v; >>> } >>> >>> public boolean isPresent() { >>> return isPresent; >>> } >>> >>> public void ifPresent(IntConsumer consumer) { >>> if (isPresent) >>> consumer.accept(v); >>> } >>> >>> public int orElse(int other) { >>> return isPresent ? v : other; >>> } >>> } >>> >>> and some code that attempts to use it like this: >>> >>> public final class Main4 { >>> public static void main(String[] args) { >>> List opts = new ArrayList<>(); >>> for (int i=0; i < 5; i++) { >>> opts.add(OptionalInt.of(i)); >>> opts.add(OptionalInt.empty()); >>> opts.add(null); >>> } >>> >>> Integer total = opts.stream() >>> .map((OptionalInt? o) -> { >>> if (o == null) >>> return 0; >>> >>> OptionalInt op = (OptionalInt)o; >>> return op.orElse(0); >>> }) >>> .reduce(0, (x, y) -> x + y); >>> >>> System.out.println("Total: "+ total); >>> } >>> } >>> >>> Then javac barfs like this: >>> >>> bevans$ javac -XDallowWithFieldOperator -XDallowGenericsOverValues >>> javamag/Main4.java >>> >>> javamag/Main4.java:15: error: ')' expected >>> .map((OptionalInt? o) -> { >>> ^ >>> javamag/Main4.java:15: error: : expected >>> .map((OptionalInt? o) -> { >>> ^ >>> javamag/Main4.java:15: error: ';' expected >>> .map((OptionalInt? o) -> { >>> ^ >>> javamag/Main4.java:20: error: illegal start of expression\ >>> }) >>> ^ >>> 4 errors >>> >>> Could some kind person put me out of my misery and tell me what I'm >>> doing wrong here, and what the proper way to express this should be? >>> >>> Thanks, >>> >>> Ben From brian.goetz at oracle.com Wed Aug 14 17:30:13 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 14 Aug 2019 13:30:13 -0400 Subject: Can't make simple Streams over indirect projects work In-Reply-To: References: <030e9ee6-2c77-b643-4fe6-c08fdb8e85dc@oracle.com> Message-ID: <940f069c-c082-7179-954b-7dc5c57d9c5c@oracle.com> Ben; We appreciate your exploring these corners.? But, just by way of setting expectations, there's nothing "simple" about this example; you're hitting on all the areas that are at the periphery of the L2 goals.? So while we would of course like for these things to work, we're not surprised there are pitfalls and interactions.? (I say this because I want to avoid having the "simple" framing derail the discussion.) > all my attempts to use it, eg. via code like this: > > List> opts = new ArrayList<>(); The interaction of generic instantiation and the nullable projection type are definitely in the corners right now.? This would be spelled `Optional?`, though; the `?` applies to the final (inline) type, not to the base type.? (You would spell the raw type `Optional?`.)? But, I suspect in the current prototype, that syntax will not work either. But yes, it should be possible to project the type `Optional` to a nullable projection. From frederic.parain at oracle.com Wed Aug 14 19:16:22 2019 From: frederic.parain at oracle.com (Frederic Parain) Date: Wed, 14 Aug 2019 15:16:22 -0400 Subject: RFR: 8229372: Static inline fields should allow circularity. In-Reply-To: <355381ff-bd25-ee9b-1eb0-165e4ad21f73@oracle.com> References: <13B5C3C0-B21D-401A-A5A8-B8D648BF0018@oracle.com> <355381ff-bd25-ee9b-1eb0-165e4ad21f73@oracle.com> Message-ID: Thank you for the review. Fred > On Aug 14, 2019, at 08:59, David Simms wrote: > > All in all it looks good... > > I did need to re-read the code back (a second time) from src/hotspot/share/interpreter/interpreterRuntime.cpp:400, the point was the CHECK macros as per the intro comment should throw and the fatal not be reached. fatal() message says this. > > Cheer, thanks for the fix Frederic ! > > On 2019-08-13 21:42, Frederic Parain wrote: >> Greeting, >> >> Here?s a changeset to relax the circularity rules >> for static fields. >> >> The handling of erroneous situations is not great, >> but relaxing rules could allow explorations at >> the language level. Error handling would have to >> be fixed later (it requires to store the error on >> first initialization failure, in order to throw exactly >> the same error on further attempts to initialize the field). >> >> CR: https://bugs.openjdk.java.net/browse/JDK-8229372 >> >> Webrev: http://cr.openjdk.java.net/~fparain/statics2/webrev.00/index.html >> >> Thank you, >> >> Fred From frederic.parain at oracle.com Wed Aug 14 20:25:26 2019 From: frederic.parain at oracle.com (frederic.parain at oracle.com) Date: Wed, 14 Aug 2019 20:25:26 +0000 Subject: hg: valhalla/valhalla: 8229372: Static inline fields should allow circularity. Message-ID: <201908142025.x7EKPRYu005134@aojmv0008.oracle.com> Changeset: 101ce40e3a48 Author: fparain Date: 2019-08-14 16:25 -0400 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/101ce40e3a48 8229372: Static inline fields should allow circularity. Reviewed-by: dsimms ! src/hotspot/share/classfile/classFileParser.cpp ! src/hotspot/share/interpreter/interpreterRuntime.cpp ! src/hotspot/share/oops/instanceKlass.cpp ! src/hotspot/share/oops/instanceKlass.hpp + test/hotspot/jtreg/runtime/valhalla/valuetypes/StaticFieldsTest.java ! test/hotspot/jtreg/runtime/valhalla/valuetypes/classfileparser/BadValueTypes.java From ioi.lam at oracle.com Wed Aug 14 21:31:22 2019 From: ioi.lam at oracle.com (ioi.lam at oracle.com) Date: Wed, 14 Aug 2019 21:31:22 +0000 Subject: hg: valhalla/valhalla: 3 new changesets Message-ID: <201908142131.x7ELVOC3009943@aojmv0008.oracle.com> Changeset: 5adc09e1911c Author: iklam Date: 2019-08-14 12:45 -0700 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/5adc09e1911c 8229382: [lworld][c1] TestLWorld.java crashes with -XX:+UseSerialGC Summary: Do not cache C1 constants in conditionally executed LIR Reviewed-by: thartmann ! src/hotspot/share/c1/c1_LIRGenerator.cpp ! src/hotspot/share/c1/c1_LIRGenerator.hpp Changeset: 6a93e12b50a2 Author: iklam Date: 2019-08-14 12:45 -0700 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/6a93e12b50a2 8229754: [lworld][c1] arraycopy_valuetype_check needs to do null check first ! src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp ! src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestArrays.java Changeset: 75d30aa932ff Author: iklam Date: 2019-08-14 12:46 -0700 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/75d30aa932ff 8229753: [lworld] TESTBUG Do not force COMP_LEVEL_SIMPLE when EnableValhallaC1 is true ! test/hotspot/jtreg/compiler/valhalla/valuetypes/ValueTypeTest.java From tobias.hartmann at oracle.com Thu Aug 15 10:26:35 2019 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Thu, 15 Aug 2019 10:26:35 +0000 Subject: hg: valhalla/valhalla: 2 new changesets Message-ID: <201908151026.x7FAQaDQ000551@aojmv0008.oracle.com> Changeset: 00cb07e518b9 Author: thartmann Date: 2019-08-15 10:47 +0200 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/00cb07e518b9 8229758: [lworld] SharedRuntime::handle_wrong_method selects wrong entry point for static calls ! src/hotspot/share/runtime/sharedRuntime.cpp ! src/hotspot/share/runtime/sharedRuntime.hpp ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestCallingConvention.java Changeset: a209523c5a7e Author: thartmann Date: 2019-08-15 12:26 +0200 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/a209523c5a7e 8229772: [lworld] OSR compilation fails with inconsistent signature assert ! src/hotspot/share/opto/parse1.cpp ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestCallingConvention.java From frederic.parain at oracle.com Thu Aug 15 13:55:42 2019 From: frederic.parain at oracle.com (Frederic Parain) Date: Thu, 15 Aug 2019 09:55:42 -0400 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> <646D1461-DC45-4DA5-92D6-1C4AE1B254CD@oracle.com> <35ba2593-eb7e-ecb2-7372-b8530514387d@samersoff.net> Message-ID: On 8/12/19 8:14 AM, Dmitry Samersoff wrote: > Hello Frederic, > > The code looks good to me. > > > fieldLayoutBuilder.cpp:35 > > this version of constructor missed size > 0 assert, I'm not sure it's > really important but it's better to keep it uniform. I'll add it. > >>> 561, 641 >>> >>> Does it duplicate similar code within ValueKlass, if not - could we >>> move it there? > >> I?d like to keep the two codes separated. >> They are similar today, but we could realize that decisions to flatten >> or not might not the the same when the container is an identity class >> or an inline class. > > > Sorry to disagree with you here. I would prefer to have all > "is_flattened" logic in a single place. > > I.e., if in the future this logic will differ from the default one, it > is better to keep it inside ValueKlass with a clear path choice, > like is_flattened(bool class_is_inline) But the ultimate decision to flatten a field or not is taken by the container, because it is the one which decide how the field has been declared, annotated, and which additional constraints the container has to deal with. The ValueKlass of the field does not have this context. Today, having a ValueKlass with size < ValueFieldMaxFlatSize is not a guarantee that field will be flattened. If the field is static, it won't be flattened. Soon, if the field has been declared atomic, the decision to flatten won't depend on ValueFieldMaxFlatSize, but on the size of atomic operations supported by the platform. In the future, the number of parameters to consider could continue to increase, with consideration of alignment constraints for instance. All these information are in the container, so the logic to flatten or not must be in the computation of the layout of the container. > Otherwise, it becomes difficult to understand what the command line > options (e.g. ValueFieldMaxFlatSize == 0) affect. As explained above, ValueFieldMaxFlatSize is only one of the parameters considered when deciding to flatten or not. Regards, Fred > On 07.08.19 17:27, Dmitry Samersoff wrote: >> Hello Frederic, >> >>> So, I?d like to keep the old code as a backup for a little while, >>> then remove it. >>> If it causes to much burden for you, let me know. >> >> It doesn't case any burden for me, so feel free to keep this flag. >> >>> I?ve slightly refactored the code, and added a comment to simplify >>> this code ever more once the old layout code is removed. >>> >>> I?ll include changes from your second e-mail before publishing a >>> new webrev. >> >> Ok. >> >> This large and nice work really appreciated. >> >> -Dmitry >> >> On 06.08.19 22:47, Frederic Parain wrote: >>> Hi Dmitry, >>> >>> Thank you for reviewing this huge patch! >>> >>>> On Aug 6, 2019, at 09:52, Dmitry Samersoff wrote: >>>> >>>> Hello Frederic, >>>> >>>> General comment: >>>> >>>> I'm not sure we should have and maintain UseNewLayout flag. What is >>>> the reason to keep old layout? Is there any code that rely on it? >>> >>> The hope is that the old code can be completely removed. >>> However, this is a huge change, so it is kept as a fallback for now. >>> >>> Coleen has asked that the new layout code would be ported to the main line >>> before the Valhalla integration. So I?ve also a port for JDK14 in progress >>> (with more features, the ones not important for project Valhalla), so I?m >>> trying to stabilize both patches at the same time. >>> But field layout has not been changed for so long, that any change can have >>> unexpected consequences. Some codes have very strong assumptions about layout >>> that are in fact just accidental properties of the old code. Enabling some >>> optimizations just breaks these codes, or reveal some bugs (I found a memory >>> corruption in the StackWalking code, unnoticed with old layouts, breaking the >>> StalkWaking code if the layout is slightly different). >>> >>> So, I?d like to keep the old code as a backup for a little while, then remove it. >>> If it causes to much burden for you, let me know. >>> >>>> classFileParser.cpp: >>>> >>>> 5975: >>>> ValueKlass::cast(ik)->set_first_field_offset(_first_field_offset); >>>> >>>> Where the value of _first_field_offset is initialized? >>> >>> This value, which exists only for inline classes, is initialized in >>> FieldLayoutBuilder::compute_inline_class_layout(TRAPS): >>> >>> 738 _first_field_offset = _layout->start()->offset(); >>> >>>> >>>> heapInspection.cpp: >>>> >>>> 736 and below: Should we add const here? >>> >>> Done >>> >>>> >>>> 741 AccessFlags access_flags() { return _access_flags; } >>>> >>>> Could we use >>>> const AccessFlags& access_flags() { return _access_flags; } >>>> here? >>> >>> Done >>> >>>> 749 Please make it const char * and remove further casts >>> >>> Done (Sorry for the ugly code). >>> >>>> >>>> 766, 775 and few locations below. >>>> >>>> You may consider to create a proxy inside FieldDesc >>>> and replace fd.access_flags().is_static() to fd.is_static() >>>> for better readability. >>>> >>> >>> line 766, fd is a FieldStream, not a FieldDesc, I?m not sure it worth >>> adding the proxy. >>> But a proxy has been added to FieldDesc for is_flattenable(). >>> >>> >>>> instanceKlass.cpp >>>> >>>> 1130 set_value_field_klass called before the check at l.1132 >>>> >>>> Is it correct? Should we turn the check to assert? >>> >>> The check is required to deal with separate compilation issues. >>> If class C has a field of type V, V is an inline class when C >>> is compiled, but then V is changed to be a regular class and >>> is recompiled, the JVM has to detect the mismatch and must >>> reject the class with an ICCE. >>> >>> Calling set_value_field_klass() before the check is not really >>> an issue, if the field?s class is not an inline class, the >>> whole class will be rejected and the stored value will never >>> be used. >>> >>> The call to set_value_field_klass() could be moved after the >>> check, but it would require to test this->get_value_field_klass_or_null(fs.index()) >>> one more time (because set_value_field_klass() must be call twice). >>> >>>> >>>> valueKlass.cpp >>>> >>>> 52 please, add else here to improve readability. >>>> >>>> Could we move it to the header? Non inlined first_field_offset that just >>>> a call to inlined get_first_field_offset looks a bit odd to me. >>> >>> I?ve slightly refactored the code, and added a comment to simplify >>> this code ever more once the old layout code is removed. >>> >>> I?ll include changes from your second e-mail before publishing a >>> new webrev. >>> >>> Thank you, >>> >>> Fred >>> >>> >>>> >>>> >>>> Regards, >>>> >>>> -Dmitry\S >>>> >>>> >>>> >>>> On 19.07.19 18:26, Frederic Parain wrote: >>>>> Greetings, >>>>> >>>>> This is the initial request for review for a new code to layout fields. >>>>> The current code to compute field layouts is especially ugly and >>>>> not fitted to efficiently flatten inline classes. >>>>> >>>>> This changeset is an almost complete overhaul of the field layout code, >>>>> with a new framework to compute layouts and two different allocation >>>>> strategies (one for identity classes and one for inline classes). >>>>> >>>>> CR: https://bugs.openjdk.java.net/browse/JDK-8228441 >>>>> Webrev: http://cr.openjdk.java.net/~fparain/layout/webrev.00/ >>>>> >>>>> This changeset also includes some options and DCMD to ease inspection >>>>> of layouts, especially when flattenable fields are involved. >>>>> >>>>> The changeset doesn?t remove the old layout code, meaning that either >>>>> the old code or the new code can be used (controlled by VM flag). >>>>> >>>>> This code passed tiers 1 to 3 on Valhalla supported platforms. >>>>> Some failures have been identified in higher tiers with some @Contended >>>>> tests, but they are due to test bugs (tests making relying on wrong >>>>> assumptions about field layouts). >>>>> >>>>> The code contains a lot of comments about the new framework and the >>>>> different allocation strategies. Feel free to complain if comments >>>>> are not clear enough or if some code need more comments. >>>>> >>>>> Regarding the huge size of this changeset, and people being in summer >>>>> vacation, I?m not planning to push this code in the short term. >>>>> >>>>> Thank you, >>>>> >>>>> Fred >>>>> >>> From tobias.hartmann at oracle.com Fri Aug 16 12:08:18 2019 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Fri, 16 Aug 2019 12:08:18 +0000 Subject: hg: valhalla/valhalla: 8229760: [lworld] OopMap contains invalid oop for field in scalar replaced inline type array element Message-ID: <201908161208.x7GC8JoJ017400@aojmv0008.oracle.com> Changeset: 7f5b8f7cdb42 Author: thartmann Date: 2019-08-16 12:57 +0200 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/7f5b8f7cdb42 8229760: [lworld] OopMap contains invalid oop for field in scalar replaced inline type array element ! src/hotspot/share/opto/macro.cpp ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestArrays.java ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestNullableArrays.java From benjamin.john.evans at gmail.com Fri Aug 16 13:16:21 2019 From: benjamin.john.evans at gmail.com (Ben Evans) Date: Fri, 16 Aug 2019 14:16:21 +0100 Subject: longHashCode? Message-ID: Hi, The web page https://wiki.openjdk.java.net/display/valhalla/LW2 makes reference to an auto-generated longHashCode() method, but the current tip does not appear to generate this method. Is the LW2 page out of date? Thanks, ben From tobias.hartmann at oracle.com Fri Aug 16 13:27:00 2019 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Fri, 16 Aug 2019 13:27:00 +0000 Subject: hg: valhalla/valhalla: 8229823: [lworld] ArrayCopyNode::modifies returns incorrect value for inline type arrays Message-ID: <201908161327.x7GDR1AC005006@aojmv0008.oracle.com> Changeset: b51bfa6eb39f Author: thartmann Date: 2019-08-16 14:38 +0200 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/b51bfa6eb39f 8229823: [lworld] ArrayCopyNode::modifies returns incorrect value for inline type arrays ! src/hotspot/share/opto/arraycopynode.cpp ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestArrays.java From srikanth.adayapalam at oracle.com Fri Aug 16 13:38:44 2019 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Fri, 16 Aug 2019 19:08:44 +0530 Subject: longHashCode? In-Reply-To: References: Message-ID: <7586e43e-9e05-3022-b8cd-1a9b29a7d450@oracle.com> On 16/08/19 6:46 PM, Ben Evans wrote: > Hi, > > The web page https://wiki.openjdk.java.net/display/valhalla/LW2 makes > reference to an auto-generated longHashCode() method, but the current > tip does not appear to generate this method. > > Is the LW2 page out of date? No, It appears to be a regression. I am investigating. Thanks for the report. Srikanth > > Thanks, > > ben From mandy.chung at oracle.com Fri Aug 16 15:07:20 2019 From: mandy.chung at oracle.com (Mandy Chung) Date: Fri, 16 Aug 2019 08:07:20 -0700 Subject: longHashCode? In-Reply-To: References: Message-ID: <15a9a4aa-180f-d59b-0276-334fcf7d6639@oracle.com> On 8/16/19 6:16 AM, Ben Evans wrote: > Hi, > > The web page https://wiki.openjdk.java.net/display/valhalla/LW2 makes > reference to an auto-generated longHashCode() method, but the current > tip does not appear to generate this method. Thanks for the note.? It's not in LW2. > Is the LW2 page out of date? > I updated the wiki page to reflect the current implementation. Mandy From ioi.lam at oracle.com Fri Aug 16 20:30:01 2019 From: ioi.lam at oracle.com (ioi.lam at oracle.com) Date: Fri, 16 Aug 2019 20:30:01 +0000 Subject: hg: valhalla/valhalla: 8229799: [lworld][c1] incorrect handling of return value from SubstitutabilityCheckStub Message-ID: <201908162030.x7GKU2qg007803@aojmv0008.oracle.com> Changeset: a32457198d3e Author: iklam Date: 2019-08-16 13:15 -0700 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/a32457198d3e 8229799: [lworld][c1] incorrect handling of return value from SubstitutabilityCheckStub ! src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp ! src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp ! src/hotspot/share/c1/c1_CodeStubs.hpp ! src/hotspot/share/c1/c1_LIRGenerator.cpp + test/hotspot/jtreg/compiler/valhalla/valuetypes/TestC1.java From kustos at gmx.net Sat Aug 17 15:05:25 2019 From: kustos at gmx.net (Philippe Marschall) Date: Sat, 17 Aug 2019 17:05:25 +0200 Subject: Struggling with Valhalla conversion of library In-Reply-To: References: <49d3aca7-ec3d-894b-695c-cbb3ce09709b@oracle.com> Message-ID: <86cc5350-7942-4760-ce44-3aa116e88e19@gmx.net> Hello Srikanth I was able to retest with the tip of the lworld branch. I can confirm the lambda issue, the first issue, is gone. As for the second issue I was able to extract this minimal reproducer interface Sample, V> { void doesCompile(InlineType argument); void doesNotCompile(java.util.Map.Entry, ? extends V> argument); } inline class InlineType { private E element; InlineType(E element) { this.element = element; } } The method #doesCompile doe compile but the method #doesNotCompile does not compile and instead I get the following error: error: unexpected type void doesNotCompile(java.util.Map.Entry, ? extends V> argument); ^ required: reference found: InlineType where K is a type-variable: K extends Comparable declared in interface Sample Cheers Philippe On 14.08.19 12:51, Srikanth wrote: > Hello Philippe, > > There has been a further defect fix > https://bugs.openjdk.java.net/browse/JDK-8229700 that should also help > you. If you are able to test the tip of valhalla repo lworld branch, > that is great! > > If not, I am told this Friday there will a refresh of the EA bits. That > should simplify testing for those that don't want to work with source > forests. > > Could you in any case please see if you are able to extract test cases > and send them inline in mail ? > That would greatly speed up the turn around time for any remaining > problems. > > Appreciate your testing and the defect reports! > Srikanth > > On 14/08/19 2:39 PM, Srikanth wrote: >> Hello Philippe, >> >> With the resolution of >> https://bugs.openjdk.java.net/browse/JDK-8229537 via the push >> http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d at least >> the first of your >> problems should have been fixed and the explicit lambda version viz: >> >> public static AdjacencyTester adjacencyTester() { >> ??? return (U96? low, U96? high) -> { >> ????? // lambda body >> ??? }; >> ? } >> >> should compile. >> >> Can you check with the lworld branch tip of valhalla ? >> >> I am happy to verify this fix and also investigate a fix for the other >> problems you reported. >> But it would help if I have test cases extracted and attached to mail >> - is that possible ? >> I am not familiar with github and having a bit of a bother getting >> what I need from the >> pointers. >> >> TIA >> Srikanth >> >> On 05/08/19 3:14 AM, Philippe Marschall wrote: >>> Hi >>> >>> As you published the LW2 prototype I thought I tried to convert one of >>> my libraries [1] to Valhalla and see how it goes. Right now I'm >>> struggling with generics. >>> >>> Some context about the library. The library implements a range tree that >>> allows to map a range of keys to a single value. Eg. {[100,199] -> "1", >>> [200,299] -> "2"}. The library should support both inline and reference >>> types as keys and values. >>> The potential for inline classes is limited as the tree nodes are >>> mutable and recursive. There are however two good candidates, the range >>> class and an unsigned 96bit integer class (called U96) that is provided >>> for convenience. >>> >>> The unsigned 96bit integer class? was easy to convert. I had to change >>> it to implements Comparable. I am not yet sure how I want to treat >>> null / 0. >>> But there are two cases where I struggled. >>> >>> First, I have an interface >>> >>> public interface AdjacencyTester { >>> >>> ? boolean areAdjacent(T low, T high); >>> >>> } >>> >>> I want to implement this for the unsigned 96bit integer class (called >>> U96). Right know in Java 8 this is implemented as >>> >>> ? public static AdjacencyTester adjacencyTester() { >>> ??? return (low, high) -> { >>> ????? // lambda body >>> ??? }; >>> ? } >>> >>> Simply converting this to >>> >>> ? public static AdjacencyTester adjacencyTester() { >>> ??? return (low, high) -> { >>> ????? // lambda body >>> ??? }; >>> ? } >>> >>> did not work, I got >>> >>> com/github/marschall/rangetree/key/U96.java:[51,12] incompatible types: >>> incompatible parameter types in lambda expression >>> >>> Converting it to an anonymous inner class worked >>> >>> ? public static AdjacencyTester adjacencyTester() { >>> ??? return new AdjacencyTester() { >>> ????? public boolean areAdjacent(U96? low, U96? high) { >>> ??????? // method body >>> ????? } >>> ??? }; >>> >>> ? } >>> >>> Using U96? as types for the lambda arguments did not compile >>> >>> ? public static AdjacencyTester adjacencyTester() { >>> ??? return (U96? low, U96? high) -> { >>> ????? // lambda body >>> ??? }; >>> ? } >>> >>> Compilation failure: >>> /src/main/java/com/github/marschall/rangetree/key/U96.java:[51,16] ')' >>> expected >>> src/main/java/com/github/marschall/rangetree/key/U96.java:[51,21] : >>> expected >>> src/main/java/com/github/marschall/rangetree/key/U96.java:[51,32] ';' >>> expected >>> >>> Second I have a simple Range class which is supposed to hold both >>> reference and inline types. That was easy to convert but integrating >>> into my existing interfaces failed. >>> >>> public inline class Range { >>> >>> ? private E low; >>> ? private E high; >>> >>> In my RangeMap interface I have #computeIfAbsent similar to the one from >>> Map. >>> >>> V computeIfAbsent(K key, Function, ? >>> extends V>> mappingFunction) >>> >>> src/main/java/com/github/marschall/rangetree/RangeMap.java:[52,59] >>> unexpected type >>> [ERROR]?? required: reference >>> [ERROR]?? found:??? com.github.marschall.rangetree.Range >>> >>> I tried to switch to >>> Range >>> >>> but that did not help. >>> >>> You can find the code and building instructions here [2] >>> >>> ?[1] https://github.com/marschall/range-tree >>> ?[2] https://github.com/marschall/range-tree/tree/valhalla >>> >>> Cheers >>> Philippe >> > > From srikanth.adayapalam at oracle.com Mon Aug 19 10:27:36 2019 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Mon, 19 Aug 2019 15:57:36 +0530 Subject: Struggling with Valhalla conversion of library In-Reply-To: <86cc5350-7942-4760-ce44-3aa116e88e19@gmx.net> References: <49d3aca7-ec3d-894b-695c-cbb3ce09709b@oracle.com> <86cc5350-7942-4760-ce44-3aa116e88e19@gmx.net> Message-ID: <4b6e2771-a2ec-8d63-30c8-8e00fba2c2bc@oracle.com> Thanks for the test case, I am looking into this one... (same problem as reported by another EA tester: Ben Evans) Srikanth. On 17/08/19 8:35 PM, Philippe Marschall wrote: > Hello Srikanth > > I was able to retest with the tip of the lworld branch. I can confirm > the lambda issue, the first issue, is gone. > > As for the second issue I was able to extract this minimal reproducer > > interface Sample, V> { > > ? void doesCompile(InlineType argument); > > ? void doesNotCompile(java.util.Map.Entry, ? > extends V> argument); > > } > > inline class InlineType { > > ? private E element; > > ? InlineType(E element) { > ??? this.element = element; > ? } > > } > > The method #doesCompile doe compile but the method #doesNotCompile does > not compile and instead I get the following error: > > error: unexpected type > ? void doesNotCompile(java.util.Map.Entry, ? > extends V> argument); > ??????????????????????????????????????????????????? ^ > ? required: reference > ? found:??? InlineType > ? where K is a type-variable: > ??? K extends Comparable declared in interface Sample > > > Cheers > Philippe > > On 14.08.19 12:51, Srikanth wrote: >> Hello Philippe, >> >> There has been a further defect fix >> https://bugs.openjdk.java.net/browse/JDK-8229700 that should also help >> you. If you are able to test the tip of valhalla repo lworld branch, >> that is great! >> >> If not, I am told this Friday there will a refresh of the EA bits. That >> should simplify testing for those that don't want to work with source >> forests. >> >> Could you in any case please see if you are able to extract test cases >> and send them inline in mail ? >> That would greatly speed up the turn around time for any remaining >> problems. >> >> Appreciate your testing and the defect reports! >> Srikanth >> >> On 14/08/19 2:39 PM, Srikanth wrote: >>> Hello Philippe, >>> >>> With the resolution of >>> https://bugs.openjdk.java.net/browse/JDK-8229537 via the push >>> http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d at least >>> the first of your >>> problems should have been fixed and the explicit lambda version viz: >>> >>> public static AdjacencyTester adjacencyTester() { >>> ??? return (U96? low, U96? high) -> { >>> ????? // lambda body >>> ??? }; >>> ? } >>> >>> should compile. >>> >>> Can you check with the lworld branch tip of valhalla ? >>> >>> I am happy to verify this fix and also investigate a fix for the other >>> problems you reported. >>> But it would help if I have test cases extracted and attached to mail >>> - is that possible ? >>> I am not familiar with github and having a bit of a bother getting >>> what I need from the >>> pointers. >>> >>> TIA >>> Srikanth >>> >>> On 05/08/19 3:14 AM, Philippe Marschall wrote: >>>> Hi >>>> >>>> As you published the LW2 prototype I thought I tried to convert one of >>>> my libraries [1] to Valhalla and see how it goes. Right now I'm >>>> struggling with generics. >>>> >>>> Some context about the library. The library implements a range tree >>>> that >>>> allows to map a range of keys to a single value. Eg. {[100,199] -> >>>> "1", >>>> [200,299] -> "2"}. The library should support both inline and >>>> reference >>>> types as keys and values. >>>> The potential for inline classes is limited as the tree nodes are >>>> mutable and recursive. There are however two good candidates, the >>>> range >>>> class and an unsigned 96bit integer class (called U96) that is >>>> provided >>>> for convenience. >>>> >>>> The unsigned 96bit integer class? was easy to convert. I had to change >>>> it to implements Comparable. I am not yet sure how I want to >>>> treat >>>> null / 0. >>>> But there are two cases where I struggled. >>>> >>>> First, I have an interface >>>> >>>> public interface AdjacencyTester { >>>> >>>> ? boolean areAdjacent(T low, T high); >>>> >>>> } >>>> >>>> I want to implement this for the unsigned 96bit integer class (called >>>> U96). Right know in Java 8 this is implemented as >>>> >>>> ? public static AdjacencyTester adjacencyTester() { >>>> ??? return (low, high) -> { >>>> ????? // lambda body >>>> ??? }; >>>> ? } >>>> >>>> Simply converting this to >>>> >>>> ? public static AdjacencyTester adjacencyTester() { >>>> ??? return (low, high) -> { >>>> ????? // lambda body >>>> ??? }; >>>> ? } >>>> >>>> did not work, I got >>>> >>>> com/github/marschall/rangetree/key/U96.java:[51,12] incompatible >>>> types: >>>> incompatible parameter types in lambda expression >>>> >>>> Converting it to an anonymous inner class worked >>>> >>>> ? public static AdjacencyTester adjacencyTester() { >>>> ??? return new AdjacencyTester() { >>>> ????? public boolean areAdjacent(U96? low, U96? high) { >>>> ??????? // method body >>>> ????? } >>>> ??? }; >>>> >>>> ? } >>>> >>>> Using U96? as types for the lambda arguments did not compile >>>> >>>> ? public static AdjacencyTester adjacencyTester() { >>>> ??? return (U96? low, U96? high) -> { >>>> ????? // lambda body >>>> ??? }; >>>> ? } >>>> >>>> Compilation failure: >>>> /src/main/java/com/github/marschall/rangetree/key/U96.java:[51,16] ')' >>>> expected >>>> src/main/java/com/github/marschall/rangetree/key/U96.java:[51,21] : >>>> expected >>>> src/main/java/com/github/marschall/rangetree/key/U96.java:[51,32] ';' >>>> expected >>>> >>>> Second I have a simple Range class which is supposed to hold both >>>> reference and inline types. That was easy to convert but integrating >>>> into my existing interfaces failed. >>>> >>>> public inline class Range { >>>> >>>> ? private E low; >>>> ? private E high; >>>> >>>> In my RangeMap interface I have #computeIfAbsent similar to the one >>>> from >>>> Map. >>>> >>>> V computeIfAbsent(K key, Function>>> K>, ? >>>> extends V>> mappingFunction) >>>> >>>> src/main/java/com/github/marschall/rangetree/RangeMap.java:[52,59] >>>> unexpected type >>>> [ERROR]?? required: reference >>>> [ERROR]?? found: com.github.marschall.rangetree.Range >>>> >>>> I tried to switch to >>>> Range >>>> >>>> but that did not help. >>>> >>>> You can find the code and building instructions here [2] >>>> >>>> ?[1] https://github.com/marschall/range-tree >>>> ?[2] https://github.com/marschall/range-tree/tree/valhalla >>>> >>>> Cheers >>>> Philippe >>> >> >> From srikanth.adayapalam at oracle.com Mon Aug 19 10:28:17 2019 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Mon, 19 Aug 2019 15:58:17 +0530 Subject: longHashCode? In-Reply-To: <15a9a4aa-180f-d59b-0276-334fcf7d6639@oracle.com> References: <15a9a4aa-180f-d59b-0276-334fcf7d6639@oracle.com> Message-ID: <6ba4b794-b221-1849-22c6-feaf79da2b7f@oracle.com> Thanks for your clarification on this, Mandy! Srikanth On 16/08/19 8:37 PM, Mandy Chung wrote: > > > On 8/16/19 6:16 AM, Ben Evans wrote: >> Hi, >> >> The web page https://wiki.openjdk.java.net/display/valhalla/LW2 makes >> reference to an auto-generated longHashCode() method, but the current >> tip does not appear to generate this method. > > Thanks for the note.? It's not in LW2. > >> Is the LW2 page out of date? >> > I updated the wiki page to reflect the current implementation. > > Mandy From brian.goetz at oracle.com Wed Aug 21 01:16:03 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 20 Aug 2019 21:16:03 -0400 Subject: Equality for values -- new analysis, same conclusion In-Reply-To: References: <90C17B62-5968-4352-825E-4F1EFAC81052@oracle.com> <131B9329-ECE7-46BE-909F-AC88421FF6CB@oracle.com> Message-ID: <945127A0-393C-4888-AC7A-5529D66423A6@oracle.com> > (although I'm not looking forward to an alternate name or a default > value for LocalDate). >> >> Assuming that this is what we will have to do, it would be a useful exploration to identify sensible idioms and guidelines for how to name these classes. Are these new ad-hoc names (Opt for the new Optional), or a mechanically derived scheme such as Optional.Inline? Finding a less objectionable scheme here can go a long way to mitigating the sadness of having to give these things new names. From rwestrel at redhat.com Wed Aug 21 15:35:44 2019 From: rwestrel at redhat.com (Roland Westrelin) Date: Wed, 21 Aug 2019 17:35:44 +0200 Subject: Result: New Valhalla Committer: Dmitry Samersoff Message-ID: <874l2asf8v.fsf@redhat.com> Voting for Dmitry Samersoff [1] is now closed. Yes: 9 Veto: 0 Abstain: 0 According to the Bylaws definition of Lazy Consensus, this is sufficient to approve the nomination. Roland. [1] https://mail.openjdk.java.net/pipermail/valhalla-dev/2019-July/006151.html From tobias.hartmann at oracle.com Thu Aug 22 10:59:28 2019 From: tobias.hartmann at oracle.com (tobias.hartmann at oracle.com) Date: Thu, 22 Aug 2019 10:59:28 +0000 Subject: hg: valhalla/valhalla: 8230023: [lworld] CompiledMethod::preserve_callee_argument_oops needs to keep signature symbol alive Message-ID: <201908221059.x7MAxT3M006906@aojmv0008.oracle.com> Changeset: 74a9bf9bbd76 Author: thartmann Date: 2019-08-22 12:59 +0200 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/74a9bf9bbd76 8230023: [lworld] CompiledMethod::preserve_callee_argument_oops needs to keep signature symbol alive ! src/hotspot/share/code/compiledMethod.cpp From dms at samersoff.net Thu Aug 22 13:48:13 2019 From: dms at samersoff.net (Dmitry Samersoff) Date: Thu, 22 Aug 2019 16:48:13 +0300 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> <646D1461-DC45-4DA5-92D6-1C4AE1B254CD@oracle.com> <35ba2593-eb7e-ecb2-7372-b8530514387d@samersoff.net> Message-ID: <69de5e9f-76c1-0e14-8425-7f7f896d4507@samersoff.net> Frederic, > But the ultimate decision to flatten a field or not is taken by the > container, because it is the one which decide how the field has been > declared, annotated, and which additional constraints the container > has to deal with. The ValueKlass of the field does not have this > context. Will the separate is_flattened function within a container, not ValueKlass, work for you? Nevertheless, counting the fix is huge and complicated, I'm OK to leave the code as it is. -Dmitry On 15.08.19 16:55, Frederic Parain wrote: > > > On 8/12/19 8:14 AM, Dmitry Samersoff wrote: >> Hello Frederic, >> >> The code looks good to me. >> >> >> fieldLayoutBuilder.cpp:35 >> >> this version of constructor missed size > 0 assert, I'm not sure it's >> really important but it's better to keep it uniform. > > I'll add it. > >> >>>> 561, 641 >>>> >>>> Does it duplicate similar code within ValueKlass, if not - could we >>>> move it there? >> >>> I?d like to keep the two codes separated. >>> They are similar today, but we could realize that decisions to flatten >>> or not might not the the same when the container is an identity class >>> or an inline class. >> >> >> Sorry to disagree with you here. I would prefer to have all >> "is_flattened" logic in a single place. >> >> I.e., if in the future this logic will differ from the default one, it >> is better to keep it inside ValueKlass with a clear path choice, >> like is_flattened(bool class_is_inline) > > But the ultimate decision to flatten a field or not is taken by the > container, because it is the one which decide how the field has been > declared, annotated, and which additional constraints the container > has to deal with. The ValueKlass of the field does not have this > context. > Today, having a ValueKlass with size < ValueFieldMaxFlatSize is not > a guarantee that field will be flattened. If the field is static, > it won't be flattened. > Soon, if the field has been declared atomic, the decision to flatten > won't depend on ValueFieldMaxFlatSize, but on the size of atomic > operations supported by the platform. > In the future, the number of parameters to consider could continue > to increase, with consideration of alignment constraints for instance. > All these information are in the container, so the logic to flatten > or not must be in the computation of the layout of the container. > >> Otherwise, it becomes difficult to understand what the command line >> options (e.g. ValueFieldMaxFlatSize == 0) affect. > > As explained above, ValueFieldMaxFlatSize is only one of the parameters > considered when deciding to flatten or not. > > Regards, > > Fred > > >> On 07.08.19 17:27, Dmitry Samersoff wrote: >>> Hello Frederic, >>> >>>> So, I?d like to keep the old code as a backup for a little while, >>>> then remove it. >>>> If it causes to much burden for you, let me know. >>> >>> It doesn't case any burden for me, so feel free to keep this flag. >>> >>>> I?ve slightly refactored the code, and added a comment to simplify >>>> this code ever more once the old layout code is removed. >>>> >>>> I?ll include changes from your second e-mail before publishing a >>>> new webrev. >>> >>> Ok. >>> >>> This large and nice work really appreciated. >>> >>> -Dmitry >>> >>> On 06.08.19 22:47, Frederic Parain wrote: >>>> Hi Dmitry, >>>> >>>> Thank you for reviewing this huge patch! >>>> >>>>> On Aug 6, 2019, at 09:52, Dmitry Samersoff wrote: >>>>> >>>>> Hello Frederic, >>>>> >>>>> General comment: >>>>> >>>>> ?? I'm not sure we should have and maintain UseNewLayout flag.? >>>>> What is >>>>> the reason to keep old layout? Is there any code that rely on it? >>>> >>>> The hope is that the old code can be completely removed. >>>> However, this is a huge change, so it is kept as a fallback for now. >>>> >>>> Coleen has asked that the new layout code would be ported to the >>>> main line >>>> before the Valhalla integration. So I?ve also a port for JDK14 in >>>> progress >>>> (with more features, the ones not important for project Valhalla), >>>> so I?m >>>> trying to stabilize both patches at the same time. >>>> But field layout has not been changed for so long, that any change >>>> can have >>>> unexpected consequences. Some codes have very strong assumptions >>>> about layout >>>> that are in fact just accidental properties of the old code. >>>> Enabling some >>>> optimizations just breaks these codes, or reveal some bugs (I found >>>> a memory >>>> corruption in the StackWalking code, unnoticed with old layouts, >>>> breaking the >>>> StalkWaking code if the layout is slightly different). >>>> >>>> So, I?d like to keep the old code as a backup for a little while, >>>> then remove it. >>>> If it causes to much burden for you, let me know. >>>> >>>>> classFileParser.cpp: >>>>> >>>>> 5975: >>>>> ValueKlass::cast(ik)->set_first_field_offset(_first_field_offset); >>>>> >>>>> Where the value of _first_field_offset is initialized? >>>> >>>> This value, which exists only for inline classes, is initialized in >>>> FieldLayoutBuilder::compute_inline_class_layout(TRAPS): >>>> >>>> ?? 738?? _first_field_offset = _layout->start()->offset(); >>>> >>>>> >>>>> heapInspection.cpp: >>>>> >>>>> 736 and below: Should we add const here? >>>> >>>> Done >>>> >>>>> >>>>> 741?? AccessFlags access_flags() { return _access_flags; } >>>>> >>>>> Could we use >>>>> ?? const AccessFlags& access_flags() { return _access_flags; } >>>>> here? >>>> >>>> Done >>>> >>>>> 749 Please make it const char * and remove further casts >>>> >>>> Done (Sorry for the ugly code). >>>> >>>>> >>>>> 766, 775 and few locations below. >>>>> >>>>> ???????? You may consider to create a proxy inside FieldDesc >>>>> ???????? and replace fd.access_flags().is_static() to fd.is_static() >>>>> ???????? for better readability. >>>>> >>>> >>>> line 766, fd is a FieldStream, not a FieldDesc, I?m not sure it worth >>>> adding the proxy. >>>> But a proxy has been added to FieldDesc for is_flattenable(). >>>> >>>> >>>>> instanceKlass.cpp >>>>> >>>>> 1130 set_value_field_klass called before the check at l.1132 >>>>> >>>>> ???? Is it correct? Should we turn the check to assert? >>>> >>>> The check is required to deal with separate compilation issues. >>>> If class C has a field of type V, V is an inline class when C >>>> is compiled, but then V is changed to be a regular class and >>>> is recompiled, the JVM has to detect the mismatch and must >>>> reject the class with an ICCE. >>>> >>>> Calling set_value_field_klass() before the check is not really >>>> an issue, if the field?s class is not an inline class, the >>>> whole class will be rejected and the stored value will never >>>> be used. >>>> >>>> The call to set_value_field_klass() could be moved after the >>>> check, but it would require to test >>>> this->get_value_field_klass_or_null(fs.index()) >>>> one more time (because set_value_field_klass() must be call twice). >>>> >>>>> >>>>> valueKlass.cpp >>>>> >>>>> 52 please, add else here to improve readability. >>>>> >>>>> Could we move it to the header? Non inlined first_field_offset that >>>>> just >>>>> a call to inlined get_first_field_offset looks a bit odd to me. >>>> >>>> I?ve slightly refactored the code, and added a comment to simplify >>>> this code ever more once the old layout code is removed. >>>> >>>> I?ll include changes from your second e-mail before publishing a >>>> new webrev. >>>> >>>> Thank you, >>>> >>>> Fred >>>> >>>> >>>>> >>>>> >>>>> Regards, >>>>> >>>>> -Dmitry\S >>>>> >>>>> >>>>> >>>>> On 19.07.19 18:26, Frederic Parain wrote: >>>>>> Greetings, >>>>>> >>>>>> This is the initial request for review for a new code to layout >>>>>> fields. >>>>>> The current code to compute field layouts is especially ugly and >>>>>> not fitted to efficiently flatten inline classes. >>>>>> >>>>>> This changeset is an almost complete overhaul of the field layout >>>>>> code, >>>>>> with a new framework to compute layouts and two different allocation >>>>>> strategies (one for identity classes and one for inline classes). >>>>>> >>>>>> CR: https://bugs.openjdk.java.net/browse/JDK-8228441 >>>>>> Webrev: http://cr.openjdk.java.net/~fparain/layout/webrev.00/ >>>>>> >>>>>> This changeset also includes some options and DCMD to ease inspection >>>>>> of layouts, especially when flattenable fields are involved. >>>>>> >>>>>> The changeset doesn?t remove the old layout code, meaning that either >>>>>> the old code or the new code can be used (controlled by VM flag). >>>>>> >>>>>> This code passed tiers 1 to 3 on Valhalla supported platforms. >>>>>> Some failures have been identified in higher tiers with some >>>>>> @Contended >>>>>> tests, but they are due to test bugs (tests making relying on wrong >>>>>> assumptions about field layouts). >>>>>> >>>>>> The code contains a lot of comments about the new framework and the >>>>>> different allocation strategies. Feel free to complain if comments >>>>>> are not clear enough or if some code need more comments. >>>>>> >>>>>> Regarding the huge size of this changeset, and people being in summer >>>>>> vacation, I?m not planning to push this code in the short term. >>>>>> >>>>>> Thank you, >>>>>> >>>>>> Fred >>>>>> >>>> From frederic.parain at oracle.com Thu Aug 22 14:14:26 2019 From: frederic.parain at oracle.com (Frederic Parain) Date: Thu, 22 Aug 2019 10:14:26 -0400 Subject: RFR(XL): JDK-8228441 Field layout requires complete overhaul to efficiently support inline classes In-Reply-To: <69de5e9f-76c1-0e14-8425-7f7f896d4507@samersoff.net> References: <9F44BBA3-1415-40F6-BB32-0F67C6DEB4FB@oracle.com> <00193822-6bc7-ff11-1406-3a6283affab8@samersoff.net> <646D1461-DC45-4DA5-92D6-1C4AE1B254CD@oracle.com> <35ba2593-eb7e-ecb2-7372-b8530514387d@samersoff.net> <69de5e9f-76c1-0e14-8425-7f7f896d4507@samersoff.net> Message-ID: <52A63870-E033-423C-A96A-E328493BDB7F@oracle.com> > On Aug 22, 2019, at 09:48, Dmitry Samersoff wrote: > > Frederic, > >> But the ultimate decision to flatten a field or not is taken by the >> container, because it is the one which decide how the field has been >> declared, annotated, and which additional constraints the container >> has to deal with. The ValueKlass of the field does not have this >> context. > > Will the separate is_flattened function within a container, not > ValueKlass, work for you? The current approach is to encapsulate all the field layout logic inside the FieldLayoutBuilder class, so there?s a single place to look at for all layout decisions, and this logic is executed in the context of the container. I?d like to keep it this way unless we find a very good rational to delegate part of this logic to another VM component. > > Nevertheless, counting the fix is huge and complicated, I'm OK to leave > the code as it is. Thank you for being flexible and for the review. As stated above, we might reconsider the choice of the is_flattened() method as the project evolves. Best Regards, Fred > > > On 15.08.19 16:55, Frederic Parain wrote: >> >> >> On 8/12/19 8:14 AM, Dmitry Samersoff wrote: >>> Hello Frederic, >>> >>> The code looks good to me. >>> >>> >>> fieldLayoutBuilder.cpp:35 >>> >>> this version of constructor missed size > 0 assert, I'm not sure it's >>> really important but it's better to keep it uniform. >> >> I'll add it. >> >>> >>>>> 561, 641 >>>>> >>>>> Does it duplicate similar code within ValueKlass, if not - could we >>>>> move it there? >>> >>>> I?d like to keep the two codes separated. >>>> They are similar today, but we could realize that decisions to flatten >>>> or not might not the the same when the container is an identity class >>>> or an inline class. >>> >>> >>> Sorry to disagree with you here. I would prefer to have all >>> "is_flattened" logic in a single place. >>> >>> I.e., if in the future this logic will differ from the default one, it >>> is better to keep it inside ValueKlass with a clear path choice, >>> like is_flattened(bool class_is_inline) >> >> But the ultimate decision to flatten a field or not is taken by the >> container, because it is the one which decide how the field has been >> declared, annotated, and which additional constraints the container >> has to deal with. The ValueKlass of the field does not have this >> context. >> Today, having a ValueKlass with size < ValueFieldMaxFlatSize is not >> a guarantee that field will be flattened. If the field is static, >> it won't be flattened. >> Soon, if the field has been declared atomic, the decision to flatten >> won't depend on ValueFieldMaxFlatSize, but on the size of atomic >> operations supported by the platform. >> In the future, the number of parameters to consider could continue >> to increase, with consideration of alignment constraints for instance. >> All these information are in the container, so the logic to flatten >> or not must be in the computation of the layout of the container. >> >>> Otherwise, it becomes difficult to understand what the command line >>> options (e.g. ValueFieldMaxFlatSize == 0) affect. >> >> As explained above, ValueFieldMaxFlatSize is only one of the parameters >> considered when deciding to flatten or not. >> >> Regards, >> >> Fred >> >> >>> On 07.08.19 17:27, Dmitry Samersoff wrote: >>>> Hello Frederic, >>>> >>>>> So, I?d like to keep the old code as a backup for a little while, >>>>> then remove it. >>>>> If it causes to much burden for you, let me know. >>>> >>>> It doesn't case any burden for me, so feel free to keep this flag. >>>> >>>>> I?ve slightly refactored the code, and added a comment to simplify >>>>> this code ever more once the old layout code is removed. >>>>> >>>>> I?ll include changes from your second e-mail before publishing a >>>>> new webrev. >>>> >>>> Ok. >>>> >>>> This large and nice work really appreciated. >>>> >>>> -Dmitry >>>> >>>> On 06.08.19 22:47, Frederic Parain wrote: >>>>> Hi Dmitry, >>>>> >>>>> Thank you for reviewing this huge patch! >>>>> >>>>>> On Aug 6, 2019, at 09:52, Dmitry Samersoff wrote: >>>>>> >>>>>> Hello Frederic, >>>>>> >>>>>> General comment: >>>>>> >>>>>> I'm not sure we should have and maintain UseNewLayout flag. >>>>>> What is >>>>>> the reason to keep old layout? Is there any code that rely on it? >>>>> >>>>> The hope is that the old code can be completely removed. >>>>> However, this is a huge change, so it is kept as a fallback for now. >>>>> >>>>> Coleen has asked that the new layout code would be ported to the >>>>> main line >>>>> before the Valhalla integration. So I?ve also a port for JDK14 in >>>>> progress >>>>> (with more features, the ones not important for project Valhalla), >>>>> so I?m >>>>> trying to stabilize both patches at the same time. >>>>> But field layout has not been changed for so long, that any change >>>>> can have >>>>> unexpected consequences. Some codes have very strong assumptions >>>>> about layout >>>>> that are in fact just accidental properties of the old code. >>>>> Enabling some >>>>> optimizations just breaks these codes, or reveal some bugs (I found >>>>> a memory >>>>> corruption in the StackWalking code, unnoticed with old layouts, >>>>> breaking the >>>>> StalkWaking code if the layout is slightly different). >>>>> >>>>> So, I?d like to keep the old code as a backup for a little while, >>>>> then remove it. >>>>> If it causes to much burden for you, let me know. >>>>> >>>>>> classFileParser.cpp: >>>>>> >>>>>> 5975: >>>>>> ValueKlass::cast(ik)->set_first_field_offset(_first_field_offset); >>>>>> >>>>>> Where the value of _first_field_offset is initialized? >>>>> >>>>> This value, which exists only for inline classes, is initialized in >>>>> FieldLayoutBuilder::compute_inline_class_layout(TRAPS): >>>>> >>>>> 738 _first_field_offset = _layout->start()->offset(); >>>>> >>>>>> >>>>>> heapInspection.cpp: >>>>>> >>>>>> 736 and below: Should we add const here? >>>>> >>>>> Done >>>>> >>>>>> >>>>>> 741 AccessFlags access_flags() { return _access_flags; } >>>>>> >>>>>> Could we use >>>>>> const AccessFlags& access_flags() { return _access_flags; } >>>>>> here? >>>>> >>>>> Done >>>>> >>>>>> 749 Please make it const char * and remove further casts >>>>> >>>>> Done (Sorry for the ugly code). >>>>> >>>>>> >>>>>> 766, 775 and few locations below. >>>>>> >>>>>> You may consider to create a proxy inside FieldDesc >>>>>> and replace fd.access_flags().is_static() to fd.is_static() >>>>>> for better readability. >>>>>> >>>>> >>>>> line 766, fd is a FieldStream, not a FieldDesc, I?m not sure it worth >>>>> adding the proxy. >>>>> But a proxy has been added to FieldDesc for is_flattenable(). >>>>> >>>>> >>>>>> instanceKlass.cpp >>>>>> >>>>>> 1130 set_value_field_klass called before the check at l.1132 >>>>>> >>>>>> Is it correct? Should we turn the check to assert? >>>>> >>>>> The check is required to deal with separate compilation issues. >>>>> If class C has a field of type V, V is an inline class when C >>>>> is compiled, but then V is changed to be a regular class and >>>>> is recompiled, the JVM has to detect the mismatch and must >>>>> reject the class with an ICCE. >>>>> >>>>> Calling set_value_field_klass() before the check is not really >>>>> an issue, if the field?s class is not an inline class, the >>>>> whole class will be rejected and the stored value will never >>>>> be used. >>>>> >>>>> The call to set_value_field_klass() could be moved after the >>>>> check, but it would require to test >>>>> this->get_value_field_klass_or_null(fs.index()) >>>>> one more time (because set_value_field_klass() must be call twice). >>>>> >>>>>> >>>>>> valueKlass.cpp >>>>>> >>>>>> 52 please, add else here to improve readability. >>>>>> >>>>>> Could we move it to the header? Non inlined first_field_offset that >>>>>> just >>>>>> a call to inlined get_first_field_offset looks a bit odd to me. >>>>> >>>>> I?ve slightly refactored the code, and added a comment to simplify >>>>> this code ever more once the old layout code is removed. >>>>> >>>>> I?ll include changes from your second e-mail before publishing a >>>>> new webrev. >>>>> >>>>> Thank you, >>>>> >>>>> Fred >>>>> >>>>> >>>>>> >>>>>> >>>>>> Regards, >>>>>> >>>>>> -Dmitry\S >>>>>> >>>>>> >>>>>> >>>>>> On 19.07.19 18:26, Frederic Parain wrote: >>>>>>> Greetings, >>>>>>> >>>>>>> This is the initial request for review for a new code to layout >>>>>>> fields. >>>>>>> The current code to compute field layouts is especially ugly and >>>>>>> not fitted to efficiently flatten inline classes. >>>>>>> >>>>>>> This changeset is an almost complete overhaul of the field layout >>>>>>> code, >>>>>>> with a new framework to compute layouts and two different allocation >>>>>>> strategies (one for identity classes and one for inline classes). >>>>>>> >>>>>>> CR: https://bugs.openjdk.java.net/browse/JDK-8228441 >>>>>>> Webrev: http://cr.openjdk.java.net/~fparain/layout/webrev.00/ >>>>>>> >>>>>>> This changeset also includes some options and DCMD to ease inspection >>>>>>> of layouts, especially when flattenable fields are involved. >>>>>>> >>>>>>> The changeset doesn?t remove the old layout code, meaning that either >>>>>>> the old code or the new code can be used (controlled by VM flag). >>>>>>> >>>>>>> This code passed tiers 1 to 3 on Valhalla supported platforms. >>>>>>> Some failures have been identified in higher tiers with some >>>>>>> @Contended >>>>>>> tests, but they are due to test bugs (tests making relying on wrong >>>>>>> assumptions about field layouts). >>>>>>> >>>>>>> The code contains a lot of comments about the new framework and the >>>>>>> different allocation strategies. Feel free to complain if comments >>>>>>> are not clear enough or if some code need more comments. >>>>>>> >>>>>>> Regarding the huge size of this changeset, and people being in summer >>>>>>> vacation, I?m not planning to push this code in the short term. >>>>>>> >>>>>>> Thank you, >>>>>>> >>>>>>> Fred >>>>>>> >>>>> From frederic.parain at oracle.com Thu Aug 22 16:57:59 2019 From: frederic.parain at oracle.com (frederic.parain at oracle.com) Date: Thu, 22 Aug 2019 16:57:59 +0000 Subject: hg: valhalla/valhalla: 8228441: Field layout requires complete overhaul to efficiently support inline classes Message-ID: <201908221658.x7MGw0B0023402@aojmv0008.oracle.com> Changeset: d68ab9ea03b5 Author: fparain Date: 2019-08-22 12:56 -0400 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/d68ab9ea03b5 8228441: Field layout requires complete overhaul to efficiently support inline classes Reviewed-by: dsamersoff ! src/hotspot/share/classfile/classFileParser.cpp ! src/hotspot/share/classfile/classFileParser.hpp + src/hotspot/share/classfile/fieldLayoutBuilder.cpp + src/hotspot/share/classfile/fieldLayoutBuilder.hpp ! src/hotspot/share/memory/heapInspection.cpp ! src/hotspot/share/memory/heapInspection.hpp ! src/hotspot/share/oops/instanceKlass.hpp ! src/hotspot/share/oops/instanceOop.hpp ! src/hotspot/share/oops/valueKlass.cpp ! src/hotspot/share/oops/valueKlass.hpp ! src/hotspot/share/runtime/globals.hpp ! src/hotspot/share/runtime/vmOperations.cpp ! src/hotspot/share/runtime/vmOperations.hpp ! src/hotspot/share/services/diagnosticCommand.cpp ! src/hotspot/share/services/diagnosticCommand.hpp From sergey.kuksenko at oracle.com Fri Aug 23 00:12:03 2019 From: sergey.kuksenko at oracle.com (Sergey Kuksenko) Date: Thu, 22 Aug 2019 17:12:03 -0700 Subject: TWIMC: Inline types sorting study Message-ID: <03e05306-dfda-d144-5e16-02154edbff22@oracle.com> Hi All, Here you may read some result of how right now inline types work with sorting: http://cr.openjdk.java.net/~skuksenko/valhalla/reports/sort/sort.html Best regards, Sergey Kuksenko. From srikanth.adayapalam at oracle.com Sun Aug 25 10:17:32 2019 From: srikanth.adayapalam at oracle.com (srikanth.adayapalam at oracle.com) Date: Sun, 25 Aug 2019 10:17:32 +0000 Subject: hg: valhalla/valhalla: 8230121: [lworld] Javac does not properly parse nullable projection types of parameterized inline types Message-ID: <201908251017.x7PAHXAo012916@aojmv0008.oracle.com> Changeset: e9393b1577db Author: sadayapalam Date: 2019-08-25 15:47 +0530 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/e9393b1577db 8230121: [lworld] Javac does not properly parse nullable projection types of parameterized inline types ! src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java + test/langtools/tools/javac/valhalla/lworld-values/GenericsAndValues4.java + test/langtools/tools/javac/valhalla/lworld-values/GenericsAndValues5.java From srikanth.adayapalam at oracle.com Sun Aug 25 10:24:47 2019 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Sun, 25 Aug 2019 15:54:47 +0530 Subject: Can't make simple Streams over indirect projects work In-Reply-To: <940f069c-c082-7179-954b-7dc5c57d9c5c@oracle.com> References: <030e9ee6-2c77-b643-4fe6-c08fdb8e85dc@oracle.com> <940f069c-c082-7179-954b-7dc5c57d9c5c@oracle.com> Message-ID: <001973bf-485e-4af8-766c-9db741230cd7@oracle.com> Thanks for weighing on this Brian! I have pushed a change set http://hg.openjdk.java.net/valhalla/valhalla/rev/e9393b1577db on behalf of https://bugs.openjdk.java.net/browse/JDK-8230121 that addresses this problem. Ben, I am able to compile the generic version of the Optional inline type and run the test case that gave you grief earlier. Please check out valhalla repository lworld branch tip. Note: As Brian Indicated the accepted syntax for the nullable projection type of parameterized types is of the form GenericInlineType? as opposed to GenericInlineType? (That said, Brian, internally I had to model that projection type as GenericInlineType?) Ben, thanks for continued testing, I am away all week this week on a training program, but will try to address any new problems reported on a best case effort basis. Thanks! Srikanth On 14/08/19 11:00 PM, Brian Goetz wrote: > Ben; > > We appreciate your exploring these corners.? But, just by way of > setting expectations, there's nothing "simple" about this example; > you're hitting on all the areas that are at the periphery of the L2 > goals.? So while we would of course like for these things to work, > we're not surprised there are pitfalls and interactions.? (I say this > because I want to avoid having the "simple" framing derail the > discussion.) > >> all my attempts to use it, eg. via code like this: >> >> List> opts = new ArrayList<>(); > > The interaction of generic instantiation and the nullable projection > type are definitely in the corners right now.? This would be spelled > `Optional?`, though; the `?` applies to the final (inline) > type, not to the base type.? (You would spell the raw type > `Optional?`.)? But, I suspect in the current prototype, that syntax > will not work either. > > But yes, it should be possible to project the type `Optional` > to a nullable projection. > > From srikanth.adayapalam at oracle.com Sun Aug 25 10:31:07 2019 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Sun, 25 Aug 2019 16:01:07 +0530 Subject: Struggling with Valhalla conversion of library In-Reply-To: <86cc5350-7942-4760-ce44-3aa116e88e19@gmx.net> References: <49d3aca7-ec3d-894b-695c-cbb3ce09709b@oracle.com> <86cc5350-7942-4760-ce44-3aa116e88e19@gmx.net> Message-ID: <393d573d-4c8b-65b8-0803-b5f58dd49a87@oracle.com> Hello Philippe, I have pushed a change set http://hg.openjdk.java.net/valhalla/valhalla/rev/e9393b1577db, on behalf of https://bugs.openjdk.java.net/browse/JDK-8230121 that addresses this problem. Note however that the syntax to be used is: void doesNotCompile(java.util.Map.Entry*?*, ? extends V> argument); Inline types cannot be type arguments as of LW2, only their nullable projection types can be. Hence the ? I do wish to echo Brian's message in another thread: "The interaction of generic instantiation and the nullable projection type are definitely in the corners right now."? and "So while we would of course like for these things to work, we're not surprised there are pitfalls and interactions" Thanks for continued testing. I am away all of the coming week on a training, but I'll try to provide fixes as soon as possible. Thanks! Srikanth On 17/08/19 8:35 PM, Philippe Marschall wrote: > Hello Srikanth > > I was able to retest with the tip of the lworld branch. I can confirm > the lambda issue, the first issue, is gone. > > As for the second issue I was able to extract this minimal reproducer > > interface Sample, V> { > > ? void doesCompile(InlineType argument); > > ? void doesNotCompile(java.util.Map.Entry, ? > extends V> argument); > > } > > inline class InlineType { > > ? private E element; > > ? InlineType(E element) { > ??? this.element = element; > ? } > > } > > The method #doesCompile doe compile but the method #doesNotCompile does > not compile and instead I get the following error: > > error: unexpected type > ? void doesNotCompile(java.util.Map.Entry, ? > extends V> argument); > ??????????????????????????????????????????????????? ^ > ? required: reference > ? found:??? InlineType > ? where K is a type-variable: > ??? K extends Comparable declared in interface Sample > > > Cheers > Philippe > > On 14.08.19 12:51, Srikanth wrote: >> Hello Philippe, >> >> There has been a further defect fix >> https://bugs.openjdk.java.net/browse/JDK-8229700 that should also help >> you. If you are able to test the tip of valhalla repo lworld branch, >> that is great! >> >> If not, I am told this Friday there will a refresh of the EA bits. That >> should simplify testing for those that don't want to work with source >> forests. >> >> Could you in any case please see if you are able to extract test cases >> and send them inline in mail ? >> That would greatly speed up the turn around time for any remaining >> problems. >> >> Appreciate your testing and the defect reports! >> Srikanth >> >> On 14/08/19 2:39 PM, Srikanth wrote: >>> Hello Philippe, >>> >>> With the resolution of >>> https://bugs.openjdk.java.net/browse/JDK-8229537 via the push >>> http://hg.openjdk.java.net/valhalla/valhalla/rev/7ec951ef532d at least >>> the first of your >>> problems should have been fixed and the explicit lambda version viz: >>> >>> public static AdjacencyTester adjacencyTester() { >>> ??? return (U96? low, U96? high) -> { >>> ????? // lambda body >>> ??? }; >>> ? } >>> >>> should compile. >>> >>> Can you check with the lworld branch tip of valhalla ? >>> >>> I am happy to verify this fix and also investigate a fix for the other >>> problems you reported. >>> But it would help if I have test cases extracted and attached to mail >>> - is that possible ? >>> I am not familiar with github and having a bit of a bother getting >>> what I need from the >>> pointers. >>> >>> TIA >>> Srikanth >>> >>> On 05/08/19 3:14 AM, Philippe Marschall wrote: >>>> Hi >>>> >>>> As you published the LW2 prototype I thought I tried to convert one of >>>> my libraries [1] to Valhalla and see how it goes. Right now I'm >>>> struggling with generics. >>>> >>>> Some context about the library. The library implements a range tree >>>> that >>>> allows to map a range of keys to a single value. Eg. {[100,199] -> >>>> "1", >>>> [200,299] -> "2"}. The library should support both inline and >>>> reference >>>> types as keys and values. >>>> The potential for inline classes is limited as the tree nodes are >>>> mutable and recursive. There are however two good candidates, the >>>> range >>>> class and an unsigned 96bit integer class (called U96) that is >>>> provided >>>> for convenience. >>>> >>>> The unsigned 96bit integer class? was easy to convert. I had to change >>>> it to implements Comparable. I am not yet sure how I want to >>>> treat >>>> null / 0. >>>> But there are two cases where I struggled. >>>> >>>> First, I have an interface >>>> >>>> public interface AdjacencyTester { >>>> >>>> ? boolean areAdjacent(T low, T high); >>>> >>>> } >>>> >>>> I want to implement this for the unsigned 96bit integer class (called >>>> U96). Right know in Java 8 this is implemented as >>>> >>>> ? public static AdjacencyTester adjacencyTester() { >>>> ??? return (low, high) -> { >>>> ????? // lambda body >>>> ??? }; >>>> ? } >>>> >>>> Simply converting this to >>>> >>>> ? public static AdjacencyTester adjacencyTester() { >>>> ??? return (low, high) -> { >>>> ????? // lambda body >>>> ??? }; >>>> ? } >>>> >>>> did not work, I got >>>> >>>> com/github/marschall/rangetree/key/U96.java:[51,12] incompatible >>>> types: >>>> incompatible parameter types in lambda expression >>>> >>>> Converting it to an anonymous inner class worked >>>> >>>> ? public static AdjacencyTester adjacencyTester() { >>>> ??? return new AdjacencyTester() { >>>> ????? public boolean areAdjacent(U96? low, U96? high) { >>>> ??????? // method body >>>> ????? } >>>> ??? }; >>>> >>>> ? } >>>> >>>> Using U96? as types for the lambda arguments did not compile >>>> >>>> ? public static AdjacencyTester adjacencyTester() { >>>> ??? return (U96? low, U96? high) -> { >>>> ????? // lambda body >>>> ??? }; >>>> ? } >>>> >>>> Compilation failure: >>>> /src/main/java/com/github/marschall/rangetree/key/U96.java:[51,16] ')' >>>> expected >>>> src/main/java/com/github/marschall/rangetree/key/U96.java:[51,21] : >>>> expected >>>> src/main/java/com/github/marschall/rangetree/key/U96.java:[51,32] ';' >>>> expected >>>> >>>> Second I have a simple Range class which is supposed to hold both >>>> reference and inline types. That was easy to convert but integrating >>>> into my existing interfaces failed. >>>> >>>> public inline class Range { >>>> >>>> ? private E low; >>>> ? private E high; >>>> >>>> In my RangeMap interface I have #computeIfAbsent similar to the one >>>> from >>>> Map. >>>> >>>> V computeIfAbsent(K key, Function>>> K>, ? >>>> extends V>> mappingFunction) >>>> >>>> src/main/java/com/github/marschall/rangetree/RangeMap.java:[52,59] >>>> unexpected type >>>> [ERROR]?? required: reference >>>> [ERROR]?? found: com.github.marschall.rangetree.Range >>>> >>>> I tried to switch to >>>> Range >>>> >>>> but that did not help. >>>> >>>> You can find the code and building instructions here [2] >>>> >>>> ?[1] https://github.com/marschall/range-tree >>>> ?[2] https://github.com/marschall/range-tree/tree/valhalla >>>> >>>> Cheers >>>> Philippe >>> >> >> From scolebourne at joda.org Thu Aug 29 12:13:20 2019 From: scolebourne at joda.org (Stephen Colebourne) Date: Thu, 29 Aug 2019 13:13:20 +0100 Subject: Equality for values -- new analysis, same conclusion In-Reply-To: <945127A0-393C-4888-AC7A-5529D66423A6@oracle.com> References: <90C17B62-5968-4352-825E-4F1EFAC81052@oracle.com> <131B9329-ECE7-46BE-909F-AC88421FF6CB@oracle.com> <945127A0-393C-4888-AC7A-5529D66423A6@oracle.com> Message-ID: On Wed, 21 Aug 2019, 02:16 Brian Goetz, wrote: > > > (although I'm not looking forward to an alternate name or a default > > value for LocalDate). > > Assuming that this is what we will have to do, it would be a useful exploration to identify sensible idioms and guidelines for how to name these classes. Are these new ad-hoc names (Opt for the new Optional), or a mechanically derived scheme such as Optional.Inline? Finding a less objectionable scheme here can go a long way to mitigating the sadness of having to give these things new names. Braindump thoughts went as follows: LocalDate.Inline LocalDate.Val VLocalDate LocalDateV LDate LocDate Digging beyond the braindump, there are various dimensions here to consider which led me to a different answer. These include related things being discussed, notably null and ==. Do migrated inline classes have different names to highlight the migration? Highlighting migration seems like a bad idea in the long term. Specifically, in the long term it seems like the best name should go to the inline class, not the box. This seems to rule out `LocalDate.Inline` as surely we don't want to refer to `Ratio.Inline` or `Long128.Inline` everywhere. Should inline class names highlight their behaviour wrt null and ==? I think this should be seriously considered. While I'm willing to accept the recent proposals to have two names for inline classes (box and inline), I'm a lot less comfortable with the proposals around null and == and their impact on the user model. >From a user model perspective, it is pretty clear in Java today when to use == and when not to. If it is a primitive then you should use ==, otherwise you should not (unless you are an expert or doing something odd). Normal day-to-day coding essentially never needs to use == on reference types, and doing so is almost always a bug. Users don't have to think too much (curse NaN), but there are only 8 primitive types and everyone knows what they are. Again, from a user model perspective, it is clear what can be null and what can't - primitives vs reference. Again, users don't have to think too much with only 8 primitive types. Now, considering a psuedo-code example of my last email's point: inline class Ratio { long top long bottom } inline class NamedRatio { String name long top long bottom } The rules for == mean that : Ratio.of(1, 3) == Ratio.of(1, 3) but that: Ratio.of("One third", 1, 3) != Ratio.of( "One third", 1, 3) in many cases (depends if the string is inlined or not). For a naive user, this behaviour of == is deeply unhelpful and apparently semi-random. A user has to know that it is an inline class and that it contains a type that can't be == checked safely. Some inline classes can be compared using == but other inline classes can't be. And since this language feature will be used for many new primitive types like an unsigned integer or 128-bot long, it seems completely unreasonable and unrealistic to ask users not to use == for these types. Since exposing more of == as currently proposed is IMO deeply confusing. Remi and I have proposed deprecating ==, but this email essentially proposes an alternative approach - naming. What if inline classes are divided between "pure" and "impure" (better names needed). A "pure" inline class has (1) a sensible default value, not null/exception (2) a correct == implementation that always works as would be expected of a primitive type (3) no reference type fields. An "impure" inline class may contain reference type fields, may have no meaningful default value and should never be compared using == in normal code. Then we say that "pure" inline classes are named using lowerCamelCase, and "impure" inline classes using UpperCamelCase. Thus,`localDate` is the inline class for the `LocalDate` box (assuming agreement on a suitable default value). In the example above, `ratio` would be the inline class and `Ratio` the box (assuming agreement on a suitable default value). But it would be `NamedRatio`, not `namedRatio` because it contains a reference type. The overall user model is simpler I think. All types that are lowerCamelCase behave like primitives wrt == and null, and all types that are UpperCamelCase behave like reference types wrt == and null. What about the meaning of null and the box name for "impure" inline classes? Well, perhaps there is only one named type for "impure" inline classes. ie. it is effectively both the box and the inline form. I'm thinking perhaps that the JVM could treat such "impure" inline classes as always being boxes, but potentially inlining them where possible. ie. if you write an "impure" inline class as opposed to a "pure" one, you give up the ability to remove null from variables of that type. I can also see it being possible/desirable for the JVM to ensure that "pure" inline classes cannot contain reference types (providing a `ref` inline class as a backdoor to make it obvious that the content is being compared by identity). Summary: It seems possible to separate the user-defined primitives use case from the faster-objects one using naming - lowerCamelCase vs UpperCamelCase. This seems to make the user model around ==, null and migrated types clearer. thanks Stephen From david.simms at oracle.com Thu Aug 29 14:46:36 2019 From: david.simms at oracle.com (David Simms) Date: Thu, 29 Aug 2019 16:46:36 +0200 Subject: RFR 8229539: [lworld] Incorrect result of sorting test with -XX:ValueArrayElemMaxFlatSize=0 Message-ID: <6d44929c-158c-1a6d-8f2e-c4b9b76f4f0b@oracle.com> Bug: https://bugs.openjdk.java.net/browse/JDK-8229539 Webrev: http://cr.openjdk.java.net/~dsimms/valhalla/8229539/ "ObjArrayKlass::copy_array()" had implemented it's own copy logic just so it could enforce "null-free" array copy (which happens in ObjArrayKlass when flattening is disabled). There was bug in the copy code for *conjoint overlapping copies* (i.e. broke System.arraycopy()). Rather than "fix" the logic, I removed it completely, and with Erik ?sterlund's help added a new decorator to the Access API: "ARRAYCOPY_NOTNULL" (pushing down the null check into the existing API, reduce the amount of "special code", or simply duplicated code). I did note that the same bug exists for valueArrayKlass, this is now fixed as part of the patch. Said fix is temporary though, in that we should start moving to using the Access API for value stores. I limited the scope of this patch to the immediate bug fix. Whilst adding some new tests, I noted some really old code use "_WithField" and various javac compiler flags that are no longer required. So I took the opportunity to clean out some of those. Cheers /David Simms From brian.goetz at oracle.com Thu Aug 29 15:43:31 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 29 Aug 2019 11:43:31 -0400 Subject: Equality for values -- new analysis, same conclusion In-Reply-To: References: <90C17B62-5968-4352-825E-4F1EFAC81052@oracle.com> <131B9329-ECE7-46BE-909F-AC88421FF6CB@oracle.com> <945127A0-393C-4888-AC7A-5529D66423A6@oracle.com> Message-ID: > Braindump thoughts went as follows: > > LocalDate.Inline > LocalDate.Val > VLocalDate > LocalDateV > LDate > LocDate Sounds about right. The first two have a big advantage over the rest, in that they are suitable for mechanical derivation by language-level type operations (it would be reasonable for a language to know that the ?box? type of V is a class called ?V.Box?, but it would be kind of unreasonable to burn in a naming convention like BoxOfV.) > Do migrated inline classes have different names to highlight the > migration? I see where you?re going ? colonize the lower-case name syntax for values. We?ve had this discussion before, and set it aside then, but there?s new information now, so its fair to dust it off and reexamine. The last 36 times it was suggested ?let?s just spell value types with lower case letters, like primitives?, we said ?way way too early to have that discussion?, in part because making that syntax choice (tail) would have thrown the possibility of compatible in-place migration out the window (dog). (This is one of many reasons why we don?t commit to syntax too early (or even, allow it to take up too much airtime); it constrains the possible feature space in ways that are hard to even see.) And at the time, we were quite interested in supporting a compatible migration where Optional ?just? becomes a value type, and invested a great deal of work in understanding the costs of making that possible, since this would be the ideal outcome for the users ? existing code just gets faster. (And, as comments earlier in this thread suggest, you were not thrilled at the idea that we were unable to succeed on that quest, because it means coming up with new names for a bunch of perfectly good types with perfectly good names.) But, there?s new information, which is that we seem to be converging on a scheme where the ?box? is a separate nominal type, which means that this suggestion now becomes _possible_. (It still has challenges, and its still kind of early to discuss it, because there are still some serious object-model issues we really should work out first. But its a good reminder to not forget it.) > Highlighting migration seems like a bad idea in the long > term. I know what you mean, and agree, but let me restate it in a less ?absolutist" fashion. Migration compatibility is essential; flag days are often fatal. And in any migration, there are three phases: old world, transition, and new world. Ideally, we would like to arrive at the situation where the new, idiomatic code in the new world isn?t stuck with a crappy, migration-induced syntax forever, and any migration-induced compromises fade out as the transition phase comes to an end. (This is exactly why, for example, in L2 you can?t say `Foo`, you have to say `Foo`, because, when Foo becomes specialized, we want the default to be ?specialized Foo of V?, without requiring extra syntax that says ?specialize me please.? We?d rather the pain accrue to the transition phase than the new-world phase.) Sometimes this is possible; sometimes it is not. We work hard to minimize the collateral damage when it is not. > Specifically, in the long term it seems like the best name > should go to the inline class, not the box. This seems to rule out > `LocalDate.Inline` as surely we don't want to refer to `Ratio.Inline` > or `Long128.Inline` everywhere. You?ve just mixed two cases, though. For new classes, like Ratio and Long128, we have no compatibility constraint with previous utterances of the class name; for existing classes like LocalDate, we do. Yes, it would be nice to have the ?polarity? be the same in both cases, but that would-be-nice runs smack into the other would-be-nice of the above principle. > For a naive user, this behaviour of == is deeply unhelpful and (10 yard penalty for gratuitous overuse of ?deeply?) > What if inline classes are divided between "pure" and "impure" (better > names needed). A "pure" inline class has (1) a sensible default value, > not null/exception (2) a correct == implementation that always works > as would be expected of a primitive type (3) no reference type fields. > An "impure" inline class may contain reference type fields, may have > no meaningful default value and should never be compared using == in > normal code. Yes, you?ve put your finger on the essential discomfort here, which is that when values have identity in the transitive closure of their state, much hilarity ensues. And some values are well-behaved in the sense that they are ?values all the way down? (FYI, for a detailed exploration of the values-all-the-way-down imperative in a Java-like langauge, see the LiMe language: https://researcher.watson.ibm.com/researcher/files/us-bacon/Huang08Liquid.pdf ). For values like Complex, Point, Rational, etc, there is no identity anywhere in the transitive closure of the state, so there are no places where `==` and `equals()` would disagree. (However, I would point out that it is not the case that all such VATWD classes necessarily have great default values.) Early on, its was asked, ?why not constrain value types to be values all the way down?, and about 30 ms later, someone realized ?that means you couldn?t have tuples with String in them?, so clearly constraining values down to the ?well-behaved? ones is a non-starter. As you point out, another point in the spectrum is to split over well-behavedness, and mark them in the type system (?identity-polluted value class Foo?), so the compiler could warn when you try to (say) use `==` on an identity-polluted value, but I don?t think anyone would really thank us for this either. I get the appeal of splitting here, but I?m skeptical that the return on specificity carries its weight. > Then we say that "pure" inline classes are named using lowerCamelCase, > and "impure" inline classes using UpperCamelCase. That?s an interesting twist on where I thought you were going, which was ?let?s just use lower case for all value classes? ? you?re suggesting marking the distinction between VATWD and not via naming convention rather than language semantics. (Besides the fact that I think lumping is better than splitting here, I think its pretty questionable for the language to make such inferences based on a naming convention.) But the ?use lower case for values? is workable, and connects to another concern that has been raised in the past: managing the cognitive load of asking users to carry around a mental database of which classes have identity and which do not. So it may well be time to take this idea back off the shelf where we placed it many years ago, and give it another look. > Thus,`localDate` is the inline class for the `LocalDate` box (assuming > agreement on a suitable default value). But, ignoring the immediately above, and as pointed out way above, now that we?ve given up on compatible in-place migration, this again becomes a possibility. (Again, as mentioned above, I don?t want to dive any deeper on it now, because we have more important object-model concerns (such as ?what is the nature of the conversion from localDate to LocalDate ? sub typing, boxing, widening, something else??) which again we should nail down first.) > The overall user model is simpler I think. All types that are > lowerCamelCase behave like primitives wrt == and null, and all types > that are UpperCamelCase behave like reference types wrt == and null. I get where you?re going, but I?m not sure it is spending the complexity budget where it gets the most return. Implicitly, this proposal says ?the biggest problem with values is the equality semantics, so let?s spend all our syntax budget highlighting the difference.? But I am not convinced that?s our biggest problem, and if it?s not, this is an awfully big chunk of syntax budget to spend on it. Good thoughts! Cheers, -Brian From frederic.parain at oracle.com Thu Aug 29 15:44:28 2019 From: frederic.parain at oracle.com (Frederic Parain) Date: Thu, 29 Aug 2019 11:44:28 -0400 Subject: RFR 8229539: [lworld] Incorrect result of sorting test with -XX:ValueArrayElemMaxFlatSize=0 In-Reply-To: <6d44929c-158c-1a6d-8f2e-c4b9b76f4f0b@oracle.com> References: <6d44929c-158c-1a6d-8f2e-c4b9b76f4f0b@oracle.com> Message-ID: <79CE18A0-8B0F-42D4-83F9-6406AC4FFDFC@oracle.com> Nice to have ARRAYCOPY_NOTNULL as part of the Access API. Fixes in objArrayKlass and valueArrayKlass look good too. Thank you for cleaning up the old tests. Reviewed. Fred > On Aug 29, 2019, at 10:46, David Simms wrote: > > > Bug: https://bugs.openjdk.java.net/browse/JDK-8229539 > > Webrev: http://cr.openjdk.java.net/~dsimms/valhalla/8229539/ > > "ObjArrayKlass::copy_array()" had implemented it's own copy logic just so it could enforce "null-free" array copy (which happens in ObjArrayKlass when flattening is disabled). There was bug in the copy code for *conjoint overlapping copies* (i.e. broke System.arraycopy()). Rather than "fix" the logic, I removed it completely, and with Erik ?sterlund's help added a new decorator to the Access API: "ARRAYCOPY_NOTNULL" (pushing down the null check into the existing API, reduce the amount of "special code", or simply duplicated code). > > I did note that the same bug exists for valueArrayKlass, this is now fixed as part of the patch. Said fix is temporary though, in that we should start moving to using the Access API for value stores. I limited the scope of this patch to the immediate bug fix. > > Whilst adding some new tests, I noted some really old code use "_WithField" and various javac compiler flags that are no longer required. So I took the opportunity to clean out some of those. > > Cheers > > /David Simms > > > > From asviraspossible at gmail.com Thu Aug 29 16:55:37 2019 From: asviraspossible at gmail.com (Victor Nazarov) Date: Thu, 29 Aug 2019 18:55:37 +0200 Subject: Equality for values -- new analysis, same conclusion In-Reply-To: References: <90C17B62-5968-4352-825E-4F1EFAC81052@oracle.com> <131B9329-ECE7-46BE-909F-AC88421FF6CB@oracle.com> <945127A0-393C-4888-AC7A-5529D66423A6@oracle.com> Message-ID: Hi, I'd like to mention some other options here since the expert group started this discussion. I think that the way presented below is quite natural and it doesn't burn any useful names. Basically what I suggest is to use different package names: the same way we have java.io, java.nio and java.nio2 packages. The migration can become mostly hassle free and the world after migration can remain almost free of migration debrees. Here is a more detailed description of migration plan. We can make .Box scheme a standard translation generated by javac. So for new classes we'll get * java.lang.Long128 and * java.lang.Long128.Box classes. For migrated types we'll get a new package like java.time2 or something like that. So we'll define * java.time2.LocalDate * java.time2.LocalDate.Box Like this: package java.time2; inline class LocalDate implements java.time.LocalDate { } Having these we can provide a migration option by defining java.time.LocalDate as an interface: package java.time; sealed interface LocalDate permits java.time2.LocalDate { ... } -- Victor Nazarov ??, 29 ???. 2019 ?., 18:12 Brian Goetz : > > Braindump thoughts went as follows: > > > > LocalDate.Inline > > LocalDate.Val > > VLocalDate > > LocalDateV > > LDate > > LocDate > > Sounds about right. The first two have a big advantage over the rest, in > that they are suitable for mechanical derivation by language-level type > operations (it would be reasonable for a language to know that the ?box? > type of V is a class called ?V.Box?, but it would be kind of unreasonable > to burn in a naming convention like BoxOfV.) > > > Do migrated inline classes have different names to highlight the > > migration? > > I see where you?re going ? colonize the lower-case name syntax for > values. We?ve had this discussion before, and set it aside then, but > there?s new information now, so its fair to dust it off and reexamine. The > last 36 times it was suggested ?let?s just spell value types with lower > case letters, like primitives?, we said ?way way too early to have that > discussion?, in part because making that syntax choice (tail) would have > thrown the possibility of compatible in-place migration out the window > (dog). (This is one of many reasons why we don?t commit to syntax too > early (or even, allow it to take up too much airtime); it constrains the > possible feature space in ways that are hard to even see.) And at the > time, we were quite interested in supporting a compatible migration where > Optional ?just? becomes a value type, and invested a great deal of work in > understanding the costs of making that possible, since this would be the > ideal outcome for the users ? existing code just gets faster. (And, as > comments earlier in this thread suggest, you were not thrilled at the idea > that we were unable to succeed on that quest, because it means coming up > with new names for a bunch of perfectly good types with perfectly good > names.) > > But, there?s new information, which is that we seem to be converging on a > scheme where the ?box? is a separate nominal type, which means that this > suggestion now becomes _possible_. (It still has challenges, and its still > kind of early to discuss it, because there are still some serious > object-model issues we really should work out first. But its a good > reminder to not forget it.) > > > Highlighting migration seems like a bad idea in the long > > term. > > I know what you mean, and agree, but let me restate it in a less > ?absolutist" fashion. > > Migration compatibility is essential; flag days are often fatal. And in > any migration, there are three phases: old world, transition, and new > world. Ideally, we would like to arrive at the situation where the new, > idiomatic code in the new world isn?t stuck with a crappy, > migration-induced syntax forever, and any migration-induced compromises > fade out as the transition phase comes to an end. (This is exactly why, > for example, in L2 you can?t say `Foo`, you have to say `Foo projection of V>`, because, when Foo becomes specialized, we want the > default to be ?specialized Foo of V?, without requiring extra syntax that > says ?specialize me please.? We?d rather the pain accrue to the transition > phase than the new-world phase.) > > Sometimes this is possible; sometimes it is not. We work hard to minimize > the collateral damage when it is not. > > > Specifically, in the long term it seems like the best name > > should go to the inline class, not the box. This seems to rule out > > `LocalDate.Inline` as surely we don't want to refer to `Ratio.Inline` > > or `Long128.Inline` everywhere. > > You?ve just mixed two cases, though. For new classes, like Ratio and > Long128, we have no compatibility constraint with previous utterances of > the class name; for existing classes like LocalDate, we do. Yes, it would > be nice to have the ?polarity? be the same in both cases, but that > would-be-nice runs smack into the other would-be-nice of the above > principle. > > > For a naive user, this behaviour of == is deeply unhelpful and > > (10 yard penalty for gratuitous overuse of ?deeply?) > > > What if inline classes are divided between "pure" and "impure" (better > > names needed). A "pure" inline class has (1) a sensible default value, > > not null/exception (2) a correct == implementation that always works > > as would be expected of a primitive type (3) no reference type fields. > > An "impure" inline class may contain reference type fields, may have > > no meaningful default value and should never be compared using == in > > normal code. > > Yes, you?ve put your finger on the essential discomfort here, which is > that when values have identity in the transitive closure of their state, > much hilarity ensues. And some values are well-behaved in the sense that > they are ?values all the way down? (FYI, for a detailed exploration of the > values-all-the-way-down imperative in a Java-like langauge, see the LiMe > language: > https://researcher.watson.ibm.com/researcher/files/us-bacon/Huang08Liquid.pdf > < > https://researcher.watson.ibm.com/researcher/files/us-bacon/Huang08Liquid.pdf>). > For values like Complex, Point, Rational, etc, there is no identity > anywhere in the transitive closure of the state, so there are no places > where `==` and `equals()` would disagree. (However, I would point out that > it is not the case that all such VATWD classes necessarily have great > default values.) > > Early on, its was asked, ?why not constrain value types to be values all > the way down?, and about 30 ms later, someone realized ?that means you > couldn?t have tuples with String in them?, so clearly constraining values > down to the ?well-behaved? ones is a non-starter. > > As you point out, another point in the spectrum is to split over > well-behavedness, and mark them in the type system (?identity-polluted > value class Foo?), so the compiler could warn when you try to (say) use > `==` on an identity-polluted value, but I don?t think anyone would really > thank us for this either. I get the appeal of splitting here, but I?m > skeptical that the return on specificity carries its weight. > > > Then we say that "pure" inline classes are named using lowerCamelCase, > > and "impure" inline classes using UpperCamelCase. > > That?s an interesting twist on where I thought you were going, which was > ?let?s just use lower case for all value classes? ? you?re suggesting > marking the distinction between VATWD and not via naming convention rather > than language semantics. (Besides the fact that I think lumping is better > than splitting here, I think its pretty questionable for the language to > make such inferences based on a naming convention.) But the ?use lower > case for values? is workable, and connects to another concern that has been > raised in the past: managing the cognitive load of asking users to carry > around a mental database of which classes have identity and which do not. > So it may well be time to take this idea back off the shelf where we placed > it many years ago, and give it another look. > > > Thus,`localDate` is the inline class for the `LocalDate` box (assuming > > agreement on a suitable default value). > > But, ignoring the immediately above, and as pointed out way above, now > that we?ve given up on compatible in-place migration, this again becomes a > possibility. (Again, as mentioned above, I don?t want to dive any deeper > on it now, because we have more important object-model concerns (such as > ?what is the nature of the conversion from localDate to LocalDate ? sub > typing, boxing, widening, something else??) which again we should nail down > first.) > > > The overall user model is simpler I think. All types that are > > lowerCamelCase behave like primitives wrt == and null, and all types > > that are UpperCamelCase behave like reference types wrt == and null. > > I get where you?re going, but I?m not sure it is spending the complexity > budget where it gets the most return. Implicitly, this proposal says ?the > biggest problem with values is the equality semantics, so let?s spend all > our syntax budget highlighting the difference.? But I am not convinced > that?s our biggest problem, and if it?s not, this is an awfully big chunk > of syntax budget to spend on it. > > Good thoughts! > > Cheers, > -Brian > > > From mandy.chung at oracle.com Thu Aug 29 18:34:25 2019 From: mandy.chung at oracle.com (Mandy Chung) Date: Thu, 29 Aug 2019 11:34:25 -0700 Subject: [nestmates] Name of a hidden class and stack trace Message-ID: I'm writing a JEP proposal of hidden/nestmate/weak classes prototyped in the nestmates branch (JDK-8171335).? Attached describes about hidden classes (thanks to Alex Buckley for the help) and description about nestmates/weak will come next. A hidden class cannot be named by other class.?? Ideally a hidden class should? be nameless.? For troubleshooting and stack trace, a hidden class needs a name.?? So the proposal has been: Class::getName returns a name for a hidden class and the name is unique in the runtime package namespace.? That is, there is no two Class objects with the same name in the same runtime package. Below shows the stack trace where a hidden class throws an exception. $ java -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames DefineClass foo/Foo.class java.lang.Error: error ??? at foo.Foo_/0x0000000800b79258.run(Foo.java:9) ??? at DefineClass.main(DefineClass.java:18) The current impl includes `/` in the hidden class's name to disjoint from the ordinary class names (same trick as VM anonymous class). Another class calls Class::forName with the hidden class's name which would fail since that's not a valid binary name. ? If someone attempts to spin a class referencing this hidden class's name with replace('.', '/'), it may attempt to load a class named 'foo/Foo_/0x0000000800b79258'? and may succeed if such a class file exists and can be located by class loader.? This is no difference than today as one can spin a class file to any class names. Class::getName may return an invalid binary name if it's a hidden class.? It will impact existing code that expects the returned name is a valid binary name or use the name to perform class lookup.? I think the compatibility concern should not be high. Thought? Mandy From brian.goetz at oracle.com Thu Aug 29 18:42:03 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 29 Aug 2019 14:42:03 -0400 Subject: [nestmates] Name of a hidden class and stack trace In-Reply-To: References: Message-ID: <9512BF19-22C4-4825-9735-829F23DA7F2A@oracle.com> This trick has worked well for us with anon classes, and there?s already plenty of code out there that does `name.contains(?/?)` to defend against it, so I see no reason to break from this convention. > On Aug 29, 2019, at 2:34 PM, Mandy Chung wrote: > > I'm writing a JEP proposal of hidden/nestmate/weak classes prototyped in the nestmates branch (JDK-8171335). Attached describes about hidden classes (thanks to Alex Buckley for the help) and description about nestmates/weak will come next. > > A hidden class cannot be named by other class. Ideally a hidden class should be nameless. For troubleshooting and stack trace, a hidden class needs a name. So the proposal has been: > > Class::getName returns a name for a hidden class and the name is unique in the runtime package namespace. That is, there is no two Class objects with the same name in the same runtime package. > > Below shows the stack trace where a hidden class throws an exception. > > $ java -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames DefineClass foo/Foo.class > java.lang.Error: error > at foo.Foo_/0x0000000800b79258.run(Foo.java:9) > at DefineClass.main(DefineClass.java:18) > > The current impl includes `/` in the hidden class's name to disjoint from the ordinary class names > (same trick as VM anonymous class). > > Another class calls Class::forName with the hidden class's name which would fail since that's not a valid binary name. If someone attempts to spin a class referencing this hidden class's name with replace('.', '/'), it may attempt to load a class named 'foo/Foo_/0x0000000800b79258' and may succeed if such a class file exists and can be located by class loader. This is no difference than today as one can spin a class file to any class names. > > Class::getName may return an invalid binary name if it's a hidden class. It will impact existing code that expects the returned name is a valid binary name or use the name to perform class lookup. I think the compatibility concern should not be high. > > Thought? > > Mandy > From mandy.chung at oracle.com Thu Aug 29 18:44:47 2019 From: mandy.chung at oracle.com (Mandy Chung) Date: Thu, 29 Aug 2019 11:44:47 -0700 Subject: [nestmates] Name of a hidden class and stack trace In-Reply-To: <9512BF19-22C4-4825-9735-829F23DA7F2A@oracle.com> References: <9512BF19-22C4-4825-9735-829F23DA7F2A@oracle.com> Message-ID: Yes, I forgot to mention that is another reason to keep '/' rather than another scheme. Mandy On 8/29/19 11:42 AM, Brian Goetz wrote: > This trick has worked well for us with anon classes, and there?s already plenty of code out there that does `name.contains(?/?)` to defend against it, so I see no reason to break from this convention. > >> On Aug 29, 2019, at 2:34 PM, Mandy Chung wrote: >> >> I'm writing a JEP proposal of hidden/nestmate/weak classes prototyped in the nestmates branch (JDK-8171335). Attached describes about hidden classes (thanks to Alex Buckley for the help) and description about nestmates/weak will come next. >> >> A hidden class cannot be named by other class. Ideally a hidden class should be nameless. For troubleshooting and stack trace, a hidden class needs a name. So the proposal has been: >> >> Class::getName returns a name for a hidden class and the name is unique in the runtime package namespace. That is, there is no two Class objects with the same name in the same runtime package. >> >> Below shows the stack trace where a hidden class throws an exception. >> >> $ java -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames DefineClass foo/Foo.class >> java.lang.Error: error >> at foo.Foo_/0x0000000800b79258.run(Foo.java:9) >> at DefineClass.main(DefineClass.java:18) >> >> The current impl includes `/` in the hidden class's name to disjoint from the ordinary class names >> (same trick as VM anonymous class). >> >> Another class calls Class::forName with the hidden class's name which would fail since that's not a valid binary name. If someone attempts to spin a class referencing this hidden class's name with replace('.', '/'), it may attempt to load a class named 'foo/Foo_/0x0000000800b79258' and may succeed if such a class file exists and can be located by class loader. This is no difference than today as one can spin a class file to any class names. >> >> Class::getName may return an invalid binary name if it's a hidden class. It will impact existing code that expects the returned name is a valid binary name or use the name to perform class lookup. I think the compatibility concern should not be high. >> >> Thought? >> >> Mandy >> From forax at univ-mlv.fr Thu Aug 29 20:28:57 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 29 Aug 2019 22:28:57 +0200 (CEST) Subject: [nestmates] Name of a hidden class and stack trace In-Reply-To: References: <9512BF19-22C4-4825-9735-829F23DA7F2A@oracle.com> Message-ID: <1662841269.1696523.1567110537358.JavaMail.zimbra@u-pem.fr> Yes, resing the same scheme is fine. BTW, is there a better way to test hidden classes ? R?mi ----- Mail original ----- > De: "mandy chung" > ?: "Brian Goetz" > Cc: "valhalla-dev" > Envoy?: Jeudi 29 Ao?t 2019 20:44:47 > Objet: Re: [nestmates] Name of a hidden class and stack trace > Yes, I forgot to mention that is another reason to keep '/' rather than > another scheme. > > Mandy > > On 8/29/19 11:42 AM, Brian Goetz wrote: >> This trick has worked well for us with anon classes, and there?s already plenty >> of code out there that does `name.contains(?/?)` to defend against it, so I see >> no reason to break from this convention. >> >>> On Aug 29, 2019, at 2:34 PM, Mandy Chung wrote: >>> >>> I'm writing a JEP proposal of hidden/nestmate/weak classes prototyped in the >>> nestmates branch (JDK-8171335). Attached describes about hidden classes >>> (thanks to Alex Buckley for the help) and description about nestmates/weak will >>> come next. >>> >>> A hidden class cannot be named by other class. Ideally a hidden class should >>> be nameless. For troubleshooting and stack trace, a hidden class needs a >>> name. So the proposal has been: >>> >>> Class::getName returns a name for a hidden class and the name is unique in the >>> runtime package namespace. That is, there is no two Class objects with the >>> same name in the same runtime package. >>> >>> Below shows the stack trace where a hidden class throws an exception. >>> >>> $ java -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames DefineClass >>> foo/Foo.class >>> java.lang.Error: error >>> at foo.Foo_/0x0000000800b79258.run(Foo.java:9) >>> at DefineClass.main(DefineClass.java:18) >>> >>> The current impl includes `/` in the hidden class's name to disjoint from the >>> ordinary class names >>> (same trick as VM anonymous class). >>> >>> Another class calls Class::forName with the hidden class's name which would fail >>> since that's not a valid binary name. If someone attempts to spin a class >>> referencing this hidden class's name with replace('.', '/'), it may attempt to >>> load a class named 'foo/Foo_/0x0000000800b79258' and may succeed if such a >>> class file exists and can be located by class loader. This is no difference >>> than today as one can spin a class file to any class names. >>> >>> Class::getName may return an invalid binary name if it's a hidden class. It >>> will impact existing code that expects the returned name is a valid binary name >>> or use the name to perform class lookup. I think the compatibility concern >>> should not be high. >>> >>> Thought? >>> >>> Mandy From mandy.chung at oracle.com Thu Aug 29 21:00:11 2019 From: mandy.chung at oracle.com (Mandy Chung) Date: Thu, 29 Aug 2019 14:00:11 -0700 Subject: [nestmates] Name of a hidden class and stack trace In-Reply-To: <1662841269.1696523.1567110537358.JavaMail.zimbra@u-pem.fr> References: <9512BF19-22C4-4825-9735-829F23DA7F2A@oracle.com> <1662841269.1696523.1567110537358.JavaMail.zimbra@u-pem.fr> Message-ID: One thought I have is to tag along a bit in the modifiers and of course getModifiers will have to mask with the legal bits. Mandy On 8/29/19 1:28 PM, Remi Forax wrote: > Yes, > resing the same scheme is fine. > > BTW, is there a better way to test hidden classes ? > > R?mi > > ----- Mail original ----- >> De: "mandy chung" >> ?: "Brian Goetz" >> Cc: "valhalla-dev" >> Envoy?: Jeudi 29 Ao?t 2019 20:44:47 >> Objet: Re: [nestmates] Name of a hidden class and stack trace >> Yes, I forgot to mention that is another reason to keep '/' rather than >> another scheme. >> >> Mandy >> >> On 8/29/19 11:42 AM, Brian Goetz wrote: >>> This trick has worked well for us with anon classes, and there?s already plenty >>> of code out there that does `name.contains(?/?)` to defend against it, so I see >>> no reason to break from this convention. >>> >>>> On Aug 29, 2019, at 2:34 PM, Mandy Chung wrote: >>>> >>>> I'm writing a JEP proposal of hidden/nestmate/weak classes prototyped in the >>>> nestmates branch (JDK-8171335). Attached describes about hidden classes >>>> (thanks to Alex Buckley for the help) and description about nestmates/weak will >>>> come next. >>>> >>>> A hidden class cannot be named by other class. Ideally a hidden class should >>>> be nameless. For troubleshooting and stack trace, a hidden class needs a >>>> name. So the proposal has been: >>>> >>>> Class::getName returns a name for a hidden class and the name is unique in the >>>> runtime package namespace. That is, there is no two Class objects with the >>>> same name in the same runtime package. >>>> >>>> Below shows the stack trace where a hidden class throws an exception. >>>> >>>> $ java -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames DefineClass >>>> foo/Foo.class >>>> java.lang.Error: error >>>> at foo.Foo_/0x0000000800b79258.run(Foo.java:9) >>>> at DefineClass.main(DefineClass.java:18) >>>> >>>> The current impl includes `/` in the hidden class's name to disjoint from the >>>> ordinary class names >>>> (same trick as VM anonymous class). >>>> >>>> Another class calls Class::forName with the hidden class's name which would fail >>>> since that's not a valid binary name. If someone attempts to spin a class >>>> referencing this hidden class's name with replace('.', '/'), it may attempt to >>>> load a class named 'foo/Foo_/0x0000000800b79258' and may succeed if such a >>>> class file exists and can be located by class loader. This is no difference >>>> than today as one can spin a class file to any class names. >>>> >>>> Class::getName may return an invalid binary name if it's a hidden class. It >>>> will impact existing code that expects the returned name is a valid binary name >>>> or use the name to perform class lookup. I think the compatibility concern >>>> should not be high. >>>> >>>> Thought? >>>> >>>> Mandy From mandy.chung at oracle.com Thu Aug 29 23:16:22 2019 From: mandy.chung at oracle.com (Mandy Chung) Date: Thu, 29 Aug 2019 16:16:22 -0700 Subject: [nestmates] Name of a hidden class and stack trace In-Reply-To: <9512BF19-22C4-4825-9735-829F23DA7F2A@oracle.com> References: <9512BF19-22C4-4825-9735-829F23DA7F2A@oracle.com> Message-ID: If a hidden class invokes a lambda, as the target class is a hidden class whose name contains '/', it will need to be converted so that the lambda proxy class will be in the same package "foo". So stack trace will look like something like this: java.lang.Error: thrown from hidden class foo.Foo_0x0000000800b7a470 at m1/foo.Foo/0x0000000800b7a470.toString(Foo.java:16) at m1/foo.Foo_0x0000000800b7a470$$Lambda$29/0x0000000800b7c040.apply(:1000001) at m1/foo.Foo/0x0000000800b7a470.test(Foo.java:11) lambda proxy: foo.Foo_0x0000000800b7a470$$Lambda$29/0x0000000800b7c040 for: foo.Foo/0x0000000800b7a470 One single '/' in both hidden class's names while the simple name has one odd single character difference. It's not too bad though as the frames are hidden by default. The alternative would use a valid binary name but that requires existing tools to migrate. Another thing I like '/' is that StackTraceElement::toString uses '/' in separating classloader/module/classname and now /0x.... is shown to separate its id. Mandy On 8/29/19 11:42 AM, Brian Goetz wrote: > This trick has worked well for us with anon classes, and there?s already plenty of code out there that does `name.contains(?/?)` to defend against it, so I see no reason to break from this convention. > >> On Aug 29, 2019, at 2:34 PM, Mandy Chung wrote: >> >> I'm writing a JEP proposal of hidden/nestmate/weak classes prototyped in the nestmates branch (JDK-8171335). Attached describes about hidden classes (thanks to Alex Buckley for the help) and description about nestmates/weak will come next. >> >> A hidden class cannot be named by other class. Ideally a hidden class should be nameless. For troubleshooting and stack trace, a hidden class needs a name. So the proposal has been: >> >> Class::getName returns a name for a hidden class and the name is unique in the runtime package namespace. That is, there is no two Class objects with the same name in the same runtime package. >> >> Below shows the stack trace where a hidden class throws an exception. >> >> $ java -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames DefineClass foo/Foo.class >> java.lang.Error: error >> at foo.Foo_/0x0000000800b79258.run(Foo.java:9) >> at DefineClass.main(DefineClass.java:18) >> >> The current impl includes `/` in the hidden class's name to disjoint from the ordinary class names >> (same trick as VM anonymous class). >> >> Another class calls Class::forName with the hidden class's name which would fail since that's not a valid binary name. If someone attempts to spin a class referencing this hidden class's name with replace('.', '/'), it may attempt to load a class named 'foo/Foo_/0x0000000800b79258' and may succeed if such a class file exists and can be located by class loader. This is no difference than today as one can spin a class file to any class names. >> >> Class::getName may return an invalid binary name if it's a hidden class. It will impact existing code that expects the returned name is a valid binary name or use the name to perform class lookup. I think the compatibility concern should not be high. >> >> Thought? >> >> Mandy >> From mandy.chung at oracle.com Fri Aug 30 02:48:39 2019 From: mandy.chung at oracle.com (mandy.chung at oracle.com) Date: Fri, 30 Aug 2019 02:48:39 +0000 Subject: hg: valhalla/valhalla: [Nestmates] update hidden/nestmate/weak class prototype Message-ID: <201908300248.x7U2mdJE024253@aojmv0008.oracle.com> Changeset: 4be2cb65666f Author: mchung Date: 2019-08-29 19:32 -0700 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/4be2cb65666f [Nestmates] update hidden/nestmate/weak class prototype ! src/hotspot/share/oops/instanceKlass.cpp ! src/hotspot/share/oops/method.hpp ! src/hotspot/share/runtime/reflection.cpp ! src/java.base/share/classes/java/lang/Class.java ! src/java.base/share/classes/java/lang/StringConcatHelper.java ! src/java.base/share/classes/java/lang/System.java ! src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java ! src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java ! src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java ! src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java ! src/java.base/share/classes/java/lang/invoke/MethodHandles.java ! src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java ! src/java.base/share/classes/java/lang/reflect/AccessibleObject.java ! src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java ! src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java ! src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java ! src/jdk.unsupported/share/classes/sun/misc/Unsafe.java + test/hotspot/jtreg/compiler/cha/ObjectHashCode.java + test/hotspot/jtreg/compiler/cha/ObjectToString.java ! test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java + test/hotspot/jtreg/compiler/cha/ThreeLevelDefaultHierarchy.java + test/hotspot/jtreg/compiler/cha/ThreeLevelDefaultHierarchy1.java + test/hotspot/jtreg/compiler/cha/ThreeLevelHierarchyAbstractVsDefault.java + test/hotspot/jtreg/compiler/cha/ThreeLevelHierarchyLinear.java + test/hotspot/jtreg/compiler/cha/TwoLevelHierarchyLinear.java ! test/hotspot/jtreg/runtime/Nestmates/membership/TestDynamicNestmateMembership.java ! test/jdk/java/lang/StackWalker/VerifyStackTrace.java - test/jdk/java/lang/invoke/defineClass/DefineClassTest.java - test/jdk/java/lang/invoke/defineClass/DefineClassWithClassData.java - test/jdk/java/lang/invoke/defineClass/DefineNonFindableClass.java - test/jdk/java/lang/invoke/defineClass/nonFindable/NonFindable.java - test/jdk/java/lang/invoke/defineClass/nonFindable/NonFindableField.java - test/jdk/java/lang/invoke/defineClass/nonFindable/NonFindableMethod.java + test/jdk/java/lang/invoke/defineHiddenClass/BasicTest.java + test/jdk/java/lang/invoke/defineHiddenClass/DefineClassWithClassData.java + test/jdk/java/lang/invoke/defineHiddenClass/DefineHiddenClassTest.java + test/jdk/java/lang/invoke/defineHiddenClass/SelfRefField.java + test/jdk/java/lang/invoke/defineHiddenClass/SelfRefMethod.java + test/jdk/java/lang/invoke/defineHiddenClass/SelfReferenceDescriptor.java + test/jdk/java/lang/invoke/defineHiddenClass/src/AbstractClass.java + test/jdk/java/lang/invoke/defineHiddenClass/src/EnclosingClass.java + test/jdk/java/lang/invoke/defineHiddenClass/src/HiddenCantReflect.java + test/jdk/java/lang/invoke/defineHiddenClass/src/HiddenClass.java + test/jdk/java/lang/invoke/defineHiddenClass/src/HiddenClassThrow.java + test/jdk/java/lang/invoke/defineHiddenClass/src/HiddenInterface.java + test/jdk/java/lang/invoke/defineHiddenClass/src/HiddenSuper.java + test/jdk/java/lang/invoke/defineHiddenClass/src/Lambda.java + test/jdk/java/lang/invoke/defineHiddenClass/src/Outer.java ! test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java + test/micro/org/openjdk/bench/java/lang/invoke/LookupDefineClass.java From mandy.chung at oracle.com Fri Aug 30 05:38:11 2019 From: mandy.chung at oracle.com (Mandy Chung) Date: Thu, 29 Aug 2019 22:38:11 -0700 Subject: [Nestmates] update hidden/nestmate/weak class prototype In-Reply-To: <201908300248.x7U2mdJE024253@aojmv0008.oracle.com> References: <201908300248.x7U2mdJE024253@aojmv0008.oracle.com> Message-ID: <7780c11a-a304-039d-a900-8c67c27b236f@oracle.com> This patch simplifies the API to define hidden classes (make the API explicit `defineHiddenClass`).? JDK no longer uses Unsafe::defineAnonymousClass but convert to the new API. http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8171335/api/ http://cr.openjdk.java.net/~mchung/valhalla/webrevs/8171335/specdiff/overview-summary.html Mandy -------- Forwarded Message -------- Subject: hg: valhalla/valhalla: [Nestmates] update hidden/nestmate/weak class prototype Date: Fri, 30 Aug 2019 02:48:39 +0000 From: mandy.chung at oracle.com To: valhalla-dev at openjdk.java.net Changeset: 4be2cb65666f Author: mchung Date: 2019-08-29 19:32 -0700 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/4be2cb65666f [Nestmates] update hidden/nestmate/weak class prototype ! src/hotspot/share/oops/instanceKlass.cpp ! src/hotspot/share/oops/method.hpp ! src/hotspot/share/runtime/reflection.cpp ! src/java.base/share/classes/java/lang/Class.java ! src/java.base/share/classes/java/lang/StringConcatHelper.java ! src/java.base/share/classes/java/lang/System.java ! src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java ! src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java ! src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java ! src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java ! src/java.base/share/classes/java/lang/invoke/MethodHandles.java ! src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java ! src/java.base/share/classes/java/lang/reflect/AccessibleObject.java ! src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java ! src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java ! src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java ! src/jdk.unsupported/share/classes/sun/misc/Unsafe.java + test/hotspot/jtreg/compiler/cha/ObjectHashCode.java + test/hotspot/jtreg/compiler/cha/ObjectToString.java ! test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java + test/hotspot/jtreg/compiler/cha/ThreeLevelDefaultHierarchy.java + test/hotspot/jtreg/compiler/cha/ThreeLevelDefaultHierarchy1.java + test/hotspot/jtreg/compiler/cha/ThreeLevelHierarchyAbstractVsDefault.java + test/hotspot/jtreg/compiler/cha/ThreeLevelHierarchyLinear.java + test/hotspot/jtreg/compiler/cha/TwoLevelHierarchyLinear.java ! test/hotspot/jtreg/runtime/Nestmates/membership/TestDynamicNestmateMembership.java ! test/jdk/java/lang/StackWalker/VerifyStackTrace.java - test/jdk/java/lang/invoke/defineClass/DefineClassTest.java - test/jdk/java/lang/invoke/defineClass/DefineClassWithClassData.java - test/jdk/java/lang/invoke/defineClass/DefineNonFindableClass.java - test/jdk/java/lang/invoke/defineClass/nonFindable/NonFindable.java - test/jdk/java/lang/invoke/defineClass/nonFindable/NonFindableField.java - test/jdk/java/lang/invoke/defineClass/nonFindable/NonFindableMethod.java + test/jdk/java/lang/invoke/defineHiddenClass/BasicTest.java + test/jdk/java/lang/invoke/defineHiddenClass/DefineClassWithClassData.java + test/jdk/java/lang/invoke/defineHiddenClass/DefineHiddenClassTest.java + test/jdk/java/lang/invoke/defineHiddenClass/SelfRefField.java + test/jdk/java/lang/invoke/defineHiddenClass/SelfRefMethod.java + test/jdk/java/lang/invoke/defineHiddenClass/SelfReferenceDescriptor.java + test/jdk/java/lang/invoke/defineHiddenClass/src/AbstractClass.java + test/jdk/java/lang/invoke/defineHiddenClass/src/EnclosingClass.java + test/jdk/java/lang/invoke/defineHiddenClass/src/HiddenCantReflect.java + test/jdk/java/lang/invoke/defineHiddenClass/src/HiddenClass.java + test/jdk/java/lang/invoke/defineHiddenClass/src/HiddenClassThrow.java + test/jdk/java/lang/invoke/defineHiddenClass/src/HiddenInterface.java + test/jdk/java/lang/invoke/defineHiddenClass/src/HiddenSuper.java + test/jdk/java/lang/invoke/defineHiddenClass/src/Lambda.java + test/jdk/java/lang/invoke/defineHiddenClass/src/Outer.java ! test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java + test/micro/org/openjdk/bench/java/lang/invoke/LookupDefineClass.java From david.simms at oracle.com Fri Aug 30 07:59:40 2019 From: david.simms at oracle.com (david.simms at oracle.com) Date: Fri, 30 Aug 2019 07:59:40 +0000 Subject: hg: valhalla/valhalla: 8229539: [lworld] Incorrect result of sorting test with -XX:ValueArrayElemMaxFlatSize=0 Message-ID: <201908300759.x7U7xfsM013214@aojmv0008.oracle.com> Changeset: 966737ceafe7 Author: dsimms Date: 2019-08-30 09:59 +0200 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/966737ceafe7 8229539: [lworld] Incorrect result of sorting test with -XX:ValueArrayElemMaxFlatSize=0 ! src/hotspot/share/gc/shared/barrierSet.cpp ! src/hotspot/share/gc/shared/barrierSet.hpp ! src/hotspot/share/gc/shared/barrierSet.inline.hpp ! src/hotspot/share/gc/shared/modRefBarrierSet.hpp ! src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp ! src/hotspot/share/gc/z/zBarrierSet.hpp ! src/hotspot/share/gc/z/zBarrierSet.inline.hpp ! src/hotspot/share/oops/access.hpp ! src/hotspot/share/oops/access.inline.hpp ! src/hotspot/share/oops/accessBackend.hpp ! src/hotspot/share/oops/accessBackend.inline.hpp ! src/hotspot/share/oops/accessDecorators.hpp ! src/hotspot/share/oops/objArrayKlass.cpp ! src/hotspot/share/oops/valueArrayKlass.cpp ! test/hotspot/jtreg/runtime/valhalla/valuetypes/Long8Value.java ! test/hotspot/jtreg/runtime/valhalla/valuetypes/Person.java ! test/hotspot/jtreg/runtime/valhalla/valuetypes/Point.java ! test/hotspot/jtreg/runtime/valhalla/valuetypes/ValueTypeArray.java From ioi.lam at oracle.com Sat Aug 31 03:02:35 2019 From: ioi.lam at oracle.com (ioi.lam at oracle.com) Date: Sat, 31 Aug 2019 03:02:35 +0000 Subject: hg: valhalla/valhalla: 8230325: Incorrect generation of C1 unverified entry point Message-ID: <201908310302.x7V32aUq015713@aojmv0008.oracle.com> Changeset: 6822a6f27c5b Author: iklam Date: 2019-08-30 20:00 -0700 URL: https://hg.openjdk.java.net/valhalla/valhalla/rev/6822a6f27c5b 8230325: Incorrect generation of C1 unverified entry point ! src/hotspot/share/c1/c1_LIRAssembler.cpp ! test/hotspot/jtreg/compiler/valhalla/valuetypes/TestCallingConventionC1.java From kustos at gmx.net Sat Aug 31 18:08:33 2019 From: kustos at gmx.net (Philippe Marschall) Date: Sat, 31 Aug 2019 20:08:33 +0200 Subject: Struggling with Valhalla conversion of library In-Reply-To: <393d573d-4c8b-65b8-0803-b5f58dd49a87@oracle.com> References: <49d3aca7-ec3d-894b-695c-cbb3ce09709b@oracle.com> <86cc5350-7942-4760-ce44-3aa116e88e19@gmx.net> <393d573d-4c8b-65b8-0803-b5f58dd49a87@oracle.com> Message-ID: <0e0166c6-db5a-eef7-8a94-85eea0fbfb3f@gmx.net> On 25.08.19 12:31, Srikanth wrote: > Hello Philippe, > > I have pushed a change set > http://hg.openjdk.java.net/valhalla/valhalla/rev/e9393b1577db, on behalf of > https://bugs.openjdk.java.net/browse/JDK-8230121 that addresses this > problem. I tried to build the tip of the lworld branch but compilation fails for me with gcc 8.3.0 in src/hotspot/share/oops/access.inline.hpp. I'm not sure whether it makes sense to debug this or I should just rather wait for the next build. > Note however that the syntax to be used is: > > void doesNotCompile(java.util.Map.Entry*?*, ? > extends V> argument); > > Inline types cannot be type arguments as of LW2, only their nullable > projection types can be. Hence the ? > > I do wish to echo Brian's message in another thread: > > "The interaction of generic instantiation and the nullable projection > type are definitely in the corners right now."? and "So while we would > of course like for these things to work, we're not surprised there are > pitfalls and interactions" Sure, no problem, I understand. Cheers Philippe