Skip to content

Commit 6cf69ff

Browse files
committed
Improve replayability with different compiler options.
1 parent 4dc6019 commit 6cf69ff

16 files changed

+350
-252
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public GlobalMetrics getMetricValues() {
172172
throw new GraalError("No backend available for host architecture \"%s\"", hostArchitecture);
173173
}
174174
if (replayCompilationSupport != null) {
175-
factory = replayCompilationSupport.decorateBackendFactory(factory);
175+
factory = replayCompilationSupport.decorateBackendFactory(factory, jvmciRuntime);
176176
}
177177
hostBackend = registerBackend(factory.createBackend(this, compilerConfiguration, jvmciRuntime, null));
178178
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import jdk.graal.compiler.graph.NodeMap;
6363
import jdk.graal.compiler.graph.NodeSourcePosition;
6464
import jdk.graal.compiler.hotspot.meta.HotSpotProviders;
65+
import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedObjectTypeProxy;
6566
import jdk.graal.compiler.hotspot.stubs.AbstractForeignCallStub;
6667
import jdk.graal.compiler.hotspot.stubs.ForeignCallStub;
6768
import jdk.graal.compiler.hotspot.word.HotSpotWordTypes;
@@ -532,6 +533,8 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug, Economic
532533
lookupSnippetType(SnippetTemplate.SnippetInfo.class);
533534
lookupSnippetType(ForeignCallStub.class);
534535
lookupSnippetType(HotSpotSpeculationLog.HotSpotSpeculation.class);
536+
// Needed to pass constant type parameters to snippets when recording/replaying.
537+
lookupSnippetType(HotSpotResolvedObjectTypeProxy.class);
535538

536539
registerAbstractForeignCallStubInfo();
537540

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java

Lines changed: 119 additions & 82 deletions
Large diffs are not rendered by default.

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
3333
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
3434
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
35+
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
3536
import jdk.vm.ci.meta.Constant;
3637
import jdk.vm.ci.meta.JavaConstant;
3738
import jdk.vm.ci.meta.MemoryAccessProvider;
@@ -48,11 +49,12 @@ class HotSpotProxyBackendFactory implements HotSpotBackendFactoryDecorators {
4849

4950
private final ReplayCompilationSupport replayCompilationSupport;
5051

51-
private MetaAccessProvider metaAccessProviderProxy;
52+
private final HotSpotJVMCIRuntime jvmciRuntime;
5253

53-
HotSpotProxyBackendFactory(CompilationProxies proxies, ReplayCompilationSupport replayCompilationSupport) {
54+
HotSpotProxyBackendFactory(CompilationProxies proxies, ReplayCompilationSupport replayCompilationSupport, HotSpotJVMCIRuntime jvmciRuntime) {
5455
this.proxies = proxies;
5556
this.replayCompilationSupport = replayCompilationSupport;
57+
this.jvmciRuntime = jvmciRuntime;
5658
}
5759

5860
@Override
@@ -62,14 +64,13 @@ public void afterJVMCIProvidersCreated() {
6264
* mirrors. We must identify the local mirrors before initialization continues to avoid
6365
* creating duplicate proxies for equivalent local mirrors.
6466
*/
65-
replayCompilationSupport.findLocalMirrors();
67+
replayCompilationSupport.findLocalMirrors(jvmciRuntime);
6668
}
6769

6870
@Override
6971
public MetaAccessProvider decorateMetaAccessProvider(MetaAccessProvider metaAccess) {
7072
// Do not record snippet types in libgraal - decorate the JVMCI meta access only.
71-
metaAccessProviderProxy = (MetaAccessProvider) proxies.proxify(metaAccess);
72-
return new HotSpotSnippetMetaAccessProvider(metaAccessProviderProxy);
73+
return new HotSpotSnippetMetaAccessProvider((MetaAccessProvider) proxies.proxify(metaAccess));
7374
}
7475

7576
@Override
@@ -79,7 +80,7 @@ public HotSpotConstantReflectionProvider decorateConstantReflectionProvider(HotS
7980
return new DecoratedConstantReflectionProvider(delegate);
8081
}
8182

82-
private final class DecoratedConstantReflectionProvider extends HotSpotConstantReflectionProvider {
83+
private static final class DecoratedConstantReflectionProvider extends HotSpotConstantReflectionProvider {
8384
private final HotSpotConstantReflectionProvider delegate;
8485

8586
private DecoratedConstantReflectionProvider(HotSpotConstantReflectionProvider delegate) {
@@ -142,7 +143,7 @@ public ResolvedJavaType asJavaType(Constant constant) {
142143
* Avoid recording an operation with the snippet constant, which is not
143144
* serializable.
144145
*/
145-
return metaAccessProviderProxy.lookupJavaType(objectConstant.asObject(Object.class).getClass());
146+
return objectConstant.asObject(ResolvedJavaType.class);
146147
} else {
147148
return delegate.asJavaType(constant);
148149
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java

Lines changed: 69 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,20 @@ private interface RecursiveDeserializer {
144144
Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException;
145145

146146
Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException;
147+
148+
/**
149+
* Sets the {@link Architecture} parsed by this deserializer.
150+
*
151+
* @param arch the architecture
152+
*/
153+
void setArchitecture(Architecture arch);
154+
155+
/**
156+
* Gets the {@link Architecture} parsed by this deserializer.
157+
*
158+
* @return the architecture
159+
*/
160+
Architecture getArchitecture();
147161
}
148162

149163
private sealed interface ObjectSerializer {
@@ -805,7 +819,6 @@ public Object deserialize(EconomicMap<String, Object> json, RecursiveDeserialize
805819
}
806820

807821
private static final class RegisterSerializer implements ObjectSerializer {
808-
809822
@Override
810823
public Class<?> clazz() {
811824
return Register.class;
@@ -820,20 +833,17 @@ public String tag() {
820833
public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException {
821834
Register register = (Register) instance;
822835
objectBuilder.append("number", register.number);
823-
objectBuilder.append("name", register.name);
824-
objectBuilder.append("encoding", register.encoding);
825-
objectBuilder.append("catName", register.getRegisterCategory().toString());
826-
objectBuilder.append("containsRef", register.mayContainReference());
827836
}
828837

829838
@Override
830-
public Object deserialize(EconomicMap<String, Object> json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) {
839+
public Object deserialize(EconomicMap<String, Object> json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException {
831840
int number = (int) json.get("number");
832-
String name = (String) json.get("name");
833-
int encoding = (int) json.get("encoding");
834-
String catName = (String) json.get("catName");
835-
boolean containsRef = (boolean) json.get("containsRef");
836-
return new Register(number, encoding, name, new Register.RegisterCategory(catName, containsRef));
841+
for (Register register : deserializer.getArchitecture().getRegisters()) {
842+
if (register.number == number) {
843+
return register;
844+
}
845+
}
846+
throw new DeserializationException(this, json, "Register not found");
837847
}
838848
}
839849

@@ -1687,12 +1697,14 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
16871697
public Object deserialize(EconomicMap<String, Object> json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException {
16881698
String name = (String) json.get("name");
16891699
EnumSet<?> features = (EnumSet<?>) deserializer.deserialize(json.get("features"), proxyFactory);
1690-
return switch (name) {
1700+
Architecture architecture = switch (name) {
16911701
case "AMD64" -> new AMD64((EnumSet<AMD64.CPUFeature>) features);
16921702
case "riscv64" -> new RISCV64((EnumSet<RISCV64.CPUFeature>) features);
16931703
case "aarch64" -> new AArch64((EnumSet<AArch64.CPUFeature>) features);
16941704
default -> throw new IllegalStateException("Unexpected value: " + name);
16951705
};
1706+
deserializer.setArchitecture(architecture);
1707+
return architecture;
16961708
}
16971709
}
16981710

@@ -1932,41 +1944,55 @@ public void dump(RecordedCompilationUnit compilationUnit, JsonWriter writer) thr
19321944
recursiveSerializer.serialize(compilationUnit, writer.valueBuilder(), RecordedCompilationUnitSerializer.TAG);
19331945
}
19341946

1935-
private final RecursiveDeserializer recursiveDeserializer = new RecursiveDeserializer() {
1936-
@Override
1937-
@SuppressWarnings("unchecked")
1938-
public Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException {
1939-
if (json instanceof EconomicMap<?, ?>) {
1940-
EconomicMap<String, Object> map = (EconomicMap<String, Object>) json;
1941-
String tag = (String) map.get("tag");
1942-
if (tag == null) {
1943-
throw new IllegalArgumentException("The JSON map does not contain a tag: " + map);
1944-
}
1945-
ObjectSerializer deserializer = tagSerializers.get(tag);
1946-
if (deserializer == null) {
1947-
throw new IllegalArgumentException("No deserializer registered for tag " + tag);
1947+
private RecursiveDeserializer createRecursiveDeserializer() {
1948+
return new RecursiveDeserializer() {
1949+
@Override
1950+
@SuppressWarnings("unchecked")
1951+
public Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException {
1952+
if (json instanceof EconomicMap<?, ?>) {
1953+
EconomicMap<String, Object> map = (EconomicMap<String, Object>) json;
1954+
String tag = (String) map.get("tag");
1955+
if (tag == null) {
1956+
throw new IllegalArgumentException("The JSON map does not contain a tag: " + map);
1957+
}
1958+
ObjectSerializer deserializer = tagSerializers.get(tag);
1959+
if (deserializer == null) {
1960+
throw new IllegalArgumentException("No deserializer registered for tag " + tag);
1961+
}
1962+
return deserializer.deserialize(map, this, proxyFactory);
1963+
} else {
1964+
return json;
19481965
}
1949-
return deserializer.deserialize(map, this, proxyFactory);
1950-
} else {
1951-
return json;
19521966
}
1953-
}
19541967

1955-
@Override
1956-
@SuppressWarnings("unchecked")
1957-
public Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException {
1958-
if (json instanceof EconomicMap<?, ?>) {
1959-
EconomicMap<String, Object> map = (EconomicMap<String, Object>) json;
1960-
ObjectSerializer deserializer = tagSerializers.get(tag);
1961-
if (deserializer == null) {
1962-
throw new IllegalArgumentException("No deserializer registered for tag " + tag);
1968+
@Override
1969+
@SuppressWarnings("unchecked")
1970+
public Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException {
1971+
if (json instanceof EconomicMap<?, ?>) {
1972+
EconomicMap<String, Object> map = (EconomicMap<String, Object>) json;
1973+
ObjectSerializer deserializer = tagSerializers.get(tag);
1974+
if (deserializer == null) {
1975+
throw new IllegalArgumentException("No deserializer registered for tag " + tag);
1976+
}
1977+
return deserializer.deserialize(map, this, proxyFactory);
1978+
} else {
1979+
throw new IllegalArgumentException("Expected a map.");
19631980
}
1964-
return deserializer.deserialize(map, this, proxyFactory);
1965-
} else {
1966-
throw new IllegalArgumentException("Expected a map.");
19671981
}
1968-
}
1969-
};
1982+
1983+
private Architecture architecture;
1984+
1985+
@Override
1986+
public void setArchitecture(Architecture arch) {
1987+
architecture = arch;
1988+
}
1989+
1990+
@Override
1991+
public Architecture getArchitecture() {
1992+
return architecture;
1993+
}
1994+
};
1995+
}
19701996

19711997
/**
19721998
* Loads a recorded compilation unit from the given reader.
@@ -1979,6 +2005,6 @@ public Object deserialize(Object json, ProxyFactory proxyFactory, String tag) th
19792005
*/
19802006
public RecordedCompilationUnit load(Reader source, ProxyFactory proxyFactory) throws IOException, DeserializationException {
19812007
JsonParser parser = new JsonParser(source);
1982-
return (RecordedCompilationUnit) recursiveDeserializer.deserialize(parser.parse(), proxyFactory, RecordedCompilationUnitSerializer.TAG);
2008+
return (RecordedCompilationUnit) createRecursiveDeserializer().deserialize(parser.parse(), proxyFactory, RecordedCompilationUnitSerializer.TAG);
19832009
}
19842010
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@
4949
import jdk.graal.compiler.options.OptionType;
5050
import jdk.graal.compiler.options.OptionValues;
5151
import jdk.vm.ci.code.TargetDescription;
52+
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
53+
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
5254
import jdk.vm.ci.meta.Constant;
55+
import jdk.vm.ci.meta.MetaAccessProvider;
5356

5457
//JaCoCo Exclude
5558

@@ -66,7 +69,7 @@
6669
* memory usage low, which is important when replaying many compilations on libgraal and
6770
* benchmarking compile time.
6871
* <p>
69-
* It is necessary to call {@link #findLocalMirrors()} after the operations are loaded and JVMCI
72+
* It is necessary to call {@link #findLocalMirrors} after the operations are loaded and JVMCI
7073
* providers are created. The local mirrors may be required during a replayed compilation to query
7174
* information from the local VM, which is needed for snippet parsing.
7275
*
@@ -143,6 +146,11 @@ public void setLocalMirror(Object newLocalMirror) {
143146
*/
144147
private final EconomicMap<Class<?>, Object> singletonObjects;
145148

149+
/**
150+
* The host meta access provider.
151+
*/
152+
private MetaAccessProvider hostMetaAccess;
153+
146154
/**
147155
* Proxifies and unproxifies composite objects.
148156
*/
@@ -330,14 +338,17 @@ private static Object intern(Object object, EconomicMap<Object, Object> internPo
330338
* <p>
331339
* During snippet parsing, the compiler may discover a JVMCI object which has no matching proxy.
332340
* For such objects, local-only proxies are created using {@link #proxify(Object)}.
341+
*
342+
* @param jvmciRuntime the JVMCI runtime
333343
*/
334-
public void findLocalMirrors() {
344+
public void findLocalMirrors(HotSpotJVMCIRuntime jvmciRuntime) {
345+
HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class);
335346
var cursor = createdProxies.getEntries();
336347
while (cursor.advance()) {
337348
CompilationProxy proxy = cursor.getKey();
338349
CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(proxy);
339350
if (registration.mirrorLocator() != null) {
340-
Object localMirror = registration.mirrorLocator().findLocalMirror(proxy, singletonObjects);
351+
Object localMirror = registration.mirrorLocator().findLocalMirror(proxy, hostMetaAccess, constantReflection, jvmciRuntime);
341352
if (localMirror != null) {
342353
Object previousProxy = localMirrorToProxy.put(localMirror, proxy);
343354
GraalError.guarantee(previousProxy == null, "there must be at most one proxy instance for an object");
@@ -402,6 +413,9 @@ public CompilationProxy proxify(Object input) {
402413
localMirrorToProxy.put(input, proxy);
403414
if (registration.singleton()) {
404415
singletonObjects.put(registration.clazz(), input);
416+
if (input instanceof MetaAccessProvider metaAccess) {
417+
hostMetaAccess = metaAccess;
418+
}
405419
}
406420
return proxy;
407421
}
@@ -461,13 +475,13 @@ public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration r
461475
if (proxyInfo.localMirror == null) {
462476
CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method);
463477
if (handler != null) {
464-
return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, singletonObjects));
478+
return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, hostMetaAccess));
465479
}
466480
}
467481
GraalError.guarantee(proxyInfo.localMirror != null, "a proxy with passthrough strategy must have a local mirror or fallback handler");
468482
return callback.invoke(proxyInfo.localMirror, args);
469483
} else if (strategy == CompilerInterfaceDeclarations.MethodStrategy.DefaultValue) {
470-
return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, singletonObjects));
484+
return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, hostMetaAccess));
471485
}
472486
Object result = findResult(proxyInfo, method, args);
473487
if (result != SpecialResultMarker.NO_RESULT_MARKER) {
@@ -495,7 +509,7 @@ public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration r
495509
}
496510
CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method);
497511
if (handler != null) {
498-
return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, singletonObjects));
512+
return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, hostMetaAccess));
499513
}
500514
if (args != null) {
501515
for (Object arg : args) {
@@ -507,7 +521,7 @@ public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration r
507521
if (divergenceIsFailure) {
508522
failOnDivergence(proxy, proxyInfo, method, args);
509523
}
510-
return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, singletonObjects));
524+
return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, hostMetaAccess));
511525
}
512526
});
513527
if (registration.singleton()) {

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ public static ExitStatus run(String[] args, PrintStream out) {
181181
codeHash = codeHash * 31 + Arrays.hashCode(replayResult.replayedArtifacts().result().getTargetCode());
182182
} catch (Exception e) {
183183
out.println("Replay failed: " + e);
184+
e.printStackTrace(out);
184185
return ExitStatus.Failure;
185186
}
186187
}
@@ -206,6 +207,7 @@ public static ExitStatus run(String[] args, PrintStream out) {
206207
task.setFailureReason(failure.getMessage());
207208
} catch (Exception e) {
208209
out.println("Replay failed: " + e);
210+
e.printStackTrace(out);
209211
return ExitStatus.Failure;
210212
}
211213
}

0 commit comments

Comments
 (0)