Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 } | 392 } |
| 393 | 393 |
| 394 | 394 |
| 395 void CompareIC::Clear(Address address, Code* target) { | 395 void CompareIC::Clear(Address address, Code* target) { |
| 396 ASSERT(target->major_key() == CodeStub::CompareIC); | 396 ASSERT(target->major_key() == CodeStub::CompareIC); |
| 397 CompareIC::State handler_state; | 397 CompareIC::State handler_state; |
| 398 Token::Value op; | 398 Token::Value op; |
| 399 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, | 399 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, |
| 400 &handler_state, &op); | 400 &handler_state, &op); |
| 401 // Only clear CompareICs that can retain objects. | 401 // Only clear CompareICs that can retain objects. |
| 402 if (handler_state != KNOWN_OBJECTS) return; | 402 if (handler_state != KNOWN_OBJECT) return; |
| 403 SetTargetAtAddress(address, GetRawUninitialized(op)); | 403 SetTargetAtAddress(address, GetRawUninitialized(op)); |
| 404 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 404 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
| 405 } | 405 } |
| 406 | 406 |
| 407 | 407 |
| 408 static bool HasInterceptorGetter(JSObject* object) { | 408 static bool HasInterceptorGetter(JSObject* object) { |
| 409 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | 409 return !object->GetNamedInterceptor()->getter()->IsUndefined(); |
| 410 } | 410 } |
| 411 | 411 |
| 412 | 412 |
| (...skipping 1953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2366 Handle<Code> CompareIC::GetUninitialized(Token::Value op) { | 2366 Handle<Code> CompareIC::GetUninitialized(Token::Value op) { |
| 2367 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2367 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
| 2368 return stub.GetCode(); | 2368 return stub.GetCode(); |
| 2369 } | 2369 } |
| 2370 | 2370 |
| 2371 | 2371 |
| 2372 const char* CompareIC::GetStateName(State state) { | 2372 const char* CompareIC::GetStateName(State state) { |
| 2373 switch (state) { | 2373 switch (state) { |
| 2374 case UNINITIALIZED: return "UNINITIALIZED"; | 2374 case UNINITIALIZED: return "UNINITIALIZED"; |
| 2375 case SMI: return "SMI"; | 2375 case SMI: return "SMI"; |
| 2376 case HEAP_NUMBER: return "HEAP_NUMBER"; | 2376 case NUMBER: return "NUMBER"; |
| 2377 case OBJECT: return "OBJECTS"; | |
| 2378 case KNOWN_OBJECTS: return "KNOWN_OBJECTS"; | |
| 2379 case SYMBOL: return "SYMBOL"; | 2377 case SYMBOL: return "SYMBOL"; |
| 2380 case STRING: return "STRING"; | 2378 case STRING: return "STRING"; |
| 2379 case OBJECT: return "OBJECT"; | |
| 2380 case KNOWN_OBJECT: return "KNOWN_OBJECT"; | |
| 2381 case GENERIC: return "GENERIC"; | 2381 case GENERIC: return "GENERIC"; |
| 2382 default: | 2382 default: |
| 2383 UNREACHABLE(); | 2383 UNREACHABLE(); |
| 2384 return NULL; | 2384 return NULL; |
| 2385 } | 2385 } |
| 2386 } | 2386 } |
| 2387 | 2387 |
| 2388 | 2388 |
| 2389 static CompareIC::State InputState(CompareIC::State old_state, | 2389 static CompareIC::State InputState(CompareIC::State old_state, |
| 2390 Handle<Object> value) { | 2390 Handle<Object> value) { |
| 2391 switch (old_state) { | 2391 switch (old_state) { |
| 2392 case CompareIC::UNINITIALIZED: | 2392 case CompareIC::UNINITIALIZED: |
| 2393 if (value->IsSmi()) return CompareIC::SMI; | 2393 if (value->IsSmi()) return CompareIC::SMI; |
| 2394 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER; | 2394 if (value->IsHeapNumber()) return CompareIC::NUMBER; |
| 2395 if (value->IsSymbol()) return CompareIC::SYMBOL; | 2395 if (value->IsSymbol()) return CompareIC::SYMBOL; |
| 2396 if (value->IsString()) return CompareIC::STRING; | 2396 if (value->IsString()) return CompareIC::STRING; |
| 2397 if (value->IsJSObject()) return CompareIC::OBJECT; | 2397 if (value->IsJSObject()) return CompareIC::OBJECT; |
| 2398 break; | 2398 break; |
| 2399 case CompareIC::SMI: | 2399 case CompareIC::SMI: |
| 2400 if (value->IsSmi()) return CompareIC::SMI; | 2400 if (value->IsSmi()) return CompareIC::SMI; |
| 2401 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER; | 2401 if (value->IsHeapNumber()) return CompareIC::NUMBER; |
| 2402 break; | 2402 break; |
| 2403 case CompareIC::HEAP_NUMBER: | 2403 case CompareIC::NUMBER: |
| 2404 if (value->IsNumber()) return CompareIC::HEAP_NUMBER; | 2404 if (value->IsNumber()) return CompareIC::NUMBER; |
| 2405 break; | 2405 break; |
| 2406 case CompareIC::SYMBOL: | 2406 case CompareIC::SYMBOL: |
| 2407 if (value->IsSymbol()) return CompareIC::SYMBOL; | 2407 if (value->IsSymbol()) return CompareIC::SYMBOL; |
| 2408 if (value->IsString()) return CompareIC::STRING; | 2408 if (value->IsString()) return CompareIC::STRING; |
| 2409 break; | 2409 break; |
| 2410 case CompareIC::STRING: | 2410 case CompareIC::STRING: |
| 2411 if (value->IsSymbol() || value->IsString()) return CompareIC::STRING; | 2411 if (value->IsSymbol() || value->IsString()) return CompareIC::STRING; |
| 2412 break; | 2412 break; |
| 2413 case CompareIC::OBJECT: | 2413 case CompareIC::OBJECT: |
| 2414 if (value->IsJSObject()) return CompareIC::OBJECT; | 2414 if (value->IsJSObject()) return CompareIC::OBJECT; |
| 2415 break; | 2415 break; |
| 2416 case CompareIC::GENERIC: | 2416 case CompareIC::GENERIC: |
| 2417 break; | 2417 break; |
| 2418 case CompareIC::KNOWN_OBJECTS: | 2418 case CompareIC::KNOWN_OBJECT: |
| 2419 UNREACHABLE(); | 2419 UNREACHABLE(); |
| 2420 break; | 2420 break; |
| 2421 } | 2421 } |
| 2422 return CompareIC::GENERIC; | 2422 return CompareIC::GENERIC; |
| 2423 } | 2423 } |
| 2424 | 2424 |
| 2425 | 2425 |
| 2426 CompareIC::State CompareIC::TargetState(State old_state, | 2426 CompareIC::State CompareIC::TargetState(State old_state, |
| 2427 State old_left, | 2427 State old_left, |
| 2428 State old_right, | 2428 State old_right, |
| 2429 bool has_inlined_smi_code, | 2429 bool has_inlined_smi_code, |
| 2430 Handle<Object> x, | 2430 Handle<Object> x, |
| 2431 Handle<Object> y) { | 2431 Handle<Object> y) { |
| 2432 switch (old_state) { | 2432 switch (old_state) { |
| 2433 case UNINITIALIZED: | 2433 case UNINITIALIZED: |
| 2434 if (x->IsSmi() && y->IsSmi()) return SMI; | 2434 if (x->IsSmi() && y->IsSmi()) return SMI; |
| 2435 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBER; | 2435 if (x->IsNumber() && y->IsNumber()) return NUMBER; |
| 2436 if (Token::IsOrderedRelationalCompareOp(op_)) { | 2436 if (Token::IsOrderedRelationalCompareOp(op_)) { |
| 2437 // Ordered comparisons treat undefined as NaN, so the | 2437 // Ordered comparisons treat undefined as NaN, so the |
| 2438 // HEAP_NUMBER stub will do the right thing. | 2438 // HEAP_NUMBER stub will do the right thing. |
|
Jakob Kummerow
2013/02/15 09:12:53
s/HEAP_//
rossberg
2013/02/19 11:32:13
Done.
| |
| 2439 if ((x->IsNumber() && y->IsUndefined()) || | 2439 if ((x->IsNumber() && y->IsUndefined()) || |
| 2440 (y->IsNumber() && x->IsUndefined())) { | 2440 (y->IsNumber() && x->IsUndefined())) { |
| 2441 return HEAP_NUMBER; | 2441 return NUMBER; |
| 2442 } | 2442 } |
| 2443 } | 2443 } |
| 2444 if (x->IsSymbol() && y->IsSymbol()) { | 2444 if (x->IsSymbol() && y->IsSymbol()) { |
| 2445 // We compare symbols as strings if we need to determine | 2445 // We compare symbols as strings if we need to determine |
| 2446 // the order in a non-equality compare. | 2446 // the order in a non-equality compare. |
| 2447 return Token::IsEqualityOp(op_) ? SYMBOL : STRING; | 2447 return Token::IsEqualityOp(op_) ? SYMBOL : STRING; |
| 2448 } | 2448 } |
| 2449 if (x->IsString() && y->IsString()) return STRING; | 2449 if (x->IsString() && y->IsString()) return STRING; |
| 2450 if (!Token::IsEqualityOp(op_)) return GENERIC; | 2450 if (!Token::IsEqualityOp(op_)) return GENERIC; |
| 2451 if (x->IsJSObject() && y->IsJSObject()) { | 2451 if (x->IsJSObject() && y->IsJSObject()) { |
| 2452 if (Handle<JSObject>::cast(x)->map() == | 2452 if (Handle<JSObject>::cast(x)->map() == |
| 2453 Handle<JSObject>::cast(y)->map() && | 2453 Handle<JSObject>::cast(y)->map()) { |
| 2454 Token::IsEqualityOp(op_)) { | 2454 return KNOWN_OBJECT; |
| 2455 return KNOWN_OBJECTS; | |
| 2456 } else { | 2455 } else { |
| 2457 return OBJECT; | 2456 return OBJECT; |
| 2458 } | 2457 } |
| 2459 } | 2458 } |
| 2460 return GENERIC; | 2459 return GENERIC; |
| 2461 case SMI: | 2460 case SMI: |
| 2462 return x->IsNumber() && y->IsNumber() | 2461 return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC; |
| 2463 ? HEAP_NUMBER | |
| 2464 : GENERIC; | |
| 2465 case SYMBOL: | 2462 case SYMBOL: |
| 2466 ASSERT(Token::IsEqualityOp(op_)); | 2463 ASSERT(Token::IsEqualityOp(op_)); |
| 2467 return x->IsString() && y->IsString() ? STRING : GENERIC; | 2464 return x->IsString() && y->IsString() ? STRING : GENERIC; |
| 2468 case HEAP_NUMBER: | 2465 case NUMBER: |
| 2469 if (old_left == SMI && x->IsHeapNumber()) return HEAP_NUMBER; | 2466 // If the failure was due to one side changing from smi to heap number, |
| 2470 if (old_right == SMI && y->IsHeapNumber()) return HEAP_NUMBER; | 2467 // then keep the state (if other changed at the same time, we will get |
| 2468 // a second miss and then go to generic). | |
| 2469 if (old_left == SMI && x->IsHeapNumber()) return NUMBER; | |
| 2470 if (old_right == SMI && y->IsHeapNumber()) return NUMBER; | |
| 2471 return GENERIC; | |
| 2472 case KNOWN_OBJECT: | |
| 2473 ASSERT(Token::IsEqualityOp(op_)); | |
| 2474 if (x->IsJSObject() && y->IsJSObject()) { | |
| 2475 if (Handle<JSObject>::cast(x)->map() == | |
| 2476 Handle<JSObject>::cast(y)->map()) { | |
| 2477 return KNOWN_OBJECT; | |
|
Jakob Kummerow
2013/02/15 09:12:53
We should not have a KNOWN_OBJECT -> KNOWN_OBJECT
rossberg
2013/02/19 11:32:13
Done.
| |
| 2478 } else { | |
| 2479 return OBJECT; | |
| 2480 } | |
| 2481 } | |
| 2482 return GENERIC; | |
| 2471 case STRING: | 2483 case STRING: |
| 2472 case OBJECT: | 2484 case OBJECT: |
| 2473 case KNOWN_OBJECTS: | |
| 2474 case GENERIC: | 2485 case GENERIC: |
| 2475 return GENERIC; | 2486 return GENERIC; |
| 2476 } | 2487 } |
| 2477 UNREACHABLE(); | 2488 UNREACHABLE(); |
| 2478 return GENERIC; // Make the compiler happy. | 2489 return GENERIC; // Make the compiler happy. |
| 2479 } | 2490 } |
| 2480 | 2491 |
| 2481 | 2492 |
| 2482 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { | 2493 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { |
| 2483 HandleScope scope; | 2494 HandleScope scope; |
| 2484 State previous_left, previous_right, previous_state; | 2495 State previous_left, previous_right, previous_state; |
| 2485 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, | 2496 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, |
| 2486 &previous_right, &previous_state, NULL); | 2497 &previous_right, &previous_state, NULL); |
| 2487 State new_left = InputState(previous_left, x); | 2498 State new_left = InputState(previous_left, x); |
| 2488 State new_right = InputState(previous_right, y); | 2499 State new_right = InputState(previous_right, y); |
| 2489 State state = TargetState(previous_state, previous_left, previous_right, | 2500 State state = TargetState(previous_state, previous_left, previous_right, |
| 2490 HasInlinedSmiCode(address()), x, y); | 2501 HasInlinedSmiCode(address()), x, y); |
| 2491 ICCompareStub stub(op_, new_left, new_right, state); | 2502 ICCompareStub stub(op_, new_left, new_right, state); |
| 2492 if (state == KNOWN_OBJECTS) { | 2503 if (state == KNOWN_OBJECT) { |
| 2493 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); | 2504 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); |
| 2494 } | 2505 } |
| 2495 set_target(*stub.GetCode()); | 2506 set_target(*stub.GetCode()); |
| 2496 | 2507 |
| 2497 #ifdef DEBUG | 2508 #ifdef DEBUG |
| 2498 if (FLAG_trace_ic) { | 2509 if (FLAG_trace_ic) { |
| 2499 PrintF("[CompareIC in "); | 2510 PrintF("[CompareIC in "); |
| 2500 JavaScriptFrame::PrintTop(stdout, false, true); | 2511 JavaScriptFrame::PrintTop(stdout, false, true); |
| 2501 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", | 2512 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", |
| 2502 GetStateName(previous_left), | 2513 GetStateName(previous_left), |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2559 #undef ADDR | 2570 #undef ADDR |
| 2560 }; | 2571 }; |
| 2561 | 2572 |
| 2562 | 2573 |
| 2563 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2574 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2564 return IC_utilities[id]; | 2575 return IC_utilities[id]; |
| 2565 } | 2576 } |
| 2566 | 2577 |
| 2567 | 2578 |
| 2568 } } // namespace v8::internal | 2579 } } // namespace v8::internal |
| OLD | NEW |