Skip to content

Commit f09c033

Browse files
guybedfordruyadorno
authored andcommittedMar 31, 2021
deps: backport v8 f19142e6
[top-level-await] Implement the new post-order requirement for async subgraphs Refs: v8/v8@f19142e PR-URL: #37864 Backport-PR-URL: #37985 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
1 parent 2fd97ce commit f09c033

17 files changed

+336
-87
lines changed
 

‎deps/v8/src/common/globals.h

+3
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ constexpr int kUC16Size = sizeof(uc16); // NOLINT
349349
// 128 bit SIMD value size.
350350
constexpr int kSimd128Size = 16;
351351

352+
// Maximum ordinal used for tracking asynchronous module evaluation order.
353+
constexpr unsigned kMaxModuleAsyncEvaluatingOrdinal = (1 << 30) - 1;
354+
352355
// FUNCTION_ADDR(f) gets the address of a C function f.
353356
#define FUNCTION_ADDR(f) (reinterpret_cast<v8::internal::Address>(f))
354357

‎deps/v8/src/diagnostics/objects-debug.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -1390,7 +1390,8 @@ void SourceTextModule::SourceTextModuleVerify(Isolate* isolate) {
13901390
(status() == kPreInstantiating && code().IsSharedFunctionInfo()) ||
13911391
(status() == kUninstantiated && code().IsSharedFunctionInfo()));
13921392
CHECK(top_level_capability().IsUndefined() && !AsyncParentModuleCount() &&
1393-
!pending_async_dependencies() && !async_evaluating());
1393+
!pending_async_dependencies());
1394+
CHECK(!IsAsyncEvaluating());
13941395
}
13951396

13961397
CHECK_EQ(requested_modules().length(), info().module_requests().length());

‎deps/v8/src/diagnostics/objects-printer.cc

+1
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,7 @@ void SourceTextModule::SourceTextModulePrint(std::ostream& os) { // NOLINT
16021602
os << "\n - script: " << Brief(script());
16031603
os << "\n - import_meta: " << Brief(import_meta());
16041604
os << "\n - cycle_root: " << Brief(cycle_root());
1605+
os << "\n - async_evaluating_ordinal: " << async_evaluating_ordinal();
16051606
os << "\n";
16061607
}
16071608

‎deps/v8/src/execution/isolate-inl.h

+31
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "src/objects/property-cell.h"
1414
#include "src/objects/regexp-match-info.h"
1515
#include "src/objects/shared-function-info.h"
16+
#include "src/objects/source-text-module.h"
1617

1718
namespace v8 {
1819
namespace internal {
@@ -118,6 +119,36 @@ Isolate::ExceptionScope::~ExceptionScope() {
118119
isolate_->set_pending_exception(*pending_exception_);
119120
}
120121

122+
void Isolate::DidFinishModuleAsyncEvaluation(unsigned ordinal) {
123+
// To address overflow, the ordinal is reset when the async module with the
124+
// largest vended ordinal finishes evaluating. Modules are evaluated in
125+
// ascending order of their async_evaluating_ordinal.
126+
//
127+
// While the specification imposes a global total ordering, the intention is
128+
// that for each async module, all its parents are totally ordered by when
129+
// they first had their [[AsyncEvaluating]] bit set.
130+
//
131+
// The module with largest vended ordinal finishes evaluating implies that the
132+
// async dependency as well as all other modules in that module's graph
133+
// depending on async dependencies are finished evaluating.
134+
//
135+
// If the async dependency participates in other module graphs (e.g. via
136+
// dynamic import, or other <script type=module> tags), those module graphs
137+
// must have been evaluated either before or after the async dependency is
138+
// settled, as the concrete Evaluate() method on cyclic module records is
139+
// neither reentrant nor performs microtask checkpoints during its
140+
// evaluation. If before, then all modules that depend on the async
141+
// dependencies were given an ordinal that ensure they are relatively ordered,
142+
// before the global ordinal was reset. If after, then the async evaluating
143+
// ordering does not apply, as the dependency is no longer asynchronous.
144+
//
145+
// https://tc39.es/ecma262/#sec-moduleevaluation
146+
if (ordinal + 1 == next_module_async_evaluating_ordinal_) {
147+
next_module_async_evaluating_ordinal_ =
148+
SourceTextModule::kFirstAsyncEvaluatingOrdinal;
149+
}
150+
}
151+
121152
#define NATIVE_CONTEXT_FIELD_ACCESSOR(index, type, name) \
122153
Handle<type> Isolate::name() { \
123154
return Handle<type>(raw_native_context().name(), this); \

‎deps/v8/src/execution/isolate.cc

+3
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
#include "src/objects/prototype.h"
7070
#include "src/objects/slots.h"
7171
#include "src/objects/smi.h"
72+
#include "src/objects/source-text-module.h"
7273
#include "src/objects/stack-frame-info-inl.h"
7374
#include "src/objects/visitors.h"
7475
#include "src/profiler/heap-profiler.h"
@@ -2929,6 +2930,8 @@ Isolate::Isolate(std::unique_ptr<i::IsolateAllocator> isolate_allocator)
29292930
#if V8_SFI_HAS_UNIQUE_ID
29302931
next_unique_sfi_id_(0),
29312932
#endif
2933+
next_module_async_evaluating_ordinal_(
2934+
SourceTextModule::kFirstAsyncEvaluatingOrdinal),
29322935
cancelable_task_manager_(new CancelableTaskManager()) {
29332936
TRACE_ISOLATE(constructor);
29342937
CheckIsolateLayout();

‎deps/v8/src/execution/isolate.h

+18
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,22 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
12841284
return id;
12851285
}
12861286

1287+
// https://github.com/tc39/proposal-top-level-await/pull/159
1288+
// TODO(syg): Update to actual spec link once merged.
1289+
//
1290+
// According to the spec, modules that depend on async modules (i.e. modules
1291+
// with top-level await) must be evaluated in order in which their
1292+
// [[AsyncEvaluating]] flags were set to true. V8 tracks this global total
1293+
// order with next_module_async_evaluating_ordinal_. Each module that sets its
1294+
// [[AsyncEvaluating]] to true grabs the next ordinal.
1295+
unsigned NextModuleAsyncEvaluatingOrdinal() {
1296+
unsigned ordinal = next_module_async_evaluating_ordinal_++;
1297+
CHECK_LT(ordinal, kMaxModuleAsyncEvaluatingOrdinal);
1298+
return ordinal;
1299+
}
1300+
1301+
inline void DidFinishModuleAsyncEvaluation(unsigned ordinal);
1302+
12871303
void AddNearHeapLimitCallback(v8::NearHeapLimitCallback, void* data);
12881304
void RemoveNearHeapLimitCallback(v8::NearHeapLimitCallback callback,
12891305
size_t heap_limit);
@@ -1815,6 +1831,8 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
18151831
std::atomic<int> next_unique_sfi_id_;
18161832
#endif
18171833

1834+
unsigned next_module_async_evaluating_ordinal_;
1835+
18181836
// Vector of callbacks before a Call starts execution.
18191837
std::vector<BeforeCallEnteredCallback> before_call_entered_callbacks_;
18201838

‎deps/v8/src/heap/factory.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2504,7 +2504,7 @@ Handle<SourceTextModule> Factory::NewSourceTextModule(
25042504
module->set_top_level_capability(roots.undefined_value());
25052505
module->set_flags(0);
25062506
module->set_async(IsAsyncModule(code->kind()));
2507-
module->set_async_evaluating(false);
2507+
module->set_async_evaluating_ordinal(SourceTextModule::kNotAsyncEvaluated);
25082508
module->set_cycle_root(roots.the_hole_value());
25092509
module->set_async_parent_modules(*async_parent_modules);
25102510
module->set_pending_async_dependencies(0);

‎deps/v8/src/objects/module-inl.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ SMI_ACCESSORS(Module, status, kStatusOffset)
3737
SMI_ACCESSORS(Module, hash, kHashOffset)
3838

3939
BOOL_ACCESSORS(SourceTextModule, flags, async, AsyncBit::kShift)
40-
BOOL_ACCESSORS(SourceTextModule, flags, async_evaluating,
41-
AsyncEvaluatingBit::kShift)
40+
BIT_FIELD_ACCESSORS(SourceTextModule, flags, async_evaluating_ordinal,
41+
SourceTextModule::AsyncEvaluatingOrdinalBits)
4242
ACCESSORS(SourceTextModule, async_parent_modules, ArrayList,
4343
kAsyncParentModulesOffset)
4444
ACCESSORS(SourceTextModule, top_level_capability, HeapObject,
@@ -141,6 +141,10 @@ int SourceTextModule::AsyncParentModuleCount() {
141141
return async_parent_modules().Length();
142142
}
143143

144+
bool SourceTextModule::IsAsyncEvaluating() const {
145+
return async_evaluating_ordinal() >= kFirstAsyncEvaluatingOrdinal;
146+
}
147+
144148
bool SourceTextModule::HasPendingAsyncDependencies() {
145149
DCHECK_GE(pending_async_dependencies(), 0);
146150
return pending_async_dependencies() > 0;

0 commit comments

Comments
 (0)
Please sign in to comment.