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_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
(...skipping 1884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 __ j(not_equal, cont); | 1895 __ j(not_equal, cont); |
1896 | 1896 |
1897 // Do not transform the receiver for natives. | 1897 // Do not transform the receiver for natives. |
1898 // SharedFunctionInfo is already loaded into rcx. | 1898 // SharedFunctionInfo is already loaded into rcx. |
1899 __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset), | 1899 __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset), |
1900 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); | 1900 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); |
1901 __ j(not_equal, cont); | 1901 __ j(not_equal, cont); |
1902 } | 1902 } |
1903 | 1903 |
1904 | 1904 |
1905 static void EmitSlowCase(Isolate* isolate, | 1905 static void EmitSlowCase(MacroAssembler* masm, StackArgumentsAccessor* args, |
1906 MacroAssembler* masm, | 1906 int argc) { |
1907 StackArgumentsAccessor* args, | |
1908 int argc, | |
1909 Label* non_function) { | |
1910 // Check for function proxy. | |
1911 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | |
1912 __ j(not_equal, non_function); | |
1913 __ PopReturnAddressTo(rcx); | |
1914 __ Push(rdi); // put proxy as additional argument under return address | |
1915 __ PushReturnAddressFrom(rcx); | |
1916 __ Set(rax, argc + 1); | |
1917 __ Set(rbx, 0); | |
1918 __ GetBuiltinEntry(rdx, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX); | |
1919 { | |
1920 Handle<Code> adaptor = | |
1921 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | |
1922 __ jmp(adaptor, RelocInfo::CODE_TARGET); | |
1923 } | |
1924 | |
1925 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | |
1926 // of the original receiver from the call site). | |
1927 __ bind(non_function); | |
1928 __ movp(args->GetReceiverOperand(), rdi); | |
1929 __ Set(rax, argc); | 1907 __ Set(rax, argc); |
1930 __ Set(rbx, 0); | 1908 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1931 __ GetBuiltinEntry(rdx, Context::CALL_NON_FUNCTION_BUILTIN_INDEX); | |
1932 Handle<Code> adaptor = | |
1933 isolate->builtins()->ArgumentsAdaptorTrampoline(); | |
1934 __ Jump(adaptor, RelocInfo::CODE_TARGET); | |
1935 } | 1909 } |
1936 | 1910 |
1937 | 1911 |
1938 static void EmitWrapCase(MacroAssembler* masm, | 1912 static void EmitWrapCase(MacroAssembler* masm, |
1939 StackArgumentsAccessor* args, | 1913 StackArgumentsAccessor* args, |
1940 Label* cont) { | 1914 Label* cont) { |
1941 // Wrap the receiver and patch it back onto the stack. | 1915 // Wrap the receiver and patch it back onto the stack. |
1942 { FrameScope frame_scope(masm, StackFrame::INTERNAL); | 1916 { FrameScope frame_scope(masm, StackFrame::INTERNAL); |
1943 __ Push(rdi); | 1917 __ Push(rdi); |
1944 ToObjectStub stub(masm->isolate()); | 1918 ToObjectStub stub(masm->isolate()); |
1945 __ CallStub(&stub); | 1919 __ CallStub(&stub); |
1946 __ Pop(rdi); | 1920 __ Pop(rdi); |
1947 } | 1921 } |
1948 __ movp(args->GetReceiverOperand(), rax); | 1922 __ movp(args->GetReceiverOperand(), rax); |
1949 __ jmp(cont); | 1923 __ jmp(cont); |
1950 } | 1924 } |
1951 | 1925 |
1952 | 1926 |
1953 static void CallFunctionNoFeedback(MacroAssembler* masm, | 1927 static void CallFunctionNoFeedback(MacroAssembler* masm, |
1954 int argc, bool needs_checks, | 1928 int argc, bool needs_checks, |
1955 bool call_as_method) { | 1929 bool call_as_method) { |
1956 // rdi : the function to call | 1930 // rdi : the function to call |
1957 | 1931 |
1958 // wrap_and_call can only be true if we are compiling a monomorphic method. | 1932 // wrap_and_call can only be true if we are compiling a monomorphic method. |
1959 Isolate* isolate = masm->isolate(); | 1933 Label slow, wrap, cont; |
1960 Label slow, non_function, wrap, cont; | |
1961 StackArgumentsAccessor args(rsp, argc); | 1934 StackArgumentsAccessor args(rsp, argc); |
1962 | 1935 |
1963 if (needs_checks) { | 1936 if (needs_checks) { |
1964 // Check that the function really is a JavaScript function. | 1937 // Check that the function really is a JavaScript function. |
1965 __ JumpIfSmi(rdi, &non_function); | 1938 __ JumpIfSmi(rdi, &slow); |
1966 | 1939 |
1967 // Goto slow case if we do not have a function. | 1940 // Goto slow case if we do not have a function. |
1968 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 1941 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
1969 __ j(not_equal, &slow); | 1942 __ j(not_equal, &slow); |
1970 } | 1943 } |
1971 | 1944 |
1972 // Fast-case: Just invoke the function. | 1945 // Fast-case: Just invoke the function. |
1973 ParameterCount actual(argc); | 1946 ParameterCount actual(argc); |
1974 | 1947 |
1975 if (call_as_method) { | 1948 if (call_as_method) { |
(...skipping 14 matching lines...) Expand all Loading... |
1990 } | 1963 } |
1991 | 1964 |
1992 __ bind(&cont); | 1965 __ bind(&cont); |
1993 } | 1966 } |
1994 | 1967 |
1995 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); | 1968 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); |
1996 | 1969 |
1997 if (needs_checks) { | 1970 if (needs_checks) { |
1998 // Slow-case: Non-function called. | 1971 // Slow-case: Non-function called. |
1999 __ bind(&slow); | 1972 __ bind(&slow); |
2000 EmitSlowCase(isolate, masm, &args, argc, &non_function); | 1973 EmitSlowCase(masm, &args, argc); |
2001 } | 1974 } |
2002 | 1975 |
2003 if (call_as_method) { | 1976 if (call_as_method) { |
2004 __ bind(&wrap); | 1977 __ bind(&wrap); |
2005 EmitWrapCase(masm, &args, &cont); | 1978 EmitWrapCase(masm, &args, &cont); |
2006 } | 1979 } |
2007 } | 1980 } |
2008 | 1981 |
2009 | 1982 |
2010 void CallFunctionStub::Generate(MacroAssembler* masm) { | 1983 void CallFunctionStub::Generate(MacroAssembler* masm) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2106 __ SmiToInteger32(rdx, rdx); | 2079 __ SmiToInteger32(rdx, rdx); |
2107 | 2080 |
2108 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx); | 2081 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx); |
2109 __ cmpp(rdi, rcx); | 2082 __ cmpp(rdi, rcx); |
2110 __ j(not_equal, &miss); | 2083 __ j(not_equal, &miss); |
2111 | 2084 |
2112 __ movp(rax, Immediate(arg_count())); | 2085 __ movp(rax, Immediate(arg_count())); |
2113 __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, | 2086 __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, |
2114 FixedArray::kHeaderSize)); | 2087 FixedArray::kHeaderSize)); |
2115 // Verify that ecx contains an AllocationSite | 2088 // Verify that ecx contains an AllocationSite |
2116 Factory* factory = masm->isolate()->factory(); | 2089 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
2117 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), | 2090 Heap::kAllocationSiteMapRootIndex); |
2118 factory->allocation_site_map()); | 2091 __ j(not_equal, &miss, Label::kNear); |
2119 __ j(not_equal, &miss); | |
2120 | 2092 |
2121 // Increment the call count for monomorphic function calls. | 2093 // Increment the call count for monomorphic function calls. |
2122 __ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size, | 2094 { |
2123 FixedArray::kHeaderSize + kPointerSize), | 2095 __ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size, |
2124 Smi::FromInt(CallICNexus::kCallCountIncrement)); | 2096 FixedArray::kHeaderSize + kPointerSize), |
| 2097 Smi::FromInt(CallICNexus::kCallCountIncrement)); |
2125 | 2098 |
2126 __ movp(rbx, rcx); | 2099 __ movp(rbx, rcx); |
2127 __ movp(rdx, rdi); | 2100 __ movp(rdx, rdi); |
2128 ArrayConstructorStub stub(masm->isolate(), arg_count()); | 2101 ArrayConstructorStub stub(masm->isolate(), arg_count()); |
2129 __ TailCallStub(&stub); | 2102 __ TailCallStub(&stub); |
| 2103 } |
2130 | 2104 |
2131 __ bind(&miss); | 2105 __ bind(&miss); |
2132 GenerateMiss(masm); | 2106 GenerateMiss(masm); |
2133 | 2107 |
2134 // The slow case, we need this no matter what to complete a call after a miss. | 2108 // The slow case, we need this no matter what to complete a call after a miss. |
2135 CallFunctionNoFeedback(masm, | 2109 __ Set(rax, arg_count()); |
2136 arg_count(), | 2110 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
2137 true, | |
2138 CallAsMethod()); | |
2139 | |
2140 // Unreachable. | |
2141 __ int3(); | |
2142 } | 2111 } |
2143 | 2112 |
2144 | 2113 |
2145 void CallICStub::Generate(MacroAssembler* masm) { | 2114 void CallICStub::Generate(MacroAssembler* masm) { |
2146 // rdi - function | 2115 // rdi - function |
2147 // rdx - slot id | 2116 // rdx - slot id |
2148 // rbx - vector | 2117 // rbx - vector |
2149 Isolate* isolate = masm->isolate(); | 2118 Isolate* isolate = masm->isolate(); |
2150 const int with_types_offset = | 2119 const int with_types_offset = |
2151 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); | 2120 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); |
2152 const int generic_offset = | 2121 const int generic_offset = |
2153 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); | 2122 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); |
2154 Label extra_checks_or_miss, slow_start; | 2123 Label extra_checks_or_miss, slow_start; |
2155 Label slow, non_function, wrap, cont; | 2124 Label slow, wrap, cont; |
2156 Label have_js_function; | 2125 Label have_js_function; |
2157 int argc = arg_count(); | 2126 int argc = arg_count(); |
2158 StackArgumentsAccessor args(rsp, argc); | 2127 StackArgumentsAccessor args(rsp, argc); |
2159 ParameterCount actual(argc); | 2128 ParameterCount actual(argc); |
2160 | 2129 |
2161 // The checks. First, does rdi match the recorded monomorphic target? | 2130 // The checks. First, does rdi match the recorded monomorphic target? |
2162 __ SmiToInteger32(rdx, rdx); | 2131 __ SmiToInteger32(rdx, rdx); |
2163 __ movp(rcx, | 2132 __ movp(rcx, |
2164 FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize)); | 2133 FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize)); |
2165 | 2134 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2200 | 2169 |
2201 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); | 2170 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); |
2202 __ j(below, &wrap); | 2171 __ j(below, &wrap); |
2203 | 2172 |
2204 __ bind(&cont); | 2173 __ bind(&cont); |
2205 } | 2174 } |
2206 | 2175 |
2207 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); | 2176 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); |
2208 | 2177 |
2209 __ bind(&slow); | 2178 __ bind(&slow); |
2210 EmitSlowCase(isolate, masm, &args, argc, &non_function); | 2179 EmitSlowCase(masm, &args, argc); |
2211 | 2180 |
2212 if (CallAsMethod()) { | 2181 if (CallAsMethod()) { |
2213 __ bind(&wrap); | 2182 __ bind(&wrap); |
2214 EmitWrapCase(masm, &args, &cont); | 2183 EmitWrapCase(masm, &args, &cont); |
2215 } | 2184 } |
2216 | 2185 |
2217 __ bind(&extra_checks_or_miss); | 2186 __ bind(&extra_checks_or_miss); |
2218 Label uninitialized, miss; | 2187 Label uninitialized, miss; |
2219 | 2188 |
2220 __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate)); | 2189 __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate)); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2281 __ jmp(&have_js_function); | 2250 __ jmp(&have_js_function); |
2282 | 2251 |
2283 // We are here because tracing is on or we encountered a MISS case we can't | 2252 // We are here because tracing is on or we encountered a MISS case we can't |
2284 // handle here. | 2253 // handle here. |
2285 __ bind(&miss); | 2254 __ bind(&miss); |
2286 GenerateMiss(masm); | 2255 GenerateMiss(masm); |
2287 | 2256 |
2288 // the slow case | 2257 // the slow case |
2289 __ bind(&slow_start); | 2258 __ bind(&slow_start); |
2290 // Check that function is not a smi. | 2259 // Check that function is not a smi. |
2291 __ JumpIfSmi(rdi, &non_function); | 2260 __ JumpIfSmi(rdi, &slow); |
2292 // Check that function is a JSFunction. | 2261 // Check that function is a JSFunction. |
2293 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2262 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2294 __ j(not_equal, &slow); | 2263 __ j(not_equal, &slow); |
2295 __ jmp(&have_js_function); | 2264 __ jmp(&have_js_function); |
2296 | 2265 |
2297 // Unreachable | 2266 // Unreachable |
2298 __ int3(); | 2267 __ int3(); |
2299 } | 2268 } |
2300 | 2269 |
2301 | 2270 |
(...skipping 3323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5625 kStackSpace, nullptr, return_value_operand, NULL); | 5594 kStackSpace, nullptr, return_value_operand, NULL); |
5626 } | 5595 } |
5627 | 5596 |
5628 | 5597 |
5629 #undef __ | 5598 #undef __ |
5630 | 5599 |
5631 } // namespace internal | 5600 } // namespace internal |
5632 } // namespace v8 | 5601 } // namespace v8 |
5633 | 5602 |
5634 #endif // V8_TARGET_ARCH_X64 | 5603 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |