Chromium Code Reviews| Index: src/builtins/builtins-promise.cc |
| diff --git a/src/builtins/builtins-promise.cc b/src/builtins/builtins-promise.cc |
| index e6034e7b6bf70299450ad972a518583b8f2b2557..dcc41f0515661959bee9b99b46cb6aa61f8b1e5e 100644 |
| --- a/src/builtins/builtins-promise.cc |
| +++ b/src/builtins/builtins-promise.cc |
| @@ -51,6 +51,13 @@ Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context, |
| return instance; |
| } |
| +Node* PromiseBuiltinsAssembler::AllocateAndInitInternalJSPromise( |
| + Node* context) { |
|
caitp
2017/01/10 04:19:33
This seemed more useful earlier today, but after d
gsathya
2017/01/10 17:47:24
The Async-from-Sync iterator methods seems to use
caitp
2017/01/10 17:48:54
sgtm
|
| + Node* const instance = AllocateJSPromise(context); |
| + PromiseInit(instance); |
| + return instance; |
| +} |
| + |
| Node* PromiseBuiltinsAssembler::AllocateAndSetJSPromise(Node* context, |
| Node* status, |
| Node* result) { |
| @@ -605,6 +612,75 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen( |
| return deferred_promise; |
| } |
| +void PromiseBuiltinsAssembler::FastPerformPromiseThen(Node* context, |
| + Node* promise, |
| + Node* on_resolve, |
| + Node* on_reject, |
| + Node* result_promise) { |
| + CSA_SLOW_ASSERT(this, HasInstanceType(promise, JS_PROMISE_TYPE)); |
|
caitp
2017/01/10 04:13:41
Basically just a slightly smaller version of Inter
|
| + if (result_promise != nullptr) { |
| + CSA_SLOW_ASSERT(this, HasInstanceType(result_promise, JS_PROMISE_TYPE)); |
| + } |
| + |
| + if (on_resolve == nullptr) { |
| + on_resolve = LoadContextElement(LoadNativeContext(context), |
| + Context::PROMISE_ID_RESOLVE_HANDLER_INDEX); |
| + } else if (on_reject == nullptr) { |
| + on_reject = LoadContextElement(LoadNativeContext(context), |
| + Context::PROMISE_ID_REJECT_HANDLER_INDEX); |
| + } |
| + CSA_SLOW_ASSERT(this, IsJSFunction(on_resolve)); |
| + CSA_SLOW_ASSERT(this, IsJSFunction(on_reject)); |
| + |
| + Label if_ispending(this), if_isfulfilled(this), merge(this); |
| + |
| + Node* const status = LoadObjectField(promise, JSPromise::kStatusOffset); |
| + Branch(SmiEqual(status, SmiConstant(v8::Promise::kPending)), &if_ispending, |
| + &if_isfulfilled); |
| + |
| + Bind(&if_ispending); |
| + { |
| + // Assert: There are no callbacks attached. |
| + CSA_SLOW_ASSERT(this, IsUndefined(LoadObjectField( |
| + promise, JSPromise::kDeferredPromiseOffset))); |
| + |
| + // Store callbacks directly in the slots. |
| + StoreObjectField(promise, JSPromise::kDeferredPromiseOffset, |
| + result_promise ? result_promise : UndefinedConstant()); |
| + StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, on_resolve); |
| + StoreObjectField(promise, JSPromise::kRejectReactionsOffset, on_reject); |
| + Goto(&merge); |
| + } |
| + |
| + Bind(&if_isfulfilled); |
| + { |
| + Node* const handler = |
| + Select(SmiEqual(status, SmiConstant(v8::Promise::kFulfilled)), |
| + [&]() -> Node* { return on_resolve; }, |
| + [&]() -> Node* { |
| + Label done(this); |
| + GotoIf(PromiseHasHandler(promise), &done); |
| + // TODO(gsathya): Fold these runtime calls and move to TF. |
| + CallRuntime(Runtime::kPromiseRevokeReject, context, promise); |
| + Goto(&done); |
| + Bind(&done); |
| + return on_reject; |
| + }, |
| + MachineRepresentation::kTagged); |
| + |
| + Node* const result = LoadObjectField(promise, JSPromise::kResultOffset); |
| + Node* info = AllocatePromiseReactionJobInfo( |
| + promise, result, handler, |
| + result_promise ? result_promise : UndefinedConstant(), |
| + UndefinedConstant(), UndefinedConstant(), context); |
| + // TODO(gsathya): Move this to TF |
| + CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info, status); |
| + Goto(&merge); |
| + } |
| + |
| + Bind(&merge); |
| +} |
| + |
| // 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 |
| @@ -1068,7 +1144,7 @@ TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) { |
| Node* const context = Parameter(7); |
| // No deferred_on_resolve/deferred_on_reject because this is just an |
| - // internal promise created by async-await. |
| + // internal promise created by async-await / async-iteration. |
| Node* const result = InternalPerformPromiseThen( |
| context, promise, on_resolve, on_reject, deferred_promise, |
| UndefinedConstant(), UndefinedConstant()); |