Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: src/ic.cc

Issue 10837165: Lattice-based representation inference, powered by left/right specific type feedback for BinaryOps … (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: more performance polish Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW
« src/hydrogen-instructions.cc ('K') | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698