[promises] Remove runtime call from PromiseReject
Also moves some functions to prologue.js BUG=v8:5343 Review-Url: https://codereview.chromium.org/2630593004 Cr-Commit-Position: refs/heads/master@{#42417}
This commit is contained in:
parent
6715439932
commit
2fd434160a
@ -7307,9 +7307,12 @@ Maybe<bool> Promise::Resolver::Reject(Local<Context> context,
|
||||
Local<Value> value) {
|
||||
PREPARE_FOR_EXECUTION_PRIMITIVE(context, Promise_Resolver, Resolve, bool);
|
||||
auto self = Utils::OpenHandle(this);
|
||||
i::Handle<i::Object> argv[] = {self, Utils::OpenHandle(*value)};
|
||||
|
||||
// We pass true to trigger the debugger's on exception handler.
|
||||
i::Handle<i::Object> argv[] = {self, Utils::OpenHandle(*value),
|
||||
isolate->factory()->ToBoolean(true)};
|
||||
has_pending_exception =
|
||||
i::Execution::Call(isolate, isolate->promise_reject(),
|
||||
i::Execution::Call(isolate, isolate->promise_internal_reject(),
|
||||
isolate->factory()->undefined_value(), arraysize(argv),
|
||||
argv)
|
||||
.is_null();
|
||||
|
@ -1971,6 +1971,14 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
promise_handle->set_is_exception_caught(true);
|
||||
}
|
||||
|
||||
{ // Internal: InternalPromiseReject
|
||||
Handle<JSFunction> function =
|
||||
SimpleCreateFunction(isolate, factory->empty_string(),
|
||||
Builtins::kInternalPromiseReject, 3, true);
|
||||
InstallWithIntrinsicDefaultProto(isolate, function,
|
||||
Context::PROMISE_INTERNAL_REJECT_INDEX);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<Code> code =
|
||||
handle(isolate->builtins()->builtin(Builtins::kPromiseResolveClosure),
|
||||
|
@ -748,8 +748,7 @@ void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context,
|
||||
|
||||
Bind(&reject);
|
||||
// Don't cause a debug event as this case is forwarding a rejection
|
||||
CallRuntime(Runtime::kPromiseReject, context, promise, thenable_value,
|
||||
FalseConstant());
|
||||
InternalPromiseReject(context, promise, thenable_value, false);
|
||||
PromiseSetHasHandler(result);
|
||||
Goto(&out);
|
||||
}
|
||||
@ -836,8 +835,7 @@ void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context,
|
||||
// 9.a Return RejectPromise(promise, then.[[Value]]).
|
||||
Bind(&if_rejectpromise);
|
||||
{
|
||||
CallRuntime(Runtime::kPromiseReject, context, promise, var_reason.value(),
|
||||
TrueConstant());
|
||||
InternalPromiseReject(context, promise, var_reason.value(), true);
|
||||
Goto(&out);
|
||||
}
|
||||
|
||||
@ -943,6 +941,52 @@ void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed(
|
||||
Bind(&has_access);
|
||||
}
|
||||
|
||||
void PromiseBuiltinsAssembler::InternalPromiseReject(Node* context,
|
||||
Node* promise, Node* value,
|
||||
Node* debug_event) {
|
||||
Label out(this);
|
||||
GotoUnless(IsDebugActive(), &out);
|
||||
GotoUnless(WordEqual(TrueConstant(), debug_event), &out);
|
||||
CallRuntime(Runtime::kDebugPromiseReject, context, promise, value);
|
||||
Goto(&out);
|
||||
|
||||
Bind(&out);
|
||||
InternalPromiseReject(context, promise, value, false);
|
||||
}
|
||||
|
||||
// This duplicates a lot of logic from PromiseRejectEvent in
|
||||
// runtime-promise.cc
|
||||
void PromiseBuiltinsAssembler::InternalPromiseReject(Node* context,
|
||||
Node* promise, Node* value,
|
||||
bool debug_event) {
|
||||
Label fulfill(this), report_unhandledpromise(this), run_promise_hook(this);
|
||||
|
||||
if (debug_event) {
|
||||
GotoUnless(IsDebugActive(), &run_promise_hook);
|
||||
CallRuntime(Runtime::kDebugPromiseReject, context, promise, value);
|
||||
Goto(&run_promise_hook);
|
||||
} else {
|
||||
Goto(&run_promise_hook);
|
||||
}
|
||||
|
||||
Bind(&run_promise_hook);
|
||||
{
|
||||
GotoUnless(IsPromiseHookEnabled(), &report_unhandledpromise);
|
||||
CallRuntime(Runtime::kPromiseHookResolve, context, promise);
|
||||
Goto(&report_unhandledpromise);
|
||||
}
|
||||
|
||||
Bind(&report_unhandledpromise);
|
||||
{
|
||||
GotoIf(PromiseHasHandler(promise), &fulfill);
|
||||
CallRuntime(Runtime::kReportPromiseReject, context, promise, value);
|
||||
Goto(&fulfill);
|
||||
}
|
||||
|
||||
Bind(&fulfill);
|
||||
PromiseFulfill(context, promise, value, v8::Promise::kRejected);
|
||||
}
|
||||
|
||||
// ES#sec-promise-reject-functions
|
||||
// Promise Reject Functions
|
||||
TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) {
|
||||
@ -970,7 +1014,7 @@ TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) {
|
||||
Node* const debug_event = LoadContextElement(
|
||||
context, IntPtrConstant(PromiseUtils::kDebugEventSlot));
|
||||
|
||||
CallRuntime(Runtime::kPromiseReject, context, promise, value, debug_event);
|
||||
InternalPromiseReject(context, promise, value, debug_event);
|
||||
Return(UndefinedConstant());
|
||||
|
||||
Bind(&out);
|
||||
@ -1207,8 +1251,7 @@ TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) {
|
||||
|
||||
Bind(&if_internalhandler);
|
||||
{
|
||||
CallRuntime(Runtime::kPromiseReject, context, promise, exception,
|
||||
FalseConstant());
|
||||
InternalPromiseReject(context, promise, exception, false);
|
||||
Return(UndefinedConstant());
|
||||
}
|
||||
|
||||
@ -1504,5 +1547,15 @@ TF_BUILTIN(PromiseReject, PromiseBuiltinsAssembler) {
|
||||
}
|
||||
}
|
||||
|
||||
TF_BUILTIN(InternalPromiseReject, PromiseBuiltinsAssembler) {
|
||||
Node* const promise = Parameter(1);
|
||||
Node* const reason = Parameter(2);
|
||||
Node* const debug_event = Parameter(3);
|
||||
Node* const context = Parameter(6);
|
||||
|
||||
InternalPromiseReject(context, promise, reason, debug_event);
|
||||
Return(UndefinedConstant());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -34,6 +34,23 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler {
|
||||
Node* resolve, Node* reject,
|
||||
Node* context);
|
||||
|
||||
std::pair<Node*, Node*> CreatePromiseResolvingFunctions(
|
||||
Node* promise, Node* native_context, Node* promise_context);
|
||||
|
||||
Node* PromiseHasHandler(Node* promise);
|
||||
|
||||
Node* CreatePromiseResolvingFunctionsContext(Node* promise, Node* debug_event,
|
||||
Node* native_context);
|
||||
|
||||
Node* CreatePromiseGetCapabilitiesExecutorContext(Node* native_context,
|
||||
Node* promise_capability);
|
||||
|
||||
Node* NewPromiseCapability(Node* context, Node* constructor,
|
||||
Node* debug_event = nullptr);
|
||||
|
||||
protected:
|
||||
void PromiseInit(Node* promise);
|
||||
|
||||
Node* ThrowIfNotJSReceiver(Node* context, Node* value,
|
||||
MessageTemplate::Template msg_template,
|
||||
const char* method_name = nullptr);
|
||||
@ -41,8 +58,6 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler {
|
||||
Node* SpeciesConstructor(Node* context, Node* object,
|
||||
Node* default_constructor);
|
||||
|
||||
Node* PromiseHasHandler(Node* promise);
|
||||
|
||||
void PromiseSetHasHandler(Node* promise);
|
||||
|
||||
void AppendPromiseCallback(int offset, compiler::Node* promise,
|
||||
@ -66,27 +81,17 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler {
|
||||
Label* if_isunmodified, Label* if_ismodified);
|
||||
|
||||
Node* CreatePromiseContext(Node* native_context, int slots);
|
||||
Node* CreatePromiseResolvingFunctionsContext(Node* promise, Node* debug_event,
|
||||
Node* native_context);
|
||||
|
||||
std::pair<Node*, Node*> CreatePromiseResolvingFunctions(
|
||||
Node* promise, Node* native_context, Node* promise_context);
|
||||
|
||||
Node* CreatePromiseGetCapabilitiesExecutorContext(Node* native_context,
|
||||
Node* promise_capability);
|
||||
|
||||
void PromiseFulfill(Node* context, Node* promise, Node* result,
|
||||
v8::Promise::PromiseState status);
|
||||
|
||||
Node* NewPromiseCapability(Node* context, Node* constructor,
|
||||
Node* debug_event = nullptr);
|
||||
|
||||
void BranchIfAccessCheckFailed(Node* context, Node* native_context,
|
||||
Node* promise_constructor, Node* executor,
|
||||
Label* if_noaccess);
|
||||
|
||||
protected:
|
||||
void PromiseInit(Node* promise);
|
||||
void InternalPromiseReject(Node* context, Node* promise, Node* value,
|
||||
bool debug_event);
|
||||
void InternalPromiseReject(Node* context, Node* promise, Node* value,
|
||||
Node* debug_event);
|
||||
|
||||
private:
|
||||
Node* AllocateJSPromise(Node* context);
|
||||
|
@ -639,6 +639,7 @@ namespace internal {
|
||||
TFJ(PromiseHandle, 5) \
|
||||
TFJ(PromiseResolve, 1) \
|
||||
TFJ(PromiseReject, 1) \
|
||||
TFJ(InternalPromiseReject, 3) \
|
||||
\
|
||||
/* Proxy */ \
|
||||
CPP(ProxyConstructor) \
|
||||
|
@ -64,6 +64,7 @@ enum ContextLookupFlags {
|
||||
V(NEW_PROMISE_CAPABILITY_INDEX, JSFunction, new_promise_capability) \
|
||||
V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \
|
||||
promise_internal_constructor) \
|
||||
V(PROMISE_INTERNAL_REJECT_INDEX, JSFunction, promise_internal_reject) \
|
||||
V(IS_PROMISE_INDEX, JSFunction, is_promise) \
|
||||
V(PERFORM_PROMISE_THEN_INDEX, JSFunction, perform_promise_then) \
|
||||
V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \
|
||||
@ -103,7 +104,6 @@ enum ContextLookupFlags {
|
||||
V(OBJECT_TO_STRING, JSFunction, object_to_string) \
|
||||
V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \
|
||||
V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \
|
||||
V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \
|
||||
V(PROMISE_ID_RESOLVE_HANDLER_INDEX, JSFunction, promise_id_resolve_handler) \
|
||||
V(PROMISE_ID_REJECT_HANDLER_INDEX, JSFunction, promise_id_reject_handler) \
|
||||
V(RANGE_ERROR_FUNCTION_INDEX, JSFunction, range_error_function) \
|
||||
|
@ -108,7 +108,7 @@ function AsyncFunctionAwaitCaught(generator, awaited, outerPromise) {
|
||||
|
||||
// How the parser rejects promises from async/await desugaring
|
||||
function RejectPromiseNoDebugEvent(promise, reason) {
|
||||
return %PromiseReject(promise, reason, false);
|
||||
return %promise_internal_reject(promise, reason, false);
|
||||
}
|
||||
|
||||
function AsyncFunctionPromiseCreate() {
|
||||
|
@ -266,7 +266,7 @@ utils.PostDebug = PostDebug;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
%OptimizeObjectForAddingMultipleProperties(extrasUtils, 5);
|
||||
%OptimizeObjectForAddingMultipleProperties(extrasUtils, 7);
|
||||
|
||||
extrasUtils.logStackTrace = function logStackTrace() {
|
||||
%DebugTrace();
|
||||
@ -307,6 +307,15 @@ extrasUtils.uncurryThis = function uncurryThis(func) {
|
||||
};
|
||||
};
|
||||
|
||||
// We pass true to trigger the debugger's on exception handler.
|
||||
extrasUtils.rejectPromise = function rejectPromise(promise, reason) {
|
||||
%promise_internal_reject(promise, reason, true);
|
||||
}
|
||||
|
||||
extrasUtils.markPromiseAsHandled = function markPromiseAsHandled(promise) {
|
||||
%PromiseMarkAsHandled(promise);
|
||||
};
|
||||
|
||||
%ToFastProperties(extrasUtils);
|
||||
|
||||
})
|
||||
|
@ -29,13 +29,6 @@ SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true);
|
||||
// -------------------------------------------------------------------
|
||||
// Define exported functions.
|
||||
|
||||
// For bootstrapper.
|
||||
|
||||
// Export to bindings
|
||||
function DoRejectPromise(promise, reason) {
|
||||
%PromiseReject(promise, reason, true);
|
||||
}
|
||||
|
||||
// Combinators.
|
||||
|
||||
// ES#sec-promise.all
|
||||
@ -136,10 +129,6 @@ function PromiseRace(iterable) {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function MarkPromiseAsHandled(promise) {
|
||||
%PromiseMarkAsHandled(promise);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Install exported functions.
|
||||
|
||||
@ -149,17 +138,8 @@ utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
|
||||
]);
|
||||
|
||||
%InstallToContext([
|
||||
"promise_reject", DoRejectPromise,
|
||||
"promise_id_resolve_handler", PromiseIdResolveHandler,
|
||||
"promise_id_reject_handler", PromiseIdRejectHandler
|
||||
]);
|
||||
|
||||
// This allows extras to create promises quickly without building extra
|
||||
// resolve/reject closures, and allows them to later resolve and reject any
|
||||
// promise without having to hold on to those closures forever.
|
||||
utils.InstallFunctions(extrasUtils, 0, [
|
||||
"rejectPromise", DoRejectPromise,
|
||||
"markPromiseAsHandled", MarkPromiseAsHandled
|
||||
]);
|
||||
|
||||
})
|
||||
|
@ -1896,6 +1896,16 @@ RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionPromiseCreated) {
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_DebugPromiseReject) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSPromise, rejected_promise, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
|
||||
|
||||
isolate->debug()->OnPromiseReject(rejected_promise, value);
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_DebugAsyncEventEnqueueRecurring) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
|
@ -51,6 +51,16 @@ RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack) {
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ReportPromiseReject) {
|
||||
DCHECK_EQ(2, args.length());
|
||||
HandleScope scope(isolate);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
|
||||
isolate->ReportPromiseReject(Handle<JSObject>::cast(promise), value,
|
||||
v8::kPromiseRejectWithNoHandler);
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) {
|
||||
DCHECK_EQ(1, args.length());
|
||||
HandleScope scope(isolate);
|
||||
@ -130,58 +140,8 @@ void EnqueuePromiseReactionJob(Isolate* isolate, Handle<JSPromise> promise,
|
||||
isolate->EnqueueMicrotask(info);
|
||||
}
|
||||
|
||||
void PromiseSet(Isolate* isolate, Handle<JSPromise> promise, int status,
|
||||
Handle<Object> result) {
|
||||
promise->set_status(status);
|
||||
promise->set_result(*result);
|
||||
promise->set_deferred_promise(isolate->heap()->undefined_value());
|
||||
promise->set_deferred_on_resolve(isolate->heap()->undefined_value());
|
||||
promise->set_deferred_on_reject(isolate->heap()->undefined_value());
|
||||
promise->set_fulfill_reactions(isolate->heap()->undefined_value());
|
||||
promise->set_reject_reactions(isolate->heap()->undefined_value());
|
||||
}
|
||||
|
||||
void PromiseFulfill(Isolate* isolate, Handle<JSPromise> promise, int status,
|
||||
Handle<Object> value) {
|
||||
if (isolate->debug()->is_active()) {
|
||||
isolate->debug()->OnAsyncTaskEvent(
|
||||
status == v8::Promise::kFulfilled ? debug::kDebugEnqueuePromiseResolve
|
||||
: debug::kDebugEnqueuePromiseReject,
|
||||
isolate->debug()->NextAsyncTaskId(promise));
|
||||
}
|
||||
// Check if there are any callbacks.
|
||||
if (!promise->deferred_promise()->IsUndefined(isolate)) {
|
||||
Handle<Object> tasks((status == v8::Promise::kFulfilled)
|
||||
? promise->fulfill_reactions()
|
||||
: promise->reject_reactions(),
|
||||
isolate);
|
||||
Handle<PromiseReactionJobInfo> info =
|
||||
isolate->factory()->NewPromiseReactionJobInfo(
|
||||
value, tasks, handle(promise->deferred_promise(), isolate),
|
||||
handle(promise->deferred_on_resolve(), isolate),
|
||||
handle(promise->deferred_on_reject(), isolate),
|
||||
isolate->native_context());
|
||||
EnqueuePromiseReactionJob(isolate, promise, info, status);
|
||||
}
|
||||
|
||||
PromiseSet(isolate, promise, status, value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_PromiseReject) {
|
||||
DCHECK_EQ(3, args.length());
|
||||
HandleScope scope(isolate);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1);
|
||||
CONVERT_BOOLEAN_ARG_CHECKED(debug_event, 2);
|
||||
|
||||
PromiseRejectEvent(isolate, promise, promise, reason, debug_event);
|
||||
PromiseFulfill(isolate, promise, v8::Promise::kRejected, reason);
|
||||
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_EnqueuePromiseReactionJob) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
|
@ -199,6 +199,7 @@ namespace internal {
|
||||
F(DebugRecordGenerator, 1, 1) \
|
||||
F(DebugPushPromise, 1, 1) \
|
||||
F(DebugPopPromise, 0, 1) \
|
||||
F(DebugPromiseReject, 2, 1) \
|
||||
F(DebugNextAsyncTaskId, 1, 1) \
|
||||
F(DebugAsyncEventEnqueueRecurring, 2, 1) \
|
||||
F(DebugAsyncFunctionPromiseCreated, 1, 1) \
|
||||
@ -304,7 +305,7 @@ namespace internal {
|
||||
F(NewSyntaxError, 2, 1) \
|
||||
F(NewTypeError, 2, 1) \
|
||||
F(OrdinaryHasInstance, 2, 1) \
|
||||
F(PromiseReject, 3, 1) \
|
||||
F(ReportPromiseReject, 2, 1) \
|
||||
F(PromiseHookInit, 2, 1) \
|
||||
F(PromiseHookResolve, 1, 1) \
|
||||
F(PromiseHookBefore, 1, 1) \
|
||||
|
Loading…
Reference in New Issue
Block a user