| OLD | NEW | 
|     1 // Copyright 2016 the V8 project authors. All rights reserved. |     1 // Copyright 2016 the V8 project authors. All rights reserved. | 
|     2 // Use of this source code is governed by a BSD-style license that can be |     2 // Use of this source code is governed by a BSD-style license that can be | 
|     3 // found in the LICENSE file. |     3 // found in the LICENSE file. | 
|     4  |     4  | 
|     5 #include "src/builtins/builtins-promise.h" |     5 #include "src/builtins/builtins-promise.h" | 
|     6 #include "src/builtins/builtins-utils.h" |     6 #include "src/builtins/builtins-utils.h" | 
|     7 #include "src/builtins/builtins.h" |     7 #include "src/builtins/builtins.h" | 
|     8 #include "src/code-factory.h" |     8 #include "src/code-factory.h" | 
|     9 #include "src/code-stub-assembler.h" |     9 #include "src/code-stub-assembler.h" | 
|    10 #include "src/promise-utils.h" |    10 #include "src/promise-utils.h" | 
|    11  |    11  | 
|    12 namespace v8 { |    12 namespace v8 { | 
|    13 namespace internal { |    13 namespace internal { | 
|    14  |    14  | 
|    15 typedef compiler::Node Node; |    15 typedef compiler::Node Node; | 
|    16 typedef CodeStubAssembler::ParameterMode ParameterMode; |    16 typedef CodeStubAssembler::ParameterMode ParameterMode; | 
|    17 typedef compiler::CodeAssemblerState CodeAssemblerState; |    17 typedef compiler::CodeAssemblerState CodeAssemblerState; | 
|    18  |    18  | 
 |    19 Node* PromiseBuiltinsAssembler::AllocateAndInitPromise(Node* context, | 
 |    20                                                        Node* parent) { | 
 |    21   Node* const instance = AllocateJSPromise(context); | 
 |    22   PromiseInit(instance); | 
 |    23  | 
 |    24   Label out(this); | 
 |    25   GotoUnless(IsPromiseHookEnabled(), &out); | 
 |    26   CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); | 
 |    27   Goto(&out); | 
 |    28  | 
 |    29   Bind(&out); | 
 |    30   return instance; | 
 |    31 } | 
 |    32  | 
|    19 Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext( |    33 Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext( | 
|    20     Node* promise, Node* debug_event, Node* native_context) { |    34     Node* promise, Node* debug_event, Node* native_context) { | 
|    21   Node* const context = |    35   Node* const context = | 
|    22       Allocate(FixedArray::SizeFor(PromiseUtils::kPromiseContextLength)); |    36       Allocate(FixedArray::SizeFor(PromiseUtils::kPromiseContextLength)); | 
|    23   StoreMapNoWriteBarrier(context, Heap::kFunctionContextMapRootIndex); |    37   StoreMapNoWriteBarrier(context, Heap::kFunctionContextMapRootIndex); | 
|    24   StoreObjectFieldNoWriteBarrier( |    38   StoreObjectFieldNoWriteBarrier( | 
|    25       context, FixedArray::kLengthOffset, |    39       context, FixedArray::kLengthOffset, | 
|    26       SmiConstant(PromiseUtils::kPromiseContextLength)); |    40       SmiConstant(PromiseUtils::kPromiseContextLength)); | 
|    27  |    41  | 
|    28   Node* const empty_fn = |    42   Node* const empty_fn = | 
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   194   Node* const promise_fun = |   208   Node* const promise_fun = | 
|   195       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); |   209       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | 
|   196  |   210  | 
|   197   // 3. Let C be ? SpeciesConstructor(promise, %Promise%). |   211   // 3. Let C be ? SpeciesConstructor(promise, %Promise%). | 
|   198   Node* constructor = SpeciesConstructor(context, promise, promise_fun); |   212   Node* constructor = SpeciesConstructor(context, promise, promise_fun); | 
|   199  |   213  | 
|   200   // 4. Let resultCapability be ? NewPromiseCapability(C). |   214   // 4. Let resultCapability be ? NewPromiseCapability(C). | 
|   201   Callable call_callable = CodeFactory::Call(isolate); |   215   Callable call_callable = CodeFactory::Call(isolate); | 
|   202   Label fast_promise_capability(this), promise_capability(this), |   216   Label fast_promise_capability(this), promise_capability(this), | 
|   203       perform_promise_then(this); |   217       perform_promise_then(this); | 
|   204   Variable var_deferred(this, MachineRepresentation::kTagged); |   218   Variable var_deferred_promise(this, MachineRepresentation::kTagged), | 
 |   219       var_deferred_on_resolve(this, MachineRepresentation::kTagged), | 
 |   220       var_deferred_on_reject(this, MachineRepresentation::kTagged); | 
|   205  |   221  | 
|   206   Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, |   222   Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, | 
|   207          &promise_capability); |   223          &promise_capability); | 
|   208  |   224  | 
|   209   // TODO(gsathya): Remove deferred object and move |  | 
|   210   // NewPromiseCapabability functions to TF. |  | 
|   211   Bind(&fast_promise_capability); |   225   Bind(&fast_promise_capability); | 
|   212   { |   226   { | 
|   213     // TODO(gsathya): Move this to TF. |   227     Node* const deferred_promise = AllocateAndInitPromise(context, promise); | 
|   214     Node* const promise_internal_capability = LoadContextElement( |   228     PromiseInit(deferred_promise); | 
|   215         native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); |   229     var_deferred_promise.Bind(deferred_promise); | 
|   216     Node* const capability = |   230     var_deferred_on_resolve.Bind(UndefinedConstant()); | 
|   217         CallJS(call_callable, context, promise_internal_capability, |   231     var_deferred_on_reject.Bind(UndefinedConstant()); | 
|   218                UndefinedConstant(), promise); |  | 
|   219     var_deferred.Bind(capability); |  | 
|   220     Goto(&perform_promise_then); |   232     Goto(&perform_promise_then); | 
|   221   } |   233   } | 
|   222  |   234  | 
|   223   Bind(&promise_capability); |   235   Bind(&promise_capability); | 
|   224   { |   236   { | 
|   225     // TODO(gsathya): Move this to TF. |   237     // TODO(gsathya): Move this to TF. | 
|   226     Node* const new_promise_capability = LoadContextElement( |   238     Node* const new_promise_capability = LoadContextElement( | 
|   227         native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); |   239         native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); | 
|   228     Node* const capability = |   240     Node* const deferred = | 
|   229         CallJS(call_callable, context, new_promise_capability, |   241         CallJS(call_callable, context, new_promise_capability, | 
|   230                UndefinedConstant(), constructor); |   242                UndefinedConstant(), constructor); | 
|   231     var_deferred.Bind(capability); |   243     Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 
 |   244     Node* key = HeapConstant(isolate->factory()->promise_string()); | 
 |   245     Node* const deferred_promise = | 
 |   246         CallStub(getproperty_callable, context, deferred, key); | 
 |   247     var_deferred_promise.Bind(deferred_promise); | 
 |   248  | 
 |   249     key = HeapConstant(isolate->factory()->resolve_string()); | 
 |   250     Node* const deferred_on_resolve = | 
 |   251         CallStub(getproperty_callable, context, deferred, key); | 
 |   252     var_deferred_on_resolve.Bind(deferred_on_resolve); | 
 |   253  | 
 |   254     key = HeapConstant(isolate->factory()->reject_string()); | 
 |   255     Node* const deferred_on_reject = | 
 |   256         CallStub(getproperty_callable, context, deferred, key); | 
 |   257     var_deferred_on_reject.Bind(deferred_on_reject); | 
 |   258  | 
|   232     Goto(&perform_promise_then); |   259     Goto(&perform_promise_then); | 
|   233   } |   260   } | 
|   234  |   261  | 
|   235   // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, |   262   // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, | 
|   236   //    resultCapability). |   263   //    resultCapability). | 
|   237   Bind(&perform_promise_then); |   264   Bind(&perform_promise_then); | 
|   238   Node* const result = InternalPerformPromiseThen( |   265   Node* const result = InternalPerformPromiseThen( | 
|   239       context, promise, on_resolve, on_reject, var_deferred.value()); |   266       context, promise, on_resolve, on_reject, var_deferred_promise.value(), | 
 |   267       var_deferred_on_resolve.value(), var_deferred_on_reject.value()); | 
|   240   return result; |   268   return result; | 
|   241 } |   269 } | 
|   242  |   270  | 
|   243 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |   271 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen( | 
|   244                                                            Node* promise, |   272     Node* context, Node* promise, Node* on_resolve, Node* on_reject, | 
|   245                                                            Node* on_resolve, |   273     Node* deferred_promise, Node* deferred_on_resolve, | 
|   246                                                            Node* on_reject, |   274     Node* deferred_on_reject) { | 
|   247                                                            Node* deferred) { |  | 
|   248   Node* const native_context = LoadNativeContext(context); |   275   Node* const native_context = LoadNativeContext(context); | 
|   249  |   276  | 
|   250   Variable var_on_resolve(this, MachineRepresentation::kTagged), |   277   Variable var_on_resolve(this, MachineRepresentation::kTagged), | 
|   251       var_on_reject(this, MachineRepresentation::kTagged); |   278       var_on_reject(this, MachineRepresentation::kTagged); | 
|   252  |   279  | 
|   253   var_on_resolve.Bind(on_resolve); |   280   var_on_resolve.Bind(on_resolve); | 
|   254   var_on_reject.Bind(on_reject); |   281   var_on_reject.Bind(on_reject); | 
|   255  |   282  | 
|   256   Label out(this), if_onresolvenotcallable(this), onrejectcheck(this), |   283   Label out(this), if_onresolvenotcallable(this), onrejectcheck(this), | 
|   257       append_callbacks(this); |   284       append_callbacks(this); | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
|   285     } |   312     } | 
|   286   } |   313   } | 
|   287  |   314  | 
|   288   Bind(&append_callbacks); |   315   Bind(&append_callbacks); | 
|   289   { |   316   { | 
|   290     Label fulfilled_check(this); |   317     Label fulfilled_check(this); | 
|   291     Node* const status = LoadObjectField(promise, JSPromise::kStatusOffset); |   318     Node* const status = LoadObjectField(promise, JSPromise::kStatusOffset); | 
|   292     GotoUnless(SmiEqual(status, SmiConstant(v8::Promise::kPending)), |   319     GotoUnless(SmiEqual(status, SmiConstant(v8::Promise::kPending)), | 
|   293                &fulfilled_check); |   320                &fulfilled_check); | 
|   294  |   321  | 
|   295     Node* const existing_deferred = |   322     Node* const existing_deferred_promise = | 
|   296         LoadObjectField(promise, JSPromise::kDeferredOffset); |   323         LoadObjectField(promise, JSPromise::kDeferredPromiseOffset); | 
|   297  |   324  | 
|   298     Label if_noexistingcallbacks(this), if_existingcallbacks(this); |   325     Label if_noexistingcallbacks(this), if_existingcallbacks(this); | 
|   299     Branch(IsUndefined(existing_deferred), &if_noexistingcallbacks, |   326     Branch(IsUndefined(existing_deferred_promise), &if_noexistingcallbacks, | 
|   300            &if_existingcallbacks); |   327            &if_existingcallbacks); | 
|   301  |   328  | 
|   302     Bind(&if_noexistingcallbacks); |   329     Bind(&if_noexistingcallbacks); | 
|   303     { |   330     { | 
|   304       // Store callbacks directly in the slots. |   331       // Store callbacks directly in the slots. | 
|   305       StoreObjectField(promise, JSPromise::kDeferredOffset, deferred); |   332       StoreObjectField(promise, JSPromise::kDeferredPromiseOffset, | 
 |   333                        deferred_promise); | 
 |   334       StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset, | 
 |   335                        deferred_on_resolve); | 
 |   336       StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset, | 
 |   337                        deferred_on_reject); | 
|   306       StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, |   338       StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, | 
|   307                        var_on_resolve.value()); |   339                        var_on_resolve.value()); | 
|   308       StoreObjectField(promise, JSPromise::kRejectReactionsOffset, |   340       StoreObjectField(promise, JSPromise::kRejectReactionsOffset, | 
|   309                        var_on_reject.value()); |   341                        var_on_reject.value()); | 
|   310       Goto(&out); |   342       Goto(&out); | 
|   311     } |   343     } | 
|   312  |   344  | 
|   313     Bind(&if_existingcallbacks); |   345     Bind(&if_existingcallbacks); | 
|   314     { |   346     { | 
|   315       Label if_singlecallback(this), if_multiplecallbacks(this); |   347       Label if_singlecallback(this), if_multiplecallbacks(this); | 
|   316       BranchIfJSObject(existing_deferred, &if_singlecallback, |   348       BranchIfJSObject(existing_deferred_promise, &if_singlecallback, | 
|   317                        &if_multiplecallbacks); |   349                        &if_multiplecallbacks); | 
|   318  |   350  | 
|   319       Bind(&if_singlecallback); |   351       Bind(&if_singlecallback); | 
|   320       { |   352       { | 
|   321         // Create new FixedArrays to store callbacks, and migrate |   353         // Create new FixedArrays to store callbacks, and migrate | 
|   322         // existing callbacks. |   354         // existing callbacks. | 
|   323         Node* const deferreds = |   355         Node* const deferred_promise_arr = | 
|   324             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |   356             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); | 
|   325         StoreFixedArrayElement(deferreds, 0, existing_deferred); |   357         StoreFixedArrayElement(deferred_promise_arr, 0, | 
|   326         StoreFixedArrayElement(deferreds, 1, deferred); |   358                                existing_deferred_promise); | 
 |   359         StoreFixedArrayElement(deferred_promise_arr, 1, deferred_promise); | 
 |   360  | 
 |   361         Node* const deferred_on_resolve_arr = | 
 |   362             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); | 
 |   363         StoreFixedArrayElement( | 
 |   364             deferred_on_resolve_arr, 0, | 
 |   365             LoadObjectField(promise, JSPromise::kDeferredOnResolveOffset)); | 
 |   366         StoreFixedArrayElement(deferred_on_resolve_arr, 1, deferred_on_resolve); | 
 |   367  | 
 |   368         Node* const deferred_on_reject_arr = | 
 |   369             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); | 
 |   370         StoreFixedArrayElement( | 
 |   371             deferred_on_reject_arr, 0, | 
 |   372             LoadObjectField(promise, JSPromise::kDeferredOnRejectOffset)); | 
 |   373         StoreFixedArrayElement(deferred_on_reject_arr, 1, deferred_on_reject); | 
|   327  |   374  | 
|   328         Node* const fulfill_reactions = |   375         Node* const fulfill_reactions = | 
|   329             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |   376             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); | 
|   330         StoreFixedArrayElement( |   377         StoreFixedArrayElement( | 
|   331             fulfill_reactions, 0, |   378             fulfill_reactions, 0, | 
|   332             LoadObjectField(promise, JSPromise::kFulfillReactionsOffset)); |   379             LoadObjectField(promise, JSPromise::kFulfillReactionsOffset)); | 
|   333         StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value()); |   380         StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value()); | 
|   334  |   381  | 
|   335         Node* const reject_reactions = |   382         Node* const reject_reactions = | 
|   336             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |   383             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); | 
|   337         StoreFixedArrayElement( |   384         StoreFixedArrayElement( | 
|   338             reject_reactions, 0, |   385             reject_reactions, 0, | 
|   339             LoadObjectField(promise, JSPromise::kRejectReactionsOffset)); |   386             LoadObjectField(promise, JSPromise::kRejectReactionsOffset)); | 
|   340         StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value()); |   387         StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value()); | 
|   341  |   388  | 
|   342         // Store new FixedArrays in promise. |   389         // Store new FixedArrays in promise. | 
|   343         StoreObjectField(promise, JSPromise::kDeferredOffset, deferreds); |   390         StoreObjectField(promise, JSPromise::kDeferredPromiseOffset, | 
 |   391                          deferred_promise_arr); | 
 |   392         StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset, | 
 |   393                          deferred_on_resolve_arr); | 
 |   394         StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset, | 
 |   395                          deferred_on_reject_arr); | 
|   344         StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, |   396         StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, | 
|   345                          fulfill_reactions); |   397                          fulfill_reactions); | 
|   346         StoreObjectField(promise, JSPromise::kRejectReactionsOffset, |   398         StoreObjectField(promise, JSPromise::kRejectReactionsOffset, | 
|   347                          reject_reactions); |   399                          reject_reactions); | 
|   348         Goto(&out); |   400         Goto(&out); | 
|   349       } |   401       } | 
|   350  |   402  | 
|   351       Bind(&if_multiplecallbacks); |   403       Bind(&if_multiplecallbacks); | 
|   352       { |   404       { | 
|   353         AppendPromiseCallback(JSPromise::kDeferredOffset, promise, deferred); |   405         AppendPromiseCallback(JSPromise::kDeferredPromiseOffset, promise, | 
 |   406                               deferred_promise); | 
 |   407         AppendPromiseCallback(JSPromise::kDeferredOnResolveOffset, promise, | 
 |   408                               deferred_on_resolve); | 
 |   409         AppendPromiseCallback(JSPromise::kDeferredOnRejectOffset, promise, | 
 |   410                               deferred_on_reject); | 
|   354         AppendPromiseCallback(JSPromise::kFulfillReactionsOffset, promise, |   411         AppendPromiseCallback(JSPromise::kFulfillReactionsOffset, promise, | 
|   355                               var_on_resolve.value()); |   412                               var_on_resolve.value()); | 
|   356         AppendPromiseCallback(JSPromise::kRejectReactionsOffset, promise, |   413         AppendPromiseCallback(JSPromise::kRejectReactionsOffset, promise, | 
|   357                               var_on_reject.value()); |   414                               var_on_reject.value()); | 
|   358         Goto(&out); |   415         Goto(&out); | 
|   359       } |   416       } | 
|   360     } |   417     } | 
|   361  |   418  | 
|   362     Bind(&fulfilled_check); |   419     Bind(&fulfilled_check); | 
|   363     { |   420     { | 
|   364       Label reject(this); |   421       Label reject(this); | 
|   365       Node* const result = LoadObjectField(promise, JSPromise::kResultOffset); |   422       Node* const result = LoadObjectField(promise, JSPromise::kResultOffset); | 
|   366       GotoUnless(WordEqual(status, SmiConstant(v8::Promise::kFulfilled)), |   423       GotoUnless(WordEqual(status, SmiConstant(v8::Promise::kFulfilled)), | 
|   367                  &reject); |   424                  &reject); | 
|   368  |   425  | 
|   369       // TODO(gsathya): Move this to TF. |   426       Node* info = AllocatePromiseReactionJobInfo( | 
|   370       CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise, result, |   427           promise, result, var_on_resolve.value(), deferred_promise, | 
|   371                   var_on_resolve.value(), deferred, |   428           deferred_on_resolve, deferred_on_reject, context); | 
 |   429       // TODO(gsathya): Move this to TF | 
 |   430       CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info, | 
|   372                   SmiConstant(v8::Promise::kFulfilled)); |   431                   SmiConstant(v8::Promise::kFulfilled)); | 
|   373       Goto(&out); |   432       Goto(&out); | 
|   374  |   433  | 
|   375       Bind(&reject); |   434       Bind(&reject); | 
|   376       { |   435       { | 
|   377         Node* const has_handler = PromiseHasHandler(promise); |   436         Node* const has_handler = PromiseHasHandler(promise); | 
|   378         Label enqueue(this); |   437         Label enqueue(this); | 
|   379  |   438  | 
|   380         // TODO(gsathya): Fold these runtime calls and move to TF. |   439         // TODO(gsathya): Fold these runtime calls and move to TF. | 
|   381         GotoIf(has_handler, &enqueue); |   440         GotoIf(has_handler, &enqueue); | 
|   382         CallRuntime(Runtime::kPromiseRevokeReject, context, promise); |   441         CallRuntime(Runtime::kPromiseRevokeReject, context, promise); | 
|   383         Goto(&enqueue); |   442         Goto(&enqueue); | 
|   384  |   443  | 
|   385         Bind(&enqueue); |   444         Bind(&enqueue); | 
|   386         { |   445         { | 
|   387           CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, promise, |   446           Node* info = AllocatePromiseReactionJobInfo( | 
|   388                       result, var_on_reject.value(), deferred, |   447               promise, result, var_on_reject.value(), deferred_promise, | 
 |   448               deferred_on_resolve, deferred_on_reject, context); | 
 |   449           // TODO(gsathya): Move this to TF | 
 |   450           CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info, | 
|   389                       SmiConstant(v8::Promise::kRejected)); |   451                       SmiConstant(v8::Promise::kRejected)); | 
|   390  |  | 
|   391           Goto(&out); |   452           Goto(&out); | 
|   392         } |   453         } | 
|   393       } |   454       } | 
|   394     } |   455     } | 
|   395   } |   456   } | 
|   396  |   457  | 
|   397   Bind(&out); |   458   Bind(&out); | 
|   398   PromiseSetHasHandler(promise); |   459   PromiseSetHasHandler(promise); | 
|   399  |   460   return deferred_promise; | 
|   400   // TODO(gsathya): This call will be removed once we don't have to |  | 
|   401   // deal with deferred objects. |  | 
|   402   Isolate* isolate = this->isolate(); |  | 
|   403   Callable getproperty_callable = CodeFactory::GetProperty(isolate); |  | 
|   404   Node* const key = |  | 
|   405       HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise")); |  | 
|   406   Node* const result = CallStub(getproperty_callable, context, deferred, key); |  | 
|   407  |  | 
|   408   return result; |  | 
|   409 } |   461 } | 
|   410  |   462  | 
|   411 // Promise fast path implementations rely on unmodified JSPromise instances. |   463 // Promise fast path implementations rely on unmodified JSPromise instances. | 
|   412 // We use a fairly coarse granularity for this and simply check whether both |   464 // We use a fairly coarse granularity for this and simply check whether both | 
|   413 // the promise itself is unmodified (i.e. its map has not changed) and its |   465 // the promise itself is unmodified (i.e. its map has not changed) and its | 
|   414 // prototype is unmodified. |   466 // prototype is unmodified. | 
|   415 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp |   467 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp | 
|   416 void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise, |   468 void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise, | 
|   417                                                 Label* if_isunmodified, |   469                                                 Label* if_isunmodified, | 
|   418                                                 Label* if_ismodified) { |   470                                                 Label* if_ismodified) { | 
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   550     Node* const key = |   602     Node* const key = | 
|   551         HeapConstant(isolate->factory()->promise_handled_by_symbol()); |   603         HeapConstant(isolate->factory()->promise_handled_by_symbol()); | 
|   552     CallRuntime(Runtime::kSetProperty, context, result, key, promise, |   604     CallRuntime(Runtime::kSetProperty, context, result, key, promise, | 
|   553                 SmiConstant(STRICT)); |   605                 SmiConstant(STRICT)); | 
|   554     Goto(&enqueue); |   606     Goto(&enqueue); | 
|   555  |   607  | 
|   556     // 12. Perform EnqueueJob("PromiseJobs", |   608     // 12. Perform EnqueueJob("PromiseJobs", | 
|   557     // PromiseResolveThenableJob, « promise, resolution, thenAction |   609     // PromiseResolveThenableJob, « promise, resolution, thenAction | 
|   558     // »). |   610     // »). | 
|   559     Bind(&enqueue); |   611     Bind(&enqueue); | 
 |   612     // TODO(gsathya): Move this to TF | 
|   560     CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise, |   613     CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise, | 
|   561                 result, var_then.value()); |   614                 result, var_then.value()); | 
|   562     Goto(&out); |   615     Goto(&out); | 
|   563   } |   616   } | 
|   564  |   617  | 
|   565   // 7.b Return FulfillPromise(promise, resolution). |   618   // 7.b Return FulfillPromise(promise, resolution). | 
|   566   Bind(&fulfill); |   619   Bind(&fulfill); | 
|   567   { |   620   { | 
|   568     CallRuntime(Runtime::kPromiseFulfill, context, promise, |   621     CallRuntime(Runtime::kPromiseFulfill, context, promise, | 
|   569                 SmiConstant(v8::Promise::kFulfilled), result); |   622                 SmiConstant(v8::Promise::kFulfilled), result); | 
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   760     Node* const message_id = |   813     Node* const message_id = | 
|   761         SmiConstant(MessageTemplate::kResolverNotAFunction); |   814         SmiConstant(MessageTemplate::kResolverNotAFunction); | 
|   762     CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); |   815     CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); | 
|   763     Return(UndefinedConstant());  // Never reached. |   816     Return(UndefinedConstant());  // Never reached. | 
|   764   } |   817   } | 
|   765 } |   818 } | 
|   766  |   819  | 
|   767 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { |   820 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { | 
|   768   Node* const parent = Parameter(1); |   821   Node* const parent = Parameter(1); | 
|   769   Node* const context = Parameter(4); |   822   Node* const context = Parameter(4); | 
|   770   Node* const instance = AllocateJSPromise(context); |   823   Return(AllocateAndInitPromise(context, parent)); | 
|   771   PromiseInit(instance); |  | 
|   772  |  | 
|   773   Label out(this); |  | 
|   774   GotoUnless(IsPromiseHookEnabled(), &out); |  | 
|   775   CallRuntime(Runtime::kPromiseHookInit, context, instance, parent); |  | 
|   776   Goto(&out); |  | 
|   777   Bind(&out); |  | 
|   778  |  | 
|   779   Return(instance); |  | 
|   780 } |   824 } | 
|   781  |   825  | 
|   782 TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) { |   826 TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) { | 
|   783   Node* const status = Parameter(1); |   827   Node* const status = Parameter(1); | 
|   784   Node* const result = Parameter(2); |   828   Node* const result = Parameter(2); | 
|   785   Node* const context = Parameter(5); |   829   Node* const context = Parameter(5); | 
|   786  |   830  | 
|   787   Node* const instance = AllocateJSPromise(context); |   831   Node* const instance = AllocateJSPromise(context); | 
|   788   PromiseSet(instance, status, result); |   832   PromiseSet(instance, status, result); | 
|   789  |   833  | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
|   807   Return(result); |   851   Return(result); | 
|   808  |   852  | 
|   809   Bind(&if_notpromise); |   853   Bind(&if_notpromise); | 
|   810   Return(FalseConstant()); |   854   Return(FalseConstant()); | 
|   811 } |   855 } | 
|   812  |   856  | 
|   813 TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) { |   857 TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) { | 
|   814   Node* const promise = Parameter(1); |   858   Node* const promise = Parameter(1); | 
|   815   Node* const on_resolve = Parameter(2); |   859   Node* const on_resolve = Parameter(2); | 
|   816   Node* const on_reject = Parameter(3); |   860   Node* const on_reject = Parameter(3); | 
|   817   Node* const deferred = Parameter(4); |   861   Node* const deferred_promise = Parameter(4); | 
|   818   Node* const context = Parameter(7); |   862   Node* const context = Parameter(7); | 
|   819  |   863  | 
|   820   Node* const result = InternalPerformPromiseThen(context, promise, on_resolve, |   864   // No deferred_on_resolve/deferred_on_reject because this is just an | 
|   821                                                   on_reject, deferred); |   865   // internal promise created by async-await. | 
 |   866   Node* const result = InternalPerformPromiseThen( | 
 |   867       context, promise, on_resolve, on_reject, deferred_promise, | 
 |   868       UndefinedConstant(), UndefinedConstant()); | 
|   822  |   869  | 
|   823   // TODO(gsathya): This is unused, but value is returned according to spec. |   870   // TODO(gsathya): This is unused, but value is returned according to spec. | 
|   824   Return(result); |   871   Return(result); | 
|   825 } |   872 } | 
|   826  |   873  | 
|   827 // ES#sec-promise.prototype.then |   874 // ES#sec-promise.prototype.then | 
|   828 // Promise.prototype.catch ( onFulfilled, onRejected ) |   875 // Promise.prototype.catch ( onFulfilled, onRejected ) | 
|   829 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { |   876 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { | 
|   830   // 1. Let promise be the this value. |   877   // 1. Let promise be the this value. | 
|   831   Node* const promise = Parameter(0); |   878   Node* const promise = Parameter(0); | 
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   904   { |   951   { | 
|   905     CallJS(call_callable, context, on_reject, UndefinedConstant(), exception); |   952     CallJS(call_callable, context, on_reject, UndefinedConstant(), exception); | 
|   906     Return(UndefinedConstant()); |   953     Return(UndefinedConstant()); | 
|   907   } |   954   } | 
|   908 } |   955 } | 
|   909  |   956  | 
|   910 TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { |   957 TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) { | 
|   911   Node* const promise = Parameter(1); |   958   Node* const promise = Parameter(1); | 
|   912   Node* const value = Parameter(2); |   959   Node* const value = Parameter(2); | 
|   913   Node* const handler = Parameter(3); |   960   Node* const handler = Parameter(3); | 
|   914   Node* const deferred = Parameter(4); |   961   Node* const deferred_promise = Parameter(4); | 
|   915   Node* const context = Parameter(7); |   962   Node* const deferred_on_resolve = Parameter(5); | 
 |   963   Node* const deferred_on_reject = Parameter(6); | 
 |   964   Node* const context = Parameter(9); | 
|   916   Isolate* isolate = this->isolate(); |   965   Isolate* isolate = this->isolate(); | 
|   917  |   966  | 
|   918   // Get promise from deferred |  | 
|   919   // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |  | 
|   920   Callable getproperty_callable = CodeFactory::GetProperty(isolate); |  | 
|   921   Node* const key = HeapConstant(isolate->factory()->promise_string()); |  | 
|   922   Node* const deferred_promise = |  | 
|   923       CallStub(getproperty_callable, context, deferred, key); |  | 
|   924  |  | 
|   925   Variable var_reason(this, MachineRepresentation::kTagged); |   967   Variable var_reason(this, MachineRepresentation::kTagged); | 
|   926  |   968  | 
|   927   Node* const is_debug_active = IsDebugActive(); |   969   Node* const is_debug_active = IsDebugActive(); | 
|   928   Label run_handler(this), if_rejectpromise(this), promisehook_before(this), |   970   Label run_handler(this), if_rejectpromise(this), promisehook_before(this), | 
|   929       promisehook_after(this), debug_pop(this); |   971       promisehook_after(this), debug_pop(this); | 
|   930  |   972  | 
|   931   GotoUnless(is_debug_active, &promisehook_before); |   973   GotoUnless(is_debug_active, &promisehook_before); | 
|   932   CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); |   974   CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise); | 
|   933   Goto(&promisehook_before); |   975   Goto(&promisehook_before); | 
|   934  |   976  | 
|   935   Bind(&promisehook_before); |   977   Bind(&promisehook_before); | 
|   936   { |   978   { | 
|   937     GotoUnless(IsPromiseHookEnabled(), &run_handler); |   979     GotoUnless(IsPromiseHookEnabled(), &run_handler); | 
|   938     CallRuntime(Runtime::kPromiseHookBefore, context, promise); |   980     CallRuntime(Runtime::kPromiseHookBefore, context, promise); | 
|   939     Goto(&run_handler); |   981     Goto(&run_handler); | 
|   940   } |   982   } | 
|   941  |   983  | 
|   942   Bind(&run_handler); |   984   Bind(&run_handler); | 
|   943   { |   985   { | 
|   944     Callable call_callable = CodeFactory::Call(isolate); |   986     Callable call_callable = CodeFactory::Call(isolate); | 
|   945  |  | 
|   946     Node* const result = |   987     Node* const result = | 
|   947         CallJS(call_callable, context, handler, UndefinedConstant(), value); |   988         CallJS(call_callable, context, handler, UndefinedConstant(), value); | 
|   948  |   989  | 
|   949     GotoIfException(result, &if_rejectpromise, &var_reason); |   990     GotoIfException(result, &if_rejectpromise, &var_reason); | 
|   950  |   991  | 
|   951     // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |  | 
|   952     Node* const key = HeapConstant(isolate->factory()->resolve_string()); |  | 
|   953     Node* const on_resolve = |  | 
|   954         CallStub(getproperty_callable, context, deferred, key); |  | 
|   955  |  | 
|   956     Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); |   992     Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); | 
|   957     Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); |   993     Branch(IsUndefined(deferred_on_resolve), &if_internalhandler, | 
 |   994            &if_customhandler); | 
|   958  |   995  | 
|   959     Bind(&if_internalhandler); |   996     Bind(&if_internalhandler); | 
|   960     InternalResolvePromise(context, deferred_promise, result); |   997     InternalResolvePromise(context, deferred_promise, result); | 
|   961     Goto(&promisehook_after); |   998     Goto(&promisehook_after); | 
|   962  |   999  | 
|   963     Bind(&if_customhandler); |  1000     Bind(&if_customhandler); | 
|   964     { |  1001     { | 
|   965       Node* const maybe_exception = CallJS(call_callable, context, on_resolve, |  1002       Node* const maybe_exception = | 
|   966                                            UndefinedConstant(), result); |  1003           CallJS(call_callable, context, deferred_on_resolve, | 
 |  1004                  UndefinedConstant(), result); | 
|   967       GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); |  1005       GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); | 
|   968       Goto(&promisehook_after); |  1006       Goto(&promisehook_after); | 
|   969     } |  1007     } | 
|   970   } |  1008   } | 
|   971  |  1009  | 
|   972   Bind(&if_rejectpromise); |  1010   Bind(&if_rejectpromise); | 
|   973   { |  1011   { | 
|   974     // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |  | 
|   975     Node* const key = HeapConstant(isolate->factory()->reject_string()); |  | 
|   976     Node* const on_reject = |  | 
|   977         CallStub(getproperty_callable, context, deferred, key); |  | 
|   978  |  | 
|   979     Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); |  1012     Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate); | 
|   980     CallStub(promise_handle_reject, context, deferred_promise, on_reject, |  1013     CallStub(promise_handle_reject, context, deferred_promise, | 
|   981              var_reason.value()); |  1014              deferred_on_reject, var_reason.value()); | 
|   982     Goto(&promisehook_after); |  1015     Goto(&promisehook_after); | 
|   983   } |  1016   } | 
|   984  |  1017  | 
|   985   Bind(&promisehook_after); |  1018   Bind(&promisehook_after); | 
|   986   { |  1019   { | 
|   987     GotoUnless(IsPromiseHookEnabled(), &debug_pop); |  1020     GotoUnless(IsPromiseHookEnabled(), &debug_pop); | 
|   988     CallRuntime(Runtime::kPromiseHookAfter, context, promise); |  1021     CallRuntime(Runtime::kPromiseHookAfter, context, promise); | 
|   989     Goto(&debug_pop); |  1022     Goto(&debug_pop); | 
|   990   } |  1023   } | 
|   991  |  1024  | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1031         CallStub(getproperty_callable, context, promise, then_str); |  1064         CallStub(getproperty_callable, context, promise, then_str); | 
|  1032     Callable call_callable = CodeFactory::Call(isolate); |  1065     Callable call_callable = CodeFactory::Call(isolate); | 
|  1033     Node* const result = |  1066     Node* const result = | 
|  1034         CallJS(call_callable, context, then, promise, on_resolve, on_reject); |  1067         CallJS(call_callable, context, then, promise, on_resolve, on_reject); | 
|  1035     Return(result); |  1068     Return(result); | 
|  1036   } |  1069   } | 
|  1037 } |  1070 } | 
|  1038  |  1071  | 
|  1039 }  // namespace internal |  1072 }  // namespace internal | 
|  1040 }  // namespace v8 |  1073 }  // namespace v8 | 
| OLD | NEW |