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