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 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
407 void KeyedStoreIC::Clear(Address address, Code* target) { | 407 void KeyedStoreIC::Clear(Address address, Code* target) { |
408 if (target->ic_state() == UNINITIALIZED) return; | 408 if (target->ic_state() == UNINITIALIZED) return; |
409 SetTargetAtAddress(address, | 409 SetTargetAtAddress(address, |
410 (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode) | 410 (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode) |
411 ? initialize_stub_strict() | 411 ? initialize_stub_strict() |
412 : initialize_stub()); | 412 : initialize_stub()); |
413 } | 413 } |
414 | 414 |
415 | 415 |
416 void CompareIC::Clear(Address address, Code* target) { | 416 void CompareIC::Clear(Address address, Code* target) { |
417 // Only clear ICCompareStubs, we currently cannot clear generic CompareStubs. | 417 ASSERT(target->major_key() == CodeStub::CompareIC); |
418 if (target->major_key() != CodeStub::CompareIC) return; | 418 CompareIC::State handler_state; |
419 Token::Value op; | |
420 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, | |
421 &handler_state, &op); | |
419 // Only clear CompareICs that can retain objects. | 422 // Only clear CompareICs that can retain objects. |
420 if (target->compare_state() != KNOWN_OBJECTS) return; | 423 if (handler_state != KNOWN_OBJECTS) return; |
421 Token::Value op = CompareIC::ComputeOperation(target); | |
422 SetTargetAtAddress(address, GetRawUninitialized(op)); | 424 SetTargetAtAddress(address, GetRawUninitialized(op)); |
423 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 425 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
424 } | 426 } |
425 | 427 |
426 | 428 |
427 static bool HasInterceptorGetter(JSObject* object) { | 429 static bool HasInterceptorGetter(JSObject* object) { |
428 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | 430 return !object->GetNamedInterceptor()->getter()->IsUndefined(); |
429 } | 431 } |
430 | 432 |
431 | 433 |
(...skipping 1874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2306 | 2308 |
2307 void BinaryOpIC::patch(Code* code) { | 2309 void BinaryOpIC::patch(Code* code) { |
2308 set_target(code); | 2310 set_target(code); |
2309 } | 2311 } |
2310 | 2312 |
2311 | 2313 |
2312 const char* BinaryOpIC::GetName(TypeInfo type_info) { | 2314 const char* BinaryOpIC::GetName(TypeInfo type_info) { |
2313 switch (type_info) { | 2315 switch (type_info) { |
2314 case UNINITIALIZED: return "Uninitialized"; | 2316 case UNINITIALIZED: return "Uninitialized"; |
2315 case SMI: return "SMI"; | 2317 case SMI: return "SMI"; |
2316 case INT32: return "Int32s"; | 2318 case INT32: return "Int32"; |
2317 case HEAP_NUMBER: return "HeapNumbers"; | 2319 case HEAP_NUMBER: return "HeapNumber"; |
2318 case ODDBALL: return "Oddball"; | 2320 case ODDBALL: return "Oddball"; |
2319 case BOTH_STRING: return "BothStrings"; | 2321 case STRING: return "String"; |
2320 case STRING: return "Strings"; | |
2321 case GENERIC: return "Generic"; | 2322 case GENERIC: return "Generic"; |
2322 default: return "Invalid"; | 2323 default: return "Invalid"; |
2323 } | 2324 } |
2324 } | 2325 } |
2325 | 2326 |
2326 | 2327 |
2327 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) { | 2328 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) { |
2328 switch (type_info) { | 2329 switch (type_info) { |
2329 case UNINITIALIZED: | 2330 case UNINITIALIZED: |
2330 return ::v8::internal::UNINITIALIZED; | 2331 return ::v8::internal::UNINITIALIZED; |
2331 case SMI: | 2332 case SMI: |
2332 case INT32: | 2333 case INT32: |
2333 case HEAP_NUMBER: | 2334 case HEAP_NUMBER: |
2334 case ODDBALL: | 2335 case ODDBALL: |
2335 case BOTH_STRING: | |
2336 case STRING: | 2336 case STRING: |
2337 return MONOMORPHIC; | 2337 return MONOMORPHIC; |
2338 case GENERIC: | 2338 case GENERIC: |
2339 return MEGAMORPHIC; | 2339 return MEGAMORPHIC; |
2340 } | 2340 } |
2341 UNREACHABLE(); | 2341 UNREACHABLE(); |
2342 return ::v8::internal::UNINITIALIZED; | 2342 return ::v8::internal::UNINITIALIZED; |
2343 } | 2343 } |
2344 | 2344 |
2345 | 2345 |
2346 BinaryOpIC::TypeInfo BinaryOpIC::JoinTypes(BinaryOpIC::TypeInfo x, | |
2347 BinaryOpIC::TypeInfo y) { | |
2348 if (x == UNINITIALIZED) return y; | |
2349 if (y == UNINITIALIZED) return x; | |
2350 if (x == y) return x; | |
2351 if (x == BOTH_STRING && y == STRING) return STRING; | |
2352 if (x == STRING && y == BOTH_STRING) return STRING; | |
2353 if (x == STRING || x == BOTH_STRING || y == STRING || y == BOTH_STRING) { | |
2354 return GENERIC; | |
2355 } | |
2356 if (x > y) return x; | |
2357 return y; | |
2358 } | |
2359 | |
2360 | |
2361 BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Handle<Object> left, | |
2362 Handle<Object> right) { | |
2363 ::v8::internal::TypeInfo left_type = | |
2364 ::v8::internal::TypeInfo::TypeFromValue(left); | |
2365 ::v8::internal::TypeInfo right_type = | |
2366 ::v8::internal::TypeInfo::TypeFromValue(right); | |
2367 | |
2368 if (left_type.IsSmi() && right_type.IsSmi()) { | |
2369 return SMI; | |
2370 } | |
2371 | |
2372 if (left_type.IsInteger32() && right_type.IsInteger32()) { | |
2373 // Platforms with 32-bit Smis have no distinct INT32 type. | |
2374 if (kSmiValueSize == 32) return SMI; | |
2375 return INT32; | |
2376 } | |
2377 | |
2378 if (left_type.IsNumber() && right_type.IsNumber()) { | |
2379 return HEAP_NUMBER; | |
2380 } | |
2381 | |
2382 // Patching for fast string ADD makes sense even if only one of the | |
2383 // arguments is a string. | |
2384 if (left_type.IsString()) { | |
2385 return right_type.IsString() ? BOTH_STRING : STRING; | |
2386 } else if (right_type.IsString()) { | |
2387 return STRING; | |
2388 } | |
2389 | |
2390 // Check for oddball objects. | |
2391 if (left->IsUndefined() && right->IsNumber()) return ODDBALL; | |
2392 if (left->IsNumber() && right->IsUndefined()) return ODDBALL; | |
2393 | |
2394 return GENERIC; | |
2395 } | |
2396 | |
2397 | |
2398 RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) { | 2346 RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) { |
2399 ASSERT(args.length() == 4); | 2347 ASSERT(args.length() == 4); |
2400 | 2348 |
2401 HandleScope scope(isolate); | 2349 HandleScope scope(isolate); |
2402 Handle<Object> operand = args.at<Object>(0); | 2350 Handle<Object> operand = args.at<Object>(0); |
2403 Token::Value op = static_cast<Token::Value>(args.smi_at(1)); | 2351 Token::Value op = static_cast<Token::Value>(args.smi_at(1)); |
2404 UnaryOverwriteMode mode = static_cast<UnaryOverwriteMode>(args.smi_at(2)); | 2352 UnaryOverwriteMode mode = static_cast<UnaryOverwriteMode>(args.smi_at(2)); |
2405 UnaryOpIC::TypeInfo previous_type = | 2353 UnaryOpIC::TypeInfo previous_type = |
2406 static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3)); | 2354 static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3)); |
2407 | 2355 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2439 | 2387 |
2440 bool caught_exception; | 2388 bool caught_exception; |
2441 Handle<Object> result = Execution::Call(builtin_function, operand, 0, NULL, | 2389 Handle<Object> result = Execution::Call(builtin_function, operand, 0, NULL, |
2442 &caught_exception); | 2390 &caught_exception); |
2443 if (caught_exception) { | 2391 if (caught_exception) { |
2444 return Failure::Exception(); | 2392 return Failure::Exception(); |
2445 } | 2393 } |
2446 return *result; | 2394 return *result; |
2447 } | 2395 } |
2448 | 2396 |
2397 | |
2398 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value, | |
2399 Token::Value op) { | |
2400 ::v8::internal::TypeInfo type = | |
2401 ::v8::internal::TypeInfo::TypeFromValue(value); | |
2402 if (type.IsSmi()) return BinaryOpIC::SMI; | |
2403 if (type.IsInteger32()) { | |
2404 if (kSmiValueSize == 32) return BinaryOpIC::SMI; | |
2405 return BinaryOpIC::INT32; | |
2406 } | |
2407 if (type.IsNumber()) return BinaryOpIC::HEAP_NUMBER; | |
2408 if (type.IsString()) return BinaryOpIC::STRING; | |
2409 if (value->IsUndefined()) { | |
2410 if (op == Token::BIT_AND || | |
2411 op == Token::BIT_OR || | |
2412 op == Token::BIT_XOR || | |
2413 op == Token::SAR || | |
2414 op == Token::SHL || | |
2415 op == Token::SHR) { | |
2416 if (kSmiValueSize == 32) return BinaryOpIC::SMI; | |
2417 return BinaryOpIC::INT32; | |
2418 } | |
2419 return BinaryOpIC::ODDBALL; | |
2420 } | |
2421 return BinaryOpIC::GENERIC; | |
2422 } | |
2423 | |
2424 | |
2425 static BinaryOpIC::TypeInfo InputState(BinaryOpIC::TypeInfo old_type, | |
2426 Handle<Object> value, | |
2427 Token::Value op) { | |
2428 BinaryOpIC::TypeInfo new_type = TypeInfoFromValue(value, op); | |
2429 if (old_type == BinaryOpIC::UNINITIALIZED) return new_type; | |
danno
2012/11/14 10:38:22
remove above?
Jakob Kummerow
2012/11/14 15:53:23
Done.
| |
2430 if (old_type == BinaryOpIC::STRING) { | |
2431 if (new_type == BinaryOpIC::STRING) return new_type; | |
2432 return BinaryOpIC::GENERIC; | |
2433 } | |
2434 return Max(old_type, new_type); | |
2435 } | |
2436 | |
2437 | |
2449 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) { | 2438 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) { |
2450 ASSERT(args.length() == 5); | 2439 ASSERT(args.length() == 3); |
2451 | 2440 |
2452 HandleScope scope(isolate); | 2441 HandleScope scope(isolate); |
2453 Handle<Object> left = args.at<Object>(0); | 2442 Handle<Object> left = args.at<Object>(0); |
2454 Handle<Object> right = args.at<Object>(1); | 2443 Handle<Object> right = args.at<Object>(1); |
2455 int key = args.smi_at(2); | 2444 int key = args.smi_at(2); |
2456 Token::Value op = static_cast<Token::Value>(args.smi_at(3)); | 2445 Token::Value op = BinaryOpStub::decode_op_from_minor_key(key); |
2457 BinaryOpIC::TypeInfo previous_type = | 2446 BinaryOpIC::TypeInfo previous_left, previous_right, unused_previous_result; |
2458 static_cast<BinaryOpIC::TypeInfo>(args.smi_at(4)); | 2447 BinaryOpStub::decode_types_from_minor_key( |
2448 key, &previous_left, &previous_right, &unused_previous_result); | |
2459 | 2449 |
2460 BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(left, right); | 2450 BinaryOpIC::TypeInfo new_left = InputState(previous_left, left, op); |
2461 type = BinaryOpIC::JoinTypes(type, previous_type); | 2451 BinaryOpIC::TypeInfo new_right = InputState(previous_right, right, op); |
2462 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED; | 2452 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED; |
2463 if ((type == BinaryOpIC::STRING || type == BinaryOpIC::BOTH_STRING) && | 2453 |
2454 // STRING is only used for ADD operations. | |
2455 if ((new_left == BinaryOpIC::STRING || new_right == BinaryOpIC::STRING) && | |
2464 op != Token::ADD) { | 2456 op != Token::ADD) { |
2465 type = BinaryOpIC::GENERIC; | 2457 new_left = new_right = BinaryOpIC::GENERIC; |
2466 } | 2458 } |
2467 if (type == BinaryOpIC::SMI && previous_type == BinaryOpIC::SMI) { | 2459 |
2460 BinaryOpIC::TypeInfo new_overall = Max(new_left, new_right); | |
2461 BinaryOpIC::TypeInfo previous_overall = Max(previous_left, previous_right); | |
2462 | |
2463 if (new_overall == BinaryOpIC::SMI && previous_overall == BinaryOpIC::SMI) { | |
2468 if (op == Token::DIV || | 2464 if (op == Token::DIV || |
2469 op == Token::MUL || | 2465 op == Token::MUL || |
2470 op == Token::SHR || | 2466 op == Token::SHR || |
2471 kSmiValueSize == 32) { | 2467 kSmiValueSize == 32) { |
2472 // Arithmetic on two Smi inputs has yielded a heap number. | 2468 // Arithmetic on two Smi inputs has yielded a heap number. |
2473 // That is the only way to get here from the Smi stub. | 2469 // That is the only way to get here from the Smi stub. |
2474 // With 32-bit Smis, all overflows give heap numbers, but with | 2470 // With 32-bit Smis, all overflows give heap numbers, but with |
2475 // 31-bit Smis, most operations overflow to int32 results. | 2471 // 31-bit Smis, most operations overflow to int32 results. |
2476 result_type = BinaryOpIC::HEAP_NUMBER; | 2472 result_type = BinaryOpIC::HEAP_NUMBER; |
2477 } else { | 2473 } else { |
2478 // Other operations on SMIs that overflow yield int32s. | 2474 // Other operations on SMIs that overflow yield int32s. |
2479 result_type = BinaryOpIC::INT32; | 2475 result_type = BinaryOpIC::INT32; |
2480 } | 2476 } |
2481 } | 2477 } |
2482 if (type == BinaryOpIC::INT32 && previous_type == BinaryOpIC::INT32) { | 2478 if (new_overall == BinaryOpIC::INT32 && |
2483 // We must be here because an operation on two INT32 types overflowed. | 2479 previous_overall == BinaryOpIC::INT32) { |
2484 result_type = BinaryOpIC::HEAP_NUMBER; | 2480 if (new_left == previous_left && new_right == previous_right) { |
2481 result_type = BinaryOpIC::HEAP_NUMBER; | |
2482 } | |
2485 } | 2483 } |
2486 | 2484 |
2487 BinaryOpStub stub(key, type, result_type); | 2485 BinaryOpStub stub(key, new_left, new_right, result_type); |
2488 Handle<Code> code = stub.GetCode(); | 2486 Handle<Code> code = stub.GetCode(); |
2489 if (!code.is_null()) { | 2487 if (!code.is_null()) { |
2488 #ifdef DEBUG | |
2490 if (FLAG_trace_ic) { | 2489 if (FLAG_trace_ic) { |
2491 PrintF("[BinaryOpIC (%s->(%s->%s))#%s]\n", | 2490 PrintF("[BinaryOpIC in "); |
2492 BinaryOpIC::GetName(previous_type), | 2491 JavaScriptFrame::PrintTop(stdout, false, true); |
2493 BinaryOpIC::GetName(type), | 2492 PrintF(" ((%s+%s)->((%s+%s)->%s))#%s @ %p]\n", |
2493 BinaryOpIC::GetName(previous_left), | |
2494 BinaryOpIC::GetName(previous_right), | |
2495 BinaryOpIC::GetName(new_left), | |
2496 BinaryOpIC::GetName(new_right), | |
2494 BinaryOpIC::GetName(result_type), | 2497 BinaryOpIC::GetName(result_type), |
2495 Token::Name(op)); | 2498 Token::Name(op), |
2499 static_cast<void*>(*code)); | |
2496 } | 2500 } |
2501 #endif | |
2497 BinaryOpIC ic(isolate); | 2502 BinaryOpIC ic(isolate); |
2498 ic.patch(*code); | 2503 ic.patch(*code); |
2499 | 2504 |
2500 // Activate inlined smi code. | 2505 // Activate inlined smi code. |
2501 if (previous_type == BinaryOpIC::UNINITIALIZED) { | 2506 if (previous_overall == BinaryOpIC::UNINITIALIZED) { |
2502 PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK); | 2507 PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK); |
2503 } | 2508 } |
2504 } | 2509 } |
2505 | 2510 |
2506 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( | 2511 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( |
2507 isolate->thread_local_top()->context_->builtins(), isolate); | 2512 isolate->thread_local_top()->context_->builtins(), isolate); |
2508 Object* builtin = NULL; // Initialization calms down the compiler. | 2513 Object* builtin = NULL; // Initialization calms down the compiler. |
2509 switch (op) { | 2514 switch (op) { |
2510 case Token::ADD: | 2515 case Token::ADD: |
2511 builtin = builtins->javascript_builtin(Builtins::ADD); | 2516 builtin = builtins->javascript_builtin(Builtins::ADD); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2554 builtin_args, | 2559 builtin_args, |
2555 &caught_exception); | 2560 &caught_exception); |
2556 if (caught_exception) { | 2561 if (caught_exception) { |
2557 return Failure::Exception(); | 2562 return Failure::Exception(); |
2558 } | 2563 } |
2559 return *result; | 2564 return *result; |
2560 } | 2565 } |
2561 | 2566 |
2562 | 2567 |
2563 Code* CompareIC::GetRawUninitialized(Token::Value op) { | 2568 Code* CompareIC::GetRawUninitialized(Token::Value op) { |
2564 ICCompareStub stub(op, UNINITIALIZED); | 2569 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
2565 Code* code = NULL; | 2570 Code* code = NULL; |
2566 CHECK(stub.FindCodeInCache(&code)); | 2571 CHECK(stub.FindCodeInCache(&code)); |
2567 return code; | 2572 return code; |
2568 } | 2573 } |
2569 | 2574 |
2570 | 2575 |
2571 Handle<Code> CompareIC::GetUninitialized(Token::Value op) { | 2576 Handle<Code> CompareIC::GetUninitialized(Token::Value op) { |
2572 ICCompareStub stub(op, UNINITIALIZED); | 2577 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
2573 return stub.GetCode(); | 2578 return stub.GetCode(); |
2574 } | 2579 } |
2575 | 2580 |
2576 | 2581 |
2577 CompareIC::State CompareIC::ComputeState(Code* target) { | |
2578 int key = target->major_key(); | |
2579 if (key == CodeStub::Compare) return GENERIC; | |
2580 ASSERT(key == CodeStub::CompareIC); | |
2581 return static_cast<State>(target->compare_state()); | |
2582 } | |
2583 | |
2584 | |
2585 Token::Value CompareIC::ComputeOperation(Code* target) { | |
2586 ASSERT(target->major_key() == CodeStub::CompareIC); | |
2587 return static_cast<Token::Value>( | |
2588 target->compare_operation() + Token::EQ); | |
2589 } | |
2590 | |
2591 | |
2592 const char* CompareIC::GetStateName(State state) { | 2582 const char* CompareIC::GetStateName(State state) { |
2593 switch (state) { | 2583 switch (state) { |
2594 case UNINITIALIZED: return "UNINITIALIZED"; | 2584 case UNINITIALIZED: return "UNINITIALIZED"; |
2595 case SMIS: return "SMIS"; | 2585 case SMI: return "SMI"; |
2596 case HEAP_NUMBERS: return "HEAP_NUMBERS"; | 2586 case HEAP_NUMBER: return "HEAP_NUMBER"; |
2597 case OBJECTS: return "OBJECTS"; | 2587 case OBJECT: return "OBJECTS"; |
2598 case KNOWN_OBJECTS: return "KNOWN_OBJECTS"; | 2588 case KNOWN_OBJECTS: return "KNOWN_OBJECTS"; |
2599 case SYMBOLS: return "SYMBOLS"; | 2589 case SYMBOL: return "SYMBOL"; |
2600 case STRINGS: return "STRINGS"; | 2590 case STRING: return "STRING"; |
2601 case GENERIC: return "GENERIC"; | 2591 case GENERIC: return "GENERIC"; |
2602 default: | 2592 default: |
2603 UNREACHABLE(); | 2593 UNREACHABLE(); |
2604 return NULL; | 2594 return NULL; |
2605 } | 2595 } |
2606 } | 2596 } |
2607 | 2597 |
2608 | 2598 |
2609 CompareIC::State CompareIC::TargetState(State state, | 2599 static CompareIC::State InputState(CompareIC::State old_state, |
2600 Handle<Object> value) { | |
2601 switch (old_state) { | |
2602 case CompareIC::UNINITIALIZED: | |
2603 if (value->IsSmi()) return CompareIC::SMI; | |
2604 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER; | |
2605 if (value->IsSymbol()) return CompareIC::SYMBOL; | |
2606 if (value->IsString()) return CompareIC::STRING; | |
2607 if (value->IsJSObject()) return CompareIC::OBJECT; | |
2608 break; | |
2609 case CompareIC::SMI: | |
2610 if (value->IsSmi()) return CompareIC::SMI; | |
2611 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER; | |
2612 break; | |
2613 case CompareIC::HEAP_NUMBER: | |
2614 if (value->IsNumber()) return CompareIC::HEAP_NUMBER; | |
2615 break; | |
2616 case CompareIC::SYMBOL: | |
2617 if (value->IsSymbol()) return CompareIC::SYMBOL; | |
2618 if (value->IsString()) return CompareIC::STRING; | |
2619 break; | |
2620 case CompareIC::STRING: | |
2621 if (value->IsSymbol() || value->IsString()) return CompareIC::STRING; | |
2622 break; | |
2623 case CompareIC::OBJECT: | |
2624 if (value->IsJSObject()) return CompareIC::OBJECT; | |
2625 break; | |
2626 case CompareIC::GENERIC: | |
2627 break; | |
2628 case CompareIC::KNOWN_OBJECTS: | |
2629 UNREACHABLE(); | |
2630 break; | |
2631 } | |
2632 return CompareIC::GENERIC; | |
2633 } | |
2634 | |
2635 | |
2636 CompareIC::State CompareIC::TargetState(State old_state, | |
2637 State old_left, | |
2638 State old_right, | |
2610 bool has_inlined_smi_code, | 2639 bool has_inlined_smi_code, |
2611 Handle<Object> x, | 2640 Handle<Object> x, |
2612 Handle<Object> y) { | 2641 Handle<Object> y) { |
2613 switch (state) { | 2642 switch (old_state) { |
2614 case UNINITIALIZED: | 2643 case UNINITIALIZED: |
2615 if (x->IsSmi() && y->IsSmi()) return SMIS; | 2644 if (x->IsSmi() && y->IsSmi()) return SMI; |
2616 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS; | 2645 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBER; |
2617 if (Token::IsOrderedRelationalCompareOp(op_)) { | 2646 if (Token::IsOrderedRelationalCompareOp(op_)) { |
2618 // Ordered comparisons treat undefined as NaN, so the | 2647 // Ordered comparisons treat undefined as NaN, so the |
2619 // HEAP_NUMBER stub will do the right thing. | 2648 // HEAP_NUMBER stub will do the right thing. |
2620 if ((x->IsNumber() && y->IsUndefined()) || | 2649 if ((x->IsNumber() && y->IsUndefined()) || |
2621 (y->IsNumber() && x->IsUndefined())) { | 2650 (y->IsNumber() && x->IsUndefined())) { |
2622 return HEAP_NUMBERS; | 2651 return HEAP_NUMBER; |
2623 } | 2652 } |
2624 } | 2653 } |
2625 if (x->IsSymbol() && y->IsSymbol()) { | 2654 if (x->IsSymbol() && y->IsSymbol()) { |
2626 // We compare symbols as strings if we need to determine | 2655 // We compare symbols as strings if we need to determine |
2627 // the order in a non-equality compare. | 2656 // the order in a non-equality compare. |
2628 return Token::IsEqualityOp(op_) ? SYMBOLS : STRINGS; | 2657 return Token::IsEqualityOp(op_) ? SYMBOL : STRING; |
2629 } | 2658 } |
2630 if (x->IsString() && y->IsString()) return STRINGS; | 2659 if (x->IsString() && y->IsString()) return STRING; |
2631 if (!Token::IsEqualityOp(op_)) return GENERIC; | 2660 if (!Token::IsEqualityOp(op_)) return GENERIC; |
2632 if (x->IsJSObject() && y->IsJSObject()) { | 2661 if (x->IsJSObject() && y->IsJSObject()) { |
2633 if (Handle<JSObject>::cast(x)->map() == | 2662 if (Handle<JSObject>::cast(x)->map() == |
2634 Handle<JSObject>::cast(y)->map() && | 2663 Handle<JSObject>::cast(y)->map() && |
2635 Token::IsEqualityOp(op_)) { | 2664 Token::IsEqualityOp(op_)) { |
2636 return KNOWN_OBJECTS; | 2665 return KNOWN_OBJECTS; |
2637 } else { | 2666 } else { |
2638 return OBJECTS; | 2667 return OBJECT; |
2639 } | 2668 } |
2640 } | 2669 } |
2641 return GENERIC; | 2670 return GENERIC; |
2642 case SMIS: | 2671 case SMI: |
2643 return has_inlined_smi_code && x->IsNumber() && y->IsNumber() | 2672 return x->IsNumber() && y->IsNumber() |
2644 ? HEAP_NUMBERS | 2673 ? HEAP_NUMBER |
2645 : GENERIC; | 2674 : GENERIC; |
2646 case SYMBOLS: | 2675 case SYMBOL: |
2647 ASSERT(Token::IsEqualityOp(op_)); | 2676 ASSERT(Token::IsEqualityOp(op_)); |
2648 return x->IsString() && y->IsString() ? STRINGS : GENERIC; | 2677 return x->IsString() && y->IsString() ? STRING : GENERIC; |
2649 case HEAP_NUMBERS: | 2678 case HEAP_NUMBER: |
2650 case STRINGS: | 2679 if (old_left == SMI && x->IsHeapNumber()) return HEAP_NUMBER; |
2651 case OBJECTS: | 2680 if (old_right == SMI && y->IsHeapNumber()) return HEAP_NUMBER; |
2681 case STRING: | |
2682 case OBJECT: | |
2652 case KNOWN_OBJECTS: | 2683 case KNOWN_OBJECTS: |
2653 case GENERIC: | 2684 case GENERIC: |
2654 return GENERIC; | 2685 return GENERIC; |
2655 } | 2686 } |
2656 UNREACHABLE(); | 2687 UNREACHABLE(); |
2657 return GENERIC; | 2688 return GENERIC; // Make the compiler happy. |
2658 } | 2689 } |
2659 | 2690 |
2660 | 2691 |
2661 // Used from ic_<arch>.cc. | 2692 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { |
2693 HandleScope scope; | |
2694 State previous_left, previous_right, previous_state; | |
2695 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, | |
2696 &previous_right, &previous_state, NULL); | |
2697 State new_left = InputState(previous_left, x); | |
2698 State new_right = InputState(previous_right, y); | |
2699 State state = TargetState(previous_state, previous_left, previous_right, | |
2700 HasInlinedSmiCode(address()), x, y); | |
2701 ICCompareStub stub(op_, new_left, new_right, state); | |
2702 if (state == KNOWN_OBJECTS) { | |
2703 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); | |
2704 } | |
2705 set_target(*stub.GetCode()); | |
2706 | |
2707 #ifdef DEBUG | |
2708 if (FLAG_trace_ic) { | |
2709 PrintF("[CompareIC in "); | |
2710 JavaScriptFrame::PrintTop(stdout, false, true); | |
2711 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", | |
2712 GetStateName(previous_left), | |
2713 GetStateName(previous_right), | |
2714 GetStateName(previous_state), | |
2715 GetStateName(new_left), | |
2716 GetStateName(new_right), | |
2717 GetStateName(state), | |
2718 Token::Name(op_), | |
2719 static_cast<void*>(*stub.GetCode())); | |
2720 } | |
2721 #endif | |
2722 | |
2723 // Activate inlined smi code. | |
2724 if (previous_state == UNINITIALIZED) { | |
2725 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); | |
2726 } | |
2727 } | |
2728 | |
2729 | |
2730 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. | |
2662 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { | 2731 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { |
2663 NoHandleAllocation na; | 2732 NoHandleAllocation na; |
2664 ASSERT(args.length() == 3); | 2733 ASSERT(args.length() == 3); |
2665 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); | 2734 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); |
2666 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2735 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
2667 return ic.target(); | 2736 return ic.target(); |
2668 } | 2737 } |
2669 | 2738 |
2670 | 2739 |
2671 RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) { | 2740 RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) { |
(...skipping 28 matching lines...) Expand all Loading... | |
2700 #undef ADDR | 2769 #undef ADDR |
2701 }; | 2770 }; |
2702 | 2771 |
2703 | 2772 |
2704 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2773 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2705 return IC_utilities[id]; | 2774 return IC_utilities[id]; |
2706 } | 2775 } |
2707 | 2776 |
2708 | 2777 |
2709 } } // namespace v8::internal | 2778 } } // namespace v8::internal |
OLD | NEW |