| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #if V8_TARGET_ARCH_ARM | 5 #if V8_TARGET_ARCH_ARM | 
| 6 | 6 | 
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" | 
| 8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" | 
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" | 
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" | 
| (...skipping 1740 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1751   // context at this point). | 1751   // context at this point). | 
| 1752   __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1752   __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 
| 1753   __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kConstructStubOffset)); | 1753   __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kConstructStubOffset)); | 
| 1754   __ add(pc, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1754   __ add(pc, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); | 
| 1755 | 1755 | 
| 1756   __ bind(&non_function); | 1756   __ bind(&non_function); | 
| 1757   __ mov(r3, r1); | 1757   __ mov(r3, r1); | 
| 1758   __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 1758   __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 
| 1759 } | 1759 } | 
| 1760 | 1760 | 
| 1761 // Note: feedback_vector and slot are clobbered after the call. |  | 
| 1762 static void IncrementCallCount(MacroAssembler* masm, Register feedback_vector, |  | 
| 1763                                Register slot) { |  | 
| 1764   __ add(feedback_vector, feedback_vector, |  | 
| 1765          Operand::PointerOffsetFromSmiKey(slot)); |  | 
| 1766   __ add(feedback_vector, feedback_vector, |  | 
| 1767          Operand(FixedArray::kHeaderSize + kPointerSize)); |  | 
| 1768   __ ldr(slot, FieldMemOperand(feedback_vector, 0)); |  | 
| 1769   __ add(slot, slot, Operand(Smi::FromInt(1))); |  | 
| 1770   __ str(slot, FieldMemOperand(feedback_vector, 0)); |  | 
| 1771 } |  | 
| 1772 |  | 
| 1773 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { |  | 
| 1774   // r0 - number of arguments |  | 
| 1775   // r1 - function |  | 
| 1776   // r3 - slot id |  | 
| 1777   // r2 - vector |  | 
| 1778   // r4 - allocation site (loaded from vector[slot]) |  | 
| 1779   __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r5); |  | 
| 1780   __ cmp(r1, r5); |  | 
| 1781   __ b(ne, miss); |  | 
| 1782 |  | 
| 1783   // Increment the call count for monomorphic function calls. |  | 
| 1784   IncrementCallCount(masm, r2, r3); |  | 
| 1785 |  | 
| 1786   __ mov(r2, r4); |  | 
| 1787   __ mov(r3, r1); |  | 
| 1788   ArrayConstructorStub stub(masm->isolate()); |  | 
| 1789   __ TailCallStub(&stub); |  | 
| 1790 } |  | 
| 1791 |  | 
| 1792 |  | 
| 1793 void CallICStub::Generate(MacroAssembler* masm) { |  | 
| 1794   // r0 - number of arguments |  | 
| 1795   // r1 - function |  | 
| 1796   // r3 - slot id (Smi) |  | 
| 1797   // r2 - vector |  | 
| 1798   Label extra_checks_or_miss, call, call_function, call_count_incremented; |  | 
| 1799 |  | 
| 1800   // The checks. First, does r1 match the recorded monomorphic target? |  | 
| 1801   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); |  | 
| 1802   __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize)); |  | 
| 1803 |  | 
| 1804   // We don't know that we have a weak cell. We might have a private symbol |  | 
| 1805   // or an AllocationSite, but the memory is safe to examine. |  | 
| 1806   // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to |  | 
| 1807   // FixedArray. |  | 
| 1808   // WeakCell::kValueOffset - contains a JSFunction or Smi(0) |  | 
| 1809   // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not |  | 
| 1810   // computed, meaning that it can't appear to be a pointer. If the low bit is |  | 
| 1811   // 0, then hash is computed, but the 0 bit prevents the field from appearing |  | 
| 1812   // to be a pointer. |  | 
| 1813   STATIC_ASSERT(WeakCell::kSize >= kPointerSize); |  | 
| 1814   STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == |  | 
| 1815                     WeakCell::kValueOffset && |  | 
| 1816                 WeakCell::kValueOffset == Symbol::kHashFieldSlot); |  | 
| 1817 |  | 
| 1818   __ ldr(r5, FieldMemOperand(r4, WeakCell::kValueOffset)); |  | 
| 1819   __ cmp(r1, r5); |  | 
| 1820   __ b(ne, &extra_checks_or_miss); |  | 
| 1821 |  | 
| 1822   // The compare above could have been a SMI/SMI comparison. Guard against this |  | 
| 1823   // convincing us that we have a monomorphic JSFunction. |  | 
| 1824   __ JumpIfSmi(r1, &extra_checks_or_miss); |  | 
| 1825 |  | 
| 1826   __ bind(&call_function); |  | 
| 1827 |  | 
| 1828   // Increment the call count for monomorphic function calls. |  | 
| 1829   IncrementCallCount(masm, r2, r3); |  | 
| 1830 |  | 
| 1831   __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), |  | 
| 1832                                                     tail_call_mode()), |  | 
| 1833           RelocInfo::CODE_TARGET); |  | 
| 1834 |  | 
| 1835   __ bind(&extra_checks_or_miss); |  | 
| 1836   Label uninitialized, miss, not_allocation_site; |  | 
| 1837 |  | 
| 1838   __ CompareRoot(r4, Heap::kmegamorphic_symbolRootIndex); |  | 
| 1839   __ b(eq, &call); |  | 
| 1840 |  | 
| 1841   // Verify that r4 contains an AllocationSite |  | 
| 1842   __ ldr(r5, FieldMemOperand(r4, HeapObject::kMapOffset)); |  | 
| 1843   __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); |  | 
| 1844   __ b(ne, ¬_allocation_site); |  | 
| 1845 |  | 
| 1846   // We have an allocation site. |  | 
| 1847   HandleArrayCase(masm, &miss); |  | 
| 1848 |  | 
| 1849   __ bind(¬_allocation_site); |  | 
| 1850 |  | 
| 1851   // The following cases attempt to handle MISS cases without going to the |  | 
| 1852   // runtime. |  | 
| 1853   if (FLAG_trace_ic) { |  | 
| 1854     __ jmp(&miss); |  | 
| 1855   } |  | 
| 1856 |  | 
| 1857   __ CompareRoot(r4, Heap::kuninitialized_symbolRootIndex); |  | 
| 1858   __ b(eq, &uninitialized); |  | 
| 1859 |  | 
| 1860   // We are going megamorphic. If the feedback is a JSFunction, it is fine |  | 
| 1861   // to handle it here. More complex cases are dealt with in the runtime. |  | 
| 1862   __ AssertNotSmi(r4); |  | 
| 1863   __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE); |  | 
| 1864   __ b(ne, &miss); |  | 
| 1865   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); |  | 
| 1866   __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); |  | 
| 1867   __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); |  | 
| 1868 |  | 
| 1869   __ bind(&call); |  | 
| 1870 |  | 
| 1871   // Increment the call count for megamorphic function calls. |  | 
| 1872   IncrementCallCount(masm, r2, r3); |  | 
| 1873 |  | 
| 1874   __ bind(&call_count_incremented); |  | 
| 1875   __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), |  | 
| 1876           RelocInfo::CODE_TARGET); |  | 
| 1877 |  | 
| 1878   __ bind(&uninitialized); |  | 
| 1879 |  | 
| 1880   // We are going monomorphic, provided we actually have a JSFunction. |  | 
| 1881   __ JumpIfSmi(r1, &miss); |  | 
| 1882 |  | 
| 1883   // Goto miss case if we do not have a function. |  | 
| 1884   __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); |  | 
| 1885   __ b(ne, &miss); |  | 
| 1886 |  | 
| 1887   // Make sure the function is not the Array() function, which requires special |  | 
| 1888   // behavior on MISS. |  | 
| 1889   __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r4); |  | 
| 1890   __ cmp(r1, r4); |  | 
| 1891   __ b(eq, &miss); |  | 
| 1892 |  | 
| 1893   // Make sure the function belongs to the same native context. |  | 
| 1894   __ ldr(r4, FieldMemOperand(r1, JSFunction::kContextOffset)); |  | 
| 1895   __ ldr(r4, ContextMemOperand(r4, Context::NATIVE_CONTEXT_INDEX)); |  | 
| 1896   __ ldr(ip, NativeContextMemOperand()); |  | 
| 1897   __ cmp(r4, ip); |  | 
| 1898   __ b(ne, &miss); |  | 
| 1899 |  | 
| 1900   // Store the function. Use a stub since we need a frame for allocation. |  | 
| 1901   // r2 - vector |  | 
| 1902   // r3 - slot |  | 
| 1903   // r1 - function |  | 
| 1904   { |  | 
| 1905     FrameScope scope(masm, StackFrame::INTERNAL); |  | 
| 1906     CreateWeakCellStub create_stub(masm->isolate()); |  | 
| 1907     __ SmiTag(r0); |  | 
| 1908     __ Push(r0, r2, r3, cp, r1); |  | 
| 1909     __ CallStub(&create_stub); |  | 
| 1910     __ Pop(r2, r3, cp, r1); |  | 
| 1911     __ Pop(r0); |  | 
| 1912     __ SmiUntag(r0); |  | 
| 1913   } |  | 
| 1914 |  | 
| 1915   __ jmp(&call_function); |  | 
| 1916 |  | 
| 1917   // We are here because tracing is on or we encountered a MISS case we can't |  | 
| 1918   // handle here. |  | 
| 1919   __ bind(&miss); |  | 
| 1920   GenerateMiss(masm); |  | 
| 1921 |  | 
| 1922   __ jmp(&call_count_incremented); |  | 
| 1923 } |  | 
| 1924 |  | 
| 1925 |  | 
| 1926 void CallICStub::GenerateMiss(MacroAssembler* masm) { |  | 
| 1927   FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |  | 
| 1928 |  | 
| 1929   // Preserve the number of arguments as Smi. |  | 
| 1930   __ SmiTag(r0); |  | 
| 1931 |  | 
| 1932   // Push the receiver and the function and feedback info. |  | 
| 1933   __ Push(r0, r1, r2, r3); |  | 
| 1934 |  | 
| 1935   // Call the entry. |  | 
| 1936   __ CallRuntime(Runtime::kCallIC_Miss); |  | 
| 1937 |  | 
| 1938   // Move result to edi and exit the internal frame. |  | 
| 1939   __ mov(r1, r0); |  | 
| 1940 |  | 
| 1941   // Restore number of arguments. |  | 
| 1942   __ Pop(r0); |  | 
| 1943   __ SmiUntag(r0); |  | 
| 1944 } |  | 
| 1945 |  | 
| 1946 |  | 
| 1947 // StringCharCodeAtGenerator | 1761 // StringCharCodeAtGenerator | 
| 1948 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 1762 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 
| 1949   // If the receiver is a smi trigger the non-string case. | 1763   // If the receiver is a smi trigger the non-string case. | 
| 1950   if (check_mode_ == RECEIVER_IS_UNKNOWN) { | 1764   if (check_mode_ == RECEIVER_IS_UNKNOWN) { | 
| 1951     __ JumpIfSmi(object_, receiver_not_string_); | 1765     __ JumpIfSmi(object_, receiver_not_string_); | 
| 1952 | 1766 | 
| 1953     // Fetch the instance type of the receiver into result register. | 1767     // Fetch the instance type of the receiver into result register. | 
| 1954     __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 1768     __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 
| 1955     __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 1769     __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 
| 1956     // If the receiver is not a string trigger the non-string case. | 1770     // If the receiver is not a string trigger the non-string case. | 
| (...skipping 2130 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4087   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, | 3901   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, | 
| 4088                            kStackUnwindSpace, NULL, return_value_operand, NULL); | 3902                            kStackUnwindSpace, NULL, return_value_operand, NULL); | 
| 4089 } | 3903 } | 
| 4090 | 3904 | 
| 4091 #undef __ | 3905 #undef __ | 
| 4092 | 3906 | 
| 4093 }  // namespace internal | 3907 }  // namespace internal | 
| 4094 }  // namespace v8 | 3908 }  // namespace v8 | 
| 4095 | 3909 | 
| 4096 #endif  // V8_TARGET_ARCH_ARM | 3910 #endif  // V8_TARGET_ARCH_ARM | 
| OLD | NEW | 
|---|