Commit 2fd43416 authored by gsathya's avatar gsathya Committed by Commit bot

[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}
parent 67154399
......@@ -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) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment