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

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

Powered by Google App Engine
This is Rietveld 408576698