OLD | NEW |
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 2579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2590 } | 2590 } |
2591 ASSERT_NE(GENERIC, result_kind); | 2591 ASSERT_NE(GENERIC, result_kind); |
2592 return KindToType(result_kind, isolate); | 2592 return KindToType(result_kind, isolate); |
2593 } | 2593 } |
2594 | 2594 |
2595 | 2595 |
2596 void BinaryOpIC::State::Print(StringStream* stream) const { | 2596 void BinaryOpIC::State::Print(StringStream* stream) const { |
2597 stream->Add("(%s", Token::Name(op_)); | 2597 stream->Add("(%s", Token::Name(op_)); |
2598 if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft"); | 2598 if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft"); |
2599 else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight"); | 2599 else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight"); |
| 2600 if (CouldCreateAllocationMementos()) stream->Add("_CreateAllocationMementos"); |
2600 stream->Add(":%s*", KindToString(left_kind_)); | 2601 stream->Add(":%s*", KindToString(left_kind_)); |
2601 if (fixed_right_arg_.has_value) { | 2602 if (fixed_right_arg_.has_value) { |
2602 stream->Add("%d", fixed_right_arg_.value); | 2603 stream->Add("%d", fixed_right_arg_.value); |
2603 } else { | 2604 } else { |
2604 stream->Add("%s", KindToString(right_kind_)); | 2605 stream->Add("%s", KindToString(right_kind_)); |
2605 } | 2606 } |
2606 stream->Add("->%s)", KindToString(result_kind_)); | 2607 stream->Add("->%s)", KindToString(result_kind_)); |
2607 } | 2608 } |
2608 | 2609 |
2609 | 2610 |
(...skipping 19 matching lines...) Expand all Loading... |
2629 | 2630 |
2630 result_kind_ = UpdateKind(result, result_kind_); | 2631 result_kind_ = UpdateKind(result, result_kind_); |
2631 | 2632 |
2632 if (!Token::IsTruncatingBinaryOp(op_)) { | 2633 if (!Token::IsTruncatingBinaryOp(op_)) { |
2633 Kind input_kind = Max(left_kind_, right_kind_); | 2634 Kind input_kind = Max(left_kind_, right_kind_); |
2634 if (result_kind_ < input_kind && input_kind <= NUMBER) { | 2635 if (result_kind_ < input_kind && input_kind <= NUMBER) { |
2635 result_kind_ = input_kind; | 2636 result_kind_ = input_kind; |
2636 } | 2637 } |
2637 } | 2638 } |
2638 | 2639 |
| 2640 // We don't want to distinguish INT32 and NUMBER for string add (because |
| 2641 // NumberToString can't make use of this anyway). |
| 2642 if (left_kind_ == STRING && right_kind_ == INT32) { |
| 2643 ASSERT_EQ(STRING, result_kind_); |
| 2644 ASSERT_EQ(Token::ADD, op_); |
| 2645 right_kind_ = NUMBER; |
| 2646 } else if (right_kind_ == STRING && left_kind_ == INT32) { |
| 2647 ASSERT_EQ(STRING, result_kind_); |
| 2648 ASSERT_EQ(Token::ADD, op_); |
| 2649 left_kind_ = NUMBER; |
| 2650 } |
| 2651 |
2639 // Reset overwrite mode unless we can actually make use of it, or may be able | 2652 // Reset overwrite mode unless we can actually make use of it, or may be able |
2640 // to make use of it at some point in the future. | 2653 // to make use of it at some point in the future. |
2641 if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) || | 2654 if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) || |
2642 (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) || | 2655 (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) || |
2643 result_kind_ > NUMBER) { | 2656 result_kind_ > NUMBER) { |
2644 mode_ = NO_OVERWRITE; | 2657 mode_ = NO_OVERWRITE; |
2645 } | 2658 } |
2646 | 2659 |
2647 if (old_extra_ic_state == GetExtraICState()) { | 2660 if (old_extra_ic_state == GetExtraICState()) { |
2648 // Tagged operations can lead to non-truncating HChanges | 2661 // Tagged operations can lead to non-truncating HChanges |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2714 case SMI: type = Type::Smi(); break; | 2727 case SMI: type = Type::Smi(); break; |
2715 case INT32: type = Type::Signed32(); break; | 2728 case INT32: type = Type::Signed32(); break; |
2716 case NUMBER: type = Type::Number(); break; | 2729 case NUMBER: type = Type::Number(); break; |
2717 case STRING: type = Type::String(); break; | 2730 case STRING: type = Type::String(); break; |
2718 case GENERIC: type = Type::Any(); break; | 2731 case GENERIC: type = Type::Any(); break; |
2719 } | 2732 } |
2720 return handle(type, isolate); | 2733 return handle(type, isolate); |
2721 } | 2734 } |
2722 | 2735 |
2723 | 2736 |
2724 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) { | 2737 MaybeObject* BinaryOpIC::Transition(Handle<AllocationSite> allocation_site, |
| 2738 Handle<Object> left, |
| 2739 Handle<Object> right) { |
2725 State state(target()->extended_extra_ic_state()); | 2740 State state(target()->extended_extra_ic_state()); |
2726 | 2741 |
2727 // Compute the actual result using the builtin for the binary operation. | 2742 // Compute the actual result using the builtin for the binary operation. |
2728 Object* builtin = isolate()->js_builtins_object()->javascript_builtin( | 2743 Object* builtin = isolate()->js_builtins_object()->javascript_builtin( |
2729 TokenToJSBuiltin(state.op())); | 2744 TokenToJSBuiltin(state.op())); |
2730 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate()); | 2745 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate()); |
2731 bool caught_exception; | 2746 bool caught_exception; |
2732 Handle<Object> result = Execution::Call( | 2747 Handle<Object> result = Execution::Call( |
2733 isolate(), function, left, 1, &right, &caught_exception); | 2748 isolate(), function, left, 1, &right, &caught_exception); |
2734 if (caught_exception) return Failure::Exception(); | 2749 if (caught_exception) return Failure::Exception(); |
2735 | 2750 |
2736 // Compute the new state. | 2751 // Compute the new state. |
2737 State old_state = state; | 2752 State old_state = state; |
2738 state.Update(left, right, result); | 2753 state.Update(left, right, result); |
2739 | 2754 |
2740 // Install the new stub. | 2755 // Check if we have a string operation here. |
2741 BinaryOpICStub stub(state); | 2756 Handle<Code> target; |
2742 set_target(*stub.GetCode(isolate())); | 2757 if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) { |
| 2758 // Setup the allocation site on-demand. |
| 2759 if (allocation_site.is_null()) { |
| 2760 allocation_site = isolate()->factory()->NewAllocationSite(); |
| 2761 } |
| 2762 |
| 2763 // Install the stub with an allocation site. |
| 2764 BinaryOpICWithAllocationSiteStub stub(state); |
| 2765 target = stub.GetCodeCopyFromTemplate(isolate(), allocation_site); |
| 2766 |
| 2767 // Sanity check the trampoline stub. |
| 2768 ASSERT_EQ(*allocation_site, target->FindFirstAllocationSite()); |
| 2769 } else { |
| 2770 // Install the generic stub. |
| 2771 BinaryOpICStub stub(state); |
| 2772 target = stub.GetCode(isolate()); |
| 2773 |
| 2774 // Sanity check the generic stub. |
| 2775 ASSERT_EQ(NULL, target->FindFirstAllocationSite()); |
| 2776 } |
| 2777 set_target(*target); |
2743 | 2778 |
2744 if (FLAG_trace_ic) { | 2779 if (FLAG_trace_ic) { |
2745 char buffer[150]; | 2780 char buffer[150]; |
2746 NoAllocationStringAllocator allocator( | 2781 NoAllocationStringAllocator allocator( |
2747 buffer, static_cast<unsigned>(sizeof(buffer))); | 2782 buffer, static_cast<unsigned>(sizeof(buffer))); |
2748 StringStream stream(&allocator); | 2783 StringStream stream(&allocator); |
2749 stream.Add("[BinaryOpIC"); | 2784 stream.Add("[BinaryOpIC"); |
2750 old_state.Print(&stream); | 2785 old_state.Print(&stream); |
2751 stream.Add(" => "); | 2786 stream.Add(" => "); |
2752 state.Print(&stream); | 2787 state.Print(&stream); |
2753 stream.Add(" @ %p <- ", static_cast<void*>(*target())); | 2788 stream.Add(" @ %p <- ", static_cast<void*>(*target)); |
2754 stream.OutputToStdOut(); | 2789 stream.OutputToStdOut(); |
2755 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2790 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
| 2791 if (!allocation_site.is_null()) { |
| 2792 PrintF(" using allocation site %p", static_cast<void*>(*allocation_site)); |
| 2793 } |
2756 PrintF("]\n"); | 2794 PrintF("]\n"); |
2757 } | 2795 } |
2758 | 2796 |
2759 // Patch the inlined smi code as necessary. | 2797 // Patch the inlined smi code as necessary. |
2760 if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) { | 2798 if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) { |
2761 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); | 2799 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); |
2762 } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) { | 2800 } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) { |
2763 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK); | 2801 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK); |
2764 } | 2802 } |
2765 | 2803 |
2766 return *result; | 2804 return *result; |
2767 } | 2805 } |
2768 | 2806 |
2769 | 2807 |
2770 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) { | 2808 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) { |
2771 HandleScope scope(isolate); | 2809 HandleScope scope(isolate); |
| 2810 ASSERT_EQ(2, args.length()); |
2772 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft); | 2811 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft); |
2773 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight); | 2812 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight); |
2774 BinaryOpIC ic(isolate); | 2813 BinaryOpIC ic(isolate); |
2775 return ic.Transition(left, right); | 2814 return ic.Transition(Handle<AllocationSite>::null(), left, right); |
2776 } | 2815 } |
2777 | 2816 |
2778 | 2817 |
| 2818 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite) { |
| 2819 HandleScope scope(isolate); |
| 2820 ASSERT_EQ(3, args.length()); |
| 2821 Handle<AllocationSite> allocation_site = args.at<AllocationSite>( |
| 2822 BinaryOpWithAllocationSiteStub::kAllocationSite); |
| 2823 Handle<Object> left = args.at<Object>( |
| 2824 BinaryOpWithAllocationSiteStub::kLeft); |
| 2825 Handle<Object> right = args.at<Object>( |
| 2826 BinaryOpWithAllocationSiteStub::kRight); |
| 2827 BinaryOpIC ic(isolate); |
| 2828 return ic.Transition(allocation_site, left, right); |
| 2829 } |
| 2830 |
| 2831 |
2779 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { | 2832 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { |
2780 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2833 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
2781 Code* code = NULL; | 2834 Code* code = NULL; |
2782 CHECK(stub.FindCodeInCache(&code, isolate)); | 2835 CHECK(stub.FindCodeInCache(&code, isolate)); |
2783 return code; | 2836 return code; |
2784 } | 2837 } |
2785 | 2838 |
2786 | 2839 |
2787 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { | 2840 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { |
2788 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2841 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3139 #undef ADDR | 3192 #undef ADDR |
3140 }; | 3193 }; |
3141 | 3194 |
3142 | 3195 |
3143 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3196 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3144 return IC_utilities[id]; | 3197 return IC_utilities[id]; |
3145 } | 3198 } |
3146 | 3199 |
3147 | 3200 |
3148 } } // namespace v8::internal | 3201 } } // namespace v8::internal |
OLD | NEW |