76c5f5cc8a
In the GN build, libchromiumcontent is no longer a distinct library, but merely a container for a set of scripts and patches. Maintaining those patches in a separate repository is tedious and error-prone, so merge them into the main repo. Once this is merged and GN is the default way to build Electron, the libchromiumcontent repository can be archived.
2330 lines
112 KiB
Diff
2330 lines
112 KiB
Diff
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
|
|
index 43c7527de98..2138b9c73d7 100644
|
|
--- a/src/bootstrapper.cc
|
|
+++ b/src/bootstrapper.cc
|
|
@@ -1584,6 +1584,50 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
|
native_context()->set_async_iterator_value_unwrap_shared_fun(*info);
|
|
}
|
|
|
|
+ { // --- A s y n c G e n e r a t o r ---
|
|
+ Handle<JSFunction> await_caught =
|
|
+ SimpleCreateFunction(isolate, factory->empty_string(),
|
|
+ Builtins::kAsyncGeneratorAwaitCaught, 1, false);
|
|
+ native_context()->set_async_generator_await_caught(*await_caught);
|
|
+
|
|
+ Handle<JSFunction> await_uncaught =
|
|
+ SimpleCreateFunction(isolate, factory->empty_string(),
|
|
+ Builtins::kAsyncGeneratorAwaitUncaught, 1, false);
|
|
+ native_context()->set_async_generator_await_uncaught(*await_uncaught);
|
|
+
|
|
+ Handle<SharedFunctionInfo> info = SimpleCreateSharedFunctionInfo(
|
|
+ isolate, Builtins::kAsyncGeneratorAwaitResolveClosure,
|
|
+ factory->empty_string(), 1);
|
|
+ native_context()->set_async_generator_await_resolve_shared_fun(*info);
|
|
+
|
|
+ info = SimpleCreateSharedFunctionInfo(
|
|
+ isolate, Builtins::kAsyncGeneratorAwaitRejectClosure,
|
|
+ factory->empty_string(), 1);
|
|
+ native_context()->set_async_generator_await_reject_shared_fun(*info);
|
|
+
|
|
+ info = SimpleCreateSharedFunctionInfo(
|
|
+ isolate, Builtins::kAsyncGeneratorYieldResolveClosure,
|
|
+ factory->empty_string(), 1);
|
|
+ native_context()->set_async_generator_yield_resolve_shared_fun(*info);
|
|
+
|
|
+ info = SimpleCreateSharedFunctionInfo(
|
|
+ isolate, Builtins::kAsyncGeneratorReturnResolveClosure,
|
|
+ factory->empty_string(), 1);
|
|
+ native_context()->set_async_generator_return_resolve_shared_fun(*info);
|
|
+
|
|
+ info = SimpleCreateSharedFunctionInfo(
|
|
+ isolate, Builtins::kAsyncGeneratorReturnClosedResolveClosure,
|
|
+ factory->empty_string(), 1);
|
|
+ native_context()->set_async_generator_return_closed_resolve_shared_fun(
|
|
+ *info);
|
|
+
|
|
+ info = SimpleCreateSharedFunctionInfo(
|
|
+ isolate, Builtins::kAsyncGeneratorReturnClosedRejectClosure,
|
|
+ factory->empty_string(), 1);
|
|
+ native_context()->set_async_generator_return_closed_reject_shared_fun(
|
|
+ *info);
|
|
+ }
|
|
+
|
|
{ // --- A r r a y ---
|
|
Handle<JSFunction> array_function = InstallFunction(
|
|
global, "Array", JS_ARRAY_TYPE, JSArray::kSize, 0,
|
|
@@ -3998,6 +4042,34 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
|
|
JSFunction::SetPrototype(async_function_constructor,
|
|
async_function_prototype);
|
|
|
|
+ {
|
|
+ Handle<JSFunction> function =
|
|
+ SimpleCreateFunction(isolate, factory->empty_string(),
|
|
+ Builtins::kAsyncFunctionAwaitCaught, 2, false);
|
|
+ native_context->set_async_function_await_caught(*function);
|
|
+ }
|
|
+
|
|
+ {
|
|
+ Handle<JSFunction> function =
|
|
+ SimpleCreateFunction(isolate, factory->empty_string(),
|
|
+ Builtins::kAsyncFunctionAwaitUncaught, 2, false);
|
|
+ native_context->set_async_function_await_uncaught(*function);
|
|
+ }
|
|
+
|
|
+ {
|
|
+ Handle<SharedFunctionInfo> info = SimpleCreateSharedFunctionInfo(
|
|
+ isolate, Builtins::kAsyncFunctionAwaitRejectClosure,
|
|
+ factory->empty_string(), 1);
|
|
+ native_context->set_async_function_await_reject_shared_fun(*info);
|
|
+ }
|
|
+
|
|
+ {
|
|
+ Handle<SharedFunctionInfo> info = SimpleCreateSharedFunctionInfo(
|
|
+ isolate, Builtins::kAsyncFunctionAwaitResolveClosure,
|
|
+ factory->empty_string(), 1);
|
|
+ native_context->set_async_function_await_resolve_shared_fun(*info);
|
|
+ }
|
|
+
|
|
{
|
|
Handle<JSFunction> function =
|
|
SimpleCreateFunction(isolate, factory->empty_string(),
|
|
diff --git a/src/builtins/builtins-async-function-gen.cc b/src/builtins/builtins-async-function-gen.cc
|
|
index 0db53c687e6..0d0e34ee0da 100644
|
|
--- a/src/builtins/builtins-async-function-gen.cc
|
|
+++ b/src/builtins/builtins-async-function-gen.cc
|
|
@@ -21,18 +21,37 @@ class AsyncFunctionBuiltinsAssembler : public AsyncBuiltinsAssembler {
|
|
Node* const awaited, Node* const outer_promise,
|
|
const bool is_predicted_as_caught);
|
|
|
|
- void AsyncFunctionAwaitResume(Node* const context, Node* const argument,
|
|
- Node* const generator,
|
|
- JSGeneratorObject::ResumeMode resume_mode);
|
|
+ void AsyncFunctionAwaitResumeClosure(
|
|
+ Node* const context, Node* const sent_value,
|
|
+ JSGeneratorObject::ResumeMode resume_mode);
|
|
};
|
|
|
|
-void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResume(
|
|
- Node* const context, Node* const argument, Node* const generator,
|
|
+namespace {
|
|
+
|
|
+// Describe fields of Context associated with AsyncFunctionAwait resume
|
|
+// closures.
|
|
+// TODO(jgruber): Refactor to reuse code for upcoming async-generators.
|
|
+class AwaitContext {
|
|
+ public:
|
|
+ enum Fields { kGeneratorSlot = Context::MIN_CONTEXT_SLOTS, kLength };
|
|
+};
|
|
+
|
|
+} // anonymous namespace
|
|
+
|
|
+void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResumeClosure(
|
|
+ Node* context, Node* sent_value,
|
|
JSGeneratorObject::ResumeMode resume_mode) {
|
|
- CSA_ASSERT(this, IsJSGeneratorObject(generator));
|
|
DCHECK(resume_mode == JSGeneratorObject::kNext ||
|
|
resume_mode == JSGeneratorObject::kThrow);
|
|
|
|
+ Node* const generator =
|
|
+ LoadContextElement(context, AwaitContext::kGeneratorSlot);
|
|
+ CSA_SLOW_ASSERT(this, HasInstanceType(generator, JS_GENERATOR_OBJECT_TYPE));
|
|
+
|
|
+ // Inline version of GeneratorPrototypeNext / GeneratorPrototypeReturn with
|
|
+ // unnecessary runtime checks removed.
|
|
+ // TODO(jgruber): Refactor to reuse code from builtins-generator.cc.
|
|
+
|
|
// Ensure that the generator is neither closed nor running.
|
|
CSA_SLOW_ASSERT(
|
|
this,
|
|
@@ -47,23 +66,31 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResume(
|
|
|
|
// Resume the {receiver} using our trampoline.
|
|
Callable callable = CodeFactory::ResumeGenerator(isolate());
|
|
- TailCallStub(callable, context, argument, generator);
|
|
+ CallStub(callable, context, sent_value, generator);
|
|
+
|
|
+ // The resulting Promise is a throwaway, so it doesn't matter what it
|
|
+ // resolves to. What is important is that we don't end up keeping the
|
|
+ // whole chain of intermediate Promises alive by returning the return value
|
|
+ // of ResumeGenerator, as that would create a memory leak.
|
|
}
|
|
|
|
-TF_BUILTIN(AsyncFunctionAwaitFulfill, AsyncFunctionBuiltinsAssembler) {
|
|
- Node* const argument = Parameter(Descriptor::kArgument);
|
|
- Node* const generator = Parameter(Descriptor::kGenerator);
|
|
+TF_BUILTIN(AsyncFunctionAwaitRejectClosure, AsyncFunctionBuiltinsAssembler) {
|
|
+ CSA_ASSERT_JS_ARGC_EQ(this, 1);
|
|
+ Node* const sentError = Parameter(Descriptor::kSentError);
|
|
Node* const context = Parameter(Descriptor::kContext);
|
|
- AsyncFunctionAwaitResume(context, argument, generator,
|
|
- JSGeneratorObject::kNext);
|
|
+
|
|
+ AsyncFunctionAwaitResumeClosure(context, sentError,
|
|
+ JSGeneratorObject::kThrow);
|
|
+ Return(UndefinedConstant());
|
|
}
|
|
|
|
-TF_BUILTIN(AsyncFunctionAwaitReject, AsyncFunctionBuiltinsAssembler) {
|
|
- Node* const argument = Parameter(Descriptor::kArgument);
|
|
- Node* const generator = Parameter(Descriptor::kGenerator);
|
|
+TF_BUILTIN(AsyncFunctionAwaitResolveClosure, AsyncFunctionBuiltinsAssembler) {
|
|
+ CSA_ASSERT_JS_ARGC_EQ(this, 1);
|
|
+ Node* const sentValue = Parameter(Descriptor::kSentValue);
|
|
Node* const context = Parameter(Descriptor::kContext);
|
|
- AsyncFunctionAwaitResume(context, argument, generator,
|
|
- JSGeneratorObject::kThrow);
|
|
+
|
|
+ AsyncFunctionAwaitResumeClosure(context, sentValue, JSGeneratorObject::kNext);
|
|
+ Return(UndefinedConstant());
|
|
}
|
|
|
|
// ES#abstract-ops-async-function-await
|
|
@@ -78,12 +105,25 @@ TF_BUILTIN(AsyncFunctionAwaitReject, AsyncFunctionBuiltinsAssembler) {
|
|
void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwait(
|
|
Node* const context, Node* const generator, Node* const awaited,
|
|
Node* const outer_promise, const bool is_predicted_as_caught) {
|
|
- CSA_SLOW_ASSERT(this, IsJSGeneratorObject(generator));
|
|
- CSA_SLOW_ASSERT(this, IsJSPromise(outer_promise));
|
|
-
|
|
- Await(context, generator, awaited, outer_promise,
|
|
- Builtins::kAsyncFunctionAwaitFulfill,
|
|
- Builtins::kAsyncFunctionAwaitReject, is_predicted_as_caught);
|
|
+ CSA_SLOW_ASSERT(this, HasInstanceType(generator, JS_GENERATOR_OBJECT_TYPE));
|
|
+ CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE));
|
|
+
|
|
+ ContextInitializer init_closure_context = [&](Node* context) {
|
|
+ StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
|
|
+ generator);
|
|
+ };
|
|
+
|
|
+ // TODO(jgruber): AsyncBuiltinsAssembler::Await currently does not reuse
|
|
+ // the awaited promise if it is already a promise. Reuse is non-spec compliant
|
|
+ // but part of our old behavior gives us a couple of percent
|
|
+ // performance boost.
|
|
+ // TODO(jgruber): Use a faster specialized version of
|
|
+ // InternalPerformPromiseThen.
|
|
+
|
|
+ Await(context, generator, awaited, outer_promise, AwaitContext::kLength,
|
|
+ init_closure_context, Context::ASYNC_FUNCTION_AWAIT_RESOLVE_SHARED_FUN,
|
|
+ Context::ASYNC_FUNCTION_AWAIT_REJECT_SHARED_FUN,
|
|
+ is_predicted_as_caught);
|
|
|
|
// Return outer promise to avoid adding an load of the outer promise before
|
|
// suspending in BytecodeGenerator.
|
|
@@ -93,28 +133,30 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwait(
|
|
// Called by the parser from the desugaring of 'await' when catch
|
|
// prediction indicates that there is a locally surrounding catch block.
|
|
TF_BUILTIN(AsyncFunctionAwaitCaught, AsyncFunctionBuiltinsAssembler) {
|
|
+ CSA_ASSERT_JS_ARGC_EQ(this, 3);
|
|
Node* const generator = Parameter(Descriptor::kGenerator);
|
|
- Node* const value = Parameter(Descriptor::kValue);
|
|
+ Node* const awaited = Parameter(Descriptor::kAwaited);
|
|
Node* const outer_promise = Parameter(Descriptor::kOuterPromise);
|
|
Node* const context = Parameter(Descriptor::kContext);
|
|
|
|
static const bool kIsPredictedAsCaught = true;
|
|
|
|
- AsyncFunctionAwait(context, generator, value, outer_promise,
|
|
+ AsyncFunctionAwait(context, generator, awaited, outer_promise,
|
|
kIsPredictedAsCaught);
|
|
}
|
|
|
|
// Called by the parser from the desugaring of 'await' when catch
|
|
// prediction indicates no locally surrounding catch block.
|
|
TF_BUILTIN(AsyncFunctionAwaitUncaught, AsyncFunctionBuiltinsAssembler) {
|
|
+ CSA_ASSERT_JS_ARGC_EQ(this, 3);
|
|
Node* const generator = Parameter(Descriptor::kGenerator);
|
|
- Node* const value = Parameter(Descriptor::kValue);
|
|
+ Node* const awaited = Parameter(Descriptor::kAwaited);
|
|
Node* const outer_promise = Parameter(Descriptor::kOuterPromise);
|
|
Node* const context = Parameter(Descriptor::kContext);
|
|
|
|
static const bool kIsPredictedAsCaught = false;
|
|
|
|
- AsyncFunctionAwait(context, generator, value, outer_promise,
|
|
+ AsyncFunctionAwait(context, generator, awaited, outer_promise,
|
|
kIsPredictedAsCaught);
|
|
}
|
|
|
|
diff --git a/src/builtins/builtins-async-gen.cc b/src/builtins/builtins-async-gen.cc
|
|
index 073c96a2e09..ba0226d7b3a 100644
|
|
--- a/src/builtins/builtins-async-gen.cc
|
|
+++ b/src/builtins/builtins-async-gen.cc
|
|
@@ -13,58 +13,6 @@ namespace internal {
|
|
|
|
using compiler::Node;
|
|
|
|
-void AsyncBuiltinsAssembler::Await(Node* context, Node* generator, Node* value,
|
|
- Node* outer_promise,
|
|
- Builtins::Name fulfill_builtin,
|
|
- Builtins::Name reject_builtin,
|
|
- Node* is_predicted_as_caught) {
|
|
- CSA_SLOW_ASSERT(this, Word32Or(IsJSAsyncGeneratorObject(generator),
|
|
- IsJSGeneratorObject(generator)));
|
|
- CSA_SLOW_ASSERT(this, IsJSPromise(outer_promise));
|
|
- CSA_SLOW_ASSERT(this, IsBoolean(is_predicted_as_caught));
|
|
-
|
|
- Node* const native_context = LoadNativeContext(context);
|
|
-
|
|
- // TODO(bmeurer): This could be optimized and folded into a single allocation.
|
|
- Node* const promise = AllocateAndInitJSPromise(native_context);
|
|
- Node* const promise_reactions =
|
|
- LoadObjectField(promise, JSPromise::kReactionsOrResultOffset);
|
|
- Node* const fulfill_handler =
|
|
- HeapConstant(Builtins::CallableFor(isolate(), fulfill_builtin).code());
|
|
- Node* const reject_handler =
|
|
- HeapConstant(Builtins::CallableFor(isolate(), reject_builtin).code());
|
|
- Node* const reaction = AllocatePromiseReaction(
|
|
- promise_reactions, generator, fulfill_handler, reject_handler);
|
|
- StoreObjectField(promise, JSPromise::kReactionsOrResultOffset, reaction);
|
|
- PromiseSetHasHandler(promise);
|
|
-
|
|
- // Perform ! Call(promiseCapability.[[Resolve]], undefined, « value »).
|
|
- CallBuiltin(Builtins::kResolvePromise, native_context, promise, value);
|
|
-
|
|
- // When debugging, we need to link from the {generator} to the
|
|
- // {outer_promise} of the async function/generator.
|
|
- Label done(this);
|
|
- GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &done);
|
|
- CallRuntime(Runtime::kSetProperty, native_context, generator,
|
|
- LoadRoot(Heap::kgenerator_outer_promise_symbolRootIndex),
|
|
- outer_promise, SmiConstant(LanguageMode::kStrict));
|
|
- GotoIf(IsFalse(is_predicted_as_caught), &done);
|
|
- GotoIf(TaggedIsSmi(value), &done);
|
|
- GotoIfNot(IsJSPromise(value), &done);
|
|
- PromiseSetHandledHint(value);
|
|
- Goto(&done);
|
|
- BIND(&done);
|
|
-}
|
|
-
|
|
-void AsyncBuiltinsAssembler::Await(Node* context, Node* generator, Node* value,
|
|
- Node* outer_promise,
|
|
- Builtins::Name fulfill_builtin,
|
|
- Builtins::Name reject_builtin,
|
|
- bool is_predicted_as_caught) {
|
|
- return Await(context, generator, value, outer_promise, fulfill_builtin,
|
|
- reject_builtin, BooleanConstant(is_predicted_as_caught));
|
|
-}
|
|
-
|
|
namespace {
|
|
// Describe fields of Context associated with the AsyncIterator unwrap closure.
|
|
class ValueUnwrapContext {
|
|
@@ -74,6 +22,161 @@ class ValueUnwrapContext {
|
|
|
|
} // namespace
|
|
|
|
+Node* AsyncBuiltinsAssembler::Await(
|
|
+ Node* context, Node* generator, Node* value, Node* outer_promise,
|
|
+ int context_length, const ContextInitializer& init_closure_context,
|
|
+ Node* on_resolve_context_index, Node* on_reject_context_index,
|
|
+ Node* is_predicted_as_caught) {
|
|
+ DCHECK_GE(context_length, Context::MIN_CONTEXT_SLOTS);
|
|
+
|
|
+ Node* const native_context = LoadNativeContext(context);
|
|
+
|
|
+ static const int kWrappedPromiseOffset = FixedArray::SizeFor(context_length);
|
|
+ static const int kThrowawayPromiseOffset =
|
|
+ kWrappedPromiseOffset + JSPromise::kSizeWithEmbedderFields;
|
|
+ static const int kResolveClosureOffset =
|
|
+ kThrowawayPromiseOffset + JSPromise::kSizeWithEmbedderFields;
|
|
+ static const int kRejectClosureOffset =
|
|
+ kResolveClosureOffset + JSFunction::kSizeWithoutPrototype;
|
|
+ static const int kTotalSize =
|
|
+ kRejectClosureOffset + JSFunction::kSizeWithoutPrototype;
|
|
+
|
|
+ Node* const base = AllocateInNewSpace(kTotalSize);
|
|
+ Node* const closure_context = base;
|
|
+ {
|
|
+ // Initialize closure context
|
|
+ InitializeFunctionContext(native_context, closure_context, context_length);
|
|
+ init_closure_context(closure_context);
|
|
+ }
|
|
+
|
|
+ // Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
|
+ Node* const promise_fun =
|
|
+ LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
|
|
+ CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun)));
|
|
+ Node* const promise_map =
|
|
+ LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
|
|
+ // Assert that the JSPromise map has an instance size is
|
|
+ // JSPromise::kSizeWithEmbedderFields.
|
|
+ CSA_ASSERT(this, WordEqual(LoadMapInstanceSizeInWords(promise_map),
|
|
+ IntPtrConstant(JSPromise::kSizeWithEmbedderFields /
|
|
+ kPointerSize)));
|
|
+ Node* const wrapped_value = InnerAllocate(base, kWrappedPromiseOffset);
|
|
+ {
|
|
+ // Initialize Promise
|
|
+ StoreMapNoWriteBarrier(wrapped_value, promise_map);
|
|
+ InitializeJSObjectFromMap(
|
|
+ wrapped_value, promise_map,
|
|
+ IntPtrConstant(JSPromise::kSizeWithEmbedderFields));
|
|
+ PromiseInit(wrapped_value);
|
|
+ }
|
|
+
|
|
+ Node* const throwaway = InnerAllocate(base, kThrowawayPromiseOffset);
|
|
+ {
|
|
+ // Initialize throwawayPromise
|
|
+ StoreMapNoWriteBarrier(throwaway, promise_map);
|
|
+ InitializeJSObjectFromMap(
|
|
+ throwaway, promise_map,
|
|
+ IntPtrConstant(JSPromise::kSizeWithEmbedderFields));
|
|
+ PromiseInit(throwaway);
|
|
+ }
|
|
+
|
|
+ Node* const on_resolve = InnerAllocate(base, kResolveClosureOffset);
|
|
+ {
|
|
+ // Initialize resolve handler
|
|
+ InitializeNativeClosure(closure_context, native_context, on_resolve,
|
|
+ on_resolve_context_index);
|
|
+ }
|
|
+
|
|
+ Node* const on_reject = InnerAllocate(base, kRejectClosureOffset);
|
|
+ {
|
|
+ // Initialize reject handler
|
|
+ InitializeNativeClosure(closure_context, native_context, on_reject,
|
|
+ on_reject_context_index);
|
|
+ }
|
|
+
|
|
+ {
|
|
+ // Add PromiseHooks if needed
|
|
+ Label next(this);
|
|
+ GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &next);
|
|
+ CallRuntime(Runtime::kPromiseHookInit, context, wrapped_value,
|
|
+ outer_promise);
|
|
+ CallRuntime(Runtime::kPromiseHookInit, context, throwaway, wrapped_value);
|
|
+ Goto(&next);
|
|
+ BIND(&next);
|
|
+ }
|
|
+
|
|
+ // Perform ! Call(promiseCapability.[[Resolve]], undefined, « promise »).
|
|
+ CallBuiltin(Builtins::kResolvePromise, context, wrapped_value, value);
|
|
+
|
|
+ // The Promise will be thrown away and not handled, but it shouldn't trigger
|
|
+ // unhandled reject events as its work is done
|
|
+ PromiseSetHasHandler(throwaway);
|
|
+
|
|
+ Label do_perform_promise_then(this);
|
|
+ GotoIfNot(IsDebugActive(), &do_perform_promise_then);
|
|
+ {
|
|
+ Label common(this);
|
|
+ GotoIf(TaggedIsSmi(value), &common);
|
|
+ GotoIfNot(HasInstanceType(value, JS_PROMISE_TYPE), &common);
|
|
+ {
|
|
+ // Mark the reject handler callback to be a forwarding edge, rather
|
|
+ // than a meaningful catch handler
|
|
+ Node* const key =
|
|
+ HeapConstant(factory()->promise_forwarding_handler_symbol());
|
|
+ CallRuntime(Runtime::kSetProperty, context, on_reject, key,
|
|
+ TrueConstant(), SmiConstant(LanguageMode::kStrict));
|
|
+
|
|
+ GotoIf(IsFalse(is_predicted_as_caught), &common);
|
|
+ PromiseSetHandledHint(value);
|
|
+ }
|
|
+
|
|
+ Goto(&common);
|
|
+ BIND(&common);
|
|
+ // Mark the dependency to outer Promise in case the throwaway Promise is
|
|
+ // found on the Promise stack
|
|
+ CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE));
|
|
+
|
|
+ Node* const key = HeapConstant(factory()->promise_handled_by_symbol());
|
|
+ CallRuntime(Runtime::kSetProperty, context, throwaway, key, outer_promise,
|
|
+ SmiConstant(LanguageMode::kStrict));
|
|
+ }
|
|
+
|
|
+ Goto(&do_perform_promise_then);
|
|
+ BIND(&do_perform_promise_then);
|
|
+ return CallBuiltin(Builtins::kPerformPromiseThen, context, wrapped_value,
|
|
+ on_resolve, on_reject, throwaway);
|
|
+}
|
|
+
|
|
+void AsyncBuiltinsAssembler::InitializeNativeClosure(Node* context,
|
|
+ Node* native_context,
|
|
+ Node* function,
|
|
+ Node* context_index) {
|
|
+ Node* const function_map = LoadContextElement(
|
|
+ native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
|
|
+ // Ensure that we don't have to initialize prototype_or_initial_map field of
|
|
+ // JSFunction.
|
|
+ CSA_ASSERT(this, WordEqual(LoadMapInstanceSizeInWords(function_map),
|
|
+ IntPtrConstant(JSFunction::kSizeWithoutPrototype /
|
|
+ kPointerSize)));
|
|
+ STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize);
|
|
+ StoreMapNoWriteBarrier(function, function_map);
|
|
+ StoreObjectFieldRoot(function, JSObject::kPropertiesOrHashOffset,
|
|
+ Heap::kEmptyFixedArrayRootIndex);
|
|
+ StoreObjectFieldRoot(function, JSObject::kElementsOffset,
|
|
+ Heap::kEmptyFixedArrayRootIndex);
|
|
+ StoreObjectFieldRoot(function, JSFunction::kFeedbackCellOffset,
|
|
+ Heap::kManyClosuresCellRootIndex);
|
|
+
|
|
+ Node* shared_info = LoadContextElement(native_context, context_index);
|
|
+ CSA_ASSERT(this, IsSharedFunctionInfo(shared_info));
|
|
+ StoreObjectFieldNoWriteBarrier(
|
|
+ function, JSFunction::kSharedFunctionInfoOffset, shared_info);
|
|
+ StoreObjectFieldNoWriteBarrier(function, JSFunction::kContextOffset, context);
|
|
+
|
|
+ Node* const code = GetSharedFunctionInfoCode(shared_info);
|
|
+ StoreObjectFieldNoWriteBarrier(function, JSFunction::kCodeOffset, code);
|
|
+}
|
|
+
|
|
Node* AsyncBuiltinsAssembler::CreateUnwrapClosure(Node* native_context,
|
|
Node* done) {
|
|
Node* const map = LoadContextElement(
|
|
diff --git a/src/builtins/builtins-async-gen.h b/src/builtins/builtins-async-gen.h
|
|
index 70f68a498b7..45d7c8689a9 100644
|
|
--- a/src/builtins/builtins-async-gen.h
|
|
+++ b/src/builtins/builtins-async-gen.h
|
|
@@ -16,23 +16,48 @@ class AsyncBuiltinsAssembler : public PromiseBuiltinsAssembler {
|
|
: PromiseBuiltinsAssembler(state) {}
|
|
|
|
protected:
|
|
- void Await(Node* context, Node* generator, Node* value, Node* outer_promise,
|
|
- Builtins::Name fulfill_builtin, Builtins::Name reject_builtin,
|
|
- Node* is_predicted_as_caught);
|
|
- void Await(Node* context, Node* generator, Node* value, Node* outer_promise,
|
|
- Builtins::Name fulfill_builtin, Builtins::Name reject_builtin,
|
|
- bool is_predicted_as_caught);
|
|
+ typedef std::function<void(Node*)> ContextInitializer;
|
|
+
|
|
+ // Perform steps to resume generator after `value` is resolved.
|
|
+ // `on_reject_context_index` is an index into the Native Context, which should
|
|
+ // point to a SharedFunctioninfo instance used to create the closure. The
|
|
+ // value following the reject index should be a similar value for the resolve
|
|
+ // closure. Returns the Promise-wrapped `value`.
|
|
+ Node* Await(Node* context, Node* generator, Node* value, Node* outer_promise,
|
|
+ int context_length,
|
|
+ const ContextInitializer& init_closure_context,
|
|
+ Node* on_resolve_context_index, Node* on_reject_context_index,
|
|
+ Node* is_predicted_as_caught);
|
|
+ Node* Await(Node* context, Node* generator, Node* value, Node* outer_promise,
|
|
+ int context_length,
|
|
+ const ContextInitializer& init_closure_context,
|
|
+ int on_resolve_context_index, int on_reject_context_index,
|
|
+ Node* is_predicted_as_caught) {
|
|
+ return Await(context, generator, value, outer_promise, context_length,
|
|
+ init_closure_context, IntPtrConstant(on_resolve_context_index),
|
|
+ IntPtrConstant(on_reject_context_index),
|
|
+ is_predicted_as_caught);
|
|
+ }
|
|
+ Node* Await(Node* context, Node* generator, Node* value, Node* outer_promise,
|
|
+ int context_length,
|
|
+ const ContextInitializer& init_closure_context,
|
|
+ int on_resolve_context_index, int on_reject_context_index,
|
|
+ bool is_predicted_as_caught) {
|
|
+ return Await(context, generator, value, outer_promise, context_length,
|
|
+ init_closure_context, on_resolve_context_index,
|
|
+ on_reject_context_index,
|
|
+ BooleanConstant(is_predicted_as_caught));
|
|
+ }
|
|
|
|
// Return a new built-in function object as defined in
|
|
// Async Iterator Value Unwrap Functions
|
|
Node* CreateUnwrapClosure(Node* const native_context, Node* const done);
|
|
|
|
private:
|
|
+ void InitializeNativeClosure(Node* context, Node* native_context,
|
|
+ Node* function, Node* context_index);
|
|
Node* AllocateAsyncIteratorValueUnwrapContext(Node* native_context,
|
|
Node* done);
|
|
- Node* AllocateAwaitPromiseJobTask(Node* generator, Node* fulfill_handler,
|
|
- Node* reject_handler, Node* promise,
|
|
- Node* context);
|
|
};
|
|
|
|
} // namespace internal
|
|
diff --git a/src/builtins/builtins-async-generator-gen.cc b/src/builtins/builtins-async-generator-gen.cc
|
|
index 290252da624..dd6c6441964 100644
|
|
--- a/src/builtins/builtins-async-generator-gen.cc
|
|
+++ b/src/builtins/builtins-async-generator-gen.cc
|
|
@@ -140,8 +140,8 @@ class AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler {
|
|
// for AsyncGenerators.
|
|
template <typename Descriptor>
|
|
void AsyncGeneratorAwait(bool is_catchable);
|
|
- void AsyncGeneratorAwaitResume(
|
|
- Node* context, Node* generator, Node* argument,
|
|
+ void AsyncGeneratorAwaitResumeClosure(
|
|
+ Node* context, Node* value,
|
|
JSAsyncGeneratorObject::ResumeMode resume_mode);
|
|
};
|
|
|
|
@@ -219,9 +219,11 @@ Node* AsyncGeneratorBuiltinsAssembler::AllocateAsyncGeneratorRequest(
|
|
return request;
|
|
}
|
|
|
|
-void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResume(
|
|
- Node* context, Node* generator, Node* argument,
|
|
+void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResumeClosure(
|
|
+ Node* context, Node* value,
|
|
JSAsyncGeneratorObject::ResumeMode resume_mode) {
|
|
+ Node* const generator =
|
|
+ LoadContextElement(context, AwaitContext::kGeneratorSlot);
|
|
CSA_SLOW_ASSERT(this, TaggedIsAsyncGenerator(generator));
|
|
|
|
SetGeneratorNotAwaiting(generator);
|
|
@@ -233,30 +235,36 @@ void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResume(
|
|
JSGeneratorObject::kResumeModeOffset,
|
|
SmiConstant(resume_mode));
|
|
|
|
- CallStub(CodeFactory::ResumeGenerator(isolate()), context, argument,
|
|
- generator);
|
|
+ CallStub(CodeFactory::ResumeGenerator(isolate()), context, value, generator);
|
|
|
|
TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);
|
|
}
|
|
|
|
template <typename Descriptor>
|
|
void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwait(bool is_catchable) {
|
|
- Node* const generator = Parameter(Descriptor::kGenerator);
|
|
- Node* const value = Parameter(Descriptor::kValue);
|
|
- Node* const context = Parameter(Descriptor::kContext);
|
|
+ Node* generator = Parameter(Descriptor::kGenerator);
|
|
+ Node* value = Parameter(Descriptor::kAwaited);
|
|
+ Node* context = Parameter(Descriptor::kContext);
|
|
|
|
CSA_SLOW_ASSERT(this, TaggedIsAsyncGenerator(generator));
|
|
|
|
Node* const request = LoadFirstAsyncGeneratorRequestFromQueue(generator);
|
|
CSA_ASSERT(this, IsNotUndefined(request));
|
|
|
|
+ ContextInitializer init_closure_context = [&](Node* context) {
|
|
+ StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
|
|
+ generator);
|
|
+ };
|
|
+
|
|
Node* outer_promise =
|
|
LoadObjectField(request, AsyncGeneratorRequest::kPromiseOffset);
|
|
|
|
+ const int resolve_index = Context::ASYNC_GENERATOR_AWAIT_RESOLVE_SHARED_FUN;
|
|
+ const int reject_index = Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN;
|
|
+
|
|
SetGeneratorAwaiting(generator);
|
|
- Await(context, generator, value, outer_promise,
|
|
- Builtins::kAsyncGeneratorAwaitFulfill,
|
|
- Builtins::kAsyncGeneratorAwaitReject, is_catchable);
|
|
+ Await(context, generator, value, outer_promise, AwaitContext::kLength,
|
|
+ init_closure_context, resolve_index, reject_index, is_catchable);
|
|
Return(UndefinedConstant());
|
|
}
|
|
|
|
@@ -367,20 +375,18 @@ TF_BUILTIN(AsyncGeneratorPrototypeThrow, AsyncGeneratorBuiltinsAssembler) {
|
|
"[AsyncGenerator].prototype.throw");
|
|
}
|
|
|
|
-TF_BUILTIN(AsyncGeneratorAwaitFulfill, AsyncGeneratorBuiltinsAssembler) {
|
|
- Node* const generator = Parameter(Descriptor::kGenerator);
|
|
- Node* const argument = Parameter(Descriptor::kArgument);
|
|
- Node* const context = Parameter(Descriptor::kContext);
|
|
- AsyncGeneratorAwaitResume(context, generator, argument,
|
|
- JSAsyncGeneratorObject::kNext);
|
|
+TF_BUILTIN(AsyncGeneratorAwaitResolveClosure, AsyncGeneratorBuiltinsAssembler) {
|
|
+ Node* value = Parameter(Descriptor::kValue);
|
|
+ Node* context = Parameter(Descriptor::kContext);
|
|
+ AsyncGeneratorAwaitResumeClosure(context, value,
|
|
+ JSAsyncGeneratorObject::kNext);
|
|
}
|
|
|
|
-TF_BUILTIN(AsyncGeneratorAwaitReject, AsyncGeneratorBuiltinsAssembler) {
|
|
- Node* const generator = Parameter(Descriptor::kGenerator);
|
|
- Node* const argument = Parameter(Descriptor::kArgument);
|
|
- Node* const context = Parameter(Descriptor::kContext);
|
|
- AsyncGeneratorAwaitResume(context, generator, argument,
|
|
- JSAsyncGeneratorObject::kThrow);
|
|
+TF_BUILTIN(AsyncGeneratorAwaitRejectClosure, AsyncGeneratorBuiltinsAssembler) {
|
|
+ Node* value = Parameter(Descriptor::kValue);
|
|
+ Node* context = Parameter(Descriptor::kContext);
|
|
+ AsyncGeneratorAwaitResumeClosure(context, value,
|
|
+ JSAsyncGeneratorObject::kThrow);
|
|
}
|
|
|
|
TF_BUILTIN(AsyncGeneratorAwaitUncaught, AsyncGeneratorBuiltinsAssembler) {
|
|
@@ -518,34 +524,11 @@ TF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) {
|
|
done);
|
|
}
|
|
|
|
- // We know that {iter_result} itself doesn't have any "then" property and
|
|
- // we also know that the [[Prototype]] of {iter_result} is the intrinsic
|
|
- // %ObjectPrototype%. So we can skip the [[Resolve]] logic here completely
|
|
- // and directly call into the FulfillPromise operation if we can prove
|
|
- // that the %ObjectPrototype% also doesn't have any "then" property. This
|
|
- // is guarded by the Promise#then protector.
|
|
- Label if_fast(this), if_slow(this, Label::kDeferred), return_promise(this);
|
|
- GotoIfForceSlowPath(&if_slow);
|
|
- Branch(IsPromiseThenProtectorCellInvalid(), &if_slow, &if_fast);
|
|
-
|
|
- BIND(&if_fast);
|
|
- {
|
|
- // Skip the "then" on {iter_result} and directly fulfill the {promise}
|
|
- // with the {iter_result}.
|
|
- CallBuiltin(Builtins::kFulfillPromise, context, promise, iter_result);
|
|
- Goto(&return_promise);
|
|
- }
|
|
-
|
|
- BIND(&if_slow);
|
|
- {
|
|
- // Perform Call(promiseCapability.[[Resolve]], undefined, «iteratorResult»).
|
|
- CallBuiltin(Builtins::kResolvePromise, context, promise, iter_result);
|
|
- Goto(&return_promise);
|
|
- }
|
|
+ // Perform Call(promiseCapability.[[Resolve]], undefined, «iteratorResult»).
|
|
+ CallBuiltin(Builtins::kResolvePromise, context, promise, iter_result);
|
|
|
|
// Per spec, AsyncGeneratorResolve() returns undefined. However, for the
|
|
// benefit of %TraceExit(), return the Promise.
|
|
- BIND(&return_promise);
|
|
Return(promise);
|
|
}
|
|
|
|
@@ -571,54 +554,31 @@ TF_BUILTIN(AsyncGeneratorYield, AsyncGeneratorBuiltinsAssembler) {
|
|
Node* const request = LoadFirstAsyncGeneratorRequestFromQueue(generator);
|
|
Node* const outer_promise = LoadPromiseFromAsyncGeneratorRequest(request);
|
|
|
|
- // Mark the generator as "awaiting".
|
|
- SetGeneratorAwaiting(generator);
|
|
+ ContextInitializer init_closure_context = [&](Node* context) {
|
|
+ StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
|
|
+ generator);
|
|
+ };
|
|
|
|
- // We can skip the creation of a temporary promise and the whole
|
|
- // [[Resolve]] logic if we already know that the {value} that's
|
|
- // being yielded is a primitive, as in that case we would immediately
|
|
- // fulfill the temporary promise anyways and schedule a fulfill
|
|
- // reaction job. This gives a nice performance boost for async
|
|
- // generators that yield only primitives, e.g. numbers or strings.
|
|
- Label if_primitive(this), if_generic(this);
|
|
- GotoIfForceSlowPath(&if_generic);
|
|
- GotoIf(IsPromiseHookEnabledOrDebugIsActive(), &if_generic);
|
|
- GotoIf(TaggedIsSmi(value), &if_primitive);
|
|
- Branch(IsJSReceiver(value), &if_generic, &if_primitive);
|
|
-
|
|
- BIND(&if_generic);
|
|
- {
|
|
- Await(context, generator, value, outer_promise,
|
|
- Builtins::kAsyncGeneratorYieldFulfill,
|
|
- Builtins::kAsyncGeneratorAwaitReject, is_caught);
|
|
- Return(UndefinedConstant());
|
|
- }
|
|
+ const int on_resolve = Context::ASYNC_GENERATOR_YIELD_RESOLVE_SHARED_FUN;
|
|
+ const int on_reject = Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN;
|
|
|
|
- BIND(&if_primitive);
|
|
- {
|
|
- // For primitive {value}s we can skip the allocation of the temporary
|
|
- // promise and the resolution of that, and directly allocate the fulfill
|
|
- // reaction job.
|
|
- Node* const microtask = AllocatePromiseReactionJobTask(
|
|
- Heap::kPromiseFulfillReactionJobTaskMapRootIndex, context, value,
|
|
- HeapConstant(Builtins::CallableFor(
|
|
- isolate(), Builtins::kAsyncGeneratorYieldFulfill)
|
|
- .code()),
|
|
- generator);
|
|
- TailCallBuiltin(Builtins::kEnqueueMicrotask, context, microtask);
|
|
- }
|
|
+ SetGeneratorAwaiting(generator);
|
|
+ Await(context, generator, value, outer_promise, AwaitContext::kLength,
|
|
+ init_closure_context, on_resolve, on_reject, is_caught);
|
|
+ Return(UndefinedConstant());
|
|
}
|
|
|
|
-TF_BUILTIN(AsyncGeneratorYieldFulfill, AsyncGeneratorBuiltinsAssembler) {
|
|
+TF_BUILTIN(AsyncGeneratorYieldResolveClosure, AsyncGeneratorBuiltinsAssembler) {
|
|
Node* const context = Parameter(Descriptor::kContext);
|
|
- Node* const generator = Parameter(Descriptor::kGenerator);
|
|
- Node* const argument = Parameter(Descriptor::kArgument);
|
|
+ Node* const value = Parameter(Descriptor::kValue);
|
|
+ Node* const generator =
|
|
+ LoadContextElement(context, AwaitContext::kGeneratorSlot);
|
|
|
|
SetGeneratorNotAwaiting(generator);
|
|
|
|
// Per proposal-async-iteration/#sec-asyncgeneratoryield step 9
|
|
// Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *false*).
|
|
- CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, argument,
|
|
+ CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, value,
|
|
FalseConstant());
|
|
|
|
TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);
|
|
@@ -644,33 +604,39 @@ TF_BUILTIN(AsyncGeneratorReturn, AsyncGeneratorBuiltinsAssembler) {
|
|
Node* const generator = Parameter(Descriptor::kGenerator);
|
|
Node* const value = Parameter(Descriptor::kValue);
|
|
Node* const is_caught = Parameter(Descriptor::kIsCaught);
|
|
- Node* const context = Parameter(Descriptor::kContext);
|
|
Node* const req = LoadFirstAsyncGeneratorRequestFromQueue(generator);
|
|
- Node* const outer_promise = LoadPromiseFromAsyncGeneratorRequest(req);
|
|
CSA_ASSERT(this, IsNotUndefined(req));
|
|
|
|
- Label if_closed(this, Label::kDeferred), if_not_closed(this), done(this);
|
|
+ Label perform_await(this);
|
|
+ VARIABLE(var_on_resolve, MachineType::PointerRepresentation(),
|
|
+ IntPtrConstant(
|
|
+ Context::ASYNC_GENERATOR_RETURN_CLOSED_RESOLVE_SHARED_FUN));
|
|
+ VARIABLE(
|
|
+ var_on_reject, MachineType::PointerRepresentation(),
|
|
+ IntPtrConstant(Context::ASYNC_GENERATOR_RETURN_CLOSED_REJECT_SHARED_FUN));
|
|
+
|
|
Node* const state = LoadGeneratorState(generator);
|
|
- SetGeneratorAwaiting(generator);
|
|
- Branch(IsGeneratorStateClosed(state), &if_closed, &if_not_closed);
|
|
+ GotoIf(IsGeneratorStateClosed(state), &perform_await);
|
|
+ var_on_resolve.Bind(
|
|
+ IntPtrConstant(Context::ASYNC_GENERATOR_RETURN_RESOLVE_SHARED_FUN));
|
|
+ var_on_reject.Bind(
|
|
+ IntPtrConstant(Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN));
|
|
+ Goto(&perform_await);
|
|
|
|
- BIND(&if_closed);
|
|
- {
|
|
- Await(context, generator, value, outer_promise,
|
|
- Builtins::kAsyncGeneratorReturnClosedFulfill,
|
|
- Builtins::kAsyncGeneratorReturnClosedReject, is_caught);
|
|
- Goto(&done);
|
|
- }
|
|
+ BIND(&perform_await);
|
|
|
|
- BIND(&if_not_closed);
|
|
- {
|
|
- Await(context, generator, value, outer_promise,
|
|
- Builtins::kAsyncGeneratorReturnFulfill,
|
|
- Builtins::kAsyncGeneratorAwaitReject, is_caught);
|
|
- Goto(&done);
|
|
- }
|
|
+ ContextInitializer init_closure_context = [&](Node* context) {
|
|
+ StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
|
|
+ generator);
|
|
+ };
|
|
+
|
|
+ SetGeneratorAwaiting(generator);
|
|
+ Node* const context = Parameter(Descriptor::kContext);
|
|
+ Node* const outer_promise = LoadPromiseFromAsyncGeneratorRequest(req);
|
|
+ Await(context, generator, value, outer_promise, AwaitContext::kLength,
|
|
+ init_closure_context, var_on_resolve.value(), var_on_reject.value(),
|
|
+ is_caught);
|
|
|
|
- BIND(&done);
|
|
Return(UndefinedConstant());
|
|
}
|
|
|
|
@@ -678,44 +644,47 @@ TF_BUILTIN(AsyncGeneratorReturn, AsyncGeneratorBuiltinsAssembler) {
|
|
// Resume the generator with "return" resume_mode, and finally perform
|
|
// AsyncGeneratorResumeNext. Per
|
|
// proposal-async-iteration/#sec-asyncgeneratoryield step 8.e
|
|
-TF_BUILTIN(AsyncGeneratorReturnFulfill, AsyncGeneratorBuiltinsAssembler) {
|
|
- Node* const generator = Parameter(Descriptor::kGenerator);
|
|
- Node* const argument = Parameter(Descriptor::kArgument);
|
|
+TF_BUILTIN(AsyncGeneratorReturnResolveClosure,
|
|
+ AsyncGeneratorBuiltinsAssembler) {
|
|
Node* const context = Parameter(Descriptor::kContext);
|
|
- AsyncGeneratorAwaitResume(context, generator, argument,
|
|
- JSGeneratorObject::kReturn);
|
|
+ Node* const value = Parameter(Descriptor::kValue);
|
|
+ AsyncGeneratorAwaitResumeClosure(context, value, JSGeneratorObject::kReturn);
|
|
}
|
|
|
|
// On-resolve closure for Await in AsyncGeneratorReturn
|
|
// Perform AsyncGeneratorResolve({awaited_value}, true) and finally perform
|
|
// AsyncGeneratorResumeNext.
|
|
-TF_BUILTIN(AsyncGeneratorReturnClosedFulfill, AsyncGeneratorBuiltinsAssembler) {
|
|
- Node* const generator = Parameter(Descriptor::kGenerator);
|
|
- Node* const argument = Parameter(Descriptor::kArgument);
|
|
+TF_BUILTIN(AsyncGeneratorReturnClosedResolveClosure,
|
|
+ AsyncGeneratorBuiltinsAssembler) {
|
|
Node* const context = Parameter(Descriptor::kContext);
|
|
+ Node* const value = Parameter(Descriptor::kValue);
|
|
+ Node* const generator =
|
|
+ LoadContextElement(context, AwaitContext::kGeneratorSlot);
|
|
|
|
SetGeneratorNotAwaiting(generator);
|
|
|
|
// https://tc39.github.io/proposal-async-iteration/
|
|
// #async-generator-resume-next-return-processor-fulfilled step 2:
|
|
// Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *true*).
|
|
- CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, argument,
|
|
+ CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, value,
|
|
TrueConstant());
|
|
|
|
TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);
|
|
}
|
|
|
|
-TF_BUILTIN(AsyncGeneratorReturnClosedReject, AsyncGeneratorBuiltinsAssembler) {
|
|
- Node* const generator = Parameter(Descriptor::kGenerator);
|
|
- Node* const argument = Parameter(Descriptor::kArgument);
|
|
+TF_BUILTIN(AsyncGeneratorReturnClosedRejectClosure,
|
|
+ AsyncGeneratorBuiltinsAssembler) {
|
|
Node* const context = Parameter(Descriptor::kContext);
|
|
+ Node* const value = Parameter(Descriptor::kValue);
|
|
+ Node* const generator =
|
|
+ LoadContextElement(context, AwaitContext::kGeneratorSlot);
|
|
|
|
SetGeneratorNotAwaiting(generator);
|
|
|
|
// https://tc39.github.io/proposal-async-iteration/
|
|
// #async-generator-resume-next-return-processor-rejected step 2:
|
|
// Return ! AsyncGeneratorReject(_F_.[[Generator]], _reason_).
|
|
- CallBuiltin(Builtins::kAsyncGeneratorReject, context, generator, argument);
|
|
+ CallBuiltin(Builtins::kAsyncGeneratorReject, context, generator, value);
|
|
|
|
TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);
|
|
}
|
|
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
|
|
index 0f60dfd97e8..5f06abeceb0 100644
|
|
--- a/src/builtins/builtins-definitions.h
|
|
+++ b/src/builtins/builtins-definitions.h
|
|
@@ -381,10 +381,10 @@ namespace internal {
|
|
CPP(ArrayBufferPrototypeSlice) \
|
|
\
|
|
/* AsyncFunction */ \
|
|
- TFC(AsyncFunctionAwaitFulfill, PromiseReactionHandler, 1) \
|
|
- TFC(AsyncFunctionAwaitReject, PromiseReactionHandler, 1) \
|
|
- TFS(AsyncFunctionAwaitCaught, kGenerator, kValue, kOuterPromise) \
|
|
- TFS(AsyncFunctionAwaitUncaught, kGenerator, kValue, kOuterPromise) \
|
|
+ TFJ(AsyncFunctionAwaitCaught, 3, kGenerator, kAwaited, kOuterPromise) \
|
|
+ TFJ(AsyncFunctionAwaitUncaught, 3, kGenerator, kAwaited, kOuterPromise) \
|
|
+ TFJ(AsyncFunctionAwaitRejectClosure, 1, kSentError) \
|
|
+ TFJ(AsyncFunctionAwaitResolveClosure, 1, kSentValue) \
|
|
TFJ(AsyncFunctionPromiseCreate, 0) \
|
|
TFJ(AsyncFunctionPromiseRelease, 1, kPromise) \
|
|
\
|
|
@@ -838,8 +838,8 @@ namespace internal {
|
|
/* ES #sec-promise.prototype.catch */ \
|
|
TFJ(PromisePrototypeCatch, 1, kOnRejected) \
|
|
/* ES #sec-promisereactionjob */ \
|
|
- TFS(PromiseRejectReactionJob, kReason, kHandler, kPayload) \
|
|
- TFS(PromiseFulfillReactionJob, kValue, kHandler, kPayload) \
|
|
+ TFS(PromiseRejectReactionJob, kReason, kHandler, kPromiseOrCapability) \
|
|
+ TFS(PromiseFulfillReactionJob, kValue, kHandler, kPromiseOrCapability) \
|
|
/* ES #sec-promiseresolvethenablejob */ \
|
|
TFS(PromiseResolveThenableJob, kPromiseToResolve, kThenable, kThen) \
|
|
/* ES #sec-promise.resolve */ \
|
|
@@ -1203,17 +1203,6 @@ namespace internal {
|
|
\
|
|
/* AsyncGenerator */ \
|
|
\
|
|
- /* Await (proposal-async-iteration/#await), with resume behaviour */ \
|
|
- /* specific to Async Generators. Internal / Not exposed to JS code. */ \
|
|
- TFS(AsyncGeneratorAwaitCaught, kGenerator, kValue) \
|
|
- TFS(AsyncGeneratorAwaitUncaught, kGenerator, kValue) \
|
|
- TFC(AsyncGeneratorAwaitFulfill, PromiseReactionHandler, 1) \
|
|
- TFC(AsyncGeneratorAwaitReject, PromiseReactionHandler, 1) \
|
|
- TFC(AsyncGeneratorYieldFulfill, PromiseReactionHandler, 1) \
|
|
- TFC(AsyncGeneratorReturnClosedFulfill, PromiseReactionHandler, 1) \
|
|
- TFC(AsyncGeneratorReturnClosedReject, PromiseReactionHandler, 1) \
|
|
- TFC(AsyncGeneratorReturnFulfill, PromiseReactionHandler, 1) \
|
|
- \
|
|
TFS(AsyncGeneratorResolve, kGenerator, kValue, kDone) \
|
|
TFS(AsyncGeneratorReject, kGenerator, kValue) \
|
|
TFS(AsyncGeneratorYield, kGenerator, kValue, kIsCaught) \
|
|
@@ -1236,6 +1225,17 @@ namespace internal {
|
|
TFJ(AsyncGeneratorPrototypeThrow, \
|
|
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
|
\
|
|
+ /* Await (proposal-async-iteration/#await), with resume behaviour */ \
|
|
+ /* specific to Async Generators. Internal / Not exposed to JS code. */ \
|
|
+ TFJ(AsyncGeneratorAwaitCaught, 2, kGenerator, kAwaited) \
|
|
+ TFJ(AsyncGeneratorAwaitUncaught, 2, kGenerator, kAwaited) \
|
|
+ TFJ(AsyncGeneratorAwaitResolveClosure, 1, kValue) \
|
|
+ TFJ(AsyncGeneratorAwaitRejectClosure, 1, kValue) \
|
|
+ TFJ(AsyncGeneratorYieldResolveClosure, 1, kValue) \
|
|
+ TFJ(AsyncGeneratorReturnClosedResolveClosure, 1, kValue) \
|
|
+ TFJ(AsyncGeneratorReturnClosedRejectClosure, 1, kValue) \
|
|
+ TFJ(AsyncGeneratorReturnResolveClosure, 1, kValue) \
|
|
+ \
|
|
/* Async-from-Sync Iterator */ \
|
|
\
|
|
/* %AsyncFromSyncIteratorPrototype% */ \
|
|
@@ -1284,7 +1284,11 @@ namespace internal {
|
|
V(AsyncFromSyncIteratorPrototypeNext) \
|
|
V(AsyncFromSyncIteratorPrototypeReturn) \
|
|
V(AsyncFromSyncIteratorPrototypeThrow) \
|
|
+ V(AsyncFunctionAwaitCaught) \
|
|
+ V(AsyncFunctionAwaitUncaught) \
|
|
V(AsyncGeneratorResolve) \
|
|
+ V(AsyncGeneratorAwaitCaught) \
|
|
+ V(AsyncGeneratorAwaitUncaught) \
|
|
V(PromiseAll) \
|
|
V(PromiseConstructor) \
|
|
V(PromiseConstructorLazyDeoptContinuation) \
|
|
diff --git a/src/builtins/builtins-internal-gen.cc b/src/builtins/builtins-internal-gen.cc
|
|
index e1f4aea4052..4e533ad1c4c 100644
|
|
--- a/src/builtins/builtins-internal-gen.cc
|
|
+++ b/src/builtins/builtins-internal-gen.cc
|
|
@@ -669,7 +669,7 @@ class InternalBuiltinsAssembler : public CodeStubAssembler {
|
|
void LeaveMicrotaskContext();
|
|
|
|
void RunPromiseHook(Runtime::FunctionId id, TNode<Context> context,
|
|
- SloppyTNode<HeapObject> payload);
|
|
+ SloppyTNode<HeapObject> promise_or_capability);
|
|
|
|
TNode<Object> GetPendingException() {
|
|
auto ref = ExternalReference(kPendingExceptionAddress, isolate());
|
|
@@ -790,12 +790,20 @@ void InternalBuiltinsAssembler::LeaveMicrotaskContext() {
|
|
|
|
void InternalBuiltinsAssembler::RunPromiseHook(
|
|
Runtime::FunctionId id, TNode<Context> context,
|
|
- SloppyTNode<HeapObject> payload) {
|
|
+ SloppyTNode<HeapObject> promise_or_capability) {
|
|
Label hook(this, Label::kDeferred), done_hook(this);
|
|
Branch(IsPromiseHookEnabledOrDebugIsActive(), &hook, &done_hook);
|
|
BIND(&hook);
|
|
{
|
|
- CallRuntime(id, context, payload);
|
|
+ // Get to the underlying JSPromise instance.
|
|
+ Node* const promise = Select<HeapObject>(
|
|
+ IsJSPromise(promise_or_capability),
|
|
+ [=] { return promise_or_capability; },
|
|
+ [=] {
|
|
+ return CAST(LoadObjectField(promise_or_capability,
|
|
+ PromiseCapability::kPromiseOffset));
|
|
+ });
|
|
+ CallRuntime(id, context, promise);
|
|
Goto(&done_hook);
|
|
}
|
|
BIND(&done_hook);
|
|
@@ -1008,19 +1016,21 @@ TF_BUILTIN(RunMicrotasks, InternalBuiltinsAssembler) {
|
|
LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset);
|
|
Node* const handler =
|
|
LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset);
|
|
- Node* const payload =
|
|
- LoadObjectField(microtask, PromiseReactionJobTask::kPayloadOffset);
|
|
+ Node* const promise_or_capability = LoadObjectField(
|
|
+ microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset);
|
|
|
|
// Run the promise before/debug hook if enabled.
|
|
- RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, payload);
|
|
+ RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context,
|
|
+ promise_or_capability);
|
|
|
|
Node* const result =
|
|
CallBuiltin(Builtins::kPromiseFulfillReactionJob, microtask_context,
|
|
- argument, handler, payload);
|
|
+ argument, handler, promise_or_capability);
|
|
GotoIfException(result, &if_exception, &var_exception);
|
|
|
|
// Run the promise after/debug hook if enabled.
|
|
- RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, payload);
|
|
+ RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context,
|
|
+ promise_or_capability);
|
|
|
|
LeaveMicrotaskContext();
|
|
SetCurrentContext(current_context);
|
|
@@ -1041,19 +1051,21 @@ TF_BUILTIN(RunMicrotasks, InternalBuiltinsAssembler) {
|
|
LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset);
|
|
Node* const handler =
|
|
LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset);
|
|
- Node* const payload =
|
|
- LoadObjectField(microtask, PromiseReactionJobTask::kPayloadOffset);
|
|
+ Node* const promise_or_capability = LoadObjectField(
|
|
+ microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset);
|
|
|
|
// Run the promise before/debug hook if enabled.
|
|
- RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, payload);
|
|
+ RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context,
|
|
+ promise_or_capability);
|
|
|
|
Node* const result =
|
|
CallBuiltin(Builtins::kPromiseRejectReactionJob, microtask_context,
|
|
- argument, handler, payload);
|
|
+ argument, handler, promise_or_capability);
|
|
GotoIfException(result, &if_exception, &var_exception);
|
|
|
|
// Run the promise after/debug hook if enabled.
|
|
- RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, payload);
|
|
+ RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context,
|
|
+ promise_or_capability);
|
|
|
|
LeaveMicrotaskContext();
|
|
SetCurrentContext(current_context);
|
|
diff --git a/src/builtins/builtins-promise-gen.cc b/src/builtins/builtins-promise-gen.cc
|
|
index dd38dbc5435..868b45a8316 100644
|
|
--- a/src/builtins/builtins-promise-gen.cc
|
|
+++ b/src/builtins/builtins-promise-gen.cc
|
|
@@ -391,15 +391,15 @@ TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) {
|
|
Return(result_promise);
|
|
}
|
|
|
|
-Node* PromiseBuiltinsAssembler::AllocatePromiseReaction(Node* next,
|
|
- Node* payload,
|
|
- Node* fulfill_handler,
|
|
- Node* reject_handler) {
|
|
+Node* PromiseBuiltinsAssembler::AllocatePromiseReaction(
|
|
+ Node* next, Node* promise_or_capability, Node* fulfill_handler,
|
|
+ Node* reject_handler) {
|
|
Node* const reaction = Allocate(PromiseReaction::kSize);
|
|
StoreMapNoWriteBarrier(reaction, Heap::kPromiseReactionMapRootIndex);
|
|
StoreObjectFieldNoWriteBarrier(reaction, PromiseReaction::kNextOffset, next);
|
|
- StoreObjectFieldNoWriteBarrier(reaction, PromiseReaction::kPayloadOffset,
|
|
- payload);
|
|
+ StoreObjectFieldNoWriteBarrier(reaction,
|
|
+ PromiseReaction::kPromiseOrCapabilityOffset,
|
|
+ promise_or_capability);
|
|
StoreObjectFieldNoWriteBarrier(
|
|
reaction, PromiseReaction::kFulfillHandlerOffset, fulfill_handler);
|
|
StoreObjectFieldNoWriteBarrier(
|
|
@@ -408,7 +408,8 @@ Node* PromiseBuiltinsAssembler::AllocatePromiseReaction(Node* next,
|
|
}
|
|
|
|
Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask(
|
|
- Node* map, Node* context, Node* argument, Node* handler, Node* payload) {
|
|
+ Node* map, Node* context, Node* argument, Node* handler,
|
|
+ Node* promise_or_capability) {
|
|
Node* const microtask = Allocate(PromiseReactionJobTask::kSize);
|
|
StoreMapNoWriteBarrier(microtask, map);
|
|
StoreObjectFieldNoWriteBarrier(
|
|
@@ -418,18 +419,19 @@ Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask(
|
|
StoreObjectFieldNoWriteBarrier(
|
|
microtask, PromiseReactionJobTask::kHandlerOffset, handler);
|
|
StoreObjectFieldNoWriteBarrier(
|
|
- microtask, PromiseReactionJobTask::kPayloadOffset, payload);
|
|
+ microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset,
|
|
+ promise_or_capability);
|
|
return microtask;
|
|
}
|
|
|
|
Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask(
|
|
Heap::RootListIndex map_root_index, Node* context, Node* argument,
|
|
- Node* handler, Node* payload) {
|
|
+ Node* handler, Node* promise_or_capability) {
|
|
DCHECK(map_root_index == Heap::kPromiseFulfillReactionJobTaskMapRootIndex ||
|
|
map_root_index == Heap::kPromiseRejectReactionJobTaskMapRootIndex);
|
|
Node* const map = LoadRoot(map_root_index);
|
|
return AllocatePromiseReactionJobTask(map, context, argument, handler,
|
|
- payload);
|
|
+ promise_or_capability);
|
|
}
|
|
|
|
Node* PromiseBuiltinsAssembler::AllocatePromiseResolveThenableJobTask(
|
|
@@ -502,8 +504,8 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions(
|
|
context);
|
|
STATIC_ASSERT(PromiseReaction::kFulfillHandlerOffset ==
|
|
PromiseReactionJobTask::kHandlerOffset);
|
|
- STATIC_ASSERT(PromiseReaction::kPayloadOffset ==
|
|
- PromiseReactionJobTask::kPayloadOffset);
|
|
+ STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset ==
|
|
+ PromiseReactionJobTask::kPromiseOrCapabilityOffset);
|
|
} else {
|
|
Node* handler =
|
|
LoadObjectField(current, PromiseReaction::kRejectHandlerOffset);
|
|
@@ -515,8 +517,8 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions(
|
|
context);
|
|
StoreObjectField(current, PromiseReactionJobTask::kHandlerOffset,
|
|
handler);
|
|
- STATIC_ASSERT(PromiseReaction::kPayloadOffset ==
|
|
- PromiseReactionJobTask::kPayloadOffset);
|
|
+ STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset ==
|
|
+ PromiseReactionJobTask::kPromiseOrCapabilityOffset);
|
|
}
|
|
CallBuiltin(Builtins::kEnqueueMicrotask, NoContextConstant(), current);
|
|
Goto(&loop);
|
|
@@ -1118,28 +1120,20 @@ TF_BUILTIN(PromiseResolveThenableJob, PromiseBuiltinsAssembler) {
|
|
|
|
// ES #sec-promisereactionjob
|
|
void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument,
|
|
- Node* handler, Node* payload,
|
|
+ Node* handler,
|
|
+ Node* promise_or_capability,
|
|
PromiseReaction::Type type) {
|
|
CSA_ASSERT(this, TaggedIsNotSmi(handler));
|
|
- CSA_ASSERT(this, Word32Or(IsCallable(handler),
|
|
- Word32Or(IsCode(handler), IsUndefined(handler))));
|
|
- CSA_ASSERT(this, TaggedIsNotSmi(payload));
|
|
+ CSA_ASSERT(this, Word32Or(IsUndefined(handler), IsCallable(handler)));
|
|
+ CSA_ASSERT(this, TaggedIsNotSmi(promise_or_capability));
|
|
+ CSA_ASSERT(this, Word32Or(IsJSPromise(promise_or_capability),
|
|
+ IsPromiseCapability(promise_or_capability)));
|
|
|
|
VARIABLE(var_handler_result, MachineRepresentation::kTagged, argument);
|
|
- Label if_handler_callable(this), if_fulfill(this), if_reject(this),
|
|
- if_code_handler(this);
|
|
-
|
|
- GotoIf(IsUndefined(handler),
|
|
- type == PromiseReaction::kFulfill ? &if_fulfill : &if_reject);
|
|
- Branch(IsCode(handler), &if_code_handler, &if_handler_callable);
|
|
-
|
|
- BIND(&if_code_handler);
|
|
- {
|
|
- // The {handler} is a Code object that knows how to deal with
|
|
- // the {payload} and the {argument}.
|
|
- PromiseReactionHandlerDescriptor descriptor(isolate());
|
|
- TailCallStub(descriptor, handler, context, argument, payload);
|
|
- }
|
|
+ Label if_handler_callable(this), if_fulfill(this), if_reject(this);
|
|
+ Branch(IsUndefined(handler),
|
|
+ type == PromiseReaction::kFulfill ? &if_fulfill : &if_reject,
|
|
+ &if_handler_callable);
|
|
|
|
BIND(&if_handler_callable);
|
|
{
|
|
@@ -1155,22 +1149,24 @@ void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument,
|
|
{
|
|
Label if_promise(this), if_promise_capability(this, Label::kDeferred);
|
|
Node* const value = var_handler_result.value();
|
|
- Branch(IsPromiseCapability(payload), &if_promise_capability, &if_promise);
|
|
+ Branch(IsPromiseCapability(promise_or_capability), &if_promise_capability,
|
|
+ &if_promise);
|
|
|
|
BIND(&if_promise);
|
|
{
|
|
// For fast native promises we can skip the indirection
|
|
// via the promiseCapability.[[Resolve]] function and
|
|
// run the resolve logic directly from here.
|
|
- TailCallBuiltin(Builtins::kResolvePromise, context, payload, value);
|
|
+ TailCallBuiltin(Builtins::kResolvePromise, context, promise_or_capability,
|
|
+ value);
|
|
}
|
|
|
|
BIND(&if_promise_capability);
|
|
{
|
|
// In the general case we need to call the (user provided)
|
|
// promiseCapability.[[Resolve]] function.
|
|
- Node* const resolve =
|
|
- LoadObjectField(payload, PromiseCapability::kResolveOffset);
|
|
+ Node* const resolve = LoadObjectField(promise_or_capability,
|
|
+ PromiseCapability::kResolveOffset);
|
|
Node* const result = CallJS(
|
|
CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
|
|
context, resolve, UndefinedConstant(), value);
|
|
@@ -1183,15 +1179,16 @@ void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument,
|
|
if (type == PromiseReaction::kReject) {
|
|
Label if_promise(this), if_promise_capability(this, Label::kDeferred);
|
|
Node* const reason = var_handler_result.value();
|
|
- Branch(IsPromiseCapability(payload), &if_promise_capability, &if_promise);
|
|
+ Branch(IsPromiseCapability(promise_or_capability), &if_promise_capability,
|
|
+ &if_promise);
|
|
|
|
BIND(&if_promise);
|
|
{
|
|
// For fast native promises we can skip the indirection
|
|
// via the promiseCapability.[[Reject]] function and
|
|
// run the resolve logic directly from here.
|
|
- TailCallBuiltin(Builtins::kRejectPromise, context, payload, reason,
|
|
- FalseConstant());
|
|
+ TailCallBuiltin(Builtins::kRejectPromise, context, promise_or_capability,
|
|
+ reason, FalseConstant());
|
|
}
|
|
|
|
BIND(&if_promise_capability);
|
|
@@ -1201,8 +1198,8 @@ void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument,
|
|
Label if_exception(this, Label::kDeferred);
|
|
VARIABLE(var_exception, MachineRepresentation::kTagged,
|
|
TheHoleConstant());
|
|
- Node* const reject =
|
|
- LoadObjectField(payload, PromiseCapability::kRejectOffset);
|
|
+ Node* const reject = LoadObjectField(promise_or_capability,
|
|
+ PromiseCapability::kRejectOffset);
|
|
Node* const result = CallJS(
|
|
CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
|
|
context, reject, UndefinedConstant(), reason);
|
|
@@ -1219,7 +1216,8 @@ void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument,
|
|
// predictions in the debugger will be wrong, which just walks the stack
|
|
// and checks for certain builtins.
|
|
TailCallBuiltin(Builtins::kPromiseRejectReactionJob, context,
|
|
- var_handler_result.value(), UndefinedConstant(), payload);
|
|
+ var_handler_result.value(), UndefinedConstant(),
|
|
+ promise_or_capability);
|
|
}
|
|
}
|
|
|
|
@@ -1228,9 +1226,10 @@ TF_BUILTIN(PromiseFulfillReactionJob, PromiseBuiltinsAssembler) {
|
|
Node* const context = Parameter(Descriptor::kContext);
|
|
Node* const value = Parameter(Descriptor::kValue);
|
|
Node* const handler = Parameter(Descriptor::kHandler);
|
|
- Node* const payload = Parameter(Descriptor::kPayload);
|
|
+ Node* const promise_or_capability =
|
|
+ Parameter(Descriptor::kPromiseOrCapability);
|
|
|
|
- PromiseReactionJob(context, value, handler, payload,
|
|
+ PromiseReactionJob(context, value, handler, promise_or_capability,
|
|
PromiseReaction::kFulfill);
|
|
}
|
|
|
|
@@ -1239,9 +1238,10 @@ TF_BUILTIN(PromiseRejectReactionJob, PromiseBuiltinsAssembler) {
|
|
Node* const context = Parameter(Descriptor::kContext);
|
|
Node* const reason = Parameter(Descriptor::kReason);
|
|
Node* const handler = Parameter(Descriptor::kHandler);
|
|
- Node* const payload = Parameter(Descriptor::kPayload);
|
|
+ Node* const promise_or_capability =
|
|
+ Parameter(Descriptor::kPromiseOrCapability);
|
|
|
|
- PromiseReactionJob(context, reason, handler, payload,
|
|
+ PromiseReactionJob(context, reason, handler, promise_or_capability,
|
|
PromiseReaction::kReject);
|
|
}
|
|
|
|
@@ -1717,23 +1717,21 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) {
|
|
|
|
// 7. If Type(resolution) is not Object, then
|
|
GotoIf(TaggedIsSmi(resolution), &if_fulfill);
|
|
- Node* const resolution_map = LoadMap(resolution);
|
|
- GotoIfNot(IsJSReceiverMap(resolution_map), &if_fulfill);
|
|
+ Node* const result_map = LoadMap(resolution);
|
|
+ GotoIfNot(IsJSReceiverMap(result_map), &if_fulfill);
|
|
|
|
// We can skip the "then" lookup on {resolution} if its [[Prototype]]
|
|
// is the (initial) Promise.prototype and the Promise#then protector
|
|
// is intact, as that guards the lookup path for the "then" property
|
|
// on JSPromise instances which have the (initial) %PromisePrototype%.
|
|
- Label if_fast(this), if_generic(this), if_slow(this, Label::kDeferred);
|
|
+ Label if_fast(this), if_slow(this, Label::kDeferred);
|
|
Node* const native_context = LoadNativeContext(context);
|
|
- GotoIfForceSlowPath(&if_slow);
|
|
- GotoIf(IsPromiseThenProtectorCellInvalid(), &if_slow);
|
|
- GotoIfNot(IsJSPromiseMap(resolution_map), &if_generic);
|
|
- Node* const promise_prototype =
|
|
- LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
|
|
- Branch(WordEqual(LoadMapPrototype(resolution_map), promise_prototype),
|
|
- &if_fast, &if_slow);
|
|
+ BranchIfPromiseThenLookupChainIntact(native_context, result_map, &if_fast,
|
|
+ &if_slow);
|
|
|
|
+ // Resolution is a native promise and if it's already resolved or
|
|
+ // rejected, shortcircuit the resolution procedure by directly
|
|
+ // reusing the value from the promise.
|
|
BIND(&if_fast);
|
|
{
|
|
Node* const then =
|
|
@@ -1742,21 +1740,6 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) {
|
|
Goto(&do_enqueue);
|
|
}
|
|
|
|
- BIND(&if_generic);
|
|
- {
|
|
- // We can skip the lookup of "then" if the {resolution} is a (newly
|
|
- // created) IterResultObject, as the Promise#then protector also
|
|
- // ensures that the intrinsic %ObjectPrototype% doesn't contain any
|
|
- // "then" property. This helps to avoid negative lookups on iterator
|
|
- // results from async generators.
|
|
- CSA_ASSERT(this, IsJSReceiverMap(resolution_map));
|
|
- CSA_ASSERT(this, Word32BinaryNot(IsPromiseThenProtectorCellInvalid()));
|
|
- Node* const iterator_result_map =
|
|
- LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
|
|
- Branch(WordEqual(resolution_map, iterator_result_map), &if_fulfill,
|
|
- &if_slow);
|
|
- }
|
|
-
|
|
BIND(&if_slow);
|
|
{
|
|
// 8. Let then be Get(resolution, "then").
|
|
diff --git a/src/builtins/builtins-promise-gen.h b/src/builtins/builtins-promise-gen.h
|
|
index f21d86a141a..694cea28c06 100644
|
|
--- a/src/builtins/builtins-promise-gen.h
|
|
+++ b/src/builtins/builtins-promise-gen.h
|
|
@@ -85,14 +85,16 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler {
|
|
Node* AllocateAndSetJSPromise(Node* context, v8::Promise::PromiseState status,
|
|
Node* result);
|
|
|
|
- Node* AllocatePromiseReaction(Node* next, Node* payload,
|
|
+ Node* AllocatePromiseReaction(Node* next, Node* promise_or_capability,
|
|
Node* fulfill_handler, Node* reject_handler);
|
|
|
|
Node* AllocatePromiseReactionJobTask(Heap::RootListIndex map_root_index,
|
|
Node* context, Node* argument,
|
|
- Node* handler, Node* payload);
|
|
+ Node* handler,
|
|
+ Node* promise_or_capability);
|
|
Node* AllocatePromiseReactionJobTask(Node* map, Node* context, Node* argument,
|
|
- Node* handler, Node* payload);
|
|
+ Node* handler,
|
|
+ Node* promise_or_capability);
|
|
Node* AllocatePromiseResolveThenableJobTask(Node* promise_to_resolve,
|
|
Node* then, Node* thenable,
|
|
Node* context);
|
|
@@ -192,7 +194,8 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler {
|
|
Node* PromiseStatus(Node* promise);
|
|
|
|
void PromiseReactionJob(Node* context, Node* argument, Node* handler,
|
|
- Node* payload, PromiseReaction::Type type);
|
|
+ Node* promise_or_capability,
|
|
+ PromiseReaction::Type type);
|
|
|
|
Node* IsPromiseStatus(Node* actual, v8::Promise::PromiseState expected);
|
|
void PromiseSetStatus(Node* promise, v8::Promise::PromiseState status);
|
|
diff --git a/src/builtins/builtins.cc b/src/builtins/builtins.cc
|
|
index c348248fffb..7e6a0459a7d 100644
|
|
--- a/src/builtins/builtins.cc
|
|
+++ b/src/builtins/builtins.cc
|
|
@@ -364,17 +364,12 @@ bool Builtins::IsIsolateIndependent(int index) {
|
|
case kAsyncFromSyncIteratorPrototypeNext:
|
|
case kAsyncFromSyncIteratorPrototypeReturn:
|
|
case kAsyncFromSyncIteratorPrototypeThrow:
|
|
- case kAsyncFunctionAwaitFulfill:
|
|
- case kAsyncFunctionAwaitReject:
|
|
+ case kAsyncFunctionAwaitCaught:
|
|
case kAsyncFunctionPromiseCreate:
|
|
case kAsyncFunctionPromiseRelease:
|
|
- case kAsyncGeneratorAwaitFulfill:
|
|
- case kAsyncGeneratorAwaitReject:
|
|
case kAsyncGeneratorResumeNext:
|
|
- case kAsyncGeneratorReturnClosedFulfill:
|
|
- case kAsyncGeneratorReturnClosedReject:
|
|
- case kAsyncGeneratorReturnFulfill:
|
|
- case kAsyncGeneratorYieldFulfill:
|
|
+ case kAsyncGeneratorReturnClosedRejectClosure:
|
|
+ case kAsyncGeneratorReturn:
|
|
case kAsyncIteratorValueUnwrap:
|
|
case kBitwiseNot:
|
|
case kBooleanPrototypeToString:
|
|
diff --git a/src/compiler/js-intrinsic-lowering.cc b/src/compiler/js-intrinsic-lowering.cc
|
|
index c570a1f8ddc..d9742e47d9f 100644
|
|
--- a/src/compiler/js-intrinsic-lowering.cc
|
|
+++ b/src/compiler/js-intrinsic-lowering.cc
|
|
@@ -41,14 +41,6 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
|
|
return ReduceCreateJSGeneratorObject(node);
|
|
case Runtime::kInlineGeneratorGetInputOrDebugPos:
|
|
return ReduceGeneratorGetInputOrDebugPos(node);
|
|
- case Runtime::kInlineAsyncFunctionAwaitCaught:
|
|
- return ReduceAsyncFunctionAwaitCaught(node);
|
|
- case Runtime::kInlineAsyncFunctionAwaitUncaught:
|
|
- return ReduceAsyncFunctionAwaitUncaught(node);
|
|
- case Runtime::kInlineAsyncGeneratorAwaitCaught:
|
|
- return ReduceAsyncGeneratorAwaitCaught(node);
|
|
- case Runtime::kInlineAsyncGeneratorAwaitUncaught:
|
|
- return ReduceAsyncGeneratorAwaitUncaught(node);
|
|
case Runtime::kInlineAsyncGeneratorReject:
|
|
return ReduceAsyncGeneratorReject(node);
|
|
case Runtime::kInlineAsyncGeneratorResolve:
|
|
@@ -185,33 +177,6 @@ Reduction JSIntrinsicLowering::ReduceGeneratorGetInputOrDebugPos(Node* node) {
|
|
return Change(node, op, generator, effect, control);
|
|
}
|
|
|
|
-Reduction JSIntrinsicLowering::ReduceAsyncFunctionAwaitCaught(Node* node) {
|
|
- return Change(
|
|
- node,
|
|
- Builtins::CallableFor(isolate(), Builtins::kAsyncFunctionAwaitCaught), 0);
|
|
-}
|
|
-
|
|
-Reduction JSIntrinsicLowering::ReduceAsyncFunctionAwaitUncaught(Node* node) {
|
|
- return Change(
|
|
- node,
|
|
- Builtins::CallableFor(isolate(), Builtins::kAsyncFunctionAwaitUncaught),
|
|
- 0);
|
|
-}
|
|
-
|
|
-Reduction JSIntrinsicLowering::ReduceAsyncGeneratorAwaitCaught(Node* node) {
|
|
- return Change(
|
|
- node,
|
|
- Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorAwaitCaught),
|
|
- 0);
|
|
-}
|
|
-
|
|
-Reduction JSIntrinsicLowering::ReduceAsyncGeneratorAwaitUncaught(Node* node) {
|
|
- return Change(
|
|
- node,
|
|
- Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorAwaitUncaught),
|
|
- 0);
|
|
-}
|
|
-
|
|
Reduction JSIntrinsicLowering::ReduceAsyncGeneratorReject(Node* node) {
|
|
return Change(
|
|
node, Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorReject),
|
|
diff --git a/src/compiler/js-intrinsic-lowering.h b/src/compiler/js-intrinsic-lowering.h
|
|
index fb745986a60..18fe1248c7a 100644
|
|
--- a/src/compiler/js-intrinsic-lowering.h
|
|
+++ b/src/compiler/js-intrinsic-lowering.h
|
|
@@ -45,10 +45,6 @@ class V8_EXPORT_PRIVATE JSIntrinsicLowering final
|
|
Reduction ReduceCreateJSGeneratorObject(Node* node);
|
|
Reduction ReduceGeneratorClose(Node* node);
|
|
Reduction ReduceGeneratorGetInputOrDebugPos(Node* node);
|
|
- Reduction ReduceAsyncFunctionAwaitCaught(Node* node);
|
|
- Reduction ReduceAsyncFunctionAwaitUncaught(Node* node);
|
|
- Reduction ReduceAsyncGeneratorAwaitCaught(Node* node);
|
|
- Reduction ReduceAsyncGeneratorAwaitUncaught(Node* node);
|
|
Reduction ReduceAsyncGeneratorReject(Node* node);
|
|
Reduction ReduceAsyncGeneratorResolve(Node* node);
|
|
Reduction ReduceAsyncGeneratorYield(Node* node);
|
|
diff --git a/src/contexts.h b/src/contexts.h
|
|
index 6fc6f2d1c32..fcfeccdc44e 100644
|
|
--- a/src/contexts.h
|
|
+++ b/src/contexts.h
|
|
@@ -32,37 +32,44 @@ enum ContextLookupFlags {
|
|
// must always be allocated via Heap::AllocateContext() or
|
|
// Factory::NewContext.
|
|
|
|
-#define NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V) \
|
|
- V(ASYNC_FUNCTION_PROMISE_CREATE_INDEX, JSFunction, \
|
|
- async_function_promise_create) \
|
|
- V(ASYNC_FUNCTION_PROMISE_RELEASE_INDEX, JSFunction, \
|
|
- async_function_promise_release) \
|
|
- V(IS_ARRAYLIKE, JSFunction, is_arraylike) \
|
|
- V(GENERATOR_NEXT_INTERNAL, JSFunction, generator_next_internal) \
|
|
- V(MAKE_ERROR_INDEX, JSFunction, make_error) \
|
|
- V(MAKE_RANGE_ERROR_INDEX, JSFunction, make_range_error) \
|
|
- V(MAKE_SYNTAX_ERROR_INDEX, JSFunction, make_syntax_error) \
|
|
- V(MAKE_TYPE_ERROR_INDEX, JSFunction, make_type_error) \
|
|
- V(MAKE_URI_ERROR_INDEX, JSFunction, make_uri_error) \
|
|
- V(OBJECT_CREATE, JSFunction, object_create) \
|
|
- V(OBJECT_DEFINE_PROPERTIES, JSFunction, object_define_properties) \
|
|
- V(OBJECT_DEFINE_PROPERTY, JSFunction, object_define_property) \
|
|
- V(OBJECT_GET_PROTOTYPE_OF, JSFunction, object_get_prototype_of) \
|
|
- V(OBJECT_IS_EXTENSIBLE, JSFunction, object_is_extensible) \
|
|
- V(OBJECT_IS_FROZEN, JSFunction, object_is_frozen) \
|
|
- V(OBJECT_IS_SEALED, JSFunction, object_is_sealed) \
|
|
- V(OBJECT_KEYS, JSFunction, object_keys) \
|
|
- V(REGEXP_INTERNAL_MATCH, JSFunction, regexp_internal_match) \
|
|
- V(REFLECT_APPLY_INDEX, JSFunction, reflect_apply) \
|
|
- V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \
|
|
- V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \
|
|
- V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
|
|
- V(MATH_FLOOR_INDEX, JSFunction, math_floor) \
|
|
- V(MATH_POW_INDEX, JSFunction, math_pow) \
|
|
- V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \
|
|
- promise_internal_constructor) \
|
|
- V(IS_PROMISE_INDEX, JSFunction, is_promise) \
|
|
- V(PROMISE_THEN_INDEX, JSFunction, promise_then)
|
|
+#define NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V) \
|
|
+ V(ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX, JSFunction, \
|
|
+ async_function_await_caught) \
|
|
+ V(ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX, JSFunction, \
|
|
+ async_function_await_uncaught) \
|
|
+ V(ASYNC_FUNCTION_PROMISE_CREATE_INDEX, JSFunction, \
|
|
+ async_function_promise_create) \
|
|
+ V(ASYNC_FUNCTION_PROMISE_RELEASE_INDEX, JSFunction, \
|
|
+ async_function_promise_release) \
|
|
+ V(IS_ARRAYLIKE, JSFunction, is_arraylike) \
|
|
+ V(GENERATOR_NEXT_INTERNAL, JSFunction, generator_next_internal) \
|
|
+ V(MAKE_ERROR_INDEX, JSFunction, make_error) \
|
|
+ V(MAKE_RANGE_ERROR_INDEX, JSFunction, make_range_error) \
|
|
+ V(MAKE_SYNTAX_ERROR_INDEX, JSFunction, make_syntax_error) \
|
|
+ V(MAKE_TYPE_ERROR_INDEX, JSFunction, make_type_error) \
|
|
+ V(MAKE_URI_ERROR_INDEX, JSFunction, make_uri_error) \
|
|
+ V(OBJECT_CREATE, JSFunction, object_create) \
|
|
+ V(OBJECT_DEFINE_PROPERTIES, JSFunction, object_define_properties) \
|
|
+ V(OBJECT_DEFINE_PROPERTY, JSFunction, object_define_property) \
|
|
+ V(OBJECT_GET_PROTOTYPE_OF, JSFunction, object_get_prototype_of) \
|
|
+ V(OBJECT_IS_EXTENSIBLE, JSFunction, object_is_extensible) \
|
|
+ V(OBJECT_IS_FROZEN, JSFunction, object_is_frozen) \
|
|
+ V(OBJECT_IS_SEALED, JSFunction, object_is_sealed) \
|
|
+ V(OBJECT_KEYS, JSFunction, object_keys) \
|
|
+ V(REGEXP_INTERNAL_MATCH, JSFunction, regexp_internal_match) \
|
|
+ V(REFLECT_APPLY_INDEX, JSFunction, reflect_apply) \
|
|
+ V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \
|
|
+ V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \
|
|
+ V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
|
|
+ V(MATH_FLOOR_INDEX, JSFunction, math_floor) \
|
|
+ V(MATH_POW_INDEX, JSFunction, math_pow) \
|
|
+ V(NEW_PROMISE_CAPABILITY_INDEX, JSFunction, new_promise_capability) \
|
|
+ V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \
|
|
+ promise_internal_constructor) \
|
|
+ V(IS_PROMISE_INDEX, JSFunction, is_promise) \
|
|
+ V(PROMISE_THEN_INDEX, JSFunction, promise_then) \
|
|
+ V(ASYNC_GENERATOR_AWAIT_CAUGHT, JSFunction, async_generator_await_caught) \
|
|
+ V(ASYNC_GENERATOR_AWAIT_UNCAUGHT, JSFunction, async_generator_await_uncaught)
|
|
|
|
#define NATIVE_CONTEXT_IMPORTED_FIELDS(V) \
|
|
V(ARRAY_POP_INDEX, JSFunction, array_pop) \
|
|
@@ -116,11 +123,27 @@ enum ContextLookupFlags {
|
|
V(ARRAY_BUFFER_NOINIT_FUN_INDEX, JSFunction, array_buffer_noinit_fun) \
|
|
V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
|
|
V(ASYNC_FROM_SYNC_ITERATOR_MAP_INDEX, Map, async_from_sync_iterator_map) \
|
|
+ V(ASYNC_FUNCTION_AWAIT_REJECT_SHARED_FUN, SharedFunctionInfo, \
|
|
+ async_function_await_reject_shared_fun) \
|
|
+ V(ASYNC_FUNCTION_AWAIT_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
|
|
+ async_function_await_resolve_shared_fun) \
|
|
V(ASYNC_FUNCTION_FUNCTION_INDEX, JSFunction, async_function_constructor) \
|
|
V(ASYNC_GENERATOR_FUNCTION_FUNCTION_INDEX, JSFunction, \
|
|
async_generator_function_function) \
|
|
V(ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN, SharedFunctionInfo, \
|
|
async_iterator_value_unwrap_shared_fun) \
|
|
+ V(ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN, SharedFunctionInfo, \
|
|
+ async_generator_await_reject_shared_fun) \
|
|
+ V(ASYNC_GENERATOR_AWAIT_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
|
|
+ async_generator_await_resolve_shared_fun) \
|
|
+ V(ASYNC_GENERATOR_YIELD_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
|
|
+ async_generator_yield_resolve_shared_fun) \
|
|
+ V(ASYNC_GENERATOR_RETURN_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
|
|
+ async_generator_return_resolve_shared_fun) \
|
|
+ V(ASYNC_GENERATOR_RETURN_CLOSED_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
|
|
+ async_generator_return_closed_resolve_shared_fun) \
|
|
+ V(ASYNC_GENERATOR_RETURN_CLOSED_REJECT_SHARED_FUN, SharedFunctionInfo, \
|
|
+ async_generator_return_closed_reject_shared_fun) \
|
|
V(ATOMICS_OBJECT, JSObject, atomics_object) \
|
|
V(BIGINT_FUNCTION_INDEX, JSFunction, bigint_function) \
|
|
V(BIGINT64_ARRAY_FUN_INDEX, JSFunction, bigint64_array_fun) \
|
|
diff --git a/src/heap-symbols.h b/src/heap-symbols.h
|
|
index 82ecd766575..c15aa9ba138 100644
|
|
--- a/src/heap-symbols.h
|
|
+++ b/src/heap-symbols.h
|
|
@@ -237,7 +237,6 @@
|
|
V(error_script_symbol) \
|
|
V(error_start_pos_symbol) \
|
|
V(frozen_symbol) \
|
|
- V(generator_outer_promise_symbol) \
|
|
V(generic_symbol) \
|
|
V(home_object_symbol) \
|
|
V(intl_initialized_marker_symbol) \
|
|
diff --git a/src/interface-descriptors.h b/src/interface-descriptors.h
|
|
index 61da0c3f4ea..8375ea11971 100644
|
|
--- a/src/interface-descriptors.h
|
|
+++ b/src/interface-descriptors.h
|
|
@@ -81,7 +81,6 @@ class PlatformInterfaceDescriptor;
|
|
V(FrameDropperTrampoline) \
|
|
V(WasmRuntimeCall) \
|
|
V(RunMicrotasks) \
|
|
- V(PromiseReactionHandler) \
|
|
BUILTIN_LIST_TFS(V)
|
|
|
|
class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
|
|
@@ -889,13 +888,6 @@ class RunMicrotasksDescriptor final : public CallInterfaceDescriptor {
|
|
0)
|
|
};
|
|
|
|
-class PromiseReactionHandlerDescriptor final : public CallInterfaceDescriptor {
|
|
- public:
|
|
- DEFINE_PARAMETERS(kArgument, kGenerator)
|
|
- DECLARE_DEFAULT_DESCRIPTOR(PromiseReactionHandlerDescriptor,
|
|
- CallInterfaceDescriptor, 2)
|
|
-};
|
|
-
|
|
#define DEFINE_TFS_BUILTIN_DESCRIPTOR(Name, ...) \
|
|
class Name##Descriptor : public CallInterfaceDescriptor { \
|
|
public: \
|
|
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
|
|
index 29ad2c2a82f..744c6614f7a 100644
|
|
--- a/src/interpreter/bytecode-generator.cc
|
|
+++ b/src/interpreter/bytecode-generator.cc
|
|
@@ -3239,20 +3239,22 @@ void BytecodeGenerator::BuildAwait(Expression* await_expr) {
|
|
// Await(operand) and suspend.
|
|
RegisterAllocationScope register_scope(this);
|
|
|
|
- Runtime::FunctionId id;
|
|
+ int await_builtin_context_index;
|
|
RegisterList args;
|
|
if (IsAsyncGeneratorFunction(function_kind())) {
|
|
- id = catch_prediction() == HandlerTable::ASYNC_AWAIT
|
|
- ? Runtime::kInlineAsyncGeneratorAwaitUncaught
|
|
- : Runtime::kInlineAsyncGeneratorAwaitCaught;
|
|
+ await_builtin_context_index =
|
|
+ catch_prediction() == HandlerTable::ASYNC_AWAIT
|
|
+ ? Context::ASYNC_GENERATOR_AWAIT_UNCAUGHT
|
|
+ : Context::ASYNC_GENERATOR_AWAIT_CAUGHT;
|
|
args = register_allocator()->NewRegisterList(2);
|
|
builder()
|
|
->MoveRegister(generator_object(), args[0])
|
|
.StoreAccumulatorInRegister(args[1]);
|
|
} else {
|
|
- id = catch_prediction() == HandlerTable::ASYNC_AWAIT
|
|
- ? Runtime::kInlineAsyncFunctionAwaitUncaught
|
|
- : Runtime::kInlineAsyncFunctionAwaitCaught;
|
|
+ await_builtin_context_index =
|
|
+ catch_prediction() == HandlerTable::ASYNC_AWAIT
|
|
+ ? Context::ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX
|
|
+ : Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX;
|
|
args = register_allocator()->NewRegisterList(3);
|
|
builder()
|
|
->MoveRegister(generator_object(), args[0])
|
|
@@ -3265,7 +3267,7 @@ void BytecodeGenerator::BuildAwait(Expression* await_expr) {
|
|
builder()->StoreAccumulatorInRegister(args[2]);
|
|
}
|
|
|
|
- builder()->CallRuntime(id, args);
|
|
+ builder()->CallJSRuntime(await_builtin_context_index, args);
|
|
}
|
|
|
|
BuildSuspendPoint(await_expr);
|
|
diff --git a/src/interpreter/interpreter-intrinsics-generator.cc b/src/interpreter/interpreter-intrinsics-generator.cc
|
|
index 675a8bcccc7..0480dec6cc6 100644
|
|
--- a/src/interpreter/interpreter-intrinsics-generator.cc
|
|
+++ b/src/interpreter/interpreter-intrinsics-generator.cc
|
|
@@ -402,30 +402,6 @@ Node* IntrinsicsGenerator::GetImportMetaObject(
|
|
return return_value.value();
|
|
}
|
|
|
|
-Node* IntrinsicsGenerator::AsyncFunctionAwaitCaught(
|
|
- const InterpreterAssembler::RegListNodePair& args, Node* context) {
|
|
- return IntrinsicAsBuiltinCall(args, context,
|
|
- Builtins::kAsyncFunctionAwaitCaught);
|
|
-}
|
|
-
|
|
-Node* IntrinsicsGenerator::AsyncFunctionAwaitUncaught(
|
|
- const InterpreterAssembler::RegListNodePair& args, Node* context) {
|
|
- return IntrinsicAsBuiltinCall(args, context,
|
|
- Builtins::kAsyncFunctionAwaitUncaught);
|
|
-}
|
|
-
|
|
-Node* IntrinsicsGenerator::AsyncGeneratorAwaitCaught(
|
|
- const InterpreterAssembler::RegListNodePair& args, Node* context) {
|
|
- return IntrinsicAsBuiltinCall(args, context,
|
|
- Builtins::kAsyncGeneratorAwaitCaught);
|
|
-}
|
|
-
|
|
-Node* IntrinsicsGenerator::AsyncGeneratorAwaitUncaught(
|
|
- const InterpreterAssembler::RegListNodePair& args, Node* context) {
|
|
- return IntrinsicAsBuiltinCall(args, context,
|
|
- Builtins::kAsyncGeneratorAwaitUncaught);
|
|
-}
|
|
-
|
|
Node* IntrinsicsGenerator::AsyncGeneratorReject(
|
|
const InterpreterAssembler::RegListNodePair& args, Node* context) {
|
|
return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorReject);
|
|
diff --git a/src/interpreter/interpreter-intrinsics.h b/src/interpreter/interpreter-intrinsics.h
|
|
index 6cdfec2d04f..3016183c0b9 100644
|
|
--- a/src/interpreter/interpreter-intrinsics.h
|
|
+++ b/src/interpreter/interpreter-intrinsics.h
|
|
@@ -14,10 +14,6 @@ namespace interpreter {
|
|
// List of supported intrisics, with upper case name, lower case name and
|
|
// expected number of arguments (-1 denoting argument count is variable).
|
|
#define INTRINSICS_LIST(V) \
|
|
- V(AsyncFunctionAwaitCaught, async_function_await_caught, 3) \
|
|
- V(AsyncFunctionAwaitUncaught, async_function_await_uncaught, 3) \
|
|
- V(AsyncGeneratorAwaitCaught, async_generator_await_caught, 2) \
|
|
- V(AsyncGeneratorAwaitUncaught, async_generator_await_uncaught, 2) \
|
|
V(AsyncGeneratorReject, async_generator_reject, 2) \
|
|
V(AsyncGeneratorResolve, async_generator_resolve, 3) \
|
|
V(AsyncGeneratorYield, async_generator_yield, 3) \
|
|
diff --git a/src/isolate.cc b/src/isolate.cc
|
|
index adb30b12ace..2c4e22726d7 100644
|
|
--- a/src/isolate.cc
|
|
+++ b/src/isolate.cc
|
|
@@ -2048,7 +2048,6 @@ void Isolate::PopPromise() {
|
|
}
|
|
|
|
namespace {
|
|
-
|
|
bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
|
|
Handle<JSPromise> promise);
|
|
|
|
@@ -2095,27 +2094,29 @@ bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
|
|
}
|
|
|
|
if (promise->status() == Promise::kPending) {
|
|
- Handle<Object> current(promise->reactions(), isolate);
|
|
- while (!current->IsSmi()) {
|
|
- Handle<PromiseReaction> current_reaction =
|
|
- Handle<PromiseReaction>::cast(current);
|
|
- Handle<HeapObject> payload(current_reaction->payload(), isolate);
|
|
- Handle<JSPromise> current_promise;
|
|
- if (JSPromise::From(payload).ToHandle(¤t_promise)) {
|
|
- if (current_reaction->reject_handler()->IsCallable()) {
|
|
- Handle<JSReceiver> current_handler(
|
|
- JSReceiver::cast(current_reaction->reject_handler()), isolate);
|
|
- if (PromiseHandlerCheck(isolate, current_handler, current_promise)) {
|
|
- return true;
|
|
- }
|
|
- } else {
|
|
- if (InternalPromiseHasUserDefinedRejectHandler(isolate,
|
|
- current_promise)) {
|
|
- return true;
|
|
- }
|
|
+ for (Handle<Object> current(promise->reactions(), isolate);
|
|
+ !current->IsSmi();) {
|
|
+ Handle<PromiseReaction> reaction = Handle<PromiseReaction>::cast(current);
|
|
+ Handle<HeapObject> promise_or_capability(
|
|
+ reaction->promise_or_capability(), isolate);
|
|
+ Handle<JSPromise> promise = Handle<JSPromise>::cast(
|
|
+ promise_or_capability->IsJSPromise()
|
|
+ ? promise_or_capability
|
|
+ : handle(Handle<PromiseCapability>::cast(promise_or_capability)
|
|
+ ->promise(),
|
|
+ isolate));
|
|
+ if (reaction->reject_handler()->IsUndefined(isolate)) {
|
|
+ if (InternalPromiseHasUserDefinedRejectHandler(isolate, promise)) {
|
|
+ return true;
|
|
+ }
|
|
+ } else {
|
|
+ Handle<JSReceiver> current_handler(
|
|
+ JSReceiver::cast(reaction->reject_handler()), isolate);
|
|
+ if (PromiseHandlerCheck(isolate, current_handler, promise)) {
|
|
+ return true;
|
|
}
|
|
}
|
|
- current = handle(current_reaction->next(), isolate);
|
|
+ current = handle(reaction->next(), isolate);
|
|
}
|
|
}
|
|
|
|
diff --git a/src/isolate.h b/src/isolate.h
|
|
index 75b447f1629..82d33033737 100644
|
|
--- a/src/isolate.h
|
|
+++ b/src/isolate.h
|
|
@@ -1096,10 +1096,7 @@ class Isolate {
|
|
bool IsPromiseResolveLookupChainIntact();
|
|
|
|
// Make sure a lookup of "then" on any JSPromise whose [[Prototype]] is the
|
|
- // initial %PromisePrototype% yields the initial method. In addition this
|
|
- // protector also guards the negative lookup of "then" on the intrinsic
|
|
- // %ObjectPrototype%, meaning that such lookups are guaranteed to yield
|
|
- // undefined without triggering any side-effects.
|
|
+ // initial %PromisePrototype% yields the initial method.
|
|
bool IsPromiseThenLookupChainIntact();
|
|
bool IsPromiseThenLookupChainIntact(Handle<JSReceiver> receiver);
|
|
|
|
diff --git a/src/lookup.cc b/src/lookup.cc
|
|
index 20501149947..a4cca33d6c3 100644
|
|
--- a/src/lookup.cc
|
|
+++ b/src/lookup.cc
|
|
@@ -364,14 +364,7 @@ void LookupIterator::InternalUpdateProtector() {
|
|
if (!isolate_->IsPromiseThenLookupChainIntact()) return;
|
|
// Setting the "then" property on any JSPromise instance or on the
|
|
// initial %PromisePrototype% invalidates the Promise#then protector.
|
|
- // Also setting the "then" property on the initial %ObjectPrototype%
|
|
- // invalidates the Promise#then protector, since we use this protector
|
|
- // to guard the fast-path in AsyncGeneratorResolve, where we can skip
|
|
- // the ResolvePromise step and go directly to FulfillPromise if we
|
|
- // know that the Object.prototype doesn't contain a "then" method.
|
|
if (holder_->IsJSPromise() ||
|
|
- isolate_->IsInAnyContext(*holder_,
|
|
- Context::INITIAL_OBJECT_PROTOTYPE_INDEX) ||
|
|
isolate_->IsInAnyContext(*holder_, Context::PROMISE_PROTOTYPE_INDEX)) {
|
|
isolate_->InvalidatePromiseThenProtector();
|
|
}
|
|
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
|
|
index c735cc0813c..086078bb251 100644
|
|
--- a/src/objects-debug.cc
|
|
+++ b/src/objects-debug.cc
|
|
@@ -1172,13 +1172,10 @@ void PromiseReactionJobTask::PromiseReactionJobTaskVerify() {
|
|
VerifyHeapPointer(context());
|
|
CHECK(context()->IsContext());
|
|
VerifyHeapPointer(handler());
|
|
- VerifyHeapPointer(payload());
|
|
- if (handler()->IsCode()) {
|
|
- CHECK(payload()->IsJSReceiver());
|
|
- } else {
|
|
- CHECK(handler()->IsUndefined(isolate) || handler()->IsCallable());
|
|
- CHECK(payload()->IsJSPromise() || payload()->IsPromiseCapability());
|
|
- }
|
|
+ CHECK(handler()->IsUndefined(isolate) || handler()->IsCallable());
|
|
+ VerifyHeapPointer(promise_or_capability());
|
|
+ CHECK(promise_or_capability()->IsJSPromise() ||
|
|
+ promise_or_capability()->IsPromiseCapability());
|
|
}
|
|
|
|
void PromiseFulfillReactionJobTask::PromiseFulfillReactionJobTaskVerify() {
|
|
@@ -1220,18 +1217,14 @@ void PromiseReaction::PromiseReactionVerify() {
|
|
VerifyPointer(next());
|
|
CHECK(next()->IsSmi() || next()->IsPromiseReaction());
|
|
VerifyHeapPointer(reject_handler());
|
|
+ CHECK(reject_handler()->IsUndefined(isolate) ||
|
|
+ reject_handler()->IsCallable());
|
|
VerifyHeapPointer(fulfill_handler());
|
|
- VerifyHeapPointer(payload());
|
|
- if (reject_handler()->IsCode()) {
|
|
- CHECK(fulfill_handler()->IsCode());
|
|
- CHECK(payload()->IsJSReceiver());
|
|
- } else {
|
|
- CHECK(reject_handler()->IsUndefined(isolate) ||
|
|
- reject_handler()->IsCallable());
|
|
- CHECK(fulfill_handler()->IsUndefined(isolate) ||
|
|
- fulfill_handler()->IsCallable());
|
|
- CHECK(payload()->IsJSPromise() || payload()->IsPromiseCapability());
|
|
- }
|
|
+ CHECK(fulfill_handler()->IsUndefined(isolate) ||
|
|
+ fulfill_handler()->IsCallable());
|
|
+ VerifyHeapPointer(promise_or_capability());
|
|
+ CHECK(promise_or_capability()->IsJSPromise() ||
|
|
+ promise_or_capability()->IsPromiseCapability());
|
|
}
|
|
|
|
void JSPromise::JSPromiseVerify() {
|
|
diff --git a/src/objects-inl.h b/src/objects-inl.h
|
|
index bda031e0637..297e9fc836d 100644
|
|
--- a/src/objects-inl.h
|
|
+++ b/src/objects-inl.h
|
|
@@ -2278,7 +2278,7 @@ ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset)
|
|
ACCESSORS(AccessorInfo, name, Name, kNameOffset)
|
|
SMI_ACCESSORS(AccessorInfo, flags, kFlagsOffset)
|
|
ACCESSORS(AccessorInfo, expected_receiver_type, Object,
|
|
- kExpectedReceiverTypeOffset)
|
|
+ kExpectedReceiverTypeOffset)
|
|
|
|
ACCESSORS_CHECKED2(AccessorInfo, getter, Object, kGetterOffset, true,
|
|
Foreign::IsNormalized(value))
|
|
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
|
|
index 942b9de0ba2..8d20279b2f1 100644
|
|
--- a/src/objects-printer.cc
|
|
+++ b/src/objects-printer.cc
|
|
@@ -1441,7 +1441,7 @@ void PromiseFulfillReactionJobTask::PromiseFulfillReactionJobTaskPrint(
|
|
os << "\n - argument: " << Brief(argument());
|
|
os << "\n - context: " << Brief(context());
|
|
os << "\n - handler: " << Brief(handler());
|
|
- os << "\n - payload: " << Brief(payload());
|
|
+ os << "\n - promise_or_capability: " << Brief(promise_or_capability());
|
|
os << "\n";
|
|
}
|
|
|
|
@@ -1451,7 +1451,7 @@ void PromiseRejectReactionJobTask::PromiseRejectReactionJobTaskPrint(
|
|
os << "\n - argument: " << Brief(argument());
|
|
os << "\n - context: " << Brief(context());
|
|
os << "\n - handler: " << Brief(handler());
|
|
- os << "\n - payload: " << Brief(payload());
|
|
+ os << "\n - promise_or_capability: " << Brief(promise_or_capability());
|
|
os << "\n";
|
|
}
|
|
|
|
@@ -1478,7 +1478,7 @@ void PromiseReaction::PromiseReactionPrint(std::ostream& os) { // NOLINT
|
|
os << "\n - next: " << Brief(next());
|
|
os << "\n - reject_handler: " << Brief(reject_handler());
|
|
os << "\n - fulfill_handler: " << Brief(fulfill_handler());
|
|
- os << "\n - payload: " << Brief(payload());
|
|
+ os << "\n - promise_or_capability: " << Brief(promise_or_capability());
|
|
os << "\n";
|
|
}
|
|
|
|
diff --git a/src/objects.cc b/src/objects.cc
|
|
index 8057cb837b1..6565910fd3f 100644
|
|
--- a/src/objects.cc
|
|
+++ b/src/objects.cc
|
|
@@ -16054,27 +16054,6 @@ MaybeHandle<Object> JSPromise::Resolve(Handle<JSPromise> promise,
|
|
return isolate->factory()->undefined_value();
|
|
}
|
|
|
|
-// static
|
|
-MaybeHandle<JSPromise> JSPromise::From(Handle<HeapObject> object) {
|
|
- Isolate* const isolate = object->GetIsolate();
|
|
- if (object->IsJSPromise()) {
|
|
- return Handle<JSPromise>::cast(object);
|
|
- } else if (object->IsPromiseCapability()) {
|
|
- Handle<PromiseCapability> capability =
|
|
- Handle<PromiseCapability>::cast(object);
|
|
- if (capability->promise()->IsJSPromise()) {
|
|
- return handle(JSPromise::cast(capability->promise()), isolate);
|
|
- }
|
|
- } else if (object->IsJSGeneratorObject()) {
|
|
- Handle<JSGeneratorObject> generator =
|
|
- Handle<JSGeneratorObject>::cast(object);
|
|
- Handle<Object> handled_by = JSObject::GetDataProperty(
|
|
- generator, isolate->factory()->generator_outer_promise_symbol());
|
|
- if (handled_by->IsJSPromise()) return Handle<JSPromise>::cast(handled_by);
|
|
- }
|
|
- return MaybeHandle<JSPromise>();
|
|
-}
|
|
-
|
|
// static
|
|
Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
|
|
Handle<Object> reactions,
|
|
@@ -16114,8 +16093,8 @@ Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
|
|
*isolate->native_context());
|
|
STATIC_ASSERT(PromiseReaction::kFulfillHandlerOffset ==
|
|
PromiseFulfillReactionJobTask::kHandlerOffset);
|
|
- STATIC_ASSERT(PromiseReaction::kPayloadOffset ==
|
|
- PromiseFulfillReactionJobTask::kPayloadOffset);
|
|
+ STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset ==
|
|
+ PromiseFulfillReactionJobTask::kPromiseOrCapabilityOffset);
|
|
} else {
|
|
DisallowHeapAllocation no_gc;
|
|
HeapObject* handler = reaction->reject_handler();
|
|
@@ -16125,8 +16104,8 @@ Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
|
|
Handle<PromiseRejectReactionJobTask>::cast(task)->set_context(
|
|
*isolate->native_context());
|
|
Handle<PromiseRejectReactionJobTask>::cast(task)->set_handler(handler);
|
|
- STATIC_ASSERT(PromiseReaction::kPayloadOffset ==
|
|
- PromiseRejectReactionJobTask::kPayloadOffset);
|
|
+ STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset ==
|
|
+ PromiseRejectReactionJobTask::kPromiseOrCapabilityOffset);
|
|
}
|
|
|
|
isolate->EnqueueMicrotask(Handle<PromiseReactionJobTask>::cast(task));
|
|
diff --git a/src/objects/js-promise.h b/src/objects/js-promise.h
|
|
index 20a0a90131a..434bae89338 100644
|
|
--- a/src/objects/js-promise.h
|
|
+++ b/src/objects/js-promise.h
|
|
@@ -59,12 +59,6 @@ class JSPromise : public JSObject {
|
|
V8_WARN_UNUSED_RESULT static MaybeHandle<Object> Resolve(
|
|
Handle<JSPromise> promise, Handle<Object> resolution);
|
|
|
|
- // This is a helper that extracts the JSPromise from the input
|
|
- // {object}, which is used as a payload for PromiseReaction and
|
|
- // PromiseReactionJobTask.
|
|
- V8_WARN_UNUSED_RESULT static MaybeHandle<JSPromise> From(
|
|
- Handle<HeapObject> object);
|
|
-
|
|
DECL_CAST(JSPromise)
|
|
|
|
// Dispatched behavior.
|
|
diff --git a/src/objects/promise-inl.h b/src/objects/promise-inl.h
|
|
index 4283f0aa194..f9fb6110f34 100644
|
|
--- a/src/objects/promise-inl.h
|
|
+++ b/src/objects/promise-inl.h
|
|
@@ -23,7 +23,8 @@ CAST_ACCESSOR(PromiseResolveThenableJobTask)
|
|
ACCESSORS(PromiseReaction, next, Object, kNextOffset)
|
|
ACCESSORS(PromiseReaction, reject_handler, HeapObject, kRejectHandlerOffset)
|
|
ACCESSORS(PromiseReaction, fulfill_handler, HeapObject, kFulfillHandlerOffset)
|
|
-ACCESSORS(PromiseReaction, payload, HeapObject, kPayloadOffset)
|
|
+ACCESSORS(PromiseReaction, promise_or_capability, HeapObject,
|
|
+ kPromiseOrCapabilityOffset)
|
|
|
|
ACCESSORS(PromiseResolveThenableJobTask, context, Context, kContextOffset)
|
|
ACCESSORS(PromiseResolveThenableJobTask, promise_to_resolve, JSPromise,
|
|
@@ -34,7 +35,8 @@ ACCESSORS(PromiseResolveThenableJobTask, thenable, JSReceiver, kThenableOffset)
|
|
ACCESSORS(PromiseReactionJobTask, context, Context, kContextOffset)
|
|
ACCESSORS(PromiseReactionJobTask, argument, Object, kArgumentOffset);
|
|
ACCESSORS(PromiseReactionJobTask, handler, HeapObject, kHandlerOffset);
|
|
-ACCESSORS(PromiseReactionJobTask, payload, HeapObject, kPayloadOffset);
|
|
+ACCESSORS(PromiseReactionJobTask, promise_or_capability, HeapObject,
|
|
+ kPromiseOrCapabilityOffset);
|
|
|
|
ACCESSORS(PromiseCapability, promise, HeapObject, kPromiseOffset)
|
|
ACCESSORS(PromiseCapability, resolve, Object, kResolveOffset)
|
|
diff --git a/src/objects/promise.h b/src/objects/promise.h
|
|
index 36ef4afe1d6..5ff5dac6f37 100644
|
|
--- a/src/objects/promise.h
|
|
+++ b/src/objects/promise.h
|
|
@@ -26,16 +26,15 @@ class PromiseReactionJobTask : public Microtask {
|
|
public:
|
|
DECL_ACCESSORS(argument, Object)
|
|
DECL_ACCESSORS(context, Context)
|
|
- // [handler]: This is either a Code object, a Callable or Undefined.
|
|
DECL_ACCESSORS(handler, HeapObject)
|
|
- // [payload]: Usually a JSPromise or a PromiseCapability.
|
|
- DECL_ACCESSORS(payload, HeapObject)
|
|
+ // [promise_or_capability]: Either a JSPromise or a PromiseCapability.
|
|
+ DECL_ACCESSORS(promise_or_capability, HeapObject)
|
|
|
|
static const int kArgumentOffset = Microtask::kHeaderSize;
|
|
static const int kContextOffset = kArgumentOffset + kPointerSize;
|
|
static const int kHandlerOffset = kContextOffset + kPointerSize;
|
|
- static const int kPayloadOffset = kHandlerOffset + kPointerSize;
|
|
- static const int kSize = kPayloadOffset + kPointerSize;
|
|
+ static const int kPromiseOrCapabilityOffset = kHandlerOffset + kPointerSize;
|
|
+ static const int kSize = kPromiseOrCapabilityOffset + kPointerSize;
|
|
|
|
// Dispatched behavior.
|
|
DECL_CAST(PromiseReactionJobTask)
|
|
@@ -121,10 +120,9 @@ class PromiseCapability : public Struct {
|
|
// of microtasks. So the size of PromiseReaction and the size of the
|
|
// PromiseReactionJobTask has to be same for this to work.
|
|
//
|
|
-// The PromiseReaction::payload field usually holds a JSPromise
|
|
-// instance (in the fast case of a native promise) or a PromiseCapability
|
|
-// in case of a custom promise. For await we store the JSGeneratorObject
|
|
-// here and use custom Code handlers.
|
|
+// The PromiseReaction::promise_or_capability field can either hold a JSPromise
|
|
+// instance (in the fast case of a native promise) or a PromiseCapability in
|
|
+// case of a Promise subclass.
|
|
//
|
|
// We need to keep the context in the PromiseReaction so that we can run
|
|
// the default handlers (in case they are undefined) in the proper context.
|
|
@@ -138,18 +136,16 @@ class PromiseReaction : public Struct {
|
|
enum Type { kFulfill, kReject };
|
|
|
|
DECL_ACCESSORS(next, Object)
|
|
- // [reject_handler]: This is either a Code object, a Callable or Undefined.
|
|
DECL_ACCESSORS(reject_handler, HeapObject)
|
|
- // [fulfill_handler]: This is either a Code object, a Callable or Undefined.
|
|
DECL_ACCESSORS(fulfill_handler, HeapObject)
|
|
- // [payload]: Usually a JSPromise or a PromiseCapability.
|
|
- DECL_ACCESSORS(payload, HeapObject)
|
|
+ DECL_ACCESSORS(promise_or_capability, HeapObject)
|
|
|
|
static const int kNextOffset = Struct::kHeaderSize;
|
|
static const int kRejectHandlerOffset = kNextOffset + kPointerSize;
|
|
static const int kFulfillHandlerOffset = kRejectHandlerOffset + kPointerSize;
|
|
- static const int kPayloadOffset = kFulfillHandlerOffset + kPointerSize;
|
|
- static const int kSize = kPayloadOffset + kPointerSize;
|
|
+ static const int kPromiseOrCapabilityOffset =
|
|
+ kFulfillHandlerOffset + kPointerSize;
|
|
+ static const int kSize = kPromiseOrCapabilityOffset + kPointerSize;
|
|
|
|
// Dispatched behavior.
|
|
DECL_CAST(PromiseReaction)
|
|
diff --git a/src/runtime/runtime-generator.cc b/src/runtime/runtime-generator.cc
|
|
index e69d3340426..3c7c808c30b 100644
|
|
--- a/src/runtime/runtime-generator.cc
|
|
+++ b/src/runtime/runtime-generator.cc
|
|
@@ -70,30 +70,6 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetInputOrDebugPos) {
|
|
UNREACHABLE();
|
|
}
|
|
|
|
-RUNTIME_FUNCTION(Runtime_AsyncFunctionAwaitCaught) {
|
|
- // Runtime call is implemented in InterpreterIntrinsics and lowered in
|
|
- // JSIntrinsicLowering
|
|
- UNREACHABLE();
|
|
-}
|
|
-
|
|
-RUNTIME_FUNCTION(Runtime_AsyncFunctionAwaitUncaught) {
|
|
- // Runtime call is implemented in InterpreterIntrinsics and lowered in
|
|
- // JSIntrinsicLowering
|
|
- UNREACHABLE();
|
|
-}
|
|
-
|
|
-RUNTIME_FUNCTION(Runtime_AsyncGeneratorAwaitCaught) {
|
|
- // Runtime call is implemented in InterpreterIntrinsics and lowered in
|
|
- // JSIntrinsicLowering
|
|
- UNREACHABLE();
|
|
-}
|
|
-
|
|
-RUNTIME_FUNCTION(Runtime_AsyncGeneratorAwaitUncaught) {
|
|
- // Runtime call is implemented in InterpreterIntrinsics and lowered in
|
|
- // JSIntrinsicLowering
|
|
- UNREACHABLE();
|
|
-}
|
|
-
|
|
RUNTIME_FUNCTION(Runtime_AsyncGeneratorResolve) {
|
|
// Runtime call is implemented in InterpreterIntrinsics and lowered in
|
|
// JSIntrinsicLowering
|
|
diff --git a/src/runtime/runtime-promise.cc b/src/runtime/runtime-promise.cc
|
|
index b2a7e8bae1b..f5b9db3c028 100644
|
|
--- a/src/runtime/runtime-promise.cc
|
|
+++ b/src/runtime/runtime-promise.cc
|
|
@@ -114,14 +114,13 @@ RUNTIME_FUNCTION(Runtime_PromiseHookInit) {
|
|
RUNTIME_FUNCTION(Runtime_PromiseHookBefore) {
|
|
HandleScope scope(isolate);
|
|
DCHECK_EQ(1, args.length());
|
|
- CONVERT_ARG_HANDLE_CHECKED(HeapObject, payload, 0);
|
|
- Handle<JSPromise> promise;
|
|
- if (JSPromise::From(payload).ToHandle(&promise)) {
|
|
- if (isolate->debug()->is_active()) isolate->PushPromise(promise);
|
|
- if (promise->IsJSPromise()) {
|
|
- isolate->RunPromiseHook(PromiseHookType::kBefore, promise,
|
|
- isolate->factory()->undefined_value());
|
|
- }
|
|
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, maybe_promise, 0);
|
|
+ if (!maybe_promise->IsJSPromise()) return isolate->heap()->undefined_value();
|
|
+ Handle<JSPromise> promise = Handle<JSPromise>::cast(maybe_promise);
|
|
+ if (isolate->debug()->is_active()) isolate->PushPromise(promise);
|
|
+ if (promise->IsJSPromise()) {
|
|
+ isolate->RunPromiseHook(PromiseHookType::kBefore, promise,
|
|
+ isolate->factory()->undefined_value());
|
|
}
|
|
return isolate->heap()->undefined_value();
|
|
}
|
|
@@ -129,14 +128,13 @@ RUNTIME_FUNCTION(Runtime_PromiseHookBefore) {
|
|
RUNTIME_FUNCTION(Runtime_PromiseHookAfter) {
|
|
HandleScope scope(isolate);
|
|
DCHECK_EQ(1, args.length());
|
|
- CONVERT_ARG_HANDLE_CHECKED(HeapObject, payload, 0);
|
|
- Handle<JSPromise> promise;
|
|
- if (JSPromise::From(payload).ToHandle(&promise)) {
|
|
- if (isolate->debug()->is_active()) isolate->PopPromise();
|
|
- if (promise->IsJSPromise()) {
|
|
- isolate->RunPromiseHook(PromiseHookType::kAfter, promise,
|
|
- isolate->factory()->undefined_value());
|
|
- }
|
|
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, maybe_promise, 0);
|
|
+ if (!maybe_promise->IsJSPromise()) return isolate->heap()->undefined_value();
|
|
+ Handle<JSPromise> promise = Handle<JSPromise>::cast(maybe_promise);
|
|
+ if (isolate->debug()->is_active()) isolate->PopPromise();
|
|
+ if (promise->IsJSPromise()) {
|
|
+ isolate->RunPromiseHook(PromiseHookType::kAfter, promise,
|
|
+ isolate->factory()->undefined_value());
|
|
}
|
|
return isolate->heap()->undefined_value();
|
|
}
|
|
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
|
|
index 48a63d500da..37ce74e8250 100644
|
|
--- a/src/runtime/runtime.h
|
|
+++ b/src/runtime/runtime.h
|
|
@@ -222,10 +222,6 @@ namespace internal {
|
|
F(SetNativeFlag, 1, 1)
|
|
|
|
#define FOR_EACH_INTRINSIC_GENERATOR(F) \
|
|
- F(AsyncFunctionAwaitCaught, 3, 1) \
|
|
- F(AsyncFunctionAwaitUncaught, 3, 1) \
|
|
- F(AsyncGeneratorAwaitCaught, 2, 1) \
|
|
- F(AsyncGeneratorAwaitUncaught, 2, 1) \
|
|
F(AsyncGeneratorHasCatchHandlerForPC, 1, 1) \
|
|
F(AsyncGeneratorReject, 2, 1) \
|
|
F(AsyncGeneratorResolve, 3, 1) \
|
|
diff --git a/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden b/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden
|
|
index df6b3723586..2b4eb6b2cc5 100644
|
|
--- a/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden
|
|
+++ b/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden
|
|
@@ -39,7 +39,7 @@ bytecodes: [
|
|
B(LdaUndefined),
|
|
B(Star), R(6),
|
|
B(Mov), R(0), R(5),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(5), U8(2),
|
|
+ B(CallJSRuntime), U8(%async_generator_await_uncaught), R(5), U8(2),
|
|
B(SuspendGenerator), R(0), R(0), U8(5), U8(1),
|
|
B(ResumeGenerator), R(0), R(0), U8(5),
|
|
B(Star), R(5),
|
|
@@ -166,7 +166,7 @@ bytecodes: [
|
|
B(LdaUndefined),
|
|
B(Star), R(6),
|
|
B(Mov), R(0), R(5),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(5), U8(2),
|
|
+ B(CallJSRuntime), U8(%async_generator_await_uncaught), R(5), U8(2),
|
|
B(SuspendGenerator), R(0), R(0), U8(5), U8(2),
|
|
B(ResumeGenerator), R(0), R(0), U8(5),
|
|
B(Star), R(5),
|
|
@@ -404,7 +404,7 @@ bytecodes: [
|
|
B(LdaUndefined),
|
|
B(Star), R(16),
|
|
B(Mov), R(2), R(15),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(15), U8(2),
|
|
+ B(CallJSRuntime), U8(%async_generator_await_uncaught), R(15), U8(2),
|
|
B(SuspendGenerator), R(2), R(0), U8(15), U8(2),
|
|
B(ResumeGenerator), R(2), R(0), U8(15),
|
|
B(Star), R(15),
|
|
@@ -580,7 +580,7 @@ bytecodes: [
|
|
B(Jump), U8(2),
|
|
B(Star), R(13),
|
|
B(Mov), R(0), R(12),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(12), U8(2),
|
|
+ B(CallJSRuntime), U8(%async_generator_await_uncaught), R(12), U8(2),
|
|
/* 49 E> */ B(SuspendGenerator), R(0), R(0), U8(12), U8(1),
|
|
B(ResumeGenerator), R(0), R(0), U8(12),
|
|
B(Star), R(12),
|
|
@@ -598,7 +598,7 @@ bytecodes: [
|
|
B(CallRuntime), U16(Runtime::kThrowThrowMethodMissing), R(0), U8(0),
|
|
B(Star), R(13),
|
|
B(Mov), R(0), R(12),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(12), U8(2),
|
|
+ B(CallJSRuntime), U8(%async_generator_await_uncaught), R(12), U8(2),
|
|
/* 49 E> */ B(SuspendGenerator), R(0), R(0), U8(12), U8(2),
|
|
B(ResumeGenerator), R(0), R(0), U8(12),
|
|
B(Star), R(12),
|
|
@@ -639,7 +639,7 @@ bytecodes: [
|
|
B(LdaUndefined),
|
|
B(Star), R(6),
|
|
B(Mov), R(0), R(5),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(5), U8(2),
|
|
+ B(CallJSRuntime), U8(%async_generator_await_uncaught), R(5), U8(2),
|
|
B(SuspendGenerator), R(0), R(0), U8(5), U8(4),
|
|
B(ResumeGenerator), R(0), R(0), U8(5),
|
|
B(Star), R(5),
|
|
diff --git a/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden b/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden
|
|
index 95400dacf80..4d36315f027 100644
|
|
--- a/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden
|
|
+++ b/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden
|
|
@@ -53,7 +53,7 @@ bytecodes: [
|
|
B(Star), R(21),
|
|
B(Mov), R(2), R(20),
|
|
B(Mov), R(11), R(22),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(20), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_uncaught), R(20), U8(3),
|
|
/* 40 E> */ B(SuspendGenerator), R(2), R(0), U8(20), U8(0),
|
|
B(ResumeGenerator), R(2), R(0), U8(20),
|
|
B(Star), R(20),
|
|
@@ -137,7 +137,7 @@ bytecodes: [
|
|
B(Star), R(21),
|
|
B(Mov), R(2), R(20),
|
|
B(Mov), R(11), R(22),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitCaught), R(20), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_caught), R(20), U8(3),
|
|
B(SuspendGenerator), R(2), R(0), U8(20), U8(1),
|
|
B(ResumeGenerator), R(2), R(0), U8(20),
|
|
B(Star), R(20),
|
|
@@ -160,7 +160,7 @@ bytecodes: [
|
|
B(Star), R(20),
|
|
B(Mov), R(2), R(19),
|
|
B(Mov), R(11), R(21),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(19), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_uncaught), R(19), U8(3),
|
|
B(SuspendGenerator), R(2), R(0), U8(19), U8(2),
|
|
B(ResumeGenerator), R(2), R(0), U8(19),
|
|
B(Star), R(19),
|
|
@@ -306,7 +306,7 @@ bytecodes: [
|
|
B(Star), R(21),
|
|
B(Mov), R(2), R(20),
|
|
B(Mov), R(11), R(22),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(20), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_uncaught), R(20), U8(3),
|
|
/* 40 E> */ B(SuspendGenerator), R(2), R(0), U8(20), U8(0),
|
|
B(ResumeGenerator), R(2), R(0), U8(20),
|
|
B(Star), R(20),
|
|
@@ -391,7 +391,7 @@ bytecodes: [
|
|
B(Star), R(21),
|
|
B(Mov), R(2), R(20),
|
|
B(Mov), R(11), R(22),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitCaught), R(20), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_caught), R(20), U8(3),
|
|
B(SuspendGenerator), R(2), R(0), U8(20), U8(1),
|
|
B(ResumeGenerator), R(2), R(0), U8(20),
|
|
B(Star), R(20),
|
|
@@ -414,7 +414,7 @@ bytecodes: [
|
|
B(Star), R(20),
|
|
B(Mov), R(2), R(19),
|
|
B(Mov), R(11), R(21),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(19), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_uncaught), R(19), U8(3),
|
|
B(SuspendGenerator), R(2), R(0), U8(19), U8(2),
|
|
B(ResumeGenerator), R(2), R(0), U8(19),
|
|
B(Star), R(19),
|
|
@@ -575,7 +575,7 @@ bytecodes: [
|
|
B(Star), R(21),
|
|
B(Mov), R(2), R(20),
|
|
B(Mov), R(11), R(22),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(20), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_uncaught), R(20), U8(3),
|
|
/* 40 E> */ B(SuspendGenerator), R(2), R(0), U8(20), U8(0),
|
|
B(ResumeGenerator), R(2), R(0), U8(20),
|
|
B(Star), R(20),
|
|
@@ -667,7 +667,7 @@ bytecodes: [
|
|
B(Star), R(21),
|
|
B(Mov), R(2), R(20),
|
|
B(Mov), R(11), R(22),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitCaught), R(20), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_caught), R(20), U8(3),
|
|
B(SuspendGenerator), R(2), R(0), U8(20), U8(1),
|
|
B(ResumeGenerator), R(2), R(0), U8(20),
|
|
B(Star), R(20),
|
|
@@ -690,7 +690,7 @@ bytecodes: [
|
|
B(Star), R(20),
|
|
B(Mov), R(2), R(19),
|
|
B(Mov), R(11), R(21),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(19), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_uncaught), R(19), U8(3),
|
|
B(SuspendGenerator), R(2), R(0), U8(19), U8(2),
|
|
B(ResumeGenerator), R(2), R(0), U8(19),
|
|
B(Star), R(19),
|
|
diff --git a/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden b/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden
|
|
index 1a0155da79c..f92076e6e65 100644
|
|
--- a/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden
|
|
+++ b/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden
|
|
@@ -1196,7 +1196,7 @@ bytecodes: [
|
|
/* 45 S> */ B(Mov), R(2), R(21),
|
|
B(Mov), R(0), R(22),
|
|
B(Mov), R(11), R(23),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(21), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_uncaught), R(21), U8(3),
|
|
/* 45 E> */ B(SuspendGenerator), R(2), R(0), U8(21), U8(0),
|
|
B(ResumeGenerator), R(2), R(0), U8(21),
|
|
B(Star), R(21),
|
|
diff --git a/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden b/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden
|
|
index 80609db7b80..7edf446ce33 100644
|
|
--- a/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden
|
|
+++ b/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden
|
|
@@ -493,7 +493,7 @@ bytecodes: [
|
|
/* 52 S> */ B(Mov), R(1), R(7),
|
|
B(Mov), R(0), R(8),
|
|
B(Mov), R(2), R(9),
|
|
- B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(7), U8(3),
|
|
+ B(CallJSRuntime), U8(%async_function_await_uncaught), R(7), U8(3),
|
|
/* 52 E> */ B(SuspendGenerator), R(1), R(0), U8(7), U8(0),
|
|
B(ResumeGenerator), R(1), R(0), U8(7),
|
|
B(Star), R(7),
|
|
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
|
|
index 2f552a9d9d9..8b93944d933 100644
|
|
--- a/test/cctest/test-api.cc
|
|
+++ b/test/cctest/test-api.cc
|
|
@@ -18358,12 +18358,6 @@ TEST(PromiseHook) {
|
|
CHECK_EQ(v8::Promise::kFulfilled, GetPromise("p")->State());
|
|
CHECK_EQ(9, promise_hook_data->promise_hook_count);
|
|
|
|
- promise_hook_data->Reset();
|
|
- source = "(async() => await p)();\n";
|
|
-
|
|
- CompileRun(source);
|
|
- CHECK_EQ(11, promise_hook_data->promise_hook_count);
|
|
-
|
|
delete promise_hook_data;
|
|
isolate->SetPromiseHook(nullptr);
|
|
}
|
|
diff --git a/tools/v8heapconst.py b/tools/v8heapconst.py
|
|
index 1e57ce64a9e..e3b29f82042 100644
|
|
--- a/tools/v8heapconst.py
|
|
+++ b/tools/v8heapconst.py
|
|
@@ -263,12 +263,12 @@
|
|
("MAP_SPACE", 0x04511): (173, "Tuple2Map"),
|
|
("MAP_SPACE", 0x04569): (171, "ScriptMap"),
|
|
("MAP_SPACE", 0x045c1): (163, "InterceptorInfoMap"),
|
|
- ("MAP_SPACE", 0x04619): (154, "AccessorInfoMap"),
|
|
- ("MAP_SPACE", 0x04671): (153, "AccessCheckInfoMap"),
|
|
- ("MAP_SPACE", 0x046c9): (155, "AccessorPairMap"),
|
|
- ("MAP_SPACE", 0x04721): (156, "AliasedArgumentsEntryMap"),
|
|
- ("MAP_SPACE", 0x04779): (157, "AllocationMementoMap"),
|
|
- ("MAP_SPACE", 0x047d1): (158, "AllocationSiteMap"),
|
|
+ ("MAP_SPACE", 0x04619): (158, "AllocationSiteMap"),
|
|
+ ("MAP_SPACE", 0x04671): (154, "AccessorInfoMap"),
|
|
+ ("MAP_SPACE", 0x046c9): (153, "AccessCheckInfoMap"),
|
|
+ ("MAP_SPACE", 0x04721): (155, "AccessorPairMap"),
|
|
+ ("MAP_SPACE", 0x04779): (156, "AliasedArgumentsEntryMap"),
|
|
+ ("MAP_SPACE", 0x047d1): (157, "AllocationMementoMap"),
|
|
("MAP_SPACE", 0x04829): (159, "AsyncGeneratorRequestMap"),
|
|
("MAP_SPACE", 0x04881): (160, "ContextExtensionMap"),
|
|
("MAP_SPACE", 0x048d9): (161, "DebugInfoMap"),
|
|
@@ -366,4 +366,4 @@
|
|
"NATIVE",
|
|
)
|
|
|
|
-# This set of constants is generated from a shipping build.
|
|
+# This set of constants is generated from a non-shipping build.
|