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

Side by Side Diff: src/ic.cc

Issue 24072013: Hydrogenisation of binops (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix rewrite mode & finetune type feedback Created 7 years, 2 months 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/isolate.cc » ('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 2353 matching lines...) Expand 10 before | Expand all | Expand 10 after
2364 StrictModeFlag strict_mode = ic.strict_mode(); 2364 StrictModeFlag strict_mode = ic.strict_mode();
2365 return Runtime::SetObjectProperty(isolate, 2365 return Runtime::SetObjectProperty(isolate,
2366 object, 2366 object,
2367 key, 2367 key,
2368 value, 2368 value,
2369 NONE, 2369 NONE,
2370 strict_mode); 2370 strict_mode);
2371 } 2371 }
2372 2372
2373 2373
2374 void BinaryOpIC::patch(Code* code) {
2375 set_target(code);
2376 }
2377
2378
2379 const char* BinaryOpIC::GetName(TypeInfo type_info) { 2374 const char* BinaryOpIC::GetName(TypeInfo type_info) {
2380 switch (type_info) { 2375 switch (type_info) {
2381 case UNINITIALIZED: return "Uninitialized"; 2376 case UNINITIALIZED: return "Uninitialized";
2382 case SMI: return "Smi"; 2377 case SMI: return "Smi";
2383 case INT32: return "Int32"; 2378 case INT32: return "Int32";
2384 case NUMBER: return "Number"; 2379 case NUMBER: return "Number";
2385 case ODDBALL: return "Oddball"; 2380 case ODDBALL: return "Oddball";
2386 case STRING: return "String"; 2381 case STRING: return "String";
2387 case GENERIC: return "Generic"; 2382 case GENERIC: return "Generic";
2388 default: return "Invalid"; 2383 default: return "Invalid";
2389 } 2384 }
2390 } 2385 }
2391 2386
2392 2387
2393 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) { 2388 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) {
2394 switch (type_info) { 2389 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
2395 case UNINITIALIZED: 2390 BinaryOpStub stub(extra_ic_state);
2396 return ::v8::internal::UNINITIALIZED; 2391
2397 case SMI: 2392 bool smi_was_enabled = stub.GetLeftType(isolate())->Maybe(Type::Smi()) &&
2398 case INT32: 2393 stub.GetRightType(isolate())->Maybe(Type::Smi());
2399 case NUMBER: 2394
2400 case ODDBALL: 2395 Maybe<Handle<Object> > result = stub.Result(left, right, isolate());
2401 case STRING: 2396
2402 return MONOMORPHIC; 2397 #ifdef DEBUG
2403 case GENERIC: 2398 if (FLAG_trace_ic) {
2404 return ::v8::internal::GENERIC; 2399 char buffer[100];
2400 NoAllocationStringAllocator allocator(buffer,
2401 static_cast<unsigned>(sizeof(buffer)));
2402 StringStream stream(&allocator);
2403 stream.Add("[");
2404 stub.PrintName(&stream);
2405
2406 stub.UpdateStatus(left, right, result);
2407
2408 stream.Add(" => ");
2409 stub.PrintState(&stream);
2410 stream.Add(" ");
2411 stream.OutputToStdOut();
2412 PrintF(" @ %p <- ", static_cast<void*>(*stub.GetCode(isolate())));
2413 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2414 PrintF("]\n");
2415 } else {
2416 stub.UpdateStatus(left, right, result);
2405 } 2417 }
2406 UNREACHABLE(); 2418 #else
2407 return ::v8::internal::UNINITIALIZED; 2419 stub.UpdateStatus(left, right, result);
2420 #endif
2421
2422 Handle<Code> code = stub.GetCode(isolate());
2423 set_target(*code);
2424
2425 bool enable_smi = stub.GetLeftType(isolate())->Maybe(Type::Smi()) &&
2426 stub.GetRightType(isolate())->Maybe(Type::Smi());
2427
2428 if (!smi_was_enabled && enable_smi) {
2429 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2430 } else if (smi_was_enabled && !enable_smi) {
2431 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK);
2432 }
2433
2434 return result.has_value
2435 ? static_cast<MaybeObject*>(*result.value)
2436 : Failure::Exception();
2408 } 2437 }
2409 2438
2410 2439
2411 Handle<Type> BinaryOpIC::TypeInfoToType(BinaryOpIC::TypeInfo binary_type, 2440 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) {
2412 Isolate* isolate) { 2441 HandleScope scope(isolate);
2413 switch (binary_type) { 2442 Handle<Object> left = args.at<Object>(0);
2414 case UNINITIALIZED: 2443 Handle<Object> right = args.at<Object>(1);
2415 return handle(Type::None(), isolate); 2444 BinaryOpIC ic(isolate);
2416 case SMI: 2445 return ic.Transition(left, right);
2417 return handle(Type::Smi(), isolate);
2418 case INT32:
2419 return handle(Type::Signed32(), isolate);
2420 case NUMBER:
2421 return handle(Type::Number(), isolate);
2422 case ODDBALL:
2423 return handle(Type::Optional(
2424 handle(Type::Union(
2425 handle(Type::Number(), isolate),
2426 handle(Type::String(), isolate)), isolate)), isolate);
2427 case STRING:
2428 return handle(Type::String(), isolate);
2429 case GENERIC:
2430 return handle(Type::Any(), isolate);
2431 }
2432 UNREACHABLE();
2433 return handle(Type::Any(), isolate);
2434 } 2446 }
2435 2447
2436 2448
2437 void BinaryOpIC::StubInfoToType(int minor_key,
2438 Handle<Type>* left,
2439 Handle<Type>* right,
2440 Handle<Type>* result,
2441 Isolate* isolate) {
2442 TypeInfo left_typeinfo, right_typeinfo, result_typeinfo;
2443 BinaryOpStub::decode_types_from_minor_key(
2444 minor_key, &left_typeinfo, &right_typeinfo, &result_typeinfo);
2445 *left = TypeInfoToType(left_typeinfo, isolate);
2446 *right = TypeInfoToType(right_typeinfo, isolate);
2447 *result = TypeInfoToType(result_typeinfo, isolate);
2448 }
2449
2450
2451 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value,
2452 Token::Value op) {
2453 v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value);
2454 if (type.IsSmi()) return BinaryOpIC::SMI;
2455 if (type.IsInteger32()) {
2456 if (SmiValuesAre32Bits()) return BinaryOpIC::SMI;
2457 return BinaryOpIC::INT32;
2458 }
2459 if (type.IsNumber()) return BinaryOpIC::NUMBER;
2460 if (type.IsString()) return BinaryOpIC::STRING;
2461 if (value->IsUndefined()) {
2462 if (op == Token::BIT_AND ||
2463 op == Token::BIT_OR ||
2464 op == Token::BIT_XOR ||
2465 op == Token::SAR ||
2466 op == Token::SHL ||
2467 op == Token::SHR) {
2468 if (SmiValuesAre32Bits()) return BinaryOpIC::SMI;
2469 return BinaryOpIC::INT32;
2470 }
2471 return BinaryOpIC::ODDBALL;
2472 }
2473 return BinaryOpIC::GENERIC;
2474 }
2475
2476
2477 static BinaryOpIC::TypeInfo InputState(BinaryOpIC::TypeInfo old_type,
2478 Handle<Object> value,
2479 Token::Value op) {
2480 BinaryOpIC::TypeInfo new_type = TypeInfoFromValue(value, op);
2481 if (old_type == BinaryOpIC::STRING) {
2482 if (new_type == BinaryOpIC::STRING) return new_type;
2483 return BinaryOpIC::GENERIC;
2484 }
2485 return Max(old_type, new_type);
2486 }
2487
2488
2489 #ifdef DEBUG
2490 static void TraceBinaryOp(BinaryOpIC::TypeInfo left,
2491 BinaryOpIC::TypeInfo right,
2492 Maybe<int32_t> fixed_right_arg,
2493 BinaryOpIC::TypeInfo result) {
2494 PrintF("%s*%s", BinaryOpIC::GetName(left), BinaryOpIC::GetName(right));
2495 if (fixed_right_arg.has_value) PrintF("{%d}", fixed_right_arg.value);
2496 PrintF("->%s", BinaryOpIC::GetName(result));
2497 }
2498 #endif
2499
2500
2501 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
2502 ASSERT(args.length() == 3);
2503
2504 HandleScope scope(isolate);
2505 Handle<Object> left = args.at<Object>(0);
2506 Handle<Object> right = args.at<Object>(1);
2507 int key = args.smi_at(2);
2508 Token::Value op = BinaryOpStub::decode_op_from_minor_key(key);
2509
2510 BinaryOpIC::TypeInfo previous_left, previous_right, previous_result;
2511 BinaryOpStub::decode_types_from_minor_key(
2512 key, &previous_left, &previous_right, &previous_result);
2513
2514 BinaryOpIC::TypeInfo new_left = InputState(previous_left, left, op);
2515 BinaryOpIC::TypeInfo new_right = InputState(previous_right, right, op);
2516 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED;
2517
2518 // STRING is only used for ADD operations.
2519 if ((new_left == BinaryOpIC::STRING || new_right == BinaryOpIC::STRING) &&
2520 op != Token::ADD) {
2521 new_left = new_right = BinaryOpIC::GENERIC;
2522 }
2523
2524 BinaryOpIC::TypeInfo new_overall = Max(new_left, new_right);
2525 BinaryOpIC::TypeInfo previous_overall = Max(previous_left, previous_right);
2526
2527 Maybe<int> previous_fixed_right_arg =
2528 BinaryOpStub::decode_fixed_right_arg_from_minor_key(key);
2529
2530 int32_t value;
2531 bool new_has_fixed_right_arg =
2532 op == Token::MOD &&
2533 right->ToInt32(&value) &&
2534 BinaryOpStub::can_encode_arg_value(value) &&
2535 (previous_overall == BinaryOpIC::UNINITIALIZED ||
2536 (previous_fixed_right_arg.has_value &&
2537 previous_fixed_right_arg.value == value));
2538 Maybe<int32_t> new_fixed_right_arg(
2539 new_has_fixed_right_arg, new_has_fixed_right_arg ? value : 1);
2540
2541 if (previous_fixed_right_arg.has_value == new_fixed_right_arg.has_value) {
2542 if (new_overall == BinaryOpIC::SMI && previous_overall == BinaryOpIC::SMI) {
2543 if (op == Token::DIV ||
2544 op == Token::MUL ||
2545 op == Token::SHR ||
2546 SmiValuesAre32Bits()) {
2547 // Arithmetic on two Smi inputs has yielded a heap number.
2548 // That is the only way to get here from the Smi stub.
2549 // With 32-bit Smis, all overflows give heap numbers, but with
2550 // 31-bit Smis, most operations overflow to int32 results.
2551 result_type = BinaryOpIC::NUMBER;
2552 } else {
2553 // Other operations on SMIs that overflow yield int32s.
2554 result_type = BinaryOpIC::INT32;
2555 }
2556 }
2557 if (new_overall == BinaryOpIC::INT32 &&
2558 previous_overall == BinaryOpIC::INT32) {
2559 if (new_left == previous_left && new_right == previous_right) {
2560 result_type = BinaryOpIC::NUMBER;
2561 }
2562 }
2563 }
2564
2565 BinaryOpStub stub(key, new_left, new_right, result_type, new_fixed_right_arg);
2566 Handle<Code> code = stub.GetCode(isolate);
2567 if (!code.is_null()) {
2568 #ifdef DEBUG
2569 if (FLAG_trace_ic) {
2570 PrintF("[BinaryOpIC in ");
2571 JavaScriptFrame::PrintTop(isolate, stdout, false, true);
2572 PrintF(" ");
2573 TraceBinaryOp(previous_left, previous_right, previous_fixed_right_arg,
2574 previous_result);
2575 PrintF(" => ");
2576 TraceBinaryOp(new_left, new_right, new_fixed_right_arg, result_type);
2577 PrintF(" #%s @ %p]\n", Token::Name(op), static_cast<void*>(*code));
2578 }
2579 #endif
2580 BinaryOpIC ic(isolate);
2581 ic.patch(*code);
2582
2583 // Activate inlined smi code.
2584 if (previous_overall == BinaryOpIC::UNINITIALIZED) {
2585 PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK);
2586 }
2587 }
2588
2589 Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
2590 Object* builtin = NULL; // Initialization calms down the compiler.
2591 switch (op) {
2592 case Token::ADD:
2593 builtin = builtins->javascript_builtin(Builtins::ADD);
2594 break;
2595 case Token::SUB:
2596 builtin = builtins->javascript_builtin(Builtins::SUB);
2597 break;
2598 case Token::MUL:
2599 builtin = builtins->javascript_builtin(Builtins::MUL);
2600 break;
2601 case Token::DIV:
2602 builtin = builtins->javascript_builtin(Builtins::DIV);
2603 break;
2604 case Token::MOD:
2605 builtin = builtins->javascript_builtin(Builtins::MOD);
2606 break;
2607 case Token::BIT_AND:
2608 builtin = builtins->javascript_builtin(Builtins::BIT_AND);
2609 break;
2610 case Token::BIT_OR:
2611 builtin = builtins->javascript_builtin(Builtins::BIT_OR);
2612 break;
2613 case Token::BIT_XOR:
2614 builtin = builtins->javascript_builtin(Builtins::BIT_XOR);
2615 break;
2616 case Token::SHR:
2617 builtin = builtins->javascript_builtin(Builtins::SHR);
2618 break;
2619 case Token::SAR:
2620 builtin = builtins->javascript_builtin(Builtins::SAR);
2621 break;
2622 case Token::SHL:
2623 builtin = builtins->javascript_builtin(Builtins::SHL);
2624 break;
2625 default:
2626 UNREACHABLE();
2627 }
2628
2629 Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
2630
2631 bool caught_exception;
2632 Handle<Object> builtin_args[] = { right };
2633 Handle<Object> result = Execution::Call(isolate,
2634 builtin_function,
2635 left,
2636 ARRAY_SIZE(builtin_args),
2637 builtin_args,
2638 &caught_exception);
2639 if (caught_exception) {
2640 return Failure::Exception();
2641 }
2642 return *result;
2643 }
2644
2645
2646 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { 2449 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2647 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2450 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2648 Code* code = NULL; 2451 Code* code = NULL;
2649 CHECK(stub.FindCodeInCache(&code, isolate)); 2452 CHECK(stub.FindCodeInCache(&code, isolate));
2650 return code; 2453 return code;
2651 } 2454 }
2652 2455
2653 2456
2654 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { 2457 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) {
2655 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2458 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
2933 } 2736 }
2934 2737
2935 2738
2936 RUNTIME_FUNCTION(MaybeObject*, Unreachable) { 2739 RUNTIME_FUNCTION(MaybeObject*, Unreachable) {
2937 UNREACHABLE(); 2740 UNREACHABLE();
2938 CHECK(false); 2741 CHECK(false);
2939 return isolate->heap()->undefined_value(); 2742 return isolate->heap()->undefined_value();
2940 } 2743 }
2941 2744
2942 2745
2746 Builtins::JavaScript BinaryOpIC::TokenToJSBuiltin(Token::Value op) {
2747 switch (op) {
2748 default:
2749 UNREACHABLE();
2750 case Token::ADD:
2751 return Builtins::ADD;
2752 break;
2753 case Token::SUB:
2754 return Builtins::SUB;
2755 break;
2756 case Token::MUL:
2757 return Builtins::MUL;
2758 break;
2759 case Token::DIV:
2760 return Builtins::DIV;
2761 break;
2762 case Token::MOD:
2763 return Builtins::MOD;
2764 break;
2765 case Token::BIT_OR:
2766 return Builtins::BIT_OR;
2767 break;
2768 case Token::BIT_AND:
2769 return Builtins::BIT_AND;
2770 break;
2771 case Token::BIT_XOR:
2772 return Builtins::BIT_XOR;
2773 break;
2774 case Token::SAR:
2775 return Builtins::SAR;
2776 break;
2777 case Token::SHR:
2778 return Builtins::SHR;
2779 break;
2780 case Token::SHL:
2781 return Builtins::SHL;
2782 break;
2783 }
2784 }
2785
2786
2943 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object, 2787 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object,
2944 Code::ExtraICState extra_ic_state) { 2788 Code::ExtraICState extra_ic_state) {
2945 ToBooleanStub stub(extra_ic_state); 2789 ToBooleanStub stub(extra_ic_state);
2946 bool to_boolean_value = stub.UpdateStatus(object); 2790 bool to_boolean_value = stub.UpdateStatus(object);
2947 Handle<Code> code = stub.GetCode(isolate()); 2791 Handle<Code> code = stub.GetCode(isolate());
2948 set_target(*code); 2792 set_target(*code);
2949 return Smi::FromInt(to_boolean_value ? 1 : 0); 2793 return Smi::FromInt(to_boolean_value ? 1 : 0);
2950 } 2794 }
2951 2795
2952 2796
(...skipping 14 matching lines...) Expand all
2967 #undef ADDR 2811 #undef ADDR
2968 }; 2812 };
2969 2813
2970 2814
2971 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2815 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2972 return IC_utilities[id]; 2816 return IC_utilities[id];
2973 } 2817 }
2974 2818
2975 2819
2976 } } // namespace v8::internal 2820 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/isolate.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698