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 |