| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 __ Mov(this->name(), Operand(name)); | 702 __ Mov(this->name(), Operand(name)); |
| 703 } | 703 } |
| 704 } | 704 } |
| 705 | 705 |
| 706 | 706 |
| 707 // The function to called must be passed in x1. | 707 // The function to called must be passed in x1. |
| 708 static void GenerateCallFunction(MacroAssembler* masm, | 708 static void GenerateCallFunction(MacroAssembler* masm, |
| 709 Handle<Object> object, | 709 Handle<Object> object, |
| 710 const ParameterCount& arguments, | 710 const ParameterCount& arguments, |
| 711 Label* miss, | 711 Label* miss, |
| 712 Code::ExtraICState extra_ic_state, | 712 ExtraICState extra_ic_state, |
| 713 Register function, | 713 Register function, |
| 714 Register receiver, | 714 Register receiver, |
| 715 Register scratch) { | 715 Register scratch) { |
| 716 ASSERT(!AreAliased(function, receiver, scratch)); | 716 ASSERT(!AreAliased(function, receiver, scratch)); |
| 717 ASSERT(function.Is(x1)); | 717 ASSERT(function.Is(x1)); |
| 718 | 718 |
| 719 // Check that the function really is a function. | 719 // Check that the function really is a function. |
| 720 __ JumpIfSmi(function, miss); | 720 __ JumpIfSmi(function, miss); |
| 721 __ JumpIfNotObjectType(function, scratch, scratch, JS_FUNCTION_TYPE, miss); | 721 __ JumpIfNotObjectType(function, scratch, scratch, JS_FUNCTION_TYPE, miss); |
| 722 | 722 |
| 723 // Patch the receiver on the stack with the global proxy if necessary. | |
| 724 if (object->IsGlobalObject()) { | 723 if (object->IsGlobalObject()) { |
| 724 const int argc = arguments.immediate(); |
| 725 const int receiver_offset = argc * kPointerSize; |
| 725 __ Ldr(scratch, | 726 __ Ldr(scratch, |
| 726 FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); | 727 FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); |
| 727 __ Poke(scratch, arguments.immediate() * kPointerSize); | 728 __ Poke(scratch, receiver_offset); |
| 728 } | 729 } |
| 729 | 730 |
| 730 // Invoke the function. | 731 // Invoke the function. |
| 731 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | 732 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) |
| 732 ? CALL_AS_FUNCTION | 733 ? CALL_AS_FUNCTION |
| 733 : CALL_AS_METHOD; | 734 : CALL_AS_METHOD; |
| 734 __ InvokeFunction( | 735 __ InvokeFunction( |
| 735 function, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | 736 function, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 736 } | 737 } |
| 737 | 738 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 933 | 934 |
| 934 GenerateFastApiDirectCall(masm, optimization, argc, true); | 935 GenerateFastApiDirectCall(masm, optimization, argc, true); |
| 935 } | 936 } |
| 936 | 937 |
| 937 | 938 |
| 938 class CallInterceptorCompiler BASE_EMBEDDED { | 939 class CallInterceptorCompiler BASE_EMBEDDED { |
| 939 public: | 940 public: |
| 940 CallInterceptorCompiler(StubCompiler* stub_compiler, | 941 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 941 const ParameterCount& arguments, | 942 const ParameterCount& arguments, |
| 942 Register name, | 943 Register name, |
| 943 Code::ExtraICState extra_ic_state) | 944 ExtraICState extra_ic_state) |
| 944 : stub_compiler_(stub_compiler), | 945 : stub_compiler_(stub_compiler), |
| 945 arguments_(arguments), | 946 arguments_(arguments), |
| 946 name_(name), | 947 name_(name), |
| 947 extra_ic_state_(extra_ic_state) {} | 948 extra_ic_state_(extra_ic_state) {} |
| 948 | 949 |
| 949 void Compile(MacroAssembler* masm, | 950 void Compile(MacroAssembler* masm, |
| 950 Handle<JSObject> object, | 951 Handle<JSObject> object, |
| 951 Handle<JSObject> holder, | 952 Handle<JSObject> holder, |
| 952 Handle<Name> name, | 953 Handle<Name> name, |
| 953 LookupResult* lookup, | 954 LookupResult* lookup, |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1119 | 1120 |
| 1120 // If interceptor returns no-result sentinel, call the constant function. | 1121 // If interceptor returns no-result sentinel, call the constant function. |
| 1121 __ JumpIfNotRoot(x0, | 1122 __ JumpIfNotRoot(x0, |
| 1122 Heap::kNoInterceptorResultSentinelRootIndex, | 1123 Heap::kNoInterceptorResultSentinelRootIndex, |
| 1123 interceptor_succeeded); | 1124 interceptor_succeeded); |
| 1124 } | 1125 } |
| 1125 | 1126 |
| 1126 StubCompiler* stub_compiler_; | 1127 StubCompiler* stub_compiler_; |
| 1127 const ParameterCount& arguments_; | 1128 const ParameterCount& arguments_; |
| 1128 Register name_; | 1129 Register name_; |
| 1129 Code::ExtraICState extra_ic_state_; | 1130 ExtraICState extra_ic_state_; |
| 1130 }; | 1131 }; |
| 1131 | 1132 |
| 1132 | 1133 |
| 1133 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1134 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1134 __ Jump(code, RelocInfo::CODE_TARGET); | 1135 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1135 } | 1136 } |
| 1136 | 1137 |
| 1137 | 1138 |
| 1138 #undef __ | 1139 #undef __ |
| 1139 #define __ ACCESS_MASM(masm()) | 1140 #define __ ACCESS_MASM(masm()) |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1561 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1562 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1562 Register name_reg = x2; | 1563 Register name_reg = x2; |
| 1563 | 1564 |
| 1564 if (kind_ == Code::KEYED_CALL_IC) { | 1565 if (kind_ == Code::KEYED_CALL_IC) { |
| 1565 __ Cmp(name_reg, Operand(name)); | 1566 __ Cmp(name_reg, Operand(name)); |
| 1566 __ B(ne, miss); | 1567 __ B(ne, miss); |
| 1567 } | 1568 } |
| 1568 } | 1569 } |
| 1569 | 1570 |
| 1570 | 1571 |
| 1571 // The receiver is loaded from the stack and left in x0 register. | |
| 1572 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, | |
| 1573 Handle<JSObject> holder, | |
| 1574 Handle<Name> name, | |
| 1575 Label* miss) { | |
| 1576 ASSERT(holder->IsGlobalObject()); | |
| 1577 | |
| 1578 const int argc = arguments().immediate(); | |
| 1579 | |
| 1580 // Get the receiver from the stack. | |
| 1581 Register receiver = x0; | |
| 1582 __ Peek(receiver, argc * kPointerSize); | |
| 1583 | |
| 1584 // Check that the maps haven't changed. | |
| 1585 __ JumpIfSmi(receiver, miss); | |
| 1586 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), | |
| 1587 receiver, holder, x3, x1, x4, name, miss); | |
| 1588 } | |
| 1589 | |
| 1590 | |
| 1591 // Load the function object into x1 register. | 1572 // Load the function object into x1 register. |
| 1592 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1573 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1593 Handle<Cell> cell, | 1574 Handle<Cell> cell, |
| 1594 Handle<JSFunction> function, | 1575 Handle<JSFunction> function, |
| 1595 Label* miss) { | 1576 Label* miss) { |
| 1596 // Get the value from the cell. | 1577 // Get the value from the cell. |
| 1597 __ Mov(x3, Operand(cell)); | 1578 __ Mov(x3, Operand(cell)); |
| 1598 Register function_reg = x1; | 1579 Register function_reg = x1; |
| 1599 __ Ldr(function_reg, FieldMemOperand(x3, Cell::kValueOffset)); | 1580 __ Ldr(function_reg, FieldMemOperand(x3, Cell::kValueOffset)); |
| 1600 | 1581 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1626 kind_, | 1607 kind_, |
| 1627 extra_state_); | 1608 extra_state_); |
| 1628 __ Jump(code, RelocInfo::CODE_TARGET); | 1609 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1629 } | 1610 } |
| 1630 | 1611 |
| 1631 | 1612 |
| 1632 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1613 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1633 Handle<JSObject> holder, | 1614 Handle<JSObject> holder, |
| 1634 PropertyIndex index, | 1615 PropertyIndex index, |
| 1635 Handle<Name> name) { | 1616 Handle<Name> name) { |
| 1636 // ----------- S t a t e ------------- | |
| 1637 // -- x2 : name | |
| 1638 // -- lr : return address | |
| 1639 // ----------------------------------- | |
| 1640 Label miss; | 1617 Label miss; |
| 1641 const int argc = arguments().immediate(); | 1618 Register receiver = x0; |
| 1619 Register function = x1; |
| 1642 | 1620 |
| 1643 GenerateNameCheck(name, &miss); | 1621 Register holder_reg = HandlerFrontendHeader( |
| 1622 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1644 | 1623 |
| 1645 // Get the receiver of the function from the stack. | |
| 1646 Register receiver = x0; | |
| 1647 __ Peek(receiver, argc * kXRegSizeInBytes); | |
| 1648 // Check that the receiver isn't a smi. | |
| 1649 __ JumpIfSmi(receiver, &miss); | |
| 1650 | |
| 1651 // Do the right check and compute the holder register. | |
| 1652 Register holder_reg = CheckPrototypes( | |
| 1653 IC::CurrentTypeOf(object, isolate()), | |
| 1654 receiver, holder, x1, x3, x4, name, &miss); | |
| 1655 Register function = x1; | |
| 1656 GenerateFastPropertyLoad(masm(), function, holder_reg, | 1624 GenerateFastPropertyLoad(masm(), function, holder_reg, |
| 1657 index.is_inobject(holder), | 1625 index.is_inobject(holder), |
| 1658 index.translate(holder), | 1626 index.translate(holder), |
| 1659 Representation::Tagged()); | 1627 Representation::Tagged()); |
| 1660 | 1628 |
| 1661 GenerateCallFunction( | 1629 GenerateCallFunction( |
| 1662 masm(), object, arguments(), &miss, extra_state_, function, receiver, x3); | 1630 masm(), object, arguments(), &miss, extra_state_, function, receiver, x3); |
| 1663 | 1631 |
| 1664 // Handle call cache miss. | 1632 HandlerFrontendFooter(&miss); |
| 1665 __ Bind(&miss); | |
| 1666 GenerateMissBranch(); | |
| 1667 | 1633 |
| 1668 // Return the generated code. | 1634 // Return the generated code. |
| 1669 return GetCode(Code::FAST, name); | 1635 return GetCode(Code::FAST, name); |
| 1670 } | 1636 } |
| 1671 | 1637 |
| 1672 | 1638 |
| 1673 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1639 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1674 Handle<Object> object, | 1640 Handle<Object> object, |
| 1675 Handle<JSObject> holder, | 1641 Handle<JSObject> holder, |
| 1676 Handle<Cell> cell, | 1642 Handle<Cell> cell, |
| 1677 Handle<JSFunction> function, | 1643 Handle<JSFunction> function, |
| 1678 Handle<String> name, | 1644 Handle<String> name, |
| 1679 Code::StubType type) { | 1645 Code::StubType type) { |
| 1680 // ----------- S t a t e ------------- | |
| 1681 // -- x2 : name | |
| 1682 // -- lr : return address | |
| 1683 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) | |
| 1684 // -- ... | |
| 1685 // -- sp[argc * 8] : receiver | |
| 1686 // ----------------------------------- | |
| 1687 Label miss; | 1646 Label miss; |
| 1688 | 1647 |
| 1689 // Check that function is still array. | 1648 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1690 const int argc = arguments().immediate(); | 1649 if (!cell.is_null()) { |
| 1691 GenerateNameCheck(name, &miss); | |
| 1692 | |
| 1693 Register receiver = x1; | |
| 1694 if (cell.is_null()) { | |
| 1695 __ Peek(receiver, argc * kPointerSize); | |
| 1696 | |
| 1697 // Check that the receiver isn't a smi. | |
| 1698 __ JumpIfSmi(receiver, &miss); | |
| 1699 | |
| 1700 // Check that the maps haven't changed. | |
| 1701 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), | |
| 1702 receiver, holder, x3, x0, x4, name, &miss); | |
| 1703 } else { | |
| 1704 ASSERT(cell->value() == *function); | 1650 ASSERT(cell->value() == *function); |
| 1705 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 1706 &miss); | |
| 1707 GenerateLoadFunctionFromCell(cell, function, &miss); | 1651 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1708 } | 1652 } |
| 1709 | 1653 |
| 1710 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1654 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1711 site->SetElementsKind(GetInitialFastElementsKind()); | 1655 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1712 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1656 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| 1657 const int argc = arguments().immediate(); |
| 1713 __ Mov(x0, argc); | 1658 __ Mov(x0, argc); |
| 1714 __ Mov(x1, Operand(function)); | 1659 __ Mov(x1, Operand(function)); |
| 1715 __ Mov(x2, Operand(site_feedback_cell)); | 1660 __ Mov(x2, Operand(site_feedback_cell)); |
| 1716 | 1661 |
| 1717 ArrayConstructorStub stub(isolate()); | 1662 ArrayConstructorStub stub(isolate()); |
| 1718 __ TailCallStub(&stub); | 1663 __ TailCallStub(&stub); |
| 1719 | 1664 |
| 1720 __ Bind(&miss); | 1665 HandlerFrontendFooter(&miss); |
| 1721 GenerateMissBranch(); | |
| 1722 | 1666 |
| 1723 // Return the generated code. | 1667 // Return the generated code. |
| 1724 return GetCode(type, name); | 1668 return GetCode(type, name); |
| 1725 } | 1669 } |
| 1726 | 1670 |
| 1727 | 1671 |
| 1728 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1672 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1729 Handle<Object> object, | 1673 Handle<Object> object, |
| 1730 Handle<JSObject> holder, | 1674 Handle<JSObject> holder, |
| 1731 Handle<Cell> cell, | 1675 Handle<Cell> cell, |
| 1732 Handle<JSFunction> function, | 1676 Handle<JSFunction> function, |
| 1733 Handle<String> name, | 1677 Handle<String> name, |
| 1734 Code::StubType type) { | 1678 Code::StubType type) { |
| 1735 // ----------- S t a t e ------------- | |
| 1736 // -- x2 : name (Must be preserved on miss.) | |
| 1737 // -- lr : return address | |
| 1738 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) | |
| 1739 // -- ... | |
| 1740 // -- sp[argc * 8] : receiver | |
| 1741 // ----------------------------------- | |
| 1742 | |
| 1743 // If object is not an array or is observed, bail out to regular call. | 1679 // If object is not an array or is observed, bail out to regular call. |
| 1744 if (!object->IsJSArray() || | 1680 if (!object->IsJSArray() || |
| 1745 !cell.is_null() || | 1681 !cell.is_null() || |
| 1746 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1682 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 1747 return Handle<Code>::null(); | 1683 return Handle<Code>::null(); |
| 1748 } | 1684 } |
| 1749 | 1685 |
| 1750 Label miss; | 1686 Label miss; |
| 1751 Register result = x0; | 1687 |
| 1688 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1689 |
| 1690 Register receiver = x0; |
| 1691 |
| 1752 const int argc = arguments().immediate(); | 1692 const int argc = arguments().immediate(); |
| 1753 | |
| 1754 GenerateNameCheck(name, &miss); | |
| 1755 | |
| 1756 // Get the receiver from the stack | |
| 1757 Register receiver = x1; | |
| 1758 __ Peek(receiver, argc * kPointerSize); | |
| 1759 | |
| 1760 // Check that the receiver isn't a smi. | |
| 1761 __ JumpIfSmi(receiver, &miss); | |
| 1762 | |
| 1763 // Check that the maps haven't changed. | |
| 1764 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), | |
| 1765 receiver, holder, x3, x0, x4, name, &miss); | |
| 1766 | |
| 1767 if (argc == 0) { | 1693 if (argc == 0) { |
| 1768 // Nothing to do, just return the length. | 1694 // Nothing to do, just return the length. |
| 1769 __ Ldr(result, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1695 __ Ldr(x0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1770 __ Drop(argc + 1); | 1696 __ Drop(argc + 1); |
| 1771 __ Ret(); | 1697 __ Ret(); |
| 1772 } else { | 1698 } else { |
| 1773 Label call_builtin; | 1699 Label call_builtin; |
| 1774 | 1700 |
| 1775 if (argc == 1) { // Otherwise fall through to call the builtin. | 1701 if (argc == 1) { // Otherwise fall through to call the builtin. |
| 1776 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1702 Label attempt_to_grow_elements, with_write_barrier, check_double; |
| 1777 | 1703 |
| 1778 // Note that even though we assign the array length to x0 and the value | 1704 Register elements_length = x8; |
| 1779 // to push in x4, they are not always live. Both x0 and x4 can be locally | 1705 Register length = x7; |
| 1780 // reused as scratch registers. | |
| 1781 Register length = x0; | |
| 1782 Register value = x4; | |
| 1783 Register elements = x6; | 1706 Register elements = x6; |
| 1784 Register end_elements = x5; | 1707 Register end_elements = x5; |
| 1708 Register value = x4; |
| 1785 // Get the elements array of the object. | 1709 // Get the elements array of the object. |
| 1786 __ Ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1710 __ Ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 1787 | 1711 |
| 1788 // Check that the elements are in fast mode and writable. | 1712 // Check that the elements are in fast mode and writable. |
| 1789 __ CheckMap(elements, | 1713 __ CheckMap(elements, |
| 1790 x0, | 1714 x10, |
| 1791 Heap::kFixedArrayMapRootIndex, | 1715 Heap::kFixedArrayMapRootIndex, |
| 1792 &check_double, | 1716 &check_double, |
| 1793 DONT_DO_SMI_CHECK); | 1717 DONT_DO_SMI_CHECK); |
| 1794 | 1718 |
| 1795 // Get the array's length and calculate new length. | 1719 // Get the array's length and calculate new length. |
| 1796 __ Ldr(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1720 __ Ldr(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1797 STATIC_ASSERT(kSmiTag == 0); | 1721 STATIC_ASSERT(kSmiTag == 0); |
| 1798 __ Add(length, length, Operand(Smi::FromInt(argc))); | 1722 __ Add(length, length, Operand(Smi::FromInt(argc))); |
| 1799 | 1723 |
| 1800 // Check if we could survive without allocation. | 1724 // Check if we could survive without allocation. |
| 1801 __ Ldr(x4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1725 __ Ldr(elements_length, |
| 1802 __ Cmp(length, x4); | 1726 FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1727 __ Cmp(length, elements_length); |
| 1803 __ B(gt, &attempt_to_grow_elements); | 1728 __ B(gt, &attempt_to_grow_elements); |
| 1804 | 1729 |
| 1805 // Check if value is a smi. | 1730 // Check if value is a smi. |
| 1806 __ Peek(value, (argc - 1) * kPointerSize); | 1731 __ Peek(value, (argc - 1) * kPointerSize); |
| 1807 __ JumpIfNotSmi(value, &with_write_barrier); | 1732 __ JumpIfNotSmi(value, &with_write_barrier); |
| 1808 | 1733 |
| 1809 // Save new length. | 1734 // Save new length. |
| 1810 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1735 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1811 | 1736 |
| 1812 // Store the value. | 1737 // Store the value. |
| 1813 // We may need a register containing the address end_elements below, | 1738 // We may need a register containing the address end_elements below, |
| 1814 // so write back the value in end_elements. | 1739 // so write back the value in end_elements. |
| 1815 __ Add(end_elements, elements, | 1740 __ Add(end_elements, elements, |
| 1816 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); | 1741 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); |
| 1817 const int kEndElementsOffset = | 1742 const int kEndElementsOffset = |
| 1818 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; | 1743 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; |
| 1819 __ Str(value, MemOperand(end_elements, kEndElementsOffset, PreIndex)); | 1744 __ Str(value, MemOperand(end_elements, kEndElementsOffset, PreIndex)); |
| 1820 | 1745 |
| 1821 // Check for a smi. | 1746 // Return length. |
| 1822 __ Drop(argc + 1); | 1747 __ Drop(argc + 1); |
| 1748 __ Mov(x0, length); |
| 1823 __ Ret(); | 1749 __ Ret(); |
| 1824 | 1750 |
| 1825 __ Bind(&check_double); | 1751 __ Bind(&check_double); |
| 1826 // Check that the elements are in fast mode and writable. | 1752 // Check that the elements are in fast mode and writable. |
| 1827 __ CheckMap(elements, | 1753 __ CheckMap(elements, |
| 1828 x0, | 1754 x0, |
| 1829 Heap::kFixedDoubleArrayMapRootIndex, | 1755 Heap::kFixedDoubleArrayMapRootIndex, |
| 1830 &call_builtin, | 1756 &call_builtin, |
| 1831 DONT_DO_SMI_CHECK); | 1757 DONT_DO_SMI_CHECK); |
| 1832 | 1758 |
| 1833 // Get the array's length and calculate new length. | 1759 // Get the array's length and calculate new length. |
| 1834 Register old_length = x5; | 1760 Register old_length = x5; |
| 1835 __ Ldr(old_length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1761 __ Ldr(old_length, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1836 STATIC_ASSERT(kSmiTag == 0); | 1762 STATIC_ASSERT(kSmiTag == 0); |
| 1837 __ Add(length, old_length, Operand(Smi::FromInt(argc))); | 1763 __ Add(length, old_length, Operand(Smi::FromInt(argc))); |
| 1838 | 1764 |
| 1839 // Check if we could survive without allocation. | 1765 // Check if we could survive without allocation. |
| 1840 __ Ldr(x4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1766 __ Ldr(x10, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1841 __ Cmp(length, x4); | 1767 __ Cmp(length, x10); |
| 1842 __ B(gt, &call_builtin); | 1768 __ B(gt, &call_builtin); |
| 1843 | 1769 |
| 1844 __ Peek(value, (argc - 1) * kPointerSize); | 1770 __ Peek(value, (argc - 1) * kPointerSize); |
| 1845 __ StoreNumberToDoubleElements( | 1771 __ StoreNumberToDoubleElements( |
| 1846 value, old_length, elements, x3, d0, d1, | 1772 value, old_length, elements, x10, d0, d1, |
| 1847 &call_builtin); | 1773 &call_builtin); |
| 1848 | 1774 |
| 1849 // Save new length. | 1775 // Save new length. |
| 1850 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1776 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1851 | 1777 |
| 1852 // Check for a smi. | 1778 // Return length. |
| 1853 __ Drop(argc + 1); | 1779 __ Drop(argc + 1); |
| 1780 __ Mov(x0, length); |
| 1854 __ Ret(); | 1781 __ Ret(); |
| 1855 | 1782 |
| 1856 | 1783 |
| 1857 __ Bind(&with_write_barrier); | 1784 __ Bind(&with_write_barrier); |
| 1858 Register map = x3; | 1785 Register map = x3; |
| 1859 __ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1786 __ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1860 | 1787 |
| 1861 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { | 1788 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { |
| 1862 Label fast_object, not_fast_object; | 1789 Label fast_object, not_fast_object; |
| 1863 __ CheckFastObjectElements(map, x7, ¬_fast_object); | 1790 __ CheckFastObjectElements(map, x10, ¬_fast_object); |
| 1864 __ B(&fast_object); | 1791 __ B(&fast_object); |
| 1865 | 1792 |
| 1866 // In case of fast smi-only, convert to fast object, otherwise bail out. | 1793 // In case of fast smi-only, convert to fast object, otherwise bail out. |
| 1867 __ Bind(¬_fast_object); | 1794 __ Bind(¬_fast_object); |
| 1868 __ CheckFastSmiElements(map, x7, &call_builtin); | 1795 __ CheckFastSmiElements(map, x10, &call_builtin); |
| 1869 | 1796 |
| 1870 __ Ldr(x7, FieldMemOperand(x4, HeapObject::kMapOffset)); | 1797 __ Ldr(x10, FieldMemOperand(value, HeapObject::kMapOffset)); |
| 1871 __ JumpIfRoot(x7, Heap::kHeapNumberMapRootIndex, &call_builtin); | 1798 __ JumpIfRoot(x10, Heap::kHeapNumberMapRootIndex, &call_builtin); |
| 1872 | 1799 |
| 1873 Label try_holey_map; | 1800 Label try_holey_map; |
| 1874 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | 1801 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, |
| 1875 FAST_ELEMENTS, | 1802 FAST_ELEMENTS, |
| 1876 map, | 1803 map, |
| 1877 x7, | 1804 x10, |
| 1878 &try_holey_map); | 1805 &try_holey_map); |
| 1879 // GenerateMapChangeElementsTransition expects the receiver to be in x2. | 1806 // GenerateMapChangeElementsTransition expects the receiver to be in x2. |
| 1880 // Since from this point we cannot jump on 'miss' it is ok to clobber | 1807 // Since from this point we cannot jump on 'miss' it is ok to clobber |
| 1881 // x2 (which initialy contained called function name). | 1808 // x2 (which initialy contained called function name). |
| 1882 __ Mov(x2, receiver); | 1809 __ Mov(x2, receiver); |
| 1883 ElementsTransitionGenerator:: | 1810 ElementsTransitionGenerator:: |
| 1884 GenerateMapChangeElementsTransition(masm(), | 1811 GenerateMapChangeElementsTransition(masm(), |
| 1885 DONT_TRACK_ALLOCATION_SITE, | 1812 DONT_TRACK_ALLOCATION_SITE, |
| 1886 NULL); | 1813 NULL); |
| 1887 __ B(&fast_object); | 1814 __ B(&fast_object); |
| 1888 | 1815 |
| 1889 __ Bind(&try_holey_map); | 1816 __ Bind(&try_holey_map); |
| 1890 __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS, | 1817 __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS, |
| 1891 FAST_HOLEY_ELEMENTS, | 1818 FAST_HOLEY_ELEMENTS, |
| 1892 map, | 1819 map, |
| 1893 x7, | 1820 x10, |
| 1894 &call_builtin); | 1821 &call_builtin); |
| 1895 // The previous comment about x2 usage also applies here. | 1822 // The previous comment about x2 usage also applies here. |
| 1896 __ Mov(x2, receiver); | 1823 __ Mov(x2, receiver); |
| 1897 ElementsTransitionGenerator:: | 1824 ElementsTransitionGenerator:: |
| 1898 GenerateMapChangeElementsTransition(masm(), | 1825 GenerateMapChangeElementsTransition(masm(), |
| 1899 DONT_TRACK_ALLOCATION_SITE, | 1826 DONT_TRACK_ALLOCATION_SITE, |
| 1900 NULL); | 1827 NULL); |
| 1901 __ Bind(&fast_object); | 1828 __ Bind(&fast_object); |
| 1902 } else { | 1829 } else { |
| 1903 __ CheckFastObjectElements(map, x3, &call_builtin); | 1830 __ CheckFastObjectElements(map, x3, &call_builtin); |
| 1904 } | 1831 } |
| 1905 | 1832 |
| 1906 // Save new length. | 1833 // Save new length. |
| 1907 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1834 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1908 | 1835 |
| 1909 // Store the value. | 1836 // Store the value. |
| 1910 // We may need a register containing the address end_elements below, | 1837 // We may need a register containing the address end_elements below, |
| 1911 // so write back the value in end_elements. | 1838 // so write back the value in end_elements. |
| 1912 __ Add(end_elements, elements, | 1839 __ Add(end_elements, elements, |
| 1913 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); | 1840 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); |
| 1914 __ Str(x4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); | 1841 __ Str(value, MemOperand(end_elements, kEndElementsOffset, PreIndex)); |
| 1915 | 1842 |
| 1916 __ RecordWrite(elements, | 1843 __ RecordWrite(elements, |
| 1917 end_elements, | 1844 end_elements, |
| 1918 x4, | 1845 value, |
| 1919 kLRHasNotBeenSaved, | 1846 kLRHasNotBeenSaved, |
| 1920 kDontSaveFPRegs, | 1847 kDontSaveFPRegs, |
| 1921 EMIT_REMEMBERED_SET, | 1848 EMIT_REMEMBERED_SET, |
| 1922 OMIT_SMI_CHECK); | 1849 OMIT_SMI_CHECK); |
| 1923 __ Drop(argc + 1); | 1850 __ Drop(argc + 1); |
| 1851 __ Mov(x0, length); |
| 1924 __ Ret(); | 1852 __ Ret(); |
| 1925 | 1853 |
| 1926 | 1854 |
| 1927 __ Bind(&attempt_to_grow_elements); | 1855 __ Bind(&attempt_to_grow_elements); |
| 1928 // When we jump here, x4 must hold the length of elements. | |
| 1929 Register elements_length = x4; | |
| 1930 | 1856 |
| 1931 if (!FLAG_inline_new) { | 1857 if (!FLAG_inline_new) { |
| 1932 __ B(&call_builtin); | 1858 __ B(&call_builtin); |
| 1933 } | 1859 } |
| 1934 | 1860 |
| 1935 __ Peek(x2, (argc - 1) * kPointerSize); | 1861 Register argument = x2; |
| 1862 __ Peek(argument, (argc - 1) * kPointerSize); |
| 1936 // Growing elements that are SMI-only requires special handling in case | 1863 // Growing elements that are SMI-only requires special handling in case |
| 1937 // the new element is non-Smi. For now, delegate to the builtin. | 1864 // the new element is non-Smi. For now, delegate to the builtin. |
| 1938 Label no_fast_elements_check; | 1865 Label no_fast_elements_check; |
| 1939 __ JumpIfSmi(x2, &no_fast_elements_check); | 1866 __ JumpIfSmi(argument, &no_fast_elements_check); |
| 1940 __ Ldr(x7, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1867 __ Ldr(x10, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1941 __ CheckFastObjectElements(x7, x7, &call_builtin); | 1868 __ CheckFastObjectElements(x10, x10, &call_builtin); |
| 1942 __ Bind(&no_fast_elements_check); | 1869 __ Bind(&no_fast_elements_check); |
| 1943 | 1870 |
| 1944 ExternalReference new_space_allocation_top = | 1871 ExternalReference new_space_allocation_top = |
| 1945 ExternalReference::new_space_allocation_top_address(isolate()); | 1872 ExternalReference::new_space_allocation_top_address(isolate()); |
| 1946 ExternalReference new_space_allocation_limit = | 1873 ExternalReference new_space_allocation_limit = |
| 1947 ExternalReference::new_space_allocation_limit_address(isolate()); | 1874 ExternalReference::new_space_allocation_limit_address(isolate()); |
| 1948 | 1875 |
| 1949 const int kAllocationDelta = 4; | 1876 const int kAllocationDelta = 4; |
| 1877 Register allocation_top_addr = x5; |
| 1878 Register allocation_top = x9; |
| 1950 // Load top and check if it is the end of elements. | 1879 // Load top and check if it is the end of elements. |
| 1951 __ Add(end_elements, elements, | 1880 __ Add(end_elements, elements, |
| 1952 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); | 1881 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); |
| 1953 __ Add(end_elements, end_elements, kEndElementsOffset); | 1882 __ Add(end_elements, end_elements, kEndElementsOffset); |
| 1954 __ Mov(x7, Operand(new_space_allocation_top)); | 1883 __ Mov(allocation_top_addr, Operand(new_space_allocation_top)); |
| 1955 __ Ldr(x3, MemOperand(x7)); | 1884 __ Ldr(allocation_top, MemOperand(allocation_top_addr)); |
| 1956 __ Cmp(end_elements, x3); | 1885 __ Cmp(end_elements, allocation_top); |
| 1957 __ B(ne, &call_builtin); | 1886 __ B(ne, &call_builtin); |
| 1958 | 1887 |
| 1959 __ Mov(x10, Operand(new_space_allocation_limit)); | 1888 __ Mov(x10, Operand(new_space_allocation_limit)); |
| 1960 __ Ldr(x10, MemOperand(x10)); | 1889 __ Ldr(x10, MemOperand(x10)); |
| 1961 __ Add(x3, x3, kAllocationDelta * kPointerSize); | 1890 __ Add(allocation_top, allocation_top, kAllocationDelta * kPointerSize); |
| 1962 __ Cmp(x3, x10); | 1891 __ Cmp(allocation_top, x10); |
| 1963 __ B(hi, &call_builtin); | 1892 __ B(hi, &call_builtin); |
| 1964 | 1893 |
| 1965 // We fit and could grow elements. | 1894 // We fit and could grow elements. |
| 1966 // Update new_space_allocation_top. | 1895 // Update new_space_allocation_top. |
| 1967 __ Str(x3, MemOperand(x7)); | 1896 __ Str(allocation_top, MemOperand(allocation_top_addr)); |
| 1968 // Push the argument. | 1897 // Push the argument. |
| 1969 __ Str(x2, MemOperand(end_elements)); | 1898 __ Str(argument, MemOperand(end_elements)); |
| 1970 // Fill the rest with holes. | 1899 // Fill the rest with holes. |
| 1971 __ LoadRoot(x3, Heap::kTheHoleValueRootIndex); | 1900 __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); |
| 1972 for (int i = 1; i < kAllocationDelta; i++) { | 1901 for (int i = 1; i < kAllocationDelta; i++) { |
| 1973 __ Str(x3, MemOperand(end_elements, i * kPointerSize)); | 1902 // TODO(all): Try to use stp here. |
| 1903 __ Str(x10, MemOperand(end_elements, i * kPointerSize)); |
| 1974 } | 1904 } |
| 1975 | 1905 |
| 1976 // Update elements' and array's sizes. | 1906 // Update elements' and array's sizes. |
| 1977 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1907 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1978 __ Add(elements_length, | 1908 __ Add(elements_length, |
| 1979 elements_length, | 1909 elements_length, |
| 1980 Operand(Smi::FromInt(kAllocationDelta))); | 1910 Operand(Smi::FromInt(kAllocationDelta))); |
| 1981 __ Str(elements_length, | 1911 __ Str(elements_length, |
| 1982 FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1912 FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1983 | 1913 |
| 1984 // Elements are in new space, so write barrier is not required. | 1914 // Elements are in new space, so write barrier is not required. |
| 1985 __ Drop(argc + 1); | 1915 __ Drop(argc + 1); |
| 1916 __ Mov(x0, length); |
| 1986 __ Ret(); | 1917 __ Ret(); |
| 1987 } | 1918 } |
| 1988 __ Bind(&call_builtin); | 1919 __ Bind(&call_builtin); |
| 1989 __ TailCallExternalReference( | 1920 __ TailCallExternalReference( |
| 1990 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); | 1921 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); |
| 1991 } | 1922 } |
| 1992 | 1923 |
| 1993 // Handle call cache miss. | 1924 HandlerFrontendFooter(&miss); |
| 1994 __ Bind(&miss); | |
| 1995 GenerateMissBranch(); | |
| 1996 | 1925 |
| 1997 // Return the generated code. | 1926 // Return the generated code. |
| 1998 return GetCode(type, name); | 1927 return GetCode(type, name); |
| 1999 } | 1928 } |
| 2000 | 1929 |
| 2001 | 1930 |
| 2002 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1931 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 2003 Handle<Object> object, | 1932 Handle<Object> object, |
| 2004 Handle<JSObject> holder, | 1933 Handle<JSObject> holder, |
| 2005 Handle<Cell> cell, | 1934 Handle<Cell> cell, |
| 2006 Handle<JSFunction> function, | 1935 Handle<JSFunction> function, |
| 2007 Handle<String> name, | 1936 Handle<String> name, |
| 2008 Code::StubType type) { | 1937 Code::StubType type) { |
| 2009 // ----------- S t a t e ------------- | |
| 2010 // -- x2 : name | |
| 2011 // -- lr : return address | |
| 2012 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) | |
| 2013 // -- ... | |
| 2014 // -- sp[argc * 8] : receiver | |
| 2015 // ----------------------------------- | |
| 2016 | |
| 2017 // If object is not an array or is observed, bail out to regular call. | 1938 // If object is not an array or is observed, bail out to regular call. |
| 2018 if (!object->IsJSArray() || | 1939 if (!object->IsJSArray() || |
| 2019 !cell.is_null() || | 1940 !cell.is_null() || |
| 2020 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1941 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 2021 return Handle<Code>::null(); | 1942 return Handle<Code>::null(); |
| 2022 } | 1943 } |
| 2023 | 1944 |
| 2024 const int argc = arguments().immediate(); | 1945 const int argc = arguments().immediate(); |
| 2025 Register result = x0; | |
| 2026 Label miss, return_undefined, call_builtin; | 1946 Label miss, return_undefined, call_builtin; |
| 1947 Register receiver = x0; |
| 1948 Register result = x1; |
| 1949 Register elements = x3; |
| 1950 Register length = x4; |
| 2027 | 1951 |
| 2028 GenerateNameCheck(name, &miss); | 1952 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2029 | |
| 2030 // Get the receiver from the stack | |
| 2031 Register receiver = x1; | |
| 2032 __ Peek(receiver, argc * kPointerSize); | |
| 2033 // Check that the receiver isn't a smi. | |
| 2034 __ JumpIfSmi(receiver, &miss); | |
| 2035 | |
| 2036 // Check that the maps haven't changed. | |
| 2037 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), | |
| 2038 receiver, holder, x3, x4, x0, name, &miss); | |
| 2039 | 1953 |
| 2040 // Get the elements array of the object. | 1954 // Get the elements array of the object. |
| 2041 Register elements = x3; | |
| 2042 __ Ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1955 __ Ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 2043 | 1956 |
| 2044 // Check that the elements are in fast mode and writable. | 1957 // Check that the elements are in fast mode and writable. |
| 2045 __ CheckMap(elements, | 1958 __ CheckMap(elements, |
| 2046 x0, | 1959 x10, |
| 2047 Heap::kFixedArrayMapRootIndex, | 1960 Heap::kFixedArrayMapRootIndex, |
| 2048 &call_builtin, | 1961 &call_builtin, |
| 2049 DONT_DO_SMI_CHECK); | 1962 DONT_DO_SMI_CHECK); |
| 2050 | 1963 |
| 2051 // Get the array's length and calculate new length. | 1964 // Get the array's length and calculate new length. |
| 2052 Register length = x4; | |
| 2053 __ Ldr(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1965 __ Ldr(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 2054 __ Subs(length, length, Operand(Smi::FromInt(1))); | 1966 __ Subs(length, length, Operand(Smi::FromInt(1))); |
| 2055 __ B(lt, &return_undefined); | 1967 __ B(lt, &return_undefined); |
| 2056 | 1968 |
| 2057 // Get the last element. | 1969 // Get the last element. |
| 2058 __ Add(elements, elements, | 1970 __ Add(elements, elements, |
| 2059 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); | 1971 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); |
| 2060 __ Ldr(result, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 1972 __ Ldr(result, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
| 2061 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &call_builtin); | 1973 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &call_builtin); |
| 2062 | 1974 |
| 2063 // Set the array's length. | 1975 // Set the array's length. |
| 2064 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1976 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 2065 | 1977 |
| 2066 // Fill with the hole. | 1978 // Fill with the hole. |
| 2067 Register hole_value = x6; | 1979 __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); |
| 2068 __ LoadRoot(hole_value, Heap::kTheHoleValueRootIndex); | 1980 __ Str(x10, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
| 2069 __ Str(hole_value, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 1981 __ Drop(argc + 1); |
| 1982 __ Mov(x0, result); |
| 1983 __ Ret(); |
| 1984 |
| 1985 __ Bind(&return_undefined); |
| 1986 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
| 2070 __ Drop(argc + 1); | 1987 __ Drop(argc + 1); |
| 2071 __ Ret(); | 1988 __ Ret(); |
| 2072 | 1989 |
| 2073 __ Bind(&return_undefined); | |
| 2074 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | |
| 2075 __ Drop(argc + 1); | |
| 2076 __ Ret(); | |
| 2077 | |
| 2078 __ Bind(&call_builtin); | 1990 __ Bind(&call_builtin); |
| 2079 __ TailCallExternalReference( | 1991 __ TailCallExternalReference( |
| 2080 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); | 1992 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); |
| 2081 | 1993 |
| 2082 // Handle call cache miss. | 1994 HandlerFrontendFooter(&miss); |
| 2083 __ Bind(&miss); | |
| 2084 GenerateMissBranch(); | |
| 2085 | 1995 |
| 2086 // Return the generated code. | 1996 // Return the generated code. |
| 2087 return GetCode(type, name); | 1997 return GetCode(type, name); |
| 2088 } | 1998 } |
| 2089 | 1999 |
| 2090 | 2000 |
| 2091 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( | 2001 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
| 2092 Handle<Object> object, | 2002 Handle<Object> object, |
| 2093 Handle<JSObject> holder, | 2003 Handle<JSObject> holder, |
| 2094 Handle<Cell> cell, | 2004 Handle<Cell> cell, |
| 2095 Handle<JSFunction> function, | 2005 Handle<JSFunction> function, |
| 2096 Handle<String> name, | 2006 Handle<String> name, |
| 2097 Code::StubType type) { | 2007 Code::StubType type) { |
| 2098 // ----------- S t a t e ------------- | |
| 2099 // -- x2 : function name | |
| 2100 // -- lr : return address | |
| 2101 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) | |
| 2102 // -- ... | |
| 2103 // -- sp[argc * 8] : receiver | |
| 2104 // ----------------------------------- | |
| 2105 | |
| 2106 // If object is not a string, bail out to regular call. | 2008 // If object is not a string, bail out to regular call. |
| 2107 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 2009 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2108 | 2010 |
| 2109 const int argc = arguments().immediate(); | |
| 2110 Label miss; | 2011 Label miss; |
| 2111 Label name_miss; | 2012 Label name_miss; |
| 2112 Label index_out_of_range; | 2013 Label index_out_of_range; |
| 2113 Label* index_out_of_range_label = &index_out_of_range; | 2014 Label* index_out_of_range_label = &index_out_of_range; |
| 2114 | 2015 |
| 2115 if (kind_ == Code::CALL_IC && | 2016 if (kind_ == Code::CALL_IC && |
| 2116 (CallICBase::StringStubState::decode(extra_state_) == | 2017 (CallICBase::StringStubState::decode(extra_state_) == |
| 2117 DEFAULT_STRING_STUB)) { | 2018 DEFAULT_STRING_STUB)) { |
| 2118 index_out_of_range_label = &miss; | 2019 index_out_of_range_label = &miss; |
| 2119 } | 2020 } |
| 2120 GenerateNameCheck(name, &name_miss); | 2021 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2121 | 2022 |
| 2122 // Check that the maps starting from the prototype haven't changed. | 2023 Register receiver = x0; |
| 2123 Register prototype_reg = x0; | 2024 Register result = x1; |
| 2124 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2125 Context::STRING_FUNCTION_INDEX, | |
| 2126 prototype_reg, | |
| 2127 &miss); | |
| 2128 ASSERT(!object.is_identical_to(holder)); | |
| 2129 Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate()))); | |
| 2130 CheckPrototypes(IC::CurrentTypeOf(prototype, isolate()), | |
| 2131 prototype_reg, holder, x1, x3, x4, name, &miss); | |
| 2132 | |
| 2133 Register result = x0; | |
| 2134 Register receiver = x1; | |
| 2135 Register index = x4; | 2025 Register index = x4; |
| 2136 | 2026 |
| 2027 const int argc = arguments().immediate(); |
| 2137 __ Peek(receiver, argc * kPointerSize); | 2028 __ Peek(receiver, argc * kPointerSize); |
| 2138 if (argc > 0) { | 2029 if (argc > 0) { |
| 2139 __ Peek(index, (argc - 1) * kPointerSize); | 2030 __ Peek(index, (argc - 1) * kPointerSize); |
| 2140 } else { | 2031 } else { |
| 2141 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2032 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2142 } | 2033 } |
| 2143 | 2034 |
| 2144 StringCharCodeAtGenerator generator(receiver, | 2035 StringCharCodeAtGenerator generator(receiver, |
| 2145 index, | 2036 index, |
| 2146 result, | 2037 result, |
| 2147 &miss, // When not a string. | 2038 &miss, // When not a string. |
| 2148 &miss, // When not a number. | 2039 &miss, // When not a number. |
| 2149 index_out_of_range_label, | 2040 index_out_of_range_label, |
| 2150 STRING_INDEX_IS_NUMBER); | 2041 STRING_INDEX_IS_NUMBER); |
| 2151 generator.GenerateFast(masm()); | 2042 generator.GenerateFast(masm()); |
| 2152 __ Drop(argc + 1); | 2043 __ Drop(argc + 1); |
| 2044 __ Mov(x0, result); |
| 2153 __ Ret(); | 2045 __ Ret(); |
| 2154 | 2046 |
| 2155 StubRuntimeCallHelper call_helper; | 2047 StubRuntimeCallHelper call_helper; |
| 2156 generator.GenerateSlow(masm(), call_helper); | 2048 generator.GenerateSlow(masm(), call_helper); |
| 2157 | 2049 |
| 2158 if (index_out_of_range.is_linked()) { | 2050 if (index_out_of_range.is_linked()) { |
| 2159 __ Bind(&index_out_of_range); | 2051 __ Bind(&index_out_of_range); |
| 2160 __ LoadRoot(result, Heap::kNanValueRootIndex); | 2052 __ LoadRoot(result, Heap::kNanValueRootIndex); |
| 2161 __ Drop(argc + 1); | 2053 __ Drop(argc + 1); |
| 2162 __ Ret(); | 2054 __ Ret(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2173 } | 2065 } |
| 2174 | 2066 |
| 2175 | 2067 |
| 2176 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2068 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2177 Handle<Object> object, | 2069 Handle<Object> object, |
| 2178 Handle<JSObject> holder, | 2070 Handle<JSObject> holder, |
| 2179 Handle<Cell> cell, | 2071 Handle<Cell> cell, |
| 2180 Handle<JSFunction> function, | 2072 Handle<JSFunction> function, |
| 2181 Handle<String> name, | 2073 Handle<String> name, |
| 2182 Code::StubType type) { | 2074 Code::StubType type) { |
| 2183 // ----------- S t a t e ------------- | |
| 2184 // -- x2 : function name | |
| 2185 // -- lr : return address | |
| 2186 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) | |
| 2187 // -- ... | |
| 2188 // -- sp[argc * 8] : receiver | |
| 2189 // ----------------------------------- | |
| 2190 | |
| 2191 // If object is not a string, bail out to regular call. | 2075 // If object is not a string, bail out to regular call. |
| 2192 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 2076 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2193 | 2077 |
| 2194 const int argc = arguments().immediate(); | 2078 const int argc = arguments().immediate(); |
| 2195 Label miss; | 2079 Label miss; |
| 2196 Label name_miss; | 2080 Label name_miss; |
| 2197 Label index_out_of_range; | 2081 Label index_out_of_range; |
| 2198 Label* index_out_of_range_label = &index_out_of_range; | 2082 Label* index_out_of_range_label = &index_out_of_range; |
| 2199 | 2083 |
| 2200 if (kind_ == Code::CALL_IC && | 2084 if (kind_ == Code::CALL_IC && |
| 2201 (CallICBase::StringStubState::decode(extra_state_) == | 2085 (CallICBase::StringStubState::decode(extra_state_) == |
| 2202 DEFAULT_STRING_STUB)) { | 2086 DEFAULT_STRING_STUB)) { |
| 2203 index_out_of_range_label = &miss; | 2087 index_out_of_range_label = &miss; |
| 2204 } | 2088 } |
| 2205 GenerateNameCheck(name, &name_miss); | |
| 2206 | 2089 |
| 2207 // Check that the maps starting from the prototype haven't changed. | 2090 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2208 Register prototype_reg = x0; | |
| 2209 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2210 Context::STRING_FUNCTION_INDEX, | |
| 2211 prototype_reg, | |
| 2212 &miss); | |
| 2213 ASSERT(!object.is_identical_to(holder)); | |
| 2214 Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate()))); | |
| 2215 CheckPrototypes(IC::CurrentTypeOf(prototype, isolate()), | |
| 2216 prototype_reg, holder, x1, x3, x4, name, &miss); | |
| 2217 | 2091 |
| 2218 Register receiver = x0; | 2092 Register receiver = x0; |
| 2219 Register index = x4; | 2093 Register index = x4; |
| 2220 Register scratch = x3; | 2094 Register scratch = x3; |
| 2221 Register result = x0; | 2095 Register result = x1; |
| 2222 | 2096 |
| 2223 __ Peek(receiver, argc * kPointerSize); | |
| 2224 if (argc > 0) { | 2097 if (argc > 0) { |
| 2225 __ Peek(index, (argc - 1) * kPointerSize); | 2098 __ Peek(index, (argc - 1) * kPointerSize); |
| 2226 } else { | 2099 } else { |
| 2227 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2100 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2228 } | 2101 } |
| 2229 | 2102 |
| 2230 StringCharAtGenerator generator(receiver, | 2103 StringCharAtGenerator generator(receiver, |
| 2231 index, | 2104 index, |
| 2232 scratch, | 2105 scratch, |
| 2233 result, | 2106 result, |
| 2234 &miss, // When not a string. | 2107 &miss, // When not a string. |
| 2235 &miss, // When not a number. | 2108 &miss, // When not a number. |
| 2236 index_out_of_range_label, | 2109 index_out_of_range_label, |
| 2237 STRING_INDEX_IS_NUMBER); | 2110 STRING_INDEX_IS_NUMBER); |
| 2238 generator.GenerateFast(masm()); | 2111 generator.GenerateFast(masm()); |
| 2239 __ Drop(argc + 1); | 2112 __ Drop(argc + 1); |
| 2113 __ Mov(x0, result); |
| 2240 __ Ret(); | 2114 __ Ret(); |
| 2241 | 2115 |
| 2242 StubRuntimeCallHelper call_helper; | 2116 StubRuntimeCallHelper call_helper; |
| 2243 generator.GenerateSlow(masm(), call_helper); | 2117 generator.GenerateSlow(masm(), call_helper); |
| 2244 | 2118 |
| 2245 if (index_out_of_range.is_linked()) { | 2119 if (index_out_of_range.is_linked()) { |
| 2246 __ Bind(&index_out_of_range); | 2120 __ Bind(&index_out_of_range); |
| 2247 __ LoadRoot(result, Heap::kempty_stringRootIndex); | 2121 __ LoadRoot(result, Heap::kempty_stringRootIndex); |
| 2248 __ Drop(argc + 1); | 2122 __ Drop(argc + 1); |
| 2249 __ Ret(); | 2123 __ Ret(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2260 } | 2134 } |
| 2261 | 2135 |
| 2262 | 2136 |
| 2263 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2137 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2264 Handle<Object> object, | 2138 Handle<Object> object, |
| 2265 Handle<JSObject> holder, | 2139 Handle<JSObject> holder, |
| 2266 Handle<Cell> cell, | 2140 Handle<Cell> cell, |
| 2267 Handle<JSFunction> function, | 2141 Handle<JSFunction> function, |
| 2268 Handle<String> name, | 2142 Handle<String> name, |
| 2269 Code::StubType type) { | 2143 Code::StubType type) { |
| 2270 // ----------- S t a t e ------------- | |
| 2271 // -- x2 : function name | |
| 2272 // -- lr : return address | |
| 2273 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) | |
| 2274 // -- ... | |
| 2275 // -- sp[argc * 8] : receiver | |
| 2276 // ----------------------------------- | |
| 2277 const int argc = arguments().immediate(); | 2144 const int argc = arguments().immediate(); |
| 2278 | 2145 |
| 2279 // If the object is not a JSObject or we got an unexpected number of | 2146 // If the object is not a JSObject or we got an unexpected number of |
| 2280 // arguments, bail out to the regular call. | 2147 // arguments, bail out to the regular call. |
| 2281 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2148 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2282 | 2149 |
| 2283 Label miss; | 2150 Label miss; |
| 2284 GenerateNameCheck(name, &miss); | |
| 2285 | 2151 |
| 2286 if (cell.is_null()) { | 2152 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2287 Register receiver = x1; | 2153 if (!cell.is_null()) { |
| 2288 __ Peek(receiver, kPointerSize); | |
| 2289 __ JumpIfSmi(receiver, &miss); | |
| 2290 | |
| 2291 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), | |
| 2292 receiver, holder, x0, x3, x4, name, &miss); | |
| 2293 } else { | |
| 2294 ASSERT(cell->value() == *function); | 2154 ASSERT(cell->value() == *function); |
| 2295 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2296 &miss); | |
| 2297 GenerateLoadFunctionFromCell(cell, function, &miss); | 2155 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2298 } | 2156 } |
| 2299 | 2157 |
| 2300 // Load the char code argument. | 2158 // Load the char code argument. |
| 2301 Register code = x1; | 2159 Register code = x1; |
| 2302 __ Peek(code, 0); | 2160 __ Peek(code, 0); |
| 2303 | 2161 |
| 2304 // Check the code is a smi. | 2162 // Check the code is a smi. |
| 2305 Label slow; | 2163 Label slow; |
| 2306 __ JumpIfNotSmi(code, &slow); | 2164 __ JumpIfNotSmi(code, &slow); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2317 StubRuntimeCallHelper call_helper; | 2175 StubRuntimeCallHelper call_helper; |
| 2318 generator.GenerateSlow(masm(), call_helper); | 2176 generator.GenerateSlow(masm(), call_helper); |
| 2319 | 2177 |
| 2320 // Tail call the full function. We do not have to patch the receiver | 2178 // Tail call the full function. We do not have to patch the receiver |
| 2321 // because the function makes no use of it. | 2179 // because the function makes no use of it. |
| 2322 __ Bind(&slow); | 2180 __ Bind(&slow); |
| 2323 ParameterCount expected(function); | 2181 ParameterCount expected(function); |
| 2324 __ InvokeFunction(function, expected, arguments(), | 2182 __ InvokeFunction(function, expected, arguments(), |
| 2325 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2183 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 2326 | 2184 |
| 2327 __ Bind(&miss); | 2185 HandlerFrontendFooter(&miss); |
| 2328 GenerateMissBranch(); | |
| 2329 | 2186 |
| 2330 // Return the generated code. | 2187 // Return the generated code. |
| 2331 return GetCode(type, name); | 2188 return GetCode(type, name); |
| 2332 } | 2189 } |
| 2333 | 2190 |
| 2334 | 2191 |
| 2335 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2192 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2336 Handle<Object> object, | 2193 Handle<Object> object, |
| 2337 Handle<JSObject> holder, | 2194 Handle<JSObject> holder, |
| 2338 Handle<Cell> cell, | 2195 Handle<Cell> cell, |
| 2339 Handle<JSFunction> function, | 2196 Handle<JSFunction> function, |
| 2340 Handle<String> name, | 2197 Handle<String> name, |
| 2341 Code::StubType type) { | 2198 Code::StubType type) { |
| 2342 // ----------- S t a t e ------------- | |
| 2343 // -- x2 : function name (must be preserved on miss) | |
| 2344 // -- lr : return address | |
| 2345 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) | |
| 2346 // -- ... | |
| 2347 // -- sp[argc * 8] : receiver | |
| 2348 // ----------------------------------- | |
| 2349 Label miss; | 2199 Label miss; |
| 2350 Label return_result; | 2200 Label return_result; |
| 2351 Register result = x0; | 2201 Register result = x0; |
| 2352 const int argc = arguments().immediate(); | 2202 const int argc = arguments().immediate(); |
| 2353 | 2203 |
| 2354 // If the object is not a JSObject or we got an unexpected number of | 2204 // If the object is not a JSObject or we got an unexpected number of |
| 2355 // arguments, bail out to the regular call. | 2205 // arguments, bail out to the regular call. |
| 2356 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2206 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2357 | 2207 |
| 2358 GenerateNameCheck(name, &miss); | 2208 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2359 | 2209 if (!cell.is_null()) { |
| 2360 if (cell.is_null()) { | |
| 2361 Register receiver = x1; | |
| 2362 __ Peek(receiver, kPointerSize); | |
| 2363 __ JumpIfSmi(receiver, &miss); | |
| 2364 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), | |
| 2365 receiver, holder, x0, x3, x4, name, &miss); | |
| 2366 } else { | |
| 2367 ASSERT(cell->value() == *function); | 2210 ASSERT(cell->value() == *function); |
| 2368 GenerateGlobalReceiverCheck( | |
| 2369 Handle<JSObject>::cast(object), holder, name, &miss); | |
| 2370 GenerateLoadFunctionFromCell(cell, function, &miss); | 2211 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2371 } | 2212 } |
| 2372 | 2213 |
| 2373 // Load the (only) argument. | 2214 // Load the (only) argument. |
| 2374 Register arg = x0; | 2215 Register arg = x0; |
| 2375 __ Peek(arg, 0); | 2216 __ Peek(arg, 0); |
| 2376 | 2217 |
| 2377 // If the argument is a smi, just return. | 2218 // If the argument is a smi, just return. |
| 2378 __ JumpIfSmi(arg, &return_result); | 2219 __ JumpIfSmi(arg, &return_result); |
| 2379 | 2220 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2433 __ Drop(argc + 1); | 2274 __ Drop(argc + 1); |
| 2434 __ Ret(); | 2275 __ Ret(); |
| 2435 | 2276 |
| 2436 __ Bind(&slow); | 2277 __ Bind(&slow); |
| 2437 // Tail call the full function. We do not have to patch the receiver | 2278 // Tail call the full function. We do not have to patch the receiver |
| 2438 // because the function makes no use of it. | 2279 // because the function makes no use of it. |
| 2439 ParameterCount expected(function); | 2280 ParameterCount expected(function); |
| 2440 __ InvokeFunction(function, expected, arguments(), | 2281 __ InvokeFunction(function, expected, arguments(), |
| 2441 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2282 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 2442 | 2283 |
| 2443 __ Bind(&miss); | 2284 HandlerFrontendFooter(&miss); |
| 2444 GenerateMissBranch(); | |
| 2445 | 2285 |
| 2446 // Return the generated code. | 2286 // Return the generated code. |
| 2447 return GetCode(type, name); | 2287 return GetCode(type, name); |
| 2448 } | 2288 } |
| 2449 | 2289 |
| 2450 | 2290 |
| 2451 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2291 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2452 Handle<Object> object, | 2292 Handle<Object> object, |
| 2453 Handle<JSObject> holder, | 2293 Handle<JSObject> holder, |
| 2454 Handle<Cell> cell, | 2294 Handle<Cell> cell, |
| 2455 Handle<JSFunction> function, | 2295 Handle<JSFunction> function, |
| 2456 Handle<String> name, | 2296 Handle<String> name, |
| 2457 Code::StubType type) { | 2297 Code::StubType type) { |
| 2458 // ----------- S t a t e ------------- | |
| 2459 // -- x2 : function name | |
| 2460 // -- lr : return address | |
| 2461 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) | |
| 2462 // -- ... | |
| 2463 // -- sp[argc * 8] : receiver | |
| 2464 // ----------------------------------- | |
| 2465 | |
| 2466 const int argc = arguments().immediate(); | 2298 const int argc = arguments().immediate(); |
| 2467 | 2299 |
| 2468 // If the object is not a JSObject or we got an unexpected number of | 2300 // If the object is not a JSObject or we got an unexpected number of |
| 2469 // arguments, bail out to the regular call. | 2301 // arguments, bail out to the regular call. |
| 2470 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2302 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2471 | 2303 |
| 2472 Register result = x0; | 2304 Register result = x0; |
| 2473 Label miss, slow; | 2305 Label miss, slow; |
| 2474 GenerateNameCheck(name, &miss); | 2306 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2475 | 2307 if (!cell.is_null()) { |
| 2476 if (cell.is_null()) { | |
| 2477 Register receiver = x1; | |
| 2478 __ Peek(receiver, kPointerSize); | |
| 2479 __ JumpIfSmi(receiver, &miss); | |
| 2480 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), | |
| 2481 receiver, holder, x0, x3, x4, name, &miss); | |
| 2482 } else { | |
| 2483 ASSERT(cell->value() == *function); | 2308 ASSERT(cell->value() == *function); |
| 2484 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2485 &miss); | |
| 2486 GenerateLoadFunctionFromCell(cell, function, &miss); | 2309 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2487 } | 2310 } |
| 2488 | 2311 |
| 2489 // Load the (only) argument. | 2312 // Load the (only) argument. |
| 2490 Register arg = x0; | 2313 Register arg = x0; |
| 2491 __ Peek(arg, 0); | 2314 __ Peek(arg, 0); |
| 2492 | 2315 |
| 2493 // Check if the argument is a smi. | 2316 // Check if the argument is a smi. |
| 2494 Label not_smi; | 2317 Label not_smi; |
| 2495 __ JumpIfNotSmi(arg, ¬_smi); | 2318 __ JumpIfNotSmi(arg, ¬_smi); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2520 __ Drop(argc + 1); | 2343 __ Drop(argc + 1); |
| 2521 __ Ret(); | 2344 __ Ret(); |
| 2522 | 2345 |
| 2523 // Tail call the full function. We do not have to patch the receiver | 2346 // Tail call the full function. We do not have to patch the receiver |
| 2524 // because the function makes no use of it. | 2347 // because the function makes no use of it. |
| 2525 __ Bind(&slow); | 2348 __ Bind(&slow); |
| 2526 ParameterCount expected(function); | 2349 ParameterCount expected(function); |
| 2527 __ InvokeFunction(function, expected, arguments(), | 2350 __ InvokeFunction(function, expected, arguments(), |
| 2528 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2351 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 2529 | 2352 |
| 2530 __ Bind(&miss); | 2353 HandlerFrontendFooter(&miss); |
| 2531 GenerateMissBranch(); | |
| 2532 | 2354 |
| 2533 // Return the generated code. | 2355 // Return the generated code. |
| 2534 return GetCode(type, name); | 2356 return GetCode(type, name); |
| 2535 } | 2357 } |
| 2536 | 2358 |
| 2537 | 2359 |
| 2538 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2360 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2539 const CallOptimization& optimization, | 2361 const CallOptimization& optimization, |
| 2540 Handle<Object> object, | 2362 Handle<Object> object, |
| 2541 Handle<JSObject> holder, | 2363 Handle<JSObject> holder, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2591 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2413 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2592 Label success; | 2414 Label success; |
| 2593 // Check that the object is a boolean. | 2415 // Check that the object is a boolean. |
| 2594 // TODO(all): Optimize this like LCodeGen::DoDeferredTaggedToI. | 2416 // TODO(all): Optimize this like LCodeGen::DoDeferredTaggedToI. |
| 2595 __ JumpIfRoot(object, Heap::kTrueValueRootIndex, &success); | 2417 __ JumpIfRoot(object, Heap::kTrueValueRootIndex, &success); |
| 2596 __ JumpIfNotRoot(object, Heap::kFalseValueRootIndex, miss); | 2418 __ JumpIfNotRoot(object, Heap::kFalseValueRootIndex, miss); |
| 2597 __ Bind(&success); | 2419 __ Bind(&success); |
| 2598 } | 2420 } |
| 2599 | 2421 |
| 2600 | 2422 |
| 2601 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2423 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
| 2602 Handle<JSObject> holder, | 2424 // TODO(all): What is x0 here? Is the use of x3 significant? |
| 2603 Handle<Name> name, | 2425 if (object->IsGlobalObject()) { |
| 2604 CheckType check) { | 2426 const int argc = arguments().immediate(); |
| 2427 const int receiver_offset = argc * kPointerSize; |
| 2428 __ Ldr(x3, FieldMemOperand(x0, GlobalObject::kGlobalReceiverOffset)); |
| 2429 __ Poke(x3, receiver_offset); |
| 2430 } |
| 2431 } |
| 2432 |
| 2433 |
| 2434 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
| 2435 Handle<JSObject> holder, |
| 2436 Handle<Name> name, |
| 2437 CheckType check, |
| 2438 Label* miss) { |
| 2605 // ----------- S t a t e ------------- | 2439 // ----------- S t a t e ------------- |
| 2606 // -- x2 : name | 2440 // -- x2 : name |
| 2607 // -- lr : return address | 2441 // -- lr : return address |
| 2608 // ----------------------------------- | 2442 // ----------------------------------- |
| 2609 Label miss; | 2443 GenerateNameCheck(name, miss); |
| 2610 GenerateNameCheck(name, &miss); | 2444 |
| 2445 Register receiver = x0; |
| 2446 Register prototype_reg = x1; |
| 2611 | 2447 |
| 2612 // Get the receiver from the stack. | 2448 // Get the receiver from the stack. |
| 2613 const int argc = arguments().immediate(); | 2449 const int argc = arguments().immediate(); |
| 2614 Register receiver = x1; | 2450 const int receiver_offset = argc * kPointerSize; |
| 2615 __ Peek(receiver, argc * kPointerSize); | 2451 __ Peek(receiver, receiver_offset); |
| 2616 | 2452 |
| 2617 // Check that the receiver isn't a smi. | 2453 // Check that the receiver isn't a smi. |
| 2618 if (check != NUMBER_CHECK) { | 2454 if (check != NUMBER_CHECK) { |
| 2619 __ JumpIfSmi(receiver, &miss); | 2455 __ JumpIfSmi(receiver, miss); |
| 2620 } | 2456 } |
| 2621 | 2457 |
| 2622 // Make sure that it's okay not to patch the on stack receiver | 2458 // Make sure that it's okay not to patch the on stack receiver |
| 2623 // unless we're doing a receiver map check. | 2459 // unless we're doing a receiver map check. |
| 2624 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2460 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2625 | 2461 |
| 2626 switch (check) { | 2462 switch (check) { |
| 2627 case RECEIVER_MAP_CHECK: { | 2463 case RECEIVER_MAP_CHECK: { |
| 2628 __ IncrementCounter(isolate()->counters()->call_const(), 1, x0, x3); | 2464 __ IncrementCounter(isolate()->counters()->call_const(), 1, x1, x3); |
| 2629 | 2465 |
| 2630 // Check that the maps haven't changed. | 2466 // Check that the maps haven't changed. |
| 2631 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), | 2467 receiver = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), |
| 2632 receiver, holder, x0, x3, x4, name, &miss); | 2468 receiver, holder, x1, x3, x4, name, miss); |
| 2633 | |
| 2634 // Patch the receiver on the stack with the global proxy if necessary. | |
| 2635 if (object->IsGlobalObject()) { | |
| 2636 __ Ldr(x3, | |
| 2637 FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); | |
| 2638 __ Poke(x3, argc * kPointerSize); | |
| 2639 } | |
| 2640 break; | 2469 break; |
| 2641 } | 2470 } |
| 2642 case STRING_CHECK: { | 2471 case STRING_CHECK: { |
| 2643 // Check that the object is a string. | 2472 // Check that the object is a string. |
| 2644 __ JumpIfObjectType(receiver, x3, x3, FIRST_NONSTRING_TYPE, &miss, ge); | 2473 __ JumpIfObjectType(receiver, x3, x3, FIRST_NONSTRING_TYPE, miss, ge); |
| 2645 // Check that the maps starting from the prototype haven't changed. | 2474 // Check that the maps starting from the prototype_reg haven't changed. |
| 2646 Register prototype_reg = x0; | |
| 2647 GenerateDirectLoadGlobalFunctionPrototype( | 2475 GenerateDirectLoadGlobalFunctionPrototype( |
| 2648 masm(), Context::STRING_FUNCTION_INDEX, prototype_reg, &miss); | 2476 masm(), Context::STRING_FUNCTION_INDEX, prototype_reg, miss); |
| 2649 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2650 CheckPrototypes( | |
| 2651 IC::CurrentTypeOf(prototype, isolate()), | |
| 2652 prototype_reg, holder, x3, x1, x4, name, &miss); | |
| 2653 break; | 2477 break; |
| 2654 } | 2478 } |
| 2655 case SYMBOL_CHECK: { | 2479 case SYMBOL_CHECK: { |
| 2656 // Check that the object is a symbol. | 2480 // Check that the object is a symbol. |
| 2657 __ JumpIfNotObjectType(receiver, x3, x3, SYMBOL_TYPE, &miss); | 2481 __ JumpIfNotObjectType(receiver, x3, x3, SYMBOL_TYPE, miss); |
| 2658 // Check that the maps starting from the prototype haven't changed. | 2482 // Check that the maps starting from the prototype_reg haven't changed. |
| 2659 Register prototype_reg = x0; | |
| 2660 GenerateDirectLoadGlobalFunctionPrototype( | 2483 GenerateDirectLoadGlobalFunctionPrototype( |
| 2661 masm(), Context::SYMBOL_FUNCTION_INDEX, prototype_reg, &miss); | 2484 masm(), Context::SYMBOL_FUNCTION_INDEX, prototype_reg, miss); |
| 2662 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2663 CheckPrototypes( | |
| 2664 IC::CurrentTypeOf(prototype, isolate()), | |
| 2665 prototype_reg, holder, x3, x1, x4, name, &miss); | |
| 2666 break; | 2485 break; |
| 2667 } | 2486 } |
| 2668 case NUMBER_CHECK: { | 2487 case NUMBER_CHECK: { |
| 2669 Label fast; | 2488 Label fast; |
| 2670 // Check that the object is a smi or a heap number. | 2489 // Check that the object is a smi or a heap number. |
| 2671 __ JumpIfSmi(receiver, &fast); | 2490 __ JumpIfSmi(receiver, &fast); |
| 2672 __ JumpIfNotObjectType(receiver, x0, x0, HEAP_NUMBER_TYPE, &miss); | 2491 __ JumpIfNotObjectType(receiver, x3, x3, HEAP_NUMBER_TYPE, miss); |
| 2673 | 2492 |
| 2674 __ Bind(&fast); | 2493 __ Bind(&fast); |
| 2675 // Check that the maps starting from the prototype haven't changed. | 2494 // Check that the maps starting from the prototype_reg haven't changed. |
| 2676 Register prototype_reg = x0; | |
| 2677 GenerateDirectLoadGlobalFunctionPrototype( | 2495 GenerateDirectLoadGlobalFunctionPrototype( |
| 2678 masm(), Context::NUMBER_FUNCTION_INDEX, prototype_reg, &miss); | 2496 masm(), Context::NUMBER_FUNCTION_INDEX, prototype_reg, miss); |
| 2679 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2680 CheckPrototypes( | |
| 2681 IC::CurrentTypeOf(prototype, isolate()), | |
| 2682 prototype_reg, holder, x3, x1, x4, name, &miss); | |
| 2683 break; | 2497 break; |
| 2684 } | 2498 } |
| 2685 case BOOLEAN_CHECK: { | 2499 case BOOLEAN_CHECK: { |
| 2686 GenerateBooleanCheck(receiver, &miss); | 2500 GenerateBooleanCheck(receiver, miss); |
| 2687 | 2501 |
| 2688 // Check that the maps starting from the prototype haven't changed. | 2502 // Check that the maps starting from the prototype_reg haven't changed. |
| 2689 Register prototype_reg = x0; | |
| 2690 GenerateDirectLoadGlobalFunctionPrototype( | 2503 GenerateDirectLoadGlobalFunctionPrototype( |
| 2691 masm(), Context::BOOLEAN_FUNCTION_INDEX, prototype_reg, &miss); | 2504 masm(), Context::BOOLEAN_FUNCTION_INDEX, prototype_reg, miss); |
| 2692 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2693 CheckPrototypes( | |
| 2694 IC::CurrentTypeOf(prototype, isolate()), | |
| 2695 prototype_reg, holder, x3, x1, x4, name, &miss); | |
| 2696 break; | 2505 break; |
| 2697 } | 2506 } |
| 2698 } | 2507 } |
| 2699 | 2508 |
| 2700 Label success; | 2509 if (check != RECEIVER_MAP_CHECK) { |
| 2701 __ B(&success); | 2510 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2511 receiver = CheckPrototypes( |
| 2512 IC::CurrentTypeOf(prototype, isolate()), |
| 2513 prototype_reg, holder, x1, x3, x4, name, miss); |
| 2514 } |
| 2702 | 2515 |
| 2703 // Handle call cache miss. | 2516 return receiver; |
| 2704 __ Bind(&miss); | |
| 2705 GenerateMissBranch(); | |
| 2706 | |
| 2707 __ Bind(&success); | |
| 2708 } | 2517 } |
| 2709 | 2518 |
| 2710 | 2519 |
| 2711 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2520 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
| 2712 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2521 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2713 ? CALL_AS_FUNCTION | 2522 ? CALL_AS_FUNCTION |
| 2714 : CALL_AS_METHOD; | 2523 : CALL_AS_METHOD; |
| 2715 ParameterCount expected(function); | 2524 ParameterCount expected(function); |
| 2716 __ InvokeFunction(function, expected, arguments(), | 2525 __ InvokeFunction(function, expected, arguments(), |
| 2717 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2526 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 2718 } | 2527 } |
| 2719 | 2528 |
| 2720 | 2529 |
| 2721 Handle<Code> CallStubCompiler::CompileCallConstant( | 2530 Handle<Code> CallStubCompiler::CompileCallConstant( |
| 2722 Handle<Object> object, | 2531 Handle<Object> object, |
| 2723 Handle<JSObject> holder, | 2532 Handle<JSObject> holder, |
| 2724 Handle<Name> name, | 2533 Handle<Name> name, |
| 2725 CheckType check, | 2534 CheckType check, |
| 2726 Handle<JSFunction> function) { | 2535 Handle<JSFunction> function) { |
| 2727 if (HasCustomCallGenerator(function)) { | 2536 if (HasCustomCallGenerator(function)) { |
| 2728 Handle<Code> code = CompileCustomCall(object, holder, | 2537 Handle<Code> code = CompileCustomCall(object, holder, |
| 2729 Handle<Cell>::null(), | 2538 Handle<Cell>::null(), |
| 2730 function, Handle<String>::cast(name), | 2539 function, Handle<String>::cast(name), |
| 2731 Code::FAST); | 2540 Code::FAST); |
| 2732 // A null handle means bail out to the regular compiler code below. | 2541 // A null handle means bail out to the regular compiler code below. |
| 2733 if (!code.is_null()) return code; | 2542 if (!code.is_null()) return code; |
| 2734 } | 2543 } |
| 2735 | 2544 |
| 2736 CompileHandlerFrontend(object, holder, name, check); | 2545 Label miss; |
| 2546 HandlerFrontendHeader(object, holder, name, check, &miss); |
| 2547 PatchGlobalProxy(object); |
| 2737 CompileHandlerBackend(function); | 2548 CompileHandlerBackend(function); |
| 2549 HandlerFrontendFooter(&miss); |
| 2738 | 2550 |
| 2739 // Return the generated code. | 2551 // Return the generated code. |
| 2740 return GetCode(function); | 2552 return GetCode(function); |
| 2741 } | 2553 } |
| 2742 | 2554 |
| 2743 | 2555 |
| 2744 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2556 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2745 Handle<JSObject> holder, | 2557 Handle<JSObject> holder, |
| 2746 Handle<Name> name) { | 2558 Handle<Name> name) { |
| 2747 // ----------- S t a t e ------------- | |
| 2748 // -- x2 : name | |
| 2749 // -- lr : return address | |
| 2750 // ----------------------------------- | |
| 2751 Label miss; | 2559 Label miss; |
| 2752 Register name_reg = x2; | 2560 Register name_reg = x2; |
| 2753 | 2561 |
| 2754 GenerateNameCheck(name, &miss); | 2562 GenerateNameCheck(name, &miss); |
| 2755 | 2563 |
| 2756 const int argc = arguments().immediate(); | 2564 const int argc = arguments().immediate(); |
| 2757 LookupResult lookup(isolate()); | 2565 LookupResult lookup(isolate()); |
| 2758 LookupPostInterceptor(holder, name, &lookup); | 2566 LookupPostInterceptor(holder, name, &lookup); |
| 2759 | 2567 |
| 2760 // Get the receiver from the stack. | 2568 // Get the receiver from the stack. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2784 return GetCode(Code::FAST, name); | 2592 return GetCode(Code::FAST, name); |
| 2785 } | 2593 } |
| 2786 | 2594 |
| 2787 | 2595 |
| 2788 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2596 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2789 Handle<JSObject> object, | 2597 Handle<JSObject> object, |
| 2790 Handle<GlobalObject> holder, | 2598 Handle<GlobalObject> holder, |
| 2791 Handle<PropertyCell> cell, | 2599 Handle<PropertyCell> cell, |
| 2792 Handle<JSFunction> function, | 2600 Handle<JSFunction> function, |
| 2793 Handle<Name> name) { | 2601 Handle<Name> name) { |
| 2794 // ----------- S t a t e ------------- | |
| 2795 // -- x2 : name | |
| 2796 // -- lr : return address | |
| 2797 // ----------------------------------- | |
| 2798 if (HasCustomCallGenerator(function)) { | 2602 if (HasCustomCallGenerator(function)) { |
| 2799 Handle<Code> code = CompileCustomCall( | 2603 Handle<Code> code = CompileCustomCall( |
| 2800 object, holder, cell, function, Handle<String>::cast(name), | 2604 object, holder, cell, function, Handle<String>::cast(name), |
| 2801 Code::NORMAL); | 2605 Code::NORMAL); |
| 2802 // A null handle means bail out to the regular compiler code below. | 2606 // A null handle means bail out to the regular compiler code below. |
| 2803 if (!code.is_null()) return code; | 2607 if (!code.is_null()) return code; |
| 2804 } | 2608 } |
| 2805 | 2609 |
| 2806 Label miss; | 2610 Label miss; |
| 2807 GenerateNameCheck(name, &miss); | 2611 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2808 | |
| 2809 // Get the number of arguments. | |
| 2810 const int argc = arguments().immediate(); | |
| 2811 | |
| 2812 GenerateGlobalReceiverCheck(object, holder, name, &miss); | |
| 2813 GenerateLoadFunctionFromCell(cell, function, &miss); | 2612 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2814 // After these two calls the receiver is left in x0 and the function in x1. | 2613 // After these two calls the receiver is left in x0 and the function in x1. |
| 2815 Register receiver_reg = x0; | |
| 2816 Register function_reg = x1; | 2614 Register function_reg = x1; |
| 2817 | 2615 |
| 2818 // Patch the receiver on the stack with the global proxy if necessary. | 2616 PatchGlobalProxy(object); |
| 2819 if (object->IsGlobalObject()) { | |
| 2820 __ Ldr(x3, | |
| 2821 FieldMemOperand(receiver_reg, GlobalObject::kGlobalReceiverOffset)); | |
| 2822 __ Poke(x3, argc * kPointerSize); | |
| 2823 } | |
| 2824 | 2617 |
| 2825 // Set up the context. | 2618 // Set up the context. |
| 2826 __ Ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); | 2619 __ Ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); |
| 2827 | 2620 |
| 2828 // Jump to the cached code (tail call). | 2621 // Jump to the cached code (tail call). |
| 2829 Counters* counters = isolate()->counters(); | 2622 Counters* counters = isolate()->counters(); |
| 2830 __ IncrementCounter(counters->call_global_inline(), 1, x3, x4); | 2623 __ IncrementCounter(counters->call_global_inline(), 1, x3, x4); |
| 2831 ParameterCount expected(function->shared()->formal_parameter_count()); | 2624 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2832 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2625 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2833 ? CALL_AS_FUNCTION | 2626 ? CALL_AS_FUNCTION |
| 2834 : CALL_AS_METHOD; | 2627 : CALL_AS_METHOD; |
| 2835 // We call indirectly through the code field in the function to | 2628 // We call indirectly through the code field in the function to |
| 2836 // allow recompilation to take effect without changing any of the | 2629 // allow recompilation to take effect without changing any of the |
| 2837 // call sites. | 2630 // call sites. |
| 2838 __ Ldr(x3, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); | 2631 __ Ldr(x3, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); |
| 2839 __ InvokeCode( | 2632 __ InvokeCode( |
| 2840 x3, expected, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2633 x3, expected, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 2841 | 2634 |
| 2842 // Handle call cache miss. | 2635 HandlerFrontendFooter(&miss); |
| 2843 __ Bind(&miss); | |
| 2844 __ IncrementCounter(counters->call_global_inline_miss(), 1, x1, x3); | |
| 2845 GenerateMissBranch(); | |
| 2846 | 2636 |
| 2847 // Return the generated code. | 2637 // Return the generated code. |
| 2848 return GetCode(Code::NORMAL, name); | 2638 return GetCode(Code::NORMAL, name); |
| 2849 } | 2639 } |
| 2850 | 2640 |
| 2851 | 2641 |
| 2852 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2642 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2853 Handle<JSObject> object, | 2643 Handle<JSObject> object, |
| 2854 Handle<JSObject> holder, | 2644 Handle<JSObject> holder, |
| 2855 Handle<Name> name, | 2645 Handle<Name> name, |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2937 DO_SMI_CHECK); | 2727 DO_SMI_CHECK); |
| 2938 | 2728 |
| 2939 // Perform global security token check if needed. | 2729 // Perform global security token check if needed. |
| 2940 if (object->IsJSGlobalProxy()) { | 2730 if (object->IsJSGlobalProxy()) { |
| 2941 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss); | 2731 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss); |
| 2942 } | 2732 } |
| 2943 | 2733 |
| 2944 // Stub is never generated for non-global objects that require access checks. | 2734 // Stub is never generated for non-global objects that require access checks. |
| 2945 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2735 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 2946 | 2736 |
| 2947 __ Mov(scratch1(), Operand(Smi::FromInt(strict_mode()))); | 2737 __ Push(receiver(), this->name(), value()); |
| 2948 __ Push(receiver(), this->name(), value(), scratch1()); | |
| 2949 | 2738 |
| 2950 // Do tail-call to the runtime system. | 2739 // Do tail-call to the runtime system. |
| 2951 ExternalReference store_ic_property = | 2740 ExternalReference store_ic_property = |
| 2952 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 2741 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 2953 __ TailCallExternalReference(store_ic_property, 4, 1); | 2742 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 2954 | 2743 |
| 2955 // Handle store cache miss. | 2744 // Handle store cache miss. |
| 2956 __ Bind(&miss); | 2745 __ Bind(&miss); |
| 2957 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2746 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 2958 | 2747 |
| 2959 // Return the generated code. | 2748 // Return the generated code. |
| 2960 return GetCode(kind(), Code::FAST, name); | 2749 return GetCode(kind(), Code::FAST, name); |
| 2961 } | 2750 } |
| 2962 | 2751 |
| 2963 | 2752 |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3217 | 3006 |
| 3218 // Miss case, call the runtime. | 3007 // Miss case, call the runtime. |
| 3219 __ Bind(&miss); | 3008 __ Bind(&miss); |
| 3220 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 3009 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3221 } | 3010 } |
| 3222 | 3011 |
| 3223 | 3012 |
| 3224 } } // namespace v8::internal | 3013 } } // namespace v8::internal |
| 3225 | 3014 |
| 3226 #endif // V8_TARGET_ARCH_A64 | 3015 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |