OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1073 native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; | 1073 native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; |
1074 } else { | 1074 } else { |
1075 native = Builtins::COMPARE; | 1075 native = Builtins::COMPARE; |
1076 int ncr; // NaN compare result | 1076 int ncr; // NaN compare result |
1077 if ((cond == lt) || (cond == le)) { | 1077 if ((cond == lt) || (cond == le)) { |
1078 ncr = GREATER; | 1078 ncr = GREATER; |
1079 } else { | 1079 } else { |
1080 ASSERT((cond == gt) || (cond == ge)); // remaining cases | 1080 ASSERT((cond == gt) || (cond == ge)); // remaining cases |
1081 ncr = LESS; | 1081 ncr = LESS; |
1082 } | 1082 } |
1083 __ Mov(x10, Operand(Smi::FromInt(ncr))); | 1083 __ Mov(x10, Smi::FromInt(ncr)); |
1084 __ Push(x10); | 1084 __ Push(x10); |
1085 } | 1085 } |
1086 | 1086 |
1087 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1087 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
1088 // tagged as a small integer. | 1088 // tagged as a small integer. |
1089 __ InvokeBuiltin(native, JUMP_FUNCTION); | 1089 __ InvokeBuiltin(native, JUMP_FUNCTION); |
1090 | 1090 |
1091 __ Bind(&miss); | 1091 __ Bind(&miss); |
1092 GenerateMiss(masm); | 1092 GenerateMiss(masm); |
1093 } | 1093 } |
(...skipping 10 matching lines...) Expand all Loading... |
1104 | 1104 |
1105 // We don't allow a GC during a store buffer overflow so there is no need to | 1105 // We don't allow a GC during a store buffer overflow so there is no need to |
1106 // store the registers in any particular way, but we do have to store and | 1106 // store the registers in any particular way, but we do have to store and |
1107 // restore them. | 1107 // restore them. |
1108 __ PushCPURegList(saved_regs); | 1108 __ PushCPURegList(saved_regs); |
1109 if (save_doubles_ == kSaveFPRegs) { | 1109 if (save_doubles_ == kSaveFPRegs) { |
1110 __ PushCPURegList(kCallerSavedFP); | 1110 __ PushCPURegList(kCallerSavedFP); |
1111 } | 1111 } |
1112 | 1112 |
1113 AllowExternalCallThatCantCauseGC scope(masm); | 1113 AllowExternalCallThatCantCauseGC scope(masm); |
1114 __ Mov(x0, Operand(ExternalReference::isolate_address(masm->isolate()))); | 1114 __ Mov(x0, ExternalReference::isolate_address(masm->isolate())); |
1115 __ CallCFunction( | 1115 __ CallCFunction( |
1116 ExternalReference::store_buffer_overflow_function(masm->isolate()), | 1116 ExternalReference::store_buffer_overflow_function(masm->isolate()), |
1117 1, 0); | 1117 1, 0); |
1118 | 1118 |
1119 if (save_doubles_ == kSaveFPRegs) { | 1119 if (save_doubles_ == kSaveFPRegs) { |
1120 __ PopCPURegList(kCallerSavedFP); | 1120 __ PopCPURegList(kCallerSavedFP); |
1121 } | 1121 } |
1122 __ PopCPURegList(saved_regs); | 1122 __ PopCPURegList(saved_regs); |
1123 __ Ret(); | 1123 __ Ret(); |
1124 } | 1124 } |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1483 | 1483 |
1484 Isolate* isolate = masm->isolate(); | 1484 Isolate* isolate = masm->isolate(); |
1485 | 1485 |
1486 const Register& argv = x21; | 1486 const Register& argv = x21; |
1487 const Register& argc = x22; | 1487 const Register& argc = x22; |
1488 const Register& target = x23; | 1488 const Register& target = x23; |
1489 | 1489 |
1490 if (do_gc) { | 1490 if (do_gc) { |
1491 // Call Runtime::PerformGC, passing x0 (the result parameter for | 1491 // Call Runtime::PerformGC, passing x0 (the result parameter for |
1492 // PerformGC) and x1 (the isolate). | 1492 // PerformGC) and x1 (the isolate). |
1493 __ Mov(x1, Operand(ExternalReference::isolate_address(masm->isolate()))); | 1493 __ Mov(x1, ExternalReference::isolate_address(masm->isolate())); |
1494 __ CallCFunction( | 1494 __ CallCFunction( |
1495 ExternalReference::perform_gc_function(isolate), 2, 0); | 1495 ExternalReference::perform_gc_function(isolate), 2, 0); |
1496 } | 1496 } |
1497 | 1497 |
1498 ExternalReference scope_depth = | 1498 ExternalReference scope_depth = |
1499 ExternalReference::heap_always_allocate_scope_depth(isolate); | 1499 ExternalReference::heap_always_allocate_scope_depth(isolate); |
1500 if (always_allocate) { | 1500 if (always_allocate) { |
1501 __ Mov(x10, Operand(scope_depth)); | 1501 __ Mov(x10, Operand(scope_depth)); |
1502 __ Ldr(x11, MemOperand(x10)); | 1502 __ Ldr(x11, MemOperand(x10)); |
1503 __ Add(x11, x11, 1); | 1503 __ Add(x11, x11, 1); |
1504 __ Str(x11, MemOperand(x10)); | 1504 __ Str(x11, MemOperand(x10)); |
1505 } | 1505 } |
1506 | 1506 |
1507 // Prepare AAPCS64 arguments to pass to the builtin. | 1507 // Prepare AAPCS64 arguments to pass to the builtin. |
1508 __ Mov(x0, argc); | 1508 __ Mov(x0, argc); |
1509 __ Mov(x1, argv); | 1509 __ Mov(x1, argv); |
1510 __ Mov(x2, Operand(ExternalReference::isolate_address(isolate))); | 1510 __ Mov(x2, ExternalReference::isolate_address(isolate)); |
1511 | 1511 |
1512 // Store the return address on the stack, in the space previously allocated | 1512 // Store the return address on the stack, in the space previously allocated |
1513 // by EnterExitFrame. The return address is queried by | 1513 // by EnterExitFrame. The return address is queried by |
1514 // ExitFrame::GetStateForFramePointer. | 1514 // ExitFrame::GetStateForFramePointer. |
1515 Label return_location; | 1515 Label return_location; |
1516 __ Adr(x12, &return_location); | 1516 __ Adr(x12, &return_location); |
1517 __ Poke(x12, 0); | 1517 __ Poke(x12, 0); |
1518 if (__ emit_debug_code()) { | 1518 if (__ emit_debug_code()) { |
1519 // Verify that the slot below fp[kSPOffset]-8 points to the return location | 1519 // Verify that the slot below fp[kSPOffset]-8 points to the return location |
1520 // (currently in x12). | 1520 // (currently in x12). |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1813 // Set up the reserved register for 0.0. | 1813 // Set up the reserved register for 0.0. |
1814 __ Fmov(fp_zero, 0.0); | 1814 __ Fmov(fp_zero, 0.0); |
1815 | 1815 |
1816 // Build an entry frame (see layout below). | 1816 // Build an entry frame (see layout below). |
1817 Isolate* isolate = masm->isolate(); | 1817 Isolate* isolate = masm->isolate(); |
1818 | 1818 |
1819 // Build an entry frame. | 1819 // Build an entry frame. |
1820 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; | 1820 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; |
1821 int64_t bad_frame_pointer = -1L; // Bad frame pointer to fail if it is used. | 1821 int64_t bad_frame_pointer = -1L; // Bad frame pointer to fail if it is used. |
1822 __ Mov(x13, bad_frame_pointer); | 1822 __ Mov(x13, bad_frame_pointer); |
1823 __ Mov(x12, Operand(Smi::FromInt(marker))); | 1823 __ Mov(x12, Smi::FromInt(marker)); |
1824 __ Mov(x11, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate))); | 1824 __ Mov(x11, ExternalReference(Isolate::kCEntryFPAddress, isolate)); |
1825 __ Ldr(x10, MemOperand(x11)); | 1825 __ Ldr(x10, MemOperand(x11)); |
1826 | 1826 |
1827 __ Push(x13, xzr, x12, x10); | 1827 __ Push(x13, xzr, x12, x10); |
1828 // Set up fp. | 1828 // Set up fp. |
1829 __ Sub(fp, jssp, EntryFrameConstants::kCallerFPOffset); | 1829 __ Sub(fp, jssp, EntryFrameConstants::kCallerFPOffset); |
1830 | 1830 |
1831 // Push the JS entry frame marker. Also set js_entry_sp if this is the | 1831 // Push the JS entry frame marker. Also set js_entry_sp if this is the |
1832 // outermost JS call. | 1832 // outermost JS call. |
1833 Label non_outermost_js, done; | 1833 Label non_outermost_js, done; |
1834 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate); | 1834 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate); |
1835 __ Mov(x10, Operand(ExternalReference(js_entry_sp))); | 1835 __ Mov(x10, ExternalReference(js_entry_sp)); |
1836 __ Ldr(x11, MemOperand(x10)); | 1836 __ Ldr(x11, MemOperand(x10)); |
1837 __ Cbnz(x11, &non_outermost_js); | 1837 __ Cbnz(x11, &non_outermost_js); |
1838 __ Str(fp, MemOperand(x10)); | 1838 __ Str(fp, MemOperand(x10)); |
1839 __ Mov(x12, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); | 1839 __ Mov(x12, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)); |
1840 __ Push(x12); | 1840 __ Push(x12); |
1841 __ B(&done); | 1841 __ B(&done); |
1842 __ Bind(&non_outermost_js); | 1842 __ Bind(&non_outermost_js); |
1843 // We spare one instruction by pushing xzr since the marker is 0. | 1843 // We spare one instruction by pushing xzr since the marker is 0. |
1844 ASSERT(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME) == NULL); | 1844 ASSERT(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME) == NULL); |
1845 __ Push(xzr); | 1845 __ Push(xzr); |
1846 __ Bind(&done); | 1846 __ Bind(&done); |
1847 | 1847 |
1848 // The frame set up looks like this: | 1848 // The frame set up looks like this: |
1849 // jssp[0] : JS entry frame marker. | 1849 // jssp[0] : JS entry frame marker. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1898 | 1898 |
1899 // Expected registers by Builtins::JSEntryTrampoline | 1899 // Expected registers by Builtins::JSEntryTrampoline |
1900 // x0: code entry. | 1900 // x0: code entry. |
1901 // x1: function. | 1901 // x1: function. |
1902 // x2: receiver. | 1902 // x2: receiver. |
1903 // x3: argc. | 1903 // x3: argc. |
1904 // x4: argv. | 1904 // x4: argv. |
1905 ExternalReference entry(is_construct ? Builtins::kJSConstructEntryTrampoline | 1905 ExternalReference entry(is_construct ? Builtins::kJSConstructEntryTrampoline |
1906 : Builtins::kJSEntryTrampoline, | 1906 : Builtins::kJSEntryTrampoline, |
1907 isolate); | 1907 isolate); |
1908 __ Mov(x10, Operand(entry)); | 1908 __ Mov(x10, entry); |
1909 | 1909 |
1910 // Call the JSEntryTrampoline. | 1910 // Call the JSEntryTrampoline. |
1911 __ Ldr(x11, MemOperand(x10)); // Dereference the address. | 1911 __ Ldr(x11, MemOperand(x10)); // Dereference the address. |
1912 __ Add(x12, x11, Code::kHeaderSize - kHeapObjectTag); | 1912 __ Add(x12, x11, Code::kHeaderSize - kHeapObjectTag); |
1913 __ Blr(x12); | 1913 __ Blr(x12); |
1914 | 1914 |
1915 // Unlink this frame from the handler chain. | 1915 // Unlink this frame from the handler chain. |
1916 __ PopTryHandler(); | 1916 __ PopTryHandler(); |
1917 | 1917 |
1918 | 1918 |
1919 __ Bind(&exit); | 1919 __ Bind(&exit); |
1920 // x0 holds the result. | 1920 // x0 holds the result. |
1921 // The stack pointer points to the top of the entry frame pushed on entry from | 1921 // The stack pointer points to the top of the entry frame pushed on entry from |
1922 // C++ (at the beginning of this stub): | 1922 // C++ (at the beginning of this stub): |
1923 // jssp[0] : JS entry frame marker. | 1923 // jssp[0] : JS entry frame marker. |
1924 // jssp[1] : C entry FP. | 1924 // jssp[1] : C entry FP. |
1925 // jssp[2] : stack frame marker. | 1925 // jssp[2] : stack frame marker. |
1926 // jssp[3] : stack frmae marker. | 1926 // jssp[3] : stack frmae marker. |
1927 // jssp[4] : bad frame pointer 0xfff...ff <- fp points here. | 1927 // jssp[4] : bad frame pointer 0xfff...ff <- fp points here. |
1928 | 1928 |
1929 // Check if the current stack frame is marked as the outermost JS frame. | 1929 // Check if the current stack frame is marked as the outermost JS frame. |
1930 Label non_outermost_js_2; | 1930 Label non_outermost_js_2; |
1931 __ Pop(x10); | 1931 __ Pop(x10); |
1932 __ Cmp(x10, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); | 1932 __ Cmp(x10, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)); |
1933 __ B(ne, &non_outermost_js_2); | 1933 __ B(ne, &non_outermost_js_2); |
1934 __ Mov(x11, Operand(ExternalReference(js_entry_sp))); | 1934 __ Mov(x11, ExternalReference(js_entry_sp)); |
1935 __ Str(xzr, MemOperand(x11)); | 1935 __ Str(xzr, MemOperand(x11)); |
1936 __ Bind(&non_outermost_js_2); | 1936 __ Bind(&non_outermost_js_2); |
1937 | 1937 |
1938 // Restore the top frame descriptors from the stack. | 1938 // Restore the top frame descriptors from the stack. |
1939 __ Pop(x10); | 1939 __ Pop(x10); |
1940 __ Mov(x11, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate))); | 1940 __ Mov(x11, ExternalReference(Isolate::kCEntryFPAddress, isolate)); |
1941 __ Str(x10, MemOperand(x11)); | 1941 __ Str(x10, MemOperand(x11)); |
1942 | 1942 |
1943 // Reset the stack to the callee saved registers. | 1943 // Reset the stack to the callee saved registers. |
1944 __ Drop(-EntryFrameConstants::kCallerFPOffset, kByteSizeInBytes); | 1944 __ Drop(-EntryFrameConstants::kCallerFPOffset, kByteSizeInBytes); |
1945 // Restore the callee-saved registers and return. | 1945 // Restore the callee-saved registers and return. |
1946 ASSERT(jssp.Is(__ StackPointer())); | 1946 ASSERT(jssp.Is(__ StackPointer())); |
1947 __ Mov(csp, jssp); | 1947 __ Mov(csp, jssp); |
1948 __ SetStackPointer(csp); | 1948 __ SetStackPointer(csp); |
1949 __ PopCalleeSavedRegisters(); | 1949 __ PopCalleeSavedRegisters(); |
1950 // After this point, we must not modify jssp because it is a callee-saved | 1950 // After this point, we must not modify jssp because it is a callee-saved |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2010 Label not_js_object, slow; | 2010 Label not_js_object, slow; |
2011 | 2011 |
2012 if (!HasArgsInRegisters()) { | 2012 if (!HasArgsInRegisters()) { |
2013 __ Pop(function, object); | 2013 __ Pop(function, object); |
2014 } | 2014 } |
2015 | 2015 |
2016 if (ReturnTrueFalseObject()) { | 2016 if (ReturnTrueFalseObject()) { |
2017 __ LoadTrueFalseRoots(res_true, res_false); | 2017 __ LoadTrueFalseRoots(res_true, res_false); |
2018 } else { | 2018 } else { |
2019 // This is counter-intuitive, but correct. | 2019 // This is counter-intuitive, but correct. |
2020 __ Mov(res_true, Operand(Smi::FromInt(0))); | 2020 __ Mov(res_true, Smi::FromInt(0)); |
2021 __ Mov(res_false, Operand(Smi::FromInt(1))); | 2021 __ Mov(res_false, Smi::FromInt(1)); |
2022 } | 2022 } |
2023 | 2023 |
2024 // Check that the left hand side is a JS object and load its map as a side | 2024 // Check that the left hand side is a JS object and load its map as a side |
2025 // effect. | 2025 // effect. |
2026 Register map = x12; | 2026 Register map = x12; |
2027 __ JumpIfSmi(object, ¬_js_object); | 2027 __ JumpIfSmi(object, ¬_js_object); |
2028 __ IsObjectJSObjectType(object, map, scratch2, ¬_js_object); | 2028 __ IsObjectJSObjectType(object, map, scratch2, ¬_js_object); |
2029 | 2029 |
2030 // If there is a call site cache, don't look in the global cache, but do the | 2030 // If there is a call site cache, don't look in the global cache, but do the |
2031 // real lookup and update the call site cache. | 2031 // real lookup and update the call site cache. |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2181 __ JumpIfNotSmi(key, &slow); | 2181 __ JumpIfNotSmi(key, &slow); |
2182 | 2182 |
2183 // Check if the calling frame is an arguments adaptor frame. | 2183 // Check if the calling frame is an arguments adaptor frame. |
2184 Register local_fp = x11; | 2184 Register local_fp = x11; |
2185 Register caller_fp = x11; | 2185 Register caller_fp = x11; |
2186 Register caller_ctx = x12; | 2186 Register caller_ctx = x12; |
2187 Label skip_adaptor; | 2187 Label skip_adaptor; |
2188 __ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 2188 __ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
2189 __ Ldr(caller_ctx, MemOperand(caller_fp, | 2189 __ Ldr(caller_ctx, MemOperand(caller_fp, |
2190 StandardFrameConstants::kContextOffset)); | 2190 StandardFrameConstants::kContextOffset)); |
2191 __ Cmp(caller_ctx, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2191 __ Cmp(caller_ctx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
2192 __ Csel(local_fp, fp, caller_fp, ne); | 2192 __ Csel(local_fp, fp, caller_fp, ne); |
2193 __ B(ne, &skip_adaptor); | 2193 __ B(ne, &skip_adaptor); |
2194 | 2194 |
2195 // Load the actual arguments limit found in the arguments adaptor frame. | 2195 // Load the actual arguments limit found in the arguments adaptor frame. |
2196 __ Ldr(arg_count, MemOperand(caller_fp, | 2196 __ Ldr(arg_count, MemOperand(caller_fp, |
2197 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2197 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
2198 __ Bind(&skip_adaptor); | 2198 __ Bind(&skip_adaptor); |
2199 | 2199 |
2200 // Check index against formal parameters count limit. Use unsigned comparison | 2200 // Check index against formal parameters count limit. Use unsigned comparison |
2201 // to get negative check for free: branch if key < 0 or key >= arg_count. | 2201 // to get negative check for free: branch if key < 0 or key >= arg_count. |
(...skipping 29 matching lines...) Expand all Loading... |
2231 __ Ldr(w11, MemOperand(caller_fp, StandardFrameConstants::kContextOffset + | 2231 __ Ldr(w11, MemOperand(caller_fp, StandardFrameConstants::kContextOffset + |
2232 (kSmiShift / kBitsPerByte))); | 2232 (kSmiShift / kBitsPerByte))); |
2233 __ Cmp(w11, StackFrame::ARGUMENTS_ADAPTOR); | 2233 __ Cmp(w11, StackFrame::ARGUMENTS_ADAPTOR); |
2234 __ B(ne, &runtime); | 2234 __ B(ne, &runtime); |
2235 | 2235 |
2236 // Patch the arguments.length and parameters pointer in the current frame. | 2236 // Patch the arguments.length and parameters pointer in the current frame. |
2237 __ Ldr(x11, MemOperand(caller_fp, | 2237 __ Ldr(x11, MemOperand(caller_fp, |
2238 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2238 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
2239 __ Poke(x11, 0 * kXRegSize); | 2239 __ Poke(x11, 0 * kXRegSize); |
2240 __ Add(x10, caller_fp, Operand::UntagSmiAndScale(x11, kPointerSizeLog2)); | 2240 __ Add(x10, caller_fp, Operand::UntagSmiAndScale(x11, kPointerSizeLog2)); |
2241 __ Add(x10, x10, Operand(StandardFrameConstants::kCallerSPOffset)); | 2241 __ Add(x10, x10, StandardFrameConstants::kCallerSPOffset); |
2242 __ Poke(x10, 1 * kXRegSize); | 2242 __ Poke(x10, 1 * kXRegSize); |
2243 | 2243 |
2244 __ Bind(&runtime); | 2244 __ Bind(&runtime); |
2245 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); | 2245 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); |
2246 } | 2246 } |
2247 | 2247 |
2248 | 2248 |
2249 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { | 2249 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { |
2250 // Stack layout on entry. | 2250 // Stack layout on entry. |
2251 // jssp[0]: number of parameters (tagged) | 2251 // jssp[0]: number of parameters (tagged) |
(...skipping 12 matching lines...) Expand all Loading... |
2264 __ SmiUntag(param_count, param_count_smi); | 2264 __ SmiUntag(param_count, param_count_smi); |
2265 | 2265 |
2266 // Check if the calling frame is an arguments adaptor frame. | 2266 // Check if the calling frame is an arguments adaptor frame. |
2267 Register caller_fp = x11; | 2267 Register caller_fp = x11; |
2268 Register caller_ctx = x12; | 2268 Register caller_ctx = x12; |
2269 Label runtime; | 2269 Label runtime; |
2270 Label adaptor_frame, try_allocate; | 2270 Label adaptor_frame, try_allocate; |
2271 __ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 2271 __ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
2272 __ Ldr(caller_ctx, MemOperand(caller_fp, | 2272 __ Ldr(caller_ctx, MemOperand(caller_fp, |
2273 StandardFrameConstants::kContextOffset)); | 2273 StandardFrameConstants::kContextOffset)); |
2274 __ Cmp(caller_ctx, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2274 __ Cmp(caller_ctx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
2275 __ B(eq, &adaptor_frame); | 2275 __ B(eq, &adaptor_frame); |
2276 | 2276 |
2277 // No adaptor, parameter count = argument count. | 2277 // No adaptor, parameter count = argument count. |
2278 | 2278 |
2279 // x1 mapped_params number of mapped params, min(params, args) (uninit) | 2279 // x1 mapped_params number of mapped params, min(params, args) (uninit) |
2280 // x2 arg_count number of function arguments (uninit) | 2280 // x2 arg_count number of function arguments (uninit) |
2281 // x3 arg_count_smi number of function arguments (smi) | 2281 // x3 arg_count_smi number of function arguments (smi) |
2282 // x4 function function pointer | 2282 // x4 function function pointer |
2283 // x7 param_count number of function parameters | 2283 // x7 param_count number of function parameters |
2284 // x11 caller_fp caller's frame pointer | 2284 // x11 caller_fp caller's frame pointer |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2466 | 2466 |
2467 __ B(¶meters_test); | 2467 __ B(¶meters_test); |
2468 | 2468 |
2469 __ Bind(¶meters_loop); | 2469 __ Bind(¶meters_loop); |
2470 __ Sub(loop_count, loop_count, 1); | 2470 __ Sub(loop_count, loop_count, 1); |
2471 __ Mov(x10, Operand(loop_count, LSL, kPointerSizeLog2)); | 2471 __ Mov(x10, Operand(loop_count, LSL, kPointerSizeLog2)); |
2472 __ Add(x10, x10, kParameterMapHeaderSize - kHeapObjectTag); | 2472 __ Add(x10, x10, kParameterMapHeaderSize - kHeapObjectTag); |
2473 __ Str(index, MemOperand(elements, x10)); | 2473 __ Str(index, MemOperand(elements, x10)); |
2474 __ Sub(x10, x10, kParameterMapHeaderSize - FixedArray::kHeaderSize); | 2474 __ Sub(x10, x10, kParameterMapHeaderSize - FixedArray::kHeaderSize); |
2475 __ Str(the_hole, MemOperand(backing_store, x10)); | 2475 __ Str(the_hole, MemOperand(backing_store, x10)); |
2476 __ Add(index, index, Operand(Smi::FromInt(1))); | 2476 __ Add(index, index, Smi::FromInt(1)); |
2477 __ Bind(¶meters_test); | 2477 __ Bind(¶meters_test); |
2478 __ Cbnz(loop_count, ¶meters_loop); | 2478 __ Cbnz(loop_count, ¶meters_loop); |
2479 | 2479 |
2480 __ Bind(&skip_parameter_map); | 2480 __ Bind(&skip_parameter_map); |
2481 // Copy arguments header and remaining slots (if there are any.) | 2481 // Copy arguments header and remaining slots (if there are any.) |
2482 __ LoadRoot(x10, Heap::kFixedArrayMapRootIndex); | 2482 __ LoadRoot(x10, Heap::kFixedArrayMapRootIndex); |
2483 __ Str(x10, FieldMemOperand(backing_store, FixedArray::kMapOffset)); | 2483 __ Str(x10, FieldMemOperand(backing_store, FixedArray::kMapOffset)); |
2484 __ Str(arg_count_smi, FieldMemOperand(backing_store, | 2484 __ Str(arg_count_smi, FieldMemOperand(backing_store, |
2485 FixedArray::kLengthOffset)); | 2485 FixedArray::kLengthOffset)); |
2486 | 2486 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2535 __ Pop(param_count_smi, params, function); | 2535 __ Pop(param_count_smi, params, function); |
2536 __ SmiUntag(param_count, param_count_smi); | 2536 __ SmiUntag(param_count, param_count_smi); |
2537 | 2537 |
2538 // Test if arguments adaptor needed. | 2538 // Test if arguments adaptor needed. |
2539 Register caller_fp = x11; | 2539 Register caller_fp = x11; |
2540 Register caller_ctx = x12; | 2540 Register caller_ctx = x12; |
2541 Label try_allocate, runtime; | 2541 Label try_allocate, runtime; |
2542 __ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 2542 __ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
2543 __ Ldr(caller_ctx, MemOperand(caller_fp, | 2543 __ Ldr(caller_ctx, MemOperand(caller_fp, |
2544 StandardFrameConstants::kContextOffset)); | 2544 StandardFrameConstants::kContextOffset)); |
2545 __ Cmp(caller_ctx, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2545 __ Cmp(caller_ctx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
2546 __ B(ne, &try_allocate); | 2546 __ B(ne, &try_allocate); |
2547 | 2547 |
2548 // x1 param_count_smi number of parameters passed to function (smi) | 2548 // x1 param_count_smi number of parameters passed to function (smi) |
2549 // x2 params pointer to parameters | 2549 // x2 params pointer to parameters |
2550 // x3 function function pointer | 2550 // x3 function function pointer |
2551 // x11 caller_fp caller's frame pointer | 2551 // x11 caller_fp caller's frame pointer |
2552 // x13 param_count number of parameters passed to function | 2552 // x13 param_count number of parameters passed to function |
2553 | 2553 |
2554 // Patch the argument length and parameters pointer. | 2554 // Patch the argument length and parameters pointer. |
2555 __ Ldr(param_count_smi, | 2555 __ Ldr(param_count_smi, |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2721 const int kPreviousIndexOffset = 5 * kPointerSize; | 2721 const int kPreviousIndexOffset = 5 * kPointerSize; |
2722 const int kSubjectOffset = 6 * kPointerSize; | 2722 const int kSubjectOffset = 6 * kPointerSize; |
2723 const int kJSRegExpOffset = 7 * kPointerSize; | 2723 const int kJSRegExpOffset = 7 * kPointerSize; |
2724 | 2724 |
2725 // Ensure that a RegExp stack is allocated. | 2725 // Ensure that a RegExp stack is allocated. |
2726 Isolate* isolate = masm->isolate(); | 2726 Isolate* isolate = masm->isolate(); |
2727 ExternalReference address_of_regexp_stack_memory_address = | 2727 ExternalReference address_of_regexp_stack_memory_address = |
2728 ExternalReference::address_of_regexp_stack_memory_address(isolate); | 2728 ExternalReference::address_of_regexp_stack_memory_address(isolate); |
2729 ExternalReference address_of_regexp_stack_memory_size = | 2729 ExternalReference address_of_regexp_stack_memory_size = |
2730 ExternalReference::address_of_regexp_stack_memory_size(isolate); | 2730 ExternalReference::address_of_regexp_stack_memory_size(isolate); |
2731 __ Mov(x10, Operand(address_of_regexp_stack_memory_size)); | 2731 __ Mov(x10, address_of_regexp_stack_memory_size); |
2732 __ Ldr(x10, MemOperand(x10)); | 2732 __ Ldr(x10, MemOperand(x10)); |
2733 __ Cbz(x10, &runtime); | 2733 __ Cbz(x10, &runtime); |
2734 | 2734 |
2735 // Check that the first argument is a JSRegExp object. | 2735 // Check that the first argument is a JSRegExp object. |
2736 ASSERT(jssp.Is(__ StackPointer())); | 2736 ASSERT(jssp.Is(__ StackPointer())); |
2737 __ Peek(jsregexp_object, kJSRegExpOffset); | 2737 __ Peek(jsregexp_object, kJSRegExpOffset); |
2738 __ JumpIfSmi(jsregexp_object, &runtime); | 2738 __ JumpIfSmi(jsregexp_object, &runtime); |
2739 __ JumpIfNotObjectType(jsregexp_object, x10, x10, JS_REGEXP_TYPE, &runtime); | 2739 __ JumpIfNotObjectType(jsregexp_object, x10, x10, JS_REGEXP_TYPE, &runtime); |
2740 | 2740 |
2741 // Check that the RegExp has been compiled (data contains a fixed array). | 2741 // Check that the RegExp has been compiled (data contains a fixed array). |
2742 __ Ldr(regexp_data, FieldMemOperand(jsregexp_object, JSRegExp::kDataOffset)); | 2742 __ Ldr(regexp_data, FieldMemOperand(jsregexp_object, JSRegExp::kDataOffset)); |
2743 if (FLAG_debug_code) { | 2743 if (FLAG_debug_code) { |
2744 STATIC_ASSERT(kSmiTag == 0); | 2744 STATIC_ASSERT(kSmiTag == 0); |
2745 __ Tst(regexp_data, kSmiTagMask); | 2745 __ Tst(regexp_data, kSmiTagMask); |
2746 __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected); | 2746 __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected); |
2747 __ CompareObjectType(regexp_data, x10, x10, FIXED_ARRAY_TYPE); | 2747 __ CompareObjectType(regexp_data, x10, x10, FIXED_ARRAY_TYPE); |
2748 __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected); | 2748 __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected); |
2749 } | 2749 } |
2750 | 2750 |
2751 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | 2751 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. |
2752 __ Ldr(x10, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); | 2752 __ Ldr(x10, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); |
2753 __ Cmp(x10, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); | 2753 __ Cmp(x10, Smi::FromInt(JSRegExp::IRREGEXP)); |
2754 __ B(ne, &runtime); | 2754 __ B(ne, &runtime); |
2755 | 2755 |
2756 // Check that the number of captures fit in the static offsets vector buffer. | 2756 // Check that the number of captures fit in the static offsets vector buffer. |
2757 // We have always at least one capture for the whole match, plus additional | 2757 // We have always at least one capture for the whole match, plus additional |
2758 // ones due to capturing parentheses. A capture takes 2 registers. | 2758 // ones due to capturing parentheses. A capture takes 2 registers. |
2759 // The number of capture registers then is (number_of_captures + 1) * 2. | 2759 // The number of capture registers then is (number_of_captures + 1) * 2. |
2760 __ Ldrsw(x10, | 2760 __ Ldrsw(x10, |
2761 UntagSmiFieldMemOperand(regexp_data, | 2761 UntagSmiFieldMemOperand(regexp_data, |
2762 JSRegExp::kIrregexpCaptureCountOffset)); | 2762 JSRegExp::kIrregexpCaptureCountOffset)); |
2763 // Check (number_of_captures + 1) * 2 <= offsets vector size | 2763 // Check (number_of_captures + 1) * 2 <= offsets vector size |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2898 ASSERT(csp.Is(__ StackPointer())); | 2898 ASSERT(csp.Is(__ StackPointer())); |
2899 | 2899 |
2900 // We have 9 arguments to pass to the regexp code, therefore we have to pass | 2900 // We have 9 arguments to pass to the regexp code, therefore we have to pass |
2901 // one on the stack and the rest as registers. | 2901 // one on the stack and the rest as registers. |
2902 | 2902 |
2903 // Note that the placement of the argument on the stack isn't standard | 2903 // Note that the placement of the argument on the stack isn't standard |
2904 // AAPCS64: | 2904 // AAPCS64: |
2905 // csp[0]: Space for the return address placed by DirectCEntryStub. | 2905 // csp[0]: Space for the return address placed by DirectCEntryStub. |
2906 // csp[8]: Argument 9, the current isolate address. | 2906 // csp[8]: Argument 9, the current isolate address. |
2907 | 2907 |
2908 __ Mov(x10, Operand(ExternalReference::isolate_address(isolate))); | 2908 __ Mov(x10, ExternalReference::isolate_address(isolate)); |
2909 __ Poke(x10, kPointerSize); | 2909 __ Poke(x10, kPointerSize); |
2910 | 2910 |
2911 Register length = w11; | 2911 Register length = w11; |
2912 Register previous_index_in_bytes = w12; | 2912 Register previous_index_in_bytes = w12; |
2913 Register start = x13; | 2913 Register start = x13; |
2914 | 2914 |
2915 // Load start of the subject string. | 2915 // Load start of the subject string. |
2916 __ Add(start, subject, SeqString::kHeaderSize - kHeapObjectTag); | 2916 __ Add(start, subject, SeqString::kHeaderSize - kHeapObjectTag); |
2917 // Load the length from the original subject string from the previous stack | 2917 // Load the length from the original subject string from the previous stack |
2918 // frame. Therefore we have to use fp, which points exactly to two pointer | 2918 // frame. Therefore we have to use fp, which points exactly to two pointer |
(...skipping 28 matching lines...) Expand all Loading... |
2947 // is not sliced). | 2947 // is not sliced). |
2948 __ Add(w10, previous_index_in_bytes, sliced_string_offset); | 2948 __ Add(w10, previous_index_in_bytes, sliced_string_offset); |
2949 __ Add(x2, start, Operand(w10, UXTW)); | 2949 __ Add(x2, start, Operand(w10, UXTW)); |
2950 | 2950 |
2951 // Argument 4 (x3): | 2951 // Argument 4 (x3): |
2952 // End of input = start of input + (length of input - previous index) | 2952 // End of input = start of input + (length of input - previous index) |
2953 __ Sub(w10, length, previous_index_in_bytes); | 2953 __ Sub(w10, length, previous_index_in_bytes); |
2954 __ Add(x3, x2, Operand(w10, UXTW)); | 2954 __ Add(x3, x2, Operand(w10, UXTW)); |
2955 | 2955 |
2956 // Argument 5 (x4): static offsets vector buffer. | 2956 // Argument 5 (x4): static offsets vector buffer. |
2957 __ Mov(x4, | 2957 __ Mov(x4, ExternalReference::address_of_static_offsets_vector(isolate)); |
2958 Operand(ExternalReference::address_of_static_offsets_vector(isolate))); | |
2959 | 2958 |
2960 // Argument 6 (x5): Set the number of capture registers to zero to force | 2959 // Argument 6 (x5): Set the number of capture registers to zero to force |
2961 // global regexps to behave as non-global. This stub is not used for global | 2960 // global regexps to behave as non-global. This stub is not used for global |
2962 // regexps. | 2961 // regexps. |
2963 __ Mov(x5, 0); | 2962 __ Mov(x5, 0); |
2964 | 2963 |
2965 // Argument 7 (x6): Start (high end) of backtracking stack memory area. | 2964 // Argument 7 (x6): Start (high end) of backtracking stack memory area. |
2966 __ Mov(x10, Operand(address_of_regexp_stack_memory_address)); | 2965 __ Mov(x10, address_of_regexp_stack_memory_address); |
2967 __ Ldr(x10, MemOperand(x10)); | 2966 __ Ldr(x10, MemOperand(x10)); |
2968 __ Mov(x11, Operand(address_of_regexp_stack_memory_size)); | 2967 __ Mov(x11, address_of_regexp_stack_memory_size); |
2969 __ Ldr(x11, MemOperand(x11)); | 2968 __ Ldr(x11, MemOperand(x11)); |
2970 __ Add(x6, x10, x11); | 2969 __ Add(x6, x10, x11); |
2971 | 2970 |
2972 // Argument 8 (x7): Indicate that this is a direct call from JavaScript. | 2971 // Argument 8 (x7): Indicate that this is a direct call from JavaScript. |
2973 __ Mov(x7, 1); | 2972 __ Mov(x7, 1); |
2974 | 2973 |
2975 // Locate the code entry and call it. | 2974 // Locate the code entry and call it. |
2976 __ Add(code_object, code_object, Code::kHeaderSize - kHeapObjectTag); | 2975 __ Add(code_object, code_object, Code::kHeaderSize - kHeapObjectTag); |
2977 DirectCEntryStub stub; | 2976 DirectCEntryStub stub; |
2978 stub.GenerateCall(masm, code_object); | 2977 stub.GenerateCall(masm, code_object); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3054 kDontSaveFPRegs); | 3053 kDontSaveFPRegs); |
3055 | 3054 |
3056 Register last_match_offsets = x13; | 3055 Register last_match_offsets = x13; |
3057 Register offsets_vector_index = x14; | 3056 Register offsets_vector_index = x14; |
3058 Register current_offset = x15; | 3057 Register current_offset = x15; |
3059 | 3058 |
3060 // Get the static offsets vector filled by the native regexp code | 3059 // Get the static offsets vector filled by the native regexp code |
3061 // and fill the last match info. | 3060 // and fill the last match info. |
3062 ExternalReference address_of_static_offsets_vector = | 3061 ExternalReference address_of_static_offsets_vector = |
3063 ExternalReference::address_of_static_offsets_vector(isolate); | 3062 ExternalReference::address_of_static_offsets_vector(isolate); |
3064 __ Mov(offsets_vector_index, Operand(address_of_static_offsets_vector)); | 3063 __ Mov(offsets_vector_index, address_of_static_offsets_vector); |
3065 | 3064 |
3066 Label next_capture, done; | 3065 Label next_capture, done; |
3067 // Capture register counter starts from number of capture registers and | 3066 // Capture register counter starts from number of capture registers and |
3068 // iterates down to zero (inclusive). | 3067 // iterates down to zero (inclusive). |
3069 __ Add(last_match_offsets, | 3068 __ Add(last_match_offsets, |
3070 last_match_info_elements, | 3069 last_match_info_elements, |
3071 RegExpImpl::kFirstCaptureOffset - kHeapObjectTag); | 3070 RegExpImpl::kFirstCaptureOffset - kHeapObjectTag); |
3072 __ Bind(&next_capture); | 3071 __ Bind(&next_capture); |
3073 __ Subs(number_of_capture_registers, number_of_capture_registers, 2); | 3072 __ Subs(number_of_capture_registers, number_of_capture_registers, 2); |
3074 __ B(mi, &done); | 3073 __ B(mi, &done); |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3549 __ Mov(result_, x0); | 3548 __ Mov(result_, x0); |
3550 call_helper.AfterCall(masm); | 3549 call_helper.AfterCall(masm); |
3551 __ B(&exit_); | 3550 __ B(&exit_); |
3552 | 3551 |
3553 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); | 3552 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); |
3554 } | 3553 } |
3555 | 3554 |
3556 | 3555 |
3557 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { | 3556 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { |
3558 __ JumpIfNotSmi(code_, &slow_case_); | 3557 __ JumpIfNotSmi(code_, &slow_case_); |
3559 __ Cmp(code_, Operand(Smi::FromInt(String::kMaxOneByteCharCode))); | 3558 __ Cmp(code_, Smi::FromInt(String::kMaxOneByteCharCode)); |
3560 __ B(hi, &slow_case_); | 3559 __ B(hi, &slow_case_); |
3561 | 3560 |
3562 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); | 3561 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); |
3563 // At this point code register contains smi tagged ASCII char code. | 3562 // At this point code register contains smi tagged ASCII char code. |
3564 STATIC_ASSERT(kSmiShift > kPointerSizeLog2); | 3563 STATIC_ASSERT(kSmiShift > kPointerSizeLog2); |
3565 __ Add(result_, result_, Operand(code_, LSR, kSmiShift - kPointerSizeLog2)); | 3564 __ Add(result_, result_, Operand(code_, LSR, kSmiShift - kPointerSizeLog2)); |
3566 __ Ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); | 3565 __ Ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); |
3567 __ JumpIfRoot(result_, Heap::kUndefinedValueRootIndex, &slow_case_); | 3566 __ JumpIfRoot(result_, Heap::kUndefinedValueRootIndex, &slow_case_); |
3568 __ Bind(&exit_); | 3567 __ Bind(&exit_); |
3569 } | 3568 } |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3899 ExternalReference miss = | 3898 ExternalReference miss = |
3900 ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate()); | 3899 ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate()); |
3901 | 3900 |
3902 FrameScope scope(masm, StackFrame::INTERNAL); | 3901 FrameScope scope(masm, StackFrame::INTERNAL); |
3903 Register op = x10; | 3902 Register op = x10; |
3904 Register left = x1; | 3903 Register left = x1; |
3905 Register right = x0; | 3904 Register right = x0; |
3906 // Preserve some caller-saved registers. | 3905 // Preserve some caller-saved registers. |
3907 __ Push(x1, x0, lr); | 3906 __ Push(x1, x0, lr); |
3908 // Push the arguments. | 3907 // Push the arguments. |
3909 __ Mov(op, Operand(Smi::FromInt(op_))); | 3908 __ Mov(op, Smi::FromInt(op_)); |
3910 __ Push(left, right, op); | 3909 __ Push(left, right, op); |
3911 | 3910 |
3912 // Call the miss handler. This also pops the arguments. | 3911 // Call the miss handler. This also pops the arguments. |
3913 __ CallExternalReference(miss, 3); | 3912 __ CallExternalReference(miss, 3); |
3914 | 3913 |
3915 // Compute the entry point of the rewritten stub. | 3914 // Compute the entry point of the rewritten stub. |
3916 __ Add(stub_entry, x0, Code::kHeaderSize - kHeapObjectTag); | 3915 __ Add(stub_entry, x0, Code::kHeaderSize - kHeapObjectTag); |
3917 // Restore caller-saved registers. | 3916 // Restore caller-saved registers. |
3918 __ Pop(lr, x0, x1); | 3917 __ Pop(lr, x0, x1); |
3919 } | 3918 } |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4248 | 4247 |
4249 // Compare lengths. If lengths differ, strings can't be equal. Lengths are | 4248 // Compare lengths. If lengths differ, strings can't be equal. Lengths are |
4250 // smis, and don't need to be untagged. | 4249 // smis, and don't need to be untagged. |
4251 Label strings_not_equal, check_zero_length; | 4250 Label strings_not_equal, check_zero_length; |
4252 __ Ldr(left_length, FieldMemOperand(left, String::kLengthOffset)); | 4251 __ Ldr(left_length, FieldMemOperand(left, String::kLengthOffset)); |
4253 __ Ldr(right_length, FieldMemOperand(right, String::kLengthOffset)); | 4252 __ Ldr(right_length, FieldMemOperand(right, String::kLengthOffset)); |
4254 __ Cmp(left_length, right_length); | 4253 __ Cmp(left_length, right_length); |
4255 __ B(eq, &check_zero_length); | 4254 __ B(eq, &check_zero_length); |
4256 | 4255 |
4257 __ Bind(&strings_not_equal); | 4256 __ Bind(&strings_not_equal); |
4258 __ Mov(result, Operand(Smi::FromInt(NOT_EQUAL))); | 4257 __ Mov(result, Smi::FromInt(NOT_EQUAL)); |
4259 __ Ret(); | 4258 __ Ret(); |
4260 | 4259 |
4261 // Check if the length is zero. If so, the strings must be equal (and empty.) | 4260 // Check if the length is zero. If so, the strings must be equal (and empty.) |
4262 Label compare_chars; | 4261 Label compare_chars; |
4263 __ Bind(&check_zero_length); | 4262 __ Bind(&check_zero_length); |
4264 STATIC_ASSERT(kSmiTag == 0); | 4263 STATIC_ASSERT(kSmiTag == 0); |
4265 __ Cbnz(left_length, &compare_chars); | 4264 __ Cbnz(left_length, &compare_chars); |
4266 __ Mov(result, Operand(Smi::FromInt(EQUAL))); | 4265 __ Mov(result, Smi::FromInt(EQUAL)); |
4267 __ Ret(); | 4266 __ Ret(); |
4268 | 4267 |
4269 // Compare characters. Falls through if all characters are equal. | 4268 // Compare characters. Falls through if all characters are equal. |
4270 __ Bind(&compare_chars); | 4269 __ Bind(&compare_chars); |
4271 GenerateAsciiCharsCompareLoop(masm, left, right, left_length, scratch2, | 4270 GenerateAsciiCharsCompareLoop(masm, left, right, left_length, scratch2, |
4272 scratch3, &strings_not_equal); | 4271 scratch3, &strings_not_equal); |
4273 | 4272 |
4274 // Characters in strings are equal. | 4273 // Characters in strings are equal. |
4275 __ Mov(result, Operand(Smi::FromInt(EQUAL))); | 4274 __ Mov(result, Smi::FromInt(EQUAL)); |
4276 __ Ret(); | 4275 __ Ret(); |
4277 } | 4276 } |
4278 | 4277 |
4279 | 4278 |
4280 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, | 4279 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, |
4281 Register left, | 4280 Register left, |
4282 Register right, | 4281 Register right, |
4283 Register scratch1, | 4282 Register scratch1, |
4284 Register scratch2, | 4283 Register scratch2, |
4285 Register scratch3, | 4284 Register scratch3, |
(...skipping 21 matching lines...) Expand all Loading... |
4307 | 4306 |
4308 ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); | 4307 ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); |
4309 | 4308 |
4310 // Use length_delta as result if it's zero. | 4309 // Use length_delta as result if it's zero. |
4311 Register result = x0; | 4310 Register result = x0; |
4312 __ Subs(result, length_delta, 0); | 4311 __ Subs(result, length_delta, 0); |
4313 | 4312 |
4314 __ Bind(&result_not_equal); | 4313 __ Bind(&result_not_equal); |
4315 Register greater = x10; | 4314 Register greater = x10; |
4316 Register less = x11; | 4315 Register less = x11; |
4317 __ Mov(greater, Operand(Smi::FromInt(GREATER))); | 4316 __ Mov(greater, Smi::FromInt(GREATER)); |
4318 __ Mov(less, Operand(Smi::FromInt(LESS))); | 4317 __ Mov(less, Smi::FromInt(LESS)); |
4319 __ CmovX(result, greater, gt); | 4318 __ CmovX(result, greater, gt); |
4320 __ CmovX(result, less, lt); | 4319 __ CmovX(result, less, lt); |
4321 __ Ret(); | 4320 __ Ret(); |
4322 } | 4321 } |
4323 | 4322 |
4324 | 4323 |
4325 void StringCompareStub::GenerateAsciiCharsCompareLoop( | 4324 void StringCompareStub::GenerateAsciiCharsCompareLoop( |
4326 MacroAssembler* masm, | 4325 MacroAssembler* masm, |
4327 Register left, | 4326 Register left, |
4328 Register right, | 4327 Register right, |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4434 __ CheckMap(elements, | 4433 __ CheckMap(elements, |
4435 x10, | 4434 x10, |
4436 Heap::kFixedArrayMapRootIndex, | 4435 Heap::kFixedArrayMapRootIndex, |
4437 &call_builtin, | 4436 &call_builtin, |
4438 DONT_DO_SMI_CHECK); | 4437 DONT_DO_SMI_CHECK); |
4439 } | 4438 } |
4440 | 4439 |
4441 // Get the array's length and calculate new length. | 4440 // Get the array's length and calculate new length. |
4442 __ Ldr(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 4441 __ Ldr(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
4443 STATIC_ASSERT(kSmiTag == 0); | 4442 STATIC_ASSERT(kSmiTag == 0); |
4444 __ Add(length, length, Operand(Smi::FromInt(argc))); | 4443 __ Add(length, length, Smi::FromInt(argc)); |
4445 | 4444 |
4446 // Check if we could survive without allocation. | 4445 // Check if we could survive without allocation. |
4447 __ Ldr(elements_length, | 4446 __ Ldr(elements_length, |
4448 FieldMemOperand(elements, FixedArray::kLengthOffset)); | 4447 FieldMemOperand(elements, FixedArray::kLengthOffset)); |
4449 __ Cmp(length, elements_length); | 4448 __ Cmp(length, elements_length); |
4450 | 4449 |
4451 const int kEndElementsOffset = | 4450 const int kEndElementsOffset = |
4452 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; | 4451 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; |
4453 | 4452 |
4454 if (IsFastSmiOrObjectElementsKind(elements_kind())) { | 4453 if (IsFastSmiOrObjectElementsKind(elements_kind())) { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4561 ExternalReference::new_space_allocation_limit_address(isolate); | 4560 ExternalReference::new_space_allocation_limit_address(isolate); |
4562 | 4561 |
4563 const int kAllocationDelta = 4; | 4562 const int kAllocationDelta = 4; |
4564 ASSERT(kAllocationDelta >= argc); | 4563 ASSERT(kAllocationDelta >= argc); |
4565 Register allocation_top_addr = x5; | 4564 Register allocation_top_addr = x5; |
4566 Register allocation_top = x9; | 4565 Register allocation_top = x9; |
4567 // Load top and check if it is the end of elements. | 4566 // Load top and check if it is the end of elements. |
4568 __ Add(end_elements, elements, | 4567 __ Add(end_elements, elements, |
4569 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); | 4568 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); |
4570 __ Add(end_elements, end_elements, kEndElementsOffset); | 4569 __ Add(end_elements, end_elements, kEndElementsOffset); |
4571 __ Mov(allocation_top_addr, Operand(new_space_allocation_top)); | 4570 __ Mov(allocation_top_addr, new_space_allocation_top); |
4572 __ Ldr(allocation_top, MemOperand(allocation_top_addr)); | 4571 __ Ldr(allocation_top, MemOperand(allocation_top_addr)); |
4573 __ Cmp(end_elements, allocation_top); | 4572 __ Cmp(end_elements, allocation_top); |
4574 __ B(ne, &call_builtin); | 4573 __ B(ne, &call_builtin); |
4575 | 4574 |
4576 __ Mov(x10, Operand(new_space_allocation_limit)); | 4575 __ Mov(x10, new_space_allocation_limit); |
4577 __ Ldr(x10, MemOperand(x10)); | 4576 __ Ldr(x10, MemOperand(x10)); |
4578 __ Add(allocation_top, allocation_top, kAllocationDelta * kPointerSize); | 4577 __ Add(allocation_top, allocation_top, kAllocationDelta * kPointerSize); |
4579 __ Cmp(allocation_top, x10); | 4578 __ Cmp(allocation_top, x10); |
4580 __ B(hi, &call_builtin); | 4579 __ B(hi, &call_builtin); |
4581 | 4580 |
4582 // We fit and could grow elements. | 4581 // We fit and could grow elements. |
4583 // Update new_space_allocation_top. | 4582 // Update new_space_allocation_top. |
4584 __ Str(allocation_top, MemOperand(allocation_top_addr)); | 4583 __ Str(allocation_top, MemOperand(allocation_top_addr)); |
4585 // Push the argument. | 4584 // Push the argument. |
4586 __ Str(argument, MemOperand(end_elements)); | 4585 __ Str(argument, MemOperand(end_elements)); |
4587 // Fill the rest with holes. | 4586 // Fill the rest with holes. |
4588 __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); | 4587 __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); |
4589 ASSERT(kAllocationDelta == 4); | 4588 ASSERT(kAllocationDelta == 4); |
4590 __ Stp(x10, x10, MemOperand(end_elements, 1 * kPointerSize)); | 4589 __ Stp(x10, x10, MemOperand(end_elements, 1 * kPointerSize)); |
4591 __ Stp(x10, x10, MemOperand(end_elements, 3 * kPointerSize)); | 4590 __ Stp(x10, x10, MemOperand(end_elements, 3 * kPointerSize)); |
4592 | 4591 |
4593 // Update elements' and array's sizes. | 4592 // Update elements' and array's sizes. |
4594 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 4593 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
4595 __ Add(elements_length, | 4594 __ Add(elements_length, elements_length, Smi::FromInt(kAllocationDelta)); |
4596 elements_length, | |
4597 Operand(Smi::FromInt(kAllocationDelta))); | |
4598 __ Str(elements_length, | 4595 __ Str(elements_length, |
4599 FieldMemOperand(elements, FixedArray::kLengthOffset)); | 4596 FieldMemOperand(elements, FixedArray::kLengthOffset)); |
4600 | 4597 |
4601 // Elements are in new space, so write barrier is not required. | 4598 // Elements are in new space, so write barrier is not required. |
4602 __ Drop(argc + 1); | 4599 __ Drop(argc + 1); |
4603 __ Mov(x0, length); | 4600 __ Mov(x0, length); |
4604 __ Ret(); | 4601 __ Ret(); |
4605 | 4602 |
4606 __ Bind(&call_builtin); | 4603 __ Bind(&call_builtin); |
4607 __ TailCallExternalReference( | 4604 __ TailCallExternalReference( |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4686 | 4683 |
4687 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { | 4684 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { |
4688 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); | 4685 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); |
4689 Register address = | 4686 Register address = |
4690 x0.Is(regs_.address()) ? regs_.scratch0() : regs_.address(); | 4687 x0.Is(regs_.address()) ? regs_.scratch0() : regs_.address(); |
4691 ASSERT(!address.Is(regs_.object())); | 4688 ASSERT(!address.Is(regs_.object())); |
4692 ASSERT(!address.Is(x0)); | 4689 ASSERT(!address.Is(x0)); |
4693 __ Mov(address, regs_.address()); | 4690 __ Mov(address, regs_.address()); |
4694 __ Mov(x0, regs_.object()); | 4691 __ Mov(x0, regs_.object()); |
4695 __ Mov(x1, address); | 4692 __ Mov(x1, address); |
4696 __ Mov(x2, Operand(ExternalReference::isolate_address(masm->isolate()))); | 4693 __ Mov(x2, ExternalReference::isolate_address(masm->isolate())); |
4697 | 4694 |
4698 AllowExternalCallThatCantCauseGC scope(masm); | 4695 AllowExternalCallThatCantCauseGC scope(masm); |
4699 ExternalReference function = | 4696 ExternalReference function = |
4700 ExternalReference::incremental_marking_record_write_function( | 4697 ExternalReference::incremental_marking_record_write_function( |
4701 masm->isolate()); | 4698 masm->isolate()); |
4702 __ CallCFunction(function, 3, 0); | 4699 __ CallCFunction(function, 3, 0); |
4703 | 4700 |
4704 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); | 4701 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); |
4705 } | 4702 } |
4706 | 4703 |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4941 reinterpret_cast<uintptr_t>(masm->isolate()->function_entry_hook()); | 4938 reinterpret_cast<uintptr_t>(masm->isolate()->function_entry_hook()); |
4942 __ Mov(x10, entry_hook); | 4939 __ Mov(x10, entry_hook); |
4943 #else | 4940 #else |
4944 // Under the simulator we need to indirect the entry hook through a trampoline | 4941 // Under the simulator we need to indirect the entry hook through a trampoline |
4945 // function at a known address. | 4942 // function at a known address. |
4946 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); | 4943 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); |
4947 __ Mov(x10, Operand(ExternalReference(&dispatcher, | 4944 __ Mov(x10, Operand(ExternalReference(&dispatcher, |
4948 ExternalReference::BUILTIN_CALL, | 4945 ExternalReference::BUILTIN_CALL, |
4949 masm->isolate()))); | 4946 masm->isolate()))); |
4950 // It additionally takes an isolate as a third parameter | 4947 // It additionally takes an isolate as a third parameter |
4951 __ Mov(x2, Operand(ExternalReference::isolate_address(masm->isolate()))); | 4948 __ Mov(x2, ExternalReference::isolate_address(masm->isolate())); |
4952 #endif | 4949 #endif |
4953 | 4950 |
4954 // The caller's return address is above the saved temporaries. | 4951 // The caller's return address is above the saved temporaries. |
4955 // Grab its location for the second argument to the hook. | 4952 // Grab its location for the second argument to the hook. |
4956 __ Add(x1, __ StackPointer(), kNumSavedRegs * kPointerSize); | 4953 __ Add(x1, __ StackPointer(), kNumSavedRegs * kPointerSize); |
4957 | 4954 |
4958 { | 4955 { |
4959 // Create a dummy frame, as CallCFunction requires this. | 4956 // Create a dummy frame, as CallCFunction requires this. |
4960 FrameScope frame(masm, StackFrame::MANUAL); | 4957 FrameScope frame(masm, StackFrame::MANUAL); |
4961 __ CallCFunction(x10, 2, 0); | 4958 __ CallCFunction(x10, 2, 0); |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5328 &normal_sequence); | 5325 &normal_sequence); |
5329 __ Assert(eq, kExpectedAllocationSite); | 5326 __ Assert(eq, kExpectedAllocationSite); |
5330 } | 5327 } |
5331 | 5328 |
5332 // Save the resulting elements kind in type info. We can't just store 'kind' | 5329 // Save the resulting elements kind in type info. We can't just store 'kind' |
5333 // in the AllocationSite::transition_info field because elements kind is | 5330 // in the AllocationSite::transition_info field because elements kind is |
5334 // restricted to a portion of the field; upper bits need to be left alone. | 5331 // restricted to a portion of the field; upper bits need to be left alone. |
5335 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); | 5332 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); |
5336 __ Ldr(x11, FieldMemOperand(allocation_site, | 5333 __ Ldr(x11, FieldMemOperand(allocation_site, |
5337 AllocationSite::kTransitionInfoOffset)); | 5334 AllocationSite::kTransitionInfoOffset)); |
5338 __ Add(x11, x11, Operand(Smi::FromInt(kFastElementsKindPackedToHoley))); | 5335 __ Add(x11, x11, Smi::FromInt(kFastElementsKindPackedToHoley)); |
5339 __ Str(x11, FieldMemOperand(allocation_site, | 5336 __ Str(x11, FieldMemOperand(allocation_site, |
5340 AllocationSite::kTransitionInfoOffset)); | 5337 AllocationSite::kTransitionInfoOffset)); |
5341 | 5338 |
5342 __ Bind(&normal_sequence); | 5339 __ Bind(&normal_sequence); |
5343 int last_index = | 5340 int last_index = |
5344 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); | 5341 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
5345 for (int i = 0; i <= last_index; ++i) { | 5342 for (int i = 0; i <= last_index; ++i) { |
5346 Label next; | 5343 Label next; |
5347 ElementsKind candidate_kind = GetFastElementsKindFromSequenceIndex(i); | 5344 ElementsKind candidate_kind = GetFastElementsKindFromSequenceIndex(i); |
5348 __ CompareAndBranch(kind, candidate_kind, ne, &next); | 5345 __ CompareAndBranch(kind, candidate_kind, ne, &next); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5610 // FunctionCallbackArguments: context, callee and call data. | 5607 // FunctionCallbackArguments: context, callee and call data. |
5611 __ Push(context, callee, call_data); | 5608 __ Push(context, callee, call_data); |
5612 | 5609 |
5613 // Load context from callee | 5610 // Load context from callee |
5614 __ Ldr(context, FieldMemOperand(callee, JSFunction::kContextOffset)); | 5611 __ Ldr(context, FieldMemOperand(callee, JSFunction::kContextOffset)); |
5615 | 5612 |
5616 if (!call_data_undefined) { | 5613 if (!call_data_undefined) { |
5617 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); | 5614 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); |
5618 } | 5615 } |
5619 Register isolate_reg = x5; | 5616 Register isolate_reg = x5; |
5620 __ Mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate))); | 5617 __ Mov(isolate_reg, ExternalReference::isolate_address(isolate)); |
5621 | 5618 |
5622 // FunctionCallbackArguments: | 5619 // FunctionCallbackArguments: |
5623 // return value, return value default, isolate, holder. | 5620 // return value, return value default, isolate, holder. |
5624 __ Push(call_data, call_data, isolate_reg, holder); | 5621 __ Push(call_data, call_data, isolate_reg, holder); |
5625 | 5622 |
5626 // Prepare arguments. | 5623 // Prepare arguments. |
5627 Register args = x6; | 5624 Register args = x6; |
5628 __ Mov(args, masm->StackPointer()); | 5625 __ Mov(args, masm->StackPointer()); |
5629 | 5626 |
5630 // Allocate the v8::Arguments structure in the arguments' space, since it's | 5627 // Allocate the v8::Arguments structure in the arguments' space, since it's |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5723 MemOperand(fp, 6 * kPointerSize), | 5720 MemOperand(fp, 6 * kPointerSize), |
5724 NULL); | 5721 NULL); |
5725 } | 5722 } |
5726 | 5723 |
5727 | 5724 |
5728 #undef __ | 5725 #undef __ |
5729 | 5726 |
5730 } } // namespace v8::internal | 5727 } } // namespace v8::internal |
5731 | 5728 |
5732 #endif // V8_TARGET_ARCH_A64 | 5729 #endif // V8_TARGET_ARCH_A64 |
OLD | NEW |