OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 1504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1515 // static | 1515 // static |
1516 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { | 1516 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { |
1517 // ----------- S t a t e ------------- | 1517 // ----------- S t a t e ------------- |
1518 // -- eax : argc | 1518 // -- eax : argc |
1519 // -- esp[0] : return address | 1519 // -- esp[0] : return address |
1520 // -- esp[4] : argArray | 1520 // -- esp[4] : argArray |
1521 // -- esp[8] : thisArg | 1521 // -- esp[8] : thisArg |
1522 // -- esp[12] : receiver | 1522 // -- esp[12] : receiver |
1523 // ----------------------------------- | 1523 // ----------------------------------- |
1524 | 1524 |
1525 // 1. Load receiver into edi, argArray into eax (if present), remove all | 1525 // 1. Load receiver into edi, argArray into ebx (if present), remove all |
1526 // arguments from the stack (including the receiver), and push thisArg (if | 1526 // arguments from the stack (including the receiver), and push thisArg (if |
1527 // present) instead. | 1527 // present) instead. |
1528 { | 1528 { |
1529 Label no_arg_array, no_this_arg; | 1529 Label no_arg_array, no_this_arg; |
1530 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); | 1530 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); |
1531 __ mov(ebx, edx); | 1531 __ mov(ebx, edx); |
1532 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1532 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); |
1533 __ test(eax, eax); | 1533 __ test(eax, eax); |
1534 __ j(zero, &no_this_arg, Label::kNear); | 1534 __ j(zero, &no_this_arg, Label::kNear); |
1535 { | 1535 { |
1536 __ mov(edx, Operand(esp, eax, times_pointer_size, 0)); | 1536 __ mov(edx, Operand(esp, eax, times_pointer_size, 0)); |
1537 __ cmp(eax, Immediate(1)); | 1537 __ cmp(eax, Immediate(1)); |
1538 __ j(equal, &no_arg_array, Label::kNear); | 1538 __ j(equal, &no_arg_array, Label::kNear); |
1539 __ mov(ebx, Operand(esp, eax, times_pointer_size, -kPointerSize)); | 1539 __ mov(ebx, Operand(esp, eax, times_pointer_size, -kPointerSize)); |
1540 __ bind(&no_arg_array); | 1540 __ bind(&no_arg_array); |
1541 } | 1541 } |
1542 __ bind(&no_this_arg); | 1542 __ bind(&no_this_arg); |
1543 __ PopReturnAddressTo(ecx); | 1543 __ PopReturnAddressTo(ecx); |
1544 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1544 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); |
1545 __ Push(edx); | 1545 __ Push(edx); |
1546 __ PushReturnAddressFrom(ecx); | 1546 __ PushReturnAddressFrom(ecx); |
1547 __ Move(eax, ebx); | |
1548 } | 1547 } |
1549 | 1548 |
1550 // ----------- S t a t e ------------- | 1549 // ----------- S t a t e ------------- |
1551 // -- eax : argArray | 1550 // -- ebx : argArray |
1552 // -- edi : receiver | 1551 // -- edi : receiver |
1553 // -- esp[0] : return address | 1552 // -- esp[0] : return address |
1554 // -- esp[4] : thisArg | 1553 // -- esp[4] : thisArg |
1555 // ----------------------------------- | 1554 // ----------------------------------- |
1556 | 1555 |
1557 // 2. Make sure the receiver is actually callable. | 1556 // 2. Make sure the receiver is actually callable. |
1558 Label receiver_not_callable; | 1557 Label receiver_not_callable; |
1559 __ JumpIfSmi(edi, &receiver_not_callable, Label::kNear); | 1558 __ JumpIfSmi(edi, &receiver_not_callable, Label::kNear); |
1560 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); | 1559 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); |
1561 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | 1560 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
1562 Immediate(1 << Map::kIsCallable)); | 1561 Immediate(1 << Map::kIsCallable)); |
1563 __ j(zero, &receiver_not_callable, Label::kNear); | 1562 __ j(zero, &receiver_not_callable, Label::kNear); |
1564 | 1563 |
1565 // 3. Tail call with no arguments if argArray is null or undefined. | 1564 // 3. Tail call with no arguments if argArray is null or undefined. |
1566 Label no_arguments; | 1565 Label no_arguments; |
1567 __ JumpIfRoot(eax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); | 1566 __ JumpIfRoot(ebx, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); |
1568 __ JumpIfRoot(eax, Heap::kUndefinedValueRootIndex, &no_arguments, | 1567 __ JumpIfRoot(ebx, Heap::kUndefinedValueRootIndex, &no_arguments, |
1569 Label::kNear); | 1568 Label::kNear); |
1570 | 1569 |
1571 // 4a. Apply the receiver to the given argArray (passing undefined for | 1570 // 4a. Apply the receiver to the given argArray. |
1572 // new.target). | 1571 __ Jump(masm->isolate()->builtins()->CallWithArrayLike(), |
1573 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); | 1572 RelocInfo::CODE_TARGET); |
1574 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
1575 | 1573 |
1576 // 4b. The argArray is either null or undefined, so we tail call without any | 1574 // 4b. The argArray is either null or undefined, so we tail call without any |
1577 // arguments to the receiver. | 1575 // arguments to the receiver. |
1578 __ bind(&no_arguments); | 1576 __ bind(&no_arguments); |
1579 { | 1577 { |
1580 __ Set(eax, 0); | 1578 __ Set(eax, 0); |
1581 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1579 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1582 } | 1580 } |
1583 | 1581 |
1584 // 4c. The receiver is not callable, throw an appropriate TypeError. | 1582 // 4c. The receiver is not callable, throw an appropriate TypeError. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1638 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | 1636 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { |
1639 // ----------- S t a t e ------------- | 1637 // ----------- S t a t e ------------- |
1640 // -- eax : argc | 1638 // -- eax : argc |
1641 // -- esp[0] : return address | 1639 // -- esp[0] : return address |
1642 // -- esp[4] : argumentsList | 1640 // -- esp[4] : argumentsList |
1643 // -- esp[8] : thisArgument | 1641 // -- esp[8] : thisArgument |
1644 // -- esp[12] : target | 1642 // -- esp[12] : target |
1645 // -- esp[16] : receiver | 1643 // -- esp[16] : receiver |
1646 // ----------------------------------- | 1644 // ----------------------------------- |
1647 | 1645 |
1648 // 1. Load target into edi (if present), argumentsList into eax (if present), | 1646 // 1. Load target into edi (if present), argumentsList into ebx (if present), |
1649 // remove all arguments from the stack (including the receiver), and push | 1647 // remove all arguments from the stack (including the receiver), and push |
1650 // thisArgument (if present) instead. | 1648 // thisArgument (if present) instead. |
1651 { | 1649 { |
1652 Label done; | 1650 Label done; |
1653 __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); | 1651 __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); |
1654 __ mov(edx, edi); | 1652 __ mov(edx, edi); |
1655 __ mov(ebx, edi); | 1653 __ mov(ebx, edi); |
1656 __ cmp(eax, Immediate(1)); | 1654 __ cmp(eax, Immediate(1)); |
1657 __ j(below, &done, Label::kNear); | 1655 __ j(below, &done, Label::kNear); |
1658 __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize)); | 1656 __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize)); |
1659 __ j(equal, &done, Label::kNear); | 1657 __ j(equal, &done, Label::kNear); |
1660 __ mov(edx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize)); | 1658 __ mov(edx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize)); |
1661 __ cmp(eax, Immediate(3)); | 1659 __ cmp(eax, Immediate(3)); |
1662 __ j(below, &done, Label::kNear); | 1660 __ j(below, &done, Label::kNear); |
1663 __ mov(ebx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize)); | 1661 __ mov(ebx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize)); |
1664 __ bind(&done); | 1662 __ bind(&done); |
1665 __ PopReturnAddressTo(ecx); | 1663 __ PopReturnAddressTo(ecx); |
1666 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1664 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); |
1667 __ Push(edx); | 1665 __ Push(edx); |
1668 __ PushReturnAddressFrom(ecx); | 1666 __ PushReturnAddressFrom(ecx); |
1669 __ Move(eax, ebx); | |
1670 } | 1667 } |
1671 | 1668 |
1672 // ----------- S t a t e ------------- | 1669 // ----------- S t a t e ------------- |
1673 // -- eax : argumentsList | 1670 // -- ebx : argumentsList |
1674 // -- edi : target | 1671 // -- edi : target |
1675 // -- esp[0] : return address | 1672 // -- esp[0] : return address |
1676 // -- esp[4] : thisArgument | 1673 // -- esp[4] : thisArgument |
1677 // ----------------------------------- | 1674 // ----------------------------------- |
1678 | 1675 |
1679 // 2. Make sure the target is actually callable. | 1676 // 2. Make sure the target is actually callable. |
1680 Label target_not_callable; | 1677 Label target_not_callable; |
1681 __ JumpIfSmi(edi, &target_not_callable, Label::kNear); | 1678 __ JumpIfSmi(edi, &target_not_callable, Label::kNear); |
1682 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); | 1679 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); |
1683 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | 1680 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
1684 Immediate(1 << Map::kIsCallable)); | 1681 Immediate(1 << Map::kIsCallable)); |
1685 __ j(zero, &target_not_callable, Label::kNear); | 1682 __ j(zero, &target_not_callable, Label::kNear); |
1686 | 1683 |
1687 // 3a. Apply the target to the given argumentsList (passing undefined for | 1684 // 3a. Apply the target to the given argumentsList. |
1688 // new.target). | 1685 __ Jump(masm->isolate()->builtins()->CallWithArrayLike(), |
1689 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); | 1686 RelocInfo::CODE_TARGET); |
1690 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
1691 | 1687 |
1692 // 3b. The target is not callable, throw an appropriate TypeError. | 1688 // 3b. The target is not callable, throw an appropriate TypeError. |
1693 __ bind(&target_not_callable); | 1689 __ bind(&target_not_callable); |
1694 { | 1690 { |
1695 __ mov(Operand(esp, kPointerSize), edi); | 1691 __ mov(Operand(esp, kPointerSize), edi); |
1696 __ TailCallRuntime(Runtime::kThrowApplyNonFunction); | 1692 __ TailCallRuntime(Runtime::kThrowApplyNonFunction); |
1697 } | 1693 } |
1698 } | 1694 } |
1699 | 1695 |
1700 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | 1696 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { |
1701 // ----------- S t a t e ------------- | 1697 // ----------- S t a t e ------------- |
1702 // -- eax : argc | 1698 // -- eax : argc |
1703 // -- esp[0] : return address | 1699 // -- esp[0] : return address |
1704 // -- esp[4] : new.target (optional) | 1700 // -- esp[4] : new.target (optional) |
1705 // -- esp[8] : argumentsList | 1701 // -- esp[8] : argumentsList |
1706 // -- esp[12] : target | 1702 // -- esp[12] : target |
1707 // -- esp[16] : receiver | 1703 // -- esp[16] : receiver |
1708 // ----------------------------------- | 1704 // ----------------------------------- |
1709 | 1705 |
1710 // 1. Load target into edi (if present), argumentsList into eax (if present), | 1706 // 1. Load target into edi (if present), argumentsList into ebx (if present), |
1711 // new.target into edx (if present, otherwise use target), remove all | 1707 // new.target into edx (if present, otherwise use target), remove all |
1712 // arguments from the stack (including the receiver), and push thisArgument | 1708 // arguments from the stack (including the receiver), and push thisArgument |
1713 // (if present) instead. | 1709 // (if present) instead. |
1714 { | 1710 { |
1715 Label done; | 1711 Label done; |
1716 __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); | 1712 __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); |
1717 __ mov(edx, edi); | 1713 __ mov(edx, edi); |
1718 __ mov(ebx, edi); | 1714 __ mov(ebx, edi); |
1719 __ cmp(eax, Immediate(1)); | 1715 __ cmp(eax, Immediate(1)); |
1720 __ j(below, &done, Label::kNear); | 1716 __ j(below, &done, Label::kNear); |
1721 __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize)); | 1717 __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize)); |
1722 __ mov(edx, edi); | 1718 __ mov(edx, edi); |
1723 __ j(equal, &done, Label::kNear); | 1719 __ j(equal, &done, Label::kNear); |
1724 __ mov(ebx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize)); | 1720 __ mov(ebx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize)); |
1725 __ cmp(eax, Immediate(3)); | 1721 __ cmp(eax, Immediate(3)); |
1726 __ j(below, &done, Label::kNear); | 1722 __ j(below, &done, Label::kNear); |
1727 __ mov(edx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize)); | 1723 __ mov(edx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize)); |
1728 __ bind(&done); | 1724 __ bind(&done); |
1729 __ PopReturnAddressTo(ecx); | 1725 __ PopReturnAddressTo(ecx); |
1730 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1726 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); |
1731 __ PushRoot(Heap::kUndefinedValueRootIndex); | 1727 __ PushRoot(Heap::kUndefinedValueRootIndex); |
1732 __ PushReturnAddressFrom(ecx); | 1728 __ PushReturnAddressFrom(ecx); |
1733 __ Move(eax, ebx); | |
1734 } | 1729 } |
1735 | 1730 |
1736 // ----------- S t a t e ------------- | 1731 // ----------- S t a t e ------------- |
1737 // -- eax : argumentsList | 1732 // -- ebx : argumentsList |
1738 // -- edx : new.target | 1733 // -- edx : new.target |
1739 // -- edi : target | 1734 // -- edi : target |
1740 // -- esp[0] : return address | 1735 // -- esp[0] : return address |
1741 // -- esp[4] : receiver (undefined) | 1736 // -- esp[4] : receiver (undefined) |
1742 // ----------------------------------- | 1737 // ----------------------------------- |
1743 | 1738 |
1744 // 2. Make sure the target is actually a constructor. | 1739 // 2. Make sure the target is actually a constructor. |
1745 Label target_not_constructor; | 1740 Label target_not_constructor; |
1746 __ JumpIfSmi(edi, &target_not_constructor, Label::kNear); | 1741 __ JumpIfSmi(edi, &target_not_constructor, Label::kNear); |
1747 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); | 1742 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); |
1748 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | 1743 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
1749 Immediate(1 << Map::kIsConstructor)); | 1744 Immediate(1 << Map::kIsConstructor)); |
1750 __ j(zero, &target_not_constructor, Label::kNear); | 1745 __ j(zero, &target_not_constructor, Label::kNear); |
1751 | 1746 |
1752 // 3. Make sure the target is actually a constructor. | 1747 // 3. Make sure the target is actually a constructor. |
1753 Label new_target_not_constructor; | 1748 Label new_target_not_constructor; |
1754 __ JumpIfSmi(edx, &new_target_not_constructor, Label::kNear); | 1749 __ JumpIfSmi(edx, &new_target_not_constructor, Label::kNear); |
1755 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 1750 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
1756 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | 1751 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
1757 Immediate(1 << Map::kIsConstructor)); | 1752 Immediate(1 << Map::kIsConstructor)); |
1758 __ j(zero, &new_target_not_constructor, Label::kNear); | 1753 __ j(zero, &new_target_not_constructor, Label::kNear); |
1759 | 1754 |
1760 // 4a. Construct the target with the given new.target and argumentsList. | 1755 // 4a. Construct the target with the given new.target and argumentsList. |
1761 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | 1756 __ Jump(masm->isolate()->builtins()->ConstructWithArrayLike(), |
| 1757 RelocInfo::CODE_TARGET); |
1762 | 1758 |
1763 // 4b. The target is not a constructor, throw an appropriate TypeError. | 1759 // 4b. The target is not a constructor, throw an appropriate TypeError. |
1764 __ bind(&target_not_constructor); | 1760 __ bind(&target_not_constructor); |
1765 { | 1761 { |
1766 __ mov(Operand(esp, kPointerSize), edi); | 1762 __ mov(Operand(esp, kPointerSize), edi); |
1767 __ TailCallRuntime(Runtime::kThrowNotConstructor); | 1763 __ TailCallRuntime(Runtime::kThrowNotConstructor); |
1768 } | 1764 } |
1769 | 1765 |
1770 // 4c. The new.target is not a constructor, throw an appropriate TypeError. | 1766 // 4c. The new.target is not a constructor, throw an appropriate TypeError. |
1771 __ bind(&new_target_not_constructor); | 1767 __ bind(&new_target_not_constructor); |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2150 __ leave(); | 2146 __ leave(); |
2151 | 2147 |
2152 // Remove caller arguments from the stack. | 2148 // Remove caller arguments from the stack. |
2153 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 2149 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
2154 __ pop(ecx); | 2150 __ pop(ecx); |
2155 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver | 2151 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver |
2156 __ push(ecx); | 2152 __ push(ecx); |
2157 } | 2153 } |
2158 | 2154 |
2159 // static | 2155 // static |
2160 void Builtins::Generate_Apply(MacroAssembler* masm) { | 2156 void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm, |
| 2157 Handle<Code> code) { |
2161 // ----------- S t a t e ------------- | 2158 // ----------- S t a t e ------------- |
2162 // -- eax : argumentsList | |
2163 // -- edi : target | 2159 // -- edi : target |
| 2160 // -- eax : number of parameters on the stack (not including the receiver) |
| 2161 // -- ebx : arguments list (a FixedArray) |
| 2162 // -- ecx : len (number of elements to from args) |
2164 // -- edx : new.target (checked to be constructor or undefined) | 2163 // -- edx : new.target (checked to be constructor or undefined) |
2165 // -- esp[0] : return address. | 2164 // -- esp[0] : return address. |
2166 // -- esp[4] : thisArgument | |
2167 // ----------------------------------- | 2165 // ----------------------------------- |
| 2166 __ AssertFixedArray(ebx); |
2168 | 2167 |
2169 // Create the list of arguments from the array-like argumentsList. | 2168 // We need to preserve eax, edi and ebx. |
2170 { | 2169 __ movd(xmm0, edx); |
2171 Label create_arguments, create_array, create_holey_array, create_runtime, | 2170 __ movd(xmm1, edi); |
2172 done_create; | 2171 __ movd(xmm2, eax); |
2173 __ JumpIfSmi(eax, &create_runtime); | |
2174 | |
2175 // Load the map of argumentsList into ecx. | |
2176 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | |
2177 | |
2178 // Load native context into ebx. | |
2179 __ mov(ebx, NativeContextOperand()); | |
2180 | |
2181 // Check if argumentsList is an (unmodified) arguments object. | |
2182 __ cmp(ecx, ContextOperand(ebx, Context::SLOPPY_ARGUMENTS_MAP_INDEX)); | |
2183 __ j(equal, &create_arguments); | |
2184 __ cmp(ecx, ContextOperand(ebx, Context::STRICT_ARGUMENTS_MAP_INDEX)); | |
2185 __ j(equal, &create_arguments); | |
2186 | |
2187 // Check if argumentsList is a fast JSArray. | |
2188 __ CmpInstanceType(ecx, JS_ARRAY_TYPE); | |
2189 __ j(equal, &create_array); | |
2190 | |
2191 // Ask the runtime to create the list (actually a FixedArray). | |
2192 __ bind(&create_runtime); | |
2193 { | |
2194 FrameScope scope(masm, StackFrame::INTERNAL); | |
2195 __ Push(edi); | |
2196 __ Push(edx); | |
2197 __ Push(eax); | |
2198 __ CallRuntime(Runtime::kCreateListFromArrayLike); | |
2199 __ Pop(edx); | |
2200 __ Pop(edi); | |
2201 __ mov(ebx, FieldOperand(eax, FixedArray::kLengthOffset)); | |
2202 __ SmiUntag(ebx); | |
2203 } | |
2204 __ jmp(&done_create); | |
2205 | |
2206 // Try to create the list from an arguments object. | |
2207 __ bind(&create_arguments); | |
2208 __ mov(ebx, FieldOperand(eax, JSArgumentsObject::kLengthOffset)); | |
2209 __ mov(ecx, FieldOperand(eax, JSObject::kElementsOffset)); | |
2210 __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); | |
2211 __ j(not_equal, &create_runtime); | |
2212 __ SmiUntag(ebx); | |
2213 __ mov(eax, ecx); | |
2214 __ jmp(&done_create); | |
2215 | |
2216 // For holey JSArrays we need to check that the array prototype chain | |
2217 // protector is intact and our prototype is the Array.prototype actually. | |
2218 __ bind(&create_holey_array); | |
2219 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | |
2220 __ mov(ecx, FieldOperand(ecx, Map::kPrototypeOffset)); | |
2221 __ cmp(ecx, ContextOperand(ebx, Context::INITIAL_ARRAY_PROTOTYPE_INDEX)); | |
2222 __ j(not_equal, &create_runtime); | |
2223 __ LoadRoot(ecx, Heap::kArrayProtectorRootIndex); | |
2224 __ cmp(FieldOperand(ecx, PropertyCell::kValueOffset), | |
2225 Immediate(Smi::FromInt(Isolate::kProtectorValid))); | |
2226 __ j(not_equal, &create_runtime); | |
2227 __ mov(ebx, FieldOperand(eax, JSArray::kLengthOffset)); | |
2228 __ SmiUntag(ebx); | |
2229 __ mov(eax, FieldOperand(eax, JSArray::kElementsOffset)); | |
2230 __ jmp(&done_create); | |
2231 | |
2232 // Try to create the list from a JSArray object. | |
2233 __ bind(&create_array); | |
2234 __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); | |
2235 __ DecodeField<Map::ElementsKindBits>(ecx); | |
2236 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
2237 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
2238 STATIC_ASSERT(FAST_ELEMENTS == 2); | |
2239 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | |
2240 __ cmp(ecx, Immediate(FAST_HOLEY_SMI_ELEMENTS)); | |
2241 __ j(equal, &create_holey_array, Label::kNear); | |
2242 __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS)); | |
2243 __ j(equal, &create_holey_array, Label::kNear); | |
2244 __ j(above, &create_runtime); | |
2245 __ mov(ebx, FieldOperand(eax, JSArray::kLengthOffset)); | |
2246 __ SmiUntag(ebx); | |
2247 __ mov(eax, FieldOperand(eax, JSArray::kElementsOffset)); | |
2248 | |
2249 __ bind(&done_create); | |
2250 } | |
2251 | 2172 |
2252 // Check for stack overflow. | 2173 // Check for stack overflow. |
2253 { | 2174 { |
2254 // Check the stack for overflow. We are not trying to catch interruptions | 2175 // Check the stack for overflow. We are not trying to catch interruptions |
2255 // (i.e. debug break and preemption) here, so check the "real stack limit". | 2176 // (i.e. debug break and preemption) here, so check the "real stack limit". |
2256 Label done; | 2177 Label done; |
2257 ExternalReference real_stack_limit = | 2178 ExternalReference real_stack_limit = |
2258 ExternalReference::address_of_real_stack_limit(masm->isolate()); | 2179 ExternalReference::address_of_real_stack_limit(masm->isolate()); |
2259 __ mov(ecx, Operand::StaticVariable(real_stack_limit)); | 2180 __ mov(edx, Operand::StaticVariable(real_stack_limit)); |
2260 // Make ecx the space we have left. The stack might already be overflowed | 2181 // Make edx the space we have left. The stack might already be overflowed |
2261 // here which will cause ecx to become negative. | 2182 // here which will cause edx to become negative. |
2262 __ neg(ecx); | 2183 __ neg(edx); |
2263 __ add(ecx, esp); | 2184 __ add(edx, esp); |
2264 __ sar(ecx, kPointerSizeLog2); | 2185 __ sar(edx, kPointerSizeLog2); |
2265 // Check if the arguments will overflow the stack. | 2186 // Check if the arguments will overflow the stack. |
2266 __ cmp(ecx, ebx); | 2187 __ cmp(edx, ecx); |
2267 __ j(greater, &done, Label::kNear); // Signed comparison. | 2188 __ j(greater, &done, Label::kNear); // Signed comparison. |
2268 __ TailCallRuntime(Runtime::kThrowStackOverflow); | 2189 __ TailCallRuntime(Runtime::kThrowStackOverflow); |
2269 __ bind(&done); | 2190 __ bind(&done); |
2270 } | 2191 } |
2271 | 2192 |
2272 // ----------- S t a t e ------------- | 2193 // Push additional arguments onto the stack. |
2273 // -- edi : target | |
2274 // -- eax : args (a FixedArray built from argumentsList) | |
2275 // -- ebx : len (number of elements to push from args) | |
2276 // -- edx : new.target (checked to be constructor or undefined) | |
2277 // -- esp[0] : return address. | |
2278 // -- esp[4] : thisArgument | |
2279 // ----------------------------------- | |
2280 | |
2281 // Push arguments onto the stack (thisArgument is already on the stack). | |
2282 { | 2194 { |
2283 __ movd(xmm0, edx); | |
2284 __ movd(xmm1, edi); | |
2285 __ PopReturnAddressTo(edx); | 2195 __ PopReturnAddressTo(edx); |
2286 __ Move(ecx, Immediate(0)); | 2196 __ Move(eax, Immediate(0)); |
2287 Label done, push, loop; | 2197 Label done, push, loop; |
2288 __ bind(&loop); | 2198 __ bind(&loop); |
2289 __ cmp(ecx, ebx); | 2199 __ cmp(eax, ecx); |
2290 __ j(equal, &done, Label::kNear); | 2200 __ j(equal, &done, Label::kNear); |
2291 // Turn the hole into undefined as we go. | 2201 // Turn the hole into undefined as we go. |
2292 __ mov(edi, | 2202 __ mov(edi, |
2293 FieldOperand(eax, ecx, times_pointer_size, FixedArray::kHeaderSize)); | 2203 FieldOperand(ebx, eax, times_pointer_size, FixedArray::kHeaderSize)); |
2294 __ CompareRoot(edi, Heap::kTheHoleValueRootIndex); | 2204 __ CompareRoot(edi, Heap::kTheHoleValueRootIndex); |
2295 __ j(not_equal, &push, Label::kNear); | 2205 __ j(not_equal, &push, Label::kNear); |
2296 __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); | 2206 __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); |
2297 __ bind(&push); | 2207 __ bind(&push); |
2298 __ Push(edi); | 2208 __ Push(edi); |
2299 __ inc(ecx); | 2209 __ inc(eax); |
2300 __ jmp(&loop); | 2210 __ jmp(&loop); |
2301 __ bind(&done); | 2211 __ bind(&done); |
2302 __ PushReturnAddressFrom(edx); | 2212 __ PushReturnAddressFrom(edx); |
2303 __ movd(edi, xmm1); | |
2304 __ movd(edx, xmm0); | |
2305 __ Move(eax, ebx); | |
2306 } | 2213 } |
2307 | 2214 |
2308 // Dispatch to Call or Construct depending on whether new.target is undefined. | 2215 // Restore eax, edi and edx. |
2309 { | 2216 __ movd(eax, xmm2); |
2310 __ CompareRoot(edx, Heap::kUndefinedValueRootIndex); | 2217 __ movd(edi, xmm1); |
2311 __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 2218 __ movd(edx, xmm0); |
2312 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2219 |
2313 } | 2220 // Compute the actual parameter count. |
| 2221 __ add(eax, ecx); |
| 2222 |
| 2223 // Tail-call to the actual Call or Construct builtin. |
| 2224 __ Jump(code, RelocInfo::CODE_TARGET); |
2314 } | 2225 } |
2315 | 2226 |
2316 // static | 2227 // static |
2317 void Builtins::Generate_ForwardVarargs(MacroAssembler* masm, | 2228 void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm, |
2318 Handle<Code> code) { | 2229 Handle<Code> code) { |
2319 // ----------- S t a t e ------------- | 2230 // ----------- S t a t e ------------- |
2320 // -- eax : the number of arguments (not including the receiver) | 2231 // -- eax : the number of arguments (not including the receiver) |
2321 // -- edi : the target to call (can be any Object) | 2232 // -- edi : the target to call (can be any Object) |
2322 // -- edx : the new target (for [[Construct]] calls) | 2233 // -- edx : the new target (for [[Construct]] calls) |
2323 // -- ecx : start index (to support rest parameters) | 2234 // -- ecx : start index (to support rest parameters) |
2324 // ----------------------------------- | 2235 // ----------------------------------- |
2325 | 2236 |
2326 // Preserve new.target (in case of [[Construct]]). | 2237 // Preserve new.target (in case of [[Construct]]). |
2327 __ movd(xmm0, edx); | 2238 __ movd(xmm0, edx); |
2328 | 2239 |
(...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3330 } | 3241 } |
3331 // Now jump to the instructions of the returned code object. | 3242 // Now jump to the instructions of the returned code object. |
3332 __ jmp(edi); | 3243 __ jmp(edi); |
3333 } | 3244 } |
3334 | 3245 |
3335 #undef __ | 3246 #undef __ |
3336 } // namespace internal | 3247 } // namespace internal |
3337 } // namespace v8 | 3248 } // namespace v8 |
3338 | 3249 |
3339 #endif // V8_TARGET_ARCH_IA32 | 3250 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |