| Index: src/builtins/builtins-promise.cc
|
| diff --git a/src/builtins/builtins-promise.cc b/src/builtins/builtins-promise.cc
|
| index e335e64a6911932f2624b175e05686b721dfdd45..bbe54419afa5c129a35a457720cc59880bdd7a02 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 =
|
| @@ -201,22 +215,20 @@ Node* PromiseBuiltinsAssembler::InternalPromiseThen(Node* context,
|
| 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);
|
| }
|
|
|
| @@ -225,10 +237,25 @@ Node* PromiseBuiltinsAssembler::InternalPromiseThen(Node* context,
|
| // 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);
|
| }
|
|
|
| @@ -236,15 +263,15 @@ Node* PromiseBuiltinsAssembler::InternalPromiseThen(Node* context,
|
| // 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;
|
| }
|
|
|
| -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),
|
| @@ -292,17 +319,22 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context,
|
| GotoUnless(SmiEqual(status, SmiConstant(v8::Promise::kPending)),
|
| &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,
|
| @@ -313,17 +345,32 @@ 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_promise_arr =
|
| AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
|
| - StoreFixedArrayElement(deferreds, 0, existing_deferred);
|
| - StoreFixedArrayElement(deferreds, 1, deferred);
|
| + StoreFixedArrayElement(deferred_promise_arr, 0,
|
| + existing_deferred_promise);
|
| + StoreFixedArrayElement(deferred_promise_arr, 1, deferred_promise);
|
| +
|
| + Node* const deferred_on_resolve_arr =
|
| + AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
|
| + StoreFixedArrayElement(
|
| + deferred_on_resolve_arr, 0,
|
| + LoadObjectField(promise, JSPromise::kDeferredOnResolveOffset));
|
| + StoreFixedArrayElement(deferred_on_resolve_arr, 1, deferred_on_resolve);
|
| +
|
| + Node* const deferred_on_reject_arr =
|
| + AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
|
| + StoreFixedArrayElement(
|
| + deferred_on_reject_arr, 0,
|
| + LoadObjectField(promise, JSPromise::kDeferredOnRejectOffset));
|
| + StoreFixedArrayElement(deferred_on_reject_arr, 1, deferred_on_reject);
|
|
|
| Node* const fulfill_reactions =
|
| AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
|
| @@ -340,7 +387,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,
|
| + deferred_promise_arr);
|
| + StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset,
|
| + deferred_on_resolve_arr);
|
| + StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset,
|
| + deferred_on_reject_arr);
|
| StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
|
| fulfill_reactions);
|
| StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
|
| @@ -350,7 +402,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,
|
| @@ -366,9 +423,11 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context,
|
| GotoUnless(WordEqual(status, SmiConstant(v8::Promise::kFulfilled)),
|
| &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);
|
| + // TODO(gsathya): Move this to TF
|
| + CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info,
|
| SmiConstant(v8::Promise::kFulfilled));
|
| Goto(&out);
|
|
|
| @@ -384,10 +443,12 @@ 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);
|
| + // TODO(gsathya): Move this to TF
|
| + CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info,
|
| SmiConstant(v8::Promise::kRejected));
|
| -
|
| Goto(&out);
|
| }
|
| }
|
| @@ -396,16 +457,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.
|
| @@ -557,6 +609,7 @@ void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context,
|
| // PromiseResolveThenableJob, « promise, resolution, thenAction
|
| // »).
|
| Bind(&enqueue);
|
| + // TODO(gsathya): Move this to TF
|
| CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise,
|
| result, var_then.value());
|
| Goto(&out);
|
| @@ -767,16 +820,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) {
|
| @@ -814,11 +858,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);
|
| @@ -911,17 +958,12 @@ 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();
|
| @@ -942,19 +984,14 @@ 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);
|
| -
|
| Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
|
| - Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler);
|
| + Branch(IsUndefined(deferred_on_resolve), &if_internalhandler,
|
| + &if_customhandler);
|
|
|
| Bind(&if_internalhandler);
|
| InternalResolvePromise(context, deferred_promise, result);
|
| @@ -962,8 +999,9 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
|
|
|
| Bind(&if_customhandler);
|
| {
|
| - Node* const maybe_exception = CallJS(call_callable, context, on_resolve,
|
| - UndefinedConstant(), result);
|
| + Node* const maybe_exception =
|
| + CallJS(call_callable, context, deferred_on_resolve,
|
| + UndefinedConstant(), result);
|
| GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
|
| Goto(&promisehook_after);
|
| }
|
| @@ -971,14 +1009,9 @@ 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);
|
| -
|
| Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate);
|
| - CallStub(promise_handle_reject, context, deferred_promise, on_reject,
|
| - var_reason.value());
|
| + CallStub(promise_handle_reject, context, deferred_promise,
|
| + deferred_on_reject, var_reason.value());
|
| Goto(&promisehook_after);
|
| }
|
|
|
|
|