Don't emit code for instructions that are hiding behind an HSoftDeoptimize

Review URL: https://codereview.chromium.org/11377135

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13412 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f6659cfc
...@@ -682,6 +682,11 @@ LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { ...@@ -682,6 +682,11 @@ LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
} }
LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
}
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) { LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
return AssignEnvironment(new(zone()) LDeoptimize); return AssignEnvironment(new(zone()) LDeoptimize);
} }
......
...@@ -93,6 +93,7 @@ class LCodeGen; ...@@ -93,6 +93,7 @@ class LCodeGen;
V(Deoptimize) \ V(Deoptimize) \
V(DivI) \ V(DivI) \
V(DoubleToI) \ V(DoubleToI) \
V(DummyUse) \
V(ElementsKind) \ V(ElementsKind) \
V(FastLiteral) \ V(FastLiteral) \
V(FixedArrayBaseLength) \ V(FixedArrayBaseLength) \
...@@ -403,6 +404,15 @@ class LLazyBailout: public LTemplateInstruction<0, 0, 0> { ...@@ -403,6 +404,15 @@ class LLazyBailout: public LTemplateInstruction<0, 0, 0> {
}; };
class LDummyUse: public LTemplateInstruction<1, 1, 0> {
public:
explicit LDummyUse(LOperand* value) {
inputs_[0] = value;
}
DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
};
class LDeoptimize: public LTemplateInstruction<0, 0, 0> { class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
public: public:
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize") DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
......
...@@ -5912,6 +5912,11 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) { ...@@ -5912,6 +5912,11 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
} }
void LCodeGen::DoDummyUse(LDummyUse* instr) {
// Nothing to see here, move on!
}
void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
Register object = ToRegister(instr->object()); Register object = ToRegister(instr->object());
Register key = ToRegister(instr->key()); Register key = ToRegister(instr->key());
......
...@@ -737,6 +737,11 @@ void HInstruction::Verify() { ...@@ -737,6 +737,11 @@ void HInstruction::Verify() {
#endif #endif
void HDummyUse::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
}
void HUnaryCall::PrintDataTo(StringStream* stream) { void HUnaryCall::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream); value()->PrintNameTo(stream);
stream->Add(" "); stream->Add(" ");
......
...@@ -104,6 +104,7 @@ class LChunkBuilder; ...@@ -104,6 +104,7 @@ class LChunkBuilder;
V(DeleteProperty) \ V(DeleteProperty) \
V(Deoptimize) \ V(Deoptimize) \
V(Div) \ V(Div) \
V(DummyUse) \
V(ElementsKind) \ V(ElementsKind) \
V(EnterInlined) \ V(EnterInlined) \
V(FastLiteral) \ V(FastLiteral) \
...@@ -1032,6 +1033,28 @@ class HBlockEntry: public HTemplateInstruction<0> { ...@@ -1032,6 +1033,28 @@ class HBlockEntry: public HTemplateInstruction<0> {
}; };
class HDummyUse: public HTemplateInstruction<1> {
public:
explicit HDummyUse(HValue* value) {
SetOperandAt(0, value);
// Pretend to be a Smi so that the HChange instructions inserted
// before any use generate as little code as possible.
set_representation(Representation::Tagged());
set_type(HType::Smi());
}
HValue* value() { return OperandAt(0); }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::None();
}
virtual void PrintDataTo(StringStream* stream);
DECLARE_CONCRETE_INSTRUCTION(DummyUse);
};
// We insert soft-deoptimize when we hit code with unknown typefeedback, // We insert soft-deoptimize when we hit code with unknown typefeedback,
// so that we get a chance of re-optimizing with useful typefeedback. // so that we get a chance of re-optimizing with useful typefeedback.
// HSoftDeoptimize does not end a basic block as opposed to HDeoptimize. // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
......
...@@ -878,6 +878,7 @@ HGraph::HGraph(CompilationInfo* info) ...@@ -878,6 +878,7 @@ HGraph::HGraph(CompilationInfo* info)
zone_(info->zone()), zone_(info->zone()),
is_recursive_(false), is_recursive_(false),
use_optimistic_licm_(false), use_optimistic_licm_(false),
has_soft_deoptimize_(false),
type_change_checksum_(0) { type_change_checksum_(0) {
if (info->IsStub()) { if (info->IsStub()) {
start_environment_ = start_environment_ =
...@@ -1245,13 +1246,18 @@ void HGraph::AssignDominators() { ...@@ -1245,13 +1246,18 @@ void HGraph::AssignDominators() {
} }
} }
// Mark all blocks that are dominated by an unconditional soft deoptimize to // Mark all blocks that are dominated by an unconditional soft deoptimize to
// prevent code motion across those blocks. // prevent code motion across those blocks.
void HGraph::PropagateDeoptimizingMark() { void HGraph::PropagateDeoptimizingMark() {
HPhase phase("H_Propagate deoptimizing mark", this); HPhase phase("H_Propagate deoptimizing mark", this);
// Skip this phase if there is nothing to be done anyway.
if (!has_soft_deoptimize()) return;
MarkAsDeoptimizingRecursively(entry_block()); MarkAsDeoptimizingRecursively(entry_block());
NullifyUnreachableInstructions();
} }
void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) { void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
for (int i = 0; i < block->dominated_blocks()->length(); ++i) { for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
HBasicBlock* dominated = block->dominated_blocks()->at(i); HBasicBlock* dominated = block->dominated_blocks()->at(i);
...@@ -1260,6 +1266,61 @@ void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) { ...@@ -1260,6 +1266,61 @@ void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
} }
} }
void HGraph::NullifyUnreachableInstructions() {
int block_count = blocks_.length();
for (int i = 0; i < block_count; ++i) {
HBasicBlock* block = blocks_.at(i);
bool nullify = false;
const ZoneList<HBasicBlock*>* predecessors = block->predecessors();
int predecessors_length = predecessors->length();
bool all_predecessors_deoptimizing = (predecessors_length > 0);
for (int j = 0; j < predecessors_length; ++j) {
if (!predecessors->at(j)->IsDeoptimizing()) {
all_predecessors_deoptimizing = false;
break;
}
}
if (all_predecessors_deoptimizing) nullify = true;
for (HInstruction* instr = block->first(); instr != NULL;
instr = instr->next()) {
// Leave the basic structure of the graph intact.
if (instr->IsBlockEntry()) continue;
if (instr->IsControlInstruction()) continue;
if (instr->IsSimulate()) continue;
if (instr->IsEnterInlined()) continue;
if (instr->IsLeaveInlined()) continue;
if (nullify) {
HInstruction* last_dummy = NULL;
for (int j = 0; j < instr->OperandCount(); ++j) {
HValue* operand = instr->OperandAt(j);
// Insert an HDummyUse for each operand, unless the operand
// is an HDummyUse itself. If it's even from the same block,
// remember it as a potential replacement for the instruction.
if (operand->IsDummyUse()) {
if (operand->block() == instr->block() &&
last_dummy == NULL) {
last_dummy = HInstruction::cast(operand);
}
continue;
}
HDummyUse* dummy = new(zone()) HDummyUse(operand);
dummy->InsertBefore(instr);
last_dummy = dummy;
}
if (last_dummy == NULL) last_dummy = GetConstant1();
instr->DeleteAndReplaceWith(last_dummy);
continue;
}
if (instr->IsSoftDeoptimize()) {
ASSERT(block->IsDeoptimizing());
nullify = true;
}
}
}
}
void HGraph::EliminateRedundantPhis() { void HGraph::EliminateRedundantPhis() {
HPhase phase("H_Redundant phi elimination", this); HPhase phase("H_Redundant phi elimination", this);
...@@ -4006,6 +4067,15 @@ void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { ...@@ -4006,6 +4067,15 @@ void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) {
} }
void HOptimizedGraphBuilder::AddSoftDeoptimize() {
if (FLAG_always_opt) return;
if (current_block()->IsDeoptimizing()) return;
AddInstruction(new(zone()) HSoftDeoptimize());
current_block()->MarkAsDeoptimizing();
graph()->set_has_soft_deoptimize(true);
}
template <class Instruction> template <class Instruction>
HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
int count = call->argument_count(); int count = call->argument_count();
...@@ -6193,9 +6263,8 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( ...@@ -6193,9 +6263,8 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
HValue* object, HValue* object,
Handle<String> name, Handle<String> name,
Property* expr) { Property* expr) {
if (expr->IsUninitialized() && !FLAG_always_opt) { if (expr->IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize); AddSoftDeoptimize();
current_block()->MarkAsDeoptimizing();
} }
HValue* context = environment()->LookupContext(); HValue* context = environment()->LookupContext();
return new(zone()) HLoadNamedGeneric(context, object, name); return new(zone()) HLoadNamedGeneric(context, object, name);
...@@ -8090,8 +8159,7 @@ void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { ...@@ -8090,8 +8159,7 @@ void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
TypeInfo info = oracle()->UnaryType(expr); TypeInfo info = oracle()->UnaryType(expr);
Representation rep = ToRepresentation(info); Representation rep = ToRepresentation(info);
if (info.IsUninitialized()) { if (info.IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize); AddSoftDeoptimize();
current_block()->MarkAsDeoptimizing();
info = TypeInfo::Unknown(); info = TypeInfo::Unknown();
} }
HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep);
...@@ -8104,8 +8172,7 @@ void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { ...@@ -8104,8 +8172,7 @@ void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
HValue* value = Pop(); HValue* value = Pop();
TypeInfo info = oracle()->UnaryType(expr); TypeInfo info = oracle()->UnaryType(expr);
if (info.IsUninitialized()) { if (info.IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize); AddSoftDeoptimize();
current_block()->MarkAsDeoptimizing();
} }
HInstruction* instr = new(zone()) HBitNot(value); HInstruction* instr = new(zone()) HBitNot(value);
return ast_context()->ReturnInstruction(instr, expr->id()); return ast_context()->ReturnInstruction(instr, expr->id());
...@@ -8461,8 +8528,7 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( ...@@ -8461,8 +8528,7 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
if (left_info.IsUninitialized()) { if (left_info.IsUninitialized()) {
// Can't have initialized one but not the other. // Can't have initialized one but not the other.
ASSERT(right_info.IsUninitialized()); ASSERT(right_info.IsUninitialized());
AddInstruction(new(zone()) HSoftDeoptimize); AddSoftDeoptimize();
current_block()->MarkAsDeoptimizing();
left_info = right_info = TypeInfo::Unknown(); left_info = right_info = TypeInfo::Unknown();
} }
HInstruction* instr = NULL; HInstruction* instr = NULL;
...@@ -8778,8 +8844,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { ...@@ -8778,8 +8844,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
// Check if this expression was ever executed according to type feedback. // Check if this expression was ever executed according to type feedback.
// Note that for the special typeof/null/undefined cases we get unknown here. // Note that for the special typeof/null/undefined cases we get unknown here.
if (overall_type_info.IsUninitialized()) { if (overall_type_info.IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize); AddSoftDeoptimize();
current_block()->MarkAsDeoptimizing();
overall_type_info = left_type = right_type = TypeInfo::Unknown(); overall_type_info = left_type = right_type = TypeInfo::Unknown();
} }
......
...@@ -356,6 +356,14 @@ class HGraph: public ZoneObject { ...@@ -356,6 +356,14 @@ class HGraph: public ZoneObject {
use_optimistic_licm_ = value; use_optimistic_licm_ = value;
} }
bool has_soft_deoptimize() {
return has_soft_deoptimize_;
}
void set_has_soft_deoptimize(bool value) {
has_soft_deoptimize_ = value;
}
void MarkRecursive() { void MarkRecursive() {
is_recursive_ = true; is_recursive_ = true;
} }
...@@ -378,6 +386,7 @@ class HGraph: public ZoneObject { ...@@ -378,6 +386,7 @@ class HGraph: public ZoneObject {
int32_t integer_value); int32_t integer_value);
void MarkAsDeoptimizingRecursively(HBasicBlock* block); void MarkAsDeoptimizingRecursively(HBasicBlock* block);
void NullifyUnreachableInstructions();
void InsertTypeConversions(HInstruction* instr); void InsertTypeConversions(HInstruction* instr);
void PropagateMinusZeroChecks(HValue* value, BitVector* visited); void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi); void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
...@@ -415,6 +424,7 @@ class HGraph: public ZoneObject { ...@@ -415,6 +424,7 @@ class HGraph: public ZoneObject {
bool is_recursive_; bool is_recursive_;
bool use_optimistic_licm_; bool use_optimistic_licm_;
bool has_soft_deoptimize_;
int type_change_checksum_; int type_change_checksum_;
DISALLOW_COPY_AND_ASSIGN(HGraph); DISALLOW_COPY_AND_ASSIGN(HGraph);
...@@ -958,6 +968,8 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor { ...@@ -958,6 +968,8 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
bool inline_bailout() { return inline_bailout_; } bool inline_bailout() { return inline_bailout_; }
void AddSoftDeoptimize();
// Bailout environment manipulation. // Bailout environment manipulation.
void Push(HValue* value) { environment()->Push(value); } void Push(HValue* value) { environment()->Push(value); }
HValue* Pop() { return environment()->Pop(); } HValue* Pop() { return environment()->Pop(); }
......
...@@ -5775,6 +5775,11 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) { ...@@ -5775,6 +5775,11 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
} }
void LCodeGen::DoDummyUse(LDummyUse* instr) {
// Nothing to see here, move on!
}
void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
LOperand* obj = instr->object(); LOperand* obj = instr->object();
LOperand* key = instr->key(); LOperand* key = instr->key();
......
...@@ -726,6 +726,11 @@ LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { ...@@ -726,6 +726,11 @@ LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
} }
LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
}
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) { LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
return AssignEnvironment(new(zone()) LDeoptimize); return AssignEnvironment(new(zone()) LDeoptimize);
} }
......
...@@ -87,6 +87,7 @@ class LCodeGen; ...@@ -87,6 +87,7 @@ class LCodeGen;
V(Deoptimize) \ V(Deoptimize) \
V(DivI) \ V(DivI) \
V(DoubleToI) \ V(DoubleToI) \
V(DummyUse) \
V(ElementsKind) \ V(ElementsKind) \
V(FastLiteral) \ V(FastLiteral) \
V(FixedArrayBaseLength) \ V(FixedArrayBaseLength) \
...@@ -387,6 +388,15 @@ class LLazyBailout: public LTemplateInstruction<0, 0, 0> { ...@@ -387,6 +388,15 @@ class LLazyBailout: public LTemplateInstruction<0, 0, 0> {
}; };
class LDummyUse: public LTemplateInstruction<1, 1, 0> {
public:
explicit LDummyUse(LOperand* value) {
inputs_[0] = value;
}
DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
};
class LDeoptimize: public LTemplateInstruction<0, 0, 0> { class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
public: public:
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize") DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
......
...@@ -5377,6 +5377,11 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) { ...@@ -5377,6 +5377,11 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
} }
void LCodeGen::DoDummyUse(LDummyUse* instr) {
// Nothing to see here, move on!
}
void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
LOperand* obj = instr->object(); LOperand* obj = instr->object();
LOperand* key = instr->key(); LOperand* key = instr->key();
......
...@@ -690,6 +690,11 @@ LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { ...@@ -690,6 +690,11 @@ LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
} }
LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
}
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) { LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
return AssignEnvironment(new(zone()) LDeoptimize); return AssignEnvironment(new(zone()) LDeoptimize);
} }
......
...@@ -93,6 +93,7 @@ class LCodeGen; ...@@ -93,6 +93,7 @@ class LCodeGen;
V(Deoptimize) \ V(Deoptimize) \
V(DivI) \ V(DivI) \
V(DoubleToI) \ V(DoubleToI) \
V(DummyUse) \
V(ElementsKind) \ V(ElementsKind) \
V(FastLiteral) \ V(FastLiteral) \
V(FixedArrayBaseLength) \ V(FixedArrayBaseLength) \
...@@ -404,6 +405,15 @@ class LLazyBailout: public LTemplateInstruction<0, 0, 0> { ...@@ -404,6 +405,15 @@ class LLazyBailout: public LTemplateInstruction<0, 0, 0> {
}; };
class LDummyUse: public LTemplateInstruction<1, 1, 0> {
public:
explicit LDummyUse(LOperand* value) {
inputs_[0] = value;
}
DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
};
class LDeoptimize: public LTemplateInstruction<0, 0, 0> { class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
public: public:
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize") DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment