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