| 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());
 | 
|    }
 | 
|  }
 | 
|  
 | 
| 
 |