Commit 31bc17f0 authored by gsathya's avatar gsathya Committed by Commit bot

[promises] cleanup default promise handlers

Use private symbols to mark default promise handler, instead of calling out to default
handlers defined in JS. We check for this symbol in PromiseHandle and perform the
appropriate behavior as the default handlers.

Catch prediction logic is updated to account for a symbol.

BUG=v8:5343

Review-Url: https://codereview.chromium.org/2695593002
Cr-Commit-Position: refs/heads/master@{#43135}
parent 299f8340
...@@ -420,7 +420,6 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen( ...@@ -420,7 +420,6 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(
Node* context, Node* promise, Node* on_resolve, Node* on_reject, Node* context, Node* promise, Node* on_resolve, Node* on_reject,
Node* deferred_promise, Node* deferred_on_resolve, Node* deferred_promise, Node* deferred_on_resolve,
Node* deferred_on_reject) { Node* deferred_on_reject) {
Node* const native_context = LoadNativeContext(context);
Variable var_on_resolve(this, MachineRepresentation::kTagged), Variable var_on_resolve(this, MachineRepresentation::kTagged),
var_on_reject(this, MachineRepresentation::kTagged); var_on_reject(this, MachineRepresentation::kTagged);
...@@ -432,14 +431,17 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen( ...@@ -432,14 +431,17 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(
append_callbacks(this); append_callbacks(this);
GotoIf(TaggedIsSmi(on_resolve), &if_onresolvenotcallable); GotoIf(TaggedIsSmi(on_resolve), &if_onresolvenotcallable);
Isolate* isolate = this->isolate();
Node* const on_resolve_map = LoadMap(on_resolve); Node* const on_resolve_map = LoadMap(on_resolve);
Branch(IsCallableMap(on_resolve_map), &onrejectcheck, Branch(IsCallableMap(on_resolve_map), &onrejectcheck,
&if_onresolvenotcallable); &if_onresolvenotcallable);
Bind(&if_onresolvenotcallable); Bind(&if_onresolvenotcallable);
{ {
var_on_resolve.Bind(LoadContextElement( Isolate* isolate = this->isolate();
native_context, Context::PROMISE_ID_RESOLVE_HANDLER_INDEX)); Node* const default_resolve_handler_symbol = HeapConstant(
isolate->factory()->promise_default_resolve_handler_symbol());
var_on_resolve.Bind(default_resolve_handler_symbol);
Goto(&onrejectcheck); Goto(&onrejectcheck);
} }
...@@ -454,8 +456,9 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen( ...@@ -454,8 +456,9 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(
Bind(&if_onrejectnotcallable); Bind(&if_onrejectnotcallable);
{ {
var_on_reject.Bind(LoadContextElement( Node* const default_reject_handler_symbol = HeapConstant(
native_context, Context::PROMISE_ID_REJECT_HANDLER_INDEX)); isolate->factory()->promise_default_reject_handler_symbol());
var_on_reject.Bind(default_reject_handler_symbol);
Goto(&append_callbacks); Goto(&append_callbacks);
} }
} }
...@@ -1264,26 +1267,56 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { ...@@ -1264,26 +1267,56 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
} }
Bind(&run_handler); Bind(&run_handler);
{
Label if_defaulthandler(this), if_callablehandler(this),
if_internalhandler(this), if_customhandler(this, Label::kDeferred);
Variable var_result(this, MachineRepresentation::kTagged);
Branch(IsSymbol(handler), &if_defaulthandler, &if_callablehandler);
Bind(&if_defaulthandler);
{
Label if_resolve(this), if_reject(this);
Node* const default_resolve_handler_symbol = HeapConstant(
isolate->factory()->promise_default_resolve_handler_symbol());
Branch(WordEqual(default_resolve_handler_symbol, handler), &if_resolve,
&if_reject);
Bind(&if_resolve);
{
var_result.Bind(value);
Branch(IsUndefined(deferred_on_resolve), &if_internalhandler,
&if_customhandler);
}
Bind(&if_reject);
{
var_reason.Bind(value);
Goto(&if_rejectpromise);
}
}
Bind(&if_callablehandler);
{ {
Callable call_callable = CodeFactory::Call(isolate); Callable call_callable = CodeFactory::Call(isolate);
Node* const result = Node* const result =
CallJS(call_callable, context, handler, UndefinedConstant(), value); CallJS(call_callable, context, handler, UndefinedConstant(), value);
var_result.Bind(result);
GotoIfException(result, &if_rejectpromise, &var_reason); GotoIfException(result, &if_rejectpromise, &var_reason);
Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
Branch(IsUndefined(deferred_on_resolve), &if_internalhandler, Branch(IsUndefined(deferred_on_resolve), &if_internalhandler,
&if_customhandler); &if_customhandler);
}
Bind(&if_internalhandler); Bind(&if_internalhandler);
InternalResolvePromise(context, deferred_promise, result); InternalResolvePromise(context, deferred_promise, var_result.value());
Goto(&promisehook_after); Goto(&promisehook_after);
Bind(&if_customhandler); Bind(&if_customhandler);
{ {
Callable call_callable = CodeFactory::Call(isolate);
Node* const maybe_exception = Node* const maybe_exception =
CallJS(call_callable, context, deferred_on_resolve, CallJS(call_callable, context, deferred_on_resolve,
UndefinedConstant(), result); UndefinedConstant(), var_result.value());
GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
Goto(&promisehook_after); Goto(&promisehook_after);
} }
......
...@@ -107,8 +107,6 @@ enum ContextLookupFlags { ...@@ -107,8 +107,6 @@ enum ContextLookupFlags {
V(OBJECT_TO_STRING, JSFunction, object_to_string) \ V(OBJECT_TO_STRING, JSFunction, object_to_string) \
V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \ V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \
V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \ V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \
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) \ V(RANGE_ERROR_FUNCTION_INDEX, JSFunction, range_error_function) \
V(REFERENCE_ERROR_FUNCTION_INDEX, JSFunction, reference_error_function) \ V(REFERENCE_ERROR_FUNCTION_INDEX, JSFunction, reference_error_function) \
V(SET_ADD_METHOD_INDEX, JSFunction, set_add) \ V(SET_ADD_METHOD_INDEX, JSFunction, set_add) \
......
...@@ -238,6 +238,8 @@ ...@@ -238,6 +238,8 @@
V(promise_forwarding_handler_symbol) \ V(promise_forwarding_handler_symbol) \
V(promise_handled_by_symbol) \ V(promise_handled_by_symbol) \
V(promise_async_id_symbol) \ V(promise_async_id_symbol) \
V(promise_default_resolve_handler_symbol) \
V(promise_default_reject_handler_symbol) \
V(sealed_symbol) \ V(sealed_symbol) \
V(stack_trace_symbol) \ V(stack_trace_symbol) \
V(strict_function_transition_symbol) \ V(strict_function_transition_symbol) \
......
...@@ -1878,6 +1878,11 @@ bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate, ...@@ -1878,6 +1878,11 @@ bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
Handle<JSReceiver>::cast(deferred_promise)); Handle<JSReceiver>::cast(deferred_promise));
} }
if (queue->IsSymbol()) {
return InternalPromiseHasUserDefinedRejectHandler(
isolate, Handle<JSPromise>::cast(deferred_promise));
}
Handle<FixedArray> queue_arr = Handle<FixedArray>::cast(queue); Handle<FixedArray> queue_arr = Handle<FixedArray>::cast(queue);
Handle<FixedArray> deferred_promise_arr = Handle<FixedArray> deferred_promise_arr =
Handle<FixedArray>::cast(deferred_promise); Handle<FixedArray>::cast(deferred_promise);
......
...@@ -18,14 +18,6 @@ var promiseForwardingHandlerSymbol = ...@@ -18,14 +18,6 @@ var promiseForwardingHandlerSymbol =
utils.ImportNow("promise_forwarding_handler_symbol"); utils.ImportNow("promise_forwarding_handler_symbol");
var GlobalPromise = global.Promise; var GlobalPromise = global.Promise;
// -------------------------------------------------------------------
// Core functionality.
function PromiseIdResolveHandler(x) { return x; }
function PromiseIdRejectHandler(r) { %_ReThrow(r); }
SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Define exported functions. // Define exported functions.
...@@ -137,9 +129,4 @@ utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ ...@@ -137,9 +129,4 @@ utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
"race", PromiseRace, "race", PromiseRace,
]); ]);
%InstallToContext([
"promise_id_resolve_handler", PromiseIdResolveHandler,
"promise_id_reject_handler", PromiseIdRejectHandler
]);
}) })
...@@ -922,10 +922,11 @@ void JSPromise::JSPromiseVerify() { ...@@ -922,10 +922,11 @@ void JSPromise::JSPromiseVerify() {
deferred_on_reject()->IsCallable() || deferred_on_reject()->IsCallable() ||
deferred_on_reject()->IsFixedArray()); deferred_on_reject()->IsFixedArray());
CHECK(fulfill_reactions()->IsUndefined(isolate) || CHECK(fulfill_reactions()->IsUndefined(isolate) ||
fulfill_reactions()->IsCallable() || fulfill_reactions()->IsCallable() || fulfill_reactions()->IsSymbol() ||
fulfill_reactions()->IsFixedArray()); fulfill_reactions()->IsFixedArray());
CHECK(reject_reactions()->IsUndefined(isolate) || CHECK(reject_reactions()->IsUndefined(isolate) ||
reject_reactions()->IsCallable() || reject_reactions()->IsFixedArray()); reject_reactions()->IsSymbol() || reject_reactions()->IsCallable() ||
reject_reactions()->IsFixedArray());
} }
void JSRegExp::JSRegExpVerify() { void JSRegExp::JSRegExpVerify() {
...@@ -1051,7 +1052,8 @@ void PromiseReactionJobInfo::PromiseReactionJobInfoVerify() { ...@@ -1051,7 +1052,8 @@ void PromiseReactionJobInfo::PromiseReactionJobInfoVerify() {
Isolate* isolate = GetIsolate(); Isolate* isolate = GetIsolate();
CHECK(IsPromiseReactionJobInfo()); CHECK(IsPromiseReactionJobInfo());
CHECK(value()->IsObject()); CHECK(value()->IsObject());
CHECK(tasks()->IsFixedArray() || tasks()->IsCallable()); CHECK(tasks()->IsFixedArray() || tasks()->IsCallable() ||
tasks()->IsSymbol());
CHECK(deferred_promise()->IsUndefined(isolate) || CHECK(deferred_promise()->IsUndefined(isolate) ||
deferred_promise()->IsJSReceiver() || deferred_promise()->IsJSReceiver() ||
deferred_promise()->IsFixedArray()); deferred_promise()->IsFixedArray());
......
...@@ -8507,13 +8507,15 @@ class JSPromise : public JSObject { ...@@ -8507,13 +8507,15 @@ class JSPromise : public JSObject {
// 1) Undefined -- This is the zero state when there is no callback // 1) Undefined -- This is the zero state when there is no callback
// or deferred fields registered. // or deferred fields registered.
// //
// 2) Object -- There is a single Callable directly attached to the // 2) Object -- There is a single callback directly attached to the
// fulfill_reactions, reject_reactions and the deferred fields are // fulfill_reactions, reject_reactions and the deferred fields are
// directly attached to the slots. In this state, deferred_promise // directly attached to the slots. In this state, deferred_promise
// is a JSReceiver and deferred_on_{resolve, reject} are Callables. // is a JSReceiver and deferred_on_{resolve, reject} are Callables.
// //
// 3) FixedArray -- There is more than one callback and deferred // 3) FixedArray -- There is more than one callback and deferred
// fields attached to a FixedArray. // fields attached to a FixedArray.
//
// The callback can be a Callable or a Symbol.
DECL_ACCESSORS(deferred_promise, Object) DECL_ACCESSORS(deferred_promise, Object)
DECL_ACCESSORS(deferred_on_resolve, Object) DECL_ACCESSORS(deferred_on_resolve, Object)
DECL_ACCESSORS(deferred_on_reject, Object) DECL_ACCESSORS(deferred_on_reject, Object)
......
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