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