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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 2069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2080 | 2080 |
2081 // Unreachable. | 2081 // Unreachable. |
2082 __ int3(); | 2082 __ int3(); |
2083 } | 2083 } |
2084 | 2084 |
2085 | 2085 |
2086 void CallICStub::Generate(MacroAssembler* masm) { | 2086 void CallICStub::Generate(MacroAssembler* masm) { |
2087 // rdi - function | 2087 // rdi - function |
2088 // rdx - slot id | 2088 // rdx - slot id |
2089 Isolate* isolate = masm->isolate(); | 2089 Isolate* isolate = masm->isolate(); |
| 2090 const int with_types_offset = |
| 2091 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); |
| 2092 const int generic_offset = |
| 2093 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); |
2090 Label extra_checks_or_miss, slow_start; | 2094 Label extra_checks_or_miss, slow_start; |
2091 Label slow, non_function, wrap, cont; | 2095 Label slow, non_function, wrap, cont; |
2092 Label have_js_function; | 2096 Label have_js_function; |
2093 int argc = arg_count(); | 2097 int argc = arg_count(); |
2094 StackArgumentsAccessor args(rsp, argc); | 2098 StackArgumentsAccessor args(rsp, argc); |
2095 ParameterCount actual(argc); | 2099 ParameterCount actual(argc); |
2096 | 2100 |
2097 EmitLoadTypeFeedbackVector(masm, rbx); | 2101 EmitLoadTypeFeedbackVector(masm, rbx); |
2098 | 2102 |
2099 // The checks. First, does rdi match the recorded monomorphic target? | 2103 // The checks. First, does rdi match the recorded monomorphic target? |
(...skipping 21 matching lines...) Expand all Loading... |
2121 | 2125 |
2122 __ bind(&slow); | 2126 __ bind(&slow); |
2123 EmitSlowCase(isolate, masm, &args, argc, &non_function); | 2127 EmitSlowCase(isolate, masm, &args, argc, &non_function); |
2124 | 2128 |
2125 if (CallAsMethod()) { | 2129 if (CallAsMethod()) { |
2126 __ bind(&wrap); | 2130 __ bind(&wrap); |
2127 EmitWrapCase(masm, &args, &cont); | 2131 EmitWrapCase(masm, &args, &cont); |
2128 } | 2132 } |
2129 | 2133 |
2130 __ bind(&extra_checks_or_miss); | 2134 __ bind(&extra_checks_or_miss); |
2131 Label miss; | 2135 Label uninitialized, miss; |
2132 | 2136 |
2133 __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, | 2137 __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, |
2134 FixedArray::kHeaderSize)); | 2138 FixedArray::kHeaderSize)); |
2135 __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate)); | 2139 __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate)); |
2136 __ j(equal, &slow_start); | 2140 __ j(equal, &slow_start); |
| 2141 |
| 2142 // The following cases attempt to handle MISS cases without going to the |
| 2143 // runtime. |
| 2144 if (FLAG_trace_ic) { |
| 2145 __ jmp(&miss); |
| 2146 } |
| 2147 |
2137 __ Cmp(rcx, TypeFeedbackVector::UninitializedSentinel(isolate)); | 2148 __ Cmp(rcx, TypeFeedbackVector::UninitializedSentinel(isolate)); |
| 2149 __ j(equal, &uninitialized); |
| 2150 |
| 2151 // We are going megamorphic. If the feedback is a JSFunction, it is fine |
| 2152 // to handle it here. More complex cases are dealt with in the runtime. |
| 2153 __ AssertNotSmi(rcx); |
| 2154 __ CmpObjectType(rcx, JS_FUNCTION_TYPE, rcx); |
| 2155 __ j(not_equal, &miss); |
| 2156 __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), |
| 2157 TypeFeedbackVector::MegamorphicSentinel(isolate)); |
| 2158 // We have to update statistics for runtime profiling. |
| 2159 __ SmiAddConstant(FieldOperand(rbx, with_types_offset), Smi::FromInt(-1)); |
| 2160 __ SmiAddConstant(FieldOperand(rbx, generic_offset), Smi::FromInt(1)); |
| 2161 __ jmp(&slow_start); |
| 2162 |
| 2163 __ bind(&uninitialized); |
| 2164 |
| 2165 // We are going monomorphic, provided we actually have a JSFunction. |
| 2166 __ JumpIfSmi(rdi, &miss); |
| 2167 |
| 2168 // Goto miss case if we do not have a function. |
| 2169 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
| 2170 __ j(not_equal, &miss); |
| 2171 |
| 2172 // Make sure the function is not the Array() function, which requires special |
| 2173 // behavior on MISS. |
| 2174 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx); |
| 2175 __ cmpp(rdi, rcx); |
2138 __ j(equal, &miss); | 2176 __ j(equal, &miss); |
2139 | 2177 |
2140 if (!FLAG_trace_ic) { | 2178 // Update stats. |
2141 // We are going megamorphic. If the feedback is a JSFunction, it is fine | 2179 __ SmiAddConstant(FieldOperand(rbx, with_types_offset), Smi::FromInt(1)); |
2142 // to handle it here. More complex cases are dealt with in the runtime. | |
2143 __ AssertNotSmi(rcx); | |
2144 __ CmpObjectType(rcx, JS_FUNCTION_TYPE, rcx); | |
2145 __ j(not_equal, &miss); | |
2146 __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), | |
2147 TypeFeedbackVector::MegamorphicSentinel(isolate)); | |
2148 // We have to update statistics for runtime profiling. | |
2149 const int with_types_offset = | |
2150 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); | |
2151 __ SmiAddConstant(FieldOperand(rbx, with_types_offset), Smi::FromInt(-1)); | |
2152 const int generic_offset = | |
2153 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); | |
2154 __ SmiAddConstant(FieldOperand(rbx, generic_offset), Smi::FromInt(1)); | |
2155 __ jmp(&slow_start); | |
2156 } | |
2157 | 2180 |
2158 // We are here because tracing is on or we are going monomorphic. | 2181 // Store the function. |
| 2182 __ movp(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), |
| 2183 rdi); |
| 2184 |
| 2185 // Update the write barrier. |
| 2186 __ movp(rax, rdi); |
| 2187 __ RecordWriteArray(rbx, rax, rdx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |
| 2188 OMIT_SMI_CHECK); |
| 2189 __ jmp(&have_js_function); |
| 2190 |
| 2191 // We are here because tracing is on or we encountered a MISS case we can't |
| 2192 // handle here. |
2159 __ bind(&miss); | 2193 __ bind(&miss); |
2160 GenerateMiss(masm); | 2194 GenerateMiss(masm); |
2161 | 2195 |
2162 // the slow case | 2196 // the slow case |
2163 __ bind(&slow_start); | 2197 __ bind(&slow_start); |
2164 // Check that function is not a smi. | 2198 // Check that function is not a smi. |
2165 __ JumpIfSmi(rdi, &non_function); | 2199 __ JumpIfSmi(rdi, &non_function); |
2166 // Check that function is a JSFunction. | 2200 // Check that function is a JSFunction. |
2167 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2201 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2168 __ j(not_equal, &slow); | 2202 __ j(not_equal, &slow); |
(...skipping 2538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4707 return_value_operand, | 4741 return_value_operand, |
4708 NULL); | 4742 NULL); |
4709 } | 4743 } |
4710 | 4744 |
4711 | 4745 |
4712 #undef __ | 4746 #undef __ |
4713 | 4747 |
4714 } } // namespace v8::internal | 4748 } } // namespace v8::internal |
4715 | 4749 |
4716 #endif // V8_TARGET_ARCH_X64 | 4750 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |