From: mvstanton@chromium.org Date: Fri, 9 Aug 2013 12:50:42 +0000 (+0000) Subject: Deoptimization is easier to diagnose when there is a text reason. X-Git-Tag: upstream/4.7.83~12984 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=201c512dc7a81363d2f2e474568c315e5f1b2ac6;p=platform%2Fupstream%2Fv8.git Deoptimization is easier to diagnose when there is a text reason. BUG= R=verwaest@chromium.org Review URL: https://codereview.chromium.org/22339018 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16131 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 13ff06e..07ca55f 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -5694,6 +5694,8 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) { if (info()->IsStub() && type == Deoptimizer::EAGER) { type = Deoptimizer::LAZY; } + + Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); DeoptimizeIf(al, instr->environment(), type); } diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index 852f7b5..9bbab9a 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -92,7 +92,7 @@ class CodeStubGraphBuilderBase : public HGraphBuilder { } ~ArrayContextChecker() { - checker_.ElseDeopt(); + checker_.ElseDeopt("Array constructor called from different context"); checker_.End(); } private: @@ -233,7 +233,7 @@ class CodeStubGraphBuilder: public CodeStubGraphBuilderBase { IfBuilder builder(this); builder.IfNot(undefined, undefined); builder.Then(); - builder.ElseDeopt(); + builder.ElseDeopt("Forced deopt to runtime"); return undefined; } @@ -387,7 +387,7 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { length)); } - checker.ElseDeopt(); + checker.ElseDeopt("Uninitialized boilerplate literals"); checker.End(); return environment()->Pop(); @@ -434,7 +434,7 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { } environment()->Push(object); - checker.ElseDeopt(); + checker.ElseDeopt("Uninitialized boilerplate in fast clone"); checker.End(); return environment()->Pop(); @@ -844,7 +844,7 @@ HValue* CodeStubGraphBuilder::BuildCodeInitializedStub() { IfBuilder builder(this); builder.If(cell_contents, value); builder.Then(); - builder.ElseDeopt(); + builder.ElseDeopt("Unexpected cell contents in constant global store"); builder.End(); } else { // Load the payload of the global parameter cell. A hole indicates that the @@ -854,7 +854,7 @@ HValue* CodeStubGraphBuilder::BuildCodeInitializedStub() { HValue* hole_value = Add(hole); builder.If(cell_contents, hole_value); builder.Then(); - builder.Deopt(); + builder.Deopt("Unexpected cell contents in global store"); builder.Else(); Add(cell, access, value); builder.End(); @@ -878,7 +878,8 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { if (FLAG_trace_elements_transitions) { // Tracing elements transitions is the job of the runtime. - Add(Deoptimizer::EAGER); + Add("Deopt due to --trace-elements-transitions", + Deoptimizer::EAGER); } else { info()->MarkAsSavesCallerDoubles(); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index a03faca..1b39f6f 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -1248,19 +1248,23 @@ class HDummyUse: public HTemplateInstruction<1> { class HDeoptimize: public HTemplateInstruction<0> { public: - DECLARE_INSTRUCTION_FACTORY_P1(HDeoptimize, Deoptimizer::BailoutType); + DECLARE_INSTRUCTION_FACTORY_P2(HDeoptimize, const char*, + Deoptimizer::BailoutType); virtual Representation RequiredInputRepresentation(int index) { return Representation::None(); } + const char* reason() const { return reason_; } Deoptimizer::BailoutType type() { return type_; } DECLARE_CONCRETE_INSTRUCTION(Deoptimize) private: - explicit HDeoptimize(Deoptimizer::BailoutType type) : type_(type) {} + explicit HDeoptimize(const char* reason, Deoptimizer::BailoutType type) + : reason_(reason), type_(type) {} + const char* reason_; Deoptimizer::BailoutType type_; }; diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 81f0ef8..f1640c4 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -824,14 +824,14 @@ void HGraphBuilder::IfBuilder::Else() { } -void HGraphBuilder::IfBuilder::Deopt() { +void HGraphBuilder::IfBuilder::Deopt(const char* reason) { ASSERT(did_then_); if (did_else_) { deopt_else_ = true; } else { deopt_then_ = true; } - builder_->Add(Deoptimizer::EAGER); + builder_->Add(reason, Deoptimizer::EAGER); } @@ -1034,9 +1034,9 @@ HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { void HGraphBuilder::FinishExitWithHardDeoptimization( - HBasicBlock* continuation) { + const char* reason, HBasicBlock* continuation) { PadEnvironmentForContinuation(current_block(), continuation); - Add(Deoptimizer::EAGER); + Add(reason, Deoptimizer::EAGER); if (no_side_effects_scope_count_ > 0) { current_block()->GotoNoSimulate(continuation); } else { @@ -1108,7 +1108,7 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, IfBuilder key_checker(this); key_checker.If(key, max_capacity, Token::LT); key_checker.Then(); - key_checker.ElseDeopt(); + key_checker.ElseDeopt("Key out of capacity range"); key_checker.End(); HValue* new_capacity = BuildNewElementsCapacity(key); @@ -1264,7 +1264,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( negative_checker.Then(); HInstruction* result = AddExternalArrayElementAccess( external_elements, key, val, bounds_check, elements_kind, is_store); - negative_checker.ElseDeopt(); + negative_checker.ElseDeopt("Negative key encountered"); length_checker.End(); return result; } else { @@ -1751,7 +1751,7 @@ void HGraphBuilder::BuildCompareNil( // emitted below is the actual monomorphic map. BuildCheckMap(value, type->Classes().Current()); } else { - if_nil.Deopt(); + if_nil.Deopt("Too many undetectable types"); } } @@ -3347,7 +3347,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { if (!clause->compare_type()->Is(Type::Smi())) { - Add(Deoptimizer::SOFT); + Add("Non-smi switch type", Deoptimizer::SOFT); } HCompareNumericAndBranch* compare_ = @@ -4736,7 +4736,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( // know about and do not want to handle ones we've never seen. Otherwise // use a generic IC. if (count == types->length() && FLAG_deoptimize_uncommon_cases) { - FinishExitWithHardDeoptimization(join); + FinishExitWithHardDeoptimization("All known maps handled", join); } else { HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); instr->set_position(position); @@ -4784,7 +4784,10 @@ void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { HValue* value = environment()->ExpressionStackAt(0); HValue* object = environment()->ExpressionStackAt(1); - if (expr->IsUninitialized()) Add(Deoptimizer::SOFT); + if (expr->IsUninitialized()) { + Add("Insufficient type feedback for property assignment", + Deoptimizer::SOFT); + } return BuildStoreNamed(expr, expr->id(), expr->position(), expr->AssignmentId(), prop, object, value, value); } else { @@ -4830,7 +4833,8 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( } builder.Then(); builder.Else(); - Add(Deoptimizer::EAGER); + Add("Constant global variable assignment", + Deoptimizer::EAGER); builder.End(); } HInstruction* instr = @@ -5271,7 +5275,8 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( Handle name, Property* expr) { if (expr->IsUninitialized()) { - Add(Deoptimizer::SOFT); + Add("Insufficient feedback for generic named load", + Deoptimizer::SOFT); } HValue* context = environment()->context(); return new(zone()) HLoadNamedGeneric(context, object, name); @@ -5588,7 +5593,8 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( // Deopt if none of the cases matched. NoObservableSideEffectsScope scope(this); - FinishExitWithHardDeoptimization(join); + FinishExitWithHardDeoptimization("Unknown type in polymorphic element access", + join); set_current_block(join); return is_store ? NULL : Pop(); } @@ -5624,12 +5630,14 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( } else { if (is_store) { if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { - Add(Deoptimizer::SOFT); + Add("Insufficient feedback for keyed store", + Deoptimizer::SOFT); } instr = BuildStoreKeyedGeneric(obj, key, val); } else { if (expr->AsProperty()->IsUninitialized()) { - Add(Deoptimizer::SOFT); + Add("Insufficient feedback for keyed load", + Deoptimizer::SOFT); } instr = BuildLoadKeyedGeneric(obj, key); } @@ -6076,7 +6084,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( // that the environment stack matches the depth on deopt that it otherwise // would have had after a successful call. Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); - FinishExitWithHardDeoptimization(join); + FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); } else { HValue* context = environment()->context(); HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); @@ -7636,12 +7644,14 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( } if (left_type->Is(Type::None())) { - Add(Deoptimizer::SOFT); + Add("Insufficient type feedback for left side", + Deoptimizer::SOFT); // TODO(rossberg): we should be able to get rid of non-continuous defaults. left_type = handle(Type::Any(), isolate()); } if (right_type->Is(Type::None())) { - Add(Deoptimizer::SOFT); + Add("Insufficient type feedback for right side", + Deoptimizer::SOFT); right_type = handle(Type::Any(), isolate()); } HInstruction* instr = NULL; @@ -7991,7 +8001,8 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { // Cases handled below depend on collected type feedback. They should // soft deoptimize when there is no type feedback. if (combined_type->Is(Type::None())) { - Add(Deoptimizer::SOFT); + Add("insufficient type feedback for combined type", + Deoptimizer::SOFT); combined_type = left_type = right_type = handle(Type::Any(), isolate()); } diff --git a/src/hydrogen.h b/src/hydrogen.h index 6312a52..d5c6040 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -1270,7 +1270,8 @@ class HGraphBuilder { void PushAndAdd(HInstruction* instr); - void FinishExitWithHardDeoptimization(HBasicBlock* continuation); + void FinishExitWithHardDeoptimization(const char* reason, + HBasicBlock* continuation); void AddIncrementCounter(StatsCounter* counter, HValue* context); @@ -1374,10 +1375,10 @@ class HGraphBuilder { void Else(); void End(); - void Deopt(); - void ElseDeopt() { + void Deopt(const char* reason); + void ElseDeopt(const char* reason) { Else(); - Deopt(); + Deopt(reason); } void Return(HValue* value); @@ -1582,13 +1583,13 @@ class HGraphBuilder { template<> inline HInstruction* HGraphBuilder::AddUncasted( - Deoptimizer::BailoutType type) { + const char* reason, Deoptimizer::BailoutType type) { if (type == Deoptimizer::SOFT) { isolate()->counters()->soft_deopts_requested()->Increment(); if (FLAG_always_opt) return NULL; } if (current_block()->IsDeoptimizing()) return NULL; - HDeoptimize* instr = New(type); + HDeoptimize* instr = New(reason, type); AddInstruction(instr); if (type == Deoptimizer::SOFT) { isolate()->counters()->soft_deopts_inserted()->Increment(); @@ -1601,8 +1602,8 @@ inline HInstruction* HGraphBuilder::AddUncasted( template<> inline HDeoptimize* HGraphBuilder::Add( - Deoptimizer::BailoutType type) { - return static_cast(AddUncasted(type)); + const char* reason, Deoptimizer::BailoutType type) { + return static_cast(AddUncasted(reason, type)); } diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 8c1175d..21466ec 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -6390,6 +6390,7 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) { if (info()->IsStub() && type == Deoptimizer::EAGER) { type = Deoptimizer::LAZY; } + Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); DeoptimizeIf(no_condition, instr->environment(), type); } diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 91be0d6..758276b 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -5708,6 +5708,8 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) { if (info()->IsStub() && type == Deoptimizer::EAGER) { type = Deoptimizer::LAZY; } + + Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); DeoptimizeIf(al, instr->environment(), type, zero_reg, Operand(zero_reg)); } diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 7234065..4fa4b66 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -5459,6 +5459,8 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) { if (info()->IsStub() && type == Deoptimizer::EAGER) { type = Deoptimizer::LAZY; } + + Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); DeoptimizeIf(no_condition, instr->environment(), type); }