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 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
431 append_callbacks(this); | 431 append_callbacks(this); |
432 GotoIf(TaggedIsSmi(on_resolve), &if_onresolvenotcallable); | 432 GotoIf(TaggedIsSmi(on_resolve), &if_onresolvenotcallable); |
433 | 433 |
434 Isolate* isolate = this->isolate(); | 434 Isolate* isolate = this->isolate(); |
435 Node* const on_resolve_map = LoadMap(on_resolve); | 435 Node* const on_resolve_map = LoadMap(on_resolve); |
436 Branch(IsCallableMap(on_resolve_map), &onrejectcheck, | 436 Branch(IsCallableMap(on_resolve_map), &onrejectcheck, |
437 &if_onresolvenotcallable); | 437 &if_onresolvenotcallable); |
438 | 438 |
439 Bind(&if_onresolvenotcallable); | 439 Bind(&if_onresolvenotcallable); |
440 { | 440 { |
441 Isolate* isolate = this->isolate(); | |
442 Node* const default_resolve_handler_symbol = HeapConstant( | 441 Node* const default_resolve_handler_symbol = HeapConstant( |
443 isolate->factory()->promise_default_resolve_handler_symbol()); | 442 isolate->factory()->promise_default_resolve_handler_symbol()); |
444 var_on_resolve.Bind(default_resolve_handler_symbol); | 443 var_on_resolve.Bind(default_resolve_handler_symbol); |
445 Goto(&onrejectcheck); | 444 Goto(&onrejectcheck); |
446 } | 445 } |
447 | 446 |
448 Bind(&onrejectcheck); | 447 Bind(&onrejectcheck); |
449 { | 448 { |
450 Label if_onrejectnotcallable(this); | 449 Label if_onrejectnotcallable(this); |
451 GotoIf(TaggedIsSmi(on_reject), &if_onrejectnotcallable); | 450 GotoIf(TaggedIsSmi(on_reject), &if_onrejectnotcallable); |
(...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1557 TF_BUILTIN(InternalPromiseReject, PromiseBuiltinsAssembler) { | 1556 TF_BUILTIN(InternalPromiseReject, PromiseBuiltinsAssembler) { |
1558 Node* const promise = Parameter(1); | 1557 Node* const promise = Parameter(1); |
1559 Node* const reason = Parameter(2); | 1558 Node* const reason = Parameter(2); |
1560 Node* const debug_event = Parameter(3); | 1559 Node* const debug_event = Parameter(3); |
1561 Node* const context = Parameter(6); | 1560 Node* const context = Parameter(6); |
1562 | 1561 |
1563 InternalPromiseReject(context, promise, reason, debug_event); | 1562 InternalPromiseReject(context, promise, reason, debug_event); |
1564 Return(UndefinedConstant()); | 1563 Return(UndefinedConstant()); |
1565 } | 1564 } |
1566 | 1565 |
1566 Node* PromiseBuiltinsAssembler::CreatePromiseFinallyContext( | |
1567 Node* on_finally, Node* native_context) { | |
1568 Node* const context = | |
1569 CreatePromiseContext(native_context, kOnFinallyContextLength); | |
1570 StoreContextElementNoWriteBarrier(context, kOnFinallySlot, on_finally); | |
1571 return context; | |
1572 } | |
1573 | |
1574 std::pair<Node*, Node*> PromiseBuiltinsAssembler::CreatePromiseFinallyFunctions( | |
1575 Node* on_finally, Node* native_context) { | |
1576 Node* const promise_context = | |
1577 CreatePromiseFinallyContext(on_finally, native_context); | |
1578 Node* const map = LoadContextElement( | |
1579 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); | |
1580 Node* const then_finally_info = LoadContextElement( | |
1581 native_context, Context::PROMISE_THEN_FINALLY_SHARED_FUN); | |
1582 Node* const then_finally = AllocateFunctionWithMapAndContext( | |
1583 map, then_finally_info, promise_context); | |
1584 Node* const catch_finally_info = LoadContextElement( | |
1585 native_context, Context::PROMISE_CATCH_FINALLY_SHARED_FUN); | |
1586 Node* const catch_finally = AllocateFunctionWithMapAndContext( | |
1587 map, catch_finally_info, promise_context); | |
1588 return std::make_pair(then_finally, catch_finally); | |
1589 } | |
1590 | |
1591 TF_BUILTIN(PromiseValueThunkFinally, PromiseBuiltinsAssembler) { | |
1592 Node* const context = Parameter(3); | |
1593 | |
1594 Node* const value = LoadContextElement(context, kOnFinallySlot); | |
1595 Return(value); | |
1596 } | |
1597 | |
1598 Node* PromiseBuiltinsAssembler::CreateValueThunkFunctionContext( | |
1599 Node* value, Node* native_context) { | |
1600 Node* const context = | |
1601 CreatePromiseContext(native_context, kOnFinallyContextLength); | |
1602 StoreContextElementNoWriteBarrier(context, kOnFinallySlot, value); | |
1603 return context; | |
1604 } | |
1605 | |
1606 Node* PromiseBuiltinsAssembler::CreateValueThunkFunction(Node* value, | |
neis
2017/02/15 12:40:39
nit: s/Function//
gsathya
2017/02/16 15:05:29
Leaving as such to be consistent with CreatePromis
| |
1607 Node* native_context) { | |
1608 Node* const value_thunk_context = | |
1609 CreateValueThunkFunctionContext(value, native_context); | |
1610 Node* const map = LoadContextElement( | |
1611 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); | |
1612 Node* const value_thunk_info = LoadContextElement( | |
1613 native_context, Context::PROMISE_VALUE_THUNK_FINALLY_SHARED_FUN); | |
1614 Node* const value_thunk = AllocateFunctionWithMapAndContext( | |
1615 map, value_thunk_info, value_thunk_context); | |
1616 return value_thunk; | |
1617 } | |
1618 | |
1619 TF_BUILTIN(PromiseThenFinally, PromiseBuiltinsAssembler) { | |
1620 Node* const parent = Parameter(0); | |
neis
2017/02/15 12:40:39
This will typically be undefined.
gsathya
2017/02/16 15:05:29
Done.
| |
1621 Node* const value = Parameter(1); | |
1622 Node* const context = Parameter(4); | |
neis
2017/02/15 12:40:39
Maybe use CSA_ASSERT_JS_ARGC_EQ here and elsewhere
gsathya
2017/02/16 15:05:30
Done.
| |
1623 | |
1624 Node* const on_finally = LoadContextElement(context, kOnFinallySlot); | |
1625 | |
1626 // 2.a Let result be ? Call(onFinally, undefined). | |
1627 Callable call_callable = CodeFactory::Call(isolate()); | |
1628 Node* result = | |
1629 CallJS(call_callable, context, on_finally, UndefinedConstant()); | |
1630 | |
1631 // 2.b Let promise be ! PromiseResolve( %Promise%, result). | |
1632 Node* const promise = AllocateAndInitJSPromise(context, parent); | |
1633 InternalResolvePromise(context, promise, result); | |
1634 | |
1635 // 2.c Let valueThunk be equivalent to a function that returns value. | |
1636 Node* native_context = LoadNativeContext(context); | |
1637 Node* const value_thunk = CreateValueThunkFunction(value, native_context); | |
1638 | |
1639 // 2.d Let promiseCapability be ! NewPromiseCapability( %Promise%). | |
1640 Node* const promise_capability = AllocateAndInitJSPromise(context, promise); | |
1641 | |
1642 // 2.e Return PerformPromiseThen(promise, valueThunk, undefined, | |
1643 // promiseCapability). | |
1644 InternalPerformPromiseThen(context, promise, value_thunk, UndefinedConstant(), | |
1645 promise_capability, UndefinedConstant(), | |
1646 UndefinedConstant()); | |
1647 Return(promise_capability); | |
1648 } | |
1649 | |
1650 TF_BUILTIN(PromiseThrowerFinally, PromiseBuiltinsAssembler) { | |
1651 Node* const context = Parameter(3); | |
1652 | |
1653 Node* const reason = LoadContextElement(context, kOnFinallySlot); | |
1654 CallRuntime(Runtime::kThrow, context, reason); | |
1655 Return(UndefinedConstant()); | |
1656 } | |
1657 | |
1658 Node* PromiseBuiltinsAssembler::CreateThrowerFunctionContext( | |
1659 Node* reason, Node* native_context) { | |
1660 Node* const context = | |
1661 CreatePromiseContext(native_context, kOnFinallyContextLength); | |
1662 StoreContextElementNoWriteBarrier(context, kOnFinallySlot, reason); | |
1663 return context; | |
1664 } | |
1665 | |
1666 Node* PromiseBuiltinsAssembler::CreateThrowerFunction(Node* reason, | |
1667 Node* native_context) { | |
neis
2017/02/15 12:40:39
nit: s/Function//
gsathya
2017/02/16 15:05:29
Same as CreateValueThunkFunction
| |
1668 Node* const thrower_context = | |
1669 CreateThrowerFunctionContext(reason, native_context); | |
1670 Node* const map = LoadContextElement( | |
1671 native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); | |
1672 Node* const thrower_info = LoadContextElement( | |
1673 native_context, Context::PROMISE_THROWER_FINALLY_SHARED_FUN); | |
1674 Node* const thrower = | |
1675 AllocateFunctionWithMapAndContext(map, thrower_info, thrower_context); | |
1676 return thrower; | |
1677 } | |
1678 | |
1679 TF_BUILTIN(PromiseCatchFinally, PromiseBuiltinsAssembler) { | |
1680 Node* const parent = Parameter(0); | |
1681 Node* const value = Parameter(1); | |
neis
2017/02/15 12:40:39
nit: s/value/reason/
gsathya
2017/02/16 15:05:30
Done.
| |
1682 Node* const context = Parameter(4); | |
1683 | |
1684 Node* const on_finally = LoadContextElement(context, kOnFinallySlot); | |
1685 | |
1686 // 2.a Let result be ? Call(onFinally, undefined). | |
1687 Callable call_callable = CodeFactory::Call(isolate()); | |
1688 Node* result = | |
1689 CallJS(call_callable, context, on_finally, UndefinedConstant()); | |
1690 | |
1691 // 2.b Let promise be ! PromiseResolve( %Promise%, result). | |
1692 Node* const promise = AllocateAndInitJSPromise(context, parent); | |
1693 InternalResolvePromise(context, promise, result); | |
1694 | |
1695 // 2.c Let thrower be equivalent to a function that throws reason. | |
1696 Node* native_context = LoadNativeContext(context); | |
1697 Node* const thrower = CreateThrowerFunction(value, native_context); | |
1698 | |
1699 // 2.d Let promiseCapability be ! NewPromiseCapability( %Promise%). | |
1700 Node* const promise_capability = AllocateAndInitJSPromise(context, promise); | |
1701 | |
1702 // 2.e Return PerformPromiseThen(promise, thrower, undefined, | |
1703 // promiseCapability). | |
1704 InternalPerformPromiseThen(context, promise, thrower, UndefinedConstant(), | |
1705 promise_capability, UndefinedConstant(), | |
1706 UndefinedConstant()); | |
1707 Return(result); | |
neis
2017/02/15 12:40:39
Ouch! Return(promise_capability)
This suggests a
gsathya
2017/02/16 15:05:29
Done.
| |
1708 } | |
1709 | |
1710 TF_BUILTIN(PromiseFinally, PromiseBuiltinsAssembler) { | |
1711 // 1. Let promise be the this value. | |
1712 Node* const promise = Parameter(0); | |
1713 Node* const on_finally = Parameter(1); | |
1714 Node* const context = Parameter(4); | |
1715 | |
1716 // 2. If IsPromise(promise) is false, throw a TypeError exception. | |
1717 ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE, | |
1718 "Promise.prototype.finally"); | |
1719 | |
1720 Variable var_then_finally(this, MachineRepresentation::kTagged), | |
1721 var_catch_finally(this, MachineRepresentation::kTagged); | |
1722 | |
1723 Label if_notcallable(this, Label::kDeferred), perform_finally(this); | |
1724 | |
1725 GotoIf(TaggedIsSmi(on_finally), &if_notcallable); | |
1726 Node* const on_finally_map = LoadMap(on_finally); | |
1727 GotoUnless(IsCallableMap(on_finally_map), &if_notcallable); | |
1728 | |
1729 // 3. Let thenFinally be ! CreateThenFinally(onFinally). | |
neis
2017/02/15 12:40:39
The few lines above are already part of steps 3 an
gsathya
2017/02/16 15:05:29
Done.
| |
1730 // 4. Let catchFinally be ! CreateCatchFinally(onFinally). | |
1731 Node* const native_context = LoadNativeContext(context); | |
1732 Node* then_finally = nullptr; | |
1733 Node* catch_finally = nullptr; | |
1734 std::tie(then_finally, catch_finally) = | |
1735 CreatePromiseFinallyFunctions(on_finally, native_context); | |
1736 var_then_finally.Bind(then_finally); | |
1737 var_catch_finally.Bind(catch_finally); | |
1738 Goto(&perform_finally); | |
1739 | |
1740 Bind(&if_notcallable); | |
1741 { | |
1742 // 1. If IsCallable(onFinally) is not true, return onFinally. | |
1743 var_then_finally.Bind(on_finally); | |
1744 // 1. If IsCallable(onFinally) is not true, return onFinally. | |
neis
2017/02/15 12:40:39
I find these comments here confusing, since they a
gsathya
2017/02/16 15:05:29
Yeah, that's fair. Removed
| |
1745 var_catch_finally.Bind(on_finally); | |
1746 Goto(&perform_finally); | |
1747 } | |
1748 | |
1749 Bind(&perform_finally); | |
1750 Label if_nativepromise(this), if_custompromise(this, Label::kDeferred); | |
1751 GotoIf(TaggedIsSmi(promise), &if_custompromise); | |
neis
2017/02/15 12:40:39
We already know that promise is a JS_PROMISE objec
gsathya
2017/02/16 15:05:29
Done.
| |
1752 BranchIfFastPath(context, promise, &if_nativepromise, &if_custompromise); | |
1753 | |
neis
2017/02/15 12:40:39
The step 5 comment should appear here.
gsathya
2017/02/16 15:05:29
Done.
| |
1754 Bind(&if_nativepromise); | |
1755 { | |
1756 Node* deferred_promise = AllocateAndInitJSPromise(context, promise); | |
1757 InternalPerformPromiseThen(context, promise, var_then_finally.value(), | |
1758 var_catch_finally.value(), deferred_promise, | |
1759 UndefinedConstant(), UndefinedConstant()); | |
1760 Return(deferred_promise); | |
1761 } | |
1762 | |
1763 Bind(&if_custompromise); | |
1764 { | |
1765 Isolate* isolate = this->isolate(); | |
1766 Node* const then_str = HeapConstant(isolate->factory()->then_string()); | |
1767 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | |
1768 Node* const then = | |
1769 CallStub(getproperty_callable, context, promise, then_str); | |
1770 Callable call_callable = CodeFactory::Call(isolate); | |
1771 // 5. Return ? Invoke(promise, "then", « thenFinally, catchFinally »). | |
1772 Node* const result = | |
1773 CallJS(call_callable, context, then, promise, var_then_finally.value(), | |
1774 var_catch_finally.value()); | |
1775 Return(result); | |
1776 } | |
1777 } | |
1778 | |
1567 } // namespace internal | 1779 } // namespace internal |
1568 } // namespace v8 | 1780 } // namespace v8 |
OLD | NEW |