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 1955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1966 // The function is a "classConstructor", need to raise an exception. | 1966 // The function is a "classConstructor", need to raise an exception. |
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 namespace { | |
1977 | |
1978 void Generate_PushBoundArguments(MacroAssembler* masm) { | |
1979 // ----------- S t a t e ------------- | |
1980 // -- rax : the number of arguments (not including the receiver) | |
1981 // -- rdx : new.target (only in case of [[Construct]]) | |
1982 // -- rdi : target (checked to be a JSBoundFunction) | |
1983 // ----------------------------------- | |
1984 | |
1985 // Load [[BoundArguments]] into rcx and length of that into rbx. | |
1986 Label no_bound_arguments; | |
1987 __ movp(rcx, FieldOperand(rdi, JSBoundFunction::kBoundArgumentsOffset)); | |
1988 __ SmiToInteger32(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); | |
1989 __ testl(rbx, rbx); | |
1990 __ j(zero, &no_bound_arguments); | |
1991 { | |
1992 // ----------- S t a t e ------------- | |
1993 // -- rax : the number of arguments (not including the receiver) | |
1994 // -- rdx : new.target (only in case of [[Construct]]) | |
1995 // -- rdi : target (checked to be a JSBoundFunction) | |
1996 // -- rcx : the [[BoundArguments]] (implemented as FixedArray) | |
1997 // -- rbx : the number of [[BoundArguments]] (checked to be non-zero) | |
1998 // ----------------------------------- | |
1999 | |
2000 // Reserve stack space for the [[BoundArguments]]. | |
2001 { | |
2002 Label done; | |
2003 __ leap(kScratchRegister, Operand(rbx, times_pointer_size, 0)); | |
2004 __ subp(rsp, kScratchRegister); | |
2005 // Check the stack for overflow. We are not trying to catch interruptions | |
2006 // (i.e. debug break and preemption) here, so check the "real stack | |
2007 // limit". | |
2008 __ CompareRoot(rsp, Heap::kRealStackLimitRootIndex); | |
2009 __ j(greater, &done, Label::kNear); // Signed comparison. | |
2010 // Restore the stack pointer. | |
2011 __ leap(rsp, Operand(rsp, rbx, times_pointer_size, 0)); | |
2012 { | |
2013 FrameScope scope(masm, StackFrame::MANUAL); | |
2014 __ EnterFrame(StackFrame::INTERNAL); | |
2015 __ CallRuntime(Runtime::kThrowStackOverflow, 0); | |
2016 } | |
2017 __ bind(&done); | |
2018 } | |
2019 | |
2020 // Adjust effective number of arguments to include return address. | |
2021 __ incl(rax); | |
2022 | |
2023 // Relocate arguments and return address down the stack. | |
2024 { | |
2025 Label loop; | |
2026 __ Set(rcx, 0); | |
2027 __ leap(rbx, Operand(rsp, rbx, times_pointer_size, 0)); | |
2028 __ bind(&loop); | |
2029 __ movp(kScratchRegister, Operand(rbx, rcx, times_pointer_size, 0)); | |
2030 __ movp(Operand(rsp, rcx, times_pointer_size, 0), kScratchRegister); | |
2031 __ incl(rcx); | |
2032 __ cmpl(rcx, rax); | |
2033 __ j(less, &loop); | |
2034 } | |
2035 | |
2036 // Copy [[BoundArguments]] to the stack (below the arguments). | |
2037 { | |
2038 Label loop; | |
2039 __ movp(rcx, FieldOperand(rdi, JSBoundFunction::kBoundArgumentsOffset)); | |
2040 __ SmiToInteger32(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); | |
2041 __ bind(&loop); | |
2042 __ decl(rbx); | |
2043 __ movp(kScratchRegister, FieldOperand(rcx, rbx, times_pointer_size, | |
2044 FixedArray::kHeaderSize)); | |
2045 __ movp(Operand(rsp, rax, times_pointer_size, 0), kScratchRegister); | |
2046 __ leal(rax, Operand(rax, 1)); | |
2047 __ j(greater, &loop); | |
2048 } | |
2049 | |
2050 // Adjust effective number of arguments (rax contains the number of | |
2051 // arguments from the call plus return address plus the number of | |
2052 // [[BoundArguments]]), so we need to subtract one for the return address. | |
2053 __ decl(rax); | |
2054 } | |
2055 __ bind(&no_bound_arguments); | |
2056 } | |
2057 | |
2058 } // namespace | |
2059 | |
2060 | |
2061 // static | |
2062 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) { | |
2063 // ----------- S t a t e ------------- | |
2064 // -- rax : the number of arguments (not including the receiver) | |
2065 // -- rdi : the function to call (checked to be a JSBoundFunction) | |
2066 // ----------------------------------- | |
2067 __ AssertBoundFunction(rdi); | |
2068 | |
2069 // Patch the receiver to [[BoundThis]]. | |
2070 StackArgumentsAccessor args(rsp, rax); | |
2071 __ movp(rbx, FieldOperand(rdi, JSBoundFunction::kBoundThisOffset)); | |
2072 __ movp(args.GetReceiverOperand(), rbx); | |
2073 | |
2074 // Push the [[BoundArguments]] onto the stack. | |
2075 Generate_PushBoundArguments(masm); | |
2076 | |
2077 // Call the [[BoundTargetFunction]] via the Call builtin. | |
2078 __ movp(rdi, FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset)); | |
2079 __ Load(rcx, | |
2080 ExternalReference(Builtins::kCall_ReceiverIsAny, masm->isolate())); | |
2081 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); | |
2082 __ jmp(rcx); | |
2083 } | |
2084 | |
2085 | |
2086 // static | 1976 // static |
2087 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { | 1977 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { |
2088 // ----------- S t a t e ------------- | 1978 // ----------- S t a t e ------------- |
2089 // -- rax : the number of arguments (not including the receiver) | 1979 // -- rax : the number of arguments (not including the receiver) |
2090 // -- rdi : the target to call (can be any Object) | 1980 // -- rdi : the target to call (can be any Object) |
2091 // ----------------------------------- | 1981 // ----------------------------------- |
2092 StackArgumentsAccessor args(rsp, rax); | 1982 StackArgumentsAccessor args(rsp, rax); |
2093 | 1983 |
2094 Label non_callable, non_function, non_smi; | 1984 Label non_callable, non_function, non_smi; |
2095 __ JumpIfSmi(rdi, &non_callable); | 1985 __ JumpIfSmi(rdi, &non_callable); |
2096 __ bind(&non_smi); | 1986 __ bind(&non_smi); |
2097 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 1987 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2098 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), | 1988 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), |
2099 RelocInfo::CODE_TARGET); | 1989 RelocInfo::CODE_TARGET); |
2100 __ CmpInstanceType(rcx, JS_BOUND_FUNCTION_TYPE); | |
2101 __ j(equal, masm->isolate()->builtins()->CallBoundFunction(), | |
2102 RelocInfo::CODE_TARGET); | |
2103 __ CmpInstanceType(rcx, JS_PROXY_TYPE); | 1990 __ CmpInstanceType(rcx, JS_PROXY_TYPE); |
2104 __ j(not_equal, &non_function); | 1991 __ j(not_equal, &non_function); |
2105 | 1992 |
2106 // 1. Runtime fallback for Proxy [[Call]]. | 1993 // 1. Runtime fallback for Proxy [[Call]]. |
2107 __ PopReturnAddressTo(kScratchRegister); | 1994 __ PopReturnAddressTo(kScratchRegister); |
2108 __ Push(rdi); | 1995 __ Push(rdi); |
2109 __ PushReturnAddressFrom(kScratchRegister); | 1996 __ PushReturnAddressFrom(kScratchRegister); |
2110 // Increase the arguments size to include the pushed function and the | 1997 // Increase the arguments size to include the pushed function and the |
2111 // existing receiver on the stack. | 1998 // existing receiver on the stack. |
2112 __ addp(rax, Immediate(2)); | 1999 __ addp(rax, Immediate(2)); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2155 // Tail call to the function-specific construct stub (still in the caller | 2042 // Tail call to the function-specific construct stub (still in the caller |
2156 // context at this point). | 2043 // context at this point). |
2157 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 2044 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
2158 __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset)); | 2045 __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset)); |
2159 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); | 2046 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); |
2160 __ jmp(rcx); | 2047 __ jmp(rcx); |
2161 } | 2048 } |
2162 | 2049 |
2163 | 2050 |
2164 // static | 2051 // static |
2165 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { | |
2166 // ----------- S t a t e ------------- | |
2167 // -- rax : the number of arguments (not including the receiver) | |
2168 // -- rdx : the new target (checked to be a constructor) | |
2169 // -- rdi : the constructor to call (checked to be a JSBoundFunction) | |
2170 // ----------------------------------- | |
2171 __ AssertBoundFunction(rdi); | |
2172 | |
2173 // Push the [[BoundArguments]] onto the stack. | |
2174 Generate_PushBoundArguments(masm); | |
2175 | |
2176 // Patch new.target to [[BoundTargetFunction]] if new.target equals target. | |
2177 { | |
2178 Label done; | |
2179 __ cmpp(rdi, rdx); | |
2180 __ j(not_equal, &done, Label::kNear); | |
2181 __ movp(rdx, | |
2182 FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset)); | |
2183 __ bind(&done); | |
2184 } | |
2185 | |
2186 // Construct the [[BoundTargetFunction]] via the Construct builtin. | |
2187 __ movp(rdi, FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset)); | |
2188 __ Load(rcx, ExternalReference(Builtins::kConstruct, masm->isolate())); | |
2189 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); | |
2190 __ jmp(rcx); | |
2191 } | |
2192 | |
2193 | |
2194 // static | |
2195 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { | 2052 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { |
2196 // ----------- S t a t e ------------- | 2053 // ----------- S t a t e ------------- |
2197 // -- rax : the number of arguments (not including the receiver) | 2054 // -- rax : the number of arguments (not including the receiver) |
2198 // -- rdi : the constructor to call (checked to be a JSProxy) | 2055 // -- rdi : the constructor to call (checked to be a JSProxy) |
2199 // -- rdx : the new target (either the same as the constructor or | 2056 // -- rdx : the new target (either the same as the constructor or |
2200 // the JSFunction on which new was invoked initially) | 2057 // the JSFunction on which new was invoked initially) |
2201 // ----------------------------------- | 2058 // ----------------------------------- |
2202 | 2059 |
2203 // Call into the Runtime for Proxy [[Construct]]. | 2060 // Call into the Runtime for Proxy [[Construct]]. |
2204 __ PopReturnAddressTo(kScratchRegister); | 2061 __ PopReturnAddressTo(kScratchRegister); |
(...skipping 24 matching lines...) Expand all Loading... |
2229 // Dispatch based on instance type. | 2086 // Dispatch based on instance type. |
2230 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2087 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2231 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), | 2088 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), |
2232 RelocInfo::CODE_TARGET); | 2089 RelocInfo::CODE_TARGET); |
2233 | 2090 |
2234 // Check if target has a [[Construct]] internal method. | 2091 // Check if target has a [[Construct]] internal method. |
2235 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 2092 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
2236 Immediate(1 << Map::kIsConstructor)); | 2093 Immediate(1 << Map::kIsConstructor)); |
2237 __ j(zero, &non_constructor, Label::kNear); | 2094 __ j(zero, &non_constructor, Label::kNear); |
2238 | 2095 |
2239 // Only dispatch to bound functions after checking whether they are | |
2240 // constructors. | |
2241 __ CmpInstanceType(rcx, JS_BOUND_FUNCTION_TYPE); | |
2242 __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), | |
2243 RelocInfo::CODE_TARGET); | |
2244 | |
2245 // Only dispatch to proxies after checking whether they are constructors. | 2096 // Only dispatch to proxies after checking whether they are constructors. |
2246 __ CmpInstanceType(rcx, JS_PROXY_TYPE); | 2097 __ CmpInstanceType(rcx, JS_PROXY_TYPE); |
2247 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), | 2098 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), |
2248 RelocInfo::CODE_TARGET); | 2099 RelocInfo::CODE_TARGET); |
2249 | 2100 |
2250 // Called Construct on an exotic Object with a [[Construct]] internal method. | 2101 // Called Construct on an exotic Object with a [[Construct]] internal method. |
2251 { | 2102 { |
2252 // Overwrite the original receiver with the (original) target. | 2103 // Overwrite the original receiver with the (original) target. |
2253 __ movp(args.GetReceiverOperand(), rdi); | 2104 __ movp(args.GetReceiverOperand(), rdi); |
2254 // Let the "call_as_constructor_delegate" take care of the rest. | 2105 // Let the "call_as_constructor_delegate" take care of the rest. |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2445 __ ret(0); | 2296 __ ret(0); |
2446 } | 2297 } |
2447 | 2298 |
2448 | 2299 |
2449 #undef __ | 2300 #undef __ |
2450 | 2301 |
2451 } // namespace internal | 2302 } // namespace internal |
2452 } // namespace v8 | 2303 } // namespace v8 |
2453 | 2304 |
2454 #endif // V8_TARGET_ARCH_X64 | 2305 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |