Skip to content

Commit 5cf15b3

Browse files
committed
Create lambda names format consistent with the JDK lambda names format.
1 parent 44f7d04 commit 5cf15b3

File tree

7 files changed

+18
-19
lines changed

7 files changed

+18
-19
lines changed

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/LambdaStableNameTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,20 @@ public void checkStableLamdaNameForRunnableAndAutoCloseable() {
6969
assertEquals("Both stable lambda names are the same as they reference the same method", name, acName);
7070

7171
String myName = Type.getInternalName(getClass());
72-
assertEquals("The name known in 19.3 version is computed", "L" + myName + "$$Lambda$0a7a1b7da3e20b4eff3f548c6ba3e47a0c3be612;", name);
72+
assertEquals("The name known in 24.0 version is computed", "L" + myName + "$$Lambda.0x0a7a1b7da3e20b4eff3f548c6ba3e47a0c3be612;", name);
7373
}
7474

7575
private static void assertLambdaName(String name) {
7676
String expectedPrefix = "L" + LambdaStableNameTest.class.getCanonicalName().replace('.', '/') +
77-
"$$Lambda$";
77+
LambdaUtils.LAMBDA_CLASS_NAME_SUBSTRING;
7878
if (!name.startsWith(expectedPrefix)) {
7979
fail("Expecting " + expectedPrefix + " as prefix in lambda class name: " + name);
8080
}
8181
assertTrue("semicolon at the end", name.endsWith(";"));
8282

83-
int last = name.lastIndexOf('$');
83+
int index = name.indexOf(LambdaUtils.ADDRESS_PREFIX);
8484

85-
String hash = name.substring(last + 1, name.length() - 1);
85+
String hash = name.substring(index + LambdaUtils.ADDRESS_PREFIX.length(), name.length() - 1);
8686

8787
BigInteger aValue = new BigInteger(hash, 16);
8888
assertNotNull("Hash can be parsed as a hex number: " + hash, aValue);

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/java/LambdaUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public final class LambdaUtils {
6060
public static final String LAMBDA_CLASS_NAME_SUBSTRING = "$$Lambda";
6161
public static final String SERIALIZATION_TEST_LAMBDA_CLASS_SUBSTRING = "$$Lambda";
6262
public static final String SERIALIZATION_TEST_LAMBDA_CLASS_SPLIT_PATTERN = "\\$\\$Lambda";
63+
public static final String ADDRESS_PREFIX = ".0x";
6364

6465
private static GraphBuilderConfiguration buildLambdaParserConfig(ClassInitializationPlugin cip) {
6566
GraphBuilderConfiguration.Plugins plugins = new GraphBuilderConfiguration.Plugins(new InvocationPlugins());
@@ -141,7 +142,7 @@ private static String createStableLambdaName(ResolvedJavaType lambdaType, List<R
141142
Matcher m = lambdaMatcher(lambdaName);
142143
StringBuilder sb = new StringBuilder();
143144
targetMethods.forEach((targetMethod) -> sb.append(targetMethod.format("%H.%n(%P)%R")));
144-
return m.replaceFirst(Matcher.quoteReplacement("$$Lambda$" + digest(sb.toString()) + ";"));
145+
return m.replaceFirst(Matcher.quoteReplacement(LAMBDA_CLASS_NAME_SUBSTRING + ADDRESS_PREFIX + digest(sb.toString()) + ";"));
145146
}
146147

147148
private static Matcher lambdaMatcher(String value) {

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This changelog summarizes major changes to GraalVM Native Image.
1111
* (GR-48579) Options ParseOnce, ParseOnceJIT, and InlineBeforeAnalysis are deprecated and no longer have any effect.
1212
* (GR-39407) Add support for the `NATIVE_IMAGE_OPTIONS` environment variable, which allows users and tools to pass additional arguments via the environment. Similar to `JAVA_TOOL_OPTIONS`, the value of the environment variable is prepended to the options supplied to `native-image`.
1313
* (GR-20827): Introduce a dedicated caller-saved branch target register for software CFI implementations.
14+
* (GR-47937) Make the lambda-class name format in Native-Image consistent with the JDK name format.
1415

1516
## GraalVM for JDK 21 (Internal Version 23.1.0)
1617
* (GR-35746) Lower the default aligned chunk size from 1 MB to 512 KB for the serial and epsilon GCs, reducing memory usage and image size in many cases.

substratevm/mx.substratevm/testhello.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ def test():
900900
checker.check(exec_string, skip_fails=False)
901901
exec_string = execute("backtrace 3")
902902
rexp = [r"#0%shello\.Hello::lambda\$(static\$)?0%s %s at hello/Hello\.java:210"%(spaces_pattern, no_param_types_pattern, no_arg_values_pattern),
903-
r"#1%s%s in hello\.Hello\$\$Lambda\$(%s/0x)?%s::get%s at hello/Hello\.java:238"%(spaces_pattern, address_pattern, digits_pattern, hex_digits_pattern, wildcard_pattern),
903+
r"#1%s%s in hello\.Hello\$\$Lambda((\$%s/0x)|(\$)|(\.0x|/0x))?%s::get%s at hello/Hello\.java:238"%(spaces_pattern, address_pattern, digits_pattern, hex_digits_pattern, wildcard_pattern),
904904
r"#2%shello\.Hello::main%s %s at hello/Hello\.java:238"%(spaces_pattern, param_types_pattern, arg_values_pattern)]
905905
checker = Checker('backtrace in lambda', rexp)
906906
checker.check(exec_string, skip_fails=False)

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaProxyRenamingSubstitutionProcessor.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,13 @@
4545
/**
4646
* This substitution replaces all lambda proxy types with types that have a stable names. The name
4747
* is formed from the signature of the target method that the lambda is calling.
48-
*
48+
* <p>
4949
* NOTE: there is a particular case in which names are not stable. If multiple lambda proxies have a
5050
* same target in a same class they are indistinguishable in bytecode. Then their stable names get
5151
* appended with a unique number for that class. To make this corner case truly stable, analysis
5252
* must be run in the single-threaded mode.
5353
*/
54+
5455
public class LambdaProxyRenamingSubstitutionProcessor extends SubstitutionProcessor {
5556

5657
private final BigBang bb;
@@ -66,7 +67,7 @@ public class LambdaProxyRenamingSubstitutionProcessor extends SubstitutionProces
6667

6768
@Override
6869
public ResolvedJavaType lookup(ResolvedJavaType type) {
69-
if (LambdaUtils.isLambdaType(type)) {
70+
if (LambdaUtils.isLambdaType(type) && !type.getClass().equals(LambdaSubstitutionType.class)) {
7071
return getSubstitution(type);
7172
} else {
7273
return type;
@@ -100,14 +101,16 @@ private LambdaSubstitutionType getSubstitution(ResolvedJavaType original) {
100101
*/
101102
private String findUniqueLambdaProxyName(String lambdaTargetName) {
102103
synchronized (uniqueLambdaProxyNames) {
103-
String newStableName = lambdaTargetName;
104-
CharSequence stableNameBase = lambdaTargetName.subSequence(0, lambdaTargetName.length() - 1);
104+
String stableNameBase = lambdaTargetName.substring(0, lambdaTargetName.length() - 1);
105+
String newStableName = stableNameBase + "0;";
106+
105107
int i = 1;
106108
while (uniqueLambdaProxyNames.contains(newStableName)) {
107-
newStableName = stableNameBase + "_" + i + ";";
109+
newStableName = stableNameBase + i + ";";
108110
i += 1;
109111
}
110112
uniqueLambdaProxyNames.add(newStableName);
113+
111114
return newStableName;
112115
}
113116
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/StableLambdaProxyNameFeature.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ private static boolean checkLambdaNames(List<AnalysisType> types) {
6060
throw new AssertionError("Expensive check: should only run with assertions enabled.");
6161
}
6262
/* There should be no random lambda names visible to the analysis. */
63-
if (types.stream().anyMatch(LambdaUtils::isLambdaType)) {
63+
if (types.stream().anyMatch(type -> LambdaUtils.isLambdaType(type) && type.getWrapped().getClass() != LambdaSubstitutionType.class)) {
6464
throw new AssertionError("All lambda proxies should be substituted.");
6565
}
6666

truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostObjectToStringTest.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,7 @@
4040
*/
4141
package com.oracle.truffle.api.test.polyglot;
4242

43-
import static org.hamcrest.CoreMatchers.containsString;
44-
import static org.hamcrest.CoreMatchers.not;
4543
import static org.junit.Assert.assertEquals;
46-
import static org.junit.Assert.assertThat;
4744
import static org.junit.Assert.assertTrue;
4845

4946
import java.lang.reflect.InvocationHandler;
@@ -108,16 +105,13 @@ public void explicitToStringAccess() {
108105
@Test
109106
public void lambdaToString() {
110107
// HotSpot lambda classes have names like "pkg.HostClass$$Lambda$69/0x<hex-id>".
111-
// We strip the "/0x<hex-id>" suffix from the name.
112-
// On SVM, they are named "pkg.HostClass$$Lambda$<unique-hex-digest>", which we preserve.
108+
// On SVM, they are named "pkg.HostClass$$Lambda$/0x<unique-hex-digest>", which we preserve.
113109
final Pattern allowedClassNamePattern = Pattern.compile("^[A-Za-z.$\\d]+$");
114110
final Supplier<String> supplier = () -> "ignored";
115111

116112
setupEnv(HostAccess.EXPLICIT);
117113
Value value = context.asValue(supplier);
118114
String string = value.toString();
119-
assertThat(string, not(containsString("/")));
120-
assertThat(string, not(containsString("0x")));
121115
assertTrue(string, allowedClassNamePattern.matcher(string).matches());
122116
}
123117

0 commit comments

Comments
 (0)