| Index: src/builtins/builtins-promise.cc
|
| diff --git a/src/builtins/builtins-promise.cc b/src/builtins/builtins-promise.cc
|
| index d9635755c304d2ad8cbb84918990f5379478d881..a7e78a6ca46322376c85a17a575c68dda3e39e4b 100644
|
| --- a/src/builtins/builtins-promise.cc
|
| +++ b/src/builtins/builtins-promise.cc
|
| @@ -11,345 +11,142 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -// ES#sec-promise-reject-functions
|
| -// Promise Reject Functions
|
| -BUILTIN(PromiseRejectClosure) {
|
| - HandleScope scope(isolate);
|
| -
|
| - Handle<Context> context(isolate->context(), isolate);
|
| -
|
| - if (PromiseUtils::HasAlreadyVisited(context)) {
|
| - return isolate->heap()->undefined_value();
|
| - }
|
| -
|
| - PromiseUtils::SetAlreadyVisited(context);
|
| - Handle<Object> value = args.atOrUndefined(isolate, 1);
|
| - Handle<JSObject> promise = handle(PromiseUtils::GetPromise(context), isolate);
|
| - Handle<Object> debug_event =
|
| - handle(PromiseUtils::GetDebugEvent(context), isolate);
|
| - MaybeHandle<Object> maybe_result;
|
| - Handle<Object> argv[] = {promise, value, debug_event};
|
| - RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, Execution::Call(isolate, isolate->promise_internal_reject(),
|
| - isolate->factory()->undefined_value(),
|
| - arraysize(argv), argv));
|
| - return isolate->heap()->undefined_value();
|
| -}
|
| -
|
| -// ES#sec-createresolvingfunctions
|
| -// CreateResolvingFunctions ( promise )
|
| -BUILTIN(CreateResolvingFunctions) {
|
| - HandleScope scope(isolate);
|
| - DCHECK_EQ(3, args.length());
|
| -
|
| - Handle<JSObject> promise = args.at<JSObject>(1);
|
| - Handle<Object> debug_event = args.at(2);
|
| - Handle<JSFunction> resolve, reject;
|
| -
|
| - PromiseUtils::CreateResolvingFunctions(isolate, promise, debug_event,
|
| - &resolve, &reject);
|
| -
|
| - Handle<FixedArray> result = isolate->factory()->NewFixedArray(2);
|
| - result->set(0, *resolve);
|
| - result->set(1, *reject);
|
| -
|
| - return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2,
|
| - NOT_TENURED);
|
| -}
|
| -
|
| -void Builtins::Generate_PromiseConstructor(
|
| - compiler::CodeAssemblerState* state) {
|
| - CodeStubAssembler a(state);
|
| - typedef CodeStubAssembler::Variable Variable;
|
| - typedef CodeStubAssembler::Label Label;
|
| - typedef compiler::Node Node;
|
| -
|
| - Node* const executor = a.Parameter(1);
|
| - Node* const new_target = a.Parameter(2);
|
| - Node* const context = a.Parameter(4);
|
| - Isolate* isolate = a.isolate();
|
| -
|
| - Label if_targetisundefined(&a, Label::kDeferred);
|
| -
|
| - a.GotoIf(a.IsUndefined(new_target), &if_targetisundefined);
|
| -
|
| - Label if_notcallable(&a, Label::kDeferred);
|
| -
|
| - a.GotoIf(a.TaggedIsSmi(executor), &if_notcallable);
|
| -
|
| - Node* const executor_map = a.LoadMap(executor);
|
| - a.GotoUnless(a.IsCallableMap(executor_map), &if_notcallable);
|
| -
|
| - Node* const native_context = a.LoadNativeContext(context);
|
| - Node* const promise_fun =
|
| - a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
|
| - Node* const is_debug_active = a.IsDebugActive();
|
| - Label if_targetisnotmodified(&a), if_targetismodified(&a, Label::kDeferred),
|
| - run_executor(&a), debug_push(&a, Label::kDeferred), init(&a);
|
| -
|
| - a.Branch(a.WordEqual(promise_fun, new_target), &if_targetisnotmodified,
|
| - &if_targetismodified);
|
| -
|
| - Variable var_result(&a, MachineRepresentation::kTagged),
|
| - var_reject_call(&a, MachineRepresentation::kTagged),
|
| - var_reason(&a, MachineRepresentation::kTagged);
|
| -
|
| - a.Bind(&if_targetisnotmodified);
|
| - {
|
| - Node* const instance = a.AllocateJSPromise(context);
|
| - var_result.Bind(instance);
|
| - a.Goto(&init);
|
| - }
|
| -
|
| - a.Bind(&if_targetismodified);
|
| - {
|
| - Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate);
|
| - Node* const instance =
|
| - a.CallStub(fast_new_object_stub, context, promise_fun, new_target);
|
| -
|
| - var_result.Bind(instance);
|
| - a.Goto(&init);
|
| - }
|
| -
|
| - a.Bind(&init);
|
| - {
|
| - a.PromiseInit(var_result.value());
|
| - a.Branch(is_debug_active, &debug_push, &run_executor);
|
| - }
|
| -
|
| - a.Bind(&debug_push);
|
| - {
|
| - a.CallRuntime(Runtime::kDebugPushPromise, context, var_result.value());
|
| - a.Goto(&run_executor);
|
| - }
|
| -
|
| - a.Bind(&run_executor);
|
| - {
|
| - Label out(&a), if_rejectpromise(&a), debug_pop(&a, Label::kDeferred);
|
| -
|
| - // TODO(gsathya): Move this to TF.
|
| - Node* const resolving_functions = a.CallRuntime(
|
| - Runtime::kCreateResolvingFunctions, context, var_result.value());
|
| - Node* const resolve =
|
| - a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(0));
|
| - Node* const reject =
|
| - a.LoadFixedArrayElement(resolving_functions, a.IntPtrConstant(1));
|
| - Callable call_callable = CodeFactory::Call(isolate);
|
| -
|
| - Node* const maybe_exception =
|
| - a.CallJS(call_callable, context, executor, a.UndefinedConstant(),
|
| - resolve, reject);
|
| +typedef compiler::Node Node;
|
| +typedef CodeStubAssembler::ParameterMode ParameterMode;
|
| +typedef compiler::CodeAssemblerState CodeAssemblerState;
|
|
|
| - a.GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
|
| - a.Branch(is_debug_active, &debug_pop, &out);
|
| -
|
| - a.Bind(&if_rejectpromise);
|
| - {
|
| - Callable call_callable = CodeFactory::Call(isolate);
|
| - a.CallJS(call_callable, context, reject, a.UndefinedConstant(),
|
| - var_reason.value());
|
| - a.Branch(is_debug_active, &debug_pop, &out);
|
| - }
|
| +class PromiseBuiltinsAssembler : public CodeStubAssembler {
|
| + public:
|
| + explicit PromiseBuiltinsAssembler(CodeAssemblerState* state)
|
| + : CodeStubAssembler(state) {}
|
|
|
| - a.Bind(&debug_pop);
|
| - {
|
| - a.CallRuntime(Runtime::kDebugPopPromise, context);
|
| - a.Goto(&out);
|
| - }
|
| - a.Bind(&out);
|
| - a.Return(var_result.value());
|
| - }
|
| + protected:
|
| + Node* ThrowIfNotJSReceiver(Node* context, Node* value,
|
| + MessageTemplate::Template msg_template);
|
|
|
| - // 1. If NewTarget is undefined, throw a TypeError exception.
|
| - a.Bind(&if_targetisundefined);
|
| - {
|
| - Node* const message_id = a.SmiConstant(MessageTemplate::kNotAPromise);
|
| - a.CallRuntime(Runtime::kThrowTypeError, context, message_id, new_target);
|
| - a.Return(a.UndefinedConstant()); // Never reached.
|
| - }
|
| + Node* SpeciesConstructor(Node* context, Node* object,
|
| + Node* default_constructor);
|
|
|
| - // 2. If IsCallable(executor) is false, throw a TypeError exception.
|
| - a.Bind(&if_notcallable);
|
| - {
|
| - Node* const message_id =
|
| - a.SmiConstant(MessageTemplate::kResolverNotAFunction);
|
| - a.CallRuntime(Runtime::kThrowTypeError, context, message_id, executor);
|
| - a.Return(a.UndefinedConstant()); // Never reached.
|
| - }
|
| -}
|
| + Node* PromiseHasHandler(Node* promise);
|
|
|
| -void Builtins::Generate_PromiseInternalConstructor(
|
| - compiler::CodeAssemblerState* state) {
|
| - typedef compiler::Node Node;
|
| - CodeStubAssembler a(state);
|
| + void PromiseSetHasHandler(Node* promise);
|
|
|
| - Node* const context = a.Parameter(3);
|
| - Node* const instance = a.AllocateJSPromise(context);
|
| - a.PromiseInit(instance);
|
| - a.Return(instance);
|
| -}
|
| + void AppendPromiseCallback(int offset, compiler::Node* promise,
|
| + compiler::Node* value);
|
|
|
| -void Builtins::Generate_PromiseCreateAndSet(
|
| - compiler::CodeAssemblerState* state) {
|
| - typedef compiler::Node Node;
|
| - CodeStubAssembler a(state);
|
| + Node* InternalPerformPromiseThen(Node* context, Node* promise,
|
| + Node* on_resolve, Node* on_reject,
|
| + Node* deferred);
|
|
|
| - Node* const status = a.Parameter(1);
|
| - Node* const result = a.Parameter(2);
|
| - Node* const context = a.Parameter(5);
|
| + void InternalResolvePromise(Node* context, Node* promise, Node* result,
|
| + Label* out);
|
|
|
| - Node* const instance = a.AllocateJSPromise(context);
|
| - a.PromiseSet(instance, status, result);
|
| - a.Return(instance);
|
| -}
|
| + void BranchIfFastPath(Node* context, Node* promise, Label* if_isunmodified,
|
| + Label* if_ismodified);
|
| +};
|
|
|
| -namespace {
|
| +Node* PromiseBuiltinsAssembler::ThrowIfNotJSReceiver(
|
| + Node* context, Node* value, MessageTemplate::Template msg_template) {
|
| + Label out(this), throw_exception(this, Label::kDeferred);
|
| + Variable var_value_map(this, MachineRepresentation::kTagged);
|
|
|
| -compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate,
|
| - compiler::Node* context,
|
| - compiler::Node* value,
|
| - MessageTemplate::Template msg_template) {
|
| - typedef compiler::Node Node;
|
| - typedef CodeStubAssembler::Label Label;
|
| - typedef CodeStubAssembler::Variable Variable;
|
| -
|
| - Label out(a), throw_exception(a, Label::kDeferred);
|
| - Variable var_value_map(a, MachineRepresentation::kTagged);
|
| -
|
| - a->GotoIf(a->TaggedIsSmi(value), &throw_exception);
|
| + GotoIf(TaggedIsSmi(value), &throw_exception);
|
|
|
| // Load the instance type of the {value}.
|
| - var_value_map.Bind(a->LoadMap(value));
|
| - Node* const value_instance_type =
|
| - a->LoadMapInstanceType(var_value_map.value());
|
| + var_value_map.Bind(LoadMap(value));
|
| + Node* const value_instance_type = LoadMapInstanceType(var_value_map.value());
|
|
|
| - a->Branch(a->IsJSReceiverInstanceType(value_instance_type), &out,
|
| - &throw_exception);
|
| + Branch(IsJSReceiverInstanceType(value_instance_type), &out, &throw_exception);
|
|
|
| // The {value} is not a compatible receiver for this method.
|
| - a->Bind(&throw_exception);
|
| + Bind(&throw_exception);
|
| {
|
| - Node* const message_id = a->SmiConstant(msg_template);
|
| - a->CallRuntime(Runtime::kThrowTypeError, context, message_id);
|
| - var_value_map.Bind(a->UndefinedConstant());
|
| - a->Goto(&out); // Never reached.
|
| + Node* const message_id = SmiConstant(msg_template);
|
| + CallRuntime(Runtime::kThrowTypeError, context, message_id);
|
| + var_value_map.Bind(UndefinedConstant());
|
| + Goto(&out); // Never reached.
|
| }
|
|
|
| - a->Bind(&out);
|
| + Bind(&out);
|
| return var_value_map.value();
|
| }
|
|
|
| -} // namespace
|
| -
|
| -void Builtins::Generate_IsPromise(compiler::CodeAssemblerState* state) {
|
| - CodeStubAssembler a(state);
|
| - typedef compiler::Node Node;
|
| - typedef CodeStubAssembler::Label Label;
|
| -
|
| - Node* const maybe_promise = a.Parameter(1);
|
| - Label if_notpromise(&a, Label::kDeferred);
|
| -
|
| - a.GotoIf(a.TaggedIsSmi(maybe_promise), &if_notpromise);
|
| -
|
| - Node* const result = a.SelectBooleanConstant(
|
| - a.HasInstanceType(maybe_promise, JS_PROMISE_TYPE));
|
| - a.Return(result);
|
| -
|
| - a.Bind(&if_notpromise);
|
| - a.Return(a.FalseConstant());
|
| +Node* PromiseBuiltinsAssembler::PromiseHasHandler(Node* promise) {
|
| + Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
|
| + return IsSetWord(SmiUntag(flags), 1 << JSPromise::kHasHandlerBit);
|
| }
|
|
|
| -namespace {
|
| -
|
| -compiler::Node* PromiseHasHandler(CodeStubAssembler* a,
|
| - compiler::Node* promise) {
|
| - typedef compiler::Node Node;
|
| -
|
| - Node* const flags = a->LoadObjectField(promise, JSPromise::kFlagsOffset);
|
| - return a->IsSetWord(a->SmiUntag(flags), 1 << JSPromise::kHasHandlerBit);
|
| -}
|
| -
|
| -void PromiseSetHasHandler(CodeStubAssembler* a, compiler::Node* promise) {
|
| - typedef compiler::Node Node;
|
| -
|
| +void PromiseBuiltinsAssembler::PromiseSetHasHandler(Node* promise) {
|
| Node* const flags =
|
| - a->SmiUntag(a->LoadObjectField(promise, JSPromise::kFlagsOffset));
|
| + SmiUntag(LoadObjectField(promise, JSPromise::kFlagsOffset));
|
| Node* const new_flags =
|
| - a->WordOr(flags, a->IntPtrConstant(1 << JSPromise::kHasHandlerBit));
|
| - a->StoreObjectField(promise, JSPromise::kFlagsOffset, a->SmiTag(new_flags));
|
| + WordOr(flags, IntPtrConstant(1 << JSPromise::kHasHandlerBit));
|
| + StoreObjectField(promise, JSPromise::kFlagsOffset, SmiTag(new_flags));
|
| }
|
|
|
| -compiler::Node* SpeciesConstructor(CodeStubAssembler* a, Isolate* isolate,
|
| - compiler::Node* context,
|
| - compiler::Node* object,
|
| - compiler::Node* default_constructor) {
|
| - typedef compiler::Node Node;
|
| - typedef CodeStubAssembler::Label Label;
|
| - typedef CodeStubAssembler::Variable Variable;
|
| -
|
| - Variable var_result(a, MachineRepresentation::kTagged);
|
| +Node* PromiseBuiltinsAssembler::SpeciesConstructor(Node* context, Node* object,
|
| + Node* default_constructor) {
|
| + Isolate* isolate = this->isolate();
|
| + Variable var_result(this, MachineRepresentation::kTagged);
|
| var_result.Bind(default_constructor);
|
|
|
| // 2. Let C be ? Get(O, "constructor").
|
| Node* const constructor_str =
|
| - a->HeapConstant(isolate->factory()->constructor_string());
|
| - Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
|
| + HeapConstant(isolate->factory()->constructor_string());
|
| + Callable getproperty_callable = CodeFactory::GetProperty(isolate);
|
| Node* const constructor =
|
| - a->CallStub(getproperty_callable, context, object, constructor_str);
|
| + CallStub(getproperty_callable, context, object, constructor_str);
|
|
|
| // 3. If C is undefined, return defaultConstructor.
|
| - Label out(a);
|
| - a->GotoIf(a->IsUndefined(constructor), &out);
|
| + Label out(this);
|
| + GotoIf(IsUndefined(constructor), &out);
|
|
|
| // 4. If Type(C) is not Object, throw a TypeError exception.
|
| - ThrowIfNotJSReceiver(a, a->isolate(), context, constructor,
|
| + ThrowIfNotJSReceiver(context, constructor,
|
| MessageTemplate::kConstructorNotReceiver);
|
|
|
| // 5. Let S be ? Get(C, @@species).
|
| Node* const species_symbol =
|
| - a->HeapConstant(isolate->factory()->species_symbol());
|
| + HeapConstant(isolate->factory()->species_symbol());
|
| Node* const species =
|
| - a->CallStub(getproperty_callable, context, constructor, species_symbol);
|
| + CallStub(getproperty_callable, context, constructor, species_symbol);
|
|
|
| // 6. If S is either undefined or null, return defaultConstructor.
|
| - a->GotoIf(a->IsUndefined(species), &out);
|
| - a->GotoIf(a->WordEqual(species, a->NullConstant()), &out);
|
| + GotoIf(IsUndefined(species), &out);
|
| + GotoIf(WordEqual(species, NullConstant()), &out);
|
|
|
| // 7. If IsConstructor(S) is true, return S.
|
| - Label throw_error(a);
|
| - Node* species_bitfield = a->LoadMapBitField(a->LoadMap(species));
|
| - a->GotoUnless(
|
| - a->Word32Equal(a->Word32And(species_bitfield,
|
| - a->Int32Constant((1 << Map::kIsConstructor))),
|
| - a->Int32Constant(1 << Map::kIsConstructor)),
|
| - &throw_error);
|
| + Label throw_error(this);
|
| + Node* species_bitfield = LoadMapBitField(LoadMap(species));
|
| + GotoUnless(Word32Equal(Word32And(species_bitfield,
|
| + Int32Constant((1 << Map::kIsConstructor))),
|
| + Int32Constant(1 << Map::kIsConstructor)),
|
| + &throw_error);
|
| var_result.Bind(species);
|
| - a->Goto(&out);
|
| + Goto(&out);
|
|
|
| // 8. Throw a TypeError exception.
|
| - a->Bind(&throw_error);
|
| + Bind(&throw_error);
|
| {
|
| Node* const message_id =
|
| - a->SmiConstant(MessageTemplate::kSpeciesNotConstructor);
|
| - a->CallRuntime(Runtime::kThrowTypeError, context, message_id);
|
| - a->Goto(&out);
|
| + SmiConstant(MessageTemplate::kSpeciesNotConstructor);
|
| + CallRuntime(Runtime::kThrowTypeError, context, message_id);
|
| + Goto(&out);
|
| }
|
|
|
| - a->Bind(&out);
|
| + Bind(&out);
|
| return var_result.value();
|
| }
|
|
|
| -void AppendPromiseCallback(CodeStubAssembler* a, int offset,
|
| - compiler::Node* promise, compiler::Node* value) {
|
| - typedef compiler::Node Node;
|
| -
|
| - Node* elements = a->LoadObjectField(promise, offset);
|
| - Node* length = a->LoadFixedArrayBaseLength(elements);
|
| - CodeStubAssembler::ParameterMode mode = a->OptimalParameterMode();
|
| - length = a->TaggedToParameter(length, mode);
|
| +void PromiseBuiltinsAssembler::AppendPromiseCallback(int offset, Node* promise,
|
| + Node* value) {
|
| + Node* elements = LoadObjectField(promise, offset);
|
| + Node* length = LoadFixedArrayBaseLength(elements);
|
| + CodeStubAssembler::ParameterMode mode = OptimalParameterMode();
|
| + length = TaggedToParameter(length, mode);
|
|
|
| - Node* delta = a->IntPtrOrSmiConstant(1, mode);
|
| - Node* new_capacity = a->IntPtrOrSmiAdd(length, delta, mode);
|
| + Node* delta = IntPtrOrSmiConstant(1, mode);
|
| + Node* new_capacity = IntPtrOrSmiAdd(length, delta, mode);
|
|
|
| const ElementsKind kind = FAST_ELEMENTS;
|
| const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
|
| @@ -357,636 +154,779 @@ void AppendPromiseCallback(CodeStubAssembler* a, int offset,
|
| CodeStubAssembler::kAllowLargeObjectAllocation;
|
| int additional_offset = 0;
|
|
|
| - Node* new_elements = a->AllocateFixedArray(kind, new_capacity, mode, flags);
|
| + Node* new_elements = AllocateFixedArray(kind, new_capacity, mode, flags);
|
|
|
| - a->CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode,
|
| - mode);
|
| - a->StoreFixedArrayElement(new_elements, length, value, barrier_mode,
|
| - additional_offset, mode);
|
| + CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode,
|
| + mode);
|
| + StoreFixedArrayElement(new_elements, length, value, barrier_mode,
|
| + additional_offset, mode);
|
|
|
| - a->StoreObjectField(promise, offset, new_elements);
|
| + StoreObjectField(promise, offset, new_elements);
|
| }
|
|
|
| -compiler::Node* InternalPerformPromiseThen(CodeStubAssembler* a,
|
| - compiler::Node* context,
|
| - compiler::Node* promise,
|
| - compiler::Node* on_resolve,
|
| - compiler::Node* on_reject,
|
| - compiler::Node* deferred) {
|
| - typedef CodeStubAssembler::Variable Variable;
|
| - typedef CodeStubAssembler::Label Label;
|
| - typedef compiler::Node Node;
|
| - Isolate* isolate = a->isolate();
|
| - Node* const native_context = a->LoadNativeContext(context);
|
| -
|
| - Variable var_on_resolve(a, MachineRepresentation::kTagged),
|
| - var_on_reject(a, MachineRepresentation::kTagged);
|
| +Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context,
|
| + Node* promise,
|
| + Node* on_resolve,
|
| + Node* on_reject,
|
| + Node* deferred) {
|
| + Node* const native_context = LoadNativeContext(context);
|
| +
|
| + Variable var_on_resolve(this, MachineRepresentation::kTagged),
|
| + var_on_reject(this, MachineRepresentation::kTagged);
|
|
|
| var_on_resolve.Bind(on_resolve);
|
| var_on_reject.Bind(on_reject);
|
|
|
| - Label out(a), if_onresolvenotcallable(a), onrejectcheck(a),
|
| - append_callbacks(a);
|
| - a->GotoIf(a->TaggedIsSmi(on_resolve), &if_onresolvenotcallable);
|
| + Label out(this), if_onresolvenotcallable(this), onrejectcheck(this),
|
| + append_callbacks(this);
|
| + GotoIf(TaggedIsSmi(on_resolve), &if_onresolvenotcallable);
|
|
|
| - Node* const on_resolve_map = a->LoadMap(on_resolve);
|
| - a->Branch(a->IsCallableMap(on_resolve_map), &onrejectcheck,
|
| - &if_onresolvenotcallable);
|
| + Node* const on_resolve_map = LoadMap(on_resolve);
|
| + Branch(IsCallableMap(on_resolve_map), &onrejectcheck,
|
| + &if_onresolvenotcallable);
|
|
|
| - a->Bind(&if_onresolvenotcallable);
|
| + Bind(&if_onresolvenotcallable);
|
| {
|
| - var_on_resolve.Bind(a->LoadContextElement(
|
| + var_on_resolve.Bind(LoadContextElement(
|
| native_context, Context::PROMISE_ID_RESOLVE_HANDLER_INDEX));
|
| - a->Goto(&onrejectcheck);
|
| + Goto(&onrejectcheck);
|
| }
|
|
|
| - a->Bind(&onrejectcheck);
|
| + Bind(&onrejectcheck);
|
| {
|
| - Label if_onrejectnotcallable(a);
|
| - a->GotoIf(a->TaggedIsSmi(on_reject), &if_onrejectnotcallable);
|
| + Label if_onrejectnotcallable(this);
|
| + GotoIf(TaggedIsSmi(on_reject), &if_onrejectnotcallable);
|
|
|
| - Node* const on_reject_map = a->LoadMap(on_reject);
|
| - a->Branch(a->IsCallableMap(on_reject_map), &append_callbacks,
|
| - &if_onrejectnotcallable);
|
| + Node* const on_reject_map = LoadMap(on_reject);
|
| + Branch(IsCallableMap(on_reject_map), &append_callbacks,
|
| + &if_onrejectnotcallable);
|
|
|
| - a->Bind(&if_onrejectnotcallable);
|
| + Bind(&if_onrejectnotcallable);
|
| {
|
| - var_on_reject.Bind(a->LoadContextElement(
|
| + var_on_reject.Bind(LoadContextElement(
|
| native_context, Context::PROMISE_ID_REJECT_HANDLER_INDEX));
|
| - a->Goto(&append_callbacks);
|
| + Goto(&append_callbacks);
|
| }
|
| }
|
|
|
| - a->Bind(&append_callbacks);
|
| + Bind(&append_callbacks);
|
| {
|
| - Label fulfilled_check(a);
|
| - Node* const status = a->LoadObjectField(promise, JSPromise::kStatusOffset);
|
| - a->GotoUnless(a->SmiEqual(status, a->SmiConstant(kPromisePending)),
|
| - &fulfilled_check);
|
| + Label fulfilled_check(this);
|
| + Node* const status = LoadObjectField(promise, JSPromise::kStatusOffset);
|
| + GotoUnless(SmiEqual(status, SmiConstant(kPromisePending)),
|
| + &fulfilled_check);
|
|
|
| Node* const existing_deferred =
|
| - a->LoadObjectField(promise, JSPromise::kDeferredOffset);
|
| + LoadObjectField(promise, JSPromise::kDeferredOffset);
|
|
|
| - Label if_noexistingcallbacks(a), if_existingcallbacks(a);
|
| - a->Branch(a->IsUndefined(existing_deferred), &if_noexistingcallbacks,
|
| - &if_existingcallbacks);
|
| + Label if_noexistingcallbacks(this), if_existingcallbacks(this);
|
| + Branch(IsUndefined(existing_deferred), &if_noexistingcallbacks,
|
| + &if_existingcallbacks);
|
|
|
| - a->Bind(&if_noexistingcallbacks);
|
| + Bind(&if_noexistingcallbacks);
|
| {
|
| // Store callbacks directly in the slots.
|
| - a->StoreObjectField(promise, JSPromise::kDeferredOffset, deferred);
|
| - a->StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
|
| - var_on_resolve.value());
|
| - a->StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
|
| - var_on_reject.value());
|
| - a->Goto(&out);
|
| + StoreObjectField(promise, JSPromise::kDeferredOffset, deferred);
|
| + StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
|
| + var_on_resolve.value());
|
| + StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
|
| + var_on_reject.value());
|
| + Goto(&out);
|
| }
|
|
|
| - a->Bind(&if_existingcallbacks);
|
| + Bind(&if_existingcallbacks);
|
| {
|
| - Label if_singlecallback(a), if_multiplecallbacks(a);
|
| - a->BranchIfJSObject(existing_deferred, &if_singlecallback,
|
| - &if_multiplecallbacks);
|
| + Label if_singlecallback(this), if_multiplecallbacks(this);
|
| + BranchIfJSObject(existing_deferred, &if_singlecallback,
|
| + &if_multiplecallbacks);
|
|
|
| - a->Bind(&if_singlecallback);
|
| + Bind(&if_singlecallback);
|
| {
|
| // Create new FixedArrays to store callbacks, and migrate
|
| // existing callbacks.
|
| Node* const deferreds =
|
| - a->AllocateFixedArray(FAST_ELEMENTS, a->IntPtrConstant(2));
|
| - a->StoreFixedArrayElement(deferreds, 0, existing_deferred);
|
| - a->StoreFixedArrayElement(deferreds, 1, deferred);
|
| + AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
|
| + StoreFixedArrayElement(deferreds, 0, existing_deferred);
|
| + StoreFixedArrayElement(deferreds, 1, deferred);
|
|
|
| Node* const fulfill_reactions =
|
| - a->AllocateFixedArray(FAST_ELEMENTS, a->IntPtrConstant(2));
|
| - a->StoreFixedArrayElement(
|
| + AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
|
| + StoreFixedArrayElement(
|
| fulfill_reactions, 0,
|
| - a->LoadObjectField(promise, JSPromise::kFulfillReactionsOffset));
|
| - a->StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value());
|
| + LoadObjectField(promise, JSPromise::kFulfillReactionsOffset));
|
| + StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value());
|
|
|
| Node* const reject_reactions =
|
| - a->AllocateFixedArray(FAST_ELEMENTS, a->IntPtrConstant(2));
|
| - a->StoreFixedArrayElement(
|
| + AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
|
| + StoreFixedArrayElement(
|
| reject_reactions, 0,
|
| - a->LoadObjectField(promise, JSPromise::kRejectReactionsOffset));
|
| - a->StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value());
|
| + LoadObjectField(promise, JSPromise::kRejectReactionsOffset));
|
| + StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value());
|
|
|
| // Store new FixedArrays in promise.
|
| - a->StoreObjectField(promise, JSPromise::kDeferredOffset, deferreds);
|
| - a->StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
|
| - fulfill_reactions);
|
| - a->StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
|
| - reject_reactions);
|
| - a->Goto(&out);
|
| + StoreObjectField(promise, JSPromise::kDeferredOffset, deferreds);
|
| + StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
|
| + fulfill_reactions);
|
| + StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
|
| + reject_reactions);
|
| + Goto(&out);
|
| }
|
|
|
| - a->Bind(&if_multiplecallbacks);
|
| + Bind(&if_multiplecallbacks);
|
| {
|
| - AppendPromiseCallback(a, JSPromise::kDeferredOffset, promise, deferred);
|
| - AppendPromiseCallback(a, JSPromise::kFulfillReactionsOffset, promise,
|
| + AppendPromiseCallback(JSPromise::kDeferredOffset, promise, deferred);
|
| + AppendPromiseCallback(JSPromise::kFulfillReactionsOffset, promise,
|
| var_on_resolve.value());
|
| - AppendPromiseCallback(a, JSPromise::kRejectReactionsOffset, promise,
|
| + AppendPromiseCallback(JSPromise::kRejectReactionsOffset, promise,
|
| var_on_reject.value());
|
| - a->Goto(&out);
|
| + Goto(&out);
|
| }
|
| }
|
|
|
| - a->Bind(&fulfilled_check);
|
| + Bind(&fulfilled_check);
|
| {
|
| - Label reject(a);
|
| - Node* const result =
|
| - a->LoadObjectField(promise, JSPromise::kResultOffset);
|
| - a->GotoUnless(a->WordEqual(status, a->SmiConstant(kPromiseFulfilled)),
|
| - &reject);
|
| + Label reject(this);
|
| + Node* const result = LoadObjectField(promise, JSPromise::kResultOffset);
|
| + GotoUnless(WordEqual(status, SmiConstant(kPromiseFulfilled)), &reject);
|
|
|
| // TODO(gsathya): Move this to TF.
|
| - a->CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise,
|
| - result, var_on_resolve.value(), deferred,
|
| - a->SmiConstant(kPromiseFulfilled));
|
| - a->Goto(&out);
|
| + CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise, result,
|
| + var_on_resolve.value(), deferred,
|
| + SmiConstant(kPromiseFulfilled));
|
| + Goto(&out);
|
|
|
| - a->Bind(&reject);
|
| + Bind(&reject);
|
| {
|
| - Node* const has_handler = PromiseHasHandler(a, promise);
|
| - Label enqueue(a);
|
| + Node* const has_handler = PromiseHasHandler(promise);
|
| + Label enqueue(this);
|
|
|
| // TODO(gsathya): Fold these runtime calls and move to TF.
|
| - a->GotoIf(has_handler, &enqueue);
|
| - a->CallRuntime(Runtime::kPromiseRevokeReject, context, promise);
|
| - a->Goto(&enqueue);
|
| + GotoIf(has_handler, &enqueue);
|
| + CallRuntime(Runtime::kPromiseRevokeReject, context, promise);
|
| + Goto(&enqueue);
|
|
|
| - a->Bind(&enqueue);
|
| + Bind(&enqueue);
|
| {
|
| - a->CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise,
|
| - result, var_on_reject.value(), deferred,
|
| - a->SmiConstant(kPromiseRejected));
|
| + CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise,
|
| + result, var_on_reject.value(), deferred,
|
| + SmiConstant(kPromiseRejected));
|
|
|
| - a->Goto(&out);
|
| + Goto(&out);
|
| }
|
| }
|
| }
|
| }
|
|
|
| - a->Bind(&out);
|
| - PromiseSetHasHandler(a, promise);
|
| + Bind(&out);
|
| + PromiseSetHasHandler(promise);
|
|
|
| // TODO(gsathya): This call will be removed once we don't have to
|
| // deal with deferred objects.
|
| + Isolate* isolate = this->isolate();
|
| Callable getproperty_callable = CodeFactory::GetProperty(isolate);
|
| Node* const key =
|
| - a->HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise"));
|
| - Node* const result =
|
| - a->CallStub(getproperty_callable, context, deferred, key);
|
| + HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise"));
|
| + Node* const result = CallStub(getproperty_callable, context, deferred, key);
|
|
|
| return result;
|
| }
|
|
|
| -} // namespace
|
| -
|
| -void Builtins::Generate_PerformPromiseThen(
|
| - compiler::CodeAssemblerState* state) {
|
| - CodeStubAssembler a(state);
|
| - typedef compiler::Node Node;
|
| -
|
| - Node* const promise = a.Parameter(1);
|
| - Node* const on_resolve = a.Parameter(2);
|
| - Node* const on_reject = a.Parameter(3);
|
| - Node* const deferred = a.Parameter(4);
|
| - Node* const context = a.Parameter(7);
|
| -
|
| - Node* const result = InternalPerformPromiseThen(
|
| - &a, context, promise, on_resolve, on_reject, deferred);
|
| -
|
| - // TODO(gsathya): This is unused, but value is returned according to spec.
|
| - a.Return(result);
|
| -}
|
| -
|
| -void Builtins::Generate_PromiseThen(compiler::CodeAssemblerState* state) {
|
| - CodeStubAssembler a(state);
|
| - typedef compiler::Node Node;
|
| - typedef CodeStubAssembler::Label Label;
|
| - typedef CodeStubAssembler::Variable Variable;
|
| -
|
| - // 1. Let promise be the this value.
|
| - Node* const promise = a.Parameter(0);
|
| - Node* const on_resolve = a.Parameter(1);
|
| - Node* const on_reject = a.Parameter(2);
|
| - Node* const context = a.Parameter(5);
|
| - Isolate* isolate = a.isolate();
|
| -
|
| - // 2. If IsPromise(promise) is false, throw a TypeError exception.
|
| - a.ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
|
| - "Promise.prototype.then");
|
| -
|
| - Node* const native_context = a.LoadNativeContext(context);
|
| - Node* const promise_fun =
|
| - a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
|
| -
|
| - // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
|
| - Node* constructor =
|
| - SpeciesConstructor(&a, isolate, context, promise, promise_fun);
|
| -
|
| - // 4. Let resultCapability be ? NewPromiseCapability(C).
|
| - Callable call_callable = CodeFactory::Call(isolate);
|
| - Label fast_promise_capability(&a), promise_capability(&a),
|
| - perform_promise_then(&a);
|
| - Variable var_deferred(&a, MachineRepresentation::kTagged);
|
| -
|
| - a.Branch(a.WordEqual(promise_fun, constructor), &fast_promise_capability,
|
| - &promise_capability);
|
| -
|
| - // TODO(gsathya): Remove deferred object and move
|
| - // NewPromiseCapbability functions to TF.
|
| - a.Bind(&fast_promise_capability);
|
| - {
|
| - // TODO(gsathya): Move this to TF.
|
| - Node* const promise_internal_capability = a.LoadContextElement(
|
| - native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX);
|
| - Node* const capability =
|
| - a.CallJS(call_callable, context, promise_internal_capability,
|
| - a.UndefinedConstant());
|
| - var_deferred.Bind(capability);
|
| - a.Goto(&perform_promise_then);
|
| - }
|
| -
|
| - a.Bind(&promise_capability);
|
| - {
|
| - // TODO(gsathya): Move this to TF.
|
| - Node* const new_promise_capability = a.LoadContextElement(
|
| - native_context, Context::NEW_PROMISE_CAPABILITY_INDEX);
|
| - Node* const capability =
|
| - a.CallJS(call_callable, context, new_promise_capability,
|
| - a.UndefinedConstant(), constructor);
|
| - var_deferred.Bind(capability);
|
| - a.Goto(&perform_promise_then);
|
| - }
|
| -
|
| - // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
|
| - // resultCapability).
|
| - a.Bind(&perform_promise_then);
|
| - Node* const result = InternalPerformPromiseThen(
|
| - &a, context, promise, on_resolve, on_reject, var_deferred.value());
|
| - a.Return(result);
|
| -}
|
| -
|
| -namespace {
|
| -
|
| // Promise fast path implementations rely on unmodified JSPromise instances.
|
| // We use a fairly coarse granularity for this and simply check whether both
|
| // the promise itself is unmodified (i.e. its map has not changed) and its
|
| // prototype is unmodified.
|
| // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp
|
| -void BranchIfFastPath(CodeStubAssembler* a, compiler::Node* context,
|
| - compiler::Node* promise,
|
| - CodeStubAssembler::Label* if_isunmodified,
|
| - CodeStubAssembler::Label* if_ismodified) {
|
| - typedef compiler::Node Node;
|
| -
|
| +void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise,
|
| + Label* if_isunmodified,
|
| + Label* if_ismodified) {
|
| // TODO(gsathya): Assert if promise is receiver
|
| - Node* const map = a->LoadMap(promise);
|
| - Node* const native_context = a->LoadNativeContext(context);
|
| + Node* const map = LoadMap(promise);
|
| + Node* const native_context = LoadNativeContext(context);
|
| Node* const promise_fun =
|
| - a->LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
|
| + LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
|
| Node* const initial_map =
|
| - a->LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
|
| - Node* const has_initialmap = a->WordEqual(map, initial_map);
|
| + LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
|
| + Node* const has_initialmap = WordEqual(map, initial_map);
|
|
|
| - a->GotoUnless(has_initialmap, if_ismodified);
|
| + GotoUnless(has_initialmap, if_ismodified);
|
|
|
| - Node* const initial_proto_initial_map = a->LoadContextElement(
|
| - native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX);
|
| - Node* const proto_map = a->LoadMap(a->LoadMapPrototype(map));
|
| + Node* const initial_proto_initial_map =
|
| + LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX);
|
| + Node* const proto_map = LoadMap(LoadMapPrototype(map));
|
| Node* const proto_has_initialmap =
|
| - a->WordEqual(proto_map, initial_proto_initial_map);
|
| + WordEqual(proto_map, initial_proto_initial_map);
|
|
|
| - a->Branch(proto_has_initialmap, if_isunmodified, if_ismodified);
|
| + Branch(proto_has_initialmap, if_isunmodified, if_ismodified);
|
| }
|
|
|
| -void InternalResolvePromise(CodeStubAssembler* a, compiler::Node* context,
|
| - compiler::Node* promise, compiler::Node* result,
|
| - CodeStubAssembler::Label* out) {
|
| - typedef CodeStubAssembler::Variable Variable;
|
| - typedef CodeStubAssembler::Label Label;
|
| - typedef compiler::Node Node;
|
| -
|
| - Isolate* isolate = a->isolate();
|
| +void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context,
|
| + Node* promise,
|
| + Node* result,
|
| + Label* out) {
|
| + Isolate* isolate = this->isolate();
|
|
|
| - Variable var_reason(a, MachineRepresentation::kTagged),
|
| - var_then(a, MachineRepresentation::kTagged);
|
| + Variable var_reason(this, MachineRepresentation::kTagged),
|
| + var_then(this, MachineRepresentation::kTagged);
|
|
|
| - Label do_enqueue(a), fulfill(a), if_cycle(a, Label::kDeferred),
|
| - if_rejectpromise(a, Label::kDeferred);
|
| + Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred),
|
| + if_rejectpromise(this, Label::kDeferred);
|
|
|
| // 6. If SameValue(resolution, promise) is true, then
|
| - a->GotoIf(a->SameValue(promise, result, context), &if_cycle);
|
| + GotoIf(SameValue(promise, result, context), &if_cycle);
|
|
|
| // 7. If Type(resolution) is not Object, then
|
| - a->GotoIf(a->TaggedIsSmi(result), &fulfill);
|
| - a->GotoUnless(a->IsJSReceiver(result), &fulfill);
|
| + GotoIf(TaggedIsSmi(result), &fulfill);
|
| + GotoUnless(IsJSReceiver(result), &fulfill);
|
|
|
| - Label if_nativepromise(a), if_notnativepromise(a, Label::kDeferred);
|
| - BranchIfFastPath(a, context, result, &if_nativepromise, &if_notnativepromise);
|
| + Label if_nativepromise(this), if_notnativepromise(this, Label::kDeferred);
|
| + BranchIfFastPath(context, result, &if_nativepromise, &if_notnativepromise);
|
|
|
| // 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.
|
| - a->Bind(&if_nativepromise);
|
| + Bind(&if_nativepromise);
|
| {
|
| Node* const thenable_status =
|
| - a->LoadObjectField(result, JSPromise::kStatusOffset);
|
| + LoadObjectField(result, JSPromise::kStatusOffset);
|
| Node* const thenable_value =
|
| - a->LoadObjectField(result, JSPromise::kResultOffset);
|
| + LoadObjectField(result, JSPromise::kResultOffset);
|
|
|
| - Label if_isnotpending(a);
|
| - a->GotoUnless(a->SmiEqual(a->SmiConstant(kPromisePending), thenable_status),
|
| - &if_isnotpending);
|
| + Label if_isnotpending(this);
|
| + GotoUnless(SmiEqual(SmiConstant(kPromisePending), thenable_status),
|
| + &if_isnotpending);
|
|
|
| // TODO(gsathya): Use a marker here instead of the actual then
|
| // callback, and check for the marker in PromiseResolveThenableJob
|
| // and perform PromiseThen.
|
| - Node* const native_context = a->LoadNativeContext(context);
|
| + Node* const native_context = LoadNativeContext(context);
|
| Node* const then =
|
| - a->LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
|
| + LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
|
| var_then.Bind(then);
|
| - a->Goto(&do_enqueue);
|
| + Goto(&do_enqueue);
|
|
|
| - a->Bind(&if_isnotpending);
|
| + Bind(&if_isnotpending);
|
| {
|
| - Label if_fulfilled(a), if_rejected(a);
|
| - a->Branch(a->SmiEqual(a->SmiConstant(kPromiseFulfilled), thenable_status),
|
| - &if_fulfilled, &if_rejected);
|
| + Label if_fulfilled(this), if_rejected(this);
|
| + Branch(SmiEqual(SmiConstant(kPromiseFulfilled), thenable_status),
|
| + &if_fulfilled, &if_rejected);
|
|
|
| - a->Bind(&if_fulfilled);
|
| + Bind(&if_fulfilled);
|
| {
|
| - a->CallRuntime(Runtime::kPromiseFulfill, context, promise,
|
| - a->SmiConstant(kPromiseFulfilled), thenable_value);
|
| - PromiseSetHasHandler(a, promise);
|
| - a->Goto(out);
|
| + CallRuntime(Runtime::kPromiseFulfill, context, promise,
|
| + SmiConstant(kPromiseFulfilled), thenable_value);
|
| + PromiseSetHasHandler(promise);
|
| + Goto(out);
|
| }
|
|
|
| - a->Bind(&if_rejected);
|
| + Bind(&if_rejected);
|
| {
|
| - Label reject(a);
|
| - Node* const has_handler = PromiseHasHandler(a, result);
|
| + Label reject(this);
|
| + Node* const has_handler = PromiseHasHandler(result);
|
|
|
| // Promise has already been rejected, but had no handler.
|
| // Revoke previously triggered reject event.
|
| - a->GotoIf(has_handler, &reject);
|
| - a->CallRuntime(Runtime::kPromiseRevokeReject, context, result);
|
| - a->Goto(&reject);
|
| + GotoIf(has_handler, &reject);
|
| + CallRuntime(Runtime::kPromiseRevokeReject, context, result);
|
| + Goto(&reject);
|
|
|
| - a->Bind(&reject);
|
| + Bind(&reject);
|
| // Don't cause a debug event as this case is forwarding a rejection
|
| - a->CallRuntime(Runtime::kPromiseReject, context, promise,
|
| - thenable_value, a->FalseConstant());
|
| - PromiseSetHasHandler(a, result);
|
| - a->Goto(out);
|
| + CallRuntime(Runtime::kPromiseReject, context, promise, thenable_value,
|
| + FalseConstant());
|
| + PromiseSetHasHandler(result);
|
| + Goto(out);
|
| }
|
| }
|
| }
|
|
|
| - a->Bind(&if_notnativepromise);
|
| + Bind(&if_notnativepromise);
|
| {
|
| // 8. Let then be Get(resolution, "then").
|
| - Node* const then_str = a->HeapConstant(isolate->factory()->then_string());
|
| - Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
|
| + Node* const then_str = HeapConstant(isolate->factory()->then_string());
|
| + Callable getproperty_callable = CodeFactory::GetProperty(isolate);
|
| Node* const then =
|
| - a->CallStub(getproperty_callable, context, result, then_str);
|
| + CallStub(getproperty_callable, context, result, then_str);
|
|
|
| // 9. If then is an abrupt completion, then
|
| - a->GotoIfException(then, &if_rejectpromise, &var_reason);
|
| + GotoIfException(then, &if_rejectpromise, &var_reason);
|
|
|
| // 11. If IsCallable(thenAction) is false, then
|
| - a->GotoIf(a->TaggedIsSmi(then), &fulfill);
|
| - Node* const then_map = a->LoadMap(then);
|
| - a->GotoUnless(a->IsCallableMap(then_map), &fulfill);
|
| + GotoIf(TaggedIsSmi(then), &fulfill);
|
| + Node* const then_map = LoadMap(then);
|
| + GotoUnless(IsCallableMap(then_map), &fulfill);
|
| var_then.Bind(then);
|
| - a->Goto(&do_enqueue);
|
| + Goto(&do_enqueue);
|
| }
|
|
|
| - a->Bind(&do_enqueue);
|
| + Bind(&do_enqueue);
|
| {
|
| - Label enqueue(a);
|
| - a->GotoUnless(a->IsDebugActive(), &enqueue);
|
| - a->GotoIf(a->TaggedIsSmi(result), &enqueue);
|
| - a->GotoUnless(a->HasInstanceType(result, JS_PROMISE_TYPE), &enqueue);
|
| + Label enqueue(this);
|
| + GotoUnless(IsDebugActive(), &enqueue);
|
| + GotoIf(TaggedIsSmi(result), &enqueue);
|
| + GotoUnless(HasInstanceType(result, JS_PROMISE_TYPE), &enqueue);
|
| // Mark the dependency of the new promise on the resolution
|
| Node* const key =
|
| - a->HeapConstant(isolate->factory()->promise_handled_by_symbol());
|
| - a->CallRuntime(Runtime::kSetProperty, context, result, key, promise,
|
| - a->SmiConstant(STRICT));
|
| - a->Goto(&enqueue);
|
| + HeapConstant(isolate->factory()->promise_handled_by_symbol());
|
| + CallRuntime(Runtime::kSetProperty, context, result, key, promise,
|
| + SmiConstant(STRICT));
|
| + Goto(&enqueue);
|
|
|
| // 12. Perform EnqueueJob("PromiseJobs",
|
| // PromiseResolveThenableJob, « promise, resolution, thenAction
|
| // »).
|
| - a->Bind(&enqueue);
|
| - a->CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise,
|
| - result, var_then.value());
|
| - a->Goto(out);
|
| + Bind(&enqueue);
|
| + CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise,
|
| + result, var_then.value());
|
| + Goto(out);
|
| }
|
| +
|
| // 7.b Return FulfillPromise(promise, resolution).
|
| - a->Bind(&fulfill);
|
| + Bind(&fulfill);
|
| {
|
| - a->CallRuntime(Runtime::kPromiseFulfill, context, promise,
|
| - a->SmiConstant(kPromiseFulfilled), result);
|
| - a->Goto(out);
|
| + CallRuntime(Runtime::kPromiseFulfill, context, promise,
|
| + SmiConstant(kPromiseFulfilled), result);
|
| + Goto(out);
|
| }
|
|
|
| - a->Bind(&if_cycle);
|
| + Bind(&if_cycle);
|
| {
|
| // 6.a Let selfResolutionError be a newly created TypeError object.
|
| - Node* const message_id = a->SmiConstant(MessageTemplate::kPromiseCyclic);
|
| + Node* const message_id = SmiConstant(MessageTemplate::kPromiseCyclic);
|
| Node* const error =
|
| - a->CallRuntime(Runtime::kNewTypeError, context, message_id, result);
|
| + CallRuntime(Runtime::kNewTypeError, context, message_id, result);
|
| var_reason.Bind(error);
|
|
|
| // 6.b Return RejectPromise(promise, selfResolutionError).
|
| - a->Goto(&if_rejectpromise);
|
| + Goto(&if_rejectpromise);
|
| }
|
|
|
| // 9.a Return RejectPromise(promise, then.[[Value]]).
|
| - a->Bind(&if_rejectpromise);
|
| + Bind(&if_rejectpromise);
|
| {
|
| - a->CallRuntime(Runtime::kPromiseReject, context, promise,
|
| - var_reason.value(), a->TrueConstant());
|
| - a->Goto(out);
|
| + CallRuntime(Runtime::kPromiseReject, context, promise, var_reason.value(),
|
| + TrueConstant());
|
| + Goto(out);
|
| + }
|
| +}
|
| +
|
| +// ES#sec-promise-reject-functions
|
| +// Promise Reject Functions
|
| +BUILTIN(PromiseRejectClosure) {
|
| + HandleScope scope(isolate);
|
| +
|
| + Handle<Context> context(isolate->context(), isolate);
|
| +
|
| + if (PromiseUtils::HasAlreadyVisited(context)) {
|
| + return isolate->heap()->undefined_value();
|
| }
|
| +
|
| + PromiseUtils::SetAlreadyVisited(context);
|
| + Handle<Object> value = args.atOrUndefined(isolate, 1);
|
| + Handle<JSObject> promise = handle(PromiseUtils::GetPromise(context), isolate);
|
| + Handle<Object> debug_event =
|
| + handle(PromiseUtils::GetDebugEvent(context), isolate);
|
| + MaybeHandle<Object> maybe_result;
|
| + Handle<Object> argv[] = {promise, value, debug_event};
|
| + RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, Execution::Call(isolate, isolate->promise_internal_reject(),
|
| + isolate->factory()->undefined_value(),
|
| + arraysize(argv), argv));
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +// ES#sec-createresolvingfunctions
|
| +// CreateResolvingFunctions ( promise )
|
| +BUILTIN(CreateResolvingFunctions) {
|
| + HandleScope scope(isolate);
|
| + DCHECK_EQ(3, args.length());
|
| +
|
| + Handle<JSObject> promise = args.at<JSObject>(1);
|
| + Handle<Object> debug_event = args.at<Object>(2);
|
| + Handle<JSFunction> resolve, reject;
|
| +
|
| + PromiseUtils::CreateResolvingFunctions(isolate, promise, debug_event,
|
| + &resolve, &reject);
|
| +
|
| + Handle<FixedArray> result = isolate->factory()->NewFixedArray(2);
|
| + result->set(0, *resolve);
|
| + result->set(1, *reject);
|
| +
|
| + return *isolate->factory()->NewJSArrayWithElements(result, FAST_ELEMENTS, 2,
|
| + NOT_TENURED);
|
| }
|
|
|
| -} // namespace
|
| +TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
|
| + Node* const executor = Parameter(1);
|
| + Node* const new_target = Parameter(2);
|
| + Node* const context = Parameter(4);
|
| + Isolate* isolate = this->isolate();
|
| +
|
| + Label if_targetisundefined(this, Label::kDeferred);
|
| +
|
| + GotoIf(IsUndefined(new_target), &if_targetisundefined);
|
| +
|
| + Label if_notcallable(this, Label::kDeferred);
|
| +
|
| + GotoIf(TaggedIsSmi(executor), &if_notcallable);
|
| +
|
| + Node* const executor_map = LoadMap(executor);
|
| + GotoUnless(IsCallableMap(executor_map), &if_notcallable);
|
| +
|
| + Node* const native_context = LoadNativeContext(context);
|
| + Node* const promise_fun =
|
| + LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
|
| + Node* const is_debug_active = IsDebugActive();
|
| + Label if_targetisnotmodified(this),
|
| + if_targetismodified(this, Label::kDeferred), run_executor(this),
|
| + debug_push(this, Label::kDeferred), init(this);
|
| +
|
| + Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified,
|
| + &if_targetismodified);
|
| +
|
| + Variable var_result(this, MachineRepresentation::kTagged),
|
| + var_reject_call(this, MachineRepresentation::kTagged),
|
| + var_reason(this, MachineRepresentation::kTagged);
|
| +
|
| + Bind(&if_targetisnotmodified);
|
| + {
|
| + Node* const instance = AllocateJSPromise(context);
|
| + var_result.Bind(instance);
|
| + Goto(&init);
|
| + }
|
| +
|
| + Bind(&if_targetismodified);
|
| + {
|
| + Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate);
|
| + Node* const instance =
|
| + CallStub(fast_new_object_stub, context, promise_fun, new_target);
|
| +
|
| + var_result.Bind(instance);
|
| + Goto(&init);
|
| + }
|
| +
|
| + Bind(&init);
|
| + {
|
| + PromiseInit(var_result.value());
|
| + Branch(is_debug_active, &debug_push, &run_executor);
|
| + }
|
| +
|
| + Bind(&debug_push);
|
| + {
|
| + CallRuntime(Runtime::kDebugPushPromise, context, var_result.value());
|
| + Goto(&run_executor);
|
| + }
|
| +
|
| + Bind(&run_executor);
|
| + {
|
| + Label out(this), if_rejectpromise(this), debug_pop(this, Label::kDeferred);
|
| +
|
| + // TODO(gsathya): Move this to TF.
|
| + Node* const resolving_functions = CallRuntime(
|
| + Runtime::kCreateResolvingFunctions, context, var_result.value());
|
| + Node* const resolve =
|
| + LoadFixedArrayElement(resolving_functions, IntPtrConstant(0));
|
| + Node* const reject =
|
| + LoadFixedArrayElement(resolving_functions, IntPtrConstant(1));
|
| + Callable call_callable = CodeFactory::Call(isolate);
|
| +
|
| + Node* const maybe_exception = CallJS(call_callable, context, executor,
|
| + UndefinedConstant(), resolve, reject);
|
| +
|
| + GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
|
| + Branch(is_debug_active, &debug_pop, &out);
|
| +
|
| + Bind(&if_rejectpromise);
|
| + {
|
| + Callable call_callable = CodeFactory::Call(isolate);
|
| + CallJS(call_callable, context, reject, UndefinedConstant(),
|
| + var_reason.value());
|
| + Branch(is_debug_active, &debug_pop, &out);
|
| + }
|
| +
|
| + Bind(&debug_pop);
|
| + {
|
| + CallRuntime(Runtime::kDebugPopPromise, context);
|
| + Goto(&out);
|
| + }
|
| + Bind(&out);
|
| + Return(var_result.value());
|
| + }
|
| +
|
| + // 1. If NewTarget is undefined, throw a TypeError exception.
|
| + Bind(&if_targetisundefined);
|
| + {
|
| + Node* const message_id = SmiConstant(MessageTemplate::kNotAPromise);
|
| + CallRuntime(Runtime::kThrowTypeError, context, message_id, new_target);
|
| + Return(UndefinedConstant()); // Never reached.
|
| + }
|
| +
|
| + // 2. If IsCallable(executor) is false, throw a TypeError exception.
|
| + Bind(&if_notcallable);
|
| + {
|
| + Node* const message_id =
|
| + SmiConstant(MessageTemplate::kResolverNotAFunction);
|
| + CallRuntime(Runtime::kThrowTypeError, context, message_id, executor);
|
| + Return(UndefinedConstant()); // Never reached.
|
| + }
|
| +}
|
| +
|
| +TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) {
|
| + Node* const context = Parameter(3);
|
| + Node* const instance = AllocateJSPromise(context);
|
| + PromiseInit(instance);
|
| + Return(instance);
|
| +}
|
| +
|
| +TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) {
|
| + Node* const status = Parameter(1);
|
| + Node* const result = Parameter(2);
|
| + Node* const context = Parameter(5);
|
| +
|
| + Node* const instance = AllocateJSPromise(context);
|
| + PromiseSet(instance, status, result);
|
| + Return(instance);
|
| +}
|
| +
|
| +TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) {
|
| + Node* const maybe_promise = Parameter(1);
|
| + Label if_notpromise(this, Label::kDeferred);
|
| +
|
| + GotoIf(TaggedIsSmi(maybe_promise), &if_notpromise);
|
| +
|
| + Node* const result =
|
| + SelectBooleanConstant(HasInstanceType(maybe_promise, JS_PROMISE_TYPE));
|
| + Return(result);
|
| +
|
| + Bind(&if_notpromise);
|
| + Return(FalseConstant());
|
| +}
|
| +
|
| +TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) {
|
| + Node* const promise = Parameter(1);
|
| + Node* const on_resolve = Parameter(2);
|
| + Node* const on_reject = Parameter(3);
|
| + Node* const deferred = Parameter(4);
|
| + Node* const context = Parameter(7);
|
| +
|
| + Node* const result = InternalPerformPromiseThen(context, promise, on_resolve,
|
| + on_reject, deferred);
|
| +
|
| + // TODO(gsathya): This is unused, but value is returned according to spec.
|
| + Return(result);
|
| +}
|
| +
|
| +TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) {
|
| + // 1. Let promise be the this value.
|
| + Node* const promise = Parameter(0);
|
| + Node* const on_resolve = Parameter(1);
|
| + Node* const on_reject = Parameter(2);
|
| + Node* const context = Parameter(5);
|
| + Isolate* isolate = this->isolate();
|
| +
|
| + // 2. If IsPromise(promise) is false, throw a TypeError exception.
|
| + ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
|
| + "Promise.prototype.then");
|
| +
|
| + Node* const native_context = LoadNativeContext(context);
|
| + Node* const promise_fun =
|
| + LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
|
| +
|
| + // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
|
| + Node* constructor = SpeciesConstructor(context, promise, promise_fun);
|
| +
|
| + // 4. Let resultCapability be ? NewPromiseCapability(C).
|
| + Callable call_callable = CodeFactory::Call(isolate);
|
| + Label fast_promise_capability(this), promise_capability(this),
|
| + perform_promise_then(this);
|
| + Variable var_deferred(this, MachineRepresentation::kTagged);
|
| +
|
| + Branch(WordEqual(promise_fun, constructor), &fast_promise_capability,
|
| + &promise_capability);
|
| +
|
| + // TODO(gsathya): Remove deferred object and move
|
| + // NewPromiseCapabability functions to TF.
|
| + Bind(&fast_promise_capability);
|
| + {
|
| + // TODO(gsathya): Move this to TF.
|
| + Node* const promise_internal_capability = LoadContextElement(
|
| + native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX);
|
| + Node* const capability =
|
| + CallJS(call_callable, context, promise_internal_capability,
|
| + UndefinedConstant());
|
| + var_deferred.Bind(capability);
|
| + Goto(&perform_promise_then);
|
| + }
|
| +
|
| + Bind(&promise_capability);
|
| + {
|
| + // TODO(gsathya): Move this to TF.
|
| + Node* const new_promise_capability = LoadContextElement(
|
| + native_context, Context::NEW_PROMISE_CAPABILITY_INDEX);
|
| + Node* const capability =
|
| + CallJS(call_callable, context, new_promise_capability,
|
| + UndefinedConstant(), constructor);
|
| + var_deferred.Bind(capability);
|
| + Goto(&perform_promise_then);
|
| + }
|
| +
|
| + // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
|
| + // resultCapability).
|
| + Bind(&perform_promise_then);
|
| + Node* const result = InternalPerformPromiseThen(
|
| + context, promise, on_resolve, on_reject, var_deferred.value());
|
| + Return(result);
|
| +}
|
|
|
| // ES#sec-promise-resolve-functions
|
| // Promise Resolve Functions
|
| -void Builtins::Generate_PromiseResolveClosure(
|
| - compiler::CodeAssemblerState* state) {
|
| - CodeStubAssembler a(state);
|
| - typedef compiler::Node Node;
|
| - typedef CodeStubAssembler::Label Label;
|
| +TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) {
|
| + Node* const value = Parameter(1);
|
| + Node* const context = Parameter(4);
|
|
|
| - Node* const value = a.Parameter(1);
|
| - Node* const context = a.Parameter(4);
|
| -
|
| - Label out(&a);
|
| + Label out(this);
|
|
|
| // 3. Let alreadyResolved be F.[[AlreadyResolved]].
|
| Node* const has_already_visited_slot =
|
| - a.IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot);
|
| + IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot);
|
|
|
| Node* const has_already_visited =
|
| - a.LoadFixedArrayElement(context, has_already_visited_slot);
|
| + LoadFixedArrayElement(context, has_already_visited_slot);
|
|
|
| // 4. If alreadyResolved.[[Value]] is true, return undefined.
|
| - a.GotoIf(a.SmiEqual(has_already_visited, a.SmiConstant(1)), &out);
|
| + GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out);
|
|
|
| // 5.Set alreadyResolved.[[Value]] to true.
|
| - a.StoreFixedArrayElement(context, has_already_visited_slot, a.SmiConstant(1));
|
| + StoreFixedArrayElement(context, has_already_visited_slot, SmiConstant(1));
|
|
|
| // 2. Let promise be F.[[Promise]].
|
| - Node* const promise = a.LoadFixedArrayElement(
|
| - context, a.IntPtrConstant(PromiseUtils::kPromiseSlot));
|
| + Node* const promise = LoadFixedArrayElement(
|
| + context, IntPtrConstant(PromiseUtils::kPromiseSlot));
|
|
|
| - InternalResolvePromise(&a, context, promise, value, &out);
|
| + InternalResolvePromise(context, promise, value, &out);
|
|
|
| - a.Bind(&out);
|
| - a.Return(a.UndefinedConstant());
|
| + Bind(&out);
|
| + Return(UndefinedConstant());
|
| }
|
|
|
| -void Builtins::Generate_ResolvePromise(compiler::CodeAssemblerState* state) {
|
| - CodeStubAssembler a(state);
|
| - typedef compiler::Node Node;
|
| - typedef CodeStubAssembler::Label Label;
|
| -
|
| - Node* const promise = a.Parameter(1);
|
| - Node* const result = a.Parameter(2);
|
| - Node* const context = a.Parameter(5);
|
| +TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) {
|
| + Node* const promise = Parameter(1);
|
| + Node* const result = Parameter(2);
|
| + Node* const context = Parameter(5);
|
|
|
| - Label out(&a);
|
| - InternalResolvePromise(&a, context, promise, result, &out);
|
| + Label out(this);
|
| + InternalResolvePromise(context, promise, result, &out);
|
|
|
| - a.Bind(&out);
|
| - a.Return(a.UndefinedConstant());
|
| + Bind(&out);
|
| + Return(UndefinedConstant());
|
| }
|
|
|
| -void Builtins::Generate_PromiseHandleReject(
|
| - compiler::CodeAssemblerState* state) {
|
| - CodeStubAssembler a(state);
|
| - typedef compiler::Node Node;
|
| - typedef CodeStubAssembler::Label Label;
|
| - typedef CodeStubAssembler::Variable Variable;
|
| +TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) {
|
| typedef PromiseHandleRejectDescriptor Descriptor;
|
|
|
| - Node* const promise = a.Parameter(Descriptor::kPromise);
|
| - Node* const on_reject = a.Parameter(Descriptor::kOnReject);
|
| - Node* const exception = a.Parameter(Descriptor::kException);
|
| - Node* const context = a.Parameter(Descriptor::kContext);
|
| - Isolate* isolate = a.isolate();
|
| + Node* const promise = Parameter(Descriptor::kPromise);
|
| + Node* const on_reject = Parameter(Descriptor::kOnReject);
|
| + Node* const exception = Parameter(Descriptor::kException);
|
| + Node* const context = Parameter(Descriptor::kContext);
|
|
|
| - Callable call_callable = CodeFactory::Call(isolate);
|
| - Variable var_unused(&a, MachineRepresentation::kTagged);
|
| + Callable call_callable = CodeFactory::Call(isolate());
|
| + Variable var_unused(this, MachineRepresentation::kTagged);
|
|
|
| - Label if_internalhandler(&a), if_customhandler(&a, Label::kDeferred);
|
| - a.Branch(a.IsUndefined(on_reject), &if_internalhandler, &if_customhandler);
|
| + Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
|
| + Branch(IsUndefined(on_reject), &if_internalhandler, &if_customhandler);
|
|
|
| - a.Bind(&if_internalhandler);
|
| + Bind(&if_internalhandler);
|
| {
|
| - a.CallRuntime(Runtime::kPromiseReject, context, promise, exception,
|
| - a.FalseConstant());
|
| - a.Return(a.UndefinedConstant());
|
| + CallRuntime(Runtime::kPromiseReject, context, promise, exception,
|
| + FalseConstant());
|
| + Return(UndefinedConstant());
|
| }
|
|
|
| - a.Bind(&if_customhandler);
|
| + Bind(&if_customhandler);
|
| {
|
| - a.CallJS(call_callable, context, on_reject, a.UndefinedConstant(),
|
| - exception);
|
| - a.Return(a.UndefinedConstant());
|
| + CallJS(call_callable, context, on_reject, UndefinedConstant(), exception);
|
| + Return(UndefinedConstant());
|
| }
|
| }
|
|
|
| -void Builtins::Generate_PromiseHandle(compiler::CodeAssemblerState* state) {
|
| - CodeStubAssembler a(state);
|
| - typedef compiler::Node Node;
|
| - typedef CodeStubAssembler::Label Label;
|
| - typedef CodeStubAssembler::Variable Variable;
|
| -
|
| - Node* const value = a.Parameter(2);
|
| - Node* const handler = a.Parameter(3);
|
| - Node* const deferred = a.Parameter(4);
|
| - Node* const context = a.Parameter(7);
|
| - Isolate* isolate = a.isolate();
|
| +TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
|
| + Node* const value = Parameter(2);
|
| + Node* const handler = Parameter(3);
|
| + Node* const deferred = Parameter(4);
|
| + Node* const context = Parameter(7);
|
| + Isolate* isolate = this->isolate();
|
|
|
| // Get promise from deferred
|
| // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
|
| Callable getproperty_callable = CodeFactory::GetProperty(isolate);
|
| - Node* const key = a.HeapConstant(isolate->factory()->promise_string());
|
| + Node* const key = HeapConstant(isolate->factory()->promise_string());
|
| Node* const deferred_promise =
|
| - a.CallStub(getproperty_callable, context, deferred, key);
|
| + CallStub(getproperty_callable, context, deferred, key);
|
|
|
| - Variable var_reason(&a, MachineRepresentation::kTagged);
|
| + Variable var_reason(this, MachineRepresentation::kTagged);
|
|
|
| - Node* const is_debug_active = a.IsDebugActive();
|
| - Label run_handler(&a), if_rejectpromise(&a), debug_push(&a, Label::kDeferred),
|
| - debug_pop(&a, Label::kDeferred);
|
| - a.Branch(is_debug_active, &debug_push, &run_handler);
|
| + Node* const is_debug_active = IsDebugActive();
|
| + Label run_handler(this), if_rejectpromise(this),
|
| + debug_push(this, Label::kDeferred), debug_pop(this, Label::kDeferred);
|
| + Branch(is_debug_active, &debug_push, &run_handler);
|
|
|
| - a.Bind(&debug_push);
|
| + Bind(&debug_push);
|
| {
|
| - a.CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise);
|
| - a.Goto(&run_handler);
|
| + CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise);
|
| + Goto(&run_handler);
|
| }
|
|
|
| - a.Bind(&run_handler);
|
| + Bind(&run_handler);
|
| {
|
| Callable call_callable = CodeFactory::Call(isolate);
|
|
|
| Node* const result =
|
| - a.CallJS(call_callable, context, handler, a.UndefinedConstant(), value);
|
| + CallJS(call_callable, context, handler, UndefinedConstant(), value);
|
|
|
| - a.GotoIfException(result, &if_rejectpromise, &var_reason);
|
| + GotoIfException(result, &if_rejectpromise, &var_reason);
|
|
|
| // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
|
| - Node* const key = a.HeapConstant(isolate->factory()->resolve_string());
|
| + Node* const key = HeapConstant(isolate->factory()->resolve_string());
|
| Node* const on_resolve =
|
| - a.CallStub(getproperty_callable, context, deferred, key);
|
| + CallStub(getproperty_callable, context, deferred, key);
|
|
|
| - Label if_internalhandler(&a), if_customhandler(&a, Label::kDeferred);
|
| - a.Branch(a.IsUndefined(on_resolve), &if_internalhandler, &if_customhandler);
|
| + Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
|
| + Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler);
|
|
|
| - a.Bind(&if_internalhandler);
|
| - InternalResolvePromise(&a, context, deferred_promise, result, &debug_pop);
|
| + Bind(&if_internalhandler);
|
| + InternalResolvePromise(context, deferred_promise, result, &debug_pop);
|
|
|
| - a.Bind(&if_customhandler);
|
| + Bind(&if_customhandler);
|
| {
|
| - Node* const maybe_exception = a.CallJS(call_callable, context, on_resolve,
|
| - a.UndefinedConstant(), result);
|
| - a.GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
|
| - a.Goto(&debug_pop);
|
| + Node* const maybe_exception = CallJS(call_callable, context, on_resolve,
|
| + UndefinedConstant(), result);
|
| + GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
|
| + Goto(&debug_pop);
|
| }
|
| }
|
|
|
| - a.Bind(&if_rejectpromise);
|
| + Bind(&if_rejectpromise);
|
| {
|
| // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
|
| - Node* const key = a.HeapConstant(isolate->factory()->reject_string());
|
| + Node* const key = HeapConstant(isolate->factory()->reject_string());
|
| Node* const on_reject =
|
| - a.CallStub(getproperty_callable, context, deferred, key);
|
| + CallStub(getproperty_callable, context, deferred, key);
|
|
|
| Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate);
|
| - a.CallStub(promise_handle_reject, context, deferred_promise, on_reject,
|
| - var_reason.value());
|
| - a.Goto(&debug_pop);
|
| + CallStub(promise_handle_reject, context, deferred_promise, on_reject,
|
| + var_reason.value());
|
| + Goto(&debug_pop);
|
| }
|
|
|
| - a.Bind(&debug_pop);
|
| + Bind(&debug_pop);
|
| {
|
| - Label out(&a);
|
| + Label out(this);
|
|
|
| - a.GotoUnless(is_debug_active, &out);
|
| - a.CallRuntime(Runtime::kDebugPopPromise, context);
|
| - a.Goto(&out);
|
| + GotoUnless(is_debug_active, &out);
|
| + CallRuntime(Runtime::kDebugPopPromise, context);
|
| + Goto(&out);
|
|
|
| - a.Bind(&out);
|
| - a.Return(a.UndefinedConstant());
|
| + Bind(&out);
|
| + Return(UndefinedConstant());
|
| }
|
| }
|
|
|
|
|