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_Varargs(MacroAssembler* masm, Handle<Code> code) { |
2277 // ----------- S t a t e ------------- | 2273 // ----------- S t a t e ------------- |
2278 // -- rax : argumentsList | |
2279 // -- rdi : target | 2274 // -- rdi : target |
2280 // -- rdx : new.target (checked to be constructor or undefined) | 2275 // -- rax : number of parameters on the stack (not including the receiver) |
2281 // -- rsp[0] : return address. | 2276 // -- rbx : arguments list (a FixedArray) |
2282 // -- rsp[8] : thisArgument | 2277 // -- rcx : len (number of elements to push from args) |
| 2278 // -- rdx : new.target (for [[Construct]]) |
| 2279 // -- rsp[0] : return address |
2283 // ----------------------------------- | 2280 // ----------------------------------- |
2284 | 2281 __ 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 | 2282 |
2365 // Check for stack overflow. | 2283 // Check for stack overflow. |
2366 { | 2284 { |
2367 // Check the stack for overflow. We are not trying to catch interruptions | 2285 // 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". | 2286 // (i.e. debug break and preemption) here, so check the "real stack limit". |
2369 Label done; | 2287 Label done; |
2370 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex); | 2288 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex); |
2371 __ movp(rcx, rsp); | 2289 __ movp(r8, rsp); |
2372 // Make rcx the space we have left. The stack might already be overflowed | 2290 // Make r8 the space we have left. The stack might already be overflowed |
2373 // here which will cause rcx to become negative. | 2291 // here which will cause r8 to become negative. |
2374 __ subp(rcx, kScratchRegister); | 2292 __ subp(r8, kScratchRegister); |
2375 __ sarp(rcx, Immediate(kPointerSizeLog2)); | 2293 __ sarp(r8, Immediate(kPointerSizeLog2)); |
2376 // Check if the arguments will overflow the stack. | 2294 // Check if the arguments will overflow the stack. |
2377 __ cmpp(rcx, rbx); | 2295 __ cmpp(r8, rcx); |
2378 __ j(greater, &done, Label::kNear); // Signed comparison. | 2296 __ j(greater, &done, Label::kNear); // Signed comparison. |
2379 __ TailCallRuntime(Runtime::kThrowStackOverflow); | 2297 __ TailCallRuntime(Runtime::kThrowStackOverflow); |
2380 __ bind(&done); | 2298 __ bind(&done); |
2381 } | 2299 } |
2382 | 2300 |
2383 // ----------- S t a t e ------------- | 2301 // 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 { | 2302 { |
2394 __ PopReturnAddressTo(r8); | 2303 __ PopReturnAddressTo(r8); |
2395 __ Set(rcx, 0); | 2304 __ Set(r9, 0); |
2396 Label done, push, loop; | 2305 Label done, push, loop; |
2397 __ bind(&loop); | 2306 __ bind(&loop); |
2398 __ cmpl(rcx, rbx); | 2307 __ cmpl(r9, rcx); |
2399 __ j(equal, &done, Label::kNear); | 2308 __ j(equal, &done, Label::kNear); |
2400 // Turn the hole into undefined as we go. | 2309 // Turn the hole into undefined as we go. |
2401 __ movp(r9, FieldOperand(rax, rcx, times_pointer_size, | 2310 __ movp(r11, |
2402 FixedArray::kHeaderSize)); | 2311 FieldOperand(rbx, r9, times_pointer_size, FixedArray::kHeaderSize)); |
2403 __ CompareRoot(r9, Heap::kTheHoleValueRootIndex); | 2312 __ CompareRoot(r11, Heap::kTheHoleValueRootIndex); |
2404 __ j(not_equal, &push, Label::kNear); | 2313 __ j(not_equal, &push, Label::kNear); |
2405 __ LoadRoot(r9, Heap::kUndefinedValueRootIndex); | 2314 __ LoadRoot(r11, Heap::kUndefinedValueRootIndex); |
2406 __ bind(&push); | 2315 __ bind(&push); |
2407 __ Push(r9); | 2316 __ Push(r11); |
2408 __ incl(rcx); | 2317 __ incl(r9); |
2409 __ jmp(&loop); | 2318 __ jmp(&loop); |
2410 __ bind(&done); | 2319 __ bind(&done); |
2411 __ PushReturnAddressFrom(r8); | 2320 __ PushReturnAddressFrom(r8); |
2412 __ Move(rax, rcx); | 2321 __ addq(rax, r9); |
2413 } | 2322 } |
2414 | 2323 |
2415 // Dispatch to Call or Construct depending on whether new.target is undefined. | 2324 // Tail-call to the actual Call or Construct builtin. |
2416 { | 2325 __ 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 } | 2326 } |
2422 | 2327 |
2423 // static | 2328 // static |
2424 void Builtins::Generate_ForwardVarargs(MacroAssembler* masm, | 2329 void Builtins::Generate_ForwardVarargs(MacroAssembler* masm, |
2425 Handle<Code> code) { | 2330 Handle<Code> code) { |
2426 // ----------- S t a t e ------------- | 2331 // ----------- S t a t e ------------- |
2427 // -- rax : the number of arguments (not including the receiver) | 2332 // -- rax : the number of arguments (not including the receiver) |
2428 // -- rdx : the new target (for [[Construct]] calls) | 2333 // -- rdx : the new target (for [[Construct]] calls) |
2429 // -- rdi : the target to call (can be any Object) | 2334 // -- rdi : the target to call (can be any Object) |
2430 // -- rcx : start index (to support rest parameters) | 2335 // -- rcx : start index (to support rest parameters) |
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3240 // Now jump to the instructions of the returned code object. | 3145 // Now jump to the instructions of the returned code object. |
3241 __ jmp(r11); | 3146 __ jmp(r11); |
3242 } | 3147 } |
3243 | 3148 |
3244 #undef __ | 3149 #undef __ |
3245 | 3150 |
3246 } // namespace internal | 3151 } // namespace internal |
3247 } // namespace v8 | 3152 } // namespace v8 |
3248 | 3153 |
3249 #endif // V8_TARGET_ARCH_X64 | 3154 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |