Mark map-transition stores as map-changing instructions.

This prevents code motion from hoisting map-checks across such stores
which may result in unnecessary deoptimizations.

In the following example program we would move a map-check from the inner loop out before the outer loop which is not desirable:

function f() {
  var o = {};
  var j = 0;
  o.a = 1;
  do {
    o.b = 6;  // Map transition
    for (var i=0; i<10; i++) {
       o.a = o.b + i;
    }
  } while(++j < 1) {}
}

for (var i = 0; i < 1000000; i++) f();


Review URL: http://codereview.chromium.org/5991001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6071 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
fschneider@chromium.org 2010-12-17 13:44:19 +00:00
parent 06ac3b18a0
commit 6cc0310a72
3 changed files with 12 additions and 0 deletions

View File

@ -579,6 +579,13 @@ void HBranch::PrintDataTo(StringStream* stream) const {
} }
void HCompareMapAndBranch::PrintDataTo(StringStream* stream) const {
stream->Add("on ");
value()->PrintNameTo(stream);
stream->Add(" (%p)", *map());
}
void HGoto::PrintDataTo(StringStream* stream) const { void HGoto::PrintDataTo(StringStream* stream) const {
stream->Add("B%d", FirstSuccessor()->block_id()); stream->Add("B%d", FirstSuccessor()->block_id());
} }

View File

@ -905,6 +905,8 @@ class HCompareMapAndBranch: public HUnaryControlInstruction {
virtual HBasicBlock* FirstSuccessor() const { return true_destination_; } virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
virtual HBasicBlock* SecondSuccessor() const { return false_destination_; } virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
virtual void PrintDataTo(StringStream* stream) const;
Handle<Map> map() const { return map_; } Handle<Map> map() const { return map_; }
DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch") DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch")

View File

@ -3165,6 +3165,9 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
if (lookup->type() == MAP_TRANSITION) { if (lookup->type() == MAP_TRANSITION) {
Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
instr->set_transition(transition); instr->set_transition(transition);
// TODO(fschneider): Record the new map type of the object in the IR to
// enable elimination of redundant checks after the transition store.
instr->SetFlag(HValue::kChangesMaps);
} }
return instr; return instr;
} }