Revert promises optimizations due to regressions in async hooks

Revert "[async-await] Eliminate throwaway promise in async functions."

This reverts commit a840f1f8f7.

Revert "[async-generators] Also avoid throwaway promise here."

This reverts commit feb545ceba.

Revert "[async-await] Turn await closures into intrinsics."

This reverts commit d97bb31738.

Revert "[async-generators] Add fast-path for primitives in AsyncGeneratorYield."

This reverts commit e57b500eb2.

Revert "[async-generators] Add fast-path to skip "then" lookup in AsyncGeneratorResolve."

This reverts commit c15802e11e.

Revert "[promises] Correctly run before/after hooks for await."

This reverts commit ca7639239f.

Bug: v8:7253, v8:7745
Change-Id: I25ad0d2df3cfbc84dbb431aa25b268bce8a39e89
Reviewed-on: https://chromium-review.googlesource.com/1049975
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53139}
This commit is contained in:
Maya Lekova 2018-05-14 10:55:07 +02:00 committed by Commit Bot
parent 989285b7a0
commit 91ddb65d3b
36 changed files with 704 additions and 622 deletions

View File

@ -1587,6 +1587,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,
@ -4025,6 +4069,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(),

View File

@ -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));
CSA_SLOW_ASSERT(this, HasInstanceType(generator, JS_GENERATOR_OBJECT_TYPE));
CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE));
Await(context, generator, awaited, outer_promise,
Builtins::kAsyncFunctionAwaitFulfill,
Builtins::kAsyncFunctionAwaitReject, is_predicted_as_caught);
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);
}

View File

@ -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(

View File

@ -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

View File

@ -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".
ContextInitializer init_closure_context = [&](Node* context) {
StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
generator);
};
const int on_resolve = Context::ASYNC_GENERATOR_YIELD_RESOLVE_SHARED_FUN;
const int on_reject = Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN;
SetGeneratorAwaiting(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());
}
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);
}
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);
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(&perform_await);
ContextInitializer init_closure_context = [&](Node* context) {
StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
generator);
};
SetGeneratorAwaiting(generator);
Branch(IsGeneratorStateClosed(state), &if_closed, &if_not_closed);
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(&if_closed);
{
Await(context, generator, value, outer_promise,
Builtins::kAsyncGeneratorReturnClosedFulfill,
Builtins::kAsyncGeneratorReturnClosedReject, is_caught);
Goto(&done);
}
BIND(&if_not_closed);
{
Await(context, generator, value, outer_promise,
Builtins::kAsyncGeneratorReturnFulfill,
Builtins::kAsyncGeneratorAwaitReject, is_caught);
Goto(&done);
}
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);
}

View File

@ -375,10 +375,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) \
\
@ -835,8 +835,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% */ \
@ -1311,7 +1311,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) \

View File

@ -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::Create(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);

View File

@ -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").

View File

@ -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);

View File

@ -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),

View File

@ -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);

View File

@ -32,35 +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_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) \
@ -114,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) \

View File

@ -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) \

View File

@ -79,7 +79,6 @@ class PlatformInterfaceDescriptor;
V(FrameDropperTrampoline) \
V(WasmRuntimeCall) \
V(RunMicrotasks) \
V(PromiseReactionHandler) \
BUILTIN_LIST_TFS(V)
class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
@ -868,13 +867,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: \

View File

@ -3251,20 +3251,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])
@ -3277,7 +3279,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);

View File

@ -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);

View File

@ -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) \

View File

@ -2059,7 +2059,6 @@ void Isolate::PopPromise() {
}
namespace {
bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
Handle<JSPromise> promise);
@ -2106,27 +2105,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(&current_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);
}
}

View File

@ -1104,10 +1104,7 @@ class Isolate : private HiddenFactory {
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);

View File

@ -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();
}

View File

@ -1224,13 +1224,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() {
@ -1272,18 +1269,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() {

View File

@ -2291,7 +2291,6 @@ ACCESSORS(JSGlobalObject, global_proxy, JSObject, kGlobalProxyOffset)
ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset)
ACCESSORS(AsyncGeneratorRequest, next, Object, kNextOffset)
SMI_ACCESSORS(AsyncGeneratorRequest, resume_mode, kResumeModeOffset)
ACCESSORS(AsyncGeneratorRequest, value, Object, kValueOffset)

View File

@ -1472,7 +1472,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";
}
@ -1482,7 +1482,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";
}
@ -1509,7 +1509,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";
}

View File

@ -16118,27 +16118,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,
@ -16178,8 +16157,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();
@ -16189,8 +16168,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));

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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();
}

View File

@ -224,10 +224,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) \

View File

@ -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),
@ -164,7 +164,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),
@ -399,7 +399,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),
@ -573,7 +573,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),
@ -591,7 +591,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),
@ -632,7 +632,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),

View File

@ -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),
@ -136,7 +136,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),
@ -159,7 +159,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),
@ -303,7 +303,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),
@ -387,7 +387,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),
@ -410,7 +410,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),
@ -569,7 +569,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),
@ -660,7 +660,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),
@ -683,7 +683,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),

View File

@ -1182,7 +1182,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),

View File

@ -489,7 +489,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),

View File

@ -18432,12 +18432,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);
}

View File

@ -265,33 +265,33 @@ KNOWN_MAPS = {
("RO_SPACE", 0x05019): (172, "Tuple2Map"),
("RO_SPACE", 0x05211): (170, "ScriptMap"),
("RO_SPACE", 0x053d9): (162, "InterceptorInfoMap"),
("RO_SPACE", 0x07b99): (154, "AccessorInfoMap"),
("RO_SPACE", 0x07da9): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x07e11): (155, "AccessorPairMap"),
("RO_SPACE", 0x07e79): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x07ee1): (157, "AllocationMementoMap"),
("RO_SPACE", 0x07f49): (158, "AllocationSiteMap"),
("RO_SPACE", 0x07fb1): (159, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x08019): (160, "DebugInfoMap"),
("RO_SPACE", 0x08081): (161, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x080e9): (163, "InterpreterDataMap"),
("RO_SPACE", 0x08151): (164, "ModuleInfoEntryMap"),
("RO_SPACE", 0x081b9): (165, "ModuleMap"),
("RO_SPACE", 0x08221): (166, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x08289): (167, "PromiseCapabilityMap"),
("RO_SPACE", 0x082f1): (168, "PromiseReactionMap"),
("RO_SPACE", 0x08359): (169, "PrototypeInfoMap"),
("RO_SPACE", 0x083c1): (171, "StackFrameInfoMap"),
("RO_SPACE", 0x08429): (173, "Tuple3Map"),
("RO_SPACE", 0x08491): (174, "WasmCompiledModuleMap"),
("RO_SPACE", 0x084f9): (175, "WasmDebugInfoMap"),
("RO_SPACE", 0x08561): (176, "WasmExportedFunctionDataMap"),
("RO_SPACE", 0x085c9): (177, "WasmSharedModuleDataMap"),
("RO_SPACE", 0x08631): (178, "CallableTaskMap"),
("RO_SPACE", 0x08699): (179, "CallbackTaskMap"),
("RO_SPACE", 0x08701): (180, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x08769): (181, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x087d1): (182, "PromiseResolveThenableJobTaskMap"),
("RO_SPACE", 0x07b79): (154, "AccessorInfoMap"),
("RO_SPACE", 0x07d89): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x07df1): (155, "AccessorPairMap"),
("RO_SPACE", 0x07e59): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x07ec1): (157, "AllocationMementoMap"),
("RO_SPACE", 0x07f29): (158, "AllocationSiteMap"),
("RO_SPACE", 0x07f91): (159, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x07ff9): (160, "DebugInfoMap"),
("RO_SPACE", 0x08061): (161, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x080c9): (163, "InterpreterDataMap"),
("RO_SPACE", 0x08131): (164, "ModuleInfoEntryMap"),
("RO_SPACE", 0x08199): (165, "ModuleMap"),
("RO_SPACE", 0x08201): (166, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x08269): (167, "PromiseCapabilityMap"),
("RO_SPACE", 0x082d1): (168, "PromiseReactionMap"),
("RO_SPACE", 0x08339): (169, "PrototypeInfoMap"),
("RO_SPACE", 0x083a1): (171, "StackFrameInfoMap"),
("RO_SPACE", 0x08409): (173, "Tuple3Map"),
("RO_SPACE", 0x08471): (174, "WasmCompiledModuleMap"),
("RO_SPACE", 0x084d9): (175, "WasmDebugInfoMap"),
("RO_SPACE", 0x08541): (176, "WasmExportedFunctionDataMap"),
("RO_SPACE", 0x085a9): (177, "WasmSharedModuleDataMap"),
("RO_SPACE", 0x08611): (178, "CallableTaskMap"),
("RO_SPACE", 0x08679): (179, "CallbackTaskMap"),
("RO_SPACE", 0x086e1): (180, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x08749): (181, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x087b1): (182, "PromiseResolveThenableJobTaskMap"),
("MAP_SPACE", 0x02201): (1057, "ExternalMap"),
("MAP_SPACE", 0x02259): (1072, "JSMessageObjectMap"),
}