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