Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 50025f5210fcb3247217abbecb1403cfbb4cb04f..b11a4e981d24848d920075abf30effa9c8a6601f 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -696,7 +696,9 @@ HGraph::HGraph(CompilationInfo* info) |
phi_list_(NULL), |
info_(info), |
zone_(info->zone()), |
- is_recursive_(false) { |
+ is_recursive_(false), |
+ use_optimistic_licm_(false), |
+ type_change_checksum_(0) { |
start_environment_ = |
new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); |
start_environment_->set_ast_id(BailoutId::FunctionEntry()); |
@@ -1899,6 +1901,8 @@ GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) |
void HGlobalValueNumberer::LoopInvariantCodeMotion() { |
+ TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n", |
+ graph_->use_optimistic_licm() ? "yes" : "no"); |
for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { |
HBasicBlock* block = graph_->blocks()->at(i); |
if (block->IsLoopHeader()) { |
@@ -1942,6 +1946,9 @@ void HGlobalValueNumberer::ProcessLoopBlock( |
*GetGVNFlagsString(instr->gvn_flags()), |
*GetGVNFlagsString(loop_kills)); |
bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); |
+ if (can_hoist && !graph()->use_optimistic_licm()) { |
+ can_hoist = block->IsLoopSuccessorDominator(); |
+ } |
if (instr->IsTransitionElementsKind()) { |
// It's possible to hoist transitions out of a loop as long as the |
// hoisting wouldn't move the transition past an instruction that has a |
@@ -3086,6 +3093,21 @@ HGraph* HGraphBuilder::CreateGraph() { |
current_block()->FinishExit(instr); |
set_current_block(NULL); |
} |
+ |
+ // If the checksum of the number of type info changes is the same as the |
+ // last time this function was compiled, then this recompile is likely not |
+ // due to missing/inadequate type feedback, but rather too aggressive |
+ // optimization. Disable optimistic LICM in that case. |
+ Handle<Code> unoptimized_code(info()->shared_info()->code()); |
+ ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
+ Handle<Object> maybe_type_info(unoptimized_code->type_feedback_info()); |
+ Handle<TypeFeedbackInfo> type_info( |
+ Handle<TypeFeedbackInfo>::cast(maybe_type_info)); |
+ int checksum = type_info->own_type_change_checksum(); |
+ int composite_checksum = graph()->update_type_change_checksum(checksum); |
+ graph()->set_use_optimistic_licm( |
+ !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
+ type_info->set_inlined_type_change_checksum(composite_checksum); |
} |
return graph(); |
@@ -6821,8 +6843,9 @@ bool HGraphBuilder::TryInline(CallKind call_kind, |
// Save the pending call context and type feedback oracle. Set up new ones |
// for the inlined function. |
ASSERT(target_shared->has_deoptimization_support()); |
+ Handle<Code> unoptimized_code(target_shared->code()); |
TypeFeedbackOracle target_oracle( |
- Handle<Code>(target_shared->code()), |
+ unoptimized_code, |
Handle<Context>(target->context()->native_context()), |
isolate(), |
zone()); |
@@ -6902,6 +6925,12 @@ bool HGraphBuilder::TryInline(CallKind call_kind, |
// Update inlined nodes count. |
inlined_count_ += nodes_added; |
+ ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
+ Handle<Object> maybe_type_info(unoptimized_code->type_feedback_info()); |
+ Handle<TypeFeedbackInfo> type_info( |
+ Handle<TypeFeedbackInfo>::cast(maybe_type_info)); |
+ graph()->update_type_change_checksum(type_info->own_type_change_checksum()); |
+ |
TraceInline(target, caller, NULL); |
if (current_block() != NULL) { |