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