Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 919703003: WIP: Implement ES6 Spread-calls (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Flag calls as spread calls in parser, error on spread intrinsics/construct calls Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698