Skip to content

Commit 3216752

Browse files
committed
[GR-63802] WasmCallStubNode cannot be cast to WasmDirectCallNode.
PullRequest: graal/20493
2 parents 6da4e92 + ed6c1a5 commit 3216752

File tree

10 files changed

+174
-178
lines changed

10 files changed

+174
-178
lines changed

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/Linker.java

Lines changed: 38 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,6 @@
7373
import java.util.Objects;
7474
import java.util.Set;
7575

76-
import org.graalvm.wasm.Linker.ResolutionDag.CallsiteSym;
77-
import org.graalvm.wasm.Linker.ResolutionDag.CodeEntrySym;
7876
import org.graalvm.wasm.Linker.ResolutionDag.DataSym;
7977
import org.graalvm.wasm.Linker.ResolutionDag.ElemSym;
8078
import org.graalvm.wasm.Linker.ResolutionDag.ExportFunctionSym;
@@ -99,9 +97,6 @@
9997
import org.graalvm.wasm.globals.WasmGlobal;
10098
import org.graalvm.wasm.memory.WasmMemory;
10199
import org.graalvm.wasm.memory.WasmMemoryLibrary;
102-
import org.graalvm.wasm.nodes.WasmCallStubNode;
103-
import org.graalvm.wasm.nodes.WasmDirectCallNode;
104-
import org.graalvm.wasm.nodes.WasmIndirectCallNode;
105100

106101
import com.oracle.truffle.api.CallTarget;
107102
import com.oracle.truffle.api.CompilerAsserts;
@@ -110,7 +105,6 @@
110105
import com.oracle.truffle.api.RootCallTarget;
111106
import com.oracle.truffle.api.TruffleContext;
112107
import com.oracle.truffle.api.exception.AbstractTruffleException;
113-
import com.oracle.truffle.api.nodes.Node;
114108

115109
public class Linker {
116110
public enum LinkState {
@@ -122,6 +116,11 @@ public enum LinkState {
122116

123117
private ResolutionDag resolutionDag;
124118

119+
/**
120+
* Tries to link a module instance and other module instances in the store.
121+
*
122+
* @param instance the module instance that triggered the linking
123+
*/
125124
public void tryLink(WasmInstance instance) {
126125
// The first execution of a WebAssembly call target will trigger the linking of the modules
127126
// that are inside the current context (which will happen behind the call boundary).
@@ -131,22 +130,20 @@ public void tryLink(WasmInstance instance) {
131130
// compilation, and this check will fold away.
132131
// If the code is compiled synchronously, then this check will persist in the compiled code.
133132
// We nevertheless invalidate the compiled code that reaches this point.
134-
if (CompilerDirectives.injectBranchProbability(CompilerDirectives.SLOWPATH_PROBABILITY, instance.isNonLinked() || instance.isLinkFailed())) {
135-
// TODO: Once we support multi-threading, add adequate synchronization here.
133+
if (CompilerDirectives.injectBranchProbability(CompilerDirectives.SLOWPATH_PROBABILITY, !instance.isLinkCompleted())) {
136134
tryLinkOutsidePartialEvaluation(instance);
137-
} else {
138-
assert instance.isLinkCompleted() || instance.isLinkInProgress();
139135
}
140136
}
141137

142138
/**
139+
* Tries to link a module instantiated via the JS API, with imports supplied by an importObject.
140+
*
141+
* @see org.graalvm.wasm.api.WebAssembly#moduleInstantiate(WasmModule, Object)
143142
* @see #tryLinkOutsidePartialEvaluation(WasmInstance, ImportValueSupplier)
144143
*/
145144
public void tryLink(WasmInstance instance, ImportValueSupplier imports) {
146-
if (instance.isNonLinked() || instance.isLinkFailed()) {
145+
if (!instance.isLinkCompleted()) {
147146
tryLinkOutsidePartialEvaluation(instance, imports);
148-
} else {
149-
assert instance.isLinkCompleted() || instance.isLinkInProgress();
150147
}
151148
}
152149

@@ -157,7 +154,7 @@ private static WasmException linkFailedError(WasmInstance instance) {
157154

158155
@CompilerDirectives.TruffleBoundary
159156
private void tryLinkOutsidePartialEvaluation(WasmInstance entryPointInstance) {
160-
tryLink(entryPointInstance, null);
157+
tryLinkOutsidePartialEvaluation(entryPointInstance, null);
161158
}
162159

163160
/**
@@ -172,25 +169,28 @@ private void tryLinkOutsidePartialEvaluation(WasmInstance entryPointInstance) {
172169
*/
173170
@CompilerDirectives.TruffleBoundary
174171
private void tryLinkOutsidePartialEvaluation(WasmInstance entryPointInstance, ImportValueSupplier imports) {
175-
if (entryPointInstance.isLinkFailed()) {
176-
// If the linking of this module failed already, then throw.
177-
throw linkFailedError(entryPointInstance);
178-
}
179-
// Some Truffle configurations allow that the code gets compiled before executing the code.
180-
// We therefore check the link state again.
181-
if (entryPointInstance.isNonLinked()) {
182-
if (resolutionDag == null) {
183-
resolutionDag = new ResolutionDag();
184-
}
185-
final WasmStore store = entryPointInstance.store();
186-
Map<String, WasmInstance> instances = store.moduleInstances();
187-
ArrayList<Throwable> failures = new ArrayList<>();
188-
final int maxStartFunctionIndex = runLinkActions(store, instances, imports, failures);
189-
linkTopologically(store, failures, maxStartFunctionIndex);
190-
assignTypeEquivalenceClasses(store);
191-
resolutionDag = null;
192-
runStartFunctions(instances, failures);
193-
checkFailures(failures);
172+
final WasmStore store = entryPointInstance.store();
173+
synchronized (store) {
174+
var linkState = entryPointInstance.linkState();
175+
if (linkState == LinkState.failed) {
176+
// If the linking of this module failed already, then throw.
177+
throw linkFailedError(entryPointInstance);
178+
}
179+
// Some Truffle configurations allow the code to be compiled before executing the code.
180+
// We therefore check the link state again.
181+
if (linkState == LinkState.nonLinked) {
182+
if (resolutionDag == null) {
183+
resolutionDag = new ResolutionDag();
184+
}
185+
Map<String, WasmInstance> instances = store.moduleInstances();
186+
ArrayList<Throwable> failures = new ArrayList<>();
187+
final int maxStartFunctionIndex = runLinkActions(store, instances, imports, failures);
188+
linkTopologically(store, failures, maxStartFunctionIndex);
189+
assignTypeEquivalenceClasses(store);
190+
resolutionDag = null;
191+
runStartFunctions(instances, failures);
192+
checkFailures(failures);
193+
}
194194
}
195195
}
196196

@@ -244,7 +244,9 @@ private static void assignTypeEquivalenceClasses(WasmStore store) {
244244
}
245245

246246
private static void assignTypeEquivalenceClasses(WasmModule module, WasmLanguage language) {
247-
synchronized (module) {
247+
var lock = module.getLock();
248+
lock.lock();
249+
try {
248250
if (module.isParsed()) {
249251
return;
250252
}
@@ -259,6 +261,8 @@ private static void assignTypeEquivalenceClasses(WasmModule module, WasmLanguage
259261
function.setTypeEquivalenceClass(symtab.equivalenceClass(function.typeIndex()));
260262
}
261263
module.setParsed();
264+
} finally {
265+
lock.unlock();
262266
}
263267
}
264268

@@ -462,33 +466,6 @@ void resolveFunctionExport(WasmModule module, int functionIndex, String exported
462466
resolutionDag.resolveLater(new ExportFunctionSym(module.name(), exportedFunctionName), dependencies, NO_RESOLVE_ACTION);
463467
}
464468

465-
public void resolveCallNode(Node[] callNodes, WasmInstance instance, int callNodeIndex, int bytecodeOffset) {
466-
Node unresolvedCallNode = callNodes[callNodeIndex];
467-
if (unresolvedCallNode instanceof WasmCallStubNode) {
468-
final WasmFunction function = ((WasmCallStubNode) unresolvedCallNode).function();
469-
final CallTarget target = instance.target(function.index());
470-
callNodes[callNodeIndex] = WasmDirectCallNode.create(target, bytecodeOffset);
471-
} else {
472-
assert unresolvedCallNode instanceof WasmIndirectCallNode : unresolvedCallNode;
473-
}
474-
}
475-
476-
public void resolveCallsite(WasmInstance instance, Node[] callNodes, int instructionOffset, int controlTableOffset, int bytecodeOffset, WasmFunction function) {
477-
final Runnable resolveAction = () -> resolveCallNode(callNodes, instance, controlTableOffset, bytecodeOffset);
478-
final Sym[] dependencies = new Sym[]{
479-
function.isImported()
480-
? new ImportFunctionSym(instance.name(), function.importDescriptor(), function.index())
481-
: new CodeEntrySym(instance.name(), function.index())};
482-
resolutionDag.resolveLater(new CallsiteSym(instance.name(), instructionOffset, controlTableOffset), dependencies, resolveAction);
483-
}
484-
485-
void resolveCodeEntry(WasmModule module, int functionIndex) {
486-
if (resolutionDag == null) {
487-
resolutionDag = new ResolutionDag();
488-
}
489-
resolutionDag.resolveLater(new CodeEntrySym(module.name(), functionIndex), ResolutionDag.NO_DEPENDENCIES, NO_RESOLVE_ACTION);
490-
}
491-
492469
void resolveMemoryImport(WasmStore store, WasmInstance instance, ImportDescriptor importDescriptor, int memoryIndex, long declaredMinSize, long declaredMaxSize, boolean typeIndex64,
493470
boolean shared, ImportValueSupplier imports) {
494471
final String importedModuleName = importDescriptor.moduleName();
@@ -1160,64 +1137,6 @@ public boolean equals(Object object) {
11601137
}
11611138
}
11621139

1163-
static class CallsiteSym extends Sym {
1164-
final int instructionOffset;
1165-
final int controlTableOffset;
1166-
1167-
CallsiteSym(String moduleName, int instructionOffset, int controlTableOffset) {
1168-
super(moduleName);
1169-
this.instructionOffset = instructionOffset;
1170-
this.controlTableOffset = controlTableOffset;
1171-
}
1172-
1173-
@Override
1174-
public String toString() {
1175-
return String.format(Locale.ROOT, "(callsite %d at %d in %s)", controlTableOffset, instructionOffset, moduleName);
1176-
}
1177-
1178-
@Override
1179-
public int hashCode() {
1180-
return moduleName.hashCode() ^ instructionOffset ^ (controlTableOffset << 16);
1181-
}
1182-
1183-
@Override
1184-
public boolean equals(Object object) {
1185-
if (!(object instanceof CallsiteSym)) {
1186-
return false;
1187-
}
1188-
final CallsiteSym that = (CallsiteSym) object;
1189-
return this.instructionOffset == that.instructionOffset && this.controlTableOffset == that.controlTableOffset && this.moduleName.equals(that.moduleName);
1190-
}
1191-
}
1192-
1193-
static class CodeEntrySym extends Sym {
1194-
final int functionIndex;
1195-
1196-
CodeEntrySym(String moduleName, int functionIndex) {
1197-
super(moduleName);
1198-
this.functionIndex = functionIndex;
1199-
}
1200-
1201-
@Override
1202-
public String toString() {
1203-
return String.format(Locale.ROOT, "(code entry at %d in %s)", functionIndex, moduleName);
1204-
}
1205-
1206-
@Override
1207-
public int hashCode() {
1208-
return moduleName.hashCode() ^ functionIndex;
1209-
}
1210-
1211-
@Override
1212-
public boolean equals(Object object) {
1213-
if (!(object instanceof CodeEntrySym)) {
1214-
return false;
1215-
}
1216-
final CodeEntrySym that = (CodeEntrySym) object;
1217-
return this.functionIndex == that.functionIndex && this.moduleName.equals(that.moduleName);
1218-
}
1219-
}
1220-
12211140
static class ImportMemorySym extends Sym {
12221141
final ImportDescriptor importDescriptor;
12231142
final int memoryIndex;

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/RuntimeState.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public abstract class RuntimeState {
108108
*/
109109
private final int droppedDataInstanceOffset;
110110

111-
@CompilationFinal private Linker.LinkState linkState;
111+
@CompilationFinal private volatile Linker.LinkState linkState;
112112

113113
@CompilationFinal private int startFunctionIndex;
114114

@@ -187,6 +187,10 @@ public WasmContext context() {
187187
return store().context();
188188
}
189189

190+
public Linker.LinkState linkState() {
191+
return linkState;
192+
}
193+
190194
public boolean isNonLinked() {
191195
return linkState == Linker.LinkState.nonLinked;
192196
}

0 commit comments

Comments
 (0)