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

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: review feedback; fixed tests 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
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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::STRING) {
2430 if (new_type == BinaryOpIC::STRING) return new_type;
2431 return BinaryOpIC::GENERIC;
2432 }
2433 return Max(old_type, new_type);
2434 }
2435
2436
2449 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) { 2437 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
2450 ASSERT(args.length() == 5); 2438 ASSERT(args.length() == 3);
2451 2439
2452 HandleScope scope(isolate); 2440 HandleScope scope(isolate);
2453 Handle<Object> left = args.at<Object>(0); 2441 Handle<Object> left = args.at<Object>(0);
2454 Handle<Object> right = args.at<Object>(1); 2442 Handle<Object> right = args.at<Object>(1);
2455 int key = args.smi_at(2); 2443 int key = args.smi_at(2);
2456 Token::Value op = static_cast<Token::Value>(args.smi_at(3)); 2444 Token::Value op = BinaryOpStub::decode_op_from_minor_key(key);
2457 BinaryOpIC::TypeInfo previous_type = 2445 BinaryOpIC::TypeInfo previous_left, previous_right, unused_previous_result;
2458 static_cast<BinaryOpIC::TypeInfo>(args.smi_at(4)); 2446 BinaryOpStub::decode_types_from_minor_key(
2447 key, &previous_left, &previous_right, &unused_previous_result);
2459 2448
2460 BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(left, right); 2449 BinaryOpIC::TypeInfo new_left = InputState(previous_left, left, op);
2461 type = BinaryOpIC::JoinTypes(type, previous_type); 2450 BinaryOpIC::TypeInfo new_right = InputState(previous_right, right, op);
2462 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED; 2451 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED;
2463 if ((type == BinaryOpIC::STRING || type == BinaryOpIC::BOTH_STRING) && 2452
2453 // STRING is only used for ADD operations.
2454 if ((new_left == BinaryOpIC::STRING || new_right == BinaryOpIC::STRING) &&
2464 op != Token::ADD) { 2455 op != Token::ADD) {
2465 type = BinaryOpIC::GENERIC; 2456 new_left = new_right = BinaryOpIC::GENERIC;
2466 } 2457 }
2467 if (type == BinaryOpIC::SMI && previous_type == BinaryOpIC::SMI) { 2458
2459 BinaryOpIC::TypeInfo new_overall = Max(new_left, new_right);
2460 BinaryOpIC::TypeInfo previous_overall = Max(previous_left, previous_right);
2461
2462 if (new_overall == BinaryOpIC::SMI && previous_overall == BinaryOpIC::SMI) {
2468 if (op == Token::DIV || 2463 if (op == Token::DIV ||
2469 op == Token::MUL || 2464 op == Token::MUL ||
2470 op == Token::SHR || 2465 op == Token::SHR ||
2471 kSmiValueSize == 32) { 2466 kSmiValueSize == 32) {
2472 // Arithmetic on two Smi inputs has yielded a heap number. 2467 // Arithmetic on two Smi inputs has yielded a heap number.
2473 // That is the only way to get here from the Smi stub. 2468 // That is the only way to get here from the Smi stub.
2474 // With 32-bit Smis, all overflows give heap numbers, but with 2469 // With 32-bit Smis, all overflows give heap numbers, but with
2475 // 31-bit Smis, most operations overflow to int32 results. 2470 // 31-bit Smis, most operations overflow to int32 results.
2476 result_type = BinaryOpIC::HEAP_NUMBER; 2471 result_type = BinaryOpIC::HEAP_NUMBER;
2477 } else { 2472 } else {
2478 // Other operations on SMIs that overflow yield int32s. 2473 // Other operations on SMIs that overflow yield int32s.
2479 result_type = BinaryOpIC::INT32; 2474 result_type = BinaryOpIC::INT32;
2480 } 2475 }
2481 } 2476 }
2482 if (type == BinaryOpIC::INT32 && previous_type == BinaryOpIC::INT32) { 2477 if (new_overall == BinaryOpIC::INT32 &&
2483 // We must be here because an operation on two INT32 types overflowed. 2478 previous_overall == BinaryOpIC::INT32) {
2484 result_type = BinaryOpIC::HEAP_NUMBER; 2479 if (new_left == previous_left && new_right == previous_right) {
2480 result_type = BinaryOpIC::HEAP_NUMBER;
2481 }
2485 } 2482 }
2486 2483
2487 BinaryOpStub stub(key, type, result_type); 2484 BinaryOpStub stub(key, new_left, new_right, result_type);
2488 Handle<Code> code = stub.GetCode(); 2485 Handle<Code> code = stub.GetCode();
2489 if (!code.is_null()) { 2486 if (!code.is_null()) {
2487 #ifdef DEBUG
2490 if (FLAG_trace_ic) { 2488 if (FLAG_trace_ic) {
2491 PrintF("[BinaryOpIC (%s->(%s->%s))#%s]\n", 2489 PrintF("[BinaryOpIC in ");
2492 BinaryOpIC::GetName(previous_type), 2490 JavaScriptFrame::PrintTop(stdout, false, true);
2493 BinaryOpIC::GetName(type), 2491 PrintF(" ((%s+%s)->((%s+%s)->%s))#%s @ %p]\n",
2492 BinaryOpIC::GetName(previous_left),
2493 BinaryOpIC::GetName(previous_right),
2494 BinaryOpIC::GetName(new_left),
2495 BinaryOpIC::GetName(new_right),
2494 BinaryOpIC::GetName(result_type), 2496 BinaryOpIC::GetName(result_type),
2495 Token::Name(op)); 2497 Token::Name(op),
2498 static_cast<void*>(*code));
2496 } 2499 }
2500 #endif
2497 BinaryOpIC ic(isolate); 2501 BinaryOpIC ic(isolate);
2498 ic.patch(*code); 2502 ic.patch(*code);
2499 2503
2500 // Activate inlined smi code. 2504 // Activate inlined smi code.
2501 if (previous_type == BinaryOpIC::UNINITIALIZED) { 2505 if (previous_overall == BinaryOpIC::UNINITIALIZED) {
2502 PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK); 2506 PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK);
2503 } 2507 }
2504 } 2508 }
2505 2509
2506 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( 2510 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
2507 isolate->thread_local_top()->context_->builtins(), isolate); 2511 isolate->thread_local_top()->context_->builtins(), isolate);
2508 Object* builtin = NULL; // Initialization calms down the compiler. 2512 Object* builtin = NULL; // Initialization calms down the compiler.
2509 switch (op) { 2513 switch (op) {
2510 case Token::ADD: 2514 case Token::ADD:
2511 builtin = builtins->javascript_builtin(Builtins::ADD); 2515 builtin = builtins->javascript_builtin(Builtins::ADD);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2554 builtin_args, 2558 builtin_args,
2555 &caught_exception); 2559 &caught_exception);
2556 if (caught_exception) { 2560 if (caught_exception) {
2557 return Failure::Exception(); 2561 return Failure::Exception();
2558 } 2562 }
2559 return *result; 2563 return *result;
2560 } 2564 }
2561 2565
2562 2566
2563 Code* CompareIC::GetRawUninitialized(Token::Value op) { 2567 Code* CompareIC::GetRawUninitialized(Token::Value op) {
2564 ICCompareStub stub(op, UNINITIALIZED); 2568 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2565 Code* code = NULL; 2569 Code* code = NULL;
2566 CHECK(stub.FindCodeInCache(&code)); 2570 CHECK(stub.FindCodeInCache(&code));
2567 return code; 2571 return code;
2568 } 2572 }
2569 2573
2570 2574
2571 Handle<Code> CompareIC::GetUninitialized(Token::Value op) { 2575 Handle<Code> CompareIC::GetUninitialized(Token::Value op) {
2572 ICCompareStub stub(op, UNINITIALIZED); 2576 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2573 return stub.GetCode(); 2577 return stub.GetCode();
2574 } 2578 }
2575 2579
2576 2580
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) { 2581 const char* CompareIC::GetStateName(State state) {
2593 switch (state) { 2582 switch (state) {
2594 case UNINITIALIZED: return "UNINITIALIZED"; 2583 case UNINITIALIZED: return "UNINITIALIZED";
2595 case SMIS: return "SMIS"; 2584 case SMI: return "SMI";
2596 case HEAP_NUMBERS: return "HEAP_NUMBERS"; 2585 case HEAP_NUMBER: return "HEAP_NUMBER";
2597 case OBJECTS: return "OBJECTS"; 2586 case OBJECT: return "OBJECTS";
2598 case KNOWN_OBJECTS: return "KNOWN_OBJECTS"; 2587 case KNOWN_OBJECTS: return "KNOWN_OBJECTS";
2599 case SYMBOLS: return "SYMBOLS"; 2588 case SYMBOL: return "SYMBOL";
2600 case STRINGS: return "STRINGS"; 2589 case STRING: return "STRING";
2601 case GENERIC: return "GENERIC"; 2590 case GENERIC: return "GENERIC";
2602 default: 2591 default:
2603 UNREACHABLE(); 2592 UNREACHABLE();
2604 return NULL; 2593 return NULL;
2605 } 2594 }
2606 } 2595 }
2607 2596
2608 2597
2609 CompareIC::State CompareIC::TargetState(State state, 2598 static CompareIC::State InputState(CompareIC::State old_state,
2599 Handle<Object> value) {
2600 switch (old_state) {
2601 case CompareIC::UNINITIALIZED:
2602 if (value->IsSmi()) return CompareIC::SMI;
2603 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER;
2604 if (value->IsSymbol()) return CompareIC::SYMBOL;
2605 if (value->IsString()) return CompareIC::STRING;
2606 if (value->IsJSObject()) return CompareIC::OBJECT;
2607 break;
2608 case CompareIC::SMI:
2609 if (value->IsSmi()) return CompareIC::SMI;
2610 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER;
2611 break;
2612 case CompareIC::HEAP_NUMBER:
2613 if (value->IsNumber()) return CompareIC::HEAP_NUMBER;
2614 break;
2615 case CompareIC::SYMBOL:
2616 if (value->IsSymbol()) return CompareIC::SYMBOL;
2617 if (value->IsString()) return CompareIC::STRING;
2618 break;
2619 case CompareIC::STRING:
2620 if (value->IsSymbol() || value->IsString()) return CompareIC::STRING;
2621 break;
2622 case CompareIC::OBJECT:
2623 if (value->IsJSObject()) return CompareIC::OBJECT;
2624 break;
2625 case CompareIC::GENERIC:
2626 break;
2627 case CompareIC::KNOWN_OBJECTS:
2628 UNREACHABLE();
2629 break;
2630 }
2631 return CompareIC::GENERIC;
2632 }
2633
2634
2635 CompareIC::State CompareIC::TargetState(State old_state,
2636 State old_left,
2637 State old_right,
2610 bool has_inlined_smi_code, 2638 bool has_inlined_smi_code,
2611 Handle<Object> x, 2639 Handle<Object> x,
2612 Handle<Object> y) { 2640 Handle<Object> y) {
2613 switch (state) { 2641 switch (old_state) {
2614 case UNINITIALIZED: 2642 case UNINITIALIZED:
2615 if (x->IsSmi() && y->IsSmi()) return SMIS; 2643 if (x->IsSmi() && y->IsSmi()) return SMI;
2616 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS; 2644 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBER;
2617 if (Token::IsOrderedRelationalCompareOp(op_)) { 2645 if (Token::IsOrderedRelationalCompareOp(op_)) {
2618 // Ordered comparisons treat undefined as NaN, so the 2646 // Ordered comparisons treat undefined as NaN, so the
2619 // HEAP_NUMBER stub will do the right thing. 2647 // HEAP_NUMBER stub will do the right thing.
2620 if ((x->IsNumber() && y->IsUndefined()) || 2648 if ((x->IsNumber() && y->IsUndefined()) ||
2621 (y->IsNumber() && x->IsUndefined())) { 2649 (y->IsNumber() && x->IsUndefined())) {
2622 return HEAP_NUMBERS; 2650 return HEAP_NUMBER;
2623 } 2651 }
2624 } 2652 }
2625 if (x->IsSymbol() && y->IsSymbol()) { 2653 if (x->IsSymbol() && y->IsSymbol()) {
2626 // We compare symbols as strings if we need to determine 2654 // We compare symbols as strings if we need to determine
2627 // the order in a non-equality compare. 2655 // the order in a non-equality compare.
2628 return Token::IsEqualityOp(op_) ? SYMBOLS : STRINGS; 2656 return Token::IsEqualityOp(op_) ? SYMBOL : STRING;
2629 } 2657 }
2630 if (x->IsString() && y->IsString()) return STRINGS; 2658 if (x->IsString() && y->IsString()) return STRING;
2631 if (!Token::IsEqualityOp(op_)) return GENERIC; 2659 if (!Token::IsEqualityOp(op_)) return GENERIC;
2632 if (x->IsJSObject() && y->IsJSObject()) { 2660 if (x->IsJSObject() && y->IsJSObject()) {
2633 if (Handle<JSObject>::cast(x)->map() == 2661 if (Handle<JSObject>::cast(x)->map() ==
2634 Handle<JSObject>::cast(y)->map() && 2662 Handle<JSObject>::cast(y)->map() &&
2635 Token::IsEqualityOp(op_)) { 2663 Token::IsEqualityOp(op_)) {
2636 return KNOWN_OBJECTS; 2664 return KNOWN_OBJECTS;
2637 } else { 2665 } else {
2638 return OBJECTS; 2666 return OBJECT;
2639 } 2667 }
2640 } 2668 }
2641 return GENERIC; 2669 return GENERIC;
2642 case SMIS: 2670 case SMI:
2643 return has_inlined_smi_code && x->IsNumber() && y->IsNumber() 2671 return x->IsNumber() && y->IsNumber()
2644 ? HEAP_NUMBERS 2672 ? HEAP_NUMBER
2645 : GENERIC; 2673 : GENERIC;
2646 case SYMBOLS: 2674 case SYMBOL:
2647 ASSERT(Token::IsEqualityOp(op_)); 2675 ASSERT(Token::IsEqualityOp(op_));
2648 return x->IsString() && y->IsString() ? STRINGS : GENERIC; 2676 return x->IsString() && y->IsString() ? STRING : GENERIC;
2649 case HEAP_NUMBERS: 2677 case HEAP_NUMBER:
2650 case STRINGS: 2678 if (old_left == SMI && x->IsHeapNumber()) return HEAP_NUMBER;
2651 case OBJECTS: 2679 if (old_right == SMI && y->IsHeapNumber()) return HEAP_NUMBER;
2680 case STRING:
2681 case OBJECT:
2652 case KNOWN_OBJECTS: 2682 case KNOWN_OBJECTS:
2653 case GENERIC: 2683 case GENERIC:
2654 return GENERIC; 2684 return GENERIC;
2655 } 2685 }
2656 UNREACHABLE(); 2686 UNREACHABLE();
2657 return GENERIC; 2687 return GENERIC; // Make the compiler happy.
2658 } 2688 }
2659 2689
2660 2690
2661 // Used from ic_<arch>.cc. 2691 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
2692 HandleScope scope;
2693 State previous_left, previous_right, previous_state;
2694 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left,
2695 &previous_right, &previous_state, NULL);
2696 State new_left = InputState(previous_left, x);
2697 State new_right = InputState(previous_right, y);
2698 State state = TargetState(previous_state, previous_left, previous_right,
2699 HasInlinedSmiCode(address()), x, y);
2700 ICCompareStub stub(op_, new_left, new_right, state);
2701 if (state == KNOWN_OBJECTS) {
2702 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map()));
2703 }
2704 set_target(*stub.GetCode());
2705
2706 #ifdef DEBUG
2707 if (FLAG_trace_ic) {
2708 PrintF("[CompareIC in ");
2709 JavaScriptFrame::PrintTop(stdout, false, true);
2710 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
2711 GetStateName(previous_left),
2712 GetStateName(previous_right),
2713 GetStateName(previous_state),
2714 GetStateName(new_left),
2715 GetStateName(new_right),
2716 GetStateName(state),
2717 Token::Name(op_),
2718 static_cast<void*>(*stub.GetCode()));
2719 }
2720 #endif
2721
2722 // Activate inlined smi code.
2723 if (previous_state == UNINITIALIZED) {
2724 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2725 }
2726 }
2727
2728
2729 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
2662 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { 2730 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2663 NoHandleAllocation na; 2731 NoHandleAllocation na;
2664 ASSERT(args.length() == 3); 2732 ASSERT(args.length() == 3);
2665 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); 2733 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2666 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); 2734 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2667 return ic.target(); 2735 return ic.target();
2668 } 2736 }
2669 2737
2670 2738
2671 RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) { 2739 RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) {
(...skipping 28 matching lines...) Expand all
2700 #undef ADDR 2768 #undef ADDR
2701 }; 2769 };
2702 2770
2703 2771
2704 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2772 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2705 return IC_utilities[id]; 2773 return IC_utilities[id];
2706 } 2774 }
2707 2775
2708 2776
2709 } } // namespace v8::internal 2777 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698