Chromium Code Reviews| 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_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 1566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1577 | 1577 |
| 1578 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 1578 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
| 1579 // by calling the runtime system. | 1579 // by calling the runtime system. |
| 1580 __ bind(&slow); | 1580 __ bind(&slow); |
| 1581 __ push(a1); | 1581 __ push(a1); |
| 1582 __ TailCallRuntime(Runtime::kArguments, 1, 1); | 1582 __ TailCallRuntime(Runtime::kArguments, 1, 1); |
| 1583 } | 1583 } |
| 1584 | 1584 |
| 1585 | 1585 |
| 1586 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { | 1586 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { |
| 1587 // sp[0] : number of parameters | 1587 // a1 : function |
| 1588 // sp[4] : receiver displacement | 1588 // a2 : number of parameters (tagged) |
| 1589 // sp[8] : function | 1589 // a3 : parameters pointer |
| 1590 | |
| 1591 DCHECK(a1.is(ArgumentsAccessNewDescriptor::function())); | |
| 1592 DCHECK(a2.is(ArgumentsAccessNewDescriptor::parameter_count())); | |
| 1593 DCHECK(a3.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | |
| 1590 | 1594 |
| 1591 // Check if the calling frame is an arguments adaptor frame. | 1595 // Check if the calling frame is an arguments adaptor frame. |
| 1592 Label runtime; | 1596 Label runtime; |
| 1593 __ lw(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1597 __ lw(t0, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 1594 __ lw(a2, MemOperand(a3, StandardFrameConstants::kContextOffset)); | 1598 __ lw(a0, MemOperand(t0, StandardFrameConstants::kContextOffset)); |
| 1595 __ Branch(&runtime, | 1599 __ Branch(&runtime, ne, a0, |
| 1596 ne, | |
| 1597 a2, | |
| 1598 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1600 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 1599 | 1601 |
| 1600 // Patch the arguments.length and the parameters pointer in the current frame. | 1602 // Patch the arguments.length and the parameters pointer in the current frame. |
| 1601 __ lw(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 1603 __ lw(a2, MemOperand(t0, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 1602 __ sw(a2, MemOperand(sp, 0 * kPointerSize)); | |
| 1603 __ sll(t3, a2, 1); | 1604 __ sll(t3, a2, 1); |
| 1604 __ Addu(a3, a3, Operand(t3)); | 1605 __ Addu(t0, t0, Operand(t3)); |
| 1605 __ addiu(a3, a3, StandardFrameConstants::kCallerSPOffset); | 1606 __ addiu(a3, t0, StandardFrameConstants::kCallerSPOffset); |
| 1606 __ sw(a3, MemOperand(sp, 1 * kPointerSize)); | |
| 1607 | 1607 |
| 1608 __ bind(&runtime); | 1608 __ bind(&runtime); |
| 1609 __ Push(a1, a3, a2); | |
| 1609 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); | 1610 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); |
| 1610 } | 1611 } |
| 1611 | 1612 |
| 1612 | 1613 |
| 1613 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { | 1614 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { |
| 1614 // Stack layout: | 1615 // a1 : function |
| 1615 // sp[0] : number of parameters (tagged) | 1616 // a2 : number of parameters (tagged) |
| 1616 // sp[4] : address of receiver argument | 1617 // a3 : parameters pointer |
| 1617 // sp[8] : function | |
| 1618 // Registers used over whole function: | 1618 // Registers used over whole function: |
| 1619 // t2 : allocated object (tagged) | 1619 // t1 : arguments count (tagged) |
| 1620 // t5 : mapped parameter count (tagged) | 1620 // t2 : mapped parameter count (tagged) |
| 1621 | 1621 |
| 1622 __ lw(a1, MemOperand(sp, 0 * kPointerSize)); | 1622 DCHECK(a1.is(ArgumentsAccessNewDescriptor::function())); |
| 1623 // a1 = parameter count (tagged) | 1623 DCHECK(a2.is(ArgumentsAccessNewDescriptor::parameter_count())); |
| 1624 DCHECK(a3.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | |
| 1624 | 1625 |
| 1625 // Check if the calling frame is an arguments adaptor frame. | 1626 // Check if the calling frame is an arguments adaptor frame. |
| 1626 Label runtime; | 1627 Label adaptor_frame, try_allocate, runtime; |
| 1627 Label adaptor_frame, try_allocate; | 1628 __ lw(t0, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 1628 __ lw(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1629 __ lw(a0, MemOperand(t0, StandardFrameConstants::kContextOffset)); |
| 1629 __ lw(a2, MemOperand(a3, StandardFrameConstants::kContextOffset)); | 1630 __ Branch(&adaptor_frame, eq, a0, |
| 1630 __ Branch(&adaptor_frame, | |
| 1631 eq, | |
| 1632 a2, | |
| 1633 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1631 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 1634 | 1632 |
| 1635 // No adaptor, parameter count = argument count. | 1633 // No adaptor, parameter count = argument count. |
| 1636 __ mov(a2, a1); | 1634 __ mov(t1, a2); |
| 1637 __ b(&try_allocate); | 1635 __ Branch(USE_DELAY_SLOT, &try_allocate); |
| 1638 __ nop(); // Branch delay slot nop. | 1636 __ mov(t2, a2); // In delay slot. |
| 1639 | 1637 |
| 1640 // We have an adaptor frame. Patch the parameters pointer. | 1638 // We have an adaptor frame. Patch the parameters pointer. |
| 1641 __ bind(&adaptor_frame); | 1639 __ bind(&adaptor_frame); |
| 1642 __ lw(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 1640 __ lw(t1, MemOperand(t0, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 1643 __ sll(t6, a2, 1); | 1641 __ sll(t6, t1, 1); |
| 1644 __ Addu(a3, a3, Operand(t6)); | 1642 __ Addu(t0, t0, Operand(t6)); |
| 1645 __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset)); | 1643 __ Addu(a3, t0, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 1646 __ sw(a3, MemOperand(sp, 1 * kPointerSize)); | |
| 1647 | 1644 |
| 1648 // a1 = parameter count (tagged) | 1645 // t1 = argument count (tagged) |
| 1649 // a2 = argument count (tagged) | 1646 // t2 = parameter count (tagged) |
| 1650 // Compute the mapped parameter count = min(a1, a2) in a1. | 1647 // Compute the mapped parameter count = min(t2, t1) in t2. |
| 1651 Label skip_min; | 1648 Label skip_min; |
| 1652 __ Branch(&skip_min, lt, a1, Operand(a2)); | 1649 __ Branch(USE_DELAY_SLOT, &skip_min, lt, t2, Operand(t1)); |
| 1653 __ mov(a1, a2); | 1650 __ mov(t2, a2); // In delay slot. |
| 1651 __ mov(t2, t1); | |
| 1654 __ bind(&skip_min); | 1652 __ bind(&skip_min); |
| 1655 | 1653 |
| 1656 __ bind(&try_allocate); | 1654 __ bind(&try_allocate); |
| 1657 | 1655 |
| 1658 // Compute the sizes of backing store, parameter map, and arguments object. | 1656 // Compute the sizes of backing store, parameter map, and arguments object. |
| 1659 // 1. Parameter map, has 2 extra words containing context and backing store. | 1657 // 1. Parameter map, has 2 extra words containing context and backing store. |
| 1660 const int kParameterMapHeaderSize = | 1658 const int kParameterMapHeaderSize = |
| 1661 FixedArray::kHeaderSize + 2 * kPointerSize; | 1659 FixedArray::kHeaderSize + 2 * kPointerSize; |
| 1662 // If there are no mapped parameters, we do not need the parameter_map. | 1660 // If there are no mapped parameters, we do not need the parameter_map. |
| 1663 Label param_map_size; | 1661 Label param_map_size; |
| 1664 DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); | 1662 DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); |
| 1665 __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, a1, Operand(zero_reg)); | 1663 __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, t2, Operand(zero_reg)); |
| 1666 __ mov(t5, zero_reg); // In delay slot: param map size = 0 when a1 == 0. | 1664 __ mov(t5, zero_reg); // In delay slot: param map size = 0 when a1 == 0. |
| 1667 __ sll(t5, a1, 1); | 1665 __ sll(t5, t2, 1); |
| 1668 __ addiu(t5, t5, kParameterMapHeaderSize); | 1666 __ addiu(t5, t5, kParameterMapHeaderSize); |
| 1669 __ bind(¶m_map_size); | 1667 __ bind(¶m_map_size); |
| 1670 | 1668 |
| 1671 // 2. Backing store. | 1669 // 2. Backing store. |
| 1672 __ sll(t6, a2, 1); | 1670 __ sll(t6, t1, 1); |
| 1673 __ Addu(t5, t5, Operand(t6)); | 1671 __ Addu(t5, t5, Operand(t6)); |
| 1674 __ Addu(t5, t5, Operand(FixedArray::kHeaderSize)); | 1672 __ Addu(t5, t5, Operand(FixedArray::kHeaderSize)); |
| 1675 | 1673 |
| 1676 // 3. Arguments object. | 1674 // 3. Arguments object. |
| 1677 __ Addu(t5, t5, Operand(Heap::kSloppyArgumentsObjectSize)); | 1675 __ Addu(t5, t5, Operand(Heap::kSloppyArgumentsObjectSize)); |
| 1678 | 1676 |
| 1679 // Do the allocation of all three objects in one go. | 1677 // Do the allocation of all three objects in one go. |
| 1680 __ Allocate(t5, v0, a3, t0, &runtime, TAG_OBJECT); | 1678 __ Allocate(t5, v0, t0, t5, &runtime, TAG_OBJECT); |
| 1681 | 1679 |
| 1682 // v0 = address of new object(s) (tagged) | 1680 // v0 = address of new object(s) (tagged) |
| 1683 // a2 = argument count (smi-tagged) | 1681 // a2 = argument count (smi-tagged) |
| 1684 // Get the arguments boilerplate from the current native context into t0. | 1682 // Get the arguments boilerplate from the current native context into t0. |
| 1685 const int kNormalOffset = | 1683 const int kNormalOffset = |
| 1686 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); | 1684 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); |
| 1687 const int kAliasedOffset = | 1685 const int kAliasedOffset = |
| 1688 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); | 1686 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); |
| 1689 | 1687 |
| 1690 __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1688 __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 1691 __ lw(t0, FieldMemOperand(t0, GlobalObject::kNativeContextOffset)); | 1689 __ lw(t0, FieldMemOperand(t0, GlobalObject::kNativeContextOffset)); |
| 1692 Label skip2_ne, skip2_eq; | 1690 Label skip2_ne, skip2_eq; |
| 1693 __ Branch(&skip2_ne, ne, a1, Operand(zero_reg)); | 1691 __ Branch(&skip2_ne, ne, t2, Operand(zero_reg)); |
| 1694 __ lw(t0, MemOperand(t0, kNormalOffset)); | 1692 __ lw(t0, MemOperand(t0, kNormalOffset)); |
| 1695 __ bind(&skip2_ne); | 1693 __ bind(&skip2_ne); |
| 1696 | 1694 |
| 1697 __ Branch(&skip2_eq, eq, a1, Operand(zero_reg)); | 1695 __ Branch(&skip2_eq, eq, a1, Operand(zero_reg)); |
|
paul.l...
2015/09/24 04:07:05
The main bug is this a1 should have been changed t
paul.l...
2015/09/24 04:33:58
The 2 branches here (in older code also) bugged me
| |
| 1698 __ lw(t0, MemOperand(t0, kAliasedOffset)); | 1696 __ lw(t0, MemOperand(t0, kAliasedOffset)); |
| 1699 __ bind(&skip2_eq); | 1697 __ bind(&skip2_eq); |
| 1700 | 1698 |
| 1701 // v0 = address of new object (tagged) | 1699 // v0 = address of new object (tagged) |
| 1702 // a1 = mapped parameter count (tagged) | |
| 1703 // a2 = argument count (smi-tagged) | 1700 // a2 = argument count (smi-tagged) |
| 1704 // t0 = address of arguments map (tagged) | 1701 // t0 = address of arguments map (tagged) |
| 1702 // t2 = mapped parameter count (tagged) | |
| 1705 __ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset)); | 1703 __ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset)); |
| 1706 __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex); | 1704 __ LoadRoot(t5, Heap::kEmptyFixedArrayRootIndex); |
| 1707 __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset)); | 1705 __ sw(t5, FieldMemOperand(v0, JSObject::kPropertiesOffset)); |
| 1708 __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); | 1706 __ sw(t5, FieldMemOperand(v0, JSObject::kElementsOffset)); |
| 1709 | 1707 |
| 1710 // Set up the callee in-object property. | 1708 // Set up the callee in-object property. |
| 1711 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); | 1709 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); |
| 1712 __ lw(a3, MemOperand(sp, 2 * kPointerSize)); | 1710 __ AssertNotSmi(a1); |
| 1713 __ AssertNotSmi(a3); | |
| 1714 const int kCalleeOffset = JSObject::kHeaderSize + | 1711 const int kCalleeOffset = JSObject::kHeaderSize + |
| 1715 Heap::kArgumentsCalleeIndex * kPointerSize; | 1712 Heap::kArgumentsCalleeIndex * kPointerSize; |
| 1716 __ sw(a3, FieldMemOperand(v0, kCalleeOffset)); | 1713 __ sw(a1, FieldMemOperand(v0, kCalleeOffset)); |
| 1717 | 1714 |
| 1718 // Use the length (smi tagged) and set that as an in-object property too. | 1715 // Use the length (smi tagged) and set that as an in-object property too. |
| 1719 __ AssertSmi(a2); | 1716 __ AssertSmi(t0); |
| 1720 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 1717 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 1721 const int kLengthOffset = JSObject::kHeaderSize + | 1718 const int kLengthOffset = JSObject::kHeaderSize + |
| 1722 Heap::kArgumentsLengthIndex * kPointerSize; | 1719 Heap::kArgumentsLengthIndex * kPointerSize; |
| 1723 __ sw(a2, FieldMemOperand(v0, kLengthOffset)); | 1720 __ sw(t0, FieldMemOperand(v0, kLengthOffset)); |
| 1724 | 1721 |
| 1725 // Set up the elements pointer in the allocated arguments object. | 1722 // Set up the elements pointer in the allocated arguments object. |
| 1726 // If we allocated a parameter map, t0 will point there, otherwise | 1723 // If we allocated a parameter map, t0 will point there, otherwise |
| 1727 // it will point to the backing store. | 1724 // it will point to the backing store. |
| 1728 __ Addu(t0, v0, Operand(Heap::kSloppyArgumentsObjectSize)); | 1725 __ Addu(t0, v0, Operand(Heap::kSloppyArgumentsObjectSize)); |
| 1729 __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset)); | 1726 __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset)); |
| 1730 | 1727 |
| 1731 // v0 = address of new object (tagged) | 1728 // v0 = address of new object (tagged) |
| 1732 // a1 = mapped parameter count (tagged) | |
| 1733 // a2 = argument count (tagged) | 1729 // a2 = argument count (tagged) |
| 1734 // t0 = address of parameter map or backing store (tagged) | 1730 // t0 = address of parameter map or backing store (tagged) |
| 1731 // t2 = mapped parameter count (tagged) | |
| 1735 // Initialize parameter map. If there are no mapped arguments, we're done. | 1732 // Initialize parameter map. If there are no mapped arguments, we're done. |
| 1736 Label skip_parameter_map; | 1733 Label skip_parameter_map; |
| 1737 Label skip3; | 1734 Label skip3; |
| 1738 __ Branch(&skip3, ne, a1, Operand(Smi::FromInt(0))); | 1735 __ Branch(&skip3, ne, t2, Operand(Smi::FromInt(0))); |
| 1739 // Move backing store address to a3, because it is | 1736 // Move backing store address to a3, because it is |
| 1740 // expected there when filling in the unmapped arguments. | 1737 // expected there when filling in the unmapped arguments. |
| 1741 __ mov(a3, t0); | 1738 __ mov(a1, t0); |
| 1742 __ bind(&skip3); | 1739 __ bind(&skip3); |
| 1743 | 1740 |
| 1744 __ Branch(&skip_parameter_map, eq, a1, Operand(Smi::FromInt(0))); | 1741 __ Branch(&skip_parameter_map, eq, t2, Operand(Smi::FromInt(0))); |
| 1745 | 1742 |
| 1746 __ LoadRoot(t2, Heap::kSloppyArgumentsElementsMapRootIndex); | 1743 __ LoadRoot(t1, Heap::kSloppyArgumentsElementsMapRootIndex); |
| 1747 __ sw(t2, FieldMemOperand(t0, FixedArray::kMapOffset)); | 1744 __ sw(t1, FieldMemOperand(t0, FixedArray::kMapOffset)); |
| 1748 __ Addu(t2, a1, Operand(Smi::FromInt(2))); | 1745 __ Addu(t1, t2, Operand(Smi::FromInt(2))); |
| 1749 __ sw(t2, FieldMemOperand(t0, FixedArray::kLengthOffset)); | 1746 __ sw(t1, FieldMemOperand(t0, FixedArray::kLengthOffset)); |
| 1750 __ sw(cp, FieldMemOperand(t0, FixedArray::kHeaderSize + 0 * kPointerSize)); | 1747 __ sw(cp, FieldMemOperand(t0, FixedArray::kHeaderSize + 0 * kPointerSize)); |
| 1751 __ sll(t6, a1, 1); | 1748 __ sll(t6, t2, 1); |
| 1752 __ Addu(t2, t0, Operand(t6)); | 1749 __ Addu(t1, t0, Operand(t6)); |
| 1753 __ Addu(t2, t2, Operand(kParameterMapHeaderSize)); | 1750 __ Addu(t1, t1, Operand(kParameterMapHeaderSize)); |
| 1754 __ sw(t2, FieldMemOperand(t0, FixedArray::kHeaderSize + 1 * kPointerSize)); | 1751 __ sw(t1, FieldMemOperand(t0, FixedArray::kHeaderSize + 1 * kPointerSize)); |
| 1755 | 1752 |
| 1756 // Copy the parameter slots and the holes in the arguments. | 1753 // Copy the parameter slots and the holes in the arguments. |
| 1757 // We need to fill in mapped_parameter_count slots. They index the context, | 1754 // We need to fill in mapped_parameter_count slots. They index the context, |
| 1758 // where parameters are stored in reverse order, at | 1755 // where parameters are stored in reverse order, at |
| 1759 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | 1756 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 |
| 1760 // The mapped parameter thus need to get indices | 1757 // The mapped parameter thus need to get indices |
| 1761 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | 1758 // MIN_CONTEXT_SLOTS+parameter_count-1 .. |
| 1762 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | 1759 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count |
| 1763 // We loop from right to left. | 1760 // We loop from right to left. |
| 1764 Label parameters_loop, parameters_test; | 1761 Label parameters_loop, parameters_test; |
| 1765 __ mov(t2, a1); | 1762 __ mov(t1, t2); |
| 1766 __ lw(t5, MemOperand(sp, 0 * kPointerSize)); | 1763 __ Addu(t5, a2, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); |
| 1767 __ Addu(t5, t5, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); | 1764 __ Subu(t5, t5, Operand(t2)); |
| 1768 __ Subu(t5, t5, Operand(a1)); | |
| 1769 __ LoadRoot(t3, Heap::kTheHoleValueRootIndex); | 1765 __ LoadRoot(t3, Heap::kTheHoleValueRootIndex); |
| 1770 __ sll(t6, t2, 1); | 1766 __ sll(t6, t1, 1); |
| 1771 __ Addu(a3, t0, Operand(t6)); | 1767 __ Addu(a1, t0, Operand(t6)); |
| 1772 __ Addu(a3, a3, Operand(kParameterMapHeaderSize)); | 1768 __ Addu(a1, a1, Operand(kParameterMapHeaderSize)); |
| 1773 | 1769 |
| 1774 // t2 = loop variable (tagged) | 1770 // a1 = address of backing store (tagged) |
| 1775 // a1 = mapping index (tagged) | |
| 1776 // a3 = address of backing store (tagged) | |
| 1777 // t0 = address of parameter map (tagged) | 1771 // t0 = address of parameter map (tagged) |
| 1778 // t1 = temporary scratch (a.o., for address calculation) | 1772 // a0 = temporary scratch (a.o., for address calculation) |
| 1773 // t1 = loop variable (tagged) | |
| 1779 // t3 = the hole value | 1774 // t3 = the hole value |
| 1780 __ jmp(¶meters_test); | 1775 __ jmp(¶meters_test); |
| 1781 | 1776 |
| 1782 __ bind(¶meters_loop); | 1777 __ bind(¶meters_loop); |
| 1783 __ Subu(t2, t2, Operand(Smi::FromInt(1))); | 1778 __ Subu(t1, t1, Operand(Smi::FromInt(1))); |
| 1784 __ sll(t1, t2, 1); | 1779 __ sll(a0, t1, 1); |
| 1785 __ Addu(t1, t1, Operand(kParameterMapHeaderSize - kHeapObjectTag)); | 1780 __ Addu(a0, a0, Operand(kParameterMapHeaderSize - kHeapObjectTag)); |
| 1786 __ Addu(t6, t0, t1); | 1781 __ Addu(t6, t0, a0); |
| 1787 __ sw(t5, MemOperand(t6)); | 1782 __ sw(t5, MemOperand(t6)); |
| 1788 __ Subu(t1, t1, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); | 1783 __ Subu(a0, a0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); |
| 1789 __ Addu(t6, a3, t1); | 1784 __ Addu(t6, a1, a0); |
| 1790 __ sw(t3, MemOperand(t6)); | 1785 __ sw(t3, MemOperand(t6)); |
| 1791 __ Addu(t5, t5, Operand(Smi::FromInt(1))); | 1786 __ Addu(t5, t5, Operand(Smi::FromInt(1))); |
| 1792 __ bind(¶meters_test); | 1787 __ bind(¶meters_test); |
| 1793 __ Branch(¶meters_loop, ne, t2, Operand(Smi::FromInt(0))); | 1788 __ Branch(¶meters_loop, ne, t1, Operand(Smi::FromInt(0))); |
| 1789 | |
| 1790 // t1 = argument count (tagged). | |
| 1791 __ lw(t1, FieldMemOperand(v0, kLengthOffset)); | |
| 1794 | 1792 |
| 1795 __ bind(&skip_parameter_map); | 1793 __ bind(&skip_parameter_map); |
| 1796 // a2 = argument count (tagged) | 1794 // v0 = address of new object (tagged) |
| 1797 // a3 = address of backing store (tagged) | 1795 // a1 = address of backing store (tagged) |
| 1798 // t1 = scratch | 1796 // t1 = argument count (tagged) |
| 1797 // t2 = mapped parameter count (tagged) | |
| 1798 // t5 = scratch | |
| 1799 // Copy arguments header and remaining slots (if there are any). | 1799 // Copy arguments header and remaining slots (if there are any). |
| 1800 __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex); | 1800 __ LoadRoot(t5, Heap::kFixedArrayMapRootIndex); |
| 1801 __ sw(t1, FieldMemOperand(a3, FixedArray::kMapOffset)); | 1801 __ sw(t5, FieldMemOperand(a1, FixedArray::kMapOffset)); |
| 1802 __ sw(a2, FieldMemOperand(a3, FixedArray::kLengthOffset)); | 1802 __ sw(t1, FieldMemOperand(a1, FixedArray::kLengthOffset)); |
| 1803 | 1803 |
| 1804 Label arguments_loop, arguments_test; | 1804 Label arguments_loop, arguments_test; |
| 1805 __ mov(t5, a1); | 1805 __ sll(t6, t2, 1); |
| 1806 __ lw(t0, MemOperand(sp, 1 * kPointerSize)); | 1806 __ Subu(a3, a3, Operand(t6)); |
| 1807 __ sll(t6, t5, 1); | |
| 1808 __ Subu(t0, t0, Operand(t6)); | |
| 1809 __ jmp(&arguments_test); | 1807 __ jmp(&arguments_test); |
| 1810 | 1808 |
| 1811 __ bind(&arguments_loop); | 1809 __ bind(&arguments_loop); |
| 1812 __ Subu(t0, t0, Operand(kPointerSize)); | 1810 __ Subu(a3, a3, Operand(kPointerSize)); |
| 1813 __ lw(t2, MemOperand(t0, 0)); | 1811 __ lw(t0, MemOperand(a3, 0)); |
| 1814 __ sll(t6, t5, 1); | 1812 __ sll(t6, t2, 1); |
| 1815 __ Addu(t1, a3, Operand(t6)); | 1813 __ Addu(t5, a1, Operand(t6)); |
| 1816 __ sw(t2, FieldMemOperand(t1, FixedArray::kHeaderSize)); | 1814 __ sw(t0, FieldMemOperand(t5, FixedArray::kHeaderSize)); |
| 1817 __ Addu(t5, t5, Operand(Smi::FromInt(1))); | 1815 __ Addu(t2, t2, Operand(Smi::FromInt(1))); |
| 1818 | 1816 |
| 1819 __ bind(&arguments_test); | 1817 __ bind(&arguments_test); |
| 1820 __ Branch(&arguments_loop, lt, t5, Operand(a2)); | 1818 __ Branch(&arguments_loop, lt, t2, Operand(t1)); |
| 1821 | 1819 |
| 1822 // Return and remove the on-stack parameters. | 1820 // Return. |
| 1823 __ DropAndRet(3); | 1821 __ Ret(); |
| 1824 | 1822 |
| 1825 // Do the runtime call to allocate the arguments object. | 1823 // Do the runtime call to allocate the arguments object. |
| 1826 // a2 = argument count (tagged) | 1824 // t1 = argument count (tagged) |
| 1827 __ bind(&runtime); | 1825 __ bind(&runtime); |
| 1828 __ sw(a2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count. | 1826 __ Push(a1, a3, t1); |
| 1829 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); | 1827 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); |
| 1830 } | 1828 } |
| 1831 | 1829 |
| 1832 | 1830 |
| 1833 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { | 1831 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { |
| 1834 // Return address is in ra. | 1832 // Return address is in ra. |
| 1835 Label slow; | 1833 Label slow; |
| 1836 | 1834 |
| 1837 Register receiver = LoadDescriptor::ReceiverRegister(); | 1835 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 1838 Register key = LoadDescriptor::NameRegister(); | 1836 Register key = LoadDescriptor::NameRegister(); |
| 1839 | 1837 |
| 1840 // Check that the key is an array index, that is Uint32. | 1838 // Check that the key is an array index, that is Uint32. |
| 1841 __ And(t0, key, Operand(kSmiTagMask | kSmiSignMask)); | 1839 __ And(t0, key, Operand(kSmiTagMask | kSmiSignMask)); |
| 1842 __ Branch(&slow, ne, t0, Operand(zero_reg)); | 1840 __ Branch(&slow, ne, t0, Operand(zero_reg)); |
| 1843 | 1841 |
| 1844 // Everything is fine, call runtime. | 1842 // Everything is fine, call runtime. |
| 1845 __ Push(receiver, key); // Receiver, key. | 1843 __ Push(receiver, key); // Receiver, key. |
| 1846 | 1844 |
| 1847 // Perform tail call to the entry. | 1845 // Perform tail call to the entry. |
| 1848 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor, 2, 1); | 1846 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor, 2, 1); |
| 1849 | 1847 |
| 1850 __ bind(&slow); | 1848 __ bind(&slow); |
| 1851 PropertyAccessCompiler::TailCallBuiltin( | 1849 PropertyAccessCompiler::TailCallBuiltin( |
| 1852 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); | 1850 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); |
| 1853 } | 1851 } |
| 1854 | 1852 |
| 1855 | 1853 |
| 1856 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | 1854 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { |
| 1857 // sp[0] : number of parameters | 1855 // a1 : function |
| 1858 // sp[4] : receiver displacement | 1856 // a2 : number of parameters (tagged) |
| 1859 // sp[8] : function | 1857 // a3 : parameters pointer |
| 1858 | |
| 1859 DCHECK(a1.is(ArgumentsAccessNewDescriptor::function())); | |
| 1860 DCHECK(a2.is(ArgumentsAccessNewDescriptor::parameter_count())); | |
| 1861 DCHECK(a3.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | |
| 1862 | |
| 1860 // Check if the calling frame is an arguments adaptor frame. | 1863 // Check if the calling frame is an arguments adaptor frame. |
| 1861 Label adaptor_frame, try_allocate, runtime; | 1864 Label try_allocate, runtime; |
| 1862 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1865 __ lw(t0, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 1863 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); | 1866 __ lw(a0, MemOperand(t0, StandardFrameConstants::kContextOffset)); |
| 1864 __ Branch(&adaptor_frame, | 1867 __ Branch(&try_allocate, ne, a0, |
| 1865 eq, | |
| 1866 a3, | |
| 1867 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1868 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 1868 | 1869 |
| 1869 // Get the length from the frame. | |
| 1870 __ lw(a1, MemOperand(sp, 0)); | |
| 1871 __ Branch(&try_allocate); | |
| 1872 | |
| 1873 // Patch the arguments.length and the parameters pointer. | 1870 // Patch the arguments.length and the parameters pointer. |
| 1874 __ bind(&adaptor_frame); | 1871 __ lw(a2, MemOperand(t0, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 1875 __ lw(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 1872 __ sll(at, a2, kPointerSizeLog2 - kSmiTagSize); |
| 1876 __ sw(a1, MemOperand(sp, 0)); | 1873 __ Addu(t0, t0, Operand(at)); |
| 1877 __ sll(at, a1, kPointerSizeLog2 - kSmiTagSize); | 1874 __ Addu(a3, t0, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 1878 __ Addu(a3, a2, Operand(at)); | |
| 1879 | |
| 1880 __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset)); | |
| 1881 __ sw(a3, MemOperand(sp, 1 * kPointerSize)); | |
| 1882 | 1875 |
| 1883 // Try the new space allocation. Start out with computing the size | 1876 // Try the new space allocation. Start out with computing the size |
| 1884 // of the arguments object and the elements array in words. | 1877 // of the arguments object and the elements array in words. |
| 1885 Label add_arguments_object; | 1878 Label add_arguments_object; |
| 1886 __ bind(&try_allocate); | 1879 __ bind(&try_allocate); |
| 1887 __ Branch(&add_arguments_object, eq, a1, Operand(zero_reg)); | 1880 __ Branch(&add_arguments_object, eq, a2, Operand(zero_reg)); |
| 1888 __ srl(a1, a1, kSmiTagSize); | 1881 __ SmiUntag(t5, a2); |
| 1889 | 1882 |
| 1890 __ Addu(a1, a1, Operand(FixedArray::kHeaderSize / kPointerSize)); | 1883 __ Addu(t5, t5, Operand(FixedArray::kHeaderSize / kPointerSize)); |
| 1891 __ bind(&add_arguments_object); | 1884 __ bind(&add_arguments_object); |
| 1892 __ Addu(a1, a1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize)); | 1885 __ Addu(t5, t5, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize)); |
| 1893 | 1886 |
| 1894 // Do the allocation of both objects in one go. | 1887 // Do the allocation of both objects in one go. |
| 1895 __ Allocate(a1, v0, a2, a3, &runtime, | 1888 __ Allocate(t5, v0, t0, t1, &runtime, |
| 1896 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); | 1889 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); |
| 1897 | 1890 |
| 1898 // Get the arguments boilerplate from the current native context. | 1891 // Get the arguments boilerplate from the current native context. |
| 1899 __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1892 __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 1900 __ lw(t0, FieldMemOperand(t0, GlobalObject::kNativeContextOffset)); | 1893 __ lw(t0, FieldMemOperand(t0, GlobalObject::kNativeContextOffset)); |
| 1901 __ lw(t0, MemOperand( | 1894 __ lw(t0, MemOperand( |
| 1902 t0, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX))); | 1895 t0, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX))); |
| 1903 | 1896 |
| 1904 __ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset)); | 1897 __ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset)); |
| 1905 __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex); | 1898 __ LoadRoot(t1, Heap::kEmptyFixedArrayRootIndex); |
| 1906 __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset)); | 1899 __ sw(t1, FieldMemOperand(v0, JSObject::kPropertiesOffset)); |
| 1907 __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); | 1900 __ sw(t1, FieldMemOperand(v0, JSObject::kElementsOffset)); |
| 1908 | 1901 |
| 1909 // Get the length (smi tagged) and set that as an in-object property too. | 1902 // Get the length (smi tagged) and set that as an in-object property too. |
| 1910 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 1903 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 1911 __ lw(a1, MemOperand(sp, 0 * kPointerSize)); | 1904 __ AssertSmi(a2); |
| 1912 __ AssertSmi(a1); | 1905 __ sw(a2, |
| 1913 __ sw(a1, FieldMemOperand(v0, JSObject::kHeaderSize + | 1906 FieldMemOperand(v0, JSObject::kHeaderSize + |
| 1914 Heap::kArgumentsLengthIndex * kPointerSize)); | 1907 Heap::kArgumentsLengthIndex * kPointerSize)); |
| 1915 | 1908 |
| 1916 Label done; | 1909 Label done; |
| 1917 __ Branch(&done, eq, a1, Operand(zero_reg)); | 1910 __ Branch(&done, eq, a2, Operand(zero_reg)); |
| 1918 | |
| 1919 // Get the parameters pointer from the stack. | |
| 1920 __ lw(a2, MemOperand(sp, 1 * kPointerSize)); | |
| 1921 | 1911 |
| 1922 // Set up the elements pointer in the allocated arguments object and | 1912 // Set up the elements pointer in the allocated arguments object and |
| 1923 // initialize the header in the elements fixed array. | 1913 // initialize the header in the elements fixed array. |
| 1924 __ Addu(t0, v0, Operand(Heap::kStrictArgumentsObjectSize)); | 1914 __ Addu(t0, v0, Operand(Heap::kStrictArgumentsObjectSize)); |
| 1925 __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset)); | 1915 __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset)); |
| 1926 __ LoadRoot(a3, Heap::kFixedArrayMapRootIndex); | 1916 __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex); |
| 1927 __ sw(a3, FieldMemOperand(t0, FixedArray::kMapOffset)); | 1917 __ sw(t1, FieldMemOperand(t0, FixedArray::kMapOffset)); |
| 1928 __ sw(a1, FieldMemOperand(t0, FixedArray::kLengthOffset)); | 1918 __ sw(a2, FieldMemOperand(t0, FixedArray::kLengthOffset)); |
| 1929 // Untag the length for the loop. | 1919 __ SmiUntag(a2); |
| 1930 __ srl(a1, a1, kSmiTagSize); | |
| 1931 | 1920 |
| 1932 // Copy the fixed array slots. | 1921 // Copy the fixed array slots. |
| 1933 Label loop; | 1922 Label loop; |
| 1934 // Set up t0 to point to the first array slot. | 1923 // Set up t0 to point to the first array slot. |
| 1935 __ Addu(t0, t0, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1924 __ Addu(t0, t0, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 1936 __ bind(&loop); | 1925 __ bind(&loop); |
| 1937 // Pre-decrement a2 with kPointerSize on each iteration. | 1926 // Pre-decrement a3 with kPointerSize on each iteration. |
| 1938 // Pre-decrement in order to skip receiver. | 1927 // Pre-decrement in order to skip receiver. |
| 1939 __ Addu(a2, a2, Operand(-kPointerSize)); | 1928 __ Addu(a3, a3, Operand(-kPointerSize)); |
| 1940 __ lw(a3, MemOperand(a2)); | 1929 __ lw(t1, MemOperand(a3)); |
| 1941 // Post-increment t0 with kPointerSize on each iteration. | 1930 // Post-increment t0 with kPointerSize on each iteration. |
| 1942 __ sw(a3, MemOperand(t0)); | 1931 __ sw(t1, MemOperand(t0)); |
| 1943 __ Addu(t0, t0, Operand(kPointerSize)); | 1932 __ Addu(t0, t0, Operand(kPointerSize)); |
| 1944 __ Subu(a1, a1, Operand(1)); | 1933 __ Subu(a2, a2, Operand(1)); |
| 1945 __ Branch(&loop, ne, a1, Operand(zero_reg)); | 1934 __ Branch(&loop, ne, a2, Operand(zero_reg)); |
| 1946 | 1935 |
| 1947 // Return and remove the on-stack parameters. | 1936 // Return. |
| 1948 __ bind(&done); | 1937 __ bind(&done); |
| 1949 __ DropAndRet(3); | 1938 __ Ret(); |
| 1950 | 1939 |
| 1951 // Do the runtime call to allocate the arguments object. | 1940 // Do the runtime call to allocate the arguments object. |
| 1952 __ bind(&runtime); | 1941 __ bind(&runtime); |
| 1942 __ Push(a1, a3, a2); | |
| 1953 __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); | 1943 __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); |
| 1954 } | 1944 } |
| 1955 | 1945 |
| 1956 | 1946 |
| 1957 void RegExpExecStub::Generate(MacroAssembler* masm) { | 1947 void RegExpExecStub::Generate(MacroAssembler* masm) { |
| 1958 // Just jump directly to runtime if native RegExp is not selected at compile | 1948 // Just jump directly to runtime if native RegExp is not selected at compile |
| 1959 // time or if regexp entry in generated code is turned off runtime switch or | 1949 // time or if regexp entry in generated code is turned off runtime switch or |
| 1960 // at compilation. | 1950 // at compilation. |
| 1961 #ifdef V8_INTERPRETED_REGEXP | 1951 #ifdef V8_INTERPRETED_REGEXP |
| 1962 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 1952 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| (...skipping 3785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5748 MemOperand(fp, 6 * kPointerSize), NULL); | 5738 MemOperand(fp, 6 * kPointerSize), NULL); |
| 5749 } | 5739 } |
| 5750 | 5740 |
| 5751 | 5741 |
| 5752 #undef __ | 5742 #undef __ |
| 5753 | 5743 |
| 5754 } // namespace internal | 5744 } // namespace internal |
| 5755 } // namespace v8 | 5745 } // namespace v8 |
| 5756 | 5746 |
| 5757 #endif // V8_TARGET_ARCH_MIPS | 5747 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |