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

Side by Side Diff: src/ic.cc

Issue 23618002: Hydrogenisation of binops (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebase Created 7 years, 3 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 2519 matching lines...) Expand 10 before | Expand all | Expand 10 after
2530 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); 2530 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state);
2531 return Runtime::SetObjectProperty(isolate, 2531 return Runtime::SetObjectProperty(isolate,
2532 object, 2532 object,
2533 key, 2533 key,
2534 value, 2534 value,
2535 NONE, 2535 NONE,
2536 strict_mode); 2536 strict_mode);
2537 } 2537 }
2538 2538
2539 2539
2540 void BinaryOpIC::patch(Code* code) {
2541 set_target(code);
2542 }
2543
2544
2545 const char* BinaryOpIC::GetName(TypeInfo type_info) { 2540 const char* BinaryOpIC::GetName(TypeInfo type_info) {
2546 switch (type_info) { 2541 switch (type_info) {
2547 case UNINITIALIZED: return "Uninitialized"; 2542 case UNINITIALIZED: return "Uninitialized";
2548 case SMI: return "Smi"; 2543 case SMI: return "Smi";
2549 case INT32: return "Int32"; 2544 case INT32: return "Int32";
2550 case NUMBER: return "Number"; 2545 case NUMBER: return "Number";
2551 case ODDBALL: return "Oddball"; 2546 case ODDBALL: return "Oddball";
2552 case STRING: return "String"; 2547 case STRING: return "String";
2553 case GENERIC: return "Generic"; 2548 case GENERIC: return "Generic";
2554 default: return "Invalid"; 2549 default: return "Invalid";
2555 } 2550 }
2556 } 2551 }
2557 2552
2558 2553
2559 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) { 2554 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) {
2560 switch (type_info) { 2555 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
2561 case UNINITIALIZED: 2556 BinaryOpStub stub(extra_ic_state);
2562 return ::v8::internal::UNINITIALIZED; 2557
2563 case SMI: 2558 bool smi_was_enabled = stub.GetLeftType(isolate())->Maybe(Type::Smi()) &&
2564 case INT32: 2559 stub.GetRightType(isolate())->Maybe(Type::Smi());
2565 case NUMBER: 2560
2566 case ODDBALL: 2561 Maybe<Handle<Object> > result = stub.Result(left, right, isolate());
2567 case STRING: 2562
2568 return MONOMORPHIC; 2563 #ifdef DEBUG
2569 case GENERIC: 2564 if (FLAG_trace_ic) {
2570 return ::v8::internal::GENERIC; 2565 char buffer[100];
2566 NoAllocationStringAllocator allocator(buffer,
2567 static_cast<unsigned>(sizeof(buffer)));
2568 StringStream stream(&allocator);
2569 stream.Add("[");
2570 stub.PrintName(&stream);
2571
2572 stub.UpdateStatus(left, right, result);
2573
2574 stream.Add(" => ");
2575 stub.PrintState(&stream);
2576 stream.Add(" ");
2577 stream.OutputToStdOut();
2578 PrintF(" @ %p <- ", static_cast<void*>(*stub.GetCode(isolate())));
2579 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2580 PrintF("]\n");
2581 } else {
2582 stub.UpdateStatus(left, right, result);
2571 } 2583 }
2572 UNREACHABLE(); 2584 #else
2573 return ::v8::internal::UNINITIALIZED; 2585 stub.UpdateStatus(left, right, result);
2586 #endif
2587
2588 Handle<Code> code = stub.GetCode(isolate());
2589 set_target(*code);
2590
2591 bool enable_smi = stub.GetLeftType(isolate())->Maybe(Type::Smi()) &&
2592 stub.GetRightType(isolate())->Maybe(Type::Smi());
2593
2594 if (!smi_was_enabled && enable_smi) {
2595 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2596 } else if (smi_was_enabled && !enable_smi) {
2597 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK);
2598 }
2599
2600 return result.has_value
2601 ? static_cast<MaybeObject*>(*result.value)
2602 : Failure::Exception();
2574 } 2603 }
2575 2604
2576 2605
2577 Handle<Type> BinaryOpIC::TypeInfoToType(BinaryOpIC::TypeInfo binary_type, 2606 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) {
2578 Isolate* isolate) { 2607 HandleScope scope(isolate);
2579 switch (binary_type) { 2608 Handle<Object> left = args.at<Object>(0);
2580 case UNINITIALIZED: 2609 Handle<Object> right = args.at<Object>(1);
2581 return handle(Type::None(), isolate); 2610 BinaryOpIC ic(isolate);
2582 case SMI: 2611 return ic.Transition(left, right);
2583 return handle(Type::Smi(), isolate);
2584 case INT32:
2585 return handle(Type::Signed32(), isolate);
2586 case NUMBER:
2587 return handle(Type::Number(), isolate);
2588 case ODDBALL:
2589 return handle(Type::Optional(
2590 handle(Type::Union(
2591 handle(Type::Number(), isolate),
2592 handle(Type::String(), isolate)), isolate)), isolate);
2593 case STRING:
2594 return handle(Type::String(), isolate);
2595 case GENERIC:
2596 return handle(Type::Any(), isolate);
2597 }
2598 UNREACHABLE();
2599 return handle(Type::Any(), isolate);
2600 } 2612 }
2601 2613
2602 2614
2603 void BinaryOpIC::StubInfoToType(int minor_key,
2604 Handle<Type>* left,
2605 Handle<Type>* right,
2606 Handle<Type>* result,
2607 Isolate* isolate) {
2608 TypeInfo left_typeinfo, right_typeinfo, result_typeinfo;
2609 BinaryOpStub::decode_types_from_minor_key(
2610 minor_key, &left_typeinfo, &right_typeinfo, &result_typeinfo);
2611 *left = TypeInfoToType(left_typeinfo, isolate);
2612 *right = TypeInfoToType(right_typeinfo, isolate);
2613 *result = TypeInfoToType(result_typeinfo, isolate);
2614 }
2615
2616
2617 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value,
2618 Token::Value op) {
2619 v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value);
2620 if (type.IsSmi()) return BinaryOpIC::SMI;
2621 if (type.IsInteger32()) {
2622 if (SmiValuesAre32Bits()) return BinaryOpIC::SMI;
2623 return BinaryOpIC::INT32;
2624 }
2625 if (type.IsNumber()) return BinaryOpIC::NUMBER;
2626 if (type.IsString()) return BinaryOpIC::STRING;
2627 if (value->IsUndefined()) {
2628 if (op == Token::BIT_AND ||
2629 op == Token::BIT_OR ||
2630 op == Token::BIT_XOR ||
2631 op == Token::SAR ||
2632 op == Token::SHL ||
2633 op == Token::SHR) {
2634 if (SmiValuesAre32Bits()) return BinaryOpIC::SMI;
2635 return BinaryOpIC::INT32;
2636 }
2637 return BinaryOpIC::ODDBALL;
2638 }
2639 return BinaryOpIC::GENERIC;
2640 }
2641
2642
2643 static BinaryOpIC::TypeInfo InputState(BinaryOpIC::TypeInfo old_type,
2644 Handle<Object> value,
2645 Token::Value op) {
2646 BinaryOpIC::TypeInfo new_type = TypeInfoFromValue(value, op);
2647 if (old_type == BinaryOpIC::STRING) {
2648 if (new_type == BinaryOpIC::STRING) return new_type;
2649 return BinaryOpIC::GENERIC;
2650 }
2651 return Max(old_type, new_type);
2652 }
2653
2654
2655 #ifdef DEBUG
2656 static void TraceBinaryOp(BinaryOpIC::TypeInfo left,
2657 BinaryOpIC::TypeInfo right,
2658 Maybe<int32_t> fixed_right_arg,
2659 BinaryOpIC::TypeInfo result) {
2660 PrintF("%s*%s", BinaryOpIC::GetName(left), BinaryOpIC::GetName(right));
2661 if (fixed_right_arg.has_value) PrintF("{%d}", fixed_right_arg.value);
2662 PrintF("->%s", BinaryOpIC::GetName(result));
2663 }
2664 #endif
2665
2666
2667 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
2668 ASSERT(args.length() == 3);
2669
2670 HandleScope scope(isolate);
2671 Handle<Object> left = args.at<Object>(0);
2672 Handle<Object> right = args.at<Object>(1);
2673 int key = args.smi_at(2);
2674 Token::Value op = BinaryOpStub::decode_op_from_minor_key(key);
2675
2676 BinaryOpIC::TypeInfo previous_left, previous_right, previous_result;
2677 BinaryOpStub::decode_types_from_minor_key(
2678 key, &previous_left, &previous_right, &previous_result);
2679
2680 BinaryOpIC::TypeInfo new_left = InputState(previous_left, left, op);
2681 BinaryOpIC::TypeInfo new_right = InputState(previous_right, right, op);
2682 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED;
2683
2684 // STRING is only used for ADD operations.
2685 if ((new_left == BinaryOpIC::STRING || new_right == BinaryOpIC::STRING) &&
2686 op != Token::ADD) {
2687 new_left = new_right = BinaryOpIC::GENERIC;
2688 }
2689
2690 BinaryOpIC::TypeInfo new_overall = Max(new_left, new_right);
2691 BinaryOpIC::TypeInfo previous_overall = Max(previous_left, previous_right);
2692
2693 Maybe<int> previous_fixed_right_arg =
2694 BinaryOpStub::decode_fixed_right_arg_from_minor_key(key);
2695
2696 int32_t value;
2697 bool new_has_fixed_right_arg =
2698 op == Token::MOD &&
2699 right->ToInt32(&value) &&
2700 BinaryOpStub::can_encode_arg_value(value) &&
2701 (previous_overall == BinaryOpIC::UNINITIALIZED ||
2702 (previous_fixed_right_arg.has_value &&
2703 previous_fixed_right_arg.value == value));
2704 Maybe<int32_t> new_fixed_right_arg(
2705 new_has_fixed_right_arg, new_has_fixed_right_arg ? value : 1);
2706
2707 if (previous_fixed_right_arg.has_value == new_fixed_right_arg.has_value) {
2708 if (new_overall == BinaryOpIC::SMI && previous_overall == BinaryOpIC::SMI) {
2709 if (op == Token::DIV ||
2710 op == Token::MUL ||
2711 op == Token::SHR ||
2712 SmiValuesAre32Bits()) {
2713 // Arithmetic on two Smi inputs has yielded a heap number.
2714 // That is the only way to get here from the Smi stub.
2715 // With 32-bit Smis, all overflows give heap numbers, but with
2716 // 31-bit Smis, most operations overflow to int32 results.
2717 result_type = BinaryOpIC::NUMBER;
2718 } else {
2719 // Other operations on SMIs that overflow yield int32s.
2720 result_type = BinaryOpIC::INT32;
2721 }
2722 }
2723 if (new_overall == BinaryOpIC::INT32 &&
2724 previous_overall == BinaryOpIC::INT32) {
2725 if (new_left == previous_left && new_right == previous_right) {
2726 result_type = BinaryOpIC::NUMBER;
2727 }
2728 }
2729 }
2730
2731 BinaryOpStub stub(key, new_left, new_right, result_type, new_fixed_right_arg);
2732 Handle<Code> code = stub.GetCode(isolate);
2733 if (!code.is_null()) {
2734 #ifdef DEBUG
2735 if (FLAG_trace_ic) {
2736 PrintF("[BinaryOpIC in ");
2737 JavaScriptFrame::PrintTop(isolate, stdout, false, true);
2738 PrintF(" ");
2739 TraceBinaryOp(previous_left, previous_right, previous_fixed_right_arg,
2740 previous_result);
2741 PrintF(" => ");
2742 TraceBinaryOp(new_left, new_right, new_fixed_right_arg, result_type);
2743 PrintF(" #%s @ %p]\n", Token::Name(op), static_cast<void*>(*code));
2744 }
2745 #endif
2746 BinaryOpIC ic(isolate);
2747 ic.patch(*code);
2748
2749 // Activate inlined smi code.
2750 if (previous_overall == BinaryOpIC::UNINITIALIZED) {
2751 PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK);
2752 }
2753 }
2754
2755 Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
2756 Object* builtin = NULL; // Initialization calms down the compiler.
2757 switch (op) {
2758 case Token::ADD:
2759 builtin = builtins->javascript_builtin(Builtins::ADD);
2760 break;
2761 case Token::SUB:
2762 builtin = builtins->javascript_builtin(Builtins::SUB);
2763 break;
2764 case Token::MUL:
2765 builtin = builtins->javascript_builtin(Builtins::MUL);
2766 break;
2767 case Token::DIV:
2768 builtin = builtins->javascript_builtin(Builtins::DIV);
2769 break;
2770 case Token::MOD:
2771 builtin = builtins->javascript_builtin(Builtins::MOD);
2772 break;
2773 case Token::BIT_AND:
2774 builtin = builtins->javascript_builtin(Builtins::BIT_AND);
2775 break;
2776 case Token::BIT_OR:
2777 builtin = builtins->javascript_builtin(Builtins::BIT_OR);
2778 break;
2779 case Token::BIT_XOR:
2780 builtin = builtins->javascript_builtin(Builtins::BIT_XOR);
2781 break;
2782 case Token::SHR:
2783 builtin = builtins->javascript_builtin(Builtins::SHR);
2784 break;
2785 case Token::SAR:
2786 builtin = builtins->javascript_builtin(Builtins::SAR);
2787 break;
2788 case Token::SHL:
2789 builtin = builtins->javascript_builtin(Builtins::SHL);
2790 break;
2791 default:
2792 UNREACHABLE();
2793 }
2794
2795 Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
2796
2797 bool caught_exception;
2798 Handle<Object> builtin_args[] = { right };
2799 Handle<Object> result = Execution::Call(isolate,
2800 builtin_function,
2801 left,
2802 ARRAY_SIZE(builtin_args),
2803 builtin_args,
2804 &caught_exception);
2805 if (caught_exception) {
2806 return Failure::Exception();
2807 }
2808 return *result;
2809 }
2810
2811
2812 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { 2615 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2813 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2616 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2814 Code* code = NULL; 2617 Code* code = NULL;
2815 CHECK(stub.FindCodeInCache(&code, isolate)); 2618 CHECK(stub.FindCodeInCache(&code, isolate));
2816 return code; 2619 return code;
2817 } 2620 }
2818 2621
2819 2622
2820 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { 2623 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) {
2821 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2624 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
3099 } 2902 }
3100 2903
3101 2904
3102 RUNTIME_FUNCTION(MaybeObject*, Unreachable) { 2905 RUNTIME_FUNCTION(MaybeObject*, Unreachable) {
3103 UNREACHABLE(); 2906 UNREACHABLE();
3104 CHECK(false); 2907 CHECK(false);
3105 return isolate->heap()->undefined_value(); 2908 return isolate->heap()->undefined_value();
3106 } 2909 }
3107 2910
3108 2911
2912 Builtins::JavaScript BinaryOpIC::TokenToJSBuiltin(Token::Value op) {
2913 switch (op) {
2914 default:
2915 UNREACHABLE();
2916 case Token::ADD:
2917 return Builtins::ADD;
2918 break;
2919 case Token::SUB:
2920 return Builtins::SUB;
2921 break;
2922 case Token::MUL:
2923 return Builtins::MUL;
2924 break;
2925 case Token::DIV:
2926 return Builtins::DIV;
2927 break;
2928 case Token::MOD:
2929 return Builtins::MOD;
2930 break;
2931 case Token::BIT_OR:
2932 return Builtins::BIT_OR;
2933 break;
2934 case Token::BIT_AND:
2935 return Builtins::BIT_AND;
2936 break;
2937 case Token::BIT_XOR:
2938 return Builtins::BIT_XOR;
2939 break;
2940 case Token::SAR:
2941 return Builtins::SAR;
2942 break;
2943 case Token::SHR:
2944 return Builtins::SHR;
2945 break;
2946 case Token::SHL:
2947 return Builtins::SHL;
2948 break;
2949 }
2950 }
2951
2952
3109 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object, 2953 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object,
3110 Code::ExtraICState extra_ic_state) { 2954 Code::ExtraICState extra_ic_state) {
3111 ToBooleanStub stub(extra_ic_state); 2955 ToBooleanStub stub(extra_ic_state);
3112 bool to_boolean_value = stub.UpdateStatus(object); 2956 bool to_boolean_value = stub.UpdateStatus(object);
3113 Handle<Code> code = stub.GetCode(isolate()); 2957 Handle<Code> code = stub.GetCode(isolate());
3114 set_target(*code); 2958 set_target(*code);
3115 return Smi::FromInt(to_boolean_value ? 1 : 0); 2959 return Smi::FromInt(to_boolean_value ? 1 : 0);
3116 } 2960 }
3117 2961
3118 2962
(...skipping 14 matching lines...) Expand all
3133 #undef ADDR 2977 #undef ADDR
3134 }; 2978 };
3135 2979
3136 2980
3137 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2981 Address IC::AddressFromUtilityId(IC::UtilityId id) {
3138 return IC_utilities[id]; 2982 return IC_utilities[id];
3139 } 2983 }
3140 2984
3141 2985
3142 } } // namespace v8::internal 2986 } } // 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