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) {
}
LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
}
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
return AssignEnvironment(new(zone()) LDeoptimize);
}
......
......@@ -93,6 +93,7 @@ class LCodeGen;
V(Deoptimize) \
V(DivI) \
V(DoubleToI) \
V(DummyUse) \
V(ElementsKind) \
V(FastLiteral) \
V(FixedArrayBaseLength) \
......@@ -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> {
public:
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
......
......@@ -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) {
Register object = ToRegister(instr->object());
Register key = ToRegister(instr->key());
......
......@@ -737,6 +737,11 @@ void HInstruction::Verify() {
#endif
void HDummyUse::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
}
void HUnaryCall::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
stream->Add(" ");
......
......@@ -104,6 +104,7 @@ class LChunkBuilder;
V(DeleteProperty) \
V(Deoptimize) \
V(Div) \
V(DummyUse) \
V(ElementsKind) \
V(EnterInlined) \
V(FastLiteral) \
......@@ -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,
// so that we get a chance of re-optimizing with useful typefeedback.
// HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
......
......@@ -878,6 +878,7 @@ HGraph::HGraph(CompilationInfo* info)
zone_(info->zone()),
is_recursive_(false),
use_optimistic_licm_(false),
has_soft_deoptimize_(false),
type_change_checksum_(0) {
if (info->IsStub()) {
start_environment_ =
......@@ -1245,13 +1246,18 @@ void HGraph::AssignDominators() {
}
}
// Mark all blocks that are dominated by an unconditional soft deoptimize to
// prevent code motion across those blocks.
void HGraph::PropagateDeoptimizingMark() {
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());
NullifyUnreachableInstructions();
}
void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
HBasicBlock* dominated = block->dominated_blocks()->at(i);
......@@ -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() {
HPhase phase("H_Redundant phi elimination", this);
......@@ -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>
HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
int count = call->argument_count();
......@@ -6193,9 +6263,8 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
HValue* object,
Handle<String> name,
Property* expr) {
if (expr->IsUninitialized() && !FLAG_always_opt) {
AddInstruction(new(zone()) HSoftDeoptimize);
current_block()->MarkAsDeoptimizing();
if (expr->IsUninitialized()) {
AddSoftDeoptimize();
}
HValue* context = environment()->LookupContext();
return new(zone()) HLoadNamedGeneric(context, object, name);
......@@ -8090,8 +8159,7 @@ void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
TypeInfo info = oracle()->UnaryType(expr);
Representation rep = ToRepresentation(info);
if (info.IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize);
current_block()->MarkAsDeoptimizing();
AddSoftDeoptimize();
info = TypeInfo::Unknown();
}
HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep);
......@@ -8104,8 +8172,7 @@ void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
HValue* value = Pop();
TypeInfo info = oracle()->UnaryType(expr);
if (info.IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize);
current_block()->MarkAsDeoptimizing();
AddSoftDeoptimize();
}
HInstruction* instr = new(zone()) HBitNot(value);
return ast_context()->ReturnInstruction(instr, expr->id());
......@@ -8461,8 +8528,7 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
if (left_info.IsUninitialized()) {
// Can't have initialized one but not the other.
ASSERT(right_info.IsUninitialized());
AddInstruction(new(zone()) HSoftDeoptimize);
current_block()->MarkAsDeoptimizing();
AddSoftDeoptimize();
left_info = right_info = TypeInfo::Unknown();
}
HInstruction* instr = NULL;
......@@ -8778,8 +8844,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
// Check if this expression was ever executed according to type feedback.
// Note that for the special typeof/null/undefined cases we get unknown here.
if (overall_type_info.IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize);
current_block()->MarkAsDeoptimizing();
AddSoftDeoptimize();
overall_type_info = left_type = right_type = TypeInfo::Unknown();
}
......
......@@ -356,6 +356,14 @@ class HGraph: public ZoneObject {
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() {
is_recursive_ = true;
}
......@@ -378,6 +386,7 @@ class HGraph: public ZoneObject {
int32_t integer_value);
void MarkAsDeoptimizingRecursively(HBasicBlock* block);
void NullifyUnreachableInstructions();
void InsertTypeConversions(HInstruction* instr);
void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
......@@ -415,6 +424,7 @@ class HGraph: public ZoneObject {
bool is_recursive_;
bool use_optimistic_licm_;
bool has_soft_deoptimize_;
int type_change_checksum_;
DISALLOW_COPY_AND_ASSIGN(HGraph);
......@@ -958,6 +968,8 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
bool inline_bailout() { return inline_bailout_; }
void AddSoftDeoptimize();
// Bailout environment manipulation.
void Push(HValue* value) { environment()->Push(value); }
HValue* Pop() { return environment()->Pop(); }
......
......@@ -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) {
LOperand* obj = instr->object();
LOperand* key = instr->key();
......
......@@ -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) {
return AssignEnvironment(new(zone()) LDeoptimize);
}
......
......@@ -87,6 +87,7 @@ class LCodeGen;
V(Deoptimize) \
V(DivI) \
V(DoubleToI) \
V(DummyUse) \
V(ElementsKind) \
V(FastLiteral) \
V(FixedArrayBaseLength) \
......@@ -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> {
public:
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
......
......@@ -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) {
LOperand* obj = instr->object();
LOperand* key = instr->key();
......
......@@ -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) {
return AssignEnvironment(new(zone()) LDeoptimize);
}
......
......@@ -93,6 +93,7 @@ class LCodeGen;
V(Deoptimize) \
V(DivI) \
V(DoubleToI) \
V(DummyUse) \
V(ElementsKind) \
V(FastLiteral) \
V(FixedArrayBaseLength) \
......@@ -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> {
public:
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