OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 1956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1967 __ bind(&class_constructor); | 1967 __ bind(&class_constructor); |
1968 { | 1968 { |
1969 FrameScope frame(masm, StackFrame::INTERNAL); | 1969 FrameScope frame(masm, StackFrame::INTERNAL); |
1970 __ Push(rdi); | 1970 __ Push(rdi); |
1971 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 1); | 1971 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 1); |
1972 } | 1972 } |
1973 } | 1973 } |
1974 | 1974 |
1975 | 1975 |
1976 // static | 1976 // static |
| 1977 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) { |
| 1978 // ----------- S t a t e ------------- |
| 1979 // -- rax : the number of arguments (not including the receiver) |
| 1980 // -- rdi : the function to call (checked to be a JSBoundFunction) |
| 1981 // ----------------------------------- |
| 1982 __ AssertBoundFunction(rdi); |
| 1983 |
| 1984 // Patch the receiver to [[BoundThis]]. |
| 1985 { |
| 1986 StackArgumentsAccessor args(rsp, rax); |
| 1987 __ movp(rbx, FieldOperand(rdi, JSBoundFunction::kBoundThisOffset)); |
| 1988 __ movp(args.GetReceiverOperand(), rbx); |
| 1989 } |
| 1990 |
| 1991 // Load [[BoundArguments]] into rdx and length of that into rcx. |
| 1992 __ movp(rdx, FieldOperand(rdi, JSBoundFunction::kBoundArgumentsOffset)); |
| 1993 __ SmiToInteger32(rcx, FieldOperand(rdx, FixedArray::kLengthOffset)); |
| 1994 |
| 1995 // ----------- S t a t e ------------- |
| 1996 // -- rax : the number of arguments (not including the receiver) |
| 1997 // -- rdi : the function to call (checked to be a JSBoundFunction) |
| 1998 // -- rdx : the [[BoundArguments]] (implemented as FixedArray) |
| 1999 // -- rcx : the number of [[BoundArguments]] |
| 2000 // ----------------------------------- |
| 2001 |
| 2002 // Reserve stack space for the [[BoundArguments]]. |
| 2003 { |
| 2004 Label done; |
| 2005 __ leap(rbx, Operand(rcx, times_pointer_size, 0)); |
| 2006 __ subp(rsp, rbx); |
| 2007 // Check the stack for overflow. We are not trying to catch interruptions |
| 2008 // (i.e. debug break and preemption) here, so check the "real stack limit". |
| 2009 __ CompareRoot(rsp, Heap::kRealStackLimitRootIndex); |
| 2010 __ j(greater, &done, Label::kNear); // Signed comparison. |
| 2011 // Restore the stack pointer. |
| 2012 __ addp(rsp, rbx); |
| 2013 { |
| 2014 FrameScope scope(masm, StackFrame::MANUAL); |
| 2015 __ EnterFrame(StackFrame::INTERNAL); |
| 2016 __ CallRuntime(Runtime::kThrowStackOverflow, 0); |
| 2017 } |
| 2018 __ bind(&done); |
| 2019 } |
| 2020 |
| 2021 // Relocate arguments and return address down the stack. |
| 2022 { |
| 2023 Label loop; |
| 2024 __ incp(rax); // arguments plus return address |
| 2025 __ Set(rbx, 0); |
| 2026 __ bind(&loop); |
| 2027 __ movp(kScratchRegister, Operand(rsp, rcx, times_pointer_size, 0)); |
| 2028 __ incp(rcx); |
| 2029 __ movp(Operand(rsp, rbx, times_pointer_size, 0), kScratchRegister); |
| 2030 __ incp(rbx); |
| 2031 __ cmpp(rbx, rax); |
| 2032 __ j(less, &loop); |
| 2033 } |
| 2034 |
| 2035 // Copy [[BoundArguments]] to the stack (below the arguments). |
| 2036 { |
| 2037 Label loop, done_loop; |
| 2038 __ SmiToInteger32(rcx, FieldOperand(rdx, FixedArray::kLengthOffset)); |
| 2039 __ bind(&loop); |
| 2040 __ subp(rcx, Immediate(1)); |
| 2041 __ j(less, &done_loop, Label::kNear); |
| 2042 __ movp(rbx, FieldOperand(rdx, rcx, times_pointer_size, |
| 2043 FixedArray::kHeaderSize)); |
| 2044 __ movp(Operand(rsp, rax, times_pointer_size, 0), rbx); |
| 2045 __ incp(rax); |
| 2046 __ jmp(&loop); |
| 2047 __ bind(&done_loop); |
| 2048 } |
| 2049 |
| 2050 // Adjust effective number of arguments (rax contains the number of arguments |
| 2051 // from the call plus return address plus the number of [[BoundArguments]]), |
| 2052 // so we need to subtract one for the return address. |
| 2053 __ decp(rax); |
| 2054 |
| 2055 // Call the [[BoundTargetFunction]] via the Call builtin. |
| 2056 __ movp(rdi, FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 2057 __ Load(rcx, |
| 2058 ExternalReference(Builtins::kCall_ReceiverIsAny, masm->isolate())); |
| 2059 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); |
| 2060 __ jmp(rcx); |
| 2061 } |
| 2062 |
| 2063 |
| 2064 // static |
1977 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { | 2065 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { |
1978 // ----------- S t a t e ------------- | 2066 // ----------- S t a t e ------------- |
1979 // -- rax : the number of arguments (not including the receiver) | 2067 // -- rax : the number of arguments (not including the receiver) |
1980 // -- rdi : the target to call (can be any Object) | 2068 // -- rdi : the target to call (can be any Object) |
1981 // ----------------------------------- | 2069 // ----------------------------------- |
1982 StackArgumentsAccessor args(rsp, rax); | 2070 StackArgumentsAccessor args(rsp, rax); |
1983 | 2071 |
1984 Label non_callable, non_function, non_smi; | 2072 Label non_callable, non_function, non_smi; |
1985 __ JumpIfSmi(rdi, &non_callable); | 2073 __ JumpIfSmi(rdi, &non_callable); |
1986 __ bind(&non_smi); | 2074 __ bind(&non_smi); |
1987 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2075 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
1988 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), | 2076 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), |
1989 RelocInfo::CODE_TARGET); | 2077 RelocInfo::CODE_TARGET); |
| 2078 __ CmpInstanceType(rcx, JS_BOUND_FUNCTION_TYPE); |
| 2079 __ j(equal, masm->isolate()->builtins()->CallBoundFunction(), |
| 2080 RelocInfo::CODE_TARGET); |
1990 __ CmpInstanceType(rcx, JS_PROXY_TYPE); | 2081 __ CmpInstanceType(rcx, JS_PROXY_TYPE); |
1991 __ j(not_equal, &non_function); | 2082 __ j(not_equal, &non_function); |
1992 | 2083 |
1993 // 1. Runtime fallback for Proxy [[Call]]. | 2084 // 1. Runtime fallback for Proxy [[Call]]. |
1994 __ PopReturnAddressTo(kScratchRegister); | 2085 __ PopReturnAddressTo(kScratchRegister); |
1995 __ Push(rdi); | 2086 __ Push(rdi); |
1996 __ PushReturnAddressFrom(kScratchRegister); | 2087 __ PushReturnAddressFrom(kScratchRegister); |
1997 // Increase the arguments size to include the pushed function and the | 2088 // Increase the arguments size to include the pushed function and the |
1998 // existing receiver on the stack. | 2089 // existing receiver on the stack. |
1999 __ addp(rax, Immediate(2)); | 2090 __ addp(rax, Immediate(2)); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2042 // Tail call to the function-specific construct stub (still in the caller | 2133 // Tail call to the function-specific construct stub (still in the caller |
2043 // context at this point). | 2134 // context at this point). |
2044 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 2135 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
2045 __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset)); | 2136 __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset)); |
2046 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); | 2137 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); |
2047 __ jmp(rcx); | 2138 __ jmp(rcx); |
2048 } | 2139 } |
2049 | 2140 |
2050 | 2141 |
2051 // static | 2142 // static |
| 2143 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { |
| 2144 // ----------- S t a t e ------------- |
| 2145 // -- rax : the number of arguments (not including the receiver) |
| 2146 // -- rdx : the new target (checked to be a constructor) |
| 2147 // -- rdi : the constructor to call (checked to be a JSBoundFunction) |
| 2148 // ----------------------------------- |
| 2149 __ AssertBoundFunction(rdi); |
| 2150 |
| 2151 // Load [[BoundArguments]] into r12 and length of that into rcx. |
| 2152 __ movp(r12, FieldOperand(rdi, JSBoundFunction::kBoundArgumentsOffset)); |
| 2153 __ SmiToInteger32(rcx, FieldOperand(r12, FixedArray::kLengthOffset)); |
| 2154 |
| 2155 // ----------- S t a t e ------------- |
| 2156 // -- rax : the number of arguments (not including the receiver) |
| 2157 // -- rdi : the function to call (checked to be a JSBoundFunction) |
| 2158 // -- r12 : the [[BoundArguments]] (implemented as FixedArray) |
| 2159 // -- rcx : the number of [[BoundArguments]] |
| 2160 // ----------------------------------- |
| 2161 |
| 2162 // Reserve stack space for the [[BoundArguments]]. |
| 2163 { |
| 2164 Label done; |
| 2165 __ leap(rbx, Operand(rcx, times_pointer_size, 0)); |
| 2166 __ subp(rsp, rbx); |
| 2167 // Check the stack for overflow. We are not trying to catch interruptions |
| 2168 // (i.e. debug break and preemption) here, so check the "real stack limit". |
| 2169 __ CompareRoot(rsp, Heap::kRealStackLimitRootIndex); |
| 2170 __ j(greater, &done, Label::kNear); // Signed comparison. |
| 2171 // Restore the stack pointer. |
| 2172 __ addp(rsp, rbx); |
| 2173 { |
| 2174 FrameScope scope(masm, StackFrame::MANUAL); |
| 2175 __ EnterFrame(StackFrame::INTERNAL); |
| 2176 __ CallRuntime(Runtime::kThrowStackOverflow, 0); |
| 2177 } |
| 2178 __ bind(&done); |
| 2179 } |
| 2180 |
| 2181 // Relocate arguments and return address down the stack. |
| 2182 { |
| 2183 Label loop; |
| 2184 __ incp(rax); // arguments plus return address |
| 2185 __ Set(rbx, 0); |
| 2186 __ bind(&loop); |
| 2187 __ movp(kScratchRegister, Operand(rsp, rcx, times_pointer_size, 0)); |
| 2188 __ incp(rcx); |
| 2189 __ movp(Operand(rsp, rbx, times_pointer_size, 0), kScratchRegister); |
| 2190 __ incp(rbx); |
| 2191 __ cmpp(rbx, rax); |
| 2192 __ j(less, &loop); |
| 2193 } |
| 2194 |
| 2195 // Copy [[BoundArguments]] to the stack (below the arguments). |
| 2196 { |
| 2197 Label loop, done_loop; |
| 2198 __ SmiToInteger32(rcx, FieldOperand(r12, FixedArray::kLengthOffset)); |
| 2199 __ bind(&loop); |
| 2200 __ subp(rcx, Immediate(1)); |
| 2201 __ j(less, &done_loop, Label::kNear); |
| 2202 __ movp(rbx, FieldOperand(r12, rcx, times_pointer_size, |
| 2203 FixedArray::kHeaderSize)); |
| 2204 __ movp(Operand(rsp, rax, times_pointer_size, 0), rbx); |
| 2205 __ incp(rax); |
| 2206 __ jmp(&loop); |
| 2207 __ bind(&done_loop); |
| 2208 } |
| 2209 |
| 2210 // Adjust effective number of arguments (rax contains the number of arguments |
| 2211 // from the call plus return address plus the number of [[BoundArguments]]), |
| 2212 // so we need to subtract one for the return address. |
| 2213 __ decp(rax); |
| 2214 |
| 2215 // Patch new.target to [[BoundTargetFunction]] if new.target equals target. |
| 2216 { |
| 2217 Label done; |
| 2218 __ cmpp(rdi, rdx); |
| 2219 __ j(not_equal, &done, Label::kNear); |
| 2220 __ movp(rdx, |
| 2221 FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 2222 __ bind(&done); |
| 2223 } |
| 2224 |
| 2225 // Construct the [[BoundTargetFunction]] via the Construct builtin. |
| 2226 __ movp(rdi, FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 2227 __ Load(rcx, ExternalReference(Builtins::kConstruct, masm->isolate())); |
| 2228 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); |
| 2229 __ jmp(rcx); |
| 2230 } |
| 2231 |
| 2232 |
| 2233 // static |
2052 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { | 2234 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { |
2053 // ----------- S t a t e ------------- | 2235 // ----------- S t a t e ------------- |
2054 // -- rax : the number of arguments (not including the receiver) | 2236 // -- rax : the number of arguments (not including the receiver) |
2055 // -- rdi : the constructor to call (checked to be a JSProxy) | 2237 // -- rdi : the constructor to call (checked to be a JSProxy) |
2056 // -- rdx : the new target (either the same as the constructor or | 2238 // -- rdx : the new target (either the same as the constructor or |
2057 // the JSFunction on which new was invoked initially) | 2239 // the JSFunction on which new was invoked initially) |
2058 // ----------------------------------- | 2240 // ----------------------------------- |
2059 | 2241 |
2060 // Call into the Runtime for Proxy [[Construct]]. | 2242 // Call into the Runtime for Proxy [[Construct]]. |
2061 __ PopReturnAddressTo(kScratchRegister); | 2243 __ PopReturnAddressTo(kScratchRegister); |
(...skipping 24 matching lines...) Expand all Loading... |
2086 // Dispatch based on instance type. | 2268 // Dispatch based on instance type. |
2087 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2269 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2088 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), | 2270 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), |
2089 RelocInfo::CODE_TARGET); | 2271 RelocInfo::CODE_TARGET); |
2090 | 2272 |
2091 // Check if target has a [[Construct]] internal method. | 2273 // Check if target has a [[Construct]] internal method. |
2092 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 2274 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
2093 Immediate(1 << Map::kIsConstructor)); | 2275 Immediate(1 << Map::kIsConstructor)); |
2094 __ j(zero, &non_constructor, Label::kNear); | 2276 __ j(zero, &non_constructor, Label::kNear); |
2095 | 2277 |
| 2278 // Only dispatch to bound functions after checking whether they are |
| 2279 // constructors. |
| 2280 __ CmpInstanceType(rcx, JS_BOUND_FUNCTION_TYPE); |
| 2281 __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), |
| 2282 RelocInfo::CODE_TARGET); |
| 2283 |
2096 // Only dispatch to proxies after checking whether they are constructors. | 2284 // Only dispatch to proxies after checking whether they are constructors. |
2097 __ CmpInstanceType(rcx, JS_PROXY_TYPE); | 2285 __ CmpInstanceType(rcx, JS_PROXY_TYPE); |
2098 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), | 2286 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), |
2099 RelocInfo::CODE_TARGET); | 2287 RelocInfo::CODE_TARGET); |
2100 | 2288 |
2101 // Called Construct on an exotic Object with a [[Construct]] internal method. | 2289 // Called Construct on an exotic Object with a [[Construct]] internal method. |
2102 { | 2290 { |
2103 // Overwrite the original receiver with the (original) target. | 2291 // Overwrite the original receiver with the (original) target. |
2104 __ movp(args.GetReceiverOperand(), rdi); | 2292 __ movp(args.GetReceiverOperand(), rdi); |
2105 // Let the "call_as_constructor_delegate" take care of the rest. | 2293 // Let the "call_as_constructor_delegate" take care of the rest. |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2296 __ ret(0); | 2484 __ ret(0); |
2297 } | 2485 } |
2298 | 2486 |
2299 | 2487 |
2300 #undef __ | 2488 #undef __ |
2301 | 2489 |
2302 } // namespace internal | 2490 } // namespace internal |
2303 } // namespace v8 | 2491 } // namespace v8 |
2304 | 2492 |
2305 #endif // V8_TARGET_ARCH_X64 | 2493 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |