| Index: src/builtins/builtins-promise.cc | 
| diff --git a/src/builtins/builtins-promise.cc b/src/builtins/builtins-promise.cc | 
| index 9f5d7c88d7885e8bfbcefe65fdc80c729301b305..c12d1ebc9e221c9330f7613294e17c1fa3be960f 100644 | 
| --- a/src/builtins/builtins-promise.cc | 
| +++ b/src/builtins/builtins-promise.cc | 
| @@ -5,6 +5,7 @@ | 
| #include "src/builtins/builtins-utils.h" | 
| #include "src/builtins/builtins.h" | 
|  | 
| +#include "src/code-factory.h" | 
| #include "src/promise-utils.h" | 
|  | 
| namespace v8 { | 
| @@ -80,5 +81,163 @@ BUILTIN(CreateResolvingFunctions) { | 
| 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); | 
| +  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 initial_map = a.LoadObjectField( | 
| +        promise_fun, JSFunction::kPrototypeOrInitialMapOffset); | 
| + | 
| +    Node* const instance = a.AllocateJSObjectFromMap(initial_map); | 
| +    var_result.Bind(instance); | 
| +    a.Branch(is_debug_active, &debug_push, &run_executor); | 
| +  } | 
| + | 
| +  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.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); | 
| + | 
| +    Node* const key = a.LoadRoot(Heap::kpromise_state_symbolRootIndex); | 
| +    Node* const value = a.SmiConstant(kPromisePending); | 
| +    Node* const language_mode = a.SmiConstant(STRICT); | 
| +    // TODO(ishell): Use SetProperty stub once available. | 
| +    a.CallRuntime(Runtime::kSetProperty, context, var_result.value(), key, | 
| +                  value, language_mode); | 
| +    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); | 
| + | 
| +    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); | 
| +    } | 
| + | 
| +    a.Bind(&debug_pop); | 
| +    { | 
| +      a.CallRuntime(Runtime::kDebugPopPromise, context); | 
| +      a.Goto(&out); | 
| +    } | 
| +    a.Bind(&out); | 
| +    a.Return(var_result.value()); | 
| +  } | 
| + | 
| +  // 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. | 
| +  } | 
| + | 
| +  // 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. | 
| +  } | 
| +} | 
| + | 
| +void Builtins::Generate_PromiseInternalConstructor( | 
| +    compiler::CodeAssemblerState* state) { | 
| +  typedef compiler::Node Node; | 
| +  CodeStubAssembler a(state); | 
| + | 
| +  Node* const context = a.Parameter(3); | 
| +  Node* const native_context = a.LoadNativeContext(context); | 
| +  Node* const promise_fun = | 
| +      a.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | 
| +  Node* const initial_map = | 
| +      a.LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset); | 
| +  Node* const instance = a.AllocateJSObjectFromMap(initial_map); | 
| +  a.Return(instance); | 
| +} | 
| + | 
| +// TODO(gsathya): Refactor promise.js::IsPromise to use this. | 
| +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_ispromise(&a), if_isnotpromise(&a, Label::kDeferred); | 
| +  a.GotoIf(a.TaggedIsSmi(maybe_promise), &if_isnotpromise); | 
| + | 
| +  a.Branch(a.HasInstanceType(maybe_promise, JS_PROMISE_TYPE), &if_ispromise, | 
| +           &if_isnotpromise); | 
| + | 
| +  a.Bind(&if_ispromise); | 
| +  a.Return(a.BooleanConstant(true)); | 
| + | 
| +  a.Bind(&if_isnotpromise); | 
| +  a.Return(a.BooleanConstant(false)); | 
| +} | 
| + | 
| }  // namespace internal | 
| }  // namespace v8 | 
|  |