OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #include "src/crankshaft/arm64/lithium-codegen-arm64.h" | 5 #include "src/crankshaft/arm64/lithium-codegen-arm64.h" |
6 | 6 |
7 #include "src/arm64/frames-arm64.h" | 7 #include "src/arm64/frames-arm64.h" |
8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 1510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1521 Label invoke, loop; | 1521 Label invoke, loop; |
1522 // length is a small non-negative integer, due to the test above. | 1522 // length is a small non-negative integer, due to the test above. |
1523 __ Cbz(length, &invoke); | 1523 __ Cbz(length, &invoke); |
1524 __ Bind(&loop); | 1524 __ Bind(&loop); |
1525 __ Ldr(scratch, MemOperand(elements, length, SXTW, kPointerSizeLog2)); | 1525 __ Ldr(scratch, MemOperand(elements, length, SXTW, kPointerSizeLog2)); |
1526 __ Push(scratch); | 1526 __ Push(scratch); |
1527 __ Subs(length, length, 1); | 1527 __ Subs(length, length, 1); |
1528 __ B(ne, &loop); | 1528 __ B(ne, &loop); |
1529 | 1529 |
1530 __ Bind(&invoke); | 1530 __ Bind(&invoke); |
| 1531 |
| 1532 InvokeFlag flag = CALL_FUNCTION; |
| 1533 if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) { |
| 1534 // TODO(ishell): drop current frame before pushing arguments to the stack. |
| 1535 flag = JUMP_FUNCTION; |
| 1536 ParameterCount actual(x0); |
| 1537 // It is safe to use x3, x4 and x5 as scratch registers here given that |
| 1538 // 1) we are not going to return to caller function anyway, |
| 1539 // 2) x3 (new.target) will be initialized below. |
| 1540 PrepareForTailCall(actual, x3, x4, x5); |
| 1541 } |
| 1542 |
1531 DCHECK(instr->HasPointerMap()); | 1543 DCHECK(instr->HasPointerMap()); |
1532 LPointerMap* pointers = instr->pointer_map(); | 1544 LPointerMap* pointers = instr->pointer_map(); |
1533 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); | 1545 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); |
1534 // The number of arguments is stored in argc (receiver) which is x0, as | 1546 // The number of arguments is stored in argc (receiver) which is x0, as |
1535 // expected by InvokeFunction. | 1547 // expected by InvokeFunction. |
1536 ParameterCount actual(argc); | 1548 ParameterCount actual(argc); |
1537 __ InvokeFunction(function, no_reg, actual, CALL_FUNCTION, | 1549 __ InvokeFunction(function, no_reg, actual, flag, safepoint_generator); |
1538 safepoint_generator); | |
1539 } | 1550 } |
1540 | 1551 |
1541 | 1552 |
1542 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 1553 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
1543 Register result = ToRegister(instr->result()); | 1554 Register result = ToRegister(instr->result()); |
1544 | 1555 |
1545 if (instr->hydrogen()->from_inlined()) { | 1556 if (instr->hydrogen()->from_inlined()) { |
1546 // When we are inside an inlined function, the arguments are the last things | 1557 // When we are inside an inlined function, the arguments are the last things |
1547 // that have been pushed on the stack. Therefore the arguments array can be | 1558 // that have been pushed on the stack. Therefore the arguments array can be |
1548 // accessed directly from jssp. | 1559 // accessed directly from jssp. |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1829 | 1840 |
1830 if (!expected.IsGeneric()) { | 1841 if (!expected.IsGeneric()) { |
1831 // We've seen something for the first time -> deopt. | 1842 // We've seen something for the first time -> deopt. |
1832 // This can only happen if we are not generic already. | 1843 // This can only happen if we are not generic already. |
1833 Deoptimize(instr, Deoptimizer::kUnexpectedObject); | 1844 Deoptimize(instr, Deoptimizer::kUnexpectedObject); |
1834 } | 1845 } |
1835 } | 1846 } |
1836 } | 1847 } |
1837 } | 1848 } |
1838 | 1849 |
1839 | |
1840 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 1850 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
1841 int formal_parameter_count, int arity, | 1851 int formal_parameter_count, int arity, |
1842 LInstruction* instr) { | 1852 bool is_tail_call, LInstruction* instr) { |
1843 bool dont_adapt_arguments = | 1853 bool dont_adapt_arguments = |
1844 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 1854 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
1845 bool can_invoke_directly = | 1855 bool can_invoke_directly = |
1846 dont_adapt_arguments || formal_parameter_count == arity; | 1856 dont_adapt_arguments || formal_parameter_count == arity; |
1847 | 1857 |
1848 // The function interface relies on the following register assignments. | 1858 // The function interface relies on the following register assignments. |
1849 Register function_reg = x1; | 1859 Register function_reg = x1; |
1850 Register arity_reg = x0; | 1860 Register arity_reg = x0; |
1851 | 1861 |
1852 LPointerMap* pointers = instr->pointer_map(); | 1862 LPointerMap* pointers = instr->pointer_map(); |
1853 | 1863 |
1854 if (FLAG_debug_code) { | 1864 if (FLAG_debug_code) { |
1855 Label is_not_smi; | 1865 Label is_not_smi; |
1856 // Try to confirm that function_reg (x1) is a tagged pointer. | 1866 // Try to confirm that function_reg (x1) is a tagged pointer. |
1857 __ JumpIfNotSmi(function_reg, &is_not_smi); | 1867 __ JumpIfNotSmi(function_reg, &is_not_smi); |
1858 __ Abort(kExpectedFunctionObject); | 1868 __ Abort(kExpectedFunctionObject); |
1859 __ Bind(&is_not_smi); | 1869 __ Bind(&is_not_smi); |
1860 } | 1870 } |
1861 | 1871 |
1862 if (can_invoke_directly) { | 1872 if (can_invoke_directly) { |
1863 // Change context. | 1873 // Change context. |
1864 __ Ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); | 1874 __ Ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); |
1865 | 1875 |
1866 // Always initialize new target and number of actual arguments. | 1876 // Always initialize new target and number of actual arguments. |
1867 __ LoadRoot(x3, Heap::kUndefinedValueRootIndex); | 1877 __ LoadRoot(x3, Heap::kUndefinedValueRootIndex); |
1868 __ Mov(arity_reg, arity); | 1878 __ Mov(arity_reg, arity); |
1869 | 1879 |
| 1880 bool is_self_call = function.is_identical_to(info()->closure()); |
| 1881 |
1870 // Invoke function. | 1882 // Invoke function. |
1871 __ Ldr(x10, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); | 1883 if (is_self_call) { |
1872 __ Call(x10); | 1884 Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location())); |
| 1885 if (is_tail_call) { |
| 1886 __ Jump(self, RelocInfo::CODE_TARGET); |
| 1887 } else { |
| 1888 __ Call(self, RelocInfo::CODE_TARGET); |
| 1889 } |
| 1890 } else { |
| 1891 __ Ldr(x10, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); |
| 1892 if (is_tail_call) { |
| 1893 __ Jump(x10); |
| 1894 } else { |
| 1895 __ Call(x10); |
| 1896 } |
| 1897 } |
1873 | 1898 |
1874 // Set up deoptimization. | 1899 if (!is_tail_call) { |
1875 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 1900 // Set up deoptimization. |
| 1901 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 1902 } |
1876 } else { | 1903 } else { |
1877 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 1904 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
1878 ParameterCount count(arity); | 1905 ParameterCount actual(arity); |
1879 ParameterCount expected(formal_parameter_count); | 1906 ParameterCount expected(formal_parameter_count); |
1880 __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator); | 1907 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION; |
| 1908 __ InvokeFunction(function_reg, expected, actual, flag, generator); |
1881 } | 1909 } |
1882 } | 1910 } |
1883 | 1911 |
1884 | |
1885 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { | 1912 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
1886 DCHECK(instr->IsMarkedAsCall()); | 1913 DCHECK(instr->IsMarkedAsCall()); |
1887 DCHECK(ToRegister(instr->result()).Is(x0)); | 1914 DCHECK(ToRegister(instr->result()).Is(x0)); |
1888 | 1915 |
1889 if (instr->hydrogen()->IsTailCall()) { | 1916 if (instr->hydrogen()->IsTailCall()) { |
1890 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL); | 1917 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL); |
1891 | 1918 |
1892 if (instr->target()->IsConstantOperand()) { | 1919 if (instr->target()->IsConstantOperand()) { |
1893 LConstantOperand* target = LConstantOperand::cast(instr->target()); | 1920 LConstantOperand* target = LConstantOperand::cast(instr->target()); |
1894 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); | 1921 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); |
(...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2779 DoGap(instr); | 2806 DoGap(instr); |
2780 } | 2807 } |
2781 | 2808 |
2782 | 2809 |
2783 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 2810 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
2784 Register value = ToRegister32(instr->value()); | 2811 Register value = ToRegister32(instr->value()); |
2785 DoubleRegister result = ToDoubleRegister(instr->result()); | 2812 DoubleRegister result = ToDoubleRegister(instr->result()); |
2786 __ Scvtf(result, value); | 2813 __ Scvtf(result, value); |
2787 } | 2814 } |
2788 | 2815 |
| 2816 void LCodeGen::PrepareForTailCall(const ParameterCount& actual, |
| 2817 Register scratch1, Register scratch2, |
| 2818 Register scratch3) { |
| 2819 #if DEBUG |
| 2820 if (actual.is_reg()) { |
| 2821 DCHECK(!AreAliased(actual.reg(), scratch1, scratch2, scratch3)); |
| 2822 } else { |
| 2823 DCHECK(!AreAliased(scratch1, scratch2, scratch3)); |
| 2824 } |
| 2825 #endif |
| 2826 if (FLAG_code_comments) { |
| 2827 if (actual.is_reg()) { |
| 2828 Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString()); |
| 2829 } else { |
| 2830 Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate()); |
| 2831 } |
| 2832 } |
| 2833 |
| 2834 // Check if next frame is an arguments adaptor frame. |
| 2835 Register caller_args_count_reg = scratch1; |
| 2836 Label no_arguments_adaptor, formal_parameter_count_loaded; |
| 2837 __ Ldr(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 2838 __ Ldr(scratch3, |
| 2839 MemOperand(scratch2, StandardFrameConstants::kContextOffset)); |
| 2840 __ Cmp(scratch3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 2841 __ B(ne, &no_arguments_adaptor); |
| 2842 |
| 2843 // Drop current frame and load arguments count from arguments adaptor frame. |
| 2844 __ mov(fp, scratch2); |
| 2845 __ Ldr(caller_args_count_reg, |
| 2846 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2847 __ SmiUntag(caller_args_count_reg); |
| 2848 __ B(&formal_parameter_count_loaded); |
| 2849 |
| 2850 __ bind(&no_arguments_adaptor); |
| 2851 // Load caller's formal parameter count |
| 2852 __ Mov(caller_args_count_reg, |
| 2853 Immediate(info()->literal()->parameter_count())); |
| 2854 |
| 2855 __ bind(&formal_parameter_count_loaded); |
| 2856 __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3); |
| 2857 |
| 2858 Comment(";;; }"); |
| 2859 } |
2789 | 2860 |
2790 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 2861 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 2862 HInvokeFunction* hinstr = instr->hydrogen(); |
2791 DCHECK(ToRegister(instr->context()).is(cp)); | 2863 DCHECK(ToRegister(instr->context()).is(cp)); |
2792 // The function is required to be in x1. | 2864 // The function is required to be in x1. |
2793 DCHECK(ToRegister(instr->function()).is(x1)); | 2865 DCHECK(ToRegister(instr->function()).is(x1)); |
2794 DCHECK(instr->HasPointerMap()); | 2866 DCHECK(instr->HasPointerMap()); |
2795 | 2867 |
2796 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 2868 bool is_tail_call = hinstr->tail_call_mode() == TailCallMode::kAllow; |
| 2869 |
| 2870 if (is_tail_call) { |
| 2871 ParameterCount actual(instr->arity()); |
| 2872 // It is safe to use x3, x4 and x5 as scratch registers here given that |
| 2873 // 1) we are not going to return to caller function anyway, |
| 2874 // 2) x3 (new.target) will be initialized below. |
| 2875 PrepareForTailCall(actual, x3, x4, x5); |
| 2876 } |
| 2877 |
| 2878 Handle<JSFunction> known_function = hinstr->known_function(); |
2797 if (known_function.is_null()) { | 2879 if (known_function.is_null()) { |
2798 LPointerMap* pointers = instr->pointer_map(); | 2880 LPointerMap* pointers = instr->pointer_map(); |
2799 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 2881 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
2800 ParameterCount count(instr->arity()); | 2882 ParameterCount actual(instr->arity()); |
2801 __ InvokeFunction(x1, no_reg, count, CALL_FUNCTION, generator); | 2883 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION; |
| 2884 __ InvokeFunction(x1, no_reg, actual, flag, generator); |
2802 } else { | 2885 } else { |
2803 CallKnownFunction(known_function, | 2886 CallKnownFunction(known_function, hinstr->formal_parameter_count(), |
2804 instr->hydrogen()->formal_parameter_count(), | 2887 instr->arity(), is_tail_call, instr); |
2805 instr->arity(), instr); | |
2806 } | 2888 } |
2807 RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta()); | 2889 RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta()); |
2808 } | 2890 } |
2809 | 2891 |
2810 | 2892 |
2811 Condition LCodeGen::EmitIsString(Register input, | 2893 Condition LCodeGen::EmitIsString(Register input, |
2812 Register temp1, | 2894 Register temp1, |
2813 Label* is_not_string, | 2895 Label* is_not_string, |
2814 SmiCheck check_needed = INLINE_SMI_CHECK) { | 2896 SmiCheck check_needed = INLINE_SMI_CHECK) { |
2815 if (check_needed == INLINE_SMI_CHECK) { | 2897 if (check_needed == INLINE_SMI_CHECK) { |
(...skipping 2845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5661 | 5743 |
5662 | 5744 |
5663 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { | 5745 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { |
5664 Register context = ToRegister(instr->context()); | 5746 Register context = ToRegister(instr->context()); |
5665 __ Str(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 5747 __ Str(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
5666 } | 5748 } |
5667 | 5749 |
5668 | 5750 |
5669 } // namespace internal | 5751 } // namespace internal |
5670 } // namespace v8 | 5752 } // namespace v8 |
OLD | NEW |