| 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 1139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1150 // Go to the next object in the prototype chain. | 1150 // Go to the next object in the prototype chain. |
| 1151 current = prototype; | 1151 current = prototype; |
| 1152 } | 1152 } |
| 1153 | 1153 |
| 1154 // Check the holder map. | 1154 // Check the holder map. |
| 1155 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1155 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1156 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); | 1156 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); |
| 1157 __ b(ne, miss); | 1157 __ b(ne, miss); |
| 1158 | 1158 |
| 1159 // Log the check depth. | 1159 // Log the check depth. |
| 1160 LOG(IntEvent("check-maps-depth", depth + 1)); | 1160 LOG(Isolate::Current(), IntEvent("check-maps-depth", depth + 1)); |
| 1161 | 1161 |
| 1162 // Perform security check for access to the global object. | 1162 // Perform security check for access to the global object. |
| 1163 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1163 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 1164 if (holder->IsJSGlobalProxy()) { | 1164 if (holder->IsJSGlobalProxy()) { |
| 1165 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1165 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1166 }; | 1166 }; |
| 1167 | 1167 |
| 1168 // If we've skipped any global objects, it's not enough to verify | 1168 // If we've skipped any global objects, it's not enough to verify |
| 1169 // that their maps haven't changed. We also need to check that the | 1169 // that their maps haven't changed. We also need to check that the |
| 1170 // property cell for the property is still empty. | 1170 // property cell for the property is still empty. |
| (...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2276 Object* obj; | 2276 Object* obj; |
| 2277 { MaybeObject* maybe_obj = GenerateMissBranch(); | 2277 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 2278 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2278 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2279 } | 2279 } |
| 2280 | 2280 |
| 2281 // Return the generated code. | 2281 // Return the generated code. |
| 2282 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2282 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 2283 } | 2283 } |
| 2284 | 2284 |
| 2285 | 2285 |
| 2286 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 2287 const CallOptimization& optimization, |
| 2288 Object* object, |
| 2289 JSObject* holder, |
| 2290 JSGlobalPropertyCell* cell, |
| 2291 JSFunction* function, |
| 2292 String* name) { |
| 2293 ASSERT(optimization.is_simple_api_call()); |
| 2294 // Bail out if object is a global object as we don't want to |
| 2295 // repatch it to global receiver. |
| 2296 if (object->IsGlobalObject()) return HEAP->undefined_value(); |
| 2297 if (cell != NULL) return HEAP->undefined_value(); |
| 2298 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2299 JSObject::cast(object), holder); |
| 2300 if (depth == kInvalidProtoDepth) return HEAP->undefined_value(); |
| 2301 |
| 2302 Label miss, miss_before_stack_reserved; |
| 2303 |
| 2304 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2305 |
| 2306 // Get the receiver from the stack. |
| 2307 const int argc = arguments().immediate(); |
| 2308 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2309 |
| 2310 // Check that the receiver isn't a smi. |
| 2311 __ tst(r1, Operand(kSmiTagMask)); |
| 2312 __ b(eq, &miss_before_stack_reserved); |
| 2313 |
| 2314 __ IncrementCounter(COUNTERS->call_const(), 1, r0, r3); |
| 2315 __ IncrementCounter(COUNTERS->call_const_fast_api(), 1, r0, r3); |
| 2316 |
| 2317 ReserveSpaceForFastApiCall(masm(), r0); |
| 2318 |
| 2319 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2320 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, |
| 2321 depth, &miss); |
| 2322 |
| 2323 MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); |
| 2324 if (result->IsFailure()) return result; |
| 2325 |
| 2326 __ bind(&miss); |
| 2327 FreeSpaceForFastApiCall(masm()); |
| 2328 |
| 2329 __ bind(&miss_before_stack_reserved); |
| 2330 Object* obj; |
| 2331 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 2332 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2333 } |
| 2334 |
| 2335 // Return the generated code. |
| 2336 return GetCode(function); |
| 2337 } |
| 2338 |
| 2339 |
| 2286 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2340 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
| 2287 JSObject* holder, | 2341 JSObject* holder, |
| 2288 JSFunction* function, | 2342 JSFunction* function, |
| 2289 String* name, | 2343 String* name, |
| 2290 CheckType check) { | 2344 CheckType check) { |
| 2291 // ----------- S t a t e ------------- | 2345 // ----------- S t a t e ------------- |
| 2292 // -- r2 : name | 2346 // -- r2 : name |
| 2293 // -- lr : return address | 2347 // -- lr : return address |
| 2294 // ----------------------------------- | 2348 // ----------------------------------- |
| 2295 SharedFunctionInfo* function_info = function->shared(); | 2349 if (HasCustomCallGenerator(function)) { |
| 2296 if (function_info->HasBuiltinFunctionId()) { | |
| 2297 BuiltinFunctionId id = function_info->builtin_function_id(); | |
| 2298 MaybeObject* maybe_result = CompileCustomCall( | 2350 MaybeObject* maybe_result = CompileCustomCall( |
| 2299 id, object, holder, NULL, function, name); | 2351 object, holder, NULL, function, name); |
| 2300 Object* result; | 2352 Object* result; |
| 2301 if (!maybe_result->ToObject(&result)) return maybe_result; | 2353 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2302 // undefined means bail out to regular compiler. | 2354 // undefined means bail out to regular compiler. |
| 2303 if (!result->IsUndefined()) { | 2355 if (!result->IsUndefined()) return result; |
| 2304 return result; | |
| 2305 } | |
| 2306 } | 2356 } |
| 2307 | 2357 |
| 2308 Label miss_in_smi_check; | 2358 Label miss; |
| 2309 | 2359 |
| 2310 GenerateNameCheck(name, &miss_in_smi_check); | 2360 GenerateNameCheck(name, &miss); |
| 2311 | 2361 |
| 2312 // Get the receiver from the stack | 2362 // Get the receiver from the stack |
| 2313 const int argc = arguments().immediate(); | 2363 const int argc = arguments().immediate(); |
| 2314 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2364 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2315 | 2365 |
| 2316 // Check that the receiver isn't a smi. | 2366 // Check that the receiver isn't a smi. |
| 2317 if (check != NUMBER_CHECK) { | 2367 if (check != NUMBER_CHECK) { |
| 2318 __ tst(r1, Operand(kSmiTagMask)); | 2368 __ tst(r1, Operand(kSmiTagMask)); |
| 2319 __ b(eq, &miss_in_smi_check); | 2369 __ b(eq, &miss); |
| 2320 } | 2370 } |
| 2321 | 2371 |
| 2322 // Make sure that it's okay not to patch the on stack receiver | 2372 // Make sure that it's okay not to patch the on stack receiver |
| 2323 // unless we're doing a receiver map check. | 2373 // unless we're doing a receiver map check. |
| 2324 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2374 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2325 | 2375 |
| 2326 CallOptimization optimization(function); | 2376 SharedFunctionInfo* function_info = function->shared(); |
| 2327 int depth = kInvalidProtoDepth; | |
| 2328 Label miss; | |
| 2329 | |
| 2330 switch (check) { | 2377 switch (check) { |
| 2331 case RECEIVER_MAP_CHECK: | 2378 case RECEIVER_MAP_CHECK: |
| 2332 __ IncrementCounter(COUNTERS->call_const(), 1, r0, r3); | 2379 __ IncrementCounter(COUNTERS->call_const(), 1, r0, r3); |
| 2333 | 2380 |
| 2334 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { | |
| 2335 depth = optimization.GetPrototypeDepthOfExpectedType( | |
| 2336 JSObject::cast(object), holder); | |
| 2337 } | |
| 2338 | |
| 2339 if (depth != kInvalidProtoDepth) { | |
| 2340 __ IncrementCounter(COUNTERS->call_const_fast_api(), 1, r0, r3); | |
| 2341 ReserveSpaceForFastApiCall(masm(), r0); | |
| 2342 } | |
| 2343 | |
| 2344 // Check that the maps haven't changed. | 2381 // Check that the maps haven't changed. |
| 2345 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2382 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, |
| 2346 depth, &miss); | 2383 &miss); |
| 2347 | 2384 |
| 2348 // Patch the receiver on the stack with the global proxy if | 2385 // Patch the receiver on the stack with the global proxy if |
| 2349 // necessary. | 2386 // necessary. |
| 2350 if (object->IsGlobalObject()) { | 2387 if (object->IsGlobalObject()) { |
| 2351 ASSERT(depth == kInvalidProtoDepth); | |
| 2352 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2388 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
| 2353 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 2389 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
| 2354 } | 2390 } |
| 2355 break; | 2391 break; |
| 2356 | 2392 |
| 2357 case STRING_CHECK: | 2393 case STRING_CHECK: |
| 2358 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2394 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2359 // Calling non-strict non-builtins with a value as the receiver | 2395 // Calling non-strict non-builtins with a value as the receiver |
| 2360 // requires boxing. | 2396 // requires boxing. |
| 2361 __ jmp(&miss); | 2397 __ jmp(&miss); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2414 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2450 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
| 2415 r1, r4, name, &miss); | 2451 r1, r4, name, &miss); |
| 2416 } | 2452 } |
| 2417 break; | 2453 break; |
| 2418 } | 2454 } |
| 2419 | 2455 |
| 2420 default: | 2456 default: |
| 2421 UNREACHABLE(); | 2457 UNREACHABLE(); |
| 2422 } | 2458 } |
| 2423 | 2459 |
| 2424 if (depth != kInvalidProtoDepth) { | 2460 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
| 2425 MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); | |
| 2426 if (result->IsFailure()) return result; | |
| 2427 } else { | |
| 2428 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | |
| 2429 } | |
| 2430 | 2461 |
| 2431 // Handle call cache miss. | 2462 // Handle call cache miss. |
| 2432 __ bind(&miss); | 2463 __ bind(&miss); |
| 2433 if (depth != kInvalidProtoDepth) { | |
| 2434 FreeSpaceForFastApiCall(masm()); | |
| 2435 } | |
| 2436 | |
| 2437 __ bind(&miss_in_smi_check); | |
| 2438 Object* obj; | 2464 Object* obj; |
| 2439 { MaybeObject* maybe_obj = GenerateMissBranch(); | 2465 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 2440 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2466 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2441 } | 2467 } |
| 2442 | 2468 |
| 2443 // Return the generated code. | 2469 // Return the generated code. |
| 2444 return GetCode(function); | 2470 return GetCode(function); |
| 2445 } | 2471 } |
| 2446 | 2472 |
| 2447 | 2473 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2503 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, | 2529 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, |
| 2504 GlobalObject* holder, | 2530 GlobalObject* holder, |
| 2505 JSGlobalPropertyCell* cell, | 2531 JSGlobalPropertyCell* cell, |
| 2506 JSFunction* function, | 2532 JSFunction* function, |
| 2507 String* name) { | 2533 String* name) { |
| 2508 // ----------- S t a t e ------------- | 2534 // ----------- S t a t e ------------- |
| 2509 // -- r2 : name | 2535 // -- r2 : name |
| 2510 // -- lr : return address | 2536 // -- lr : return address |
| 2511 // ----------------------------------- | 2537 // ----------------------------------- |
| 2512 | 2538 |
| 2513 SharedFunctionInfo* function_info = function->shared(); | 2539 if (HasCustomCallGenerator(function)) { |
| 2514 if (function_info->HasBuiltinFunctionId()) { | |
| 2515 BuiltinFunctionId id = function_info->builtin_function_id(); | |
| 2516 MaybeObject* maybe_result = CompileCustomCall( | 2540 MaybeObject* maybe_result = CompileCustomCall( |
| 2517 id, object, holder, cell, function, name); | 2541 object, holder, cell, function, name); |
| 2518 Object* result; | 2542 Object* result; |
| 2519 if (!maybe_result->ToObject(&result)) return maybe_result; | 2543 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2520 // undefined means bail out to regular compiler. | 2544 // undefined means bail out to regular compiler. |
| 2521 if (!result->IsUndefined()) return result; | 2545 if (!result->IsUndefined()) return result; |
| 2522 } | 2546 } |
| 2523 | 2547 |
| 2524 Label miss; | 2548 Label miss; |
| 2525 | 2549 |
| 2526 GenerateNameCheck(name, &miss); | 2550 GenerateNameCheck(name, &miss); |
| 2527 | 2551 |
| (...skipping 1474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4002 | 4026 |
| 4003 return GetCode(flags); | 4027 return GetCode(flags); |
| 4004 } | 4028 } |
| 4005 | 4029 |
| 4006 | 4030 |
| 4007 #undef __ | 4031 #undef __ |
| 4008 | 4032 |
| 4009 } } // namespace v8::internal | 4033 } } // namespace v8::internal |
| 4010 | 4034 |
| 4011 #endif // V8_TARGET_ARCH_ARM | 4035 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |