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

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

Powered by Google App Engine
This is Rietveld 408576698