Skip to content

Commit

Permalink
deps: backport v8 f19142e6
Browse files Browse the repository at this point in the history
[top-level-await] Implement the new post-order requirement for
async subgraphs

Refs: v8/v8@f19142e
PR-URL: #37864
Reviewed-By: Michaël Zasso <[email protected]>
Reviewed-By: Colin Ihrig <[email protected]>
  • Loading branch information
guybedford committed Mar 30, 2021
1 parent abe04be commit e3e5b8b
Show file tree
Hide file tree
Showing 17 changed files with 335 additions and 87 deletions.
3 changes: 3 additions & 0 deletions deps/v8/src/common/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,9 @@ constexpr int kUC16Size = sizeof(uc16); // NOLINT
// 128 bit SIMD value size.
constexpr int kSimd128Size = 16;

// Maximum ordinal used for tracking asynchronous module evaluation order.
constexpr unsigned kMaxModuleAsyncEvaluatingOrdinal = (1 << 30) - 1;

// FUNCTION_ADDR(f) gets the address of a C function f.
#define FUNCTION_ADDR(f) (reinterpret_cast<v8::internal::Address>(f))

Expand Down
1 change: 1 addition & 0 deletions deps/v8/src/diagnostics/objects-debug.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,7 @@ void SourceTextModule::SourceTextModuleVerify(Isolate* isolate) {
(status() == kUninstantiated && code().IsSharedFunctionInfo()));
CHECK(top_level_capability().IsUndefined() && !AsyncParentModuleCount() &&
!pending_async_dependencies() && !async_evaluating());
CHECK(!IsAsyncEvaluating());
}

CHECK_EQ(requested_modules().length(), info().module_requests().length());
Expand Down
1 change: 1 addition & 0 deletions deps/v8/src/diagnostics/objects-printer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,7 @@ void SourceTextModule::SourceTextModulePrint(std::ostream& os) { // NOLINT
os << "\n - script: " << Brief(script());
os << "\n - import_meta: " << Brief(import_meta());
os << "\n - cycle_root: " << Brief(cycle_root());
os << "\n - async_evaluating_ordinal: " << async_evaluating_ordinal();
os << "\n";
}

Expand Down
31 changes: 31 additions & 0 deletions deps/v8/src/execution/isolate-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "src/objects/property-cell.h"
#include "src/objects/regexp-match-info.h"
#include "src/objects/shared-function-info.h"
#include "src/objects/source-text-module.h"

namespace v8 {
namespace internal {
Expand Down Expand Up @@ -118,6 +119,36 @@ Isolate::ExceptionScope::~ExceptionScope() {
isolate_->set_pending_exception(*pending_exception_);
}

void Isolate::DidFinishModuleAsyncEvaluation(unsigned ordinal) {
// To address overflow, the ordinal is reset when the async module with the
// largest vended ordinal finishes evaluating. Modules are evaluated in
// ascending order of their async_evaluating_ordinal.
//
// While the specification imposes a global total ordering, the intention is
// that for each async module, all its parents are totally ordered by when
// they first had their [[AsyncEvaluating]] bit set.
//
// The module with largest vended ordinal finishes evaluating implies that the
// async dependency as well as all other modules in that module's graph
// depending on async dependencies are finished evaluating.
//
// If the async dependency participates in other module graphs (e.g. via
// dynamic import, or other <script type=module> tags), those module graphs
// must have been evaluated either before or after the async dependency is
// settled, as the concrete Evaluate() method on cyclic module records is
// neither reentrant nor performs microtask checkpoints during its
// evaluation. If before, then all modules that depend on the async
// dependencies were given an ordinal that ensure they are relatively ordered,
// before the global ordinal was reset. If after, then the async evaluating
// ordering does not apply, as the dependency is no longer asynchronous.
//
// https://tc39.es/ecma262/#sec-moduleevaluation
if (ordinal + 1 == next_module_async_evaluating_ordinal_) {
next_module_async_evaluating_ordinal_ =
SourceTextModule::kFirstAsyncEvaluatingOrdinal;
}
}

#define NATIVE_CONTEXT_FIELD_ACCESSOR(index, type, name) \
Handle<type> Isolate::name() { \
return Handle<type>(raw_native_context().name(), this); \
Expand Down
3 changes: 3 additions & 0 deletions deps/v8/src/execution/isolate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
#include "src/objects/prototype.h"
#include "src/objects/slots.h"
#include "src/objects/smi.h"
#include "src/objects/source-text-module.h"
#include "src/objects/stack-frame-info-inl.h"
#include "src/objects/visitors.h"
#include "src/profiler/heap-profiler.h"
Expand Down Expand Up @@ -2929,6 +2930,8 @@ Isolate::Isolate(std::unique_ptr<i::IsolateAllocator> isolate_allocator)
#if V8_SFI_HAS_UNIQUE_ID
next_unique_sfi_id_(0),
#endif
next_module_async_evaluating_ordinal_(
SourceTextModule::kFirstAsyncEvaluatingOrdinal),
cancelable_task_manager_(new CancelableTaskManager()) {
TRACE_ISOLATE(constructor);
CheckIsolateLayout();
Expand Down
18 changes: 18 additions & 0 deletions deps/v8/src/execution/isolate.h
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,22 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
return id;
}

// https://github.com/tc39/proposal-top-level-await/pull/159
// TODO(syg): Update to actual spec link once merged.
//
// According to the spec, modules that depend on async modules (i.e. modules
// with top-level await) must be evaluated in order in which their
// [[AsyncEvaluating]] flags were set to true. V8 tracks this global total
// order with next_module_async_evaluating_ordinal_. Each module that sets its
// [[AsyncEvaluating]] to true grabs the next ordinal.
unsigned NextModuleAsyncEvaluatingOrdinal() {
unsigned ordinal = next_module_async_evaluating_ordinal_++;
CHECK_LT(ordinal, kMaxModuleAsyncEvaluatingOrdinal);
return ordinal;
}

inline void DidFinishModuleAsyncEvaluation(unsigned ordinal);

void AddNearHeapLimitCallback(v8::NearHeapLimitCallback, void* data);
void RemoveNearHeapLimitCallback(v8::NearHeapLimitCallback callback,
size_t heap_limit);
Expand Down Expand Up @@ -1815,6 +1831,8 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
std::atomic<int> next_unique_sfi_id_;
#endif

unsigned next_module_async_evaluating_ordinal_;

// Vector of callbacks before a Call starts execution.
std::vector<BeforeCallEnteredCallback> before_call_entered_callbacks_;

Expand Down
3 changes: 1 addition & 2 deletions deps/v8/src/heap/factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2503,8 +2503,7 @@ Handle<SourceTextModule> Factory::NewSourceTextModule(
module->set_dfs_ancestor_index(-1);
module->set_top_level_capability(roots.undefined_value());
module->set_flags(0);
module->set_async(IsAsyncModule(code->kind()));
module->set_async_evaluating(false);
module->set_async_evaluating_ordinal(SourceTextModule::kNotAsyncEvaluated);
module->set_cycle_root(roots.the_hole_value());
module->set_async_parent_modules(*async_parent_modules);
module->set_pending_async_dependencies(0);
Expand Down
8 changes: 6 additions & 2 deletions deps/v8/src/objects/module-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ SMI_ACCESSORS(Module, status, kStatusOffset)
SMI_ACCESSORS(Module, hash, kHashOffset)

BOOL_ACCESSORS(SourceTextModule, flags, async, AsyncBit::kShift)
BOOL_ACCESSORS(SourceTextModule, flags, async_evaluating,
AsyncEvaluatingBit::kShift)
BIT_FIELD_ACCESSORS(SourceTextModule, flags, async_evaluating_ordinal,
SourceTextModule::AsyncEvaluatingOrdinalBits)
ACCESSORS(SourceTextModule, async_parent_modules, ArrayList,
kAsyncParentModulesOffset)
ACCESSORS(SourceTextModule, top_level_capability, HeapObject,
Expand Down Expand Up @@ -141,6 +141,10 @@ int SourceTextModule::AsyncParentModuleCount() {
return async_parent_modules().Length();
}

bool SourceTextModule::IsAsyncEvaluating() const {
return async_evaluating_ordinal() >= kFirstAsyncEvaluatingOrdinal;
}

bool SourceTextModule::HasPendingAsyncDependencies() {
DCHECK_GE(pending_async_dependencies(), 0);
return pending_async_dependencies() > 0;
Expand Down
Loading

0 comments on commit e3e5b8b

Please sign in to comment.