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

Side by Side Diff: src/hydrogen.cc

Issue 10357005: Rollback of r11482 in trunk branch. (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 8 years, 7 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/hydrogen.h ('k') | src/version.cc » ('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 5644 matching lines...) Expand 10 before | Expand all | Expand 10 after
5655 AddInstruction(HCheckMaps::NewWithTransitions(receiver, receiver_map)); 5655 AddInstruction(HCheckMaps::NewWithTransitions(receiver, receiver_map));
5656 } 5656 }
5657 if (!expr->holder().is_null()) { 5657 if (!expr->holder().is_null()) {
5658 AddInstruction(new(zone()) HCheckPrototypeMaps( 5658 AddInstruction(new(zone()) HCheckPrototypeMaps(
5659 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), 5659 Handle<JSObject>(JSObject::cast(receiver_map->prototype())),
5660 expr->holder())); 5660 expr->holder()));
5661 } 5661 }
5662 } 5662 }
5663 5663
5664 5664
5665 class FunctionSorter {
5666 public:
5667 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { }
5668 FunctionSorter(int index, int ticks, int ast_length, int src_length)
5669 : index_(index),
5670 ticks_(ticks),
5671 ast_length_(ast_length),
5672 src_length_(src_length) { }
5673
5674 int index() const { return index_; }
5675 int ticks() const { return ticks_; }
5676 int ast_length() const { return ast_length_; }
5677 int src_length() const { return src_length_; }
5678
5679 private:
5680 int index_;
5681 int ticks_;
5682 int ast_length_;
5683 int src_length_;
5684 };
5685
5686
5687 static int CompareHotness(void const* a, void const* b) {
5688 FunctionSorter const* function1 = reinterpret_cast<FunctionSorter const*>(a);
5689 FunctionSorter const* function2 = reinterpret_cast<FunctionSorter const*>(b);
5690 int diff = function1->ticks() - function2->ticks();
5691 if (diff != 0) return -diff;
5692 diff = function1->ast_length() - function2->ast_length();
5693 if (diff != 0) return diff;
5694 return function1->src_length() - function2->src_length();
5695 }
5696
5697
5698 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, 5665 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
5699 HValue* receiver, 5666 HValue* receiver,
5700 SmallMapList* types, 5667 SmallMapList* types,
5701 Handle<String> name) { 5668 Handle<String> name) {
5702 // TODO(ager): We should recognize when the prototype chains for different 5669 // TODO(ager): We should recognize when the prototype chains for different
5703 // maps are identical. In that case we can avoid repeatedly generating the 5670 // maps are identical. In that case we can avoid repeatedly generating the
5704 // same prototype map checks. 5671 // same prototype map checks.
5705 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 5672 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
5673 int count = 0;
5706 HBasicBlock* join = NULL; 5674 HBasicBlock* join = NULL;
5707 FunctionSorter order[kMaxCallPolymorphism]; 5675 for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) {
5708 int ordered_functions = 0;
5709 for (int i = 0;
5710 i < types->length() && ordered_functions < kMaxCallPolymorphism;
5711 ++i) {
5712 Handle<Map> map = types->at(i); 5676 Handle<Map> map = types->at(i);
5713 if (expr->ComputeTarget(map, name)) { 5677 if (expr->ComputeTarget(map, name)) {
5714 order[ordered_functions++] = 5678 if (count == 0) {
5715 FunctionSorter(i, 5679 // Only needed once.
5716 expr->target()->shared()->code()->profiler_ticks(), 5680 AddInstruction(new(zone()) HCheckNonSmi(receiver));
5717 InliningAstSize(expr->target()), 5681 join = graph()->CreateBasicBlock();
5718 expr->target()->shared()->SourceSize()); 5682 }
5683 ++count;
5684 HBasicBlock* if_true = graph()->CreateBasicBlock();
5685 HBasicBlock* if_false = graph()->CreateBasicBlock();
5686 HCompareMap* compare =
5687 new(zone()) HCompareMap(receiver, map, if_true, if_false);
5688 current_block()->Finish(compare);
5689
5690 set_current_block(if_true);
5691 AddCheckConstantFunction(expr, receiver, map, false);
5692 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
5693 PrintF("Trying to inline the polymorphic call to %s\n",
5694 *name->ToCString());
5695 }
5696 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
5697 // Trying to inline will signal that we should bailout from the
5698 // entire compilation by setting stack overflow on the visitor.
5699 if (HasStackOverflow()) return;
5700 } else {
5701 HCallConstantFunction* call =
5702 new(zone()) HCallConstantFunction(expr->target(), argument_count);
5703 call->set_position(expr->position());
5704 PreProcessCall(call);
5705 AddInstruction(call);
5706 if (!ast_context()->IsEffect()) Push(call);
5707 }
5708
5709 if (current_block() != NULL) current_block()->Goto(join);
5710 set_current_block(if_false);
5719 } 5711 }
5720 } 5712 }
5721 5713
5722 qsort(reinterpret_cast<void*>(&order[0]),
5723 ordered_functions,
5724 sizeof(order[0]),
5725 &CompareHotness);
5726
5727 for (int fn = 0; fn < ordered_functions; ++fn) {
5728 int i = order[fn].index();
5729 Handle<Map> map = types->at(i);
5730 if (fn == 0) {
5731 // Only needed once.
5732 AddInstruction(new(zone()) HCheckNonSmi(receiver));
5733 join = graph()->CreateBasicBlock();
5734 }
5735 HBasicBlock* if_true = graph()->CreateBasicBlock();
5736 HBasicBlock* if_false = graph()->CreateBasicBlock();
5737 HCompareMap* compare =
5738 new(zone()) HCompareMap(receiver, map, if_true, if_false);
5739 current_block()->Finish(compare);
5740
5741 set_current_block(if_true);
5742 expr->ComputeTarget(map, name);
5743 AddCheckConstantFunction(expr, receiver, map, false);
5744 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
5745 Handle<JSFunction> caller = info()->closure();
5746 SmartArrayPointer<char> caller_name =
5747 caller->shared()->DebugName()->ToCString();
5748 PrintF("Trying to inline the polymorphic call to %s from %s\n",
5749 *name->ToCString(),
5750 *caller_name);
5751 }
5752 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
5753 // Trying to inline will signal that we should bailout from the
5754 // entire compilation by setting stack overflow on the visitor.
5755 if (HasStackOverflow()) return;
5756 } else {
5757 HCallConstantFunction* call =
5758 new(zone()) HCallConstantFunction(expr->target(), argument_count);
5759 call->set_position(expr->position());
5760 PreProcessCall(call);
5761 AddInstruction(call);
5762 if (!ast_context()->IsEffect()) Push(call);
5763 }
5764
5765 if (current_block() != NULL) current_block()->Goto(join);
5766 set_current_block(if_false);
5767 }
5768
5769 // Finish up. Unconditionally deoptimize if we've handled all the maps we 5714 // Finish up. Unconditionally deoptimize if we've handled all the maps we
5770 // know about and do not want to handle ones we've never seen. Otherwise 5715 // know about and do not want to handle ones we've never seen. Otherwise
5771 // use a generic IC. 5716 // use a generic IC.
5772 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { 5717 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5773 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); 5718 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
5774 } else { 5719 } else {
5775 HValue* context = environment()->LookupContext(); 5720 HValue* context = environment()->LookupContext();
5776 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); 5721 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
5777 call->set_position(expr->position()); 5722 call->set_position(expr->position());
5778 PreProcessCall(call); 5723 PreProcessCall(call);
5779 5724
5780 if (join != NULL) { 5725 if (join != NULL) {
5781 AddInstruction(call); 5726 AddInstruction(call);
5782 if (!ast_context()->IsEffect()) Push(call); 5727 if (!ast_context()->IsEffect()) Push(call);
(...skipping 28 matching lines...) Expand all
5811 if (reason == NULL) { 5756 if (reason == NULL) {
5812 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); 5757 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name);
5813 } else { 5758 } else {
5814 PrintF("Did not inline %s called from %s (%s).\n", 5759 PrintF("Did not inline %s called from %s (%s).\n",
5815 *target_name, *caller_name, reason); 5760 *target_name, *caller_name, reason);
5816 } 5761 }
5817 } 5762 }
5818 } 5763 }
5819 5764
5820 5765
5821 static const int kNotInlinable = 1000000000; 5766 bool HGraphBuilder::TryInline(CallKind call_kind,
5822 5767 Handle<JSFunction> target,
5823 5768 ZoneList<Expression*>* arguments,
5824 int HGraphBuilder::InliningAstSize(Handle<JSFunction> target) { 5769 HValue* receiver,
5825 if (!FLAG_use_inlining) return kNotInlinable; 5770 int ast_id,
5771 int return_id,
5772 ReturnHandlingFlag return_handling) {
5773 if (!FLAG_use_inlining) return false;
5826 5774
5827 // Precondition: call is monomorphic and we have found a target with the 5775 // Precondition: call is monomorphic and we have found a target with the
5828 // appropriate arity. 5776 // appropriate arity.
5829 Handle<JSFunction> caller = info()->closure(); 5777 Handle<JSFunction> caller = info()->closure();
5830 Handle<SharedFunctionInfo> target_shared(target->shared()); 5778 Handle<SharedFunctionInfo> target_shared(target->shared());
5831 5779
5832 // Do a quick check on source code length to avoid parsing large 5780 // Do a quick check on source code length to avoid parsing large
5833 // inlining candidates. 5781 // inlining candidates.
5834 if (target_shared->SourceSize() > 5782 if (target_shared->SourceSize() >
5835 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) { 5783 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
5836 TraceInline(target, caller, "target text too big"); 5784 TraceInline(target, caller, "target text too big");
5837 return kNotInlinable; 5785 return false;
5838 } 5786 }
5839 5787
5840 // Target must be inlineable. 5788 // Target must be inlineable.
5841 if (!target->IsInlineable()) { 5789 if (!target->IsInlineable()) {
5842 TraceInline(target, caller, "target not inlineable"); 5790 TraceInline(target, caller, "target not inlineable");
5843 return kNotInlinable; 5791 return false;
5844 } 5792 }
5845 if (target_shared->dont_inline() || target_shared->dont_optimize()) { 5793 if (target_shared->dont_inline() || target_shared->dont_optimize()) {
5846 TraceInline(target, caller, "target contains unsupported syntax [early]"); 5794 TraceInline(target, caller, "target contains unsupported syntax [early]");
5847 return kNotInlinable; 5795 return false;
5848 } 5796 }
5849 5797
5850 int nodes_added = target_shared->ast_node_count(); 5798 int nodes_added = target_shared->ast_node_count();
5851 return nodes_added;
5852 }
5853
5854
5855 bool HGraphBuilder::TryInline(CallKind call_kind,
5856 Handle<JSFunction> target,
5857 ZoneList<Expression*>* arguments,
5858 HValue* receiver,
5859 int ast_id,
5860 int return_id,
5861 ReturnHandlingFlag return_handling) {
5862 int nodes_added = InliningAstSize(target);
5863 if (nodes_added == kNotInlinable) return false;
5864
5865 Handle<JSFunction> caller = info()->closure();
5866
5867 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { 5799 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
5868 TraceInline(target, caller, "target AST is too large [early]"); 5800 TraceInline(target, caller, "target AST is too large [early]");
5869 return false; 5801 return false;
5870 } 5802 }
5871 5803
5872 Handle<SharedFunctionInfo> target_shared(target->shared());
5873
5874 #if !defined(V8_TARGET_ARCH_IA32) 5804 #if !defined(V8_TARGET_ARCH_IA32)
5875 // Target must be able to use caller's context. 5805 // Target must be able to use caller's context.
5876 CompilationInfo* outer_info = info(); 5806 CompilationInfo* outer_info = info();
5877 if (target->context() != outer_info->closure()->context() || 5807 if (target->context() != outer_info->closure()->context() ||
5878 outer_info->scope()->contains_with() || 5808 outer_info->scope()->contains_with() ||
5879 outer_info->scope()->num_heap_slots() > 0) { 5809 outer_info->scope()->num_heap_slots() > 0) {
5880 TraceInline(target, caller, "target requires context change"); 5810 TraceInline(target, caller, "target requires context change");
5881 return false; 5811 return false;
5882 } 5812 }
5883 #endif 5813 #endif
(...skipping 2976 matching lines...) Expand 10 before | Expand all | Expand 10 after
8860 } 8790 }
8861 } 8791 }
8862 8792
8863 #ifdef DEBUG 8793 #ifdef DEBUG
8864 if (graph_ != NULL) graph_->Verify(false); // No full verify. 8794 if (graph_ != NULL) graph_->Verify(false); // No full verify.
8865 if (allocator_ != NULL) allocator_->Verify(); 8795 if (allocator_ != NULL) allocator_->Verify();
8866 #endif 8796 #endif
8867 } 8797 }
8868 8798
8869 } } // namespace v8::internal 8799 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/version.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698