| 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/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, r2, r3, r4, | 675 StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, r2, r3, r4, |
| 676 r5); | 676 r5); |
| 677 } | 677 } |
| 678 // Never falls through to here. | 678 // Never falls through to here. |
| 679 | 679 |
| 680 __ bind(&slow); | 680 __ bind(&slow); |
| 681 | 681 |
| 682 __ Push(lhs, rhs); | 682 __ Push(lhs, rhs); |
| 683 // Figure out which native to call and setup the arguments. | 683 // Figure out which native to call and setup the arguments. |
| 684 if (cc == eq) { | 684 if (cc == eq) { |
| 685 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2); | 685 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals); |
| 686 } else { | 686 } else { |
| 687 int ncr; // NaN compare result | 687 int ncr; // NaN compare result |
| 688 if (cc == lt || cc == le) { | 688 if (cc == lt || cc == le) { |
| 689 ncr = GREATER; | 689 ncr = GREATER; |
| 690 } else { | 690 } else { |
| 691 DCHECK(cc == gt || cc == ge); // remaining cases | 691 DCHECK(cc == gt || cc == ge); // remaining cases |
| 692 ncr = LESS; | 692 ncr = LESS; |
| 693 } | 693 } |
| 694 __ mov(r0, Operand(Smi::FromInt(ncr))); | 694 __ mov(r0, Operand(Smi::FromInt(ncr))); |
| 695 __ push(r0); | 695 __ push(r0); |
| 696 | 696 |
| 697 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 697 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
| 698 // tagged as a small integer. | 698 // tagged as a small integer. |
| 699 __ TailCallRuntime( | 699 __ TailCallRuntime(is_strong(strength()) ? Runtime::kCompare_Strong |
| 700 is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, | 700 : Runtime::kCompare); |
| 701 3); | |
| 702 } | 701 } |
| 703 | 702 |
| 704 __ bind(&miss); | 703 __ bind(&miss); |
| 705 GenerateMiss(masm); | 704 GenerateMiss(masm); |
| 706 } | 705 } |
| 707 | 706 |
| 708 | 707 |
| 709 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 708 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
| 710 // We don't allow a GC during a store buffer overflow so there is no need to | 709 // We don't allow a GC during a store buffer overflow so there is no need to |
| 711 // store the registers in any particular way, but we do have to store and | 710 // store the registers in any particular way, but we do have to store and |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 // double_exponent may not containe the exponent value if the input was a | 892 // double_exponent may not containe the exponent value if the input was a |
| 894 // smi. We set it with exponent value before bailing out. | 893 // smi. We set it with exponent value before bailing out. |
| 895 __ vmov(single_scratch, exponent); | 894 __ vmov(single_scratch, exponent); |
| 896 __ vcvt_f64_s32(double_exponent, single_scratch); | 895 __ vcvt_f64_s32(double_exponent, single_scratch); |
| 897 | 896 |
| 898 // Returning or bailing out. | 897 // Returning or bailing out. |
| 899 Counters* counters = isolate()->counters(); | 898 Counters* counters = isolate()->counters(); |
| 900 if (exponent_type() == ON_STACK) { | 899 if (exponent_type() == ON_STACK) { |
| 901 // The arguments are still on the stack. | 900 // The arguments are still on the stack. |
| 902 __ bind(&call_runtime); | 901 __ bind(&call_runtime); |
| 903 __ TailCallRuntime(Runtime::kMathPowRT, 2); | 902 __ TailCallRuntime(Runtime::kMathPowRT); |
| 904 | 903 |
| 905 // The stub is called from non-optimized code, which expects the result | 904 // The stub is called from non-optimized code, which expects the result |
| 906 // as heap number in exponent. | 905 // as heap number in exponent. |
| 907 __ bind(&done); | 906 __ bind(&done); |
| 908 __ AllocateHeapNumber( | 907 __ AllocateHeapNumber( |
| 909 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); | 908 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); |
| 910 __ vstr(double_result, | 909 __ vstr(double_result, |
| 911 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); | 910 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); |
| 912 DCHECK(heapnumber.is(r0)); | 911 DCHECK(heapnumber.is(r0)); |
| 913 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); | 912 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); |
| (...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1397 __ bind(&done); | 1396 __ bind(&done); |
| 1398 __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex); | 1397 __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex); |
| 1399 __ Ret(); | 1398 __ Ret(); |
| 1400 | 1399 |
| 1401 // Found Proxy or access check needed: Call the runtime | 1400 // Found Proxy or access check needed: Call the runtime |
| 1402 __ bind(&fast_runtime_fallback); | 1401 __ bind(&fast_runtime_fallback); |
| 1403 __ Push(object, function_prototype); | 1402 __ Push(object, function_prototype); |
| 1404 // Invalidate the instanceof cache. | 1403 // Invalidate the instanceof cache. |
| 1405 __ Move(scratch, Smi::FromInt(0)); | 1404 __ Move(scratch, Smi::FromInt(0)); |
| 1406 __ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex); | 1405 __ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex); |
| 1407 __ TailCallRuntime(Runtime::kHasInPrototypeChain, 2); | 1406 __ TailCallRuntime(Runtime::kHasInPrototypeChain); |
| 1408 | 1407 |
| 1409 // Slow-case: Call the %InstanceOf runtime function. | 1408 // Slow-case: Call the %InstanceOf runtime function. |
| 1410 __ bind(&slow_case); | 1409 __ bind(&slow_case); |
| 1411 __ Push(object, function); | 1410 __ Push(object, function); |
| 1412 __ TailCallRuntime(Runtime::kInstanceOf, 2); | 1411 __ TailCallRuntime(Runtime::kInstanceOf); |
| 1413 } | 1412 } |
| 1414 | 1413 |
| 1415 | 1414 |
| 1416 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { | 1415 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { |
| 1417 Label miss; | 1416 Label miss; |
| 1418 Register receiver = LoadDescriptor::ReceiverRegister(); | 1417 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 1419 // Ensure that the vector and slot registers won't be clobbered before | 1418 // Ensure that the vector and slot registers won't be clobbered before |
| 1420 // calling the miss handler. | 1419 // calling the miss handler. |
| 1421 DCHECK(!AreAliased(r4, r5, LoadWithVectorDescriptor::VectorRegister(), | 1420 DCHECK(!AreAliased(r4, r5, LoadWithVectorDescriptor::VectorRegister(), |
| 1422 LoadWithVectorDescriptor::SlotRegister())); | 1421 LoadWithVectorDescriptor::SlotRegister())); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1504 // Read the argument from the adaptor frame and return it. | 1503 // Read the argument from the adaptor frame and return it. |
| 1505 __ sub(r3, r0, r1); | 1504 __ sub(r3, r0, r1); |
| 1506 __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r3)); | 1505 __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r3)); |
| 1507 __ ldr(r0, MemOperand(r3, kDisplacement)); | 1506 __ ldr(r0, MemOperand(r3, kDisplacement)); |
| 1508 __ Jump(lr); | 1507 __ Jump(lr); |
| 1509 | 1508 |
| 1510 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 1509 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
| 1511 // by calling the runtime system. | 1510 // by calling the runtime system. |
| 1512 __ bind(&slow); | 1511 __ bind(&slow); |
| 1513 __ push(r1); | 1512 __ push(r1); |
| 1514 __ TailCallRuntime(Runtime::kArguments, 1); | 1513 __ TailCallRuntime(Runtime::kArguments); |
| 1515 } | 1514 } |
| 1516 | 1515 |
| 1517 | 1516 |
| 1518 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { | 1517 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { |
| 1519 // r1 : function | 1518 // r1 : function |
| 1520 // r2 : number of parameters (tagged) | 1519 // r2 : number of parameters (tagged) |
| 1521 // r3 : parameters pointer | 1520 // r3 : parameters pointer |
| 1522 | 1521 |
| 1523 DCHECK(r1.is(ArgumentsAccessNewDescriptor::function())); | 1522 DCHECK(r1.is(ArgumentsAccessNewDescriptor::function())); |
| 1524 DCHECK(r2.is(ArgumentsAccessNewDescriptor::parameter_count())); | 1523 DCHECK(r2.is(ArgumentsAccessNewDescriptor::parameter_count())); |
| 1525 DCHECK(r3.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | 1524 DCHECK(r3.is(ArgumentsAccessNewDescriptor::parameter_pointer())); |
| 1526 | 1525 |
| 1527 // Check if the calling frame is an arguments adaptor frame. | 1526 // Check if the calling frame is an arguments adaptor frame. |
| 1528 Label runtime; | 1527 Label runtime; |
| 1529 __ ldr(r4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1528 __ ldr(r4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 1530 __ ldr(r0, MemOperand(r4, StandardFrameConstants::kContextOffset)); | 1529 __ ldr(r0, MemOperand(r4, StandardFrameConstants::kContextOffset)); |
| 1531 __ cmp(r0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1530 __ cmp(r0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 1532 __ b(ne, &runtime); | 1531 __ b(ne, &runtime); |
| 1533 | 1532 |
| 1534 // Patch the arguments.length and the parameters pointer in the current frame. | 1533 // Patch the arguments.length and the parameters pointer in the current frame. |
| 1535 __ ldr(r2, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 1534 __ ldr(r2, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 1536 __ add(r4, r4, Operand(r2, LSL, 1)); | 1535 __ add(r4, r4, Operand(r2, LSL, 1)); |
| 1537 __ add(r3, r4, Operand(StandardFrameConstants::kCallerSPOffset)); | 1536 __ add(r3, r4, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 1538 | 1537 |
| 1539 __ bind(&runtime); | 1538 __ bind(&runtime); |
| 1540 __ Push(r1, r3, r2); | 1539 __ Push(r1, r3, r2); |
| 1541 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3); | 1540 __ TailCallRuntime(Runtime::kNewSloppyArguments); |
| 1542 } | 1541 } |
| 1543 | 1542 |
| 1544 | 1543 |
| 1545 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { | 1544 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { |
| 1546 // r1 : function | 1545 // r1 : function |
| 1547 // r2 : number of parameters (tagged) | 1546 // r2 : number of parameters (tagged) |
| 1548 // r3 : parameters pointer | 1547 // r3 : parameters pointer |
| 1549 // Registers used over whole function: | 1548 // Registers used over whole function: |
| 1550 // r5 : arguments count (tagged) | 1549 // r5 : arguments count (tagged) |
| 1551 // r6 : mapped parameter count (tagged) | 1550 // r6 : mapped parameter count (tagged) |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1731 __ b(lt, &arguments_loop); | 1730 __ b(lt, &arguments_loop); |
| 1732 | 1731 |
| 1733 // Return. | 1732 // Return. |
| 1734 __ Ret(); | 1733 __ Ret(); |
| 1735 | 1734 |
| 1736 // Do the runtime call to allocate the arguments object. | 1735 // Do the runtime call to allocate the arguments object. |
| 1737 // r0 = address of new object (tagged) | 1736 // r0 = address of new object (tagged) |
| 1738 // r5 = argument count (tagged) | 1737 // r5 = argument count (tagged) |
| 1739 __ bind(&runtime); | 1738 __ bind(&runtime); |
| 1740 __ Push(r1, r3, r5); | 1739 __ Push(r1, r3, r5); |
| 1741 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3); | 1740 __ TailCallRuntime(Runtime::kNewSloppyArguments); |
| 1742 } | 1741 } |
| 1743 | 1742 |
| 1744 | 1743 |
| 1745 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { | 1744 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { |
| 1746 // Return address is in lr. | 1745 // Return address is in lr. |
| 1747 Label slow; | 1746 Label slow; |
| 1748 | 1747 |
| 1749 Register receiver = LoadDescriptor::ReceiverRegister(); | 1748 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 1750 Register key = LoadDescriptor::NameRegister(); | 1749 Register key = LoadDescriptor::NameRegister(); |
| 1751 | 1750 |
| 1752 // Check that the key is an array index, that is Uint32. | 1751 // Check that the key is an array index, that is Uint32. |
| 1753 __ NonNegativeSmiTst(key); | 1752 __ NonNegativeSmiTst(key); |
| 1754 __ b(ne, &slow); | 1753 __ b(ne, &slow); |
| 1755 | 1754 |
| 1756 // Everything is fine, call runtime. | 1755 // Everything is fine, call runtime. |
| 1757 __ Push(receiver, key); // Receiver, key. | 1756 __ Push(receiver, key); // Receiver, key. |
| 1758 | 1757 |
| 1759 // Perform tail call to the entry. | 1758 // Perform tail call to the entry. |
| 1760 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor, 2); | 1759 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor); |
| 1761 | 1760 |
| 1762 __ bind(&slow); | 1761 __ bind(&slow); |
| 1763 PropertyAccessCompiler::TailCallBuiltin( | 1762 PropertyAccessCompiler::TailCallBuiltin( |
| 1764 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); | 1763 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); |
| 1765 } | 1764 } |
| 1766 | 1765 |
| 1767 | 1766 |
| 1768 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | 1767 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { |
| 1769 // r1 : function | 1768 // r1 : function |
| 1770 // r2 : number of parameters (tagged) | 1769 // r2 : number of parameters (tagged) |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1843 __ cmp(r2, Operand::Zero()); | 1842 __ cmp(r2, Operand::Zero()); |
| 1844 __ b(ne, &loop); | 1843 __ b(ne, &loop); |
| 1845 | 1844 |
| 1846 // Return. | 1845 // Return. |
| 1847 __ bind(&done); | 1846 __ bind(&done); |
| 1848 __ Ret(); | 1847 __ Ret(); |
| 1849 | 1848 |
| 1850 // Do the runtime call to allocate the arguments object. | 1849 // Do the runtime call to allocate the arguments object. |
| 1851 __ bind(&runtime); | 1850 __ bind(&runtime); |
| 1852 __ Push(r1, r3, r2); | 1851 __ Push(r1, r3, r2); |
| 1853 __ TailCallRuntime(Runtime::kNewStrictArguments, 3); | 1852 __ TailCallRuntime(Runtime::kNewStrictArguments); |
| 1854 } | 1853 } |
| 1855 | 1854 |
| 1856 | 1855 |
| 1857 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) { | 1856 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) { |
| 1858 // Stack layout on entry. | 1857 // Stack layout on entry. |
| 1859 // sp[0] : language mode | 1858 // sp[0] : language mode |
| 1860 // sp[4] : index of rest parameter | 1859 // sp[4] : index of rest parameter |
| 1861 // sp[8] : number of parameters | 1860 // sp[8] : number of parameters |
| 1862 // sp[12] : receiver displacement | 1861 // sp[12] : receiver displacement |
| 1863 | 1862 |
| 1864 Label runtime; | 1863 Label runtime; |
| 1865 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1864 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 1866 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 1865 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
| 1867 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1866 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 1868 __ b(ne, &runtime); | 1867 __ b(ne, &runtime); |
| 1869 | 1868 |
| 1870 // Patch the arguments.length and the parameters pointer. | 1869 // Patch the arguments.length and the parameters pointer. |
| 1871 __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 1870 __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 1872 __ str(r1, MemOperand(sp, 2 * kPointerSize)); | 1871 __ str(r1, MemOperand(sp, 2 * kPointerSize)); |
| 1873 __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r1)); | 1872 __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r1)); |
| 1874 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); | 1873 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 1875 __ str(r3, MemOperand(sp, 3 * kPointerSize)); | 1874 __ str(r3, MemOperand(sp, 3 * kPointerSize)); |
| 1876 | 1875 |
| 1877 __ bind(&runtime); | 1876 __ bind(&runtime); |
| 1878 __ TailCallRuntime(Runtime::kNewRestParam, 4); | 1877 __ TailCallRuntime(Runtime::kNewRestParam); |
| 1879 } | 1878 } |
| 1880 | 1879 |
| 1881 | 1880 |
| 1882 void RegExpExecStub::Generate(MacroAssembler* masm) { | 1881 void RegExpExecStub::Generate(MacroAssembler* masm) { |
| 1883 // Just jump directly to runtime if native RegExp is not selected at compile | 1882 // Just jump directly to runtime if native RegExp is not selected at compile |
| 1884 // time or if regexp entry in generated code is turned off runtime switch or | 1883 // time or if regexp entry in generated code is turned off runtime switch or |
| 1885 // at compilation. | 1884 // at compilation. |
| 1886 #ifdef V8_INTERPRETED_REGEXP | 1885 #ifdef V8_INTERPRETED_REGEXP |
| 1887 __ TailCallRuntime(Runtime::kRegExpExec, 4); | 1886 __ TailCallRuntime(Runtime::kRegExpExec); |
| 1888 #else // V8_INTERPRETED_REGEXP | 1887 #else // V8_INTERPRETED_REGEXP |
| 1889 | 1888 |
| 1890 // Stack frame on entry. | 1889 // Stack frame on entry. |
| 1891 // sp[0]: last_match_info (expected JSArray) | 1890 // sp[0]: last_match_info (expected JSArray) |
| 1892 // sp[4]: previous index | 1891 // sp[4]: previous index |
| 1893 // sp[8]: subject string | 1892 // sp[8]: subject string |
| 1894 // sp[12]: JSRegExp object | 1893 // sp[12]: JSRegExp object |
| 1895 | 1894 |
| 1896 const int kLastMatchInfoOffset = 0 * kPointerSize; | 1895 const int kLastMatchInfoOffset = 0 * kPointerSize; |
| 1897 const int kPreviousIndexOffset = 1 * kPointerSize; | 1896 const int kPreviousIndexOffset = 1 * kPointerSize; |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2148 // haven't created the exception yet. Handle that in the runtime system. | 2147 // haven't created the exception yet. Handle that in the runtime system. |
| 2149 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 2148 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 2150 __ mov(r1, Operand(isolate()->factory()->the_hole_value())); | 2149 __ mov(r1, Operand(isolate()->factory()->the_hole_value())); |
| 2151 __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, | 2150 __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, |
| 2152 isolate()))); | 2151 isolate()))); |
| 2153 __ ldr(r0, MemOperand(r2, 0)); | 2152 __ ldr(r0, MemOperand(r2, 0)); |
| 2154 __ cmp(r0, r1); | 2153 __ cmp(r0, r1); |
| 2155 __ b(eq, &runtime); | 2154 __ b(eq, &runtime); |
| 2156 | 2155 |
| 2157 // For exception, throw the exception again. | 2156 // For exception, throw the exception again. |
| 2158 __ TailCallRuntime(Runtime::kRegExpExecReThrow, 4); | 2157 __ TailCallRuntime(Runtime::kRegExpExecReThrow); |
| 2159 | 2158 |
| 2160 __ bind(&failure); | 2159 __ bind(&failure); |
| 2161 // For failure and exception return null. | 2160 // For failure and exception return null. |
| 2162 __ mov(r0, Operand(isolate()->factory()->null_value())); | 2161 __ mov(r0, Operand(isolate()->factory()->null_value())); |
| 2163 __ add(sp, sp, Operand(4 * kPointerSize)); | 2162 __ add(sp, sp, Operand(4 * kPointerSize)); |
| 2164 __ Ret(); | 2163 __ Ret(); |
| 2165 | 2164 |
| 2166 // Process the result from the native regexp code. | 2165 // Process the result from the native regexp code. |
| 2167 __ bind(&success); | 2166 __ bind(&success); |
| 2168 __ ldr(r1, | 2167 __ ldr(r1, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2243 __ jmp(&next_capture); | 2242 __ jmp(&next_capture); |
| 2244 __ bind(&done); | 2243 __ bind(&done); |
| 2245 | 2244 |
| 2246 // Return last match info. | 2245 // Return last match info. |
| 2247 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); | 2246 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); |
| 2248 __ add(sp, sp, Operand(4 * kPointerSize)); | 2247 __ add(sp, sp, Operand(4 * kPointerSize)); |
| 2249 __ Ret(); | 2248 __ Ret(); |
| 2250 | 2249 |
| 2251 // Do the runtime call to execute the regexp. | 2250 // Do the runtime call to execute the regexp. |
| 2252 __ bind(&runtime); | 2251 __ bind(&runtime); |
| 2253 __ TailCallRuntime(Runtime::kRegExpExec, 4); | 2252 __ TailCallRuntime(Runtime::kRegExpExec); |
| 2254 | 2253 |
| 2255 // Deferred code for string handling. | 2254 // Deferred code for string handling. |
| 2256 // (6) Not a long external string? If yes, go to (8). | 2255 // (6) Not a long external string? If yes, go to (8). |
| 2257 __ bind(¬_seq_nor_cons); | 2256 __ bind(¬_seq_nor_cons); |
| 2258 // Compare flags are still set. | 2257 // Compare flags are still set. |
| 2259 __ b(gt, ¬_long_external); // Go to (8). | 2258 __ b(gt, ¬_long_external); // Go to (8). |
| 2260 | 2259 |
| 2261 // (7) External string. Make it, offset-wise, look like a sequential string. | 2260 // (7) External string. Make it, offset-wise, look like a sequential string. |
| 2262 __ bind(&external_string); | 2261 __ bind(&external_string); |
| 2263 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 2262 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2602 } | 2601 } |
| 2603 | 2602 |
| 2604 | 2603 |
| 2605 void CallICStub::GenerateMiss(MacroAssembler* masm) { | 2604 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
| 2606 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 2605 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 2607 | 2606 |
| 2608 // Push the receiver and the function and feedback info. | 2607 // Push the receiver and the function and feedback info. |
| 2609 __ Push(r1, r2, r3); | 2608 __ Push(r1, r2, r3); |
| 2610 | 2609 |
| 2611 // Call the entry. | 2610 // Call the entry. |
| 2612 __ CallRuntime(Runtime::kCallIC_Miss, 3); | 2611 __ CallRuntime(Runtime::kCallIC_Miss); |
| 2613 | 2612 |
| 2614 // Move result to edi and exit the internal frame. | 2613 // Move result to edi and exit the internal frame. |
| 2615 __ mov(r1, r0); | 2614 __ mov(r1, r0); |
| 2616 } | 2615 } |
| 2617 | 2616 |
| 2618 | 2617 |
| 2619 // StringCharCodeAtGenerator | 2618 // StringCharCodeAtGenerator |
| 2620 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 2619 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
| 2621 // If the receiver is a smi trigger the non-string case. | 2620 // If the receiver is a smi trigger the non-string case. |
| 2622 if (check_mode_ == RECEIVER_IS_UNKNOWN) { | 2621 if (check_mode_ == RECEIVER_IS_UNKNOWN) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2667 DONT_DO_SMI_CHECK); | 2666 DONT_DO_SMI_CHECK); |
| 2668 call_helper.BeforeCall(masm); | 2667 call_helper.BeforeCall(masm); |
| 2669 if (embed_mode == PART_OF_IC_HANDLER) { | 2668 if (embed_mode == PART_OF_IC_HANDLER) { |
| 2670 __ Push(LoadWithVectorDescriptor::VectorRegister(), | 2669 __ Push(LoadWithVectorDescriptor::VectorRegister(), |
| 2671 LoadWithVectorDescriptor::SlotRegister(), object_, index_); | 2670 LoadWithVectorDescriptor::SlotRegister(), object_, index_); |
| 2672 } else { | 2671 } else { |
| 2673 // index_ is consumed by runtime conversion function. | 2672 // index_ is consumed by runtime conversion function. |
| 2674 __ Push(object_, index_); | 2673 __ Push(object_, index_); |
| 2675 } | 2674 } |
| 2676 if (index_flags_ == STRING_INDEX_IS_NUMBER) { | 2675 if (index_flags_ == STRING_INDEX_IS_NUMBER) { |
| 2677 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); | 2676 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero); |
| 2678 } else { | 2677 } else { |
| 2679 DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); | 2678 DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); |
| 2680 // NumberToSmi discards numbers that are not exact integers. | 2679 // NumberToSmi discards numbers that are not exact integers. |
| 2681 __ CallRuntime(Runtime::kNumberToSmi, 1); | 2680 __ CallRuntime(Runtime::kNumberToSmi); |
| 2682 } | 2681 } |
| 2683 // Save the conversion result before the pop instructions below | 2682 // Save the conversion result before the pop instructions below |
| 2684 // have a chance to overwrite it. | 2683 // have a chance to overwrite it. |
| 2685 __ Move(index_, r0); | 2684 __ Move(index_, r0); |
| 2686 if (embed_mode == PART_OF_IC_HANDLER) { | 2685 if (embed_mode == PART_OF_IC_HANDLER) { |
| 2687 __ Pop(LoadWithVectorDescriptor::VectorRegister(), | 2686 __ Pop(LoadWithVectorDescriptor::VectorRegister(), |
| 2688 LoadWithVectorDescriptor::SlotRegister(), object_); | 2687 LoadWithVectorDescriptor::SlotRegister(), object_); |
| 2689 } else { | 2688 } else { |
| 2690 __ pop(object_); | 2689 __ pop(object_); |
| 2691 } | 2690 } |
| 2692 // Reload the instance type. | 2691 // Reload the instance type. |
| 2693 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 2692 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
| 2694 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 2693 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
| 2695 call_helper.AfterCall(masm); | 2694 call_helper.AfterCall(masm); |
| 2696 // If index is still not a smi, it must be out of range. | 2695 // If index is still not a smi, it must be out of range. |
| 2697 __ JumpIfNotSmi(index_, index_out_of_range_); | 2696 __ JumpIfNotSmi(index_, index_out_of_range_); |
| 2698 // Otherwise, return to the fast path. | 2697 // Otherwise, return to the fast path. |
| 2699 __ jmp(&got_smi_index_); | 2698 __ jmp(&got_smi_index_); |
| 2700 | 2699 |
| 2701 // Call runtime. We get here when the receiver is a string and the | 2700 // Call runtime. We get here when the receiver is a string and the |
| 2702 // index is a number, but the code of getting the actual character | 2701 // index is a number, but the code of getting the actual character |
| 2703 // is too complex (e.g., when the string needs to be flattened). | 2702 // is too complex (e.g., when the string needs to be flattened). |
| 2704 __ bind(&call_runtime_); | 2703 __ bind(&call_runtime_); |
| 2705 call_helper.BeforeCall(masm); | 2704 call_helper.BeforeCall(masm); |
| 2706 __ SmiTag(index_); | 2705 __ SmiTag(index_); |
| 2707 __ Push(object_, index_); | 2706 __ Push(object_, index_); |
| 2708 __ CallRuntime(Runtime::kStringCharCodeAtRT, 2); | 2707 __ CallRuntime(Runtime::kStringCharCodeAtRT); |
| 2709 __ Move(result_, r0); | 2708 __ Move(result_, r0); |
| 2710 call_helper.AfterCall(masm); | 2709 call_helper.AfterCall(masm); |
| 2711 __ jmp(&exit_); | 2710 __ jmp(&exit_); |
| 2712 | 2711 |
| 2713 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); | 2712 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); |
| 2714 } | 2713 } |
| 2715 | 2714 |
| 2716 | 2715 |
| 2717 // ------------------------------------------------------------------------- | 2716 // ------------------------------------------------------------------------- |
| 2718 // StringCharFromCodeGenerator | 2717 // StringCharFromCodeGenerator |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2737 | 2736 |
| 2738 | 2737 |
| 2739 void StringCharFromCodeGenerator::GenerateSlow( | 2738 void StringCharFromCodeGenerator::GenerateSlow( |
| 2740 MacroAssembler* masm, | 2739 MacroAssembler* masm, |
| 2741 const RuntimeCallHelper& call_helper) { | 2740 const RuntimeCallHelper& call_helper) { |
| 2742 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); | 2741 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); |
| 2743 | 2742 |
| 2744 __ bind(&slow_case_); | 2743 __ bind(&slow_case_); |
| 2745 call_helper.BeforeCall(masm); | 2744 call_helper.BeforeCall(masm); |
| 2746 __ push(code_); | 2745 __ push(code_); |
| 2747 __ CallRuntime(Runtime::kStringCharFromCode, 1); | 2746 __ CallRuntime(Runtime::kStringCharFromCode); |
| 2748 __ Move(result_, r0); | 2747 __ Move(result_, r0); |
| 2749 call_helper.AfterCall(masm); | 2748 call_helper.AfterCall(masm); |
| 2750 __ jmp(&exit_); | 2749 __ jmp(&exit_); |
| 2751 | 2750 |
| 2752 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); | 2751 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
| 2753 } | 2752 } |
| 2754 | 2753 |
| 2755 | 2754 |
| 2756 enum CopyCharactersFlags { COPY_ONE_BYTE = 1, DEST_ALWAYS_ALIGNED = 2 }; | 2755 enum CopyCharactersFlags { COPY_ONE_BYTE = 1, DEST_ALWAYS_ALIGNED = 2 }; |
| 2757 | 2756 |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2993 masm, r1, r5, r2, r3, String::TWO_BYTE_ENCODING); | 2992 masm, r1, r5, r2, r3, String::TWO_BYTE_ENCODING); |
| 2994 | 2993 |
| 2995 __ bind(&return_r0); | 2994 __ bind(&return_r0); |
| 2996 Counters* counters = isolate()->counters(); | 2995 Counters* counters = isolate()->counters(); |
| 2997 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); | 2996 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); |
| 2998 __ Drop(3); | 2997 __ Drop(3); |
| 2999 __ Ret(); | 2998 __ Ret(); |
| 3000 | 2999 |
| 3001 // Just jump to runtime to create the sub string. | 3000 // Just jump to runtime to create the sub string. |
| 3002 __ bind(&runtime); | 3001 __ bind(&runtime); |
| 3003 __ TailCallRuntime(Runtime::kSubString, 3); | 3002 __ TailCallRuntime(Runtime::kSubString); |
| 3004 | 3003 |
| 3005 __ bind(&single_char); | 3004 __ bind(&single_char); |
| 3006 // r0: original string | 3005 // r0: original string |
| 3007 // r1: instance type | 3006 // r1: instance type |
| 3008 // r2: length | 3007 // r2: length |
| 3009 // r3: from index (untagged) | 3008 // r3: from index (untagged) |
| 3010 __ SmiTag(r3, r3); | 3009 __ SmiTag(r3, r3); |
| 3011 StringCharAtGenerator generator(r0, r3, r2, r0, &runtime, &runtime, &runtime, | 3010 StringCharAtGenerator generator(r0, r3, r2, r0, &runtime, &runtime, &runtime, |
| 3012 STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING); | 3011 STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING); |
| 3013 generator.GenerateFast(masm); | 3012 generator.GenerateFast(masm); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3033 __ cmp(r1, Operand(FIRST_NONSTRING_TYPE)); | 3032 __ cmp(r1, Operand(FIRST_NONSTRING_TYPE)); |
| 3034 __ b(hs, ¬_string); | 3033 __ b(hs, ¬_string); |
| 3035 // Check if string has a cached array index. | 3034 // Check if string has a cached array index. |
| 3036 __ ldr(r2, FieldMemOperand(r0, String::kHashFieldOffset)); | 3035 __ ldr(r2, FieldMemOperand(r0, String::kHashFieldOffset)); |
| 3037 __ tst(r2, Operand(String::kContainsCachedArrayIndexMask)); | 3036 __ tst(r2, Operand(String::kContainsCachedArrayIndexMask)); |
| 3038 __ b(ne, &slow_string); | 3037 __ b(ne, &slow_string); |
| 3039 __ IndexFromHash(r2, r0); | 3038 __ IndexFromHash(r2, r0); |
| 3040 __ Ret(); | 3039 __ Ret(); |
| 3041 __ bind(&slow_string); | 3040 __ bind(&slow_string); |
| 3042 __ push(r0); // Push argument. | 3041 __ push(r0); // Push argument. |
| 3043 __ TailCallRuntime(Runtime::kStringToNumber, 1); | 3042 __ TailCallRuntime(Runtime::kStringToNumber); |
| 3044 __ bind(¬_string); | 3043 __ bind(¬_string); |
| 3045 | 3044 |
| 3046 Label not_oddball; | 3045 Label not_oddball; |
| 3047 __ cmp(r1, Operand(ODDBALL_TYPE)); | 3046 __ cmp(r1, Operand(ODDBALL_TYPE)); |
| 3048 __ b(ne, ¬_oddball); | 3047 __ b(ne, ¬_oddball); |
| 3049 __ ldr(r0, FieldMemOperand(r0, Oddball::kToNumberOffset)); | 3048 __ ldr(r0, FieldMemOperand(r0, Oddball::kToNumberOffset)); |
| 3050 __ Ret(); | 3049 __ Ret(); |
| 3051 __ bind(¬_oddball); | 3050 __ bind(¬_oddball); |
| 3052 | 3051 |
| 3053 __ push(r0); // Push argument. | 3052 __ push(r0); // Push argument. |
| 3054 __ TailCallRuntime(Runtime::kToNumber, 1); | 3053 __ TailCallRuntime(Runtime::kToNumber); |
| 3055 } | 3054 } |
| 3056 | 3055 |
| 3057 | 3056 |
| 3058 void ToLengthStub::Generate(MacroAssembler* masm) { | 3057 void ToLengthStub::Generate(MacroAssembler* masm) { |
| 3059 // The ToLength stub takes one argument in r0. | 3058 // The ToLength stub takes one argument in r0. |
| 3060 Label not_smi; | 3059 Label not_smi; |
| 3061 __ JumpIfNotSmi(r0, ¬_smi); | 3060 __ JumpIfNotSmi(r0, ¬_smi); |
| 3062 STATIC_ASSERT(kSmiTag == 0); | 3061 STATIC_ASSERT(kSmiTag == 0); |
| 3063 __ tst(r0, r0); | 3062 __ tst(r0, r0); |
| 3064 __ mov(r0, Operand(0), LeaveCC, lt); | 3063 __ mov(r0, Operand(0), LeaveCC, lt); |
| 3065 __ Ret(); | 3064 __ Ret(); |
| 3066 __ bind(¬_smi); | 3065 __ bind(¬_smi); |
| 3067 | 3066 |
| 3068 __ push(r0); // Push argument. | 3067 __ push(r0); // Push argument. |
| 3069 __ TailCallRuntime(Runtime::kToLength, 1); | 3068 __ TailCallRuntime(Runtime::kToLength); |
| 3070 } | 3069 } |
| 3071 | 3070 |
| 3072 | 3071 |
| 3073 void ToStringStub::Generate(MacroAssembler* masm) { | 3072 void ToStringStub::Generate(MacroAssembler* masm) { |
| 3074 // The ToString stub takes one argument in r0. | 3073 // The ToString stub takes one argument in r0. |
| 3075 Label is_number; | 3074 Label is_number; |
| 3076 __ JumpIfSmi(r0, &is_number); | 3075 __ JumpIfSmi(r0, &is_number); |
| 3077 | 3076 |
| 3078 __ CompareObjectType(r0, r1, r1, FIRST_NONSTRING_TYPE); | 3077 __ CompareObjectType(r0, r1, r1, FIRST_NONSTRING_TYPE); |
| 3079 // r0: receiver | 3078 // r0: receiver |
| 3080 // r1: receiver instance type | 3079 // r1: receiver instance type |
| 3081 __ Ret(lo); | 3080 __ Ret(lo); |
| 3082 | 3081 |
| 3083 Label not_heap_number; | 3082 Label not_heap_number; |
| 3084 __ cmp(r1, Operand(HEAP_NUMBER_TYPE)); | 3083 __ cmp(r1, Operand(HEAP_NUMBER_TYPE)); |
| 3085 __ b(ne, ¬_heap_number); | 3084 __ b(ne, ¬_heap_number); |
| 3086 __ bind(&is_number); | 3085 __ bind(&is_number); |
| 3087 NumberToStringStub stub(isolate()); | 3086 NumberToStringStub stub(isolate()); |
| 3088 __ TailCallStub(&stub); | 3087 __ TailCallStub(&stub); |
| 3089 __ bind(¬_heap_number); | 3088 __ bind(¬_heap_number); |
| 3090 | 3089 |
| 3091 Label not_oddball; | 3090 Label not_oddball; |
| 3092 __ cmp(r1, Operand(ODDBALL_TYPE)); | 3091 __ cmp(r1, Operand(ODDBALL_TYPE)); |
| 3093 __ b(ne, ¬_oddball); | 3092 __ b(ne, ¬_oddball); |
| 3094 __ ldr(r0, FieldMemOperand(r0, Oddball::kToStringOffset)); | 3093 __ ldr(r0, FieldMemOperand(r0, Oddball::kToStringOffset)); |
| 3095 __ Ret(); | 3094 __ Ret(); |
| 3096 __ bind(¬_oddball); | 3095 __ bind(¬_oddball); |
| 3097 | 3096 |
| 3098 __ push(r0); // Push argument. | 3097 __ push(r0); // Push argument. |
| 3099 __ TailCallRuntime(Runtime::kToString, 1); | 3098 __ TailCallRuntime(Runtime::kToString); |
| 3100 } | 3099 } |
| 3101 | 3100 |
| 3102 | 3101 |
| 3103 void StringHelper::GenerateFlatOneByteStringEquals( | 3102 void StringHelper::GenerateFlatOneByteStringEquals( |
| 3104 MacroAssembler* masm, Register left, Register right, Register scratch1, | 3103 MacroAssembler* masm, Register left, Register right, Register scratch1, |
| 3105 Register scratch2, Register scratch3) { | 3104 Register scratch2, Register scratch3) { |
| 3106 Register length = scratch1; | 3105 Register length = scratch1; |
| 3107 | 3106 |
| 3108 // Compare lengths. | 3107 // Compare lengths. |
| 3109 Label strings_not_equal, check_zero_length; | 3108 Label strings_not_equal, check_zero_length; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3219 | 3218 |
| 3220 // Compare flat one-byte strings natively. | 3219 // Compare flat one-byte strings natively. |
| 3221 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r2, | 3220 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r2, |
| 3222 r3); | 3221 r3); |
| 3223 StringHelper::GenerateCompareFlatOneByteStrings(masm, r1, r0, r2, r3, r4, r5); | 3222 StringHelper::GenerateCompareFlatOneByteStrings(masm, r1, r0, r2, r3, r4, r5); |
| 3224 | 3223 |
| 3225 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 3224 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 3226 // tagged as a small integer. | 3225 // tagged as a small integer. |
| 3227 __ bind(&runtime); | 3226 __ bind(&runtime); |
| 3228 __ Push(r1, r0); | 3227 __ Push(r1, r0); |
| 3229 __ TailCallRuntime(Runtime::kStringCompare, 2); | 3228 __ TailCallRuntime(Runtime::kStringCompare); |
| 3230 } | 3229 } |
| 3231 | 3230 |
| 3232 | 3231 |
| 3233 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 3232 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
| 3234 // ----------- S t a t e ------------- | 3233 // ----------- S t a t e ------------- |
| 3235 // -- r1 : left | 3234 // -- r1 : left |
| 3236 // -- r0 : right | 3235 // -- r0 : right |
| 3237 // -- lr : return address | 3236 // -- lr : return address |
| 3238 // ----------------------------------- | 3237 // ----------------------------------- |
| 3239 | 3238 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3261 } | 3260 } |
| 3262 | 3261 |
| 3263 | 3262 |
| 3264 void CompareICStub::GenerateBooleans(MacroAssembler* masm) { | 3263 void CompareICStub::GenerateBooleans(MacroAssembler* masm) { |
| 3265 DCHECK_EQ(CompareICState::BOOLEAN, state()); | 3264 DCHECK_EQ(CompareICState::BOOLEAN, state()); |
| 3266 Label miss; | 3265 Label miss; |
| 3267 | 3266 |
| 3268 __ CheckMap(r1, r2, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); | 3267 __ CheckMap(r1, r2, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); |
| 3269 __ CheckMap(r0, r3, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); | 3268 __ CheckMap(r0, r3, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); |
| 3270 if (op() != Token::EQ_STRICT && is_strong(strength())) { | 3269 if (op() != Token::EQ_STRICT && is_strong(strength())) { |
| 3271 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0); | 3270 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); |
| 3272 } else { | 3271 } else { |
| 3273 if (!Token::IsEqualityOp(op())) { | 3272 if (!Token::IsEqualityOp(op())) { |
| 3274 __ ldr(r1, FieldMemOperand(r1, Oddball::kToNumberOffset)); | 3273 __ ldr(r1, FieldMemOperand(r1, Oddball::kToNumberOffset)); |
| 3275 __ AssertSmi(r1); | 3274 __ AssertSmi(r1); |
| 3276 __ ldr(r0, FieldMemOperand(r0, Oddball::kToNumberOffset)); | 3275 __ ldr(r0, FieldMemOperand(r0, Oddball::kToNumberOffset)); |
| 3277 __ AssertSmi(r0); | 3276 __ AssertSmi(r0); |
| 3278 } | 3277 } |
| 3279 __ sub(r0, r1, r0); | 3278 __ sub(r0, r1, r0); |
| 3280 __ Ret(); | 3279 __ Ret(); |
| 3281 } | 3280 } |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3522 tmp3); | 3521 tmp3); |
| 3523 } else { | 3522 } else { |
| 3524 StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, | 3523 StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, |
| 3525 tmp2, tmp3, tmp4); | 3524 tmp2, tmp3, tmp4); |
| 3526 } | 3525 } |
| 3527 | 3526 |
| 3528 // Handle more complex cases in runtime. | 3527 // Handle more complex cases in runtime. |
| 3529 __ bind(&runtime); | 3528 __ bind(&runtime); |
| 3530 __ Push(left, right); | 3529 __ Push(left, right); |
| 3531 if (equality) { | 3530 if (equality) { |
| 3532 __ TailCallRuntime(Runtime::kStringEquals, 2); | 3531 __ TailCallRuntime(Runtime::kStringEquals); |
| 3533 } else { | 3532 } else { |
| 3534 __ TailCallRuntime(Runtime::kStringCompare, 2); | 3533 __ TailCallRuntime(Runtime::kStringCompare); |
| 3535 } | 3534 } |
| 3536 | 3535 |
| 3537 __ bind(&miss); | 3536 __ bind(&miss); |
| 3538 GenerateMiss(masm); | 3537 GenerateMiss(masm); |
| 3539 } | 3538 } |
| 3540 | 3539 |
| 3541 | 3540 |
| 3542 void CompareICStub::GenerateReceivers(MacroAssembler* masm) { | 3541 void CompareICStub::GenerateReceivers(MacroAssembler* masm) { |
| 3543 DCHECK_EQ(CompareICState::RECEIVER, state()); | 3542 DCHECK_EQ(CompareICState::RECEIVER, state()); |
| 3544 Label miss; | 3543 Label miss; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3570 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3569 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 3571 __ cmp(r2, r4); | 3570 __ cmp(r2, r4); |
| 3572 __ b(ne, &miss); | 3571 __ b(ne, &miss); |
| 3573 __ cmp(r3, r4); | 3572 __ cmp(r3, r4); |
| 3574 __ b(ne, &miss); | 3573 __ b(ne, &miss); |
| 3575 | 3574 |
| 3576 if (Token::IsEqualityOp(op())) { | 3575 if (Token::IsEqualityOp(op())) { |
| 3577 __ sub(r0, r0, Operand(r1)); | 3576 __ sub(r0, r0, Operand(r1)); |
| 3578 __ Ret(); | 3577 __ Ret(); |
| 3579 } else if (is_strong(strength())) { | 3578 } else if (is_strong(strength())) { |
| 3580 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0); | 3579 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); |
| 3581 } else { | 3580 } else { |
| 3582 if (op() == Token::LT || op() == Token::LTE) { | 3581 if (op() == Token::LT || op() == Token::LTE) { |
| 3583 __ mov(r2, Operand(Smi::FromInt(GREATER))); | 3582 __ mov(r2, Operand(Smi::FromInt(GREATER))); |
| 3584 } else { | 3583 } else { |
| 3585 __ mov(r2, Operand(Smi::FromInt(LESS))); | 3584 __ mov(r2, Operand(Smi::FromInt(LESS))); |
| 3586 } | 3585 } |
| 3587 __ Push(r1, r0, r2); | 3586 __ Push(r1, r0, r2); |
| 3588 __ TailCallRuntime(Runtime::kCompare, 3); | 3587 __ TailCallRuntime(Runtime::kCompare); |
| 3589 } | 3588 } |
| 3590 | 3589 |
| 3591 __ bind(&miss); | 3590 __ bind(&miss); |
| 3592 GenerateMiss(masm); | 3591 GenerateMiss(masm); |
| 3593 } | 3592 } |
| 3594 | 3593 |
| 3595 | 3594 |
| 3596 void CompareICStub::GenerateMiss(MacroAssembler* masm) { | 3595 void CompareICStub::GenerateMiss(MacroAssembler* masm) { |
| 3597 { | 3596 { |
| 3598 // Call the runtime system in a fresh internal frame. | 3597 // Call the runtime system in a fresh internal frame. |
| 3599 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 3598 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 3600 __ Push(r1, r0); | 3599 __ Push(r1, r0); |
| 3601 __ Push(lr, r1, r0); | 3600 __ Push(lr, r1, r0); |
| 3602 __ mov(ip, Operand(Smi::FromInt(op()))); | 3601 __ mov(ip, Operand(Smi::FromInt(op()))); |
| 3603 __ push(ip); | 3602 __ push(ip); |
| 3604 __ CallRuntime(Runtime::kCompareIC_Miss, 3); | 3603 __ CallRuntime(Runtime::kCompareIC_Miss); |
| 3605 // Compute the entry point of the rewritten stub. | 3604 // Compute the entry point of the rewritten stub. |
| 3606 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); | 3605 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 3607 // Restore registers. | 3606 // Restore registers. |
| 3608 __ pop(lr); | 3607 __ pop(lr); |
| 3609 __ Pop(r1, r0); | 3608 __ Pop(r1, r0); |
| 3610 } | 3609 } |
| 3611 | 3610 |
| 3612 __ Jump(r2); | 3611 __ Jump(r2); |
| 3613 } | 3612 } |
| 3614 | 3613 |
| (...skipping 1323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4938 __ ldr(result, ContextMemOperand(result)); | 4937 __ ldr(result, ContextMemOperand(result)); |
| 4939 __ ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset)); | 4938 __ ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset)); |
| 4940 | 4939 |
| 4941 // If the result is not the_hole, return. Otherwise, handle in the runtime. | 4940 // If the result is not the_hole, return. Otherwise, handle in the runtime. |
| 4942 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 4941 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 4943 __ Ret(ne); | 4942 __ Ret(ne); |
| 4944 | 4943 |
| 4945 // Fallback to runtime. | 4944 // Fallback to runtime. |
| 4946 __ SmiTag(slot); | 4945 __ SmiTag(slot); |
| 4947 __ push(slot); | 4946 __ push(slot); |
| 4948 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 1); | 4947 __ TailCallRuntime(Runtime::kLoadGlobalViaContext); |
| 4949 } | 4948 } |
| 4950 | 4949 |
| 4951 | 4950 |
| 4952 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { | 4951 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { |
| 4953 Register value = r0; | 4952 Register value = r0; |
| 4954 Register slot = r2; | 4953 Register slot = r2; |
| 4955 | 4954 |
| 4956 Register cell = r1; | 4955 Register cell = r1; |
| 4957 Register cell_details = r4; | 4956 Register cell_details = r4; |
| 4958 Register cell_value = r5; | 4957 Register cell_value = r5; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5062 __ ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); | 5061 __ ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); |
| 5063 __ cmp(cell_value_map, scratch); | 5062 __ cmp(cell_value_map, scratch); |
| 5064 __ b(eq, &fast_heapobject_case); | 5063 __ b(eq, &fast_heapobject_case); |
| 5065 | 5064 |
| 5066 // Fallback to runtime. | 5065 // Fallback to runtime. |
| 5067 __ bind(&slow_case); | 5066 __ bind(&slow_case); |
| 5068 __ SmiTag(slot); | 5067 __ SmiTag(slot); |
| 5069 __ Push(slot, value); | 5068 __ Push(slot, value); |
| 5070 __ TailCallRuntime(is_strict(language_mode()) | 5069 __ TailCallRuntime(is_strict(language_mode()) |
| 5071 ? Runtime::kStoreGlobalViaContext_Strict | 5070 ? Runtime::kStoreGlobalViaContext_Strict |
| 5072 : Runtime::kStoreGlobalViaContext_Sloppy, | 5071 : Runtime::kStoreGlobalViaContext_Sloppy); |
| 5073 2); | |
| 5074 } | 5072 } |
| 5075 | 5073 |
| 5076 | 5074 |
| 5077 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | 5075 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
| 5078 return ref0.address() - ref1.address(); | 5076 return ref0.address() - ref1.address(); |
| 5079 } | 5077 } |
| 5080 | 5078 |
| 5081 | 5079 |
| 5082 // Calls an API function. Allocates HandleScope, extracts returned value | 5080 // Calls an API function. Allocates HandleScope, extracts returned value |
| 5083 // from handle and propagates exceptions. Restores context. stack_space | 5081 // from handle and propagates exceptions. Restores context. stack_space |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5190 __ LoadRoot(r4, Heap::kTheHoleValueRootIndex); | 5188 __ LoadRoot(r4, Heap::kTheHoleValueRootIndex); |
| 5191 __ mov(ip, Operand(ExternalReference::scheduled_exception_address(isolate))); | 5189 __ mov(ip, Operand(ExternalReference::scheduled_exception_address(isolate))); |
| 5192 __ ldr(r5, MemOperand(ip)); | 5190 __ ldr(r5, MemOperand(ip)); |
| 5193 __ cmp(r4, r5); | 5191 __ cmp(r4, r5); |
| 5194 __ b(ne, &promote_scheduled_exception); | 5192 __ b(ne, &promote_scheduled_exception); |
| 5195 | 5193 |
| 5196 __ mov(pc, lr); | 5194 __ mov(pc, lr); |
| 5197 | 5195 |
| 5198 // Re-throw by promoting a scheduled exception. | 5196 // Re-throw by promoting a scheduled exception. |
| 5199 __ bind(&promote_scheduled_exception); | 5197 __ bind(&promote_scheduled_exception); |
| 5200 __ TailCallRuntime(Runtime::kPromoteScheduledException, 0); | 5198 __ TailCallRuntime(Runtime::kPromoteScheduledException); |
| 5201 | 5199 |
| 5202 // HandleScope limit has changed. Delete allocated extensions. | 5200 // HandleScope limit has changed. Delete allocated extensions. |
| 5203 __ bind(&delete_allocated_handles); | 5201 __ bind(&delete_allocated_handles); |
| 5204 __ str(r5, MemOperand(r9, kLimitOffset)); | 5202 __ str(r5, MemOperand(r9, kLimitOffset)); |
| 5205 __ mov(r4, r0); | 5203 __ mov(r4, r0); |
| 5206 __ PrepareCallCFunction(1, r5); | 5204 __ PrepareCallCFunction(1, r5); |
| 5207 __ mov(r0, Operand(ExternalReference::isolate_address(isolate))); | 5205 __ mov(r0, Operand(ExternalReference::isolate_address(isolate))); |
| 5208 __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate), | 5206 __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate), |
| 5209 1); | 5207 1); |
| 5210 __ mov(r0, r4); | 5208 __ mov(r0, r4); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5389 MemOperand(fp, 6 * kPointerSize), NULL); | 5387 MemOperand(fp, 6 * kPointerSize), NULL); |
| 5390 } | 5388 } |
| 5391 | 5389 |
| 5392 | 5390 |
| 5393 #undef __ | 5391 #undef __ |
| 5394 | 5392 |
| 5395 } // namespace internal | 5393 } // namespace internal |
| 5396 } // namespace v8 | 5394 } // namespace v8 |
| 5397 | 5395 |
| 5398 #endif // V8_TARGET_ARCH_ARM | 5396 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |