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