[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}
This commit is contained in:
parent
299f834058
commit
31bc17f006
@ -420,7 +420,6 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(
|
||||
Node* context, Node* promise, Node* on_resolve, Node* on_reject,
|
||||
Node* deferred_promise, Node* deferred_on_resolve,
|
||||
Node* deferred_on_reject) {
|
||||
Node* const native_context = LoadNativeContext(context);
|
||||
|
||||
Variable var_on_resolve(this, MachineRepresentation::kTagged),
|
||||
var_on_reject(this, MachineRepresentation::kTagged);
|
||||
@ -432,14 +431,17 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(
|
||||
append_callbacks(this);
|
||||
GotoIf(TaggedIsSmi(on_resolve), &if_onresolvenotcallable);
|
||||
|
||||
Isolate* isolate = this->isolate();
|
||||
Node* const on_resolve_map = LoadMap(on_resolve);
|
||||
Branch(IsCallableMap(on_resolve_map), &onrejectcheck,
|
||||
&if_onresolvenotcallable);
|
||||
|
||||
Bind(&if_onresolvenotcallable);
|
||||
{
|
||||
var_on_resolve.Bind(LoadContextElement(
|
||||
native_context, Context::PROMISE_ID_RESOLVE_HANDLER_INDEX));
|
||||
Isolate* isolate = this->isolate();
|
||||
Node* const default_resolve_handler_symbol = HeapConstant(
|
||||
isolate->factory()->promise_default_resolve_handler_symbol());
|
||||
var_on_resolve.Bind(default_resolve_handler_symbol);
|
||||
Goto(&onrejectcheck);
|
||||
}
|
||||
|
||||
@ -454,8 +456,9 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(
|
||||
|
||||
Bind(&if_onrejectnotcallable);
|
||||
{
|
||||
var_on_reject.Bind(LoadContextElement(
|
||||
native_context, Context::PROMISE_ID_REJECT_HANDLER_INDEX));
|
||||
Node* const default_reject_handler_symbol = HeapConstant(
|
||||
isolate->factory()->promise_default_reject_handler_symbol());
|
||||
var_on_reject.Bind(default_reject_handler_symbol);
|
||||
Goto(&append_callbacks);
|
||||
}
|
||||
}
|
||||
@ -1265,25 +1268,55 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
|
||||
|
||||
Bind(&run_handler);
|
||||
{
|
||||
Callable call_callable = CodeFactory::Call(isolate);
|
||||
Node* const result =
|
||||
CallJS(call_callable, context, handler, UndefinedConstant(), value);
|
||||
Label if_defaulthandler(this), if_callablehandler(this),
|
||||
if_internalhandler(this), if_customhandler(this, Label::kDeferred);
|
||||
Variable var_result(this, MachineRepresentation::kTagged);
|
||||
|
||||
GotoIfException(result, &if_rejectpromise, &var_reason);
|
||||
Branch(IsSymbol(handler), &if_defaulthandler, &if_callablehandler);
|
||||
|
||||
Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
|
||||
Branch(IsUndefined(deferred_on_resolve), &if_internalhandler,
|
||||
&if_customhandler);
|
||||
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);
|
||||
Node* const result =
|
||||
CallJS(call_callable, context, handler, UndefinedConstant(), value);
|
||||
var_result.Bind(result);
|
||||
GotoIfException(result, &if_rejectpromise, &var_reason);
|
||||
Branch(IsUndefined(deferred_on_resolve), &if_internalhandler,
|
||||
&if_customhandler);
|
||||
}
|
||||
|
||||
Bind(&if_internalhandler);
|
||||
InternalResolvePromise(context, deferred_promise, result);
|
||||
InternalResolvePromise(context, deferred_promise, var_result.value());
|
||||
Goto(&promisehook_after);
|
||||
|
||||
Bind(&if_customhandler);
|
||||
{
|
||||
Callable call_callable = CodeFactory::Call(isolate);
|
||||
Node* const maybe_exception =
|
||||
CallJS(call_callable, context, deferred_on_resolve,
|
||||
UndefinedConstant(), result);
|
||||
UndefinedConstant(), var_result.value());
|
||||
GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
|
||||
Goto(&promisehook_after);
|
||||
}
|
||||
|
@ -107,8 +107,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_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(REFERENCE_ERROR_FUNCTION_INDEX, JSFunction, reference_error_function) \
|
||||
V(SET_ADD_METHOD_INDEX, JSFunction, set_add) \
|
||||
|
@ -207,40 +207,42 @@
|
||||
V(writable_string, "writable") \
|
||||
V(year_string, "year")
|
||||
|
||||
#define PRIVATE_SYMBOL_LIST(V) \
|
||||
V(array_iteration_kind_symbol) \
|
||||
V(array_iterator_next_symbol) \
|
||||
V(array_iterator_object_symbol) \
|
||||
V(call_site_frame_array_symbol) \
|
||||
V(call_site_frame_index_symbol) \
|
||||
V(class_end_position_symbol) \
|
||||
V(class_start_position_symbol) \
|
||||
V(detailed_stack_trace_symbol) \
|
||||
V(elements_transition_symbol) \
|
||||
V(error_end_pos_symbol) \
|
||||
V(error_script_symbol) \
|
||||
V(error_start_pos_symbol) \
|
||||
V(frozen_symbol) \
|
||||
V(hash_code_symbol) \
|
||||
V(home_object_symbol) \
|
||||
V(intl_initialized_marker_symbol) \
|
||||
V(intl_pattern_symbol) \
|
||||
V(intl_resolved_symbol) \
|
||||
V(megamorphic_symbol) \
|
||||
V(native_context_index_symbol) \
|
||||
V(nonexistent_symbol) \
|
||||
V(nonextensible_symbol) \
|
||||
V(normal_ic_symbol) \
|
||||
V(not_mapped_symbol) \
|
||||
V(premonomorphic_symbol) \
|
||||
V(promise_async_stack_id_symbol) \
|
||||
V(promise_debug_marker_symbol) \
|
||||
V(promise_forwarding_handler_symbol) \
|
||||
V(promise_handled_by_symbol) \
|
||||
V(promise_async_id_symbol) \
|
||||
V(sealed_symbol) \
|
||||
V(stack_trace_symbol) \
|
||||
V(strict_function_transition_symbol) \
|
||||
#define PRIVATE_SYMBOL_LIST(V) \
|
||||
V(array_iteration_kind_symbol) \
|
||||
V(array_iterator_next_symbol) \
|
||||
V(array_iterator_object_symbol) \
|
||||
V(call_site_frame_array_symbol) \
|
||||
V(call_site_frame_index_symbol) \
|
||||
V(class_end_position_symbol) \
|
||||
V(class_start_position_symbol) \
|
||||
V(detailed_stack_trace_symbol) \
|
||||
V(elements_transition_symbol) \
|
||||
V(error_end_pos_symbol) \
|
||||
V(error_script_symbol) \
|
||||
V(error_start_pos_symbol) \
|
||||
V(frozen_symbol) \
|
||||
V(hash_code_symbol) \
|
||||
V(home_object_symbol) \
|
||||
V(intl_initialized_marker_symbol) \
|
||||
V(intl_pattern_symbol) \
|
||||
V(intl_resolved_symbol) \
|
||||
V(megamorphic_symbol) \
|
||||
V(native_context_index_symbol) \
|
||||
V(nonexistent_symbol) \
|
||||
V(nonextensible_symbol) \
|
||||
V(normal_ic_symbol) \
|
||||
V(not_mapped_symbol) \
|
||||
V(premonomorphic_symbol) \
|
||||
V(promise_async_stack_id_symbol) \
|
||||
V(promise_debug_marker_symbol) \
|
||||
V(promise_forwarding_handler_symbol) \
|
||||
V(promise_handled_by_symbol) \
|
||||
V(promise_async_id_symbol) \
|
||||
V(promise_default_resolve_handler_symbol) \
|
||||
V(promise_default_reject_handler_symbol) \
|
||||
V(sealed_symbol) \
|
||||
V(stack_trace_symbol) \
|
||||
V(strict_function_transition_symbol) \
|
||||
V(uninitialized_symbol)
|
||||
|
||||
#define PUBLIC_SYMBOL_LIST(V) \
|
||||
|
@ -1878,6 +1878,11 @@ bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate,
|
||||
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> deferred_promise_arr =
|
||||
Handle<FixedArray>::cast(deferred_promise);
|
||||
|
@ -18,14 +18,6 @@ var promiseForwardingHandlerSymbol =
|
||||
utils.ImportNow("promise_forwarding_handler_symbol");
|
||||
var GlobalPromise = global.Promise;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// Core functionality.
|
||||
|
||||
function PromiseIdResolveHandler(x) { return x; }
|
||||
function PromiseIdRejectHandler(r) { %_ReThrow(r); }
|
||||
SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Define exported functions.
|
||||
|
||||
@ -137,9 +129,4 @@ utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
|
||||
"race", PromiseRace,
|
||||
]);
|
||||
|
||||
%InstallToContext([
|
||||
"promise_id_resolve_handler", PromiseIdResolveHandler,
|
||||
"promise_id_reject_handler", PromiseIdRejectHandler
|
||||
]);
|
||||
|
||||
})
|
||||
|
@ -922,10 +922,11 @@ void JSPromise::JSPromiseVerify() {
|
||||
deferred_on_reject()->IsCallable() ||
|
||||
deferred_on_reject()->IsFixedArray());
|
||||
CHECK(fulfill_reactions()->IsUndefined(isolate) ||
|
||||
fulfill_reactions()->IsCallable() ||
|
||||
fulfill_reactions()->IsCallable() || fulfill_reactions()->IsSymbol() ||
|
||||
fulfill_reactions()->IsFixedArray());
|
||||
CHECK(reject_reactions()->IsUndefined(isolate) ||
|
||||
reject_reactions()->IsCallable() || reject_reactions()->IsFixedArray());
|
||||
reject_reactions()->IsSymbol() || reject_reactions()->IsCallable() ||
|
||||
reject_reactions()->IsFixedArray());
|
||||
}
|
||||
|
||||
void JSRegExp::JSRegExpVerify() {
|
||||
@ -1051,7 +1052,8 @@ void PromiseReactionJobInfo::PromiseReactionJobInfoVerify() {
|
||||
Isolate* isolate = GetIsolate();
|
||||
CHECK(IsPromiseReactionJobInfo());
|
||||
CHECK(value()->IsObject());
|
||||
CHECK(tasks()->IsFixedArray() || tasks()->IsCallable());
|
||||
CHECK(tasks()->IsFixedArray() || tasks()->IsCallable() ||
|
||||
tasks()->IsSymbol());
|
||||
CHECK(deferred_promise()->IsUndefined(isolate) ||
|
||||
deferred_promise()->IsJSReceiver() ||
|
||||
deferred_promise()->IsFixedArray());
|
||||
|
@ -8507,13 +8507,15 @@ class JSPromise : public JSObject {
|
||||
// 1) Undefined -- This is the zero state when there is no callback
|
||||
// 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
|
||||
// directly attached to the slots. In this state, deferred_promise
|
||||
// is a JSReceiver and deferred_on_{resolve, reject} are Callables.
|
||||
//
|
||||
// 3) FixedArray -- There is more than one callback and deferred
|
||||
// fields attached to a FixedArray.
|
||||
//
|
||||
// The callback can be a Callable or a Symbol.
|
||||
DECL_ACCESSORS(deferred_promise, Object)
|
||||
DECL_ACCESSORS(deferred_on_resolve, Object)
|
||||
DECL_ACCESSORS(deferred_on_reject, Object)
|
||||
|
Loading…
Reference in New Issue
Block a user