OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 ExtraICState extra_ic_state) { | 739 ExtraICState extra_ic_state) { |
740 // ----------- S t a t e ------------- | 740 // ----------- S t a t e ------------- |
741 // -- a0: receiver | 741 // -- a0: receiver |
742 // -- a1: function to call | 742 // -- a1: function to call |
743 // ----------------------------------- | 743 // ----------------------------------- |
744 // Check that the function really is a function. | 744 // Check that the function really is a function. |
745 __ JumpIfSmi(a1, miss); | 745 __ JumpIfSmi(a1, miss); |
746 __ GetObjectType(a1, a3, a3); | 746 __ GetObjectType(a1, a3, a3); |
747 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); | 747 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); |
748 | 748 |
749 // Patch the receiver on the stack with the global proxy if | |
750 // necessary. | |
751 if (object->IsGlobalObject()) { | 749 if (object->IsGlobalObject()) { |
| 750 const int argc = arguments.immediate(); |
| 751 const int receiver_offset = argc * kPointerSize; |
752 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); | 752 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); |
753 __ sw(a3, MemOperand(sp, arguments.immediate() * kPointerSize)); | 753 __ sw(a3, MemOperand(sp, receiver_offset)); |
754 } | 754 } |
755 | 755 |
756 // Invoke the function. | 756 // Invoke the function. |
757 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | 757 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) |
758 ? CALL_AS_FUNCTION | 758 ? CALL_AS_FUNCTION |
759 : CALL_AS_METHOD; | 759 : CALL_AS_METHOD; |
760 __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | 760 __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); |
761 } | 761 } |
762 | 762 |
763 | 763 |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1520 } | 1520 } |
1521 | 1521 |
1522 | 1522 |
1523 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1523 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
1524 if (kind_ == Code::KEYED_CALL_IC) { | 1524 if (kind_ == Code::KEYED_CALL_IC) { |
1525 __ Branch(miss, ne, a2, Operand(name)); | 1525 __ Branch(miss, ne, a2, Operand(name)); |
1526 } | 1526 } |
1527 } | 1527 } |
1528 | 1528 |
1529 | 1529 |
1530 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, | |
1531 Handle<JSObject> holder, | |
1532 Handle<Name> name, | |
1533 Label* miss) { | |
1534 ASSERT(holder->IsGlobalObject()); | |
1535 | |
1536 // Get the number of arguments. | |
1537 const int argc = arguments().immediate(); | |
1538 | |
1539 // Get the receiver from the stack. | |
1540 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | |
1541 | |
1542 // Check that the maps haven't changed. | |
1543 __ JumpIfSmi(a0, miss); | |
1544 CheckPrototypes( | |
1545 IC::CurrentTypeOf(object, isolate()), a0, holder, a3, a1, t0, name, miss); | |
1546 } | |
1547 | |
1548 | |
1549 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1530 void CallStubCompiler::GenerateLoadFunctionFromCell( |
1550 Handle<Cell> cell, | 1531 Handle<Cell> cell, |
1551 Handle<JSFunction> function, | 1532 Handle<JSFunction> function, |
1552 Label* miss) { | 1533 Label* miss) { |
1553 // Get the value from the cell. | 1534 // Get the value from the cell. |
1554 __ li(a3, Operand(cell)); | 1535 __ li(a3, Operand(cell)); |
1555 __ lw(a1, FieldMemOperand(a3, Cell::kValueOffset)); | 1536 __ lw(a1, FieldMemOperand(a3, Cell::kValueOffset)); |
1556 | 1537 |
1557 // Check that the cell contains the same function. | 1538 // Check that the cell contains the same function. |
1558 if (heap()->InNewSpace(*function)) { | 1539 if (heap()->InNewSpace(*function)) { |
(...skipping 22 matching lines...) Expand all Loading... |
1581 kind_, | 1562 kind_, |
1582 extra_state_); | 1563 extra_state_); |
1583 __ Jump(code, RelocInfo::CODE_TARGET); | 1564 __ Jump(code, RelocInfo::CODE_TARGET); |
1584 } | 1565 } |
1585 | 1566 |
1586 | 1567 |
1587 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1568 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
1588 Handle<JSObject> holder, | 1569 Handle<JSObject> holder, |
1589 PropertyIndex index, | 1570 PropertyIndex index, |
1590 Handle<Name> name) { | 1571 Handle<Name> name) { |
1591 // ----------- S t a t e ------------- | |
1592 // -- a2 : name | |
1593 // -- ra : return address | |
1594 // ----------------------------------- | |
1595 Label miss; | 1572 Label miss; |
1596 | 1573 |
1597 GenerateNameCheck(name, &miss); | 1574 Register reg = HandlerFrontendHeader( |
1598 | 1575 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1599 const int argc = arguments().immediate(); | |
1600 | |
1601 // Get the receiver of the function from the stack into a0. | |
1602 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | |
1603 // Check that the receiver isn't a smi. | |
1604 __ JumpIfSmi(a0, &miss, t0); | |
1605 | |
1606 // Do the right check and compute the holder register. | |
1607 Register reg = CheckPrototypes( | |
1608 IC::CurrentTypeOf(object, isolate()), | |
1609 a0, holder, a1, a3, t0, name, &miss); | |
1610 GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder), | 1576 GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder), |
1611 index.translate(holder), Representation::Tagged()); | 1577 index.translate(holder), Representation::Tagged()); |
1612 | 1578 |
1613 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | 1579 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
1614 | 1580 |
1615 // Handle call cache miss. | 1581 HandlerFrontendFooter(&miss); |
1616 __ bind(&miss); | |
1617 GenerateMissBranch(); | |
1618 | 1582 |
1619 // Return the generated code. | 1583 // Return the generated code. |
1620 return GetCode(Code::FAST, name); | 1584 return GetCode(Code::FAST, name); |
1621 } | 1585 } |
1622 | 1586 |
1623 | 1587 |
1624 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1588 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
1625 Handle<Object> object, | 1589 Handle<Object> object, |
1626 Handle<JSObject> holder, | 1590 Handle<JSObject> holder, |
1627 Handle<Cell> cell, | 1591 Handle<Cell> cell, |
1628 Handle<JSFunction> function, | 1592 Handle<JSFunction> function, |
1629 Handle<String> name, | 1593 Handle<String> name, |
1630 Code::StubType type) { | 1594 Code::StubType type) { |
1631 Label miss; | 1595 Label miss; |
1632 | 1596 |
1633 // Check that function is still array. | 1597 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1634 const int argc = arguments().immediate(); | 1598 if (!cell.is_null()) { |
1635 GenerateNameCheck(name, &miss); | |
1636 Register receiver = a1; | |
1637 | |
1638 if (cell.is_null()) { | |
1639 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
1640 | |
1641 // Check that the receiver isn't a smi. | |
1642 __ JumpIfSmi(receiver, &miss); | |
1643 | |
1644 // Check that the maps haven't changed. | |
1645 CheckPrototypes( | |
1646 IC::CurrentTypeOf(object, isolate()), receiver, holder, | |
1647 a3, a0, t0, name, &miss); | |
1648 } else { | |
1649 ASSERT(cell->value() == *function); | 1599 ASSERT(cell->value() == *function); |
1650 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
1651 &miss); | |
1652 GenerateLoadFunctionFromCell(cell, function, &miss); | 1600 GenerateLoadFunctionFromCell(cell, function, &miss); |
1653 } | 1601 } |
1654 | 1602 |
1655 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1603 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
1656 site->SetElementsKind(GetInitialFastElementsKind()); | 1604 site->SetElementsKind(GetInitialFastElementsKind()); |
1657 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1605 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| 1606 const int argc = arguments().immediate(); |
1658 __ li(a0, Operand(argc)); | 1607 __ li(a0, Operand(argc)); |
1659 __ li(a2, Operand(site_feedback_cell)); | 1608 __ li(a2, Operand(site_feedback_cell)); |
1660 __ li(a1, Operand(function)); | 1609 __ li(a1, Operand(function)); |
1661 | 1610 |
1662 ArrayConstructorStub stub(isolate()); | 1611 ArrayConstructorStub stub(isolate()); |
1663 __ TailCallStub(&stub); | 1612 __ TailCallStub(&stub); |
1664 | 1613 |
1665 __ bind(&miss); | 1614 HandlerFrontendFooter(&miss); |
1666 GenerateMissBranch(); | |
1667 | 1615 |
1668 // Return the generated code. | 1616 // Return the generated code. |
1669 return GetCode(type, name); | 1617 return GetCode(type, name); |
1670 } | 1618 } |
1671 | 1619 |
1672 | 1620 |
1673 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1621 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
1674 Handle<Object> object, | 1622 Handle<Object> object, |
1675 Handle<JSObject> holder, | 1623 Handle<JSObject> holder, |
1676 Handle<Cell> cell, | 1624 Handle<Cell> cell, |
1677 Handle<JSFunction> function, | 1625 Handle<JSFunction> function, |
1678 Handle<String> name, | 1626 Handle<String> name, |
1679 Code::StubType type) { | 1627 Code::StubType type) { |
1680 // ----------- S t a t e ------------- | |
1681 // -- a2 : name | |
1682 // -- ra : return address | |
1683 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
1684 // -- ... | |
1685 // -- sp[argc * 4] : receiver | |
1686 // ----------------------------------- | |
1687 | |
1688 // If object is not an array or is observed, bail out to regular call. | 1628 // If object is not an array or is observed, bail out to regular call. |
1689 if (!object->IsJSArray() || | 1629 if (!object->IsJSArray() || |
1690 !cell.is_null() || | 1630 !cell.is_null() || |
1691 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1631 Handle<JSArray>::cast(object)->map()->is_observed()) { |
1692 return Handle<Code>::null(); | 1632 return Handle<Code>::null(); |
1693 } | 1633 } |
1694 | 1634 |
1695 Label miss; | 1635 Label miss; |
| 1636 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1637 Register receiver = a0; |
| 1638 Register scratch = a1; |
1696 | 1639 |
1697 GenerateNameCheck(name, &miss); | |
1698 | |
1699 Register receiver = a1; | |
1700 | |
1701 // Get the receiver from the stack. | |
1702 const int argc = arguments().immediate(); | 1640 const int argc = arguments().immediate(); |
1703 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
1704 | |
1705 // Check that the receiver isn't a smi. | |
1706 __ JumpIfSmi(receiver, &miss); | |
1707 | |
1708 // Check that the maps haven't changed. | |
1709 CheckPrototypes( | |
1710 IC::CurrentTypeOf(object, isolate()), receiver, holder, | |
1711 a3, v0, t0, name, &miss); | |
1712 | 1641 |
1713 if (argc == 0) { | 1642 if (argc == 0) { |
1714 // Nothing to do, just return the length. | 1643 // Nothing to do, just return the length. |
1715 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1644 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1716 __ DropAndRet(argc + 1); | 1645 __ DropAndRet(argc + 1); |
1717 } else { | 1646 } else { |
1718 Label call_builtin; | 1647 Label call_builtin; |
1719 if (argc == 1) { // Otherwise fall through to call the builtin. | 1648 if (argc == 1) { // Otherwise fall through to call the builtin. |
1720 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1649 Label attempt_to_grow_elements, with_write_barrier, check_double; |
1721 | 1650 |
1722 Register elements = t2; | 1651 Register elements = t2; |
1723 Register end_elements = t1; | 1652 Register end_elements = t1; |
1724 // Get the elements array of the object. | 1653 // Get the elements array of the object. |
1725 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1654 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
1726 | 1655 |
1727 // Check that the elements are in fast mode and writable. | 1656 // Check that the elements are in fast mode and writable. |
1728 __ CheckMap(elements, | 1657 __ CheckMap(elements, |
1729 v0, | 1658 scratch, |
1730 Heap::kFixedArrayMapRootIndex, | 1659 Heap::kFixedArrayMapRootIndex, |
1731 &check_double, | 1660 &check_double, |
1732 DONT_DO_SMI_CHECK); | 1661 DONT_DO_SMI_CHECK); |
1733 | 1662 |
1734 // Get the array's length into v0 and calculate new length. | 1663 // Get the array's length into scratch and calculate new length. |
1735 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1664 __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1736 STATIC_ASSERT(kSmiTagSize == 1); | 1665 STATIC_ASSERT(kSmiTagSize == 1); |
1737 STATIC_ASSERT(kSmiTag == 0); | 1666 STATIC_ASSERT(kSmiTag == 0); |
1738 __ Addu(v0, v0, Operand(Smi::FromInt(argc))); | 1667 __ Addu(scratch, scratch, Operand(Smi::FromInt(argc))); |
1739 | 1668 |
1740 // Get the elements' length. | 1669 // Get the elements' length. |
1741 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1670 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1742 | 1671 |
1743 // Check if we could survive without allocation. | 1672 // Check if we could survive without allocation. |
1744 __ Branch(&attempt_to_grow_elements, gt, v0, Operand(t0)); | 1673 __ Branch(&attempt_to_grow_elements, gt, scratch, Operand(t0)); |
1745 | 1674 |
1746 // Check if value is a smi. | 1675 // Check if value is a smi. |
1747 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); | 1676 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); |
1748 __ JumpIfNotSmi(t0, &with_write_barrier); | 1677 __ JumpIfNotSmi(t0, &with_write_barrier); |
1749 | 1678 |
1750 // Save new length. | 1679 // Save new length. |
1751 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1680 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1752 | 1681 |
1753 // Store the value. | 1682 // Store the value. |
1754 // We may need a register containing the address end_elements below, | 1683 // We may need a register containing the address end_elements below, |
1755 // so write back the value in end_elements. | 1684 // so write back the value in end_elements. |
1756 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1685 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); |
1757 __ Addu(end_elements, elements, end_elements); | 1686 __ Addu(end_elements, elements, end_elements); |
1758 const int kEndElementsOffset = | 1687 const int kEndElementsOffset = |
1759 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; | 1688 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; |
1760 __ Addu(end_elements, end_elements, kEndElementsOffset); | 1689 __ Addu(end_elements, end_elements, kEndElementsOffset); |
1761 __ sw(t0, MemOperand(end_elements)); | 1690 __ sw(t0, MemOperand(end_elements)); |
1762 | 1691 |
1763 // Check for a smi. | 1692 // Check for a smi. |
| 1693 __ mov(v0, scratch); |
1764 __ DropAndRet(argc + 1); | 1694 __ DropAndRet(argc + 1); |
1765 | 1695 |
1766 __ bind(&check_double); | 1696 __ bind(&check_double); |
1767 | 1697 |
1768 // Check that the elements are in fast mode and writable. | 1698 // Check that the elements are in fast mode and writable. |
1769 __ CheckMap(elements, | 1699 __ CheckMap(elements, |
1770 a0, | 1700 scratch, |
1771 Heap::kFixedDoubleArrayMapRootIndex, | 1701 Heap::kFixedDoubleArrayMapRootIndex, |
1772 &call_builtin, | 1702 &call_builtin, |
1773 DONT_DO_SMI_CHECK); | 1703 DONT_DO_SMI_CHECK); |
1774 | 1704 |
1775 // Get the array's length into v0 and calculate new length. | 1705 // Get the array's length into scratch and calculate new length. |
1776 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1706 __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1777 STATIC_ASSERT(kSmiTagSize == 1); | 1707 STATIC_ASSERT(kSmiTagSize == 1); |
1778 STATIC_ASSERT(kSmiTag == 0); | 1708 STATIC_ASSERT(kSmiTag == 0); |
1779 __ Addu(v0, v0, Operand(Smi::FromInt(argc))); | 1709 __ Addu(scratch, scratch, Operand(Smi::FromInt(argc))); |
1780 | 1710 |
1781 // Get the elements' length. | 1711 // Get the elements' length. |
1782 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1712 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1783 | 1713 |
1784 // Check if we could survive without allocation. | 1714 // Check if we could survive without allocation. |
1785 __ Branch(&call_builtin, gt, v0, Operand(t0)); | 1715 __ Branch(&call_builtin, gt, scratch, Operand(t0)); |
1786 | 1716 |
1787 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); | 1717 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); |
1788 __ StoreNumberToDoubleElements( | 1718 __ StoreNumberToDoubleElements( |
1789 t0, v0, elements, a3, t1, a2, | 1719 t0, scratch, elements, a3, t1, a2, |
1790 &call_builtin, argc * kDoubleSize); | 1720 &call_builtin, argc * kDoubleSize); |
1791 | 1721 |
1792 // Save new length. | 1722 // Save new length. |
1793 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1723 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1794 | 1724 |
1795 // Check for a smi. | 1725 __ mov(v0, scratch); |
1796 __ DropAndRet(argc + 1); | 1726 __ DropAndRet(argc + 1); |
1797 | 1727 |
1798 __ bind(&with_write_barrier); | 1728 __ bind(&with_write_barrier); |
1799 | 1729 |
1800 __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1730 __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
1801 | 1731 |
1802 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { | 1732 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { |
1803 Label fast_object, not_fast_object; | 1733 Label fast_object, not_fast_object; |
1804 __ CheckFastObjectElements(a3, t3, ¬_fast_object); | 1734 __ CheckFastObjectElements(a3, t3, ¬_fast_object); |
1805 __ jmp(&fast_object); | 1735 __ jmp(&fast_object); |
(...skipping 29 matching lines...) Expand all Loading... |
1835 ElementsTransitionGenerator:: | 1765 ElementsTransitionGenerator:: |
1836 GenerateMapChangeElementsTransition(masm(), | 1766 GenerateMapChangeElementsTransition(masm(), |
1837 DONT_TRACK_ALLOCATION_SITE, | 1767 DONT_TRACK_ALLOCATION_SITE, |
1838 NULL); | 1768 NULL); |
1839 __ bind(&fast_object); | 1769 __ bind(&fast_object); |
1840 } else { | 1770 } else { |
1841 __ CheckFastObjectElements(a3, a3, &call_builtin); | 1771 __ CheckFastObjectElements(a3, a3, &call_builtin); |
1842 } | 1772 } |
1843 | 1773 |
1844 // Save new length. | 1774 // Save new length. |
1845 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1775 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1846 | 1776 |
1847 // Store the value. | 1777 // Store the value. |
1848 // We may need a register containing the address end_elements below, | 1778 // We may need a register containing the address end_elements below, |
1849 // so write back the value in end_elements. | 1779 // so write back the value in end_elements. |
1850 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1780 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); |
1851 __ Addu(end_elements, elements, end_elements); | 1781 __ Addu(end_elements, elements, end_elements); |
1852 __ Addu(end_elements, end_elements, kEndElementsOffset); | 1782 __ Addu(end_elements, end_elements, kEndElementsOffset); |
1853 __ sw(t0, MemOperand(end_elements)); | 1783 __ sw(t0, MemOperand(end_elements)); |
1854 | 1784 |
1855 __ RecordWrite(elements, | 1785 __ RecordWrite(elements, |
1856 end_elements, | 1786 end_elements, |
1857 t0, | 1787 t0, |
1858 kRAHasNotBeenSaved, | 1788 kRAHasNotBeenSaved, |
1859 kDontSaveFPRegs, | 1789 kDontSaveFPRegs, |
1860 EMIT_REMEMBERED_SET, | 1790 EMIT_REMEMBERED_SET, |
1861 OMIT_SMI_CHECK); | 1791 OMIT_SMI_CHECK); |
| 1792 __ mov(v0, scratch); |
1862 __ DropAndRet(argc + 1); | 1793 __ DropAndRet(argc + 1); |
1863 | 1794 |
1864 __ bind(&attempt_to_grow_elements); | 1795 __ bind(&attempt_to_grow_elements); |
1865 // v0: array's length + 1. | 1796 // scratch: array's length + 1. |
1866 // t0: elements' length. | 1797 // t0: elements' length. |
1867 | 1798 |
1868 if (!FLAG_inline_new) { | 1799 if (!FLAG_inline_new) { |
1869 __ Branch(&call_builtin); | 1800 __ Branch(&call_builtin); |
1870 } | 1801 } |
1871 | 1802 |
1872 __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize)); | 1803 __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize)); |
1873 // Growing elements that are SMI-only requires special handling in case | 1804 // Growing elements that are SMI-only requires special handling in case |
1874 // the new element is non-Smi. For now, delegate to the builtin. | 1805 // the new element is non-Smi. For now, delegate to the builtin. |
1875 Label no_fast_elements_check; | 1806 Label no_fast_elements_check; |
1876 __ JumpIfSmi(a2, &no_fast_elements_check); | 1807 __ JumpIfSmi(a2, &no_fast_elements_check); |
1877 __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1808 __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
1878 __ CheckFastObjectElements(t3, t3, &call_builtin); | 1809 __ CheckFastObjectElements(t3, t3, &call_builtin); |
1879 __ bind(&no_fast_elements_check); | 1810 __ bind(&no_fast_elements_check); |
1880 | 1811 |
1881 ExternalReference new_space_allocation_top = | 1812 ExternalReference new_space_allocation_top = |
1882 ExternalReference::new_space_allocation_top_address(isolate()); | 1813 ExternalReference::new_space_allocation_top_address(isolate()); |
1883 ExternalReference new_space_allocation_limit = | 1814 ExternalReference new_space_allocation_limit = |
1884 ExternalReference::new_space_allocation_limit_address(isolate()); | 1815 ExternalReference::new_space_allocation_limit_address(isolate()); |
1885 | 1816 |
1886 const int kAllocationDelta = 4; | 1817 const int kAllocationDelta = 4; |
1887 // Load top and check if it is the end of elements. | 1818 // Load top and check if it is the end of elements. |
1888 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1819 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); |
1889 __ Addu(end_elements, elements, end_elements); | 1820 __ Addu(end_elements, elements, end_elements); |
1890 __ Addu(end_elements, end_elements, Operand(kEndElementsOffset)); | 1821 __ Addu(end_elements, end_elements, Operand(kEndElementsOffset)); |
1891 __ li(t3, Operand(new_space_allocation_top)); | 1822 __ li(t3, Operand(new_space_allocation_top)); |
1892 __ lw(a3, MemOperand(t3)); | 1823 __ lw(a3, MemOperand(t3)); |
1893 __ Branch(&call_builtin, ne, end_elements, Operand(a3)); | 1824 __ Branch(&call_builtin, ne, end_elements, Operand(a3)); |
1894 | 1825 |
1895 __ li(t5, Operand(new_space_allocation_limit)); | 1826 __ li(t5, Operand(new_space_allocation_limit)); |
1896 __ lw(t5, MemOperand(t5)); | 1827 __ lw(t5, MemOperand(t5)); |
1897 __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize)); | 1828 __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize)); |
1898 __ Branch(&call_builtin, hi, a3, Operand(t5)); | 1829 __ Branch(&call_builtin, hi, a3, Operand(t5)); |
1899 | 1830 |
1900 // We fit and could grow elements. | 1831 // We fit and could grow elements. |
1901 // Update new_space_allocation_top. | 1832 // Update new_space_allocation_top. |
1902 __ sw(a3, MemOperand(t3)); | 1833 __ sw(a3, MemOperand(t3)); |
1903 // Push the argument. | 1834 // Push the argument. |
1904 __ sw(a2, MemOperand(end_elements)); | 1835 __ sw(a2, MemOperand(end_elements)); |
1905 // Fill the rest with holes. | 1836 // Fill the rest with holes. |
1906 __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); | 1837 __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); |
1907 for (int i = 1; i < kAllocationDelta; i++) { | 1838 for (int i = 1; i < kAllocationDelta; i++) { |
1908 __ sw(a3, MemOperand(end_elements, i * kPointerSize)); | 1839 __ sw(a3, MemOperand(end_elements, i * kPointerSize)); |
1909 } | 1840 } |
1910 | 1841 |
1911 // Update elements' and array's sizes. | 1842 // Update elements' and array's sizes. |
1912 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1843 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1913 __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta))); | 1844 __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta))); |
1914 __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1845 __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1915 | 1846 |
1916 // Elements are in new space, so write barrier is not required. | 1847 // Elements are in new space, so write barrier is not required. |
| 1848 __ mov(v0, scratch); |
1917 __ DropAndRet(argc + 1); | 1849 __ DropAndRet(argc + 1); |
1918 } | 1850 } |
1919 __ bind(&call_builtin); | 1851 __ bind(&call_builtin); |
1920 __ TailCallExternalReference( | 1852 __ TailCallExternalReference( |
1921 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); | 1853 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); |
1922 } | 1854 } |
1923 | 1855 |
1924 // Handle call cache miss. | 1856 HandlerFrontendFooter(&miss); |
1925 __ bind(&miss); | |
1926 GenerateMissBranch(); | |
1927 | 1857 |
1928 // Return the generated code. | 1858 // Return the generated code. |
1929 return GetCode(type, name); | 1859 return GetCode(type, name); |
1930 } | 1860 } |
1931 | 1861 |
1932 | 1862 |
1933 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1863 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
1934 Handle<Object> object, | 1864 Handle<Object> object, |
1935 Handle<JSObject> holder, | 1865 Handle<JSObject> holder, |
1936 Handle<Cell> cell, | 1866 Handle<Cell> cell, |
1937 Handle<JSFunction> function, | 1867 Handle<JSFunction> function, |
1938 Handle<String> name, | 1868 Handle<String> name, |
1939 Code::StubType type) { | 1869 Code::StubType type) { |
1940 // ----------- S t a t e ------------- | |
1941 // -- a2 : name | |
1942 // -- ra : return address | |
1943 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
1944 // -- ... | |
1945 // -- sp[argc * 4] : receiver | |
1946 // ----------------------------------- | |
1947 | |
1948 // If object is not an array or is observed, bail out to regular call. | 1870 // If object is not an array or is observed, bail out to regular call. |
1949 if (!object->IsJSArray() || | 1871 if (!object->IsJSArray() || |
1950 !cell.is_null() || | 1872 !cell.is_null() || |
1951 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1873 Handle<JSArray>::cast(object)->map()->is_observed()) { |
1952 return Handle<Code>::null(); | 1874 return Handle<Code>::null(); |
1953 } | 1875 } |
1954 | 1876 |
1955 Label miss, return_undefined, call_builtin; | 1877 Label miss, return_undefined, call_builtin; |
1956 Register receiver = a1; | 1878 Register receiver = a0; |
| 1879 Register scratch = a1; |
1957 Register elements = a3; | 1880 Register elements = a3; |
1958 GenerateNameCheck(name, &miss); | 1881 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1959 | |
1960 // Get the receiver from the stack. | |
1961 const int argc = arguments().immediate(); | |
1962 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
1963 // Check that the receiver isn't a smi. | |
1964 __ JumpIfSmi(receiver, &miss); | |
1965 | |
1966 // Check that the maps haven't changed. | |
1967 CheckPrototypes( | |
1968 IC::CurrentTypeOf(object, isolate()), receiver, holder, | |
1969 elements, t0, v0, name, &miss); | |
1970 | 1882 |
1971 // Get the elements array of the object. | 1883 // Get the elements array of the object. |
1972 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1884 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
1973 | 1885 |
1974 // Check that the elements are in fast mode and writable. | 1886 // Check that the elements are in fast mode and writable. |
1975 __ CheckMap(elements, | 1887 __ CheckMap(elements, |
1976 v0, | 1888 scratch, |
1977 Heap::kFixedArrayMapRootIndex, | 1889 Heap::kFixedArrayMapRootIndex, |
1978 &call_builtin, | 1890 &call_builtin, |
1979 DONT_DO_SMI_CHECK); | 1891 DONT_DO_SMI_CHECK); |
1980 | 1892 |
1981 // Get the array's length into t0 and calculate new length. | 1893 // Get the array's length into t0 and calculate new length. |
1982 __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1894 __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1983 __ Subu(t0, t0, Operand(Smi::FromInt(1))); | 1895 __ Subu(t0, t0, Operand(Smi::FromInt(1))); |
1984 __ Branch(&return_undefined, lt, t0, Operand(zero_reg)); | 1896 __ Branch(&return_undefined, lt, t0, Operand(zero_reg)); |
1985 | 1897 |
1986 // Get the last element. | 1898 // Get the last element. |
1987 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); | 1899 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); |
1988 STATIC_ASSERT(kSmiTagSize == 1); | 1900 STATIC_ASSERT(kSmiTagSize == 1); |
1989 STATIC_ASSERT(kSmiTag == 0); | 1901 STATIC_ASSERT(kSmiTag == 0); |
1990 // We can't address the last element in one operation. Compute the more | 1902 // We can't address the last element in one operation. Compute the more |
1991 // expensive shift first, and use an offset later on. | 1903 // expensive shift first, and use an offset later on. |
1992 __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize); | 1904 __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize); |
1993 __ Addu(elements, elements, t1); | 1905 __ Addu(elements, elements, t1); |
1994 __ lw(v0, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 1906 __ lw(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
1995 __ Branch(&call_builtin, eq, v0, Operand(t2)); | 1907 __ Branch(&call_builtin, eq, scratch, Operand(t2)); |
1996 | 1908 |
1997 // Set the array's length. | 1909 // Set the array's length. |
1998 __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1910 __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1999 | 1911 |
2000 // Fill with the hole. | 1912 // Fill with the hole. |
2001 __ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 1913 __ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
| 1914 const int argc = arguments().immediate(); |
| 1915 __ mov(v0, scratch); |
2002 __ DropAndRet(argc + 1); | 1916 __ DropAndRet(argc + 1); |
2003 | 1917 |
2004 __ bind(&return_undefined); | 1918 __ bind(&return_undefined); |
2005 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 1919 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
2006 __ DropAndRet(argc + 1); | 1920 __ DropAndRet(argc + 1); |
2007 | 1921 |
2008 __ bind(&call_builtin); | 1922 __ bind(&call_builtin); |
2009 __ TailCallExternalReference( | 1923 __ TailCallExternalReference( |
2010 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); | 1924 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); |
2011 | 1925 |
2012 // Handle call cache miss. | 1926 HandlerFrontendFooter(&miss); |
2013 __ bind(&miss); | |
2014 GenerateMissBranch(); | |
2015 | 1927 |
2016 // Return the generated code. | 1928 // Return the generated code. |
2017 return GetCode(type, name); | 1929 return GetCode(type, name); |
2018 } | 1930 } |
2019 | 1931 |
2020 | 1932 |
2021 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( | 1933 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
2022 Handle<Object> object, | 1934 Handle<Object> object, |
2023 Handle<JSObject> holder, | 1935 Handle<JSObject> holder, |
2024 Handle<Cell> cell, | 1936 Handle<Cell> cell, |
2025 Handle<JSFunction> function, | 1937 Handle<JSFunction> function, |
2026 Handle<String> name, | 1938 Handle<String> name, |
2027 Code::StubType type) { | 1939 Code::StubType type) { |
2028 // ----------- S t a t e ------------- | |
2029 // -- a2 : function name | |
2030 // -- ra : return address | |
2031 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
2032 // -- ... | |
2033 // -- sp[argc * 4] : receiver | |
2034 // ----------------------------------- | |
2035 | |
2036 // If object is not a string, bail out to regular call. | 1940 // If object is not a string, bail out to regular call. |
2037 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1941 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
2038 | 1942 |
2039 const int argc = arguments().immediate(); | |
2040 Label miss; | 1943 Label miss; |
2041 Label name_miss; | 1944 Label name_miss; |
2042 Label index_out_of_range; | 1945 Label index_out_of_range; |
2043 | 1946 |
2044 Label* index_out_of_range_label = &index_out_of_range; | 1947 Label* index_out_of_range_label = &index_out_of_range; |
2045 | 1948 |
2046 if (kind_ == Code::CALL_IC && | 1949 if (kind_ == Code::CALL_IC && |
2047 (CallICBase::StringStubState::decode(extra_state_) == | 1950 (CallICBase::StringStubState::decode(extra_state_) == |
2048 DEFAULT_STRING_STUB)) { | 1951 DEFAULT_STRING_STUB)) { |
2049 index_out_of_range_label = &miss; | 1952 index_out_of_range_label = &miss; |
2050 } | 1953 } |
2051 | 1954 |
2052 GenerateNameCheck(name, &name_miss); | 1955 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
2053 | 1956 |
2054 // Check that the maps starting from the prototype haven't changed. | 1957 Register receiver = a0; |
2055 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
2056 Context::STRING_FUNCTION_INDEX, | |
2057 v0, | |
2058 &miss); | |
2059 ASSERT(!object.is_identical_to(holder)); | |
2060 Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate()))); | |
2061 CheckPrototypes( | |
2062 IC::CurrentTypeOf(prototype, isolate()), | |
2063 v0, holder, a1, a3, t0, name, &miss); | |
2064 | |
2065 Register receiver = a1; | |
2066 Register index = t1; | 1958 Register index = t1; |
2067 Register result = v0; | 1959 Register result = a1; |
| 1960 const int argc = arguments().immediate(); |
2068 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | 1961 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); |
2069 if (argc > 0) { | 1962 if (argc > 0) { |
2070 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1963 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
2071 } else { | 1964 } else { |
2072 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1965 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
2073 } | 1966 } |
2074 | 1967 |
2075 StringCharCodeAtGenerator generator(receiver, | 1968 StringCharCodeAtGenerator generator(receiver, |
2076 index, | 1969 index, |
2077 result, | 1970 result, |
2078 &miss, // When not a string. | 1971 &miss, // When not a string. |
2079 &miss, // When not a number. | 1972 &miss, // When not a number. |
2080 index_out_of_range_label, | 1973 index_out_of_range_label, |
2081 STRING_INDEX_IS_NUMBER); | 1974 STRING_INDEX_IS_NUMBER); |
2082 generator.GenerateFast(masm()); | 1975 generator.GenerateFast(masm()); |
| 1976 __ mov(v0, result); |
2083 __ DropAndRet(argc + 1); | 1977 __ DropAndRet(argc + 1); |
2084 | 1978 |
2085 StubRuntimeCallHelper call_helper; | 1979 StubRuntimeCallHelper call_helper; |
2086 generator.GenerateSlow(masm(), call_helper); | 1980 generator.GenerateSlow(masm(), call_helper); |
2087 | 1981 |
2088 if (index_out_of_range.is_linked()) { | 1982 if (index_out_of_range.is_linked()) { |
2089 __ bind(&index_out_of_range); | 1983 __ bind(&index_out_of_range); |
2090 __ LoadRoot(v0, Heap::kNanValueRootIndex); | 1984 __ LoadRoot(v0, Heap::kNanValueRootIndex); |
2091 __ DropAndRet(argc + 1); | 1985 __ DropAndRet(argc + 1); |
2092 } | 1986 } |
2093 | 1987 |
2094 __ bind(&miss); | 1988 __ bind(&miss); |
2095 // Restore function name in a2. | 1989 // Restore function name in a2. |
2096 __ li(a2, name); | 1990 __ li(a2, name); |
2097 __ bind(&name_miss); | 1991 __ bind(&name_miss); |
2098 GenerateMissBranch(); | 1992 GenerateMissBranch(); |
2099 | 1993 |
2100 // Return the generated code. | 1994 // Return the generated code. |
2101 return GetCode(type, name); | 1995 return GetCode(type, name); |
2102 } | 1996 } |
2103 | 1997 |
2104 | 1998 |
2105 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 1999 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
2106 Handle<Object> object, | 2000 Handle<Object> object, |
2107 Handle<JSObject> holder, | 2001 Handle<JSObject> holder, |
2108 Handle<Cell> cell, | 2002 Handle<Cell> cell, |
2109 Handle<JSFunction> function, | 2003 Handle<JSFunction> function, |
2110 Handle<String> name, | 2004 Handle<String> name, |
2111 Code::StubType type) { | 2005 Code::StubType type) { |
2112 // ----------- S t a t e ------------- | |
2113 // -- a2 : function name | |
2114 // -- ra : return address | |
2115 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
2116 // -- ... | |
2117 // -- sp[argc * 4] : receiver | |
2118 // ----------------------------------- | |
2119 | |
2120 // If object is not a string, bail out to regular call. | 2006 // If object is not a string, bail out to regular call. |
2121 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 2007 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
2122 | 2008 |
2123 const int argc = arguments().immediate(); | 2009 const int argc = arguments().immediate(); |
2124 Label miss; | 2010 Label miss; |
2125 Label name_miss; | 2011 Label name_miss; |
2126 Label index_out_of_range; | 2012 Label index_out_of_range; |
2127 Label* index_out_of_range_label = &index_out_of_range; | 2013 Label* index_out_of_range_label = &index_out_of_range; |
2128 if (kind_ == Code::CALL_IC && | 2014 if (kind_ == Code::CALL_IC && |
2129 (CallICBase::StringStubState::decode(extra_state_) == | 2015 (CallICBase::StringStubState::decode(extra_state_) == |
2130 DEFAULT_STRING_STUB)) { | 2016 DEFAULT_STRING_STUB)) { |
2131 index_out_of_range_label = &miss; | 2017 index_out_of_range_label = &miss; |
2132 } | 2018 } |
2133 GenerateNameCheck(name, &name_miss); | |
2134 | 2019 |
2135 // Check that the maps starting from the prototype haven't changed. | 2020 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
2136 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
2137 Context::STRING_FUNCTION_INDEX, | |
2138 v0, | |
2139 &miss); | |
2140 ASSERT(!object.is_identical_to(holder)); | |
2141 Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate()))); | |
2142 CheckPrototypes( | |
2143 IC::CurrentTypeOf(prototype, isolate()), | |
2144 v0, holder, a1, a3, t0, name, &miss); | |
2145 | 2021 |
2146 Register receiver = v0; | 2022 Register receiver = a0; |
2147 Register index = t1; | 2023 Register index = t1; |
2148 Register scratch = a3; | 2024 Register scratch = a3; |
2149 Register result = v0; | 2025 Register result = a1; |
2150 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
2151 if (argc > 0) { | 2026 if (argc > 0) { |
2152 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 2027 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
2153 } else { | 2028 } else { |
2154 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2029 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
2155 } | 2030 } |
2156 | 2031 |
2157 StringCharAtGenerator generator(receiver, | 2032 StringCharAtGenerator generator(receiver, |
2158 index, | 2033 index, |
2159 scratch, | 2034 scratch, |
2160 result, | 2035 result, |
2161 &miss, // When not a string. | 2036 &miss, // When not a string. |
2162 &miss, // When not a number. | 2037 &miss, // When not a number. |
2163 index_out_of_range_label, | 2038 index_out_of_range_label, |
2164 STRING_INDEX_IS_NUMBER); | 2039 STRING_INDEX_IS_NUMBER); |
2165 generator.GenerateFast(masm()); | 2040 generator.GenerateFast(masm()); |
| 2041 __ mov(v0, result); |
2166 __ DropAndRet(argc + 1); | 2042 __ DropAndRet(argc + 1); |
2167 | 2043 |
2168 StubRuntimeCallHelper call_helper; | 2044 StubRuntimeCallHelper call_helper; |
2169 generator.GenerateSlow(masm(), call_helper); | 2045 generator.GenerateSlow(masm(), call_helper); |
2170 | 2046 |
2171 if (index_out_of_range.is_linked()) { | 2047 if (index_out_of_range.is_linked()) { |
2172 __ bind(&index_out_of_range); | 2048 __ bind(&index_out_of_range); |
2173 __ LoadRoot(v0, Heap::kempty_stringRootIndex); | 2049 __ LoadRoot(v0, Heap::kempty_stringRootIndex); |
2174 __ DropAndRet(argc + 1); | 2050 __ DropAndRet(argc + 1); |
2175 } | 2051 } |
2176 | 2052 |
2177 __ bind(&miss); | 2053 __ bind(&miss); |
2178 // Restore function name in a2. | 2054 // Restore function name in a2. |
2179 __ li(a2, name); | 2055 __ li(a2, name); |
2180 __ bind(&name_miss); | 2056 __ bind(&name_miss); |
2181 GenerateMissBranch(); | 2057 GenerateMissBranch(); |
2182 | 2058 |
2183 // Return the generated code. | 2059 // Return the generated code. |
2184 return GetCode(type, name); | 2060 return GetCode(type, name); |
2185 } | 2061 } |
2186 | 2062 |
2187 | 2063 |
2188 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2064 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
2189 Handle<Object> object, | 2065 Handle<Object> object, |
2190 Handle<JSObject> holder, | 2066 Handle<JSObject> holder, |
2191 Handle<Cell> cell, | 2067 Handle<Cell> cell, |
2192 Handle<JSFunction> function, | 2068 Handle<JSFunction> function, |
2193 Handle<String> name, | 2069 Handle<String> name, |
2194 Code::StubType type) { | 2070 Code::StubType type) { |
2195 // ----------- S t a t e ------------- | |
2196 // -- a2 : function name | |
2197 // -- ra : return address | |
2198 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
2199 // -- ... | |
2200 // -- sp[argc * 4] : receiver | |
2201 // ----------------------------------- | |
2202 | |
2203 const int argc = arguments().immediate(); | 2071 const int argc = arguments().immediate(); |
2204 | 2072 |
2205 // If the object is not a JSObject or we got an unexpected number of | 2073 // If the object is not a JSObject or we got an unexpected number of |
2206 // arguments, bail out to the regular call. | 2074 // arguments, bail out to the regular call. |
2207 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2075 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
2208 | 2076 |
2209 Label miss; | 2077 Label miss; |
2210 GenerateNameCheck(name, &miss); | 2078 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2211 | 2079 if (!cell.is_null()) { |
2212 if (cell.is_null()) { | |
2213 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | |
2214 | |
2215 STATIC_ASSERT(kSmiTag == 0); | |
2216 __ JumpIfSmi(a1, &miss); | |
2217 | |
2218 CheckPrototypes( | |
2219 IC::CurrentTypeOf(object, isolate()), | |
2220 a1, holder, v0, a3, t0, name, &miss); | |
2221 } else { | |
2222 ASSERT(cell->value() == *function); | 2080 ASSERT(cell->value() == *function); |
2223 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
2224 &miss); | |
2225 GenerateLoadFunctionFromCell(cell, function, &miss); | 2081 GenerateLoadFunctionFromCell(cell, function, &miss); |
2226 } | 2082 } |
2227 | 2083 |
2228 // Load the char code argument. | 2084 // Load the char code argument. |
2229 Register code = a1; | 2085 Register code = a1; |
2230 __ lw(code, MemOperand(sp, 0 * kPointerSize)); | 2086 __ lw(code, MemOperand(sp, 0 * kPointerSize)); |
2231 | 2087 |
2232 // Check the code is a smi. | 2088 // Check the code is a smi. |
2233 Label slow; | 2089 Label slow; |
2234 STATIC_ASSERT(kSmiTag == 0); | 2090 STATIC_ASSERT(kSmiTag == 0); |
2235 __ JumpIfNotSmi(code, &slow); | 2091 __ JumpIfNotSmi(code, &slow); |
2236 | 2092 |
2237 // Convert the smi code to uint16. | 2093 // Convert the smi code to uint16. |
2238 __ And(code, code, Operand(Smi::FromInt(0xffff))); | 2094 __ And(code, code, Operand(Smi::FromInt(0xffff))); |
2239 | 2095 |
2240 StringCharFromCodeGenerator generator(code, v0); | 2096 StringCharFromCodeGenerator generator(code, v0); |
2241 generator.GenerateFast(masm()); | 2097 generator.GenerateFast(masm()); |
2242 __ DropAndRet(argc + 1); | 2098 __ DropAndRet(argc + 1); |
2243 | 2099 |
2244 StubRuntimeCallHelper call_helper; | 2100 StubRuntimeCallHelper call_helper; |
2245 generator.GenerateSlow(masm(), call_helper); | 2101 generator.GenerateSlow(masm(), call_helper); |
2246 | 2102 |
2247 // Tail call the full function. We do not have to patch the receiver | 2103 // Tail call the full function. We do not have to patch the receiver |
2248 // because the function makes no use of it. | 2104 // because the function makes no use of it. |
2249 __ bind(&slow); | 2105 __ bind(&slow); |
2250 ParameterCount expected(function); | 2106 ParameterCount expected(function); |
2251 __ InvokeFunction(function, expected, arguments(), | 2107 __ InvokeFunction(function, expected, arguments(), |
2252 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2108 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2253 | 2109 |
2254 __ bind(&miss); | 2110 HandlerFrontendFooter(&miss); |
2255 // a2: function name. | |
2256 GenerateMissBranch(); | |
2257 | 2111 |
2258 // Return the generated code. | 2112 // Return the generated code. |
2259 return GetCode(type, name); | 2113 return GetCode(type, name); |
2260 } | 2114 } |
2261 | 2115 |
2262 | 2116 |
2263 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2117 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2264 Handle<Object> object, | 2118 Handle<Object> object, |
2265 Handle<JSObject> holder, | 2119 Handle<JSObject> holder, |
2266 Handle<Cell> cell, | 2120 Handle<Cell> cell, |
2267 Handle<JSFunction> function, | 2121 Handle<JSFunction> function, |
2268 Handle<String> name, | 2122 Handle<String> name, |
2269 Code::StubType type) { | 2123 Code::StubType type) { |
2270 // ----------- S t a t e ------------- | |
2271 // -- a2 : function name | |
2272 // -- ra : return address | |
2273 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
2274 // -- ... | |
2275 // -- sp[argc * 4] : receiver | |
2276 // ----------------------------------- | |
2277 | |
2278 | |
2279 const int argc = arguments().immediate(); | 2124 const int argc = arguments().immediate(); |
2280 // If the object is not a JSObject or we got an unexpected number of | 2125 // If the object is not a JSObject or we got an unexpected number of |
2281 // arguments, bail out to the regular call. | 2126 // arguments, bail out to the regular call. |
2282 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2127 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
2283 | 2128 |
2284 Label miss, slow; | 2129 Label miss, slow; |
2285 GenerateNameCheck(name, &miss); | 2130 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2286 | 2131 if (!cell.is_null()) { |
2287 if (cell.is_null()) { | |
2288 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | |
2289 STATIC_ASSERT(kSmiTag == 0); | |
2290 __ JumpIfSmi(a1, &miss); | |
2291 CheckPrototypes( | |
2292 IC::CurrentTypeOf(object, isolate()), | |
2293 a1, holder, a0, a3, t0, name, &miss); | |
2294 } else { | |
2295 ASSERT(cell->value() == *function); | 2132 ASSERT(cell->value() == *function); |
2296 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
2297 &miss); | |
2298 GenerateLoadFunctionFromCell(cell, function, &miss); | 2133 GenerateLoadFunctionFromCell(cell, function, &miss); |
2299 } | 2134 } |
2300 | 2135 |
2301 // Load the (only) argument into v0. | 2136 // Load the (only) argument into v0. |
2302 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | 2137 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); |
2303 | 2138 |
2304 // If the argument is a smi, just return. | 2139 // If the argument is a smi, just return. |
2305 STATIC_ASSERT(kSmiTag == 0); | 2140 STATIC_ASSERT(kSmiTag == 0); |
2306 __ SmiTst(v0, t0); | 2141 __ SmiTst(v0, t0); |
2307 __ DropAndRet(argc + 1, eq, t0, Operand(zero_reg)); | 2142 __ DropAndRet(argc + 1, eq, t0, Operand(zero_reg)); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2375 // Restore FCSR and fall to slow case. | 2210 // Restore FCSR and fall to slow case. |
2376 __ ctc1(a3, FCSR); | 2211 __ ctc1(a3, FCSR); |
2377 | 2212 |
2378 __ bind(&slow); | 2213 __ bind(&slow); |
2379 // Tail call the full function. We do not have to patch the receiver | 2214 // Tail call the full function. We do not have to patch the receiver |
2380 // because the function makes no use of it. | 2215 // because the function makes no use of it. |
2381 ParameterCount expected(function); | 2216 ParameterCount expected(function); |
2382 __ InvokeFunction(function, expected, arguments(), | 2217 __ InvokeFunction(function, expected, arguments(), |
2383 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2218 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2384 | 2219 |
2385 __ bind(&miss); | 2220 HandlerFrontendFooter(&miss); |
2386 // a2: function name. | |
2387 GenerateMissBranch(); | |
2388 | 2221 |
2389 // Return the generated code. | 2222 // Return the generated code. |
2390 return GetCode(type, name); | 2223 return GetCode(type, name); |
2391 } | 2224 } |
2392 | 2225 |
2393 | 2226 |
2394 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2227 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2395 Handle<Object> object, | 2228 Handle<Object> object, |
2396 Handle<JSObject> holder, | 2229 Handle<JSObject> holder, |
2397 Handle<Cell> cell, | 2230 Handle<Cell> cell, |
2398 Handle<JSFunction> function, | 2231 Handle<JSFunction> function, |
2399 Handle<String> name, | 2232 Handle<String> name, |
2400 Code::StubType type) { | 2233 Code::StubType type) { |
2401 // ----------- S t a t e ------------- | |
2402 // -- a2 : function name | |
2403 // -- ra : return address | |
2404 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
2405 // -- ... | |
2406 // -- sp[argc * 4] : receiver | |
2407 // ----------------------------------- | |
2408 | |
2409 const int argc = arguments().immediate(); | 2234 const int argc = arguments().immediate(); |
2410 // If the object is not a JSObject or we got an unexpected number of | 2235 // If the object is not a JSObject or we got an unexpected number of |
2411 // arguments, bail out to the regular call. | 2236 // arguments, bail out to the regular call. |
2412 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2237 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
2413 | 2238 |
2414 Label miss; | 2239 Label miss; |
2415 | 2240 |
2416 GenerateNameCheck(name, &miss); | 2241 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2417 if (cell.is_null()) { | 2242 if (!cell.is_null()) { |
2418 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | |
2419 STATIC_ASSERT(kSmiTag == 0); | |
2420 __ JumpIfSmi(a1, &miss); | |
2421 CheckPrototypes( | |
2422 IC::CurrentTypeOf(object, isolate()), | |
2423 a1, holder, v0, a3, t0, name, &miss); | |
2424 } else { | |
2425 ASSERT(cell->value() == *function); | 2243 ASSERT(cell->value() == *function); |
2426 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
2427 &miss); | |
2428 GenerateLoadFunctionFromCell(cell, function, &miss); | 2244 GenerateLoadFunctionFromCell(cell, function, &miss); |
2429 } | 2245 } |
2430 | 2246 |
2431 // Load the (only) argument into v0. | 2247 // Load the (only) argument into v0. |
2432 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | 2248 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); |
2433 | 2249 |
2434 // Check if the argument is a smi. | 2250 // Check if the argument is a smi. |
2435 Label not_smi; | 2251 Label not_smi; |
2436 STATIC_ASSERT(kSmiTag == 0); | 2252 STATIC_ASSERT(kSmiTag == 0); |
2437 __ JumpIfNotSmi(v0, ¬_smi); | 2253 __ JumpIfNotSmi(v0, ¬_smi); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2476 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 2292 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
2477 __ DropAndRet(argc + 1); | 2293 __ DropAndRet(argc + 1); |
2478 | 2294 |
2479 // Tail call the full function. We do not have to patch the receiver | 2295 // Tail call the full function. We do not have to patch the receiver |
2480 // because the function makes no use of it. | 2296 // because the function makes no use of it. |
2481 __ bind(&slow); | 2297 __ bind(&slow); |
2482 ParameterCount expected(function); | 2298 ParameterCount expected(function); |
2483 __ InvokeFunction(function, expected, arguments(), | 2299 __ InvokeFunction(function, expected, arguments(), |
2484 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2300 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2485 | 2301 |
2486 __ bind(&miss); | 2302 HandlerFrontendFooter(&miss); |
2487 // a2: function name. | |
2488 GenerateMissBranch(); | |
2489 | 2303 |
2490 // Return the generated code. | 2304 // Return the generated code. |
2491 return GetCode(type, name); | 2305 return GetCode(type, name); |
2492 } | 2306 } |
2493 | 2307 |
2494 | 2308 |
2495 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2309 Handle<Code> CallStubCompiler::CompileFastApiCall( |
2496 const CallOptimization& optimization, | 2310 const CallOptimization& optimization, |
2497 Handle<Object> object, | 2311 Handle<Object> object, |
2498 Handle<JSObject> holder, | 2312 Handle<JSObject> holder, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2550 Label success; | 2364 Label success; |
2551 // Check that the object is a boolean. | 2365 // Check that the object is a boolean. |
2552 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 2366 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
2553 __ Branch(&success, eq, object, Operand(at)); | 2367 __ Branch(&success, eq, object, Operand(at)); |
2554 __ LoadRoot(at, Heap::kFalseValueRootIndex); | 2368 __ LoadRoot(at, Heap::kFalseValueRootIndex); |
2555 __ Branch(miss, ne, object, Operand(at)); | 2369 __ Branch(miss, ne, object, Operand(at)); |
2556 __ bind(&success); | 2370 __ bind(&success); |
2557 } | 2371 } |
2558 | 2372 |
2559 | 2373 |
2560 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2374 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
2561 Handle<JSObject> holder, | 2375 if (object->IsGlobalObject()) { |
2562 Handle<Name> name, | 2376 const int argc = arguments().immediate(); |
2563 CheckType check) { | 2377 const int receiver_offset = argc * kPointerSize; |
| 2378 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); |
| 2379 __ sw(a3, MemOperand(sp, receiver_offset)); |
| 2380 } |
| 2381 } |
| 2382 |
| 2383 |
| 2384 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
| 2385 Handle<JSObject> holder, |
| 2386 Handle<Name> name, |
| 2387 CheckType check, |
| 2388 Label* miss) { |
2564 // ----------- S t a t e ------------- | 2389 // ----------- S t a t e ------------- |
2565 // -- a2 : name | 2390 // -- a2 : name |
2566 // -- ra : return address | 2391 // -- ra : return address |
2567 // ----------------------------------- | 2392 // ----------------------------------- |
2568 Label miss; | 2393 GenerateNameCheck(name, miss); |
2569 GenerateNameCheck(name, &miss); | 2394 |
| 2395 Register reg = a0; |
2570 | 2396 |
2571 // Get the receiver from the stack. | 2397 // Get the receiver from the stack. |
2572 const int argc = arguments().immediate(); | 2398 const int argc = arguments().immediate(); |
2573 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2399 const int receiver_offset = argc * kPointerSize; |
| 2400 __ lw(a0, MemOperand(sp, receiver_offset)); |
2574 | 2401 |
2575 // Check that the receiver isn't a smi. | 2402 // Check that the receiver isn't a smi. |
2576 if (check != NUMBER_CHECK) { | 2403 if (check != NUMBER_CHECK) { |
2577 __ JumpIfSmi(a1, &miss); | 2404 __ JumpIfSmi(a0, miss); |
2578 } | 2405 } |
2579 | 2406 |
2580 // Make sure that it's okay not to patch the on stack receiver | 2407 // Make sure that it's okay not to patch the on stack receiver |
2581 // unless we're doing a receiver map check. | 2408 // unless we're doing a receiver map check. |
2582 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2409 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
2583 switch (check) { | 2410 switch (check) { |
2584 case RECEIVER_MAP_CHECK: | 2411 case RECEIVER_MAP_CHECK: |
2585 __ IncrementCounter(isolate()->counters()->call_const(), 1, a0, a3); | 2412 __ IncrementCounter(isolate()->counters()->call_const(), 1, a1, a3); |
2586 | 2413 |
2587 // Check that the maps haven't changed. | 2414 // Check that the maps haven't changed. |
2588 CheckPrototypes( | 2415 reg = CheckPrototypes( |
2589 IC::CurrentTypeOf(object, isolate()), | 2416 IC::CurrentTypeOf(object, isolate()), |
2590 a1, holder, a0, a3, t0, name, &miss); | 2417 reg, holder, a1, a3, t0, name, miss); |
2591 | |
2592 // Patch the receiver on the stack with the global proxy if | |
2593 // necessary. | |
2594 if (object->IsGlobalObject()) { | |
2595 __ lw(a3, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); | |
2596 __ sw(a3, MemOperand(sp, argc * kPointerSize)); | |
2597 } | |
2598 break; | 2418 break; |
2599 | 2419 |
2600 case STRING_CHECK: { | 2420 case STRING_CHECK: { |
2601 // Check that the object is a string. | 2421 // Check that the object is a string. |
2602 __ GetObjectType(a1, a3, a3); | 2422 __ GetObjectType(reg, a3, a3); |
2603 __ Branch(&miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE)); | 2423 __ Branch(miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE)); |
2604 // Check that the maps starting from the prototype haven't changed. | 2424 // Check that the maps starting from the prototype haven't changed. |
2605 GenerateDirectLoadGlobalFunctionPrototype( | 2425 GenerateDirectLoadGlobalFunctionPrototype( |
2606 masm(), Context::STRING_FUNCTION_INDEX, a0, &miss); | 2426 masm(), Context::STRING_FUNCTION_INDEX, a1, miss); |
2607 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
2608 CheckPrototypes( | |
2609 IC::CurrentTypeOf(prototype, isolate()), | |
2610 a0, holder, a3, a1, t0, name, &miss); | |
2611 break; | 2427 break; |
2612 } | 2428 } |
2613 case SYMBOL_CHECK: { | 2429 case SYMBOL_CHECK: { |
2614 // Check that the object is a symbol. | 2430 // Check that the object is a symbol. |
2615 __ GetObjectType(a1, a1, a3); | 2431 __ GetObjectType(reg, a1, a3); |
2616 __ Branch(&miss, ne, a3, Operand(SYMBOL_TYPE)); | 2432 __ Branch(miss, ne, a3, Operand(SYMBOL_TYPE)); |
2617 // Check that the maps starting from the prototype haven't changed. | 2433 // Check that the maps starting from the prototype haven't changed. |
2618 GenerateDirectLoadGlobalFunctionPrototype( | 2434 GenerateDirectLoadGlobalFunctionPrototype( |
2619 masm(), Context::SYMBOL_FUNCTION_INDEX, a0, &miss); | 2435 masm(), Context::SYMBOL_FUNCTION_INDEX, a1, miss); |
2620 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
2621 CheckPrototypes( | |
2622 IC::CurrentTypeOf(prototype, isolate()), | |
2623 a0, holder, a3, a1, t0, name, &miss); | |
2624 break; | 2436 break; |
2625 } | 2437 } |
2626 case NUMBER_CHECK: { | 2438 case NUMBER_CHECK: { |
2627 Label fast; | 2439 Label fast; |
2628 // Check that the object is a smi or a heap number. | 2440 // Check that the object is a smi or a heap number. |
2629 __ JumpIfSmi(a1, &fast); | 2441 __ JumpIfSmi(reg, &fast); |
2630 __ GetObjectType(a1, a0, a0); | 2442 __ GetObjectType(reg, a3, a3); |
2631 __ Branch(&miss, ne, a0, Operand(HEAP_NUMBER_TYPE)); | 2443 __ Branch(miss, ne, a3, Operand(HEAP_NUMBER_TYPE)); |
2632 __ bind(&fast); | 2444 __ bind(&fast); |
2633 // Check that the maps starting from the prototype haven't changed. | 2445 // Check that the maps starting from the prototype haven't changed. |
2634 GenerateDirectLoadGlobalFunctionPrototype( | 2446 GenerateDirectLoadGlobalFunctionPrototype( |
2635 masm(), Context::NUMBER_FUNCTION_INDEX, a0, &miss); | 2447 masm(), Context::NUMBER_FUNCTION_INDEX, a1, miss); |
2636 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
2637 CheckPrototypes( | |
2638 IC::CurrentTypeOf(prototype, isolate()), | |
2639 a0, holder, a3, a1, t0, name, &miss); | |
2640 break; | 2448 break; |
2641 } | 2449 } |
2642 case BOOLEAN_CHECK: { | 2450 case BOOLEAN_CHECK: { |
2643 GenerateBooleanCheck(a1, &miss); | 2451 GenerateBooleanCheck(reg, miss); |
2644 | 2452 |
2645 // Check that the maps starting from the prototype haven't changed. | 2453 // Check that the maps starting from the prototype haven't changed. |
2646 GenerateDirectLoadGlobalFunctionPrototype( | 2454 GenerateDirectLoadGlobalFunctionPrototype( |
2647 masm(), Context::BOOLEAN_FUNCTION_INDEX, a0, &miss); | 2455 masm(), Context::BOOLEAN_FUNCTION_INDEX, a1, miss); |
2648 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
2649 CheckPrototypes( | |
2650 IC::CurrentTypeOf(prototype, isolate()), | |
2651 a0, holder, a3, a1, t0, name, &miss); | |
2652 break; | 2456 break; |
2653 } | 2457 } |
2654 } | 2458 } |
2655 | 2459 |
2656 Label success; | 2460 if (check != RECEIVER_MAP_CHECK) { |
2657 __ Branch(&success); | 2461 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2462 reg = CheckPrototypes( |
| 2463 IC::CurrentTypeOf(prototype, isolate()), |
| 2464 a1, holder, a1, a3, t0, name, miss); |
| 2465 } |
2658 | 2466 |
2659 // Handle call cache miss. | 2467 return reg; |
2660 __ bind(&miss); | |
2661 | |
2662 GenerateMissBranch(); | |
2663 | |
2664 __ bind(&success); | |
2665 } | 2468 } |
2666 | 2469 |
2667 | 2470 |
2668 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2471 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
2669 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2472 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2670 ? CALL_AS_FUNCTION | 2473 ? CALL_AS_FUNCTION |
2671 : CALL_AS_METHOD; | 2474 : CALL_AS_METHOD; |
2672 ParameterCount expected(function); | 2475 ParameterCount expected(function); |
2673 __ InvokeFunction(function, expected, arguments(), | 2476 __ InvokeFunction(function, expected, arguments(), |
2674 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2477 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
2675 } | 2478 } |
2676 | 2479 |
2677 | 2480 |
2678 Handle<Code> CallStubCompiler::CompileCallConstant( | 2481 Handle<Code> CallStubCompiler::CompileCallConstant( |
2679 Handle<Object> object, | 2482 Handle<Object> object, |
2680 Handle<JSObject> holder, | 2483 Handle<JSObject> holder, |
2681 Handle<Name> name, | 2484 Handle<Name> name, |
2682 CheckType check, | 2485 CheckType check, |
2683 Handle<JSFunction> function) { | 2486 Handle<JSFunction> function) { |
2684 if (HasCustomCallGenerator(function)) { | 2487 if (HasCustomCallGenerator(function)) { |
2685 Handle<Code> code = CompileCustomCall(object, holder, | 2488 Handle<Code> code = CompileCustomCall(object, holder, |
2686 Handle<Cell>::null(), | 2489 Handle<Cell>::null(), |
2687 function, Handle<String>::cast(name), | 2490 function, Handle<String>::cast(name), |
2688 Code::FAST); | 2491 Code::FAST); |
2689 // A null handle means bail out to the regular compiler code below. | 2492 // A null handle means bail out to the regular compiler code below. |
2690 if (!code.is_null()) return code; | 2493 if (!code.is_null()) return code; |
2691 } | 2494 } |
2692 | 2495 |
2693 CompileHandlerFrontend(object, holder, name, check); | 2496 Label miss; |
| 2497 HandlerFrontendHeader(object, holder, name, check, &miss); |
| 2498 PatchGlobalProxy(object); |
2694 CompileHandlerBackend(function); | 2499 CompileHandlerBackend(function); |
| 2500 HandlerFrontendFooter(&miss); |
2695 | 2501 |
2696 // Return the generated code. | 2502 // Return the generated code. |
2697 return GetCode(function); | 2503 return GetCode(function); |
2698 } | 2504 } |
2699 | 2505 |
2700 | 2506 |
2701 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2507 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
2702 Handle<JSObject> holder, | 2508 Handle<JSObject> holder, |
2703 Handle<Name> name) { | 2509 Handle<Name> name) { |
2704 // ----------- S t a t e ------------- | |
2705 // -- a2 : name | |
2706 // -- ra : return address | |
2707 // ----------------------------------- | |
2708 | |
2709 Label miss; | 2510 Label miss; |
2710 | 2511 |
2711 GenerateNameCheck(name, &miss); | 2512 GenerateNameCheck(name, &miss); |
2712 | 2513 |
2713 // Get the number of arguments. | 2514 // Get the number of arguments. |
2714 const int argc = arguments().immediate(); | 2515 const int argc = arguments().immediate(); |
2715 LookupResult lookup(isolate()); | 2516 LookupResult lookup(isolate()); |
2716 LookupPostInterceptor(holder, name, &lookup); | 2517 LookupPostInterceptor(holder, name, &lookup); |
2717 | 2518 |
2718 // Get the receiver from the stack. | 2519 // Get the receiver from the stack. |
(...skipping 18 matching lines...) Expand all Loading... |
2737 return GetCode(Code::FAST, name); | 2538 return GetCode(Code::FAST, name); |
2738 } | 2539 } |
2739 | 2540 |
2740 | 2541 |
2741 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2542 Handle<Code> CallStubCompiler::CompileCallGlobal( |
2742 Handle<JSObject> object, | 2543 Handle<JSObject> object, |
2743 Handle<GlobalObject> holder, | 2544 Handle<GlobalObject> holder, |
2744 Handle<PropertyCell> cell, | 2545 Handle<PropertyCell> cell, |
2745 Handle<JSFunction> function, | 2546 Handle<JSFunction> function, |
2746 Handle<Name> name) { | 2547 Handle<Name> name) { |
2747 // ----------- S t a t e ------------- | |
2748 // -- a2 : name | |
2749 // -- ra : return address | |
2750 // ----------------------------------- | |
2751 | |
2752 if (HasCustomCallGenerator(function)) { | 2548 if (HasCustomCallGenerator(function)) { |
2753 Handle<Code> code = CompileCustomCall( | 2549 Handle<Code> code = CompileCustomCall( |
2754 object, holder, cell, function, Handle<String>::cast(name), | 2550 object, holder, cell, function, Handle<String>::cast(name), |
2755 Code::NORMAL); | 2551 Code::NORMAL); |
2756 // A null handle means bail out to the regular compiler code below. | 2552 // A null handle means bail out to the regular compiler code below. |
2757 if (!code.is_null()) return code; | 2553 if (!code.is_null()) return code; |
2758 } | 2554 } |
2759 | 2555 |
2760 Label miss; | 2556 Label miss; |
2761 GenerateNameCheck(name, &miss); | 2557 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2762 | |
2763 // Get the number of arguments. | |
2764 const int argc = arguments().immediate(); | |
2765 GenerateGlobalReceiverCheck(object, holder, name, &miss); | |
2766 GenerateLoadFunctionFromCell(cell, function, &miss); | 2558 GenerateLoadFunctionFromCell(cell, function, &miss); |
2767 | 2559 PatchGlobalProxy(object); |
2768 // Patch the receiver on the stack with the global proxy if | |
2769 // necessary. | |
2770 if (object->IsGlobalObject()) { | |
2771 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); | |
2772 __ sw(a3, MemOperand(sp, argc * kPointerSize)); | |
2773 } | |
2774 | 2560 |
2775 // Set up the context (function already in r1). | 2561 // Set up the context (function already in r1). |
2776 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 2562 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
2777 | 2563 |
2778 // Jump to the cached code (tail call). | 2564 // Jump to the cached code (tail call). |
2779 Counters* counters = isolate()->counters(); | 2565 Counters* counters = isolate()->counters(); |
2780 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); | 2566 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); |
2781 ParameterCount expected(function->shared()->formal_parameter_count()); | 2567 ParameterCount expected(function->shared()->formal_parameter_count()); |
2782 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2568 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2783 ? CALL_AS_FUNCTION | 2569 ? CALL_AS_FUNCTION |
2784 : CALL_AS_METHOD; | 2570 : CALL_AS_METHOD; |
2785 // We call indirectly through the code field in the function to | 2571 // We call indirectly through the code field in the function to |
2786 // allow recompilation to take effect without changing any of the | 2572 // allow recompilation to take effect without changing any of the |
2787 // call sites. | 2573 // call sites. |
2788 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 2574 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
2789 __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, | 2575 __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, |
2790 NullCallWrapper(), call_kind); | 2576 NullCallWrapper(), call_kind); |
2791 | 2577 |
2792 // Handle call cache miss. | 2578 HandlerFrontendFooter(&miss); |
2793 __ bind(&miss); | |
2794 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); | |
2795 GenerateMissBranch(); | |
2796 | 2579 |
2797 // Return the generated code. | 2580 // Return the generated code. |
2798 return GetCode(Code::NORMAL, name); | 2581 return GetCode(Code::NORMAL, name); |
2799 } | 2582 } |
2800 | 2583 |
2801 | 2584 |
2802 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2585 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2803 Handle<JSObject> object, | 2586 Handle<JSObject> object, |
2804 Handle<JSObject> holder, | 2587 Handle<JSObject> holder, |
2805 Handle<Name> name, | 2588 Handle<Name> name, |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3177 // ----------------------------------- | 2960 // ----------------------------------- |
3178 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2961 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
3179 } | 2962 } |
3180 | 2963 |
3181 | 2964 |
3182 #undef __ | 2965 #undef __ |
3183 | 2966 |
3184 } } // namespace v8::internal | 2967 } } // namespace v8::internal |
3185 | 2968 |
3186 #endif // V8_TARGET_ARCH_MIPS | 2969 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |