| 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-constructor.h" |     6 #include "src/builtins/builtins-constructor.h" | 
|     7 #include "src/builtins/builtins-utils.h" |     7 #include "src/builtins/builtins-utils.h" | 
|     8 #include "src/builtins/builtins.h" |     8 #include "src/builtins/builtins.h" | 
|     9 #include "src/code-factory.h" |     9 #include "src/code-factory.h" | 
|    10 #include "src/code-stub-assembler.h" |    10 #include "src/code-stub-assembler.h" | 
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   598         } |   598         } | 
|   599       } |   599       } | 
|   600     } |   600     } | 
|   601   } |   601   } | 
|   602  |   602  | 
|   603   Bind(&out); |   603   Bind(&out); | 
|   604   PromiseSetHasHandler(promise); |   604   PromiseSetHasHandler(promise); | 
|   605   return deferred_promise; |   605   return deferred_promise; | 
|   606 } |   606 } | 
|   607  |   607  | 
 |   608 void PromiseBuiltinsAssembler::FastPerformPromiseThen(Node* context, | 
 |   609                                                       Node* promise, | 
 |   610                                                       Node* on_resolve, | 
 |   611                                                       Node* on_reject, | 
 |   612                                                       Node* result_promise) { | 
 |   613   CSA_SLOW_ASSERT(this, HasInstanceType(promise, JS_PROMISE_TYPE)); | 
 |   614   if (result_promise != nullptr) { | 
 |   615     CSA_SLOW_ASSERT(this, HasInstanceType(result_promise, JS_PROMISE_TYPE)); | 
 |   616   } | 
 |   617  | 
 |   618   if (on_resolve == nullptr) { | 
 |   619     on_resolve = LoadContextElement(LoadNativeContext(context), | 
 |   620                                     Context::PROMISE_ID_RESOLVE_HANDLER_INDEX); | 
 |   621   } else if (on_reject == nullptr) { | 
 |   622     on_reject = LoadContextElement(LoadNativeContext(context), | 
 |   623                                    Context::PROMISE_ID_REJECT_HANDLER_INDEX); | 
 |   624   } | 
 |   625   CSA_SLOW_ASSERT(this, IsJSFunction(on_resolve)); | 
 |   626   CSA_SLOW_ASSERT(this, IsJSFunction(on_reject)); | 
 |   627  | 
 |   628   Label if_ispending(this), if_isfulfilled(this), merge(this); | 
 |   629  | 
 |   630   Node* const status = LoadObjectField(promise, JSPromise::kStatusOffset); | 
 |   631   Branch(SmiEqual(status, SmiConstant(v8::Promise::kPending)), &if_ispending, | 
 |   632          &if_isfulfilled); | 
 |   633  | 
 |   634   Bind(&if_ispending); | 
 |   635   { | 
 |   636     // Assert: There are no callbacks attached. | 
 |   637     CSA_SLOW_ASSERT(this, IsUndefined(LoadObjectField( | 
 |   638                               promise, JSPromise::kDeferredPromiseOffset))); | 
 |   639  | 
 |   640     // Store callbacks directly in the slots. | 
 |   641     StoreObjectField(promise, JSPromise::kDeferredPromiseOffset, | 
 |   642                      result_promise ? result_promise : UndefinedConstant()); | 
 |   643     StoreObjectField(promise, JSPromise::kFulfillReactionsOffset, on_resolve); | 
 |   644     StoreObjectField(promise, JSPromise::kRejectReactionsOffset, on_reject); | 
 |   645     Goto(&merge); | 
 |   646   } | 
 |   647  | 
 |   648   Bind(&if_isfulfilled); | 
 |   649   { | 
 |   650     Node* const handler = | 
 |   651         Select(SmiEqual(status, SmiConstant(v8::Promise::kFulfilled)), | 
 |   652                [&]() -> Node* { return on_resolve; }, | 
 |   653                [&]() -> Node* { | 
 |   654                  Label done(this); | 
 |   655                  GotoIf(PromiseHasHandler(promise), &done); | 
 |   656                  // TODO(gsathya): Fold these runtime calls and move to TF. | 
 |   657                  CallRuntime(Runtime::kPromiseRevokeReject, context, promise); | 
 |   658                  Goto(&done); | 
 |   659                  Bind(&done); | 
 |   660                  return on_reject; | 
 |   661                }, | 
 |   662                MachineRepresentation::kTagged); | 
 |   663  | 
 |   664     Node* const result = LoadObjectField(promise, JSPromise::kResultOffset); | 
 |   665     Node* info = AllocatePromiseReactionJobInfo( | 
 |   666         promise, result, handler, | 
 |   667         result_promise ? result_promise : UndefinedConstant(), | 
 |   668         UndefinedConstant(), UndefinedConstant(), context); | 
 |   669     // TODO(gsathya): Move this to TF | 
 |   670     CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info, status); | 
 |   671     Goto(&merge); | 
 |   672   } | 
 |   673  | 
 |   674   Bind(&merge); | 
 |   675 } | 
 |   676  | 
|   608 // Promise fast path implementations rely on unmodified JSPromise instances. |   677 // Promise fast path implementations rely on unmodified JSPromise instances. | 
|   609 // We use a fairly coarse granularity for this and simply check whether both |   678 // We use a fairly coarse granularity for this and simply check whether both | 
|   610 // the promise itself is unmodified (i.e. its map has not changed) and its |   679 // the promise itself is unmodified (i.e. its map has not changed) and its | 
|   611 // prototype is unmodified. |   680 // prototype is unmodified. | 
|   612 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp |   681 // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp | 
|   613 void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise, |   682 void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise, | 
|   614                                                 Label* if_isunmodified, |   683                                                 Label* if_isunmodified, | 
|   615                                                 Label* if_ismodified) { |   684                                                 Label* if_ismodified) { | 
|   616   Node* const native_context = LoadNativeContext(context); |   685   Node* const native_context = LoadNativeContext(context); | 
|   617   Node* const promise_fun = |   686   Node* const promise_fun = | 
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1069 } |  1138 } | 
|  1070  |  1139  | 
|  1071 TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) { |  1140 TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) { | 
|  1072   Node* const promise = Parameter(1); |  1141   Node* const promise = Parameter(1); | 
|  1073   Node* const on_resolve = Parameter(2); |  1142   Node* const on_resolve = Parameter(2); | 
|  1074   Node* const on_reject = Parameter(3); |  1143   Node* const on_reject = Parameter(3); | 
|  1075   Node* const deferred_promise = Parameter(4); |  1144   Node* const deferred_promise = Parameter(4); | 
|  1076   Node* const context = Parameter(7); |  1145   Node* const context = Parameter(7); | 
|  1077  |  1146  | 
|  1078   // No deferred_on_resolve/deferred_on_reject because this is just an |  1147   // No deferred_on_resolve/deferred_on_reject because this is just an | 
|  1079   // internal promise created by async-await. |  1148   // internal promise created by async-await / async-iteration. | 
|  1080   Node* const result = InternalPerformPromiseThen( |  1149   Node* const result = InternalPerformPromiseThen( | 
|  1081       context, promise, on_resolve, on_reject, deferred_promise, |  1150       context, promise, on_resolve, on_reject, deferred_promise, | 
|  1082       UndefinedConstant(), UndefinedConstant()); |  1151       UndefinedConstant(), UndefinedConstant()); | 
|  1083  |  1152  | 
|  1084   // TODO(gsathya): This is unused, but value is returned according to spec. |  1153   // TODO(gsathya): This is unused, but value is returned according to spec. | 
|  1085   Return(result); |  1154   Return(result); | 
|  1086 } |  1155 } | 
|  1087  |  1156  | 
|  1088 // ES#sec-promise.prototype.then |  1157 // ES#sec-promise.prototype.then | 
|  1089 // Promise.prototype.catch ( onFulfilled, onRejected ) |  1158 // Promise.prototype.catch ( onFulfilled, onRejected ) | 
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1449  |  1518  | 
|  1450     // 5. Return promiseCapability.[[Promise]]. |  1519     // 5. Return promiseCapability.[[Promise]]. | 
|  1451     Node* const promise = |  1520     Node* const promise = | 
|  1452         LoadObjectField(capability, JSPromiseCapability::kPromiseOffset); |  1521         LoadObjectField(capability, JSPromiseCapability::kPromiseOffset); | 
|  1453     Return(promise); |  1522     Return(promise); | 
|  1454   } |  1523   } | 
|  1455 } |  1524 } | 
|  1456  |  1525  | 
|  1457 }  // namespace internal |  1526 }  // namespace internal | 
|  1458 }  // namespace v8 |  1527 }  // namespace v8 | 
| OLD | NEW |