Chromium Code Reviews| 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 |