Index: src/builtins/builtins-promise.cc |
diff --git a/src/builtins/builtins-promise.cc b/src/builtins/builtins-promise.cc |
index baa6253aecdd2f3d62f2ab69599a813cb06b8fda..fea937b75d2209e04785c6c7bcbd52195495ed1b 100644 |
--- a/src/builtins/builtins-promise.cc |
+++ b/src/builtins/builtins-promise.cc |
@@ -16,6 +16,20 @@ typedef compiler::Node Node; |
typedef CodeStubAssembler::ParameterMode ParameterMode; |
typedef compiler::CodeAssemblerState CodeAssemblerState; |
+Node* PromiseBuiltinsAssembler::AllocateAndInitPromise(Node* context, |
+ Node* parent) { |
+ Node* const instance = AllocateJSPromise(context); |
+ PromiseInit(instance); |
+ |
+ Label out(this); |
+ GotoUnless(IsPromiseHookEnabled(), &out); |
+ CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); |
+ Goto(&out); |
+ |
+ Bind(&out); |
+ return instance; |
+} |
+ |
Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext( |
Node* promise, Node* debug_event, Node* native_context) { |
Node* const context = |
@@ -181,11 +195,10 @@ void PromiseBuiltinsAssembler::AppendPromiseCallback(int offset, Node* promise, |
StoreObjectField(promise, offset, new_elements); |
} |
-Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |
- Node* promise, |
- Node* on_resolve, |
- Node* on_reject, |
- Node* deferred) { |
+Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen( |
+ Node* context, Node* promise, Node* on_resolve, Node* on_reject, |
+ Node* deferred_promise, Node* deferred_on_resolve, |
+ Node* deferred_on_reject) { |
Node* const native_context = LoadNativeContext(context); |
Variable var_on_resolve(this, MachineRepresentation::kTagged), |
@@ -233,17 +246,22 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |
GotoUnless(SmiEqual(status, SmiConstant(kPromisePending)), |
&fulfilled_check); |
- Node* const existing_deferred = |
- LoadObjectField(promise, JSPromise::kDeferredOffset); |
+ Node* const existing_deferred_promise = |
+ LoadObjectField(promise, JSPromise::kDeferredPromiseOffset); |
Label if_noexistingcallbacks(this), if_existingcallbacks(this); |
- Branch(IsUndefined(existing_deferred), &if_noexistingcallbacks, |
+ Branch(IsUndefined(existing_deferred_promise), &if_noexistingcallbacks, |
&if_existingcallbacks); |
Bind(&if_noexistingcallbacks); |
{ |
// Store callbacks directly in the slots. |
- StoreObjectField(promise, JSPromise::kDeferredOffset, deferred); |
+ StoreObjectField(promise, JSPromise::kDeferredPromiseOffset, |
+ deferred_promise); |
+ StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset, |
+ deferred_on_resolve); |
+ StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset, |
+ deferred_on_reject); |
StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, |
var_on_resolve.value()); |
StoreObjectField(promise, JSPromise::kRejectReactionsOffset, |
@@ -254,17 +272,31 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |
Bind(&if_existingcallbacks); |
{ |
Label if_singlecallback(this), if_multiplecallbacks(this); |
- BranchIfJSObject(existing_deferred, &if_singlecallback, |
+ BranchIfJSObject(existing_deferred_promise, &if_singlecallback, |
&if_multiplecallbacks); |
Bind(&if_singlecallback); |
{ |
// Create new FixedArrays to store callbacks, and migrate |
// existing callbacks. |
- Node* const deferreds = |
+ Node* const deferred_promises = |
+ AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |
+ StoreFixedArrayElement(deferred_promises, 0, existing_deferred_promise); |
+ StoreFixedArrayElement(deferred_promises, 1, deferred_promise); |
+ |
+ Node* const deferred_on_resolves = |
+ AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |
+ StoreFixedArrayElement( |
+ deferred_on_resolves, 0, |
+ LoadObjectField(promise, JSPromise::kDeferredOnResolveOffset)); |
+ StoreFixedArrayElement(deferred_on_resolve, 1, deferred_on_resolve); |
+ |
+ Node* const deferred_on_rejects = |
AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |
- StoreFixedArrayElement(deferreds, 0, existing_deferred); |
- StoreFixedArrayElement(deferreds, 1, deferred); |
+ StoreFixedArrayElement( |
+ deferred_on_rejects, 0, |
+ LoadObjectField(promise, JSPromise::kDeferredOnRejectOffset)); |
+ StoreFixedArrayElement(deferred_on_rejects, 1, deferred_on_reject); |
Node* const fulfill_reactions = |
AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |
@@ -281,7 +313,12 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |
StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value()); |
// Store new FixedArrays in promise. |
- StoreObjectField(promise, JSPromise::kDeferredOffset, deferreds); |
+ StoreObjectField(promise, JSPromise::kDeferredPromiseOffset, |
caitp
2016/12/20 02:53:01
The multiple chains case seems likely to regress w
|
+ deferred_promises); |
+ StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset, |
+ deferred_on_resolves); |
+ StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset, |
+ deferred_on_rejects); |
StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, |
fulfill_reactions); |
StoreObjectField(promise, JSPromise::kRejectReactionsOffset, |
@@ -291,7 +328,12 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |
Bind(&if_multiplecallbacks); |
{ |
- AppendPromiseCallback(JSPromise::kDeferredOffset, promise, deferred); |
+ AppendPromiseCallback(JSPromise::kDeferredPromiseOffset, promise, |
+ deferred_promise); |
+ AppendPromiseCallback(JSPromise::kDeferredOnResolveOffset, promise, |
+ deferred_on_resolve); |
+ AppendPromiseCallback(JSPromise::kDeferredOnRejectOffset, promise, |
+ deferred_on_reject); |
AppendPromiseCallback(JSPromise::kFulfillReactionsOffset, promise, |
var_on_resolve.value()); |
AppendPromiseCallback(JSPromise::kRejectReactionsOffset, promise, |
@@ -306,9 +348,10 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |
Node* const result = LoadObjectField(promise, JSPromise::kResultOffset); |
GotoUnless(WordEqual(status, SmiConstant(kPromiseFulfilled)), &reject); |
- // TODO(gsathya): Move this to TF. |
- CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise, result, |
- var_on_resolve.value(), deferred, |
+ Node* info = AllocatePromiseReactionJobInfo( |
+ promise, result, var_on_resolve.value(), deferred_promise, |
+ deferred_on_resolve, deferred_on_reject, context); |
+ CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info, |
SmiConstant(kPromiseFulfilled)); |
Goto(&out); |
@@ -324,8 +367,10 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |
Bind(&enqueue); |
{ |
- CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise, |
- result, var_on_reject.value(), deferred, |
+ Node* info = AllocatePromiseReactionJobInfo( |
+ promise, result, var_on_reject.value(), deferred_promise, |
+ deferred_on_resolve, deferred_on_reject, context); |
+ CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info, |
SmiConstant(kPromiseRejected)); |
Goto(&out); |
@@ -336,16 +381,7 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |
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 = |
- HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise")); |
- Node* const result = CallStub(getproperty_callable, context, deferred, key); |
- |
- return result; |
+ return deferred_promise; |
} |
// Promise fast path implementations rely on unmodified JSPromise instances. |
@@ -705,16 +741,7 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { |
TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { |
Node* const parent = Parameter(1); |
Node* const context = Parameter(4); |
- Node* const instance = AllocateJSPromise(context); |
- PromiseInit(instance); |
- |
- Label out(this); |
- GotoUnless(IsPromiseHookEnabled(), &out); |
- CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); |
- Goto(&out); |
- Bind(&out); |
- |
- Return(instance); |
+ Return(AllocateAndInitPromise(context, parent)); |
} |
TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) { |
@@ -752,11 +779,14 @@ 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 deferred_promise = Parameter(4); |
Node* const context = Parameter(7); |
- Node* const result = InternalPerformPromiseThen(context, promise, on_resolve, |
- on_reject, deferred); |
+ // No deferred_on_resolve/deferred_on_reject because this is just an |
+ // internal promise created by async-await. |
+ Node* const result = InternalPerformPromiseThen( |
+ context, promise, on_resolve, on_reject, deferred_promise, |
+ UndefinedConstant(), UndefinedConstant()); |
// TODO(gsathya): This is unused, but value is returned according to spec. |
Return(result); |
@@ -785,22 +815,20 @@ TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { |
Callable call_callable = CodeFactory::Call(isolate); |
Label fast_promise_capability(this), promise_capability(this), |
perform_promise_then(this); |
- Variable var_deferred(this, MachineRepresentation::kTagged); |
+ Variable var_deferred_promise(this, MachineRepresentation::kTagged), |
+ var_deferred_on_resolve(this, MachineRepresentation::kTagged), |
+ var_deferred_on_reject(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(), promise); |
- var_deferred.Bind(capability); |
+ Node* const deferred_promise = AllocateAndInitPromise(context, promise); |
+ PromiseInit(deferred_promise); |
+ var_deferred_promise.Bind(deferred_promise); |
+ var_deferred_on_resolve.Bind(UndefinedConstant()); |
+ var_deferred_on_reject.Bind(UndefinedConstant()); |
Goto(&perform_promise_then); |
} |
@@ -809,10 +837,25 @@ TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { |
// TODO(gsathya): Move this to TF. |
Node* const new_promise_capability = LoadContextElement( |
native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); |
- Node* const capability = |
+ Node* const deferred = |
CallJS(call_callable, context, new_promise_capability, |
UndefinedConstant(), constructor); |
- var_deferred.Bind(capability); |
+ Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
+ Node* key = HeapConstant(isolate->factory()->promise_string()); |
+ Node* const deferred_promise = |
+ CallStub(getproperty_callable, context, deferred, key); |
+ var_deferred_promise.Bind(deferred_promise); |
+ |
+ key = HeapConstant(isolate->factory()->resolve_string()); |
+ Node* const deferred_on_resolve = |
+ CallStub(getproperty_callable, context, deferred, key); |
+ var_deferred_on_resolve.Bind(deferred_on_resolve); |
+ |
+ key = HeapConstant(isolate->factory()->reject_string()); |
+ Node* const deferred_on_reject = |
+ CallStub(getproperty_callable, context, deferred, key); |
+ var_deferred_on_reject.Bind(deferred_on_reject); |
+ |
Goto(&perform_promise_then); |
} |
@@ -820,7 +863,8 @@ TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { |
// resultCapability). |
Bind(&perform_promise_then); |
Node* const result = InternalPerformPromiseThen( |
- context, promise, on_resolve, on_reject, var_deferred.value()); |
+ context, promise, on_resolve, on_reject, var_deferred_promise.value(), |
+ var_deferred_on_resolve.value(), var_deferred_on_reject.value()); |
Return(result); |
} |
@@ -899,17 +943,13 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { |
Node* const promise = Parameter(1); |
Node* const value = Parameter(2); |
Node* const handler = Parameter(3); |
- Node* const deferred = Parameter(4); |
- Node* const context = Parameter(7); |
+ Node* const deferred_promise = Parameter(4); |
+ Node* const deferred_on_resolve = Parameter(5); |
+ Node* const deferred_on_reject = Parameter(6); |
+ Node* const context = Parameter(9); |
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 = HeapConstant(isolate->factory()->promise_string()); |
- Node* const deferred_promise = |
- CallStub(getproperty_callable, context, deferred, key); |
- |
Variable var_reason(this, MachineRepresentation::kTagged); |
Node* const is_debug_active = IsDebugActive(); |
@@ -930,16 +970,12 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { |
Bind(&run_handler); |
{ |
Callable call_callable = CodeFactory::Call(isolate); |
- |
Node* const result = |
CallJS(call_callable, context, handler, UndefinedConstant(), value); |
GotoIfException(result, &if_rejectpromise, &var_reason); |
- // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |
- Node* const key = HeapConstant(isolate->factory()->resolve_string()); |
- Node* const on_resolve = |
- CallStub(getproperty_callable, context, deferred, key); |
+ Node* const on_resolve = deferred_on_resolve; |
Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); |
Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); |
@@ -959,11 +995,7 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { |
Bind(&if_rejectpromise); |
{ |
- // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |
- Node* const key = HeapConstant(isolate->factory()->reject_string()); |
- Node* const on_reject = |
- CallStub(getproperty_callable, context, deferred, key); |
- |
+ Node* const on_reject = deferred_on_reject; |
Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); |
CallStub(promise_handle_reject, context, deferred_promise, on_reject, |
var_reason.value()); |