Skip to content

Commit 85fdc77

Browse files
committed
Parent completion ordering DFS invariant extension.
1 parent 428c3ad commit 85fdc77

File tree

3 files changed

+62
-29
lines changed

3 files changed

+62
-29
lines changed

graal-js/src/com.oracle.truffle.js.parser/src/com/oracle/truffle/js/parser/GraalJSEvaluator.java

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import java.util.List;
5757
import java.util.Map;
5858
import java.util.Set;
59+
import java.util.TreeSet;
5960
import java.util.function.Supplier;
6061

6162
import com.oracle.js.parser.ir.Expression;
@@ -793,10 +794,13 @@ private int innerModuleEvaluation(JSRealm realm, JSModuleRecord moduleRecord, De
793794
requiredModule.appendAsyncParentModules(moduleRecord);
794795
}
795796
}
796-
if (moduleRecord.getPendingAsyncDependencies() > 0) {
797+
if (moduleRecord.getPendingAsyncDependencies() > 0 || moduleRecord.isTopLevelAsync()) {
798+
assert !moduleRecord.isAsyncEvaluating() && moduleRecord.getAsyncEvaluatingOrder() == 0;
797799
moduleRecord.setAsyncEvaluating(true);
798-
} else if (moduleRecord.isTopLevelAsync()) {
799-
moduleAsyncExecution(realm, moduleRecord);
800+
moduleRecord.setAsyncEvaluatingOrder(realm.nextAsyncEvaluationOrder());
801+
if (moduleRecord.getPendingAsyncDependencies() == 0) {
802+
moduleAsyncExecution(realm, moduleRecord);
803+
}
800804
} else {
801805
Object result = moduleExecution(realm, moduleRecord, null);
802806
moduleRecord.setExecutionResult(result);
@@ -821,7 +825,6 @@ private static void moduleAsyncExecution(JSRealm realm, JSModuleRecord module) {
821825
// ExecuteAsyncModule ( module )
822826
assert module.getStatus() == Status.Evaluating || module.getStatus() == Status.Evaluated;
823827
assert module.isTopLevelAsync();
824-
module.setAsyncEvaluating(true);
825828
PromiseCapabilityRecord capability = NewPromiseCapabilityNode.createDefault(realm);
826829
DynamicObject onFulfilled = createCallAsyncModuleFulfilled(realm, module);
827830
DynamicObject onRejected = createCallAsyncModuleRejected(realm, module);
@@ -885,42 +888,58 @@ public Object execute(VirtualFrame frame) {
885888
return JSFunctionData.createCallOnly(context, callTarget, 1, "");
886889
}
887890

888-
@TruffleBoundary
889-
private static Object asyncModuleExecutionFulfilled(JSRealm realm, JSModuleRecord module, Object dynamicImportResolutionResult) {
891+
private static void gatherAvailableAncestors(JSModuleRecord module, Set<JSModuleRecord> execList) {
892+
// GatherAvailableAncestors ( module, execList )
890893
assert module.getStatus() == Status.Evaluated;
891-
if (!module.isAsyncEvaluating()) {
892-
assert module.getEvaluationError() != null;
893-
return Undefined.instance;
894-
}
895-
assert module.getEvaluationError() == null;
896-
module.setAsyncEvaluating(false);
897894
for (JSModuleRecord m : module.getAsyncParentModules()) {
898-
if (module.getDFSIndex() != module.getDFSAncestorIndex()) {
899-
assert m.getDFSAncestorIndex() <= module.getDFSAncestorIndex();
900-
}
901-
m.decPendingAsyncDependencies();
902-
if (m.getPendingAsyncDependencies() == 0 && m.getEvaluationError() == null) {
895+
if (!execList.contains(m) && getAsyncCycleRoot(m).getEvaluationError() == null) {
896+
assert m.getEvaluationError() == null;
903897
assert m.isAsyncEvaluating();
904-
JSModuleRecord cycleRoot = getAsyncCycleRoot(m);
905-
if (cycleRoot.getEvaluationError() != null) {
906-
return Undefined.instance;
907-
}
908-
if (m.isTopLevelAsync()) {
909-
moduleAsyncExecution(realm, m);
910-
} else {
911-
try {
912-
moduleExecution(realm, m, null);
913-
asyncModuleExecutionFulfilled(realm, m, dynamicImportResolutionResult);
914-
} catch (Exception e) {
915-
asyncModuleExecutionRejected(realm, m, e);
898+
assert m.getPendingAsyncDependencies() > 0;
899+
m.decPendingAsyncDependencies();
900+
if (m.getPendingAsyncDependencies() == 0) {
901+
execList.add(m);
902+
if (!m.isTopLevelAsync()) {
903+
gatherAvailableAncestors(m, execList);
916904
}
917905
}
918906
}
919907
}
908+
}
909+
910+
@TruffleBoundary
911+
private static Object asyncModuleExecutionFulfilled(JSRealm realm, JSModuleRecord module, Object dynamicImportResolutionResult) {
912+
assert module.isAsyncEvaluating();
913+
assert module.getEvaluationError() == null;
914+
module.setAsyncEvaluating(false);
920915
if (module.getTopLevelCapability() != null) {
921916
assert module.getDFSIndex() == module.getDFSAncestorIndex();
922917
JSFunction.call(JSArguments.create(Undefined.instance, module.getTopLevelCapability().getResolve(), dynamicImportResolutionResult));
923918
}
919+
Set<JSModuleRecord> execList = new TreeSet<>(new Comparator<JSModuleRecord>() {
920+
@Override
921+
public int compare(JSModuleRecord o1, JSModuleRecord o2) {
922+
return Long.compare(o1.getAsyncEvaluatingOrder(), o2.getAsyncEvaluatingOrder());
923+
}
924+
});
925+
gatherAvailableAncestors(module, execList);
926+
for (JSModuleRecord m : execList) {
927+
if (!m.isAsyncEvaluating()) {
928+
assert m.getEvaluationError() != null;
929+
} else if (m.isTopLevelAsync()) {
930+
moduleAsyncExecution(realm, m);
931+
} else {
932+
try {
933+
moduleExecution(realm, m, null);
934+
m.setAsyncEvaluating(false);
935+
if (m.getTopLevelCapability() != null) {
936+
JSFunction.call(JSArguments.create(Undefined.instance, m.getTopLevelCapability().getResolve(), dynamicImportResolutionResult));
937+
}
938+
} catch (Exception e) {
939+
asyncModuleExecutionRejected(realm, m, e);
940+
}
941+
}
942+
}
924943
return Undefined.instance;
925944
}
926945

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/JSRealm.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ public class JSRealm {
441441

442442
private final JSConsoleUtil consoleUtil;
443443
private JSModuleLoader moduleLoader;
444+
private long lastAsyncEvaluationOrder;
444445

445446
/**
446447
* ECMA2017 8.7 Agent object.
@@ -2755,4 +2756,8 @@ public void closeInnerContexts() {
27552756
}
27562757
}
27572758

2759+
public long nextAsyncEvaluationOrder() {
2760+
return ++lastAsyncEvaluationOrder;
2761+
}
2762+
27582763
}

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/objects/JSModuleRecord.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ public void setUninstantiated() {
243243
private final boolean async;
244244
// [[AsyncEvaluating]]
245245
private boolean asyncEvaluating = false;
246+
private long asyncEvaluatingOrder;
246247
// [[TopLevelCapability]]
247248
private PromiseCapabilityRecord topLevelPromiseCapability = null;
248249
// [[AsyncParentModules]]
@@ -295,6 +296,14 @@ public void setAsyncEvaluating(boolean value) {
295296
asyncEvaluating = value;
296297
}
297298

299+
public void setAsyncEvaluatingOrder(long order) {
300+
asyncEvaluatingOrder = order;
301+
}
302+
303+
public long getAsyncEvaluatingOrder() {
304+
return asyncEvaluatingOrder;
305+
}
306+
298307
public boolean isTopLevelAsync() {
299308
return async;
300309
}

0 commit comments

Comments
 (0)