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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 1977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1988 __ Ldr(x4, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); | 1988 __ Ldr(x4, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); |
1989 __ Ldr(x4, FieldMemOperand(x4, SharedFunctionInfo::kConstructStubOffset)); | 1989 __ Ldr(x4, FieldMemOperand(x4, SharedFunctionInfo::kConstructStubOffset)); |
1990 __ Add(x4, x4, Code::kHeaderSize - kHeapObjectTag); | 1990 __ Add(x4, x4, Code::kHeaderSize - kHeapObjectTag); |
1991 __ Br(x4); | 1991 __ Br(x4); |
1992 | 1992 |
1993 __ Bind(&non_function); | 1993 __ Bind(&non_function); |
1994 __ Mov(x3, function); | 1994 __ Mov(x3, function); |
1995 __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 1995 __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
1996 } | 1996 } |
1997 | 1997 |
| 1998 // Note: feedback_vector and slot are clobbered after the call. |
| 1999 static void IncrementCallCount(MacroAssembler* masm, Register feedback_vector, |
| 2000 Register slot) { |
| 2001 __ Add(feedback_vector, feedback_vector, |
| 2002 Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); |
| 2003 __ Add(feedback_vector, feedback_vector, |
| 2004 Operand(FixedArray::kHeaderSize + kPointerSize)); |
| 2005 __ Ldr(slot, FieldMemOperand(feedback_vector, 0)); |
| 2006 __ Add(slot, slot, Operand(Smi::FromInt(1))); |
| 2007 __ Str(slot, FieldMemOperand(feedback_vector, 0)); |
| 2008 } |
1998 | 2009 |
1999 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { | 2010 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { |
2000 // x1 - function | 2011 // x1 - function |
2001 // x3 - slot id | 2012 // x3 - slot id |
2002 // x2 - vector | 2013 // x2 - vector |
2003 // x4 - allocation site (loaded from vector[slot]) | 2014 // x4 - allocation site (loaded from vector[slot]) |
2004 Register function = x1; | 2015 Register function = x1; |
2005 Register feedback_vector = x2; | 2016 Register feedback_vector = x2; |
2006 Register index = x3; | 2017 Register index = x3; |
2007 Register allocation_site = x4; | 2018 Register allocation_site = x4; |
2008 Register scratch = x5; | 2019 Register scratch = x5; |
2009 | 2020 |
2010 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, scratch); | 2021 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, scratch); |
2011 __ Cmp(function, scratch); | 2022 __ Cmp(function, scratch); |
2012 __ B(ne, miss); | 2023 __ B(ne, miss); |
2013 | 2024 |
2014 __ Mov(x0, Operand(arg_count())); | 2025 __ Mov(x0, Operand(arg_count())); |
2015 | 2026 |
2016 // Increment the call count for monomorphic function calls. | 2027 // Increment the call count for monomorphic function calls. |
2017 __ Add(feedback_vector, feedback_vector, | 2028 IncrementCallCount(masm, feedback_vector, index); |
2018 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | |
2019 __ Add(feedback_vector, feedback_vector, | |
2020 Operand(FixedArray::kHeaderSize + kPointerSize)); | |
2021 __ Ldr(index, FieldMemOperand(feedback_vector, 0)); | |
2022 __ Add(index, index, Operand(Smi::FromInt(1))); | |
2023 __ Str(index, FieldMemOperand(feedback_vector, 0)); | |
2024 | 2029 |
2025 // Set up arguments for the array constructor stub. | 2030 // Set up arguments for the array constructor stub. |
2026 Register allocation_site_arg = feedback_vector; | 2031 Register allocation_site_arg = feedback_vector; |
2027 Register new_target_arg = index; | 2032 Register new_target_arg = index; |
2028 __ Mov(allocation_site_arg, allocation_site); | 2033 __ Mov(allocation_site_arg, allocation_site); |
2029 __ Mov(new_target_arg, function); | 2034 __ Mov(new_target_arg, function); |
2030 ArrayConstructorStub stub(masm->isolate(), arg_count()); | 2035 ArrayConstructorStub stub(masm->isolate(), arg_count()); |
2031 __ TailCallStub(&stub); | 2036 __ TailCallStub(&stub); |
2032 } | 2037 } |
2033 | 2038 |
2034 | 2039 |
2035 void CallICStub::Generate(MacroAssembler* masm) { | 2040 void CallICStub::Generate(MacroAssembler* masm) { |
2036 ASM_LOCATION("CallICStub"); | 2041 ASM_LOCATION("CallICStub"); |
2037 | 2042 |
2038 // x1 - function | 2043 // x1 - function |
2039 // x3 - slot id (Smi) | 2044 // x3 - slot id (Smi) |
2040 // x2 - vector | 2045 // x2 - vector |
2041 Label extra_checks_or_miss, call, call_function; | 2046 Label extra_checks_or_miss, call, call_function, call_count_incremented; |
2042 int argc = arg_count(); | 2047 int argc = arg_count(); |
2043 ParameterCount actual(argc); | 2048 ParameterCount actual(argc); |
2044 | 2049 |
2045 Register function = x1; | 2050 Register function = x1; |
2046 Register feedback_vector = x2; | 2051 Register feedback_vector = x2; |
2047 Register index = x3; | 2052 Register index = x3; |
2048 | 2053 |
2049 // The checks. First, does x1 match the recorded monomorphic target? | 2054 // The checks. First, does x1 match the recorded monomorphic target? |
2050 __ Add(x4, feedback_vector, | 2055 __ Add(x4, feedback_vector, |
2051 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 2056 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
(...skipping 14 matching lines...) Expand all Loading... |
2066 WeakCell::kValueOffset == Symbol::kHashFieldSlot); | 2071 WeakCell::kValueOffset == Symbol::kHashFieldSlot); |
2067 | 2072 |
2068 __ Ldr(x5, FieldMemOperand(x4, WeakCell::kValueOffset)); | 2073 __ Ldr(x5, FieldMemOperand(x4, WeakCell::kValueOffset)); |
2069 __ Cmp(x5, function); | 2074 __ Cmp(x5, function); |
2070 __ B(ne, &extra_checks_or_miss); | 2075 __ B(ne, &extra_checks_or_miss); |
2071 | 2076 |
2072 // The compare above could have been a SMI/SMI comparison. Guard against this | 2077 // The compare above could have been a SMI/SMI comparison. Guard against this |
2073 // convincing us that we have a monomorphic JSFunction. | 2078 // convincing us that we have a monomorphic JSFunction. |
2074 __ JumpIfSmi(function, &extra_checks_or_miss); | 2079 __ JumpIfSmi(function, &extra_checks_or_miss); |
2075 | 2080 |
| 2081 __ Bind(&call_function); |
| 2082 |
2076 // Increment the call count for monomorphic function calls. | 2083 // Increment the call count for monomorphic function calls. |
2077 __ Add(feedback_vector, feedback_vector, | 2084 IncrementCallCount(masm, feedback_vector, index); |
2078 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | |
2079 __ Add(feedback_vector, feedback_vector, | |
2080 Operand(FixedArray::kHeaderSize + kPointerSize)); | |
2081 __ Ldr(index, FieldMemOperand(feedback_vector, 0)); | |
2082 __ Add(index, index, Operand(Smi::FromInt(1))); | |
2083 __ Str(index, FieldMemOperand(feedback_vector, 0)); | |
2084 | 2085 |
2085 __ Bind(&call_function); | |
2086 __ Mov(x0, argc); | 2086 __ Mov(x0, argc); |
2087 __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), | 2087 __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), |
2088 tail_call_mode()), | 2088 tail_call_mode()), |
2089 RelocInfo::CODE_TARGET); | 2089 RelocInfo::CODE_TARGET); |
2090 | 2090 |
2091 __ bind(&extra_checks_or_miss); | 2091 __ bind(&extra_checks_or_miss); |
2092 Label uninitialized, miss, not_allocation_site; | 2092 Label uninitialized, miss, not_allocation_site; |
2093 | 2093 |
2094 __ JumpIfRoot(x4, Heap::kmegamorphic_symbolRootIndex, &call); | 2094 __ JumpIfRoot(x4, Heap::kmegamorphic_symbolRootIndex, &call); |
2095 | 2095 |
2096 __ Ldr(x5, FieldMemOperand(x4, HeapObject::kMapOffset)); | 2096 __ Ldr(x5, FieldMemOperand(x4, HeapObject::kMapOffset)); |
2097 __ JumpIfNotRoot(x5, Heap::kAllocationSiteMapRootIndex, ¬_allocation_site); | 2097 __ JumpIfNotRoot(x5, Heap::kAllocationSiteMapRootIndex, ¬_allocation_site); |
2098 | 2098 |
2099 HandleArrayCase(masm, &miss); | 2099 HandleArrayCase(masm, &miss); |
2100 | 2100 |
2101 __ bind(¬_allocation_site); | 2101 __ bind(¬_allocation_site); |
2102 | 2102 |
2103 // The following cases attempt to handle MISS cases without going to the | 2103 // The following cases attempt to handle MISS cases without going to the |
2104 // runtime. | 2104 // runtime. |
2105 if (FLAG_trace_ic) { | 2105 if (FLAG_trace_ic) { |
2106 __ jmp(&miss); | 2106 __ jmp(&miss); |
2107 } | 2107 } |
2108 | 2108 |
| 2109 // TODO(mvstanton): the code below is effectively disabled. Investigate. |
2109 __ JumpIfRoot(x4, Heap::kuninitialized_symbolRootIndex, &miss); | 2110 __ JumpIfRoot(x4, Heap::kuninitialized_symbolRootIndex, &miss); |
2110 | 2111 |
2111 // We are going megamorphic. If the feedback is a JSFunction, it is fine | 2112 // We are going megamorphic. If the feedback is a JSFunction, it is fine |
2112 // to handle it here. More complex cases are dealt with in the runtime. | 2113 // to handle it here. More complex cases are dealt with in the runtime. |
2113 __ AssertNotSmi(x4); | 2114 __ AssertNotSmi(x4); |
2114 __ JumpIfNotObjectType(x4, x5, x5, JS_FUNCTION_TYPE, &miss); | 2115 __ JumpIfNotObjectType(x4, x5, x5, JS_FUNCTION_TYPE, &miss); |
2115 __ Add(x4, feedback_vector, | 2116 __ Add(x4, feedback_vector, |
2116 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 2117 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
2117 __ LoadRoot(x5, Heap::kmegamorphic_symbolRootIndex); | 2118 __ LoadRoot(x5, Heap::kmegamorphic_symbolRootIndex); |
2118 __ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize)); | 2119 __ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize)); |
2119 | 2120 |
2120 __ Bind(&call); | 2121 __ Bind(&call); |
| 2122 |
| 2123 // Increment the call count for megamorphic function calls. |
| 2124 IncrementCallCount(masm, feedback_vector, index); |
| 2125 |
| 2126 __ Bind(&call_count_incremented); |
2121 __ Mov(x0, argc); | 2127 __ Mov(x0, argc); |
2122 __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), | 2128 __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), |
2123 RelocInfo::CODE_TARGET); | 2129 RelocInfo::CODE_TARGET); |
2124 | 2130 |
2125 __ bind(&uninitialized); | 2131 __ bind(&uninitialized); |
2126 | 2132 |
2127 // We are going monomorphic, provided we actually have a JSFunction. | 2133 // We are going monomorphic, provided we actually have a JSFunction. |
2128 __ JumpIfSmi(function, &miss); | 2134 __ JumpIfSmi(function, &miss); |
2129 | 2135 |
2130 // Goto miss case if we do not have a function. | 2136 // Goto miss case if we do not have a function. |
2131 __ JumpIfNotObjectType(function, x5, x5, JS_FUNCTION_TYPE, &miss); | 2137 __ JumpIfNotObjectType(function, x5, x5, JS_FUNCTION_TYPE, &miss); |
2132 | 2138 |
2133 // Make sure the function is not the Array() function, which requires special | 2139 // Make sure the function is not the Array() function, which requires special |
2134 // behavior on MISS. | 2140 // behavior on MISS. |
2135 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, x5); | 2141 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, x5); |
2136 __ Cmp(function, x5); | 2142 __ Cmp(function, x5); |
2137 __ B(eq, &miss); | 2143 __ B(eq, &miss); |
2138 | 2144 |
2139 // Make sure the function belongs to the same native context. | 2145 // Make sure the function belongs to the same native context. |
2140 __ Ldr(x4, FieldMemOperand(function, JSFunction::kContextOffset)); | 2146 __ Ldr(x4, FieldMemOperand(function, JSFunction::kContextOffset)); |
2141 __ Ldr(x4, ContextMemOperand(x4, Context::NATIVE_CONTEXT_INDEX)); | 2147 __ Ldr(x4, ContextMemOperand(x4, Context::NATIVE_CONTEXT_INDEX)); |
2142 __ Ldr(x5, NativeContextMemOperand()); | 2148 __ Ldr(x5, NativeContextMemOperand()); |
2143 __ Cmp(x4, x5); | 2149 __ Cmp(x4, x5); |
2144 __ B(ne, &miss); | 2150 __ B(ne, &miss); |
2145 | 2151 |
2146 // Initialize the call counter. | |
2147 __ Mov(x5, Smi::FromInt(1)); | |
2148 __ Adds(x4, feedback_vector, | |
2149 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | |
2150 __ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize + kPointerSize)); | |
2151 | |
2152 // Store the function. Use a stub since we need a frame for allocation. | 2152 // Store the function. Use a stub since we need a frame for allocation. |
2153 // x2 - vector | 2153 // x2 - vector |
2154 // x3 - slot | 2154 // x3 - slot |
2155 // x1 - function | 2155 // x1 - function |
2156 { | 2156 { |
2157 FrameScope scope(masm, StackFrame::INTERNAL); | 2157 FrameScope scope(masm, StackFrame::INTERNAL); |
2158 CreateWeakCellStub create_stub(masm->isolate()); | 2158 CreateWeakCellStub create_stub(masm->isolate()); |
| 2159 __ Push(feedback_vector, index); |
| 2160 |
2159 __ Push(cp, function); | 2161 __ Push(cp, function); |
2160 __ CallStub(&create_stub); | 2162 __ CallStub(&create_stub); |
2161 __ Pop(cp, function); | 2163 __ Pop(cp, function); |
| 2164 |
| 2165 __ Pop(feedback_vector, index); |
2162 } | 2166 } |
2163 | 2167 |
2164 __ B(&call_function); | 2168 __ B(&call_function); |
2165 | 2169 |
2166 // We are here because tracing is on or we encountered a MISS case we can't | 2170 // We are here because tracing is on or we encountered a MISS case we can't |
2167 // handle here. | 2171 // handle here. |
2168 __ bind(&miss); | 2172 __ bind(&miss); |
2169 GenerateMiss(masm); | 2173 GenerateMiss(masm); |
2170 | 2174 |
2171 __ B(&call); | 2175 // The runtime increments the call count in the vector for us. |
| 2176 __ B(&call_count_incremented); |
2172 } | 2177 } |
2173 | 2178 |
2174 | 2179 |
2175 void CallICStub::GenerateMiss(MacroAssembler* masm) { | 2180 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
2176 ASM_LOCATION("CallICStub[Miss]"); | 2181 ASM_LOCATION("CallICStub[Miss]"); |
2177 | 2182 |
2178 FrameScope scope(masm, StackFrame::INTERNAL); | 2183 FrameScope scope(masm, StackFrame::INTERNAL); |
2179 | 2184 |
2180 // Push the receiver and the function and feedback info. | 2185 // Push the receiver and the function and feedback info. |
2181 __ Push(x1, x2, x3); | 2186 __ Push(x1, x2, x3); |
(...skipping 3360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5542 kStackUnwindSpace, NULL, spill_offset, | 5547 kStackUnwindSpace, NULL, spill_offset, |
5543 return_value_operand, NULL); | 5548 return_value_operand, NULL); |
5544 } | 5549 } |
5545 | 5550 |
5546 #undef __ | 5551 #undef __ |
5547 | 5552 |
5548 } // namespace internal | 5553 } // namespace internal |
5549 } // namespace v8 | 5554 } // namespace v8 |
5550 | 5555 |
5551 #endif // V8_TARGET_ARCH_ARM64 | 5556 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |