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 1857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1868 CallStubInRecordCallTarget(masm, &weak_cell_stub, is_super); | 1868 CallStubInRecordCallTarget(masm, &weak_cell_stub, is_super); |
1869 __ jmp(&done_no_smi_convert); | 1869 __ jmp(&done_no_smi_convert); |
1870 | 1870 |
1871 __ bind(&done); | 1871 __ bind(&done); |
1872 __ Integer32ToSmi(rdx, rdx); | 1872 __ Integer32ToSmi(rdx, rdx); |
1873 | 1873 |
1874 __ bind(&done_no_smi_convert); | 1874 __ bind(&done_no_smi_convert); |
1875 } | 1875 } |
1876 | 1876 |
1877 | 1877 |
1878 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { | |
1879 // ----------- S t a t e ------------- | |
1880 // -- rdi : the function to call | |
1881 // -- rdx : the function's shared function info | |
1882 // ----------------------------------- | |
1883 // Assume that SharedFunctionInfo is already loaded into rdx. | |
1884 // Do not transform the receiver for strict mode functions. | |
1885 __ testb(FieldOperand(rdx, SharedFunctionInfo::kStrictModeByteOffset), | |
1886 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); | |
1887 __ j(not_equal, cont); | |
1888 | |
1889 // Do not transform the receiver for natives. | |
1890 __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset), | |
1891 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); | |
1892 __ j(not_equal, cont); | |
1893 } | |
1894 | |
1895 | |
1896 static void EmitSlowCase(MacroAssembler* masm, StackArgumentsAccessor* args, | |
1897 int argc) { | |
1898 __ Set(rax, argc); | |
1899 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
1900 } | |
1901 | |
1902 | |
1903 static void EmitWrapCase(MacroAssembler* masm, | |
1904 StackArgumentsAccessor* args, | |
1905 Label* cont) { | |
1906 // Wrap the receiver and patch it back onto the stack. | |
1907 { FrameScope frame_scope(masm, StackFrame::INTERNAL); | |
1908 __ Push(rdi); | |
1909 ToObjectStub stub(masm->isolate()); | |
1910 __ CallStub(&stub); | |
1911 __ Pop(rdi); | |
1912 } | |
1913 __ movp(args->GetReceiverOperand(), rax); | |
1914 __ jmp(cont); | |
1915 } | |
1916 | |
1917 | |
1918 static void EmitClassConstructorCallCheck(MacroAssembler* masm) { | |
1919 // ----------- S t a t e ------------- | |
1920 // -- rdi : the function to call | |
1921 // -- rdx : the function's shared function info | |
1922 // ----------------------------------- | |
1923 // ClassConstructor Check: ES6 section 9.2.1 [[Call]] | |
1924 Label non_class_constructor; | |
1925 // Check whether the current function is a classConstructor | |
1926 __ testb(FieldOperand(rdx, SharedFunctionInfo::kFunctionKindByteOffset), | |
1927 Immediate(SharedFunctionInfo::kClassConstructorBitsWithinByte)); | |
1928 __ j(zero, &non_class_constructor, Label::kNear); | |
1929 // If we call a classConstructor Function throw a TypeError | |
1930 // indirectly via the CallFunction builtin. | |
1931 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | |
1932 __ bind(&non_class_constructor); | |
1933 } | |
1934 | |
1935 | |
1936 static void CallFunctionNoFeedback(MacroAssembler* masm, | |
1937 int argc, bool needs_checks, | |
1938 bool call_as_method) { | |
1939 // ----------- S t a t e ------------- | |
1940 // -- rdi : the function to call | |
1941 // ----------------------------------- | |
1942 | |
1943 // wrap_and_call can only be true if we are compiling a monomorphic method. | |
1944 Label slow, wrap, cont; | |
1945 StackArgumentsAccessor args(rsp, argc); | |
1946 | |
1947 if (needs_checks) { | |
1948 // Check that the function really is a JavaScript function. | |
1949 __ JumpIfSmi(rdi, &slow); | |
1950 | |
1951 // Goto slow case if we do not have a function. | |
1952 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | |
1953 __ j(not_equal, &slow); | |
1954 } | |
1955 | |
1956 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | |
1957 EmitClassConstructorCallCheck(masm); | |
1958 | |
1959 // Fast-case: Just invoke the function. | |
1960 ParameterCount actual(argc); | |
1961 | |
1962 if (call_as_method) { | |
1963 if (needs_checks) { | |
1964 EmitContinueIfStrictOrNative(masm, &cont); | |
1965 } | |
1966 | |
1967 // Load the receiver from the stack. | |
1968 __ movp(rax, args.GetReceiverOperand()); | |
1969 | |
1970 if (needs_checks) { | |
1971 __ JumpIfSmi(rax, &wrap); | |
1972 | |
1973 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); | |
1974 __ j(below, &wrap); | |
1975 } else { | |
1976 __ jmp(&wrap); | |
1977 } | |
1978 | |
1979 __ bind(&cont); | |
1980 } | |
1981 | |
1982 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); | |
1983 | |
1984 if (needs_checks) { | |
1985 // Slow-case: Non-function called. | |
1986 __ bind(&slow); | |
1987 EmitSlowCase(masm, &args, argc); | |
1988 } | |
1989 | |
1990 if (call_as_method) { | |
1991 __ bind(&wrap); | |
1992 EmitWrapCase(masm, &args, &cont); | |
1993 } | |
1994 } | |
1995 | |
1996 | |
1997 void CallFunctionStub::Generate(MacroAssembler* masm) { | |
1998 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); | |
1999 } | |
2000 | |
2001 | |
2002 void CallConstructStub::Generate(MacroAssembler* masm) { | 1878 void CallConstructStub::Generate(MacroAssembler* masm) { |
2003 // rax : number of arguments | 1879 // rax : number of arguments |
2004 // rbx : feedback vector | 1880 // rbx : feedback vector |
2005 // rcx : original constructor (for IsSuperConstructorCall) | 1881 // rcx : original constructor (for IsSuperConstructorCall) |
2006 // rdx : slot in feedback vector (Smi, for RecordCallTarget) | 1882 // rdx : slot in feedback vector (Smi, for RecordCallTarget) |
2007 // rdi : constructor function | 1883 // rdi : constructor function |
2008 | 1884 |
2009 Label non_function; | 1885 Label non_function; |
2010 // Check that the constructor is not a smi. | 1886 // Check that the constructor is not a smi. |
2011 __ JumpIfSmi(rdi, &non_function); | 1887 __ JumpIfSmi(rdi, &non_function); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 // ----------- S t a t e ------------- | 1952 // ----------- S t a t e ------------- |
2077 // -- rdi - function | 1953 // -- rdi - function |
2078 // -- rdx - slot id | 1954 // -- rdx - slot id |
2079 // -- rbx - vector | 1955 // -- rbx - vector |
2080 // ----------------------------------- | 1956 // ----------------------------------- |
2081 Isolate* isolate = masm->isolate(); | 1957 Isolate* isolate = masm->isolate(); |
2082 const int with_types_offset = | 1958 const int with_types_offset = |
2083 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); | 1959 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); |
2084 const int generic_offset = | 1960 const int generic_offset = |
2085 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); | 1961 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); |
2086 Label extra_checks_or_miss, slow_start; | 1962 Label extra_checks_or_miss, call; |
2087 Label slow, wrap, cont; | |
2088 Label have_js_function; | |
2089 int argc = arg_count(); | 1963 int argc = arg_count(); |
2090 StackArgumentsAccessor args(rsp, argc); | 1964 StackArgumentsAccessor args(rsp, argc); |
2091 ParameterCount actual(argc); | 1965 ParameterCount actual(argc); |
2092 | 1966 |
2093 // The checks. First, does rdi match the recorded monomorphic target? | 1967 // The checks. First, does rdi match the recorded monomorphic target? |
2094 __ SmiToInteger32(rdx, rdx); | 1968 __ SmiToInteger32(rdx, rdx); |
2095 __ movp(rcx, | 1969 __ movp(rcx, |
2096 FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize)); | 1970 FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize)); |
2097 | 1971 |
2098 // We don't know that we have a weak cell. We might have a private symbol | 1972 // We don't know that we have a weak cell. We might have a private symbol |
(...skipping 15 matching lines...) Expand all Loading... |
2114 | 1988 |
2115 // The compare above could have been a SMI/SMI comparison. Guard against this | 1989 // The compare above could have been a SMI/SMI comparison. Guard against this |
2116 // convincing us that we have a monomorphic JSFunction. | 1990 // convincing us that we have a monomorphic JSFunction. |
2117 __ JumpIfSmi(rdi, &extra_checks_or_miss); | 1991 __ JumpIfSmi(rdi, &extra_checks_or_miss); |
2118 | 1992 |
2119 // Increment the call count for monomorphic function calls. | 1993 // Increment the call count for monomorphic function calls. |
2120 __ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size, | 1994 __ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size, |
2121 FixedArray::kHeaderSize + kPointerSize), | 1995 FixedArray::kHeaderSize + kPointerSize), |
2122 Smi::FromInt(CallICNexus::kCallCountIncrement)); | 1996 Smi::FromInt(CallICNexus::kCallCountIncrement)); |
2123 | 1997 |
2124 __ bind(&have_js_function); | 1998 __ bind(&call); |
2125 | 1999 __ Set(rax, argc); |
2126 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 2000 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
2127 EmitClassConstructorCallCheck(masm); | |
2128 | |
2129 if (CallAsMethod()) { | |
2130 EmitContinueIfStrictOrNative(masm, &cont); | |
2131 | |
2132 // Load the receiver from the stack. | |
2133 __ movp(rax, args.GetReceiverOperand()); | |
2134 | |
2135 __ JumpIfSmi(rax, &wrap); | |
2136 | |
2137 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); | |
2138 __ j(below, &wrap); | |
2139 | |
2140 __ bind(&cont); | |
2141 } | |
2142 | |
2143 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); | |
2144 | |
2145 __ bind(&slow); | |
2146 EmitSlowCase(masm, &args, argc); | |
2147 | |
2148 if (CallAsMethod()) { | |
2149 __ bind(&wrap); | |
2150 EmitWrapCase(masm, &args, &cont); | |
2151 } | |
2152 | 2001 |
2153 __ bind(&extra_checks_or_miss); | 2002 __ bind(&extra_checks_or_miss); |
2154 Label uninitialized, miss, not_allocation_site; | 2003 Label uninitialized, miss, not_allocation_site; |
2155 | 2004 |
2156 __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate)); | 2005 __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate)); |
2157 __ j(equal, &slow_start); | 2006 __ j(equal, &call); |
2158 | 2007 |
2159 // Check if we have an allocation site. | 2008 // Check if we have an allocation site. |
2160 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | 2009 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
2161 Heap::kAllocationSiteMapRootIndex); | 2010 Heap::kAllocationSiteMapRootIndex); |
2162 __ j(not_equal, ¬_allocation_site); | 2011 __ j(not_equal, ¬_allocation_site); |
2163 | 2012 |
2164 // We have an allocation site. | 2013 // We have an allocation site. |
2165 HandleArrayCase(masm, &miss); | 2014 HandleArrayCase(masm, &miss); |
2166 | 2015 |
2167 __ bind(¬_allocation_site); | 2016 __ bind(¬_allocation_site); |
(...skipping 10 matching lines...) Expand all Loading... |
2178 // We are going megamorphic. If the feedback is a JSFunction, it is fine | 2027 // We are going megamorphic. If the feedback is a JSFunction, it is fine |
2179 // to handle it here. More complex cases are dealt with in the runtime. | 2028 // to handle it here. More complex cases are dealt with in the runtime. |
2180 __ AssertNotSmi(rcx); | 2029 __ AssertNotSmi(rcx); |
2181 __ CmpObjectType(rcx, JS_FUNCTION_TYPE, rcx); | 2030 __ CmpObjectType(rcx, JS_FUNCTION_TYPE, rcx); |
2182 __ j(not_equal, &miss); | 2031 __ j(not_equal, &miss); |
2183 __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), | 2032 __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), |
2184 TypeFeedbackVector::MegamorphicSentinel(isolate)); | 2033 TypeFeedbackVector::MegamorphicSentinel(isolate)); |
2185 // We have to update statistics for runtime profiling. | 2034 // We have to update statistics for runtime profiling. |
2186 __ SmiAddConstant(FieldOperand(rbx, with_types_offset), Smi::FromInt(-1)); | 2035 __ SmiAddConstant(FieldOperand(rbx, with_types_offset), Smi::FromInt(-1)); |
2187 __ SmiAddConstant(FieldOperand(rbx, generic_offset), Smi::FromInt(1)); | 2036 __ SmiAddConstant(FieldOperand(rbx, generic_offset), Smi::FromInt(1)); |
2188 __ jmp(&slow_start); | 2037 __ jmp(&call); |
2189 | 2038 |
2190 __ bind(&uninitialized); | 2039 __ bind(&uninitialized); |
2191 | 2040 |
2192 // We are going monomorphic, provided we actually have a JSFunction. | 2041 // We are going monomorphic, provided we actually have a JSFunction. |
2193 __ JumpIfSmi(rdi, &miss); | 2042 __ JumpIfSmi(rdi, &miss); |
2194 | 2043 |
2195 // Goto miss case if we do not have a function. | 2044 // Goto miss case if we do not have a function. |
2196 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2045 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2197 __ j(not_equal, &miss); | 2046 __ j(not_equal, &miss); |
2198 | 2047 |
(...skipping 18 matching lines...) Expand all Loading... |
2217 { | 2066 { |
2218 FrameScope scope(masm, StackFrame::INTERNAL); | 2067 FrameScope scope(masm, StackFrame::INTERNAL); |
2219 CreateWeakCellStub create_stub(isolate); | 2068 CreateWeakCellStub create_stub(isolate); |
2220 | 2069 |
2221 __ Integer32ToSmi(rdx, rdx); | 2070 __ Integer32ToSmi(rdx, rdx); |
2222 __ Push(rdi); | 2071 __ Push(rdi); |
2223 __ CallStub(&create_stub); | 2072 __ CallStub(&create_stub); |
2224 __ Pop(rdi); | 2073 __ Pop(rdi); |
2225 } | 2074 } |
2226 | 2075 |
2227 __ jmp(&have_js_function); | 2076 __ jmp(&call); |
2228 | 2077 |
2229 // We are here because tracing is on or we encountered a MISS case we can't | 2078 // We are here because tracing is on or we encountered a MISS case we can't |
2230 // handle here. | 2079 // handle here. |
2231 __ bind(&miss); | 2080 __ bind(&miss); |
2232 GenerateMiss(masm); | 2081 GenerateMiss(masm); |
2233 | 2082 |
2234 // the slow case | 2083 __ jmp(&call); |
2235 __ bind(&slow_start); | |
2236 // Check that function is not a smi. | |
2237 __ JumpIfSmi(rdi, &slow); | |
2238 // Check that function is a JSFunction. | |
2239 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | |
2240 __ j(not_equal, &slow); | |
2241 __ jmp(&have_js_function); | |
2242 | 2084 |
2243 // Unreachable | 2085 // Unreachable |
2244 __ int3(); | 2086 __ int3(); |
2245 } | 2087 } |
2246 | 2088 |
2247 | 2089 |
2248 void CallICStub::GenerateMiss(MacroAssembler* masm) { | 2090 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
2249 FrameScope scope(masm, StackFrame::INTERNAL); | 2091 FrameScope scope(masm, StackFrame::INTERNAL); |
2250 | 2092 |
2251 // Push the receiver and the function and feedback info. | 2093 // Push the receiver and the function and feedback info. |
(...skipping 3375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5627 kStackSpace, nullptr, return_value_operand, NULL); | 5469 kStackSpace, nullptr, return_value_operand, NULL); |
5628 } | 5470 } |
5629 | 5471 |
5630 | 5472 |
5631 #undef __ | 5473 #undef __ |
5632 | 5474 |
5633 } // namespace internal | 5475 } // namespace internal |
5634 } // namespace v8 | 5476 } // namespace v8 |
5635 | 5477 |
5636 #endif // V8_TARGET_ARCH_X64 | 5478 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |