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

Side by Side Diff: src/ic.cc

Issue 106453003: Allocation site support for monomorphic StringAdds in BinaryOps. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE Created 6 years, 11 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/objects.h » ('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 2380 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698