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

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 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 @ %p]\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),
2486 static_cast<void*>(*code));
2490 } 2487 }
2488 #endif
2491 BinaryOpIC ic(isolate); 2489 BinaryOpIC ic(isolate);
2492 ic.patch(*code); 2490 ic.patch(*code);
2493 2491
2494 // Activate inlined smi code. 2492 // Activate inlined smi code.
2495 if (previous_type == BinaryOpIC::UNINITIALIZED) { 2493 if (previous_overall == BinaryOpIC::UNINITIALIZED) {
2496 PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK); 2494 PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK);
2497 } 2495 }
2498 } 2496 }
2499 2497
2500 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( 2498 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
2501 isolate->thread_local_top()->context_->builtins(), isolate); 2499 isolate->thread_local_top()->context_->builtins(), isolate);
2502 Object* builtin = NULL; // Initialization calms down the compiler. 2500 Object* builtin = NULL; // Initialization calms down the compiler.
2503 switch (op) { 2501 switch (op) {
2504 case Token::ADD: 2502 case Token::ADD:
2505 builtin = builtins->javascript_builtin(Builtins::ADD); 2503 builtin = builtins->javascript_builtin(Builtins::ADD);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2548 builtin_args, 2546 builtin_args,
2549 &caught_exception); 2547 &caught_exception);
2550 if (caught_exception) { 2548 if (caught_exception) {
2551 return Failure::Exception(); 2549 return Failure::Exception();
2552 } 2550 }
2553 return *result; 2551 return *result;
2554 } 2552 }
2555 2553
2556 2554
2557 Code* CompareIC::GetRawUninitialized(Token::Value op) { 2555 Code* CompareIC::GetRawUninitialized(Token::Value op) {
2558 ICCompareStub stub(op, UNINITIALIZED); 2556 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2559 Code* code = NULL; 2557 Code* code = NULL;
2560 CHECK(stub.FindCodeInCache(&code)); 2558 CHECK(stub.FindCodeInCache(&code));
2561 return code; 2559 return code;
2562 } 2560 }
2563 2561
2564 2562
2565 Handle<Code> CompareIC::GetUninitialized(Token::Value op) { 2563 Handle<Code> CompareIC::GetUninitialized(Token::Value op) {
2566 ICCompareStub stub(op, UNINITIALIZED); 2564 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2567 return stub.GetCode(); 2565 return stub.GetCode();
2568 } 2566 }
2569 2567
2570 2568
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) { 2569 const char* CompareIC::GetStateName(State state) {
2587 switch (state) { 2570 switch (state) {
2588 case UNINITIALIZED: return "UNINITIALIZED"; 2571 case UNINITIALIZED: return "UNINITIALIZED";
2589 case SMIS: return "SMIS"; 2572 case SMI: return "SMI";
2590 case HEAP_NUMBERS: return "HEAP_NUMBERS"; 2573 case HEAP_NUMBER: return "HEAP_NUMBER";
2591 case OBJECTS: return "OBJECTS"; 2574 case OBJECT: return "OBJECTS";
2592 case KNOWN_OBJECTS: return "KNOWN_OBJECTS"; 2575 case KNOWN_OBJECTS: return "KNOWN_OBJECTS";
2593 case SYMBOLS: return "SYMBOLS"; 2576 case SYMBOL: return "SYMBOL";
2594 case STRINGS: return "STRINGS"; 2577 case STRING: return "STRING";
2595 case GENERIC: return "GENERIC"; 2578 case GENERIC: return "GENERIC";
2596 default: 2579 default:
2597 UNREACHABLE(); 2580 UNREACHABLE();
2598 return NULL; 2581 return NULL;
2599 } 2582 }
2600 } 2583 }
2601 2584
2602 2585
2603 CompareIC::State CompareIC::TargetState(State state, 2586 static CompareIC::State InputState(CompareIC::State old_state,
2587 Handle<Object> value) {
2588 switch (old_state) {
2589 case CompareIC::UNINITIALIZED:
2590 if (value->IsSmi()) return CompareIC::SMI;
2591 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER;
2592 if (value->IsSymbol()) return CompareIC::SYMBOL;
2593 if (value->IsString()) return CompareIC::STRING;
2594 if (value->IsJSObject()) return CompareIC::OBJECT;
2595 break;
2596 case CompareIC::SMI:
2597 if (value->IsSmi()) return CompareIC::SMI;
2598 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER;
2599 break;
2600 case CompareIC::HEAP_NUMBER:
2601 if (value->IsNumber()) return CompareIC::HEAP_NUMBER;
2602 break;
2603 case CompareIC::SYMBOL:
2604 if (value->IsSymbol()) return CompareIC::SYMBOL;
2605 if (value->IsString()) return CompareIC::STRING;
2606 break;
2607 case CompareIC::STRING:
2608 if (value->IsSymbol() || value->IsString()) return CompareIC::STRING;
2609 break;
2610 case CompareIC::OBJECT:
2611 if (value->IsJSObject()) return CompareIC::OBJECT;
2612 break;
2613 case CompareIC::GENERIC:
2614 break;
2615 case CompareIC::KNOWN_OBJECTS:
2616 UNREACHABLE();
2617 break;
2618 }
2619 return CompareIC::GENERIC;
2620 }
2621
2622
2623 CompareIC::State CompareIC::TargetState(State old_state,
2624 State old_left,
2625 State old_right,
2604 bool has_inlined_smi_code, 2626 bool has_inlined_smi_code,
2605 Handle<Object> x, 2627 Handle<Object> x,
2606 Handle<Object> y) { 2628 Handle<Object> y) {
2607 switch (state) { 2629 switch (old_state) {
2608 case UNINITIALIZED: 2630 case UNINITIALIZED:
2609 if (x->IsSmi() && y->IsSmi()) return SMIS; 2631 if (x->IsSmi() && y->IsSmi()) return SMI;
2610 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS; 2632 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBER;
2611 if (Token::IsOrderedRelationalCompareOp(op_)) { 2633 if (Token::IsOrderedRelationalCompareOp(op_)) {
2612 // Ordered comparisons treat undefined as NaN, so the 2634 // Ordered comparisons treat undefined as NaN, so the
2613 // HEAP_NUMBER stub will do the right thing. 2635 // HEAP_NUMBER stub will do the right thing.
2614 if ((x->IsNumber() && y->IsUndefined()) || 2636 if ((x->IsNumber() && y->IsUndefined()) ||
2615 (y->IsNumber() && x->IsUndefined())) { 2637 (y->IsNumber() && x->IsUndefined())) {
2616 return HEAP_NUMBERS; 2638 return HEAP_NUMBER;
2617 } 2639 }
2618 } 2640 }
2619 if (x->IsSymbol() && y->IsSymbol()) { 2641 if (x->IsSymbol() && y->IsSymbol()) {
2620 // We compare symbols as strings if we need to determine 2642 // We compare symbols as strings if we need to determine
2621 // the order in a non-equality compare. 2643 // the order in a non-equality compare.
2622 return Token::IsEqualityOp(op_) ? SYMBOLS : STRINGS; 2644 return Token::IsEqualityOp(op_) ? SYMBOL : STRING;
2623 } 2645 }
2624 if (x->IsString() && y->IsString()) return STRINGS; 2646 if (x->IsString() && y->IsString()) return STRING;
2625 if (!Token::IsEqualityOp(op_)) return GENERIC; 2647 if (!Token::IsEqualityOp(op_)) return GENERIC;
2626 if (x->IsJSObject() && y->IsJSObject()) { 2648 if (x->IsJSObject() && y->IsJSObject()) {
2627 if (Handle<JSObject>::cast(x)->map() == 2649 if (Handle<JSObject>::cast(x)->map() ==
2628 Handle<JSObject>::cast(y)->map() && 2650 Handle<JSObject>::cast(y)->map() &&
2629 Token::IsEqualityOp(op_)) { 2651 Token::IsEqualityOp(op_)) {
2630 return KNOWN_OBJECTS; 2652 return KNOWN_OBJECTS;
2631 } else { 2653 } else {
2632 return OBJECTS; 2654 return OBJECT;
2633 } 2655 }
2634 } 2656 }
2635 return GENERIC; 2657 return GENERIC;
2636 case SMIS: 2658 case SMI:
2637 return has_inlined_smi_code && x->IsNumber() && y->IsNumber() 2659 return has_inlined_smi_code && x->IsNumber() && y->IsNumber()
2638 ? HEAP_NUMBERS 2660 ? HEAP_NUMBER
2639 : GENERIC; 2661 : GENERIC;
2640 case SYMBOLS: 2662 case SYMBOL:
2641 ASSERT(Token::IsEqualityOp(op_)); 2663 ASSERT(Token::IsEqualityOp(op_));
2642 return x->IsString() && y->IsString() ? STRINGS : GENERIC; 2664 return x->IsString() && y->IsString() ? STRING : GENERIC;
2643 case HEAP_NUMBERS: 2665 case HEAP_NUMBER:
2644 case STRINGS: 2666 if (old_left == SMI && x->IsHeapNumber()) return HEAP_NUMBER;
2645 case OBJECTS: 2667 if (old_right == SMI && y->IsHeapNumber()) return HEAP_NUMBER;
2668 case STRING:
2669 case OBJECT:
2646 case KNOWN_OBJECTS: 2670 case KNOWN_OBJECTS:
2647 case GENERIC: 2671 case GENERIC:
2648 return GENERIC; 2672 return GENERIC;
2649 } 2673 }
2650 UNREACHABLE(); 2674 UNREACHABLE();
2651 return GENERIC; 2675 return GENERIC; // Make the compiler happy.
2652 } 2676 }
2653 2677
2654 2678
2655 // Used from ic_<arch>.cc. 2679 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
2680 HandleScope scope;
2681 State previous_left, previous_right, previous_state;
2682 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left,
2683 &previous_right, &previous_state, NULL);
2684 State new_left = InputState(previous_left, x);
2685 State new_right = InputState(previous_right, y);
2686 State state = TargetState(previous_state, previous_left, previous_right,
2687 HasInlinedSmiCode(address()), x, y);
2688 ICCompareStub stub(op_, new_left, new_right, state);
2689 if (state == KNOWN_OBJECTS) {
2690 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map()));
2691 }
2692 set_target(*stub.GetCode());
2693
2694 #ifdef DEBUG
2695 if (FLAG_trace_ic) {
2696 PrintF("[CompareIC (%s->%s)#%s]\n",
2697 GetStateName(previous_state),
2698 GetStateName(state),
2699 Token::Name(op_));
2700 }
2701 #endif
2702
2703 // Activate inlined smi code.
2704 if (previous_state == UNINITIALIZED) {
2705 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2706 }
2707 }
2708
2709
2710 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
2656 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { 2711 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2657 NoHandleAllocation na; 2712 NoHandleAllocation na;
2658 ASSERT(args.length() == 3); 2713 ASSERT(args.length() == 3);
2659 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); 2714 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2660 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); 2715 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2661 return ic.target(); 2716 return ic.target();
2662 } 2717 }
2663 2718
2664 2719
2665 RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) { 2720 RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) {
(...skipping 28 matching lines...) Expand all
2694 #undef ADDR 2749 #undef ADDR
2695 }; 2750 };
2696 2751
2697 2752
2698 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2753 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2699 return IC_utilities[id]; 2754 return IC_utilities[id];
2700 } 2755 }
2701 2756
2702 2757
2703 } } // namespace v8::internal 2758 } } // namespace v8::internal
OLDNEW
« src/hydrogen-instructions.h ('K') | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698