Skip to content

Commit 006d13e

Browse files
committed
compiler test option reuse - support content equal maps
1 parent fd9f9a1 commit 006d13e

File tree

2 files changed

+136
-4
lines changed

2 files changed

+136
-4
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.core.test;
26+
27+
import java.util.HashMap;
28+
29+
import org.graalvm.collections.Pair;
30+
import org.junit.Assert;
31+
import org.junit.Test;
32+
33+
import jdk.graal.compiler.core.phases.HighTier;
34+
import jdk.graal.compiler.options.OptionValues;
35+
import jdk.vm.ci.code.InstalledCode;
36+
import jdk.vm.ci.meta.ResolvedJavaMethod;
37+
38+
/**
39+
* Tests that the cache used by the compiler tests properly handles different options.
40+
*/
41+
public class CacheResetTest extends GraalCompilerTest {
42+
43+
public static void snippet() {
44+
// do nothing
45+
}
46+
47+
private static final String SNIPPET_NAME = "snippet";
48+
49+
@Test
50+
public void testSameOptionsReuse() {
51+
final ResolvedJavaMethod installedCodeOwner = getResolvedJavaMethod(SNIPPET_NAME);
52+
53+
OptionValues opt = new OptionValues(getInitialOptions(), HighTier.Options.Inline, true);
54+
55+
test(opt, SNIPPET_NAME);
56+
InstalledCode firstInstalled = getCachedCode(installedCodeOwner);
57+
58+
test(opt, SNIPPET_NAME);
59+
InstalledCode secondInstalled = getCachedCode(installedCodeOwner);
60+
61+
assert firstInstalled.isValid();
62+
assert secondInstalled.isValid();
63+
64+
Assert.assertEquals(firstInstalled.getStart(), secondInstalled.getStart());
65+
}
66+
67+
@Test
68+
public void testSameOptionsDeepReuse() {
69+
final ResolvedJavaMethod installedCodeOwner = getResolvedJavaMethod(SNIPPET_NAME);
70+
71+
OptionValues opt = new OptionValues(getInitialOptions(), HighTier.Options.Inline, true);
72+
test(opt, SNIPPET_NAME);
73+
InstalledCode firstInstalled = getCachedCode(installedCodeOwner);
74+
75+
OptionValues opt1 = new OptionValues(getInitialOptions(), HighTier.Options.Inline, true);
76+
test(opt1, SNIPPET_NAME);
77+
InstalledCode secondInstalled = getCachedCode(installedCodeOwner);
78+
79+
assert firstInstalled.isValid();
80+
assert secondInstalled.isValid();
81+
82+
Assert.assertEquals(firstInstalled.getStart(), secondInstalled.getStart());
83+
}
84+
85+
private static InstalledCode getCachedCode(ResolvedJavaMethod method) {
86+
HashMap<ResolvedJavaMethod, Pair<OptionValues, InstalledCode>> tlCache = cache.get();
87+
Pair<OptionValues, InstalledCode> cached = tlCache.get(method);
88+
return cached.getRight();
89+
}
90+
91+
@Test
92+
public void testDifferentOptionsNoReuse() {
93+
final ResolvedJavaMethod installedCodeOwner = getResolvedJavaMethod(SNIPPET_NAME);
94+
95+
OptionValues opt = new OptionValues(getInitialOptions(), HighTier.Options.Inline, true);
96+
test(opt, SNIPPET_NAME);
97+
InstalledCode firstInstalled = getCachedCode(installedCodeOwner);
98+
99+
OptionValues opt1 = new OptionValues(getInitialOptions(), HighTier.Options.Inline, false);
100+
test(opt1, SNIPPET_NAME);
101+
InstalledCode secondInstalled = getCachedCode(installedCodeOwner);
102+
103+
assert firstInstalled.isValid();
104+
assert secondInstalled.isValid();
105+
106+
Assert.assertNotEquals(firstInstalled.getStart(), secondInstalled.getStart());
107+
}
108+
}

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import java.util.function.Supplier;
6161

6262
import org.graalvm.collections.Pair;
63+
import org.graalvm.collections.UnmodifiableEconomicMap;
6364
import org.junit.After;
6465
import org.junit.Assert;
6566
import org.junit.Before;
@@ -130,6 +131,7 @@
130131
import jdk.graal.compiler.nodes.spi.ProfileProvider;
131132
import jdk.graal.compiler.nodes.spi.Replacements;
132133
import jdk.graal.compiler.nodes.virtual.VirtualObjectNode;
134+
import jdk.graal.compiler.options.OptionKey;
133135
import jdk.graal.compiler.options.OptionValues;
134136
import jdk.graal.compiler.phases.BasePhase;
135137
import jdk.graal.compiler.phases.OptimisticOptimizations;
@@ -396,7 +398,7 @@ protected LIRSuites createLIRSuites(OptionValues opts) {
396398
return ret;
397399
}
398400

399-
private static final ThreadLocal<HashMap<ResolvedJavaMethod, Pair<OptionValues, InstalledCode>>> cache = ThreadLocal.withInitial(HashMap::new);
401+
protected static final ThreadLocal<HashMap<ResolvedJavaMethod, Pair<OptionValues, InstalledCode>>> cache = ThreadLocal.withInitial(HashMap::new);
400402

401403
/**
402404
* Reset the entire {@linkplain #cache} of {@linkplain InstalledCode}. Additionally, invalidate
@@ -1138,9 +1140,9 @@ protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, Str
11381140
Pair<OptionValues, InstalledCode> cached = tlCache.get(installedCodeOwner);
11391141
if (cached != null) {
11401142
// Reuse the cached code is the it's still valid and the same options were used for
1141-
// the compilation.
1142-
if (cached.getRight().isValid() && options.getMap().equals(cached.getLeft().getMap())) {
1143-
GraalError.unimplemented("map value compare");
1143+
// the compilation. We use a deep equals for the option values to catch cases where
1144+
// users create new option values but with the same values.
1145+
if (cached.getRight().isValid() && (options.getMap().equals(cached.getLeft().getMap()) || optionsMapDeepEquals(options.getMap(), cached.getLeft().getMap()))) {
11441146
return cached.getRight();
11451147
} else {
11461148
tlCache.remove(installedCodeOwner);
@@ -1195,6 +1197,28 @@ protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, Str
11951197
throw GraalError.shouldNotReachHere("Bailout limit reached"); // ExcludeFromJacocoGeneratedReport
11961198
}
11971199

1200+
private static boolean optionsMapDeepEquals(UnmodifiableEconomicMap<OptionKey<?>, Object> map1, UnmodifiableEconomicMap<OptionKey<?>, Object> map2) {
1201+
if (map1.size() != map2.size()) {
1202+
return false;
1203+
}
1204+
var c1 = map1.getEntries();
1205+
var c2 = map2.getEntries();
1206+
while (c1.advance() && c2.advance()) {
1207+
Object c1Key = c1.getKey();
1208+
Object c2Key = c2.getKey();
1209+
if (!c1Key.equals(c2Key)) {
1210+
return false;
1211+
}
1212+
Object c1Val = c1.getValue();
1213+
Object c2Val = c2.getValue();
1214+
if (!c1Val.equals(c2Val)) {
1215+
return false;
1216+
}
1217+
}
1218+
1219+
return true;
1220+
}
1221+
11981222
/**
11991223
* Used to produce a graph for a method about to be compiled by
12001224
* {@link #compile(ResolvedJavaMethod, StructuredGraph)} if the second parameter to that method

0 commit comments

Comments
 (0)