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