Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(692)

Side by Side Diff: src/builtins/ia32/builtins-ia32.cc

Issue 2930623002: [builtins] Start refactoring the Apply builtin. (Closed)
Patch Set: Address feedback. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins-definitions.h ('k') | src/builtins/mips/builtins-mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/builtins/builtins-definitions.h ('k') | src/builtins/mips/builtins-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698