| 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 |