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

Side by Side Diff: src/hydrogen.cc

Issue 10867033: Disable speculative LICM when it may lead to unnecessary deopts (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: feedback addressed Created 8 years, 4 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/ic.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 678 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 689
690 HGraph::HGraph(CompilationInfo* info) 690 HGraph::HGraph(CompilationInfo* info)
691 : isolate_(info->isolate()), 691 : isolate_(info->isolate()),
692 next_block_id_(0), 692 next_block_id_(0),
693 entry_block_(NULL), 693 entry_block_(NULL),
694 blocks_(8, info->zone()), 694 blocks_(8, info->zone()),
695 values_(16, info->zone()), 695 values_(16, info->zone()),
696 phi_list_(NULL), 696 phi_list_(NULL),
697 info_(info), 697 info_(info),
698 zone_(info->zone()), 698 zone_(info->zone()),
699 is_recursive_(false) { 699 is_recursive_(false),
700 use_optimistic_licm_(false),
701 type_change_checksum_(0) {
700 start_environment_ = 702 start_environment_ =
701 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); 703 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
702 start_environment_->set_ast_id(BailoutId::FunctionEntry()); 704 start_environment_->set_ast_id(BailoutId::FunctionEntry());
703 entry_block_ = CreateBasicBlock(); 705 entry_block_ = CreateBasicBlock();
704 entry_block_->SetInitialEnvironment(start_environment_); 706 entry_block_->SetInitialEnvironment(start_environment_);
705 } 707 }
706 708
707 709
708 HBasicBlock* HGraph::CreateBasicBlock() { 710 HBasicBlock* HGraph::CreateBasicBlock() {
709 HBasicBlock* result = new(zone()) HBasicBlock(this); 711 HBasicBlock* result = new(zone()) HBasicBlock(this);
(...skipping 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after
1892 #endif 1894 #endif
1893 size_t string_len = strlen(underlying_buffer) + 1; 1895 size_t string_len = strlen(underlying_buffer) + 1;
1894 ASSERT(string_len <= sizeof(underlying_buffer)); 1896 ASSERT(string_len <= sizeof(underlying_buffer));
1895 char* result = new char[strlen(underlying_buffer) + 1]; 1897 char* result = new char[strlen(underlying_buffer) + 1];
1896 memcpy(result, underlying_buffer, string_len); 1898 memcpy(result, underlying_buffer, string_len);
1897 return SmartArrayPointer<char>(result); 1899 return SmartArrayPointer<char>(result);
1898 } 1900 }
1899 1901
1900 1902
1901 void HGlobalValueNumberer::LoopInvariantCodeMotion() { 1903 void HGlobalValueNumberer::LoopInvariantCodeMotion() {
1904 TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n",
1905 graph_->use_optimistic_licm() ? "yes" : "no");
1902 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1906 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1903 HBasicBlock* block = graph_->blocks()->at(i); 1907 HBasicBlock* block = graph_->blocks()->at(i);
1904 if (block->IsLoopHeader()) { 1908 if (block->IsLoopHeader()) {
1905 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; 1909 GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
1906 TRACE_GVN_2("Try loop invariant motion for block B%d %s\n", 1910 TRACE_GVN_2("Try loop invariant motion for block B%d %s\n",
1907 block->block_id(), 1911 block->block_id(),
1908 *GetGVNFlagsString(side_effects)); 1912 *GetGVNFlagsString(side_effects));
1909 1913
1910 GVNFlagSet accumulated_first_time_depends; 1914 GVNFlagSet accumulated_first_time_depends;
1911 GVNFlagSet accumulated_first_time_changes; 1915 GVNFlagSet accumulated_first_time_changes;
(...skipping 23 matching lines...) Expand all
1935 while (instr != NULL) { 1939 while (instr != NULL) {
1936 HInstruction* next = instr->next(); 1940 HInstruction* next = instr->next();
1937 bool hoisted = false; 1941 bool hoisted = false;
1938 if (instr->CheckFlag(HValue::kUseGVN)) { 1942 if (instr->CheckFlag(HValue::kUseGVN)) {
1939 TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n", 1943 TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n",
1940 instr->id(), 1944 instr->id(),
1941 instr->Mnemonic(), 1945 instr->Mnemonic(),
1942 *GetGVNFlagsString(instr->gvn_flags()), 1946 *GetGVNFlagsString(instr->gvn_flags()),
1943 *GetGVNFlagsString(loop_kills)); 1947 *GetGVNFlagsString(loop_kills));
1944 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); 1948 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags);
1949 if (can_hoist && !graph()->use_optimistic_licm()) {
1950 can_hoist = block->IsLoopSuccessorDominator();
1951 }
1945 if (instr->IsTransitionElementsKind()) { 1952 if (instr->IsTransitionElementsKind()) {
1946 // It's possible to hoist transitions out of a loop as long as the 1953 // It's possible to hoist transitions out of a loop as long as the
1947 // hoisting wouldn't move the transition past an instruction that has a 1954 // hoisting wouldn't move the transition past an instruction that has a
1948 // DependsOn flag for anything it changes. 1955 // DependsOn flag for anything it changes.
1949 GVNFlagSet hoist_depends_blockers = 1956 GVNFlagSet hoist_depends_blockers =
1950 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags()); 1957 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags());
1951 1958
1952 // In addition, the transition must not be hoisted above elements kind 1959 // In addition, the transition must not be hoisted above elements kind
1953 // changes, or if the transition is destructive to the elements buffer, 1960 // changes, or if the transition is destructive to the elements buffer,
1954 // changes to array pointer or array contents. 1961 // changes to array pointer or array contents.
(...skipping 1124 matching lines...) Expand 10 before | Expand all | Expand 10 after
3079 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); 3086 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
3080 3087
3081 VisitStatements(info()->function()->body()); 3088 VisitStatements(info()->function()->body());
3082 if (HasStackOverflow()) return NULL; 3089 if (HasStackOverflow()) return NULL;
3083 3090
3084 if (current_block() != NULL) { 3091 if (current_block() != NULL) {
3085 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); 3092 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined());
3086 current_block()->FinishExit(instr); 3093 current_block()->FinishExit(instr);
3087 set_current_block(NULL); 3094 set_current_block(NULL);
3088 } 3095 }
3096
3097 // If the checksum of the number of type info changes is the same as the
3098 // last time this function was compiled, then this recompile is likely not
3099 // due to missing/inadequate type feedback, but rather too aggressive
3100 // optimization. Disable optimistic LICM in that case.
3101 Handle<Code> unoptimized_code(info()->shared_info()->code());
3102 ASSERT(unoptimized_code->kind() == Code::FUNCTION);
3103 Handle<Object> maybe_type_info(unoptimized_code->type_feedback_info());
3104 Handle<TypeFeedbackInfo> type_info(
3105 Handle<TypeFeedbackInfo>::cast(maybe_type_info));
3106 int checksum = type_info->own_type_change_checksum();
3107 int composite_checksum = graph()->update_type_change_checksum(checksum);
3108 graph()->set_use_optimistic_licm(
3109 !type_info->matches_inlined_type_change_checksum(composite_checksum));
3110 type_info->set_inlined_type_change_checksum(composite_checksum);
3089 } 3111 }
3090 3112
3091 return graph(); 3113 return graph();
3092 } 3114 }
3093 3115
3094 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { 3116 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
3095 *bailout_reason = SmartArrayPointer<char>(); 3117 *bailout_reason = SmartArrayPointer<char>();
3096 OrderBlocks(); 3118 OrderBlocks();
3097 AssignDominators(); 3119 AssignDominators();
3098 3120
(...skipping 3715 matching lines...) Expand 10 before | Expand all | Expand 10 after
6814 target_shared); 6836 target_shared);
6815 } 6837 }
6816 6838
6817 // ---------------------------------------------------------------- 6839 // ----------------------------------------------------------------
6818 // After this point, we've made a decision to inline this function (so 6840 // After this point, we've made a decision to inline this function (so
6819 // TryInline should always return true). 6841 // TryInline should always return true).
6820 6842
6821 // Save the pending call context and type feedback oracle. Set up new ones 6843 // Save the pending call context and type feedback oracle. Set up new ones
6822 // for the inlined function. 6844 // for the inlined function.
6823 ASSERT(target_shared->has_deoptimization_support()); 6845 ASSERT(target_shared->has_deoptimization_support());
6846 Handle<Code> unoptimized_code(target_shared->code());
6824 TypeFeedbackOracle target_oracle( 6847 TypeFeedbackOracle target_oracle(
6825 Handle<Code>(target_shared->code()), 6848 unoptimized_code,
6826 Handle<Context>(target->context()->native_context()), 6849 Handle<Context>(target->context()->native_context()),
6827 isolate(), 6850 isolate(),
6828 zone()); 6851 zone());
6829 // The function state is new-allocated because we need to delete it 6852 // The function state is new-allocated because we need to delete it
6830 // in two different places. 6853 // in two different places.
6831 FunctionState* target_state = new FunctionState( 6854 FunctionState* target_state = new FunctionState(
6832 this, &target_info, &target_oracle, inlining_kind); 6855 this, &target_info, &target_oracle, inlining_kind);
6833 6856
6834 HConstant* undefined = graph()->GetConstantUndefined(); 6857 HConstant* undefined = graph()->GetConstantUndefined();
6835 HEnvironment* inner_env = 6858 HEnvironment* inner_env =
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
6895 TraceInline(target, caller, "inline graph construction failed"); 6918 TraceInline(target, caller, "inline graph construction failed");
6896 target_shared->DisableOptimization(); 6919 target_shared->DisableOptimization();
6897 inline_bailout_ = true; 6920 inline_bailout_ = true;
6898 delete target_state; 6921 delete target_state;
6899 return true; 6922 return true;
6900 } 6923 }
6901 6924
6902 // Update inlined nodes count. 6925 // Update inlined nodes count.
6903 inlined_count_ += nodes_added; 6926 inlined_count_ += nodes_added;
6904 6927
6928 ASSERT(unoptimized_code->kind() == Code::FUNCTION);
6929 Handle<Object> maybe_type_info(unoptimized_code->type_feedback_info());
6930 Handle<TypeFeedbackInfo> type_info(
6931 Handle<TypeFeedbackInfo>::cast(maybe_type_info));
6932 graph()->update_type_change_checksum(type_info->own_type_change_checksum());
6933
6905 TraceInline(target, caller, NULL); 6934 TraceInline(target, caller, NULL);
6906 6935
6907 if (current_block() != NULL) { 6936 if (current_block() != NULL) {
6908 FunctionState* state = function_state(); 6937 FunctionState* state = function_state();
6909 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { 6938 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
6910 // Falling off the end of an inlined construct call. In a test context the 6939 // Falling off the end of an inlined construct call. In a test context the
6911 // return value will always evaluate to true, in a value context the 6940 // return value will always evaluate to true, in a value context the
6912 // return value is the newly allocated receiver. 6941 // return value is the newly allocated receiver.
6913 if (call_context()->IsTest()) { 6942 if (call_context()->IsTest()) {
6914 current_block()->Goto(inlined_test_context()->if_true(), state); 6943 current_block()->Goto(inlined_test_context()->if_true(), state);
(...skipping 2782 matching lines...) Expand 10 before | Expand all | Expand 10 after
9697 } 9726 }
9698 } 9727 }
9699 9728
9700 #ifdef DEBUG 9729 #ifdef DEBUG
9701 if (graph_ != NULL) graph_->Verify(false); // No full verify. 9730 if (graph_ != NULL) graph_->Verify(false); // No full verify.
9702 if (allocator_ != NULL) allocator_->Verify(); 9731 if (allocator_ != NULL) allocator_->Verify();
9703 #endif 9732 #endif
9704 } 9733 }
9705 9734
9706 } } // namespace v8::internal 9735 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/ic.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698