| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 2122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2133 Object* obj; | 2133 Object* obj; |
| 2134 { MaybeObject* maybe_obj = GenerateMissBranch(); | 2134 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 2135 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2135 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2136 } | 2136 } |
| 2137 | 2137 |
| 2138 // Return the generated code. | 2138 // Return the generated code. |
| 2139 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2139 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 2140 } | 2140 } |
| 2141 | 2141 |
| 2142 | 2142 |
| 2143 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 2144 const CallOptimization& optimization, |
| 2145 Object* object, |
| 2146 JSObject* holder, |
| 2147 JSGlobalPropertyCell* cell, |
| 2148 JSFunction* function, |
| 2149 String* name) { |
| 2150 ASSERT(optimization.is_simple_api_call()); |
| 2151 // Bail out if object is a global object as we don't want to |
| 2152 // repatch it to global receiver. |
| 2153 if (object->IsGlobalObject()) return Heap::undefined_value(); |
| 2154 if (cell != NULL) return Heap::undefined_value(); |
| 2155 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2156 JSObject::cast(object), holder); |
| 2157 if (depth == kInvalidProtoDepth) return Heap::undefined_value(); |
| 2158 |
| 2159 Label miss, miss_before_stack_reserved; |
| 2160 |
| 2161 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2162 |
| 2163 // Get the receiver from the stack. |
| 2164 const int argc = arguments().immediate(); |
| 2165 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2166 |
| 2167 // Check that the receiver isn't a smi. |
| 2168 __ test(edx, Immediate(kSmiTagMask)); |
| 2169 __ j(zero, &miss_before_stack_reserved, not_taken); |
| 2170 |
| 2171 __ IncrementCounter(&Counters::call_const, 1); |
| 2172 __ IncrementCounter(&Counters::call_const_fast_api, 1); |
| 2173 |
| 2174 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2175 // before calling any runtime function. |
| 2176 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
| 2177 |
| 2178 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2179 CheckPrototypes(JSObject::cast(object), edx, holder, |
| 2180 ebx, eax, edi, name, depth, &miss); |
| 2181 |
| 2182 // Move the return address on top of the stack. |
| 2183 __ mov(eax, Operand(esp, 3 * kPointerSize)); |
| 2184 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 2185 |
| 2186 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
| 2187 // duplicate of return address and will be overwritten. |
| 2188 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
| 2189 if (result->IsFailure()) return result; |
| 2190 |
| 2191 __ bind(&miss); |
| 2192 __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
| 2193 |
| 2194 __ bind(&miss_before_stack_reserved); |
| 2195 Object* obj; |
| 2196 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 2197 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2198 } |
| 2199 |
| 2200 // Return the generated code. |
| 2201 return GetCode(function); |
| 2202 } |
| 2203 |
| 2204 |
| 2143 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2205 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
| 2144 JSObject* holder, | 2206 JSObject* holder, |
| 2145 JSFunction* function, | 2207 JSFunction* function, |
| 2146 String* name, | 2208 String* name, |
| 2147 CheckType check) { | 2209 CheckType check) { |
| 2148 // ----------- S t a t e ------------- | 2210 // ----------- S t a t e ------------- |
| 2149 // -- ecx : name | 2211 // -- ecx : name |
| 2150 // -- esp[0] : return address | 2212 // -- esp[0] : return address |
| 2151 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2213 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2152 // -- ... | 2214 // -- ... |
| 2153 // -- esp[(argc + 1) * 4] : receiver | 2215 // -- esp[(argc + 1) * 4] : receiver |
| 2154 // ----------------------------------- | 2216 // ----------------------------------- |
| 2155 | 2217 |
| 2156 SharedFunctionInfo* function_info = function->shared(); | 2218 if (HasCustomCallGenerator(function)) { |
| 2157 if (function_info->HasBuiltinFunctionId()) { | |
| 2158 BuiltinFunctionId id = function_info->builtin_function_id(); | |
| 2159 MaybeObject* maybe_result = CompileCustomCall( | 2219 MaybeObject* maybe_result = CompileCustomCall( |
| 2160 id, object, holder, NULL, function, name); | 2220 object, holder, NULL, function, name); |
| 2161 Object* result; | 2221 Object* result; |
| 2162 if (!maybe_result->ToObject(&result)) return maybe_result; | 2222 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2163 // undefined means bail out to regular compiler. | 2223 // undefined means bail out to regular compiler. |
| 2164 if (!result->IsUndefined()) return result; | 2224 if (!result->IsUndefined()) return result; |
| 2165 } | 2225 } |
| 2166 | 2226 |
| 2167 Label miss_in_smi_check; | 2227 Label miss; |
| 2168 | 2228 |
| 2169 GenerateNameCheck(name, &miss_in_smi_check); | 2229 GenerateNameCheck(name, &miss); |
| 2170 | 2230 |
| 2171 // Get the receiver from the stack. | 2231 // Get the receiver from the stack. |
| 2172 const int argc = arguments().immediate(); | 2232 const int argc = arguments().immediate(); |
| 2173 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2233 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2174 | 2234 |
| 2175 // Check that the receiver isn't a smi. | 2235 // Check that the receiver isn't a smi. |
| 2176 if (check != NUMBER_CHECK) { | 2236 if (check != NUMBER_CHECK) { |
| 2177 __ test(edx, Immediate(kSmiTagMask)); | 2237 __ test(edx, Immediate(kSmiTagMask)); |
| 2178 __ j(zero, &miss_in_smi_check, not_taken); | 2238 __ j(zero, &miss, not_taken); |
| 2179 } | 2239 } |
| 2180 | 2240 |
| 2181 // Make sure that it's okay not to patch the on stack receiver | 2241 // Make sure that it's okay not to patch the on stack receiver |
| 2182 // unless we're doing a receiver map check. | 2242 // unless we're doing a receiver map check. |
| 2183 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2243 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2184 | 2244 |
| 2185 CallOptimization optimization(function); | 2245 SharedFunctionInfo* function_info = function->shared(); |
| 2186 int depth = kInvalidProtoDepth; | |
| 2187 Label miss; | |
| 2188 | |
| 2189 switch (check) { | 2246 switch (check) { |
| 2190 case RECEIVER_MAP_CHECK: | 2247 case RECEIVER_MAP_CHECK: |
| 2191 __ IncrementCounter(&Counters::call_const, 1); | 2248 __ IncrementCounter(&Counters::call_const, 1); |
| 2192 | 2249 |
| 2193 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { | |
| 2194 depth = optimization.GetPrototypeDepthOfExpectedType( | |
| 2195 JSObject::cast(object), holder); | |
| 2196 } | |
| 2197 | |
| 2198 if (depth != kInvalidProtoDepth) { | |
| 2199 __ IncrementCounter(&Counters::call_const_fast_api, 1); | |
| 2200 | |
| 2201 // Allocate space for v8::Arguments implicit values. Must be initialized | |
| 2202 // before to call any runtime function. | |
| 2203 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | |
| 2204 } | |
| 2205 | |
| 2206 // Check that the maps haven't changed. | 2250 // Check that the maps haven't changed. |
| 2207 CheckPrototypes(JSObject::cast(object), edx, holder, | 2251 CheckPrototypes(JSObject::cast(object), edx, holder, |
| 2208 ebx, eax, edi, name, depth, &miss); | 2252 ebx, eax, edi, name, &miss); |
| 2209 | 2253 |
| 2210 // Patch the receiver on the stack with the global proxy if | 2254 // Patch the receiver on the stack with the global proxy if |
| 2211 // necessary. | 2255 // necessary. |
| 2212 if (object->IsGlobalObject()) { | 2256 if (object->IsGlobalObject()) { |
| 2213 ASSERT(depth == kInvalidProtoDepth); | |
| 2214 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2257 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2215 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2258 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 2216 } | 2259 } |
| 2217 break; | 2260 break; |
| 2218 | 2261 |
| 2219 case STRING_CHECK: | 2262 case STRING_CHECK: |
| 2220 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2263 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2221 // Calling non-strict non-builtins with a value as the receiver | 2264 // Calling non-strict non-builtins with a value as the receiver |
| 2222 // requires boxing. | 2265 // requires boxing. |
| 2223 __ jmp(&miss); | 2266 __ jmp(&miss); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2274 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2317 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 2275 ebx, edx, edi, name, &miss); | 2318 ebx, edx, edi, name, &miss); |
| 2276 } | 2319 } |
| 2277 break; | 2320 break; |
| 2278 } | 2321 } |
| 2279 | 2322 |
| 2280 default: | 2323 default: |
| 2281 UNREACHABLE(); | 2324 UNREACHABLE(); |
| 2282 } | 2325 } |
| 2283 | 2326 |
| 2284 if (depth != kInvalidProtoDepth) { | 2327 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
| 2285 // Move the return address on top of the stack. | |
| 2286 __ mov(eax, Operand(esp, 3 * kPointerSize)); | |
| 2287 __ mov(Operand(esp, 0 * kPointerSize), eax); | |
| 2288 | |
| 2289 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | |
| 2290 // duplicate of return address and will be overwritten. | |
| 2291 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | |
| 2292 if (result->IsFailure()) return result; | |
| 2293 } else { | |
| 2294 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | |
| 2295 } | |
| 2296 | 2328 |
| 2297 // Handle call cache miss. | 2329 // Handle call cache miss. |
| 2298 __ bind(&miss); | 2330 __ bind(&miss); |
| 2299 if (depth != kInvalidProtoDepth) { | |
| 2300 __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | |
| 2301 } | |
| 2302 __ bind(&miss_in_smi_check); | |
| 2303 Object* obj; | 2331 Object* obj; |
| 2304 { MaybeObject* maybe_obj = GenerateMissBranch(); | 2332 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 2305 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2333 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2306 } | 2334 } |
| 2307 | 2335 |
| 2308 // Return the generated code. | 2336 // Return the generated code. |
| 2309 return GetCode(function); | 2337 return GetCode(function); |
| 2310 } | 2338 } |
| 2311 | 2339 |
| 2312 | 2340 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2384 JSFunction* function, | 2412 JSFunction* function, |
| 2385 String* name) { | 2413 String* name) { |
| 2386 // ----------- S t a t e ------------- | 2414 // ----------- S t a t e ------------- |
| 2387 // -- ecx : name | 2415 // -- ecx : name |
| 2388 // -- esp[0] : return address | 2416 // -- esp[0] : return address |
| 2389 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2417 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2390 // -- ... | 2418 // -- ... |
| 2391 // -- esp[(argc + 1) * 4] : receiver | 2419 // -- esp[(argc + 1) * 4] : receiver |
| 2392 // ----------------------------------- | 2420 // ----------------------------------- |
| 2393 | 2421 |
| 2394 SharedFunctionInfo* function_info = function->shared(); | 2422 if (HasCustomCallGenerator(function)) { |
| 2395 if (function_info->HasBuiltinFunctionId()) { | |
| 2396 BuiltinFunctionId id = function_info->builtin_function_id(); | |
| 2397 MaybeObject* maybe_result = CompileCustomCall( | 2423 MaybeObject* maybe_result = CompileCustomCall( |
| 2398 id, object, holder, cell, function, name); | 2424 object, holder, cell, function, name); |
| 2399 Object* result; | 2425 Object* result; |
| 2400 if (!maybe_result->ToObject(&result)) return maybe_result; | 2426 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2401 // undefined means bail out to regular compiler. | 2427 // undefined means bail out to regular compiler. |
| 2402 if (!result->IsUndefined()) return result; | 2428 if (!result->IsUndefined()) return result; |
| 2403 } | 2429 } |
| 2404 | 2430 |
| 2405 Label miss; | 2431 Label miss; |
| 2406 | 2432 |
| 2407 GenerateNameCheck(name, &miss); | 2433 GenerateNameCheck(name, &miss); |
| 2408 | 2434 |
| (...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3672 | 3698 |
| 3673 return GetCode(flags); | 3699 return GetCode(flags); |
| 3674 } | 3700 } |
| 3675 | 3701 |
| 3676 | 3702 |
| 3677 #undef __ | 3703 #undef __ |
| 3678 | 3704 |
| 3679 } } // namespace v8::internal | 3705 } } // namespace v8::internal |
| 3680 | 3706 |
| 3681 #endif // V8_TARGET_ARCH_IA32 | 3707 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |