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" |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 Node* new_elements = AllocateFixedArray(kind, new_capacity, mode, flags); | 174 Node* new_elements = AllocateFixedArray(kind, new_capacity, mode, flags); |
175 | 175 |
176 CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode, | 176 CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode, |
177 mode); | 177 mode); |
178 StoreFixedArrayElement(new_elements, length, value, barrier_mode, | 178 StoreFixedArrayElement(new_elements, length, value, barrier_mode, |
179 additional_offset, mode); | 179 additional_offset, mode); |
180 | 180 |
181 StoreObjectField(promise, offset, new_elements); | 181 StoreObjectField(promise, offset, new_elements); |
182 } | 182 } |
183 | 183 |
184 Node* PromiseBuiltinsAssembler::InternalPromiseThen(Node* context, | |
185 Node* promise, | |
186 Node* on_resolve, | |
187 Node* on_reject) { | |
188 Isolate* isolate = this->isolate(); | |
189 | |
190 // 2. If IsPromise(promise) is false, throw a TypeError exception. | |
191 ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE, | |
192 "Promise.prototype.then"); | |
193 | |
194 Node* const native_context = LoadNativeContext(context); | |
195 Node* const promise_fun = | |
196 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | |
197 | |
198 // 3. Let C be ? SpeciesConstructor(promise, %Promise%). | |
199 Node* constructor = SpeciesConstructor(context, promise, promise_fun); | |
200 | |
201 // 4. Let resultCapability be ? NewPromiseCapability(C). | |
202 Callable call_callable = CodeFactory::Call(isolate); | |
203 Label fast_promise_capability(this), promise_capability(this), | |
204 perform_promise_then(this); | |
205 Variable var_deferred(this, MachineRepresentation::kTagged); | |
206 | |
207 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, | |
208 &promise_capability); | |
209 | |
210 // TODO(gsathya): Remove deferred object and move | |
211 // NewPromiseCapabability functions to TF. | |
212 Bind(&fast_promise_capability); | |
213 { | |
214 // TODO(gsathya): Move this to TF. | |
215 Node* const promise_internal_capability = LoadContextElement( | |
216 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); | |
217 Node* const capability = | |
218 CallJS(call_callable, context, promise_internal_capability, | |
219 UndefinedConstant(), promise); | |
220 var_deferred.Bind(capability); | |
221 Goto(&perform_promise_then); | |
222 } | |
223 | |
224 Bind(&promise_capability); | |
225 { | |
226 // TODO(gsathya): Move this to TF. | |
227 Node* const new_promise_capability = LoadContextElement( | |
228 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); | |
229 Node* const capability = | |
230 CallJS(call_callable, context, new_promise_capability, | |
231 UndefinedConstant(), constructor); | |
232 var_deferred.Bind(capability); | |
233 Goto(&perform_promise_then); | |
234 } | |
235 | |
236 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, | |
237 // resultCapability). | |
238 Bind(&perform_promise_then); | |
239 Node* const result = InternalPerformPromiseThen( | |
240 context, promise, on_resolve, on_reject, var_deferred.value()); | |
241 return result; | |
242 } | |
243 | |
184 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, | 244 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |
185 Node* promise, | 245 Node* promise, |
186 Node* on_resolve, | 246 Node* on_resolve, |
187 Node* on_reject, | 247 Node* on_reject, |
188 Node* deferred) { | 248 Node* deferred) { |
189 Node* const native_context = LoadNativeContext(context); | 249 Node* const native_context = LoadNativeContext(context); |
190 | 250 |
191 Variable var_on_resolve(this, MachineRepresentation::kTagged), | 251 Variable var_on_resolve(this, MachineRepresentation::kTagged), |
192 var_on_reject(this, MachineRepresentation::kTagged); | 252 var_on_reject(this, MachineRepresentation::kTagged); |
193 | 253 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
372 LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX); | 432 LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX); |
373 Node* const proto_map = LoadMap(LoadMapPrototype(map)); | 433 Node* const proto_map = LoadMap(LoadMapPrototype(map)); |
374 Node* const proto_has_initialmap = | 434 Node* const proto_has_initialmap = |
375 WordEqual(proto_map, initial_proto_initial_map); | 435 WordEqual(proto_map, initial_proto_initial_map); |
376 | 436 |
377 Branch(proto_has_initialmap, if_isunmodified, if_ismodified); | 437 Branch(proto_has_initialmap, if_isunmodified, if_ismodified); |
378 } | 438 } |
379 | 439 |
380 void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context, | 440 void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context, |
381 Node* promise, | 441 Node* promise, |
382 Node* result, | 442 Node* result) { |
383 Label* out) { | |
384 Isolate* isolate = this->isolate(); | 443 Isolate* isolate = this->isolate(); |
385 | 444 |
386 Variable var_reason(this, MachineRepresentation::kTagged), | 445 Variable var_reason(this, MachineRepresentation::kTagged), |
387 var_then(this, MachineRepresentation::kTagged); | 446 var_then(this, MachineRepresentation::kTagged); |
388 | 447 |
389 Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred), | 448 Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred), |
390 if_rejectpromise(this, Label::kDeferred); | 449 if_rejectpromise(this, Label::kDeferred), out(this); |
391 | 450 |
392 Label cycle_check(this); | 451 Label cycle_check(this); |
393 GotoUnless(IsPromiseHookEnabled(), &cycle_check); | 452 GotoUnless(IsPromiseHookEnabled(), &cycle_check); |
394 CallRuntime(Runtime::kPromiseHookResolve, context, promise); | 453 CallRuntime(Runtime::kPromiseHookResolve, context, promise); |
395 Goto(&cycle_check); | 454 Goto(&cycle_check); |
396 | 455 |
397 Bind(&cycle_check); | 456 Bind(&cycle_check); |
398 // 6. If SameValue(resolution, promise) is true, then | 457 // 6. If SameValue(resolution, promise) is true, then |
399 GotoIf(SameValue(promise, result, context), &if_cycle); | 458 GotoIf(SameValue(promise, result, context), &if_cycle); |
400 | 459 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
432 { | 491 { |
433 Label if_fulfilled(this), if_rejected(this); | 492 Label if_fulfilled(this), if_rejected(this); |
434 Branch(SmiEqual(SmiConstant(v8::Promise::kFulfilled), thenable_status), | 493 Branch(SmiEqual(SmiConstant(v8::Promise::kFulfilled), thenable_status), |
435 &if_fulfilled, &if_rejected); | 494 &if_fulfilled, &if_rejected); |
436 | 495 |
437 Bind(&if_fulfilled); | 496 Bind(&if_fulfilled); |
438 { | 497 { |
439 CallRuntime(Runtime::kPromiseFulfill, context, promise, | 498 CallRuntime(Runtime::kPromiseFulfill, context, promise, |
440 SmiConstant(v8::Promise::kFulfilled), thenable_value); | 499 SmiConstant(v8::Promise::kFulfilled), thenable_value); |
441 PromiseSetHasHandler(promise); | 500 PromiseSetHasHandler(promise); |
442 Goto(out); | 501 Goto(&out); |
443 } | 502 } |
444 | 503 |
445 Bind(&if_rejected); | 504 Bind(&if_rejected); |
446 { | 505 { |
447 Label reject(this); | 506 Label reject(this); |
448 Node* const has_handler = PromiseHasHandler(result); | 507 Node* const has_handler = PromiseHasHandler(result); |
449 | 508 |
450 // Promise has already been rejected, but had no handler. | 509 // Promise has already been rejected, but had no handler. |
451 // Revoke previously triggered reject event. | 510 // Revoke previously triggered reject event. |
452 GotoIf(has_handler, &reject); | 511 GotoIf(has_handler, &reject); |
453 CallRuntime(Runtime::kPromiseRevokeReject, context, result); | 512 CallRuntime(Runtime::kPromiseRevokeReject, context, result); |
454 Goto(&reject); | 513 Goto(&reject); |
455 | 514 |
456 Bind(&reject); | 515 Bind(&reject); |
457 // Don't cause a debug event as this case is forwarding a rejection | 516 // Don't cause a debug event as this case is forwarding a rejection |
458 CallRuntime(Runtime::kPromiseReject, context, promise, thenable_value, | 517 CallRuntime(Runtime::kPromiseReject, context, promise, thenable_value, |
459 FalseConstant()); | 518 FalseConstant()); |
460 PromiseSetHasHandler(result); | 519 PromiseSetHasHandler(result); |
461 Goto(out); | 520 Goto(&out); |
462 } | 521 } |
463 } | 522 } |
464 } | 523 } |
465 | 524 |
466 Bind(&if_notnativepromise); | 525 Bind(&if_notnativepromise); |
467 { | 526 { |
468 // 8. Let then be Get(resolution, "then"). | 527 // 8. Let then be Get(resolution, "then"). |
469 Node* const then_str = HeapConstant(isolate->factory()->then_string()); | 528 Node* const then_str = HeapConstant(isolate->factory()->then_string()); |
470 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 529 Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
471 Node* const then = | 530 Node* const then = |
(...skipping 22 matching lines...) Expand all Loading... | |
494 CallRuntime(Runtime::kSetProperty, context, result, key, promise, | 553 CallRuntime(Runtime::kSetProperty, context, result, key, promise, |
495 SmiConstant(STRICT)); | 554 SmiConstant(STRICT)); |
496 Goto(&enqueue); | 555 Goto(&enqueue); |
497 | 556 |
498 // 12. Perform EnqueueJob("PromiseJobs", | 557 // 12. Perform EnqueueJob("PromiseJobs", |
499 // PromiseResolveThenableJob, « promise, resolution, thenAction | 558 // PromiseResolveThenableJob, « promise, resolution, thenAction |
500 // »). | 559 // »). |
501 Bind(&enqueue); | 560 Bind(&enqueue); |
502 CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise, | 561 CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise, |
503 result, var_then.value()); | 562 result, var_then.value()); |
504 Goto(out); | 563 Goto(&out); |
505 } | 564 } |
506 | 565 |
507 // 7.b Return FulfillPromise(promise, resolution). | 566 // 7.b Return FulfillPromise(promise, resolution). |
508 Bind(&fulfill); | 567 Bind(&fulfill); |
509 { | 568 { |
510 CallRuntime(Runtime::kPromiseFulfill, context, promise, | 569 CallRuntime(Runtime::kPromiseFulfill, context, promise, |
511 SmiConstant(v8::Promise::kFulfilled), result); | 570 SmiConstant(v8::Promise::kFulfilled), result); |
512 Goto(out); | 571 Goto(&out); |
513 } | 572 } |
514 | 573 |
515 Bind(&if_cycle); | 574 Bind(&if_cycle); |
516 { | 575 { |
517 // 6.a Let selfResolutionError be a newly created TypeError object. | 576 // 6.a Let selfResolutionError be a newly created TypeError object. |
518 Node* const message_id = SmiConstant(MessageTemplate::kPromiseCyclic); | 577 Node* const message_id = SmiConstant(MessageTemplate::kPromiseCyclic); |
519 Node* const error = | 578 Node* const error = |
520 CallRuntime(Runtime::kNewTypeError, context, message_id, result); | 579 CallRuntime(Runtime::kNewTypeError, context, message_id, result); |
521 var_reason.Bind(error); | 580 var_reason.Bind(error); |
522 | 581 |
523 // 6.b Return RejectPromise(promise, selfResolutionError). | 582 // 6.b Return RejectPromise(promise, selfResolutionError). |
524 Goto(&if_rejectpromise); | 583 Goto(&if_rejectpromise); |
525 } | 584 } |
526 | 585 |
527 // 9.a Return RejectPromise(promise, then.[[Value]]). | 586 // 9.a Return RejectPromise(promise, then.[[Value]]). |
528 Bind(&if_rejectpromise); | 587 Bind(&if_rejectpromise); |
529 { | 588 { |
530 CallRuntime(Runtime::kPromiseReject, context, promise, var_reason.value(), | 589 CallRuntime(Runtime::kPromiseReject, context, promise, var_reason.value(), |
531 TrueConstant()); | 590 TrueConstant()); |
532 Goto(out); | 591 Goto(&out); |
533 } | 592 } |
593 | |
594 Bind(&out); | |
595 return; | |
jgruber
2016/12/21 06:55:29
Nit: Please remove this.
gsathya
2016/12/21 17:27:54
Done.
| |
534 } | 596 } |
535 | 597 |
536 // ES#sec-promise-reject-functions | 598 // ES#sec-promise-reject-functions |
537 // Promise Reject Functions | 599 // Promise Reject Functions |
538 BUILTIN(PromiseRejectClosure) { | 600 BUILTIN(PromiseRejectClosure) { |
539 HandleScope scope(isolate); | 601 HandleScope scope(isolate); |
540 | 602 |
541 Handle<Context> context(isolate->context(), isolate); | 603 Handle<Context> context(isolate->context(), isolate); |
542 | 604 |
543 if (PromiseUtils::HasAlreadyVisited(context)) { | 605 if (PromiseUtils::HasAlreadyVisited(context)) { |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
762 // TODO(gsathya): This is unused, but value is returned according to spec. | 824 // TODO(gsathya): This is unused, but value is returned according to spec. |
763 Return(result); | 825 Return(result); |
764 } | 826 } |
765 | 827 |
766 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { | 828 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { |
767 // 1. Let promise be the this value. | 829 // 1. Let promise be the this value. |
768 Node* const promise = Parameter(0); | 830 Node* const promise = Parameter(0); |
769 Node* const on_resolve = Parameter(1); | 831 Node* const on_resolve = Parameter(1); |
770 Node* const on_reject = Parameter(2); | 832 Node* const on_reject = Parameter(2); |
771 Node* const context = Parameter(5); | 833 Node* const context = Parameter(5); |
772 Isolate* isolate = this->isolate(); | |
773 | 834 |
774 // 2. If IsPromise(promise) is false, throw a TypeError exception. | 835 Node* const result = |
775 ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE, | 836 InternalPromiseThen(context, promise, on_resolve, on_reject); |
776 "Promise.prototype.then"); | |
777 | |
778 Node* const native_context = LoadNativeContext(context); | |
779 Node* const promise_fun = | |
780 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | |
781 | |
782 // 3. Let C be ? SpeciesConstructor(promise, %Promise%). | |
783 Node* constructor = SpeciesConstructor(context, promise, promise_fun); | |
784 | |
785 // 4. Let resultCapability be ? NewPromiseCapability(C). | |
786 Callable call_callable = CodeFactory::Call(isolate); | |
787 Label fast_promise_capability(this), promise_capability(this), | |
788 perform_promise_then(this); | |
789 Variable var_deferred(this, MachineRepresentation::kTagged); | |
790 | |
791 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, | |
792 &promise_capability); | |
793 | |
794 // TODO(gsathya): Remove deferred object and move | |
795 // NewPromiseCapabability functions to TF. | |
796 Bind(&fast_promise_capability); | |
797 { | |
798 // TODO(gsathya): Move this to TF. | |
799 Node* const promise_internal_capability = LoadContextElement( | |
800 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); | |
801 Node* const capability = | |
802 CallJS(call_callable, context, promise_internal_capability, | |
803 UndefinedConstant(), promise); | |
804 var_deferred.Bind(capability); | |
805 Goto(&perform_promise_then); | |
806 } | |
807 | |
808 Bind(&promise_capability); | |
809 { | |
810 // TODO(gsathya): Move this to TF. | |
811 Node* const new_promise_capability = LoadContextElement( | |
812 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); | |
813 Node* const capability = | |
814 CallJS(call_callable, context, new_promise_capability, | |
815 UndefinedConstant(), constructor); | |
816 var_deferred.Bind(capability); | |
817 Goto(&perform_promise_then); | |
818 } | |
819 | |
820 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, | |
821 // resultCapability). | |
822 Bind(&perform_promise_then); | |
823 Node* const result = InternalPerformPromiseThen( | |
824 context, promise, on_resolve, on_reject, var_deferred.value()); | |
825 Return(result); | 837 Return(result); |
826 } | 838 } |
827 | 839 |
828 // ES#sec-promise-resolve-functions | 840 // ES#sec-promise-resolve-functions |
829 // Promise Resolve Functions | 841 // Promise Resolve Functions |
830 TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) { | 842 TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) { |
831 Node* const value = Parameter(1); | 843 Node* const value = Parameter(1); |
832 Node* const context = Parameter(4); | 844 Node* const context = Parameter(4); |
833 | 845 |
834 Label out(this); | 846 Label out(this); |
835 | 847 |
836 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | 848 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. |
837 Node* const has_already_visited_slot = | 849 Node* const has_already_visited_slot = |
838 IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot); | 850 IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot); |
839 | 851 |
840 Node* const has_already_visited = | 852 Node* const has_already_visited = |
841 LoadFixedArrayElement(context, has_already_visited_slot); | 853 LoadFixedArrayElement(context, has_already_visited_slot); |
842 | 854 |
843 // 4. If alreadyResolved.[[Value]] is true, return undefined. | 855 // 4. If alreadyResolved.[[Value]] is true, return undefined. |
844 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); | 856 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); |
845 | 857 |
846 // 5.Set alreadyResolved.[[Value]] to true. | 858 // 5.Set alreadyResolved.[[Value]] to true. |
847 StoreFixedArrayElement(context, has_already_visited_slot, SmiConstant(1)); | 859 StoreFixedArrayElement(context, has_already_visited_slot, SmiConstant(1)); |
848 | 860 |
849 // 2. Let promise be F.[[Promise]]. | 861 // 2. Let promise be F.[[Promise]]. |
850 Node* const promise = LoadFixedArrayElement( | 862 Node* const promise = LoadFixedArrayElement( |
851 context, IntPtrConstant(PromiseUtils::kPromiseSlot)); | 863 context, IntPtrConstant(PromiseUtils::kPromiseSlot)); |
852 | 864 |
853 InternalResolvePromise(context, promise, value, &out); | 865 InternalResolvePromise(context, promise, value); |
866 Return(UndefinedConstant()); | |
854 | 867 |
855 Bind(&out); | 868 Bind(&out); |
856 Return(UndefinedConstant()); | 869 Return(UndefinedConstant()); |
857 } | 870 } |
858 | 871 |
859 TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { | 872 TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { |
860 Node* const promise = Parameter(1); | 873 Node* const promise = Parameter(1); |
861 Node* const result = Parameter(2); | 874 Node* const result = Parameter(2); |
862 Node* const context = Parameter(5); | 875 Node* const context = Parameter(5); |
863 | 876 |
864 Label out(this); | 877 InternalResolvePromise(context, promise, result); |
865 InternalResolvePromise(context, promise, result, &out); | |
866 | |
867 Bind(&out); | |
868 Return(UndefinedConstant()); | 878 Return(UndefinedConstant()); |
869 } | 879 } |
870 | 880 |
871 TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) { | 881 TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) { |
872 typedef PromiseHandleRejectDescriptor Descriptor; | 882 typedef PromiseHandleRejectDescriptor Descriptor; |
873 | 883 |
874 Node* const promise = Parameter(Descriptor::kPromise); | 884 Node* const promise = Parameter(Descriptor::kPromise); |
875 Node* const on_reject = Parameter(Descriptor::kOnReject); | 885 Node* const on_reject = Parameter(Descriptor::kOnReject); |
876 Node* const exception = Parameter(Descriptor::kException); | 886 Node* const exception = Parameter(Descriptor::kException); |
877 Node* const context = Parameter(Descriptor::kContext); | 887 Node* const context = Parameter(Descriptor::kContext); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
939 | 949 |
940 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | 950 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |
941 Node* const key = HeapConstant(isolate->factory()->resolve_string()); | 951 Node* const key = HeapConstant(isolate->factory()->resolve_string()); |
942 Node* const on_resolve = | 952 Node* const on_resolve = |
943 CallStub(getproperty_callable, context, deferred, key); | 953 CallStub(getproperty_callable, context, deferred, key); |
944 | 954 |
945 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); | 955 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); |
946 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); | 956 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); |
947 | 957 |
948 Bind(&if_internalhandler); | 958 Bind(&if_internalhandler); |
949 InternalResolvePromise(context, deferred_promise, result, | 959 InternalResolvePromise(context, deferred_promise, result); |
950 &promisehook_after); | 960 Goto(&promisehook_after); |
951 | 961 |
952 Bind(&if_customhandler); | 962 Bind(&if_customhandler); |
953 { | 963 { |
954 Node* const maybe_exception = CallJS(call_callable, context, on_resolve, | 964 Node* const maybe_exception = CallJS(call_callable, context, on_resolve, |
955 UndefinedConstant(), result); | 965 UndefinedConstant(), result); |
956 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); | 966 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); |
957 Goto(&promisehook_after); | 967 Goto(&promisehook_after); |
958 } | 968 } |
959 } | 969 } |
960 | 970 |
(...skipping 23 matching lines...) Expand all Loading... | |
984 | 994 |
985 GotoUnless(is_debug_active, &out); | 995 GotoUnless(is_debug_active, &out); |
986 CallRuntime(Runtime::kDebugPopPromise, context); | 996 CallRuntime(Runtime::kDebugPopPromise, context); |
987 Goto(&out); | 997 Goto(&out); |
988 | 998 |
989 Bind(&out); | 999 Bind(&out); |
990 Return(UndefinedConstant()); | 1000 Return(UndefinedConstant()); |
991 } | 1001 } |
992 } | 1002 } |
993 | 1003 |
1004 TF_BUILTIN(PromiseCatch, PromiseBuiltinsAssembler) { | |
jgruber
2016/12/21 06:55:29
Could you add a comment linking to the spec (same
gsathya
2016/12/21 17:27:54
Done.
| |
1005 // 1. Let promise be the this value. | |
1006 Node* const promise = Parameter(0); | |
1007 Node* const on_resolve = UndefinedConstant(); | |
1008 Node* const on_reject = Parameter(1); | |
1009 Node* const context = Parameter(4); | |
1010 | |
1011 Label if_internalthen(this), if_customthen(this, Label::kDeferred); | |
1012 BranchIfFastPath(context, promise, &if_internalthen, &if_customthen); | |
1013 | |
1014 Bind(&if_internalthen); | |
1015 { | |
1016 Node* const result = | |
1017 InternalPromiseThen(context, promise, on_resolve, on_reject); | |
1018 Return(result); | |
1019 } | |
1020 | |
1021 Bind(&if_customthen); | |
1022 { | |
1023 Isolate* isolate = this->isolate(); | |
1024 Node* const then_str = HeapConstant(isolate->factory()->then_string()); | |
1025 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | |
1026 Node* const then = | |
1027 CallStub(getproperty_callable, context, promise, then_str); | |
1028 Callable call_callable = CodeFactory::Call(isolate); | |
1029 Node* const result = | |
1030 CallJS(call_callable, context, then, promise, on_resolve, on_reject); | |
1031 Return(result); | |
1032 } | |
1033 } | |
1034 | |
994 } // namespace internal | 1035 } // namespace internal |
995 } // namespace v8 | 1036 } // namespace v8 |
OLD | NEW |