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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 1866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1877 __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset), | 1877 __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset), |
1878 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); | 1878 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); |
1879 __ j(not_equal, cont); | 1879 __ j(not_equal, cont); |
1880 } | 1880 } |
1881 | 1881 |
1882 | 1882 |
1883 static void EmitSlowCase(Isolate* isolate, | 1883 static void EmitSlowCase(Isolate* isolate, |
1884 MacroAssembler* masm, | 1884 MacroAssembler* masm, |
1885 StackArgumentsAccessor* args, | 1885 StackArgumentsAccessor* args, |
1886 int argc, | 1886 int argc, |
1887 Label* non_function) { | 1887 Label* non_function, |
| 1888 bool is_spread = false) { |
1888 // Check for function proxy. | 1889 // Check for function proxy. |
1889 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | 1890 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
1890 __ j(not_equal, non_function); | 1891 __ j(not_equal, non_function); |
1891 __ PopReturnAddressTo(rcx); | 1892 __ PopReturnAddressTo(rcx); |
1892 __ Push(rdi); // put proxy as additional argument under return address | 1893 __ Push(rdi); // put proxy as additional argument under return address |
1893 __ PushReturnAddressFrom(rcx); | 1894 __ PushReturnAddressFrom(rcx); |
1894 __ Set(rax, argc + 1); | 1895 if (!is_spread) { |
| 1896 __ Set(rax, argc + 1); |
| 1897 } |
1895 __ Set(rbx, 0); | 1898 __ Set(rbx, 0); |
1896 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); | 1899 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); |
1897 { | 1900 { |
1898 Handle<Code> adaptor = | 1901 Handle<Code> adaptor = |
1899 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 1902 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
1900 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 1903 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
1901 } | 1904 } |
1902 | 1905 |
1903 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 1906 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
1904 // of the original receiver from the call site). | 1907 // of the original receiver from the call site). |
1905 __ bind(non_function); | 1908 __ bind(non_function); |
1906 __ movp(args->GetReceiverOperand(), rdi); | 1909 __ movp(args->GetReceiverOperand(), rdi); |
1907 __ Set(rax, argc); | 1910 if (!is_spread) { |
| 1911 __ Set(rax, argc); |
| 1912 } |
1908 __ Set(rbx, 0); | 1913 __ Set(rbx, 0); |
1909 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); | 1914 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); |
1910 Handle<Code> adaptor = | 1915 Handle<Code> adaptor = |
1911 isolate->builtins()->ArgumentsAdaptorTrampoline(); | 1916 isolate->builtins()->ArgumentsAdaptorTrampoline(); |
1912 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 1917 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
1913 } | 1918 } |
1914 | 1919 |
1915 | 1920 |
1916 static void EmitWrapCase(MacroAssembler* masm, | 1921 static void EmitWrapCase(MacroAssembler* masm, |
1917 StackArgumentsAccessor* args, | 1922 StackArgumentsAccessor* args, |
1918 Label* cont) { | 1923 Label* cont, bool is_spread = false) { |
1919 // Wrap the receiver and patch it back onto the stack. | 1924 // Wrap the receiver and patch it back onto the stack. |
1920 { FrameScope frame_scope(masm, StackFrame::INTERNAL); | 1925 { FrameScope frame_scope(masm, StackFrame::INTERNAL); |
| 1926 // If is_spread is true, dynamic argument count is in $r8 temporarily |
| 1927 if (is_spread) __ Push(r8); |
1921 __ Push(rdi); | 1928 __ Push(rdi); |
1922 __ Push(rax); | 1929 __ Push(rax); |
1923 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 1930 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
1924 __ Pop(rdi); | 1931 __ Pop(rdi); |
| 1932 if (is_spread) __ Pop(r8); |
1925 } | 1933 } |
1926 __ movp(args->GetReceiverOperand(), rax); | 1934 if (is_spread) { |
| 1935 DCHECK(args->argument_count_reg().is(rax)); |
| 1936 __ xchgp(rax, r8); |
| 1937 __ movp(args->GetReceiverOperand(), r8); |
| 1938 } else { |
| 1939 __ movp(args->GetReceiverOperand(), rax); |
| 1940 } |
1927 __ jmp(cont); | 1941 __ jmp(cont); |
1928 } | 1942 } |
1929 | 1943 |
1930 | 1944 |
1931 static void CallFunctionNoFeedback(MacroAssembler* masm, | 1945 static void CallFunctionNoFeedback(MacroAssembler* masm, |
1932 int argc, bool needs_checks, | 1946 int argc, bool needs_checks, |
1933 bool call_as_method) { | 1947 bool call_as_method, |
| 1948 bool is_spread = false) { |
1934 // rdi : the function to call | 1949 // rdi : the function to call |
| 1950 // rcx : the dynamic argument count (if is_spread is true) |
1935 | 1951 |
1936 // wrap_and_call can only be true if we are compiling a monomorphic method. | 1952 // wrap_and_call can only be true if we are compiling a monomorphic method. |
1937 Isolate* isolate = masm->isolate(); | 1953 Isolate* isolate = masm->isolate(); |
1938 Label slow, non_function, wrap, cont; | 1954 Label slow, non_function, wrap, cont; |
1939 StackArgumentsAccessor args(rsp, argc); | 1955 StackArgumentsAccessor args = is_spread ? |
1940 | 1956 StackArgumentsAccessor(rsp, rax) : StackArgumentsAccessor(rsp, argc); |
1941 if (needs_checks) { | 1957 if (needs_checks) { |
1942 // Check that the function really is a JavaScript function. | 1958 // Check that the function really is a JavaScript function. |
1943 __ JumpIfSmi(rdi, &non_function); | 1959 __ JumpIfSmi(rdi, &non_function); |
1944 | 1960 |
1945 // Goto slow case if we do not have a function. | 1961 // Goto slow case if we do not have a function. |
1946 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 1962 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
1947 __ j(not_equal, &slow); | 1963 __ j(not_equal, &slow); |
1948 } | 1964 } |
1949 | 1965 |
1950 // Fast-case: Just invoke the function. | 1966 // Fast-case: Just invoke the function. |
1951 ParameterCount actual(argc); | 1967 ParameterCount actual = is_spread ? |
| 1968 ParameterCount(rax) : ParameterCount(argc); |
1952 | 1969 |
1953 if (call_as_method) { | 1970 if (call_as_method) { |
| 1971 // If is_spread is true, preserve dynamic argument count in r8 |
| 1972 if (is_spread) __ xchgp(r8, rax); |
| 1973 |
1954 if (needs_checks) { | 1974 if (needs_checks) { |
1955 EmitContinueIfStrictOrNative(masm, &cont); | 1975 EmitContinueIfStrictOrNative(masm, &cont); |
1956 } | 1976 } |
1957 | 1977 |
1958 // Load the receiver from the stack. | 1978 // Load the receiver from the stack. If is_spread is true, args is now |
| 1979 // broken. |
1959 __ movp(rax, args.GetReceiverOperand()); | 1980 __ movp(rax, args.GetReceiverOperand()); |
1960 | 1981 |
1961 if (needs_checks) { | 1982 if (needs_checks) { |
1962 __ JumpIfSmi(rax, &wrap); | 1983 __ JumpIfSmi(rax, &wrap); |
1963 | 1984 |
1964 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); | 1985 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); |
1965 __ j(below, &wrap); | 1986 __ j(below, &wrap); |
1966 } else { | 1987 } else { |
1967 __ jmp(&wrap); | 1988 __ jmp(&wrap); |
1968 } | 1989 } |
1969 | 1990 |
1970 __ bind(&cont); | 1991 __ bind(&cont); |
1971 } | 1992 } |
1972 | 1993 |
1973 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); | 1994 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); |
1974 | 1995 |
1975 if (needs_checks) { | 1996 if (needs_checks) { |
1976 // Slow-case: Non-function called. | 1997 // Slow-case: Non-function called. |
1977 __ bind(&slow); | 1998 __ bind(&slow); |
1978 EmitSlowCase(isolate, masm, &args, argc, &non_function); | 1999 EmitSlowCase(isolate, masm, &args, argc, &non_function, is_spread); |
1979 } | 2000 } |
1980 | 2001 |
1981 if (call_as_method) { | 2002 if (call_as_method) { |
1982 __ bind(&wrap); | 2003 __ bind(&wrap); |
1983 EmitWrapCase(masm, &args, &cont); | 2004 EmitWrapCase(masm, &args, &cont, is_spread); |
1984 } | 2005 } |
1985 } | 2006 } |
1986 | 2007 |
1987 | 2008 |
1988 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2009 void CallFunctionStub::Generate(MacroAssembler* masm) { |
1989 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); | 2010 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod(), |
| 2011 is_spread()); |
1990 } | 2012 } |
1991 | 2013 |
1992 | 2014 |
1993 void CallConstructStub::Generate(MacroAssembler* masm) { | 2015 void CallConstructStub::Generate(MacroAssembler* masm) { |
1994 // rax : number of arguments | 2016 // rax : number of arguments |
1995 // rbx : feedback vector | 2017 // rbx : feedback vector |
1996 // rdx : (only if rbx is not the megamorphic symbol) slot in feedback | 2018 // rdx : (only if rbx is not the megamorphic symbol) slot in feedback |
1997 // vector (Smi) | 2019 // vector (Smi) |
1998 // rdi : constructor function | 2020 // rdi : constructor function |
1999 Label slow, non_function_call; | 2021 Label slow, non_function_call; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2106 arg_count(), | 2128 arg_count(), |
2107 true, | 2129 true, |
2108 CallAsMethod()); | 2130 CallAsMethod()); |
2109 | 2131 |
2110 // Unreachable. | 2132 // Unreachable. |
2111 __ int3(); | 2133 __ int3(); |
2112 } | 2134 } |
2113 | 2135 |
2114 | 2136 |
2115 void CallICStub::Generate(MacroAssembler* masm) { | 2137 void CallICStub::Generate(MacroAssembler* masm) { |
| 2138 // rax - argument count (only if call is a spread call) |
2116 // rdi - function | 2139 // rdi - function |
2117 // rdx - slot id | 2140 // rdx - slot id |
2118 // rbx - vector | 2141 // rbx - vector |
2119 Isolate* isolate = masm->isolate(); | 2142 Isolate* isolate = masm->isolate(); |
2120 const int with_types_offset = | 2143 const int with_types_offset = |
2121 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); | 2144 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); |
2122 const int generic_offset = | 2145 const int generic_offset = |
2123 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); | 2146 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); |
2124 Label extra_checks_or_miss, slow_start; | 2147 Label extra_checks_or_miss, slow_start; |
2125 Label slow, non_function, wrap, cont; | 2148 Label slow, non_function, wrap, cont; |
2126 Label have_js_function; | 2149 Label have_js_function; |
2127 int argc = arg_count(); | 2150 int argc = arg_count(); |
2128 StackArgumentsAccessor args(rsp, argc); | 2151 StackArgumentsAccessor args = is_spread() ? |
2129 ParameterCount actual(argc); | 2152 StackArgumentsAccessor(rsp, rax) : StackArgumentsAccessor(rsp, argc); |
| 2153 ParameterCount actual = is_spread() ? |
| 2154 ParameterCount(rax) : ParameterCount(argc); |
2130 | 2155 |
2131 // The checks. First, does rdi match the recorded monomorphic target? | 2156 // The checks. First, does rdi match the recorded monomorphic target? |
2132 __ SmiToInteger32(rdx, rdx); | 2157 __ SmiToInteger32(rdx, rdx); |
2133 __ movp(rcx, | 2158 __ movp(rcx, |
2134 FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize)); | 2159 FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize)); |
2135 | 2160 |
2136 // We don't know that we have a weak cell. We might have a private symbol | 2161 // We don't know that we have a weak cell. We might have a private symbol |
2137 // or an AllocationSite, but the memory is safe to examine. | 2162 // or an AllocationSite, but the memory is safe to examine. |
2138 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to | 2163 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to |
2139 // FixedArray. | 2164 // FixedArray. |
(...skipping 2929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5069 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, getter_arg, | 5094 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, getter_arg, |
5070 kStackSpace, nullptr, return_value_operand, NULL); | 5095 kStackSpace, nullptr, return_value_operand, NULL); |
5071 } | 5096 } |
5072 | 5097 |
5073 | 5098 |
5074 #undef __ | 5099 #undef __ |
5075 | 5100 |
5076 } } // namespace v8::internal | 5101 } } // namespace v8::internal |
5077 | 5102 |
5078 #endif // V8_TARGET_ARCH_X64 | 5103 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |