| 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_X64 | 5 #if V8_TARGET_ARCH_X64 |
| 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/counters.h" | 9 #include "src/counters.h" |
| 10 #include "src/deoptimizer.h" | 10 #include "src/deoptimizer.h" |
| (...skipping 1469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1480 // static | 1480 // static |
| 1481 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { | 1481 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { |
| 1482 // ----------- S t a t e ------------- | 1482 // ----------- S t a t e ------------- |
| 1483 // -- rax : argc | 1483 // -- rax : argc |
| 1484 // -- rsp[0] : return address | 1484 // -- rsp[0] : return address |
| 1485 // -- rsp[8] : argArray | 1485 // -- rsp[8] : argArray |
| 1486 // -- rsp[16] : thisArg | 1486 // -- rsp[16] : thisArg |
| 1487 // -- rsp[24] : receiver | 1487 // -- rsp[24] : receiver |
| 1488 // ----------------------------------- | 1488 // ----------------------------------- |
| 1489 | 1489 |
| 1490 // 1. Load receiver into rdi, argArray into rax (if present), remove all | 1490 // 1. Load receiver into rdi, argArray into rbx (if present), remove all |
| 1491 // arguments from the stack (including the receiver), and push thisArg (if | 1491 // arguments from the stack (including the receiver), and push thisArg (if |
| 1492 // present) instead. | 1492 // present) instead. |
| 1493 { | 1493 { |
| 1494 Label no_arg_array, no_this_arg; | 1494 Label no_arg_array, no_this_arg; |
| 1495 StackArgumentsAccessor args(rsp, rax); | 1495 StackArgumentsAccessor args(rsp, rax); |
| 1496 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); | 1496 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); |
| 1497 __ movp(rbx, rdx); | 1497 __ movp(rbx, rdx); |
| 1498 __ movp(rdi, args.GetReceiverOperand()); | 1498 __ movp(rdi, args.GetReceiverOperand()); |
| 1499 __ testp(rax, rax); | 1499 __ testp(rax, rax); |
| 1500 __ j(zero, &no_this_arg, Label::kNear); | 1500 __ j(zero, &no_this_arg, Label::kNear); |
| 1501 { | 1501 { |
| 1502 __ movp(rdx, args.GetArgumentOperand(1)); | 1502 __ movp(rdx, args.GetArgumentOperand(1)); |
| 1503 __ cmpp(rax, Immediate(1)); | 1503 __ cmpp(rax, Immediate(1)); |
| 1504 __ j(equal, &no_arg_array, Label::kNear); | 1504 __ j(equal, &no_arg_array, Label::kNear); |
| 1505 __ movp(rbx, args.GetArgumentOperand(2)); | 1505 __ movp(rbx, args.GetArgumentOperand(2)); |
| 1506 __ bind(&no_arg_array); | 1506 __ bind(&no_arg_array); |
| 1507 } | 1507 } |
| 1508 __ bind(&no_this_arg); | 1508 __ bind(&no_this_arg); |
| 1509 __ PopReturnAddressTo(rcx); | 1509 __ PopReturnAddressTo(rcx); |
| 1510 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); | 1510 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); |
| 1511 __ Push(rdx); | 1511 __ Push(rdx); |
| 1512 __ PushReturnAddressFrom(rcx); | 1512 __ PushReturnAddressFrom(rcx); |
| 1513 __ movp(rax, rbx); | |
| 1514 } | 1513 } |
| 1515 | 1514 |
| 1516 // ----------- S t a t e ------------- | 1515 // ----------- S t a t e ------------- |
| 1517 // -- rax : argArray | 1516 // -- rbx : argArray |
| 1518 // -- rdi : receiver | 1517 // -- rdi : receiver |
| 1519 // -- rsp[0] : return address | 1518 // -- rsp[0] : return address |
| 1520 // -- rsp[8] : thisArg | 1519 // -- rsp[8] : thisArg |
| 1521 // ----------------------------------- | 1520 // ----------------------------------- |
| 1522 | 1521 |
| 1523 // 2. Make sure the receiver is actually callable. | 1522 // 2. Make sure the receiver is actually callable. |
| 1524 Label receiver_not_callable; | 1523 Label receiver_not_callable; |
| 1525 __ JumpIfSmi(rdi, &receiver_not_callable, Label::kNear); | 1524 __ JumpIfSmi(rdi, &receiver_not_callable, Label::kNear); |
| 1526 __ movp(rcx, FieldOperand(rdi, HeapObject::kMapOffset)); | 1525 __ movp(rcx, FieldOperand(rdi, HeapObject::kMapOffset)); |
| 1527 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 1526 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
| 1528 Immediate(1 << Map::kIsCallable)); | 1527 Immediate(1 << Map::kIsCallable)); |
| 1529 __ j(zero, &receiver_not_callable, Label::kNear); | 1528 __ j(zero, &receiver_not_callable, Label::kNear); |
| 1530 | 1529 |
| 1531 // 3. Tail call with no arguments if argArray is null or undefined. | 1530 // 3. Tail call with no arguments if argArray is null or undefined. |
| 1532 Label no_arguments; | 1531 Label no_arguments; |
| 1533 __ JumpIfRoot(rax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); | 1532 __ JumpIfRoot(rbx, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); |
| 1534 __ JumpIfRoot(rax, Heap::kUndefinedValueRootIndex, &no_arguments, | 1533 __ JumpIfRoot(rbx, Heap::kUndefinedValueRootIndex, &no_arguments, |
| 1535 Label::kNear); | 1534 Label::kNear); |
| 1536 | 1535 |
| 1537 // 4a. Apply the receiver to the given argArray (passing undefined for | 1536 // 4a. Apply the receiver to the given argArray. |
| 1538 // new.target). | 1537 __ Jump(masm->isolate()->builtins()->CallWithArrayLike(), |
| 1539 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); | 1538 RelocInfo::CODE_TARGET); |
| 1540 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
| 1541 | 1539 |
| 1542 // 4b. The argArray is either null or undefined, so we tail call without any | 1540 // 4b. The argArray is either null or undefined, so we tail call without any |
| 1543 // arguments to the receiver. Since we did not create a frame for | 1541 // arguments to the receiver. Since we did not create a frame for |
| 1544 // Function.prototype.apply() yet, we use a normal Call builtin here. | 1542 // Function.prototype.apply() yet, we use a normal Call builtin here. |
| 1545 __ bind(&no_arguments); | 1543 __ bind(&no_arguments); |
| 1546 { | 1544 { |
| 1547 __ Set(rax, 0); | 1545 __ Set(rax, 0); |
| 1548 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1546 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1549 } | 1547 } |
| 1550 | 1548 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1612 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | 1610 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { |
| 1613 // ----------- S t a t e ------------- | 1611 // ----------- S t a t e ------------- |
| 1614 // -- rax : argc | 1612 // -- rax : argc |
| 1615 // -- rsp[0] : return address | 1613 // -- rsp[0] : return address |
| 1616 // -- rsp[8] : argumentsList | 1614 // -- rsp[8] : argumentsList |
| 1617 // -- rsp[16] : thisArgument | 1615 // -- rsp[16] : thisArgument |
| 1618 // -- rsp[24] : target | 1616 // -- rsp[24] : target |
| 1619 // -- rsp[32] : receiver | 1617 // -- rsp[32] : receiver |
| 1620 // ----------------------------------- | 1618 // ----------------------------------- |
| 1621 | 1619 |
| 1622 // 1. Load target into rdi (if present), argumentsList into rax (if present), | 1620 // 1. Load target into rdi (if present), argumentsList into rbx (if present), |
| 1623 // remove all arguments from the stack (including the receiver), and push | 1621 // remove all arguments from the stack (including the receiver), and push |
| 1624 // thisArgument (if present) instead. | 1622 // thisArgument (if present) instead. |
| 1625 { | 1623 { |
| 1626 Label done; | 1624 Label done; |
| 1627 StackArgumentsAccessor args(rsp, rax); | 1625 StackArgumentsAccessor args(rsp, rax); |
| 1628 __ LoadRoot(rdi, Heap::kUndefinedValueRootIndex); | 1626 __ LoadRoot(rdi, Heap::kUndefinedValueRootIndex); |
| 1629 __ movp(rdx, rdi); | 1627 __ movp(rdx, rdi); |
| 1630 __ movp(rbx, rdi); | 1628 __ movp(rbx, rdi); |
| 1631 __ cmpp(rax, Immediate(1)); | 1629 __ cmpp(rax, Immediate(1)); |
| 1632 __ j(below, &done, Label::kNear); | 1630 __ j(below, &done, Label::kNear); |
| 1633 __ movp(rdi, args.GetArgumentOperand(1)); // target | 1631 __ movp(rdi, args.GetArgumentOperand(1)); // target |
| 1634 __ j(equal, &done, Label::kNear); | 1632 __ j(equal, &done, Label::kNear); |
| 1635 __ movp(rdx, args.GetArgumentOperand(2)); // thisArgument | 1633 __ movp(rdx, args.GetArgumentOperand(2)); // thisArgument |
| 1636 __ cmpp(rax, Immediate(3)); | 1634 __ cmpp(rax, Immediate(3)); |
| 1637 __ j(below, &done, Label::kNear); | 1635 __ j(below, &done, Label::kNear); |
| 1638 __ movp(rbx, args.GetArgumentOperand(3)); // argumentsList | 1636 __ movp(rbx, args.GetArgumentOperand(3)); // argumentsList |
| 1639 __ bind(&done); | 1637 __ bind(&done); |
| 1640 __ PopReturnAddressTo(rcx); | 1638 __ PopReturnAddressTo(rcx); |
| 1641 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); | 1639 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); |
| 1642 __ Push(rdx); | 1640 __ Push(rdx); |
| 1643 __ PushReturnAddressFrom(rcx); | 1641 __ PushReturnAddressFrom(rcx); |
| 1644 __ movp(rax, rbx); | |
| 1645 } | 1642 } |
| 1646 | 1643 |
| 1647 // ----------- S t a t e ------------- | 1644 // ----------- S t a t e ------------- |
| 1648 // -- rax : argumentsList | 1645 // -- rbx : argumentsList |
| 1649 // -- rdi : target | 1646 // -- rdi : target |
| 1650 // -- rsp[0] : return address | 1647 // -- rsp[0] : return address |
| 1651 // -- rsp[8] : thisArgument | 1648 // -- rsp[8] : thisArgument |
| 1652 // ----------------------------------- | 1649 // ----------------------------------- |
| 1653 | 1650 |
| 1654 // 2. Make sure the target is actually callable. | 1651 // 2. Make sure the target is actually callable. |
| 1655 Label target_not_callable; | 1652 Label target_not_callable; |
| 1656 __ JumpIfSmi(rdi, &target_not_callable, Label::kNear); | 1653 __ JumpIfSmi(rdi, &target_not_callable, Label::kNear); |
| 1657 __ movp(rcx, FieldOperand(rdi, HeapObject::kMapOffset)); | 1654 __ movp(rcx, FieldOperand(rdi, HeapObject::kMapOffset)); |
| 1658 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 1655 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
| 1659 Immediate(1 << Map::kIsCallable)); | 1656 Immediate(1 << Map::kIsCallable)); |
| 1660 __ j(zero, &target_not_callable, Label::kNear); | 1657 __ j(zero, &target_not_callable, Label::kNear); |
| 1661 | 1658 |
| 1662 // 3a. Apply the target to the given argumentsList (passing undefined for | 1659 // 3a. Apply the target to the given argumentsList. |
| 1663 // new.target). | 1660 __ Jump(masm->isolate()->builtins()->CallWithArrayLike(), |
| 1664 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); | 1661 RelocInfo::CODE_TARGET); |
| 1665 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
| 1666 | 1662 |
| 1667 // 3b. The target is not callable, throw an appropriate TypeError. | 1663 // 3b. The target is not callable, throw an appropriate TypeError. |
| 1668 __ bind(&target_not_callable); | 1664 __ bind(&target_not_callable); |
| 1669 { | 1665 { |
| 1670 StackArgumentsAccessor args(rsp, 0); | 1666 StackArgumentsAccessor args(rsp, 0); |
| 1671 __ movp(args.GetReceiverOperand(), rdi); | 1667 __ movp(args.GetReceiverOperand(), rdi); |
| 1672 __ TailCallRuntime(Runtime::kThrowApplyNonFunction); | 1668 __ TailCallRuntime(Runtime::kThrowApplyNonFunction); |
| 1673 } | 1669 } |
| 1674 } | 1670 } |
| 1675 | 1671 |
| 1676 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | 1672 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { |
| 1677 // ----------- S t a t e ------------- | 1673 // ----------- S t a t e ------------- |
| 1678 // -- rax : argc | 1674 // -- rax : argc |
| 1679 // -- rsp[0] : return address | 1675 // -- rsp[0] : return address |
| 1680 // -- rsp[8] : new.target (optional) | 1676 // -- rsp[8] : new.target (optional) |
| 1681 // -- rsp[16] : argumentsList | 1677 // -- rsp[16] : argumentsList |
| 1682 // -- rsp[24] : target | 1678 // -- rsp[24] : target |
| 1683 // -- rsp[32] : receiver | 1679 // -- rsp[32] : receiver |
| 1684 // ----------------------------------- | 1680 // ----------------------------------- |
| 1685 | 1681 |
| 1686 // 1. Load target into rdi (if present), argumentsList into rax (if present), | 1682 // 1. Load target into rdi (if present), argumentsList into rbx (if present), |
| 1687 // new.target into rdx (if present, otherwise use target), remove all | 1683 // new.target into rdx (if present, otherwise use target), remove all |
| 1688 // arguments from the stack (including the receiver), and push thisArgument | 1684 // arguments from the stack (including the receiver), and push thisArgument |
| 1689 // (if present) instead. | 1685 // (if present) instead. |
| 1690 { | 1686 { |
| 1691 Label done; | 1687 Label done; |
| 1692 StackArgumentsAccessor args(rsp, rax); | 1688 StackArgumentsAccessor args(rsp, rax); |
| 1693 __ LoadRoot(rdi, Heap::kUndefinedValueRootIndex); | 1689 __ LoadRoot(rdi, Heap::kUndefinedValueRootIndex); |
| 1694 __ movp(rdx, rdi); | 1690 __ movp(rdx, rdi); |
| 1695 __ movp(rbx, rdi); | 1691 __ movp(rbx, rdi); |
| 1696 __ cmpp(rax, Immediate(1)); | 1692 __ cmpp(rax, Immediate(1)); |
| 1697 __ j(below, &done, Label::kNear); | 1693 __ j(below, &done, Label::kNear); |
| 1698 __ movp(rdi, args.GetArgumentOperand(1)); // target | 1694 __ movp(rdi, args.GetArgumentOperand(1)); // target |
| 1699 __ movp(rdx, rdi); // new.target defaults to target | 1695 __ movp(rdx, rdi); // new.target defaults to target |
| 1700 __ j(equal, &done, Label::kNear); | 1696 __ j(equal, &done, Label::kNear); |
| 1701 __ movp(rbx, args.GetArgumentOperand(2)); // argumentsList | 1697 __ movp(rbx, args.GetArgumentOperand(2)); // argumentsList |
| 1702 __ cmpp(rax, Immediate(3)); | 1698 __ cmpp(rax, Immediate(3)); |
| 1703 __ j(below, &done, Label::kNear); | 1699 __ j(below, &done, Label::kNear); |
| 1704 __ movp(rdx, args.GetArgumentOperand(3)); // new.target | 1700 __ movp(rdx, args.GetArgumentOperand(3)); // new.target |
| 1705 __ bind(&done); | 1701 __ bind(&done); |
| 1706 __ PopReturnAddressTo(rcx); | 1702 __ PopReturnAddressTo(rcx); |
| 1707 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); | 1703 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); |
| 1708 __ PushRoot(Heap::kUndefinedValueRootIndex); | 1704 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 1709 __ PushReturnAddressFrom(rcx); | 1705 __ PushReturnAddressFrom(rcx); |
| 1710 __ movp(rax, rbx); | |
| 1711 } | 1706 } |
| 1712 | 1707 |
| 1713 // ----------- S t a t e ------------- | 1708 // ----------- S t a t e ------------- |
| 1714 // -- rax : argumentsList | 1709 // -- rbx : argumentsList |
| 1715 // -- rdx : new.target | 1710 // -- rdx : new.target |
| 1716 // -- rdi : target | 1711 // -- rdi : target |
| 1717 // -- rsp[0] : return address | 1712 // -- rsp[0] : return address |
| 1718 // -- rsp[8] : receiver (undefined) | 1713 // -- rsp[8] : receiver (undefined) |
| 1719 // ----------------------------------- | 1714 // ----------------------------------- |
| 1720 | 1715 |
| 1721 // 2. Make sure the target is actually a constructor. | 1716 // 2. Make sure the target is actually a constructor. |
| 1722 Label target_not_constructor; | 1717 Label target_not_constructor; |
| 1723 __ JumpIfSmi(rdi, &target_not_constructor, Label::kNear); | 1718 __ JumpIfSmi(rdi, &target_not_constructor, Label::kNear); |
| 1724 __ movp(rcx, FieldOperand(rdi, HeapObject::kMapOffset)); | 1719 __ movp(rcx, FieldOperand(rdi, HeapObject::kMapOffset)); |
| 1725 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 1720 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
| 1726 Immediate(1 << Map::kIsConstructor)); | 1721 Immediate(1 << Map::kIsConstructor)); |
| 1727 __ j(zero, &target_not_constructor, Label::kNear); | 1722 __ j(zero, &target_not_constructor, Label::kNear); |
| 1728 | 1723 |
| 1729 // 3. Make sure the target is actually a constructor. | 1724 // 3. Make sure the target is actually a constructor. |
| 1730 Label new_target_not_constructor; | 1725 Label new_target_not_constructor; |
| 1731 __ JumpIfSmi(rdx, &new_target_not_constructor, Label::kNear); | 1726 __ JumpIfSmi(rdx, &new_target_not_constructor, Label::kNear); |
| 1732 __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | 1727 __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 1733 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 1728 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
| 1734 Immediate(1 << Map::kIsConstructor)); | 1729 Immediate(1 << Map::kIsConstructor)); |
| 1735 __ j(zero, &new_target_not_constructor, Label::kNear); | 1730 __ j(zero, &new_target_not_constructor, Label::kNear); |
| 1736 | 1731 |
| 1737 // 4a. Construct the target with the given new.target and argumentsList. | 1732 // 4a. Construct the target with the given new.target and argumentsList. |
| 1738 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | 1733 __ Jump(masm->isolate()->builtins()->ConstructWithArrayLike(), |
| 1734 RelocInfo::CODE_TARGET); |
| 1739 | 1735 |
| 1740 // 4b. The target is not a constructor, throw an appropriate TypeError. | 1736 // 4b. The target is not a constructor, throw an appropriate TypeError. |
| 1741 __ bind(&target_not_constructor); | 1737 __ bind(&target_not_constructor); |
| 1742 { | 1738 { |
| 1743 StackArgumentsAccessor args(rsp, 0); | 1739 StackArgumentsAccessor args(rsp, 0); |
| 1744 __ movp(args.GetReceiverOperand(), rdi); | 1740 __ movp(args.GetReceiverOperand(), rdi); |
| 1745 __ TailCallRuntime(Runtime::kThrowNotConstructor); | 1741 __ TailCallRuntime(Runtime::kThrowNotConstructor); |
| 1746 } | 1742 } |
| 1747 | 1743 |
| 1748 // 4c. The new.target is not a constructor, throw an appropriate TypeError. | 1744 // 4c. The new.target is not a constructor, throw an appropriate TypeError. |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2266 | 2262 |
| 2267 __ bind(&stack_overflow); | 2263 __ bind(&stack_overflow); |
| 2268 { | 2264 { |
| 2269 FrameScope frame(masm, StackFrame::MANUAL); | 2265 FrameScope frame(masm, StackFrame::MANUAL); |
| 2270 __ CallRuntime(Runtime::kThrowStackOverflow); | 2266 __ CallRuntime(Runtime::kThrowStackOverflow); |
| 2271 __ int3(); | 2267 __ int3(); |
| 2272 } | 2268 } |
| 2273 } | 2269 } |
| 2274 | 2270 |
| 2275 // static | 2271 // static |
| 2276 void Builtins::Generate_Apply(MacroAssembler* masm) { | 2272 void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm, |
| 2273 Handle<Code> code) { |
| 2277 // ----------- S t a t e ------------- | 2274 // ----------- S t a t e ------------- |
| 2278 // -- rax : argumentsList | |
| 2279 // -- rdi : target | 2275 // -- rdi : target |
| 2280 // -- rdx : new.target (checked to be constructor or undefined) | 2276 // -- rax : number of parameters on the stack (not including the receiver) |
| 2281 // -- rsp[0] : return address. | 2277 // -- rbx : arguments list (a FixedArray) |
| 2282 // -- rsp[8] : thisArgument | 2278 // -- rcx : len (number of elements to push from args) |
| 2279 // -- rdx : new.target (for [[Construct]]) |
| 2280 // -- rsp[0] : return address |
| 2283 // ----------------------------------- | 2281 // ----------------------------------- |
| 2284 | 2282 __ AssertFixedArray(rbx); |
| 2285 // Create the list of arguments from the array-like argumentsList. | |
| 2286 { | |
| 2287 Label create_arguments, create_array, create_holey_array, create_runtime, | |
| 2288 done_create; | |
| 2289 __ JumpIfSmi(rax, &create_runtime); | |
| 2290 | |
| 2291 // Load the map of argumentsList into rcx. | |
| 2292 __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset)); | |
| 2293 | |
| 2294 // Load native context into rbx. | |
| 2295 __ movp(rbx, NativeContextOperand()); | |
| 2296 | |
| 2297 // Check if argumentsList is an (unmodified) arguments object. | |
| 2298 __ cmpp(rcx, ContextOperand(rbx, Context::SLOPPY_ARGUMENTS_MAP_INDEX)); | |
| 2299 __ j(equal, &create_arguments); | |
| 2300 __ cmpp(rcx, ContextOperand(rbx, Context::STRICT_ARGUMENTS_MAP_INDEX)); | |
| 2301 __ j(equal, &create_arguments); | |
| 2302 | |
| 2303 // Check if argumentsList is a fast JSArray. | |
| 2304 __ CmpInstanceType(rcx, JS_ARRAY_TYPE); | |
| 2305 __ j(equal, &create_array); | |
| 2306 | |
| 2307 // Ask the runtime to create the list (actually a FixedArray). | |
| 2308 __ bind(&create_runtime); | |
| 2309 { | |
| 2310 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 2311 __ Push(rdi); | |
| 2312 __ Push(rdx); | |
| 2313 __ Push(rax); | |
| 2314 __ CallRuntime(Runtime::kCreateListFromArrayLike); | |
| 2315 __ Pop(rdx); | |
| 2316 __ Pop(rdi); | |
| 2317 __ SmiToInteger32(rbx, FieldOperand(rax, FixedArray::kLengthOffset)); | |
| 2318 } | |
| 2319 __ jmp(&done_create); | |
| 2320 | |
| 2321 // Try to create the list from an arguments object. | |
| 2322 __ bind(&create_arguments); | |
| 2323 __ movp(rbx, FieldOperand(rax, JSArgumentsObject::kLengthOffset)); | |
| 2324 __ movp(rcx, FieldOperand(rax, JSObject::kElementsOffset)); | |
| 2325 __ cmpp(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); | |
| 2326 __ j(not_equal, &create_runtime); | |
| 2327 __ SmiToInteger32(rbx, rbx); | |
| 2328 __ movp(rax, rcx); | |
| 2329 __ jmp(&done_create); | |
| 2330 | |
| 2331 __ bind(&create_holey_array); | |
| 2332 // For holey JSArrays we need to check that the array prototype chain | |
| 2333 // protector is intact and our prototype is the Array.prototype actually. | |
| 2334 __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset)); | |
| 2335 __ movp(rcx, FieldOperand(rcx, Map::kPrototypeOffset)); | |
| 2336 __ cmpp(rcx, ContextOperand(rbx, Context::INITIAL_ARRAY_PROTOTYPE_INDEX)); | |
| 2337 __ j(not_equal, &create_runtime); | |
| 2338 __ LoadRoot(rcx, Heap::kArrayProtectorRootIndex); | |
| 2339 __ Cmp(FieldOperand(rcx, PropertyCell::kValueOffset), | |
| 2340 Smi::FromInt(Isolate::kProtectorValid)); | |
| 2341 __ j(not_equal, &create_runtime); | |
| 2342 __ SmiToInteger32(rbx, FieldOperand(rax, JSArray::kLengthOffset)); | |
| 2343 __ movp(rax, FieldOperand(rax, JSArray::kElementsOffset)); | |
| 2344 __ jmp(&done_create); | |
| 2345 | |
| 2346 // Try to create the list from a JSArray object. | |
| 2347 __ bind(&create_array); | |
| 2348 __ movzxbp(rcx, FieldOperand(rcx, Map::kBitField2Offset)); | |
| 2349 __ DecodeField<Map::ElementsKindBits>(rcx); | |
| 2350 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
| 2351 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
| 2352 STATIC_ASSERT(FAST_ELEMENTS == 2); | |
| 2353 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | |
| 2354 __ cmpl(rcx, Immediate(FAST_HOLEY_SMI_ELEMENTS)); | |
| 2355 __ j(equal, &create_holey_array); | |
| 2356 __ cmpl(rcx, Immediate(FAST_HOLEY_ELEMENTS)); | |
| 2357 __ j(equal, &create_holey_array); | |
| 2358 __ j(above, &create_runtime); | |
| 2359 __ SmiToInteger32(rbx, FieldOperand(rax, JSArray::kLengthOffset)); | |
| 2360 __ movp(rax, FieldOperand(rax, JSArray::kElementsOffset)); | |
| 2361 | |
| 2362 __ bind(&done_create); | |
| 2363 } | |
| 2364 | 2283 |
| 2365 // Check for stack overflow. | 2284 // Check for stack overflow. |
| 2366 { | 2285 { |
| 2367 // Check the stack for overflow. We are not trying to catch interruptions | 2286 // Check the stack for overflow. We are not trying to catch interruptions |
| 2368 // (i.e. debug break and preemption) here, so check the "real stack limit". | 2287 // (i.e. debug break and preemption) here, so check the "real stack limit". |
| 2369 Label done; | 2288 Label done; |
| 2370 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex); | 2289 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex); |
| 2371 __ movp(rcx, rsp); | 2290 __ movp(r8, rsp); |
| 2372 // Make rcx the space we have left. The stack might already be overflowed | 2291 // Make r8 the space we have left. The stack might already be overflowed |
| 2373 // here which will cause rcx to become negative. | 2292 // here which will cause r8 to become negative. |
| 2374 __ subp(rcx, kScratchRegister); | 2293 __ subp(r8, kScratchRegister); |
| 2375 __ sarp(rcx, Immediate(kPointerSizeLog2)); | 2294 __ sarp(r8, Immediate(kPointerSizeLog2)); |
| 2376 // Check if the arguments will overflow the stack. | 2295 // Check if the arguments will overflow the stack. |
| 2377 __ cmpp(rcx, rbx); | 2296 __ cmpp(r8, rcx); |
| 2378 __ j(greater, &done, Label::kNear); // Signed comparison. | 2297 __ j(greater, &done, Label::kNear); // Signed comparison. |
| 2379 __ TailCallRuntime(Runtime::kThrowStackOverflow); | 2298 __ TailCallRuntime(Runtime::kThrowStackOverflow); |
| 2380 __ bind(&done); | 2299 __ bind(&done); |
| 2381 } | 2300 } |
| 2382 | 2301 |
| 2383 // ----------- S t a t e ------------- | 2302 // Push additional arguments onto the stack. |
| 2384 // -- rdi : target | |
| 2385 // -- rax : args (a FixedArray built from argumentsList) | |
| 2386 // -- rbx : len (number of elements to push from args) | |
| 2387 // -- rdx : new.target (checked to be constructor or undefined) | |
| 2388 // -- rsp[0] : return address. | |
| 2389 // -- rsp[8] : thisArgument | |
| 2390 // ----------------------------------- | |
| 2391 | |
| 2392 // Push arguments onto the stack (thisArgument is already on the stack). | |
| 2393 { | 2303 { |
| 2394 __ PopReturnAddressTo(r8); | 2304 __ PopReturnAddressTo(r8); |
| 2395 __ Set(rcx, 0); | 2305 __ Set(r9, 0); |
| 2396 Label done, push, loop; | 2306 Label done, push, loop; |
| 2397 __ bind(&loop); | 2307 __ bind(&loop); |
| 2398 __ cmpl(rcx, rbx); | 2308 __ cmpl(r9, rcx); |
| 2399 __ j(equal, &done, Label::kNear); | 2309 __ j(equal, &done, Label::kNear); |
| 2400 // Turn the hole into undefined as we go. | 2310 // Turn the hole into undefined as we go. |
| 2401 __ movp(r9, FieldOperand(rax, rcx, times_pointer_size, | 2311 __ movp(r11, |
| 2402 FixedArray::kHeaderSize)); | 2312 FieldOperand(rbx, r9, times_pointer_size, FixedArray::kHeaderSize)); |
| 2403 __ CompareRoot(r9, Heap::kTheHoleValueRootIndex); | 2313 __ CompareRoot(r11, Heap::kTheHoleValueRootIndex); |
| 2404 __ j(not_equal, &push, Label::kNear); | 2314 __ j(not_equal, &push, Label::kNear); |
| 2405 __ LoadRoot(r9, Heap::kUndefinedValueRootIndex); | 2315 __ LoadRoot(r11, Heap::kUndefinedValueRootIndex); |
| 2406 __ bind(&push); | 2316 __ bind(&push); |
| 2407 __ Push(r9); | 2317 __ Push(r11); |
| 2408 __ incl(rcx); | 2318 __ incl(r9); |
| 2409 __ jmp(&loop); | 2319 __ jmp(&loop); |
| 2410 __ bind(&done); | 2320 __ bind(&done); |
| 2411 __ PushReturnAddressFrom(r8); | 2321 __ PushReturnAddressFrom(r8); |
| 2412 __ Move(rax, rcx); | 2322 __ addq(rax, r9); |
| 2413 } | 2323 } |
| 2414 | 2324 |
| 2415 // Dispatch to Call or Construct depending on whether new.target is undefined. | 2325 // Tail-call to the actual Call or Construct builtin. |
| 2416 { | 2326 __ Jump(code, RelocInfo::CODE_TARGET); |
| 2417 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); | |
| 2418 __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
| 2419 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | |
| 2420 } | |
| 2421 } | 2327 } |
| 2422 | 2328 |
| 2423 // static | 2329 // static |
| 2424 void Builtins::Generate_ForwardVarargs(MacroAssembler* masm, | 2330 void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm, |
| 2425 Handle<Code> code) { | 2331 Handle<Code> code) { |
| 2426 // ----------- S t a t e ------------- | 2332 // ----------- S t a t e ------------- |
| 2427 // -- rax : the number of arguments (not including the receiver) | 2333 // -- rax : the number of arguments (not including the receiver) |
| 2428 // -- rdx : the new target (for [[Construct]] calls) | 2334 // -- rdx : the new target (for [[Construct]] calls) |
| 2429 // -- rdi : the target to call (can be any Object) | 2335 // -- rdi : the target to call (can be any Object) |
| 2430 // -- rcx : start index (to support rest parameters) | 2336 // -- rcx : start index (to support rest parameters) |
| 2431 // ----------------------------------- | 2337 // ----------------------------------- |
| 2432 | 2338 |
| 2433 // Check if we have an arguments adaptor frame below the function frame. | 2339 // Check if we have an arguments adaptor frame below the function frame. |
| 2434 Label arguments_adaptor, arguments_done; | 2340 Label arguments_adaptor, arguments_done; |
| 2435 __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2341 __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| (...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3240 // Now jump to the instructions of the returned code object. | 3146 // Now jump to the instructions of the returned code object. |
| 3241 __ jmp(r11); | 3147 __ jmp(r11); |
| 3242 } | 3148 } |
| 3243 | 3149 |
| 3244 #undef __ | 3150 #undef __ |
| 3245 | 3151 |
| 3246 } // namespace internal | 3152 } // namespace internal |
| 3247 } // namespace v8 | 3153 } // namespace v8 |
| 3248 | 3154 |
| 3249 #endif // V8_TARGET_ARCH_X64 | 3155 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |