| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1975 Object* obj; | 1975 Object* obj; |
| 1976 { MaybeObject* maybe_obj = GenerateMissBranch(); | 1976 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 1977 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1977 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1978 } | 1978 } |
| 1979 | 1979 |
| 1980 // Return the generated code. | 1980 // Return the generated code. |
| 1981 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 1981 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 1982 } | 1982 } |
| 1983 | 1983 |
| 1984 | 1984 |
| 1985 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 1986 const CallOptimization& optimization, |
| 1987 Object* object, |
| 1988 JSObject* holder, |
| 1989 JSGlobalPropertyCell* cell, |
| 1990 JSFunction* function, |
| 1991 String* name) { |
| 1992 ASSERT(optimization.is_simple_api_call()); |
| 1993 // Bail out if object is a global object as we don't want to |
| 1994 // repatch it to global receiver. |
| 1995 if (object->IsGlobalObject()) return Heap::undefined_value(); |
| 1996 if (cell != NULL) return Heap::undefined_value(); |
| 1997 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 1998 JSObject::cast(object), holder); |
| 1999 if (depth == kInvalidProtoDepth) return Heap::undefined_value(); |
| 2000 |
| 2001 Label miss, miss_before_stack_reserved; |
| 2002 |
| 2003 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2004 |
| 2005 // Get the receiver from the stack. |
| 2006 const int argc = arguments().immediate(); |
| 2007 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2008 |
| 2009 // Check that the receiver isn't a smi. |
| 2010 __ JumpIfSmi(rdx, &miss_before_stack_reserved); |
| 2011 |
| 2012 __ IncrementCounter(&Counters::call_const, 1); |
| 2013 __ IncrementCounter(&Counters::call_const_fast_api, 1); |
| 2014 |
| 2015 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2016 // before calling any runtime function. |
| 2017 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2018 |
| 2019 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2020 CheckPrototypes(JSObject::cast(object), rdx, holder, |
| 2021 rbx, rax, rdi, name, depth, &miss); |
| 2022 |
| 2023 // Move the return address on top of the stack. |
| 2024 __ movq(rax, Operand(rsp, 3 * kPointerSize)); |
| 2025 __ movq(Operand(rsp, 0 * kPointerSize), rax); |
| 2026 |
| 2027 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
| 2028 if (result->IsFailure()) return result; |
| 2029 |
| 2030 __ bind(&miss); |
| 2031 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2032 |
| 2033 __ bind(&miss_before_stack_reserved); |
| 2034 Object* obj; |
| 2035 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 2036 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2037 } |
| 2038 |
| 2039 // Return the generated code. |
| 2040 return GetCode(function); |
| 2041 } |
| 2042 |
| 2043 |
| 1985 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2044 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
| 1986 JSObject* holder, | 2045 JSObject* holder, |
| 1987 JSFunction* function, | 2046 JSFunction* function, |
| 1988 String* name, | 2047 String* name, |
| 1989 CheckType check) { | 2048 CheckType check) { |
| 1990 // ----------- S t a t e ------------- | 2049 // ----------- S t a t e ------------- |
| 1991 // rcx : function name | 2050 // rcx : function name |
| 1992 // rsp[0] : return address | 2051 // rsp[0] : return address |
| 1993 // rsp[8] : argument argc | 2052 // rsp[8] : argument argc |
| 1994 // rsp[16] : argument argc - 1 | 2053 // rsp[16] : argument argc - 1 |
| 1995 // ... | 2054 // ... |
| 1996 // rsp[argc * 8] : argument 1 | 2055 // rsp[argc * 8] : argument 1 |
| 1997 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2056 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1998 // ----------------------------------- | 2057 // ----------------------------------- |
| 1999 | 2058 |
| 2000 SharedFunctionInfo* function_info = function->shared(); | 2059 if (HasCustomCallGenerator(function)) { |
| 2001 if (function_info->HasBuiltinFunctionId()) { | |
| 2002 BuiltinFunctionId id = function_info->builtin_function_id(); | |
| 2003 MaybeObject* maybe_result = CompileCustomCall( | 2060 MaybeObject* maybe_result = CompileCustomCall( |
| 2004 id, object, holder, NULL, function, name); | 2061 object, holder, NULL, function, name); |
| 2005 Object* result; | 2062 Object* result; |
| 2006 if (!maybe_result->ToObject(&result)) return maybe_result; | 2063 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2007 // undefined means bail out to regular compiler. | 2064 // undefined means bail out to regular compiler. |
| 2008 if (!result->IsUndefined()) return result; | 2065 if (!result->IsUndefined()) return result; |
| 2009 } | 2066 } |
| 2010 | 2067 |
| 2011 Label miss_in_smi_check; | 2068 Label miss; |
| 2012 | 2069 |
| 2013 GenerateNameCheck(name, &miss_in_smi_check); | 2070 GenerateNameCheck(name, &miss); |
| 2014 | 2071 |
| 2015 // Get the receiver from the stack. | 2072 // Get the receiver from the stack. |
| 2016 const int argc = arguments().immediate(); | 2073 const int argc = arguments().immediate(); |
| 2017 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2074 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2018 | 2075 |
| 2019 // Check that the receiver isn't a smi. | 2076 // Check that the receiver isn't a smi. |
| 2020 if (check != NUMBER_CHECK) { | 2077 if (check != NUMBER_CHECK) { |
| 2021 __ JumpIfSmi(rdx, &miss_in_smi_check); | 2078 __ JumpIfSmi(rdx, &miss); |
| 2022 } | 2079 } |
| 2023 | 2080 |
| 2024 // Make sure that it's okay not to patch the on stack receiver | 2081 // Make sure that it's okay not to patch the on stack receiver |
| 2025 // unless we're doing a receiver map check. | 2082 // unless we're doing a receiver map check. |
| 2026 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2083 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2027 | 2084 |
| 2028 CallOptimization optimization(function); | 2085 SharedFunctionInfo* function_info = function->shared(); |
| 2029 int depth = kInvalidProtoDepth; | |
| 2030 Label miss; | |
| 2031 | |
| 2032 switch (check) { | 2086 switch (check) { |
| 2033 case RECEIVER_MAP_CHECK: | 2087 case RECEIVER_MAP_CHECK: |
| 2034 __ IncrementCounter(&Counters::call_const, 1); | 2088 __ IncrementCounter(&Counters::call_const, 1); |
| 2035 | 2089 |
| 2036 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { | |
| 2037 depth = optimization.GetPrototypeDepthOfExpectedType( | |
| 2038 JSObject::cast(object), holder); | |
| 2039 } | |
| 2040 | |
| 2041 if (depth != kInvalidProtoDepth) { | |
| 2042 __ IncrementCounter(&Counters::call_const_fast_api, 1); | |
| 2043 | |
| 2044 // Allocate space for v8::Arguments implicit values. Must be initialized | |
| 2045 // before to call any runtime function. | |
| 2046 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | |
| 2047 } | |
| 2048 | |
| 2049 // Check that the maps haven't changed. | 2090 // Check that the maps haven't changed. |
| 2050 CheckPrototypes(JSObject::cast(object), rdx, holder, | 2091 CheckPrototypes(JSObject::cast(object), rdx, holder, |
| 2051 rbx, rax, rdi, name, depth, &miss); | 2092 rbx, rax, rdi, name, &miss); |
| 2052 | 2093 |
| 2053 // Patch the receiver on the stack with the global proxy if | 2094 // Patch the receiver on the stack with the global proxy if |
| 2054 // necessary. | 2095 // necessary. |
| 2055 if (object->IsGlobalObject()) { | 2096 if (object->IsGlobalObject()) { |
| 2056 ASSERT(depth == kInvalidProtoDepth); | |
| 2057 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2097 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2058 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2098 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2059 } | 2099 } |
| 2060 break; | 2100 break; |
| 2061 | 2101 |
| 2062 case STRING_CHECK: | 2102 case STRING_CHECK: |
| 2063 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2103 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2064 // Calling non-strict non-builtins with a value as the receiver | 2104 // Calling non-strict non-builtins with a value as the receiver |
| 2065 // requires boxing. | 2105 // requires boxing. |
| 2066 __ jmp(&miss); | 2106 __ jmp(&miss); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2116 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 2156 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 2117 rbx, rdx, rdi, name, &miss); | 2157 rbx, rdx, rdi, name, &miss); |
| 2118 } | 2158 } |
| 2119 break; | 2159 break; |
| 2120 } | 2160 } |
| 2121 | 2161 |
| 2122 default: | 2162 default: |
| 2123 UNREACHABLE(); | 2163 UNREACHABLE(); |
| 2124 } | 2164 } |
| 2125 | 2165 |
| 2126 if (depth != kInvalidProtoDepth) { | 2166 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
| 2127 // Move the return address on top of the stack. | |
| 2128 __ movq(rax, Operand(rsp, 3 * kPointerSize)); | |
| 2129 __ movq(Operand(rsp, 0 * kPointerSize), rax); | |
| 2130 | |
| 2131 // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains | |
| 2132 // duplicate of return address and will be overwritten. | |
| 2133 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | |
| 2134 if (result->IsFailure()) return result; | |
| 2135 } else { | |
| 2136 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | |
| 2137 } | |
| 2138 | 2167 |
| 2139 // Handle call cache miss. | 2168 // Handle call cache miss. |
| 2140 __ bind(&miss); | 2169 __ bind(&miss); |
| 2141 if (depth != kInvalidProtoDepth) { | |
| 2142 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | |
| 2143 } | |
| 2144 | |
| 2145 // Handle call cache miss. | |
| 2146 __ bind(&miss_in_smi_check); | |
| 2147 Object* obj; | 2170 Object* obj; |
| 2148 { MaybeObject* maybe_obj = GenerateMissBranch(); | 2171 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 2149 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2172 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2150 } | 2173 } |
| 2151 | 2174 |
| 2152 // Return the generated code. | 2175 // Return the generated code. |
| 2153 return GetCode(function); | 2176 return GetCode(function); |
| 2154 } | 2177 } |
| 2155 | 2178 |
| 2156 | 2179 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2231 // ----------- S t a t e ------------- | 2254 // ----------- S t a t e ------------- |
| 2232 // rcx : function name | 2255 // rcx : function name |
| 2233 // rsp[0] : return address | 2256 // rsp[0] : return address |
| 2234 // rsp[8] : argument argc | 2257 // rsp[8] : argument argc |
| 2235 // rsp[16] : argument argc - 1 | 2258 // rsp[16] : argument argc - 1 |
| 2236 // ... | 2259 // ... |
| 2237 // rsp[argc * 8] : argument 1 | 2260 // rsp[argc * 8] : argument 1 |
| 2238 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2261 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2239 // ----------------------------------- | 2262 // ----------------------------------- |
| 2240 | 2263 |
| 2241 SharedFunctionInfo* function_info = function->shared(); | 2264 if (HasCustomCallGenerator(function)) { |
| 2242 if (function_info->HasBuiltinFunctionId()) { | |
| 2243 BuiltinFunctionId id = function_info->builtin_function_id(); | |
| 2244 MaybeObject* maybe_result = CompileCustomCall( | 2265 MaybeObject* maybe_result = CompileCustomCall( |
| 2245 id, object, holder, cell, function, name); | 2266 object, holder, cell, function, name); |
| 2246 Object* result; | 2267 Object* result; |
| 2247 if (!maybe_result->ToObject(&result)) return maybe_result; | 2268 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2248 // undefined means bail out to regular compiler. | 2269 // undefined means bail out to regular compiler. |
| 2249 if (!result->IsUndefined()) return result; | 2270 if (!result->IsUndefined()) return result; |
| 2250 } | 2271 } |
| 2251 | 2272 |
| 2252 Label miss; | 2273 Label miss; |
| 2253 | 2274 |
| 2254 GenerateNameCheck(name, &miss); | 2275 GenerateNameCheck(name, &miss); |
| 2255 | 2276 |
| (...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2953 | 2974 |
| 2954 // Return the generated code. | 2975 // Return the generated code. |
| 2955 return GetCode(CALLBACKS, name); | 2976 return GetCode(CALLBACKS, name); |
| 2956 } | 2977 } |
| 2957 | 2978 |
| 2958 | 2979 |
| 2959 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { | 2980 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
| 2960 // ----------- S t a t e ------------- | 2981 // ----------- S t a t e ------------- |
| 2961 // -- rax : key | 2982 // -- rax : key |
| 2962 // -- rdx : receiver | 2983 // -- rdx : receiver |
| 2963 // -- esp[0] : return address | 2984 // -- rsp[0] : return address |
| 2964 // ----------------------------------- | 2985 // ----------------------------------- |
| 2965 Label miss; | 2986 Label miss; |
| 2966 | 2987 |
| 2967 // Check that the receiver isn't a smi. | 2988 // Check that the receiver isn't a smi. |
| 2968 __ JumpIfSmi(rdx, &miss); | 2989 __ JumpIfSmi(rdx, &miss); |
| 2969 | 2990 |
| 2970 // Check that the map matches. | 2991 // Check that the map matches. |
| 2971 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | 2992 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), |
| 2972 Handle<Map>(receiver->map())); | 2993 Handle<Map>(receiver->map())); |
| 2973 __ j(not_equal, &miss); | 2994 __ j(not_equal, &miss); |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3423 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); | 3444 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); |
| 3424 | 3445 |
| 3425 return GetCode(flags); | 3446 return GetCode(flags); |
| 3426 } | 3447 } |
| 3427 | 3448 |
| 3428 #undef __ | 3449 #undef __ |
| 3429 | 3450 |
| 3430 } } // namespace v8::internal | 3451 } } // namespace v8::internal |
| 3431 | 3452 |
| 3432 #endif // V8_TARGET_ARCH_X64 | 3453 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |