| 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 |