Begin changing Hydrogen branch instructions.

Rename HBranch (the instruction that coerces an arbitrary HValue to
control flow) to HTest to free up the term Branch to refer to any
control instruction with two successors.

Change the virtual FirstSuccessor and SecondSuccessor functions on
control instructions to a pair of data members.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6417 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2011-01-20 12:56:34 +00:00
parent 89e74000a0
commit 3d15b43393
9 changed files with 131 additions and 157 deletions

View File

@ -882,8 +882,8 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
if (FLAG_stress_environments && !instr->HasEnvironment()) { if (FLAG_stress_environments && !instr->HasEnvironment()) {
instr = AssignEnvironment(instr); instr = AssignEnvironment(instr);
} }
if (current->IsBranch()) { if (current->IsTest()) {
instr->set_hydrogen_value(HBranch::cast(current)->value()); instr->set_hydrogen_value(HTest::cast(current)->value());
} else { } else {
instr->set_hydrogen_value(current); instr->set_hydrogen_value(current);
} }
@ -937,7 +937,7 @@ LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
} }
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { LInstruction* LChunkBuilder::DoTest(HTest* instr) {
HValue* v = instr->value(); HValue* v = instr->value();
HBasicBlock* first = instr->FirstSuccessor(); HBasicBlock* first = instr->FirstSuccessor();
HBasicBlock* second = instr->SecondSuccessor(); HBasicBlock* second = instr->SecondSuccessor();
@ -1059,8 +1059,7 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
} }
LInstruction* LChunkBuilder::DoCompareMapAndBranch( LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
HCompareMapAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged()); ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value()); LOperand* value = UseRegisterAtStart(instr->value());
LOperand* temp = TempRegister(); LOperand* temp = TempRegister();

View File

@ -1082,17 +1082,17 @@ class LCmpMapAndBranch: public LUnaryOperation {
: LUnaryOperation(value), temp_(temp) { } : LUnaryOperation(value), temp_(temp) { }
DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch") DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
DECLARE_HYDROGEN_ACCESSOR(CompareMapAndBranch) DECLARE_HYDROGEN_ACCESSOR(CompareMap)
virtual bool IsControl() const { return true; } virtual bool IsControl() const { return true; }
LOperand* temp() const { return temp_; } LOperand* temp() const { return temp_; }
Handle<Map> map() const { return hydrogen()->map(); } Handle<Map> map() const { return hydrogen()->map(); }
int true_block_id() const { int true_block_id() const {
return hydrogen()->true_destination()->block_id(); return hydrogen()->FirstSuccessor()->block_id();
} }
int false_block_id() const { int false_block_id() const {
return hydrogen()->false_destination()->block_id(); return hydrogen()->SecondSuccessor()->block_id();
} }
private: private:

View File

@ -570,34 +570,29 @@ void HCallConstantFunction::PrintDataTo(StringStream* stream) const {
} }
void HBranch::PrintDataTo(StringStream* stream) const { void HControlInstruction::PrintDataTo(StringStream* stream) const {
if (FirstSuccessor() != NULL) {
int first_id = FirstSuccessor()->block_id(); int first_id = FirstSuccessor()->block_id();
if (SecondSuccessor() == NULL) {
stream->Add(" B%d", first_id);
} else {
int second_id = SecondSuccessor()->block_id(); int second_id = SecondSuccessor()->block_id();
stream->Add("on "); stream->Add(" goto (B%d, B%d)", first_id, second_id);
value()->PrintNameTo(stream); }
stream->Add(" (B%d, B%d)", first_id, second_id); }
} }
void HCompareMapAndBranch::PrintDataTo(StringStream* stream) const { void HUnaryControlInstruction::PrintDataTo(StringStream* stream) const {
stream->Add("on "); value()->PrintNameTo(stream);
HControlInstruction::PrintDataTo(stream);
}
void HCompareMap::PrintDataTo(StringStream* stream) const {
value()->PrintNameTo(stream); value()->PrintNameTo(stream);
stream->Add(" (%p)", *map()); stream->Add(" (%p)", *map());
} HControlInstruction::PrintDataTo(stream);
void HGoto::PrintDataTo(StringStream* stream) const {
stream->Add("B%d", FirstSuccessor()->block_id());
}
void HReturn::PrintDataTo(StringStream* stream) const {
value()->PrintNameTo(stream);
}
void HThrow::PrintDataTo(StringStream* stream) const {
value()->PrintNameTo(stream);
} }

View File

@ -1,4 +1,4 @@
// Copyright 2010 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -99,9 +99,9 @@ class LChunkBuilder;
// HDeoptimize // HDeoptimize
// HGoto // HGoto
// HUnaryControlInstruction // HUnaryControlInstruction
// HBranch // HCompareMap
// HCompareMapAndBranch
// HReturn // HReturn
// HTest
// HThrow // HThrow
// HEnterInlined // HEnterInlined
// HFunctionLiteral // HFunctionLiteral
@ -183,7 +183,6 @@ class LChunkBuilder;
V(BitXor) \ V(BitXor) \
V(BlockEntry) \ V(BlockEntry) \
V(BoundsCheck) \ V(BoundsCheck) \
V(Branch) \
V(CallConstantFunction) \ V(CallConstantFunction) \
V(CallFunction) \ V(CallFunction) \
V(CallGlobal) \ V(CallGlobal) \
@ -202,7 +201,7 @@ class LChunkBuilder;
V(CheckSmi) \ V(CheckSmi) \
V(Compare) \ V(Compare) \
V(CompareJSObjectEq) \ V(CompareJSObjectEq) \
V(CompareMapAndBranch) \ V(CompareMap) \
V(Constant) \ V(Constant) \
V(DeleteProperty) \ V(DeleteProperty) \
V(Deoptimize) \ V(Deoptimize) \
@ -253,6 +252,7 @@ class LChunkBuilder;
V(StringCharCodeAt) \ V(StringCharCodeAt) \
V(StringLength) \ V(StringLength) \
V(Sub) \ V(Sub) \
V(Test) \
V(Throw) \ V(Throw) \
V(Typeof) \ V(Typeof) \
V(TypeofIs) \ V(TypeofIs) \
@ -815,44 +815,55 @@ class HBlockEntry: public HInstruction {
class HControlInstruction: public HInstruction { class HControlInstruction: public HInstruction {
public: public:
virtual HBasicBlock* FirstSuccessor() const { return NULL; } HControlInstruction(HBasicBlock* first, HBasicBlock* second)
virtual HBasicBlock* SecondSuccessor() const { return NULL; } : first_successor_(first), second_successor_(second) {
}
HBasicBlock* FirstSuccessor() const { return first_successor_; }
HBasicBlock* SecondSuccessor() const { return second_successor_; }
virtual void PrintDataTo(StringStream* stream) const;
DECLARE_INSTRUCTION(ControlInstruction) DECLARE_INSTRUCTION(ControlInstruction)
private:
HBasicBlock* first_successor_;
HBasicBlock* second_successor_;
}; };
class HDeoptimize: public HControlInstruction { class HDeoptimize: public HControlInstruction {
public: public:
HDeoptimize() : HControlInstruction(NULL, NULL) { }
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize") DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
}; };
class HGoto: public HControlInstruction { class HGoto: public HControlInstruction {
public: public:
explicit HGoto(HBasicBlock* destination) explicit HGoto(HBasicBlock* target)
: destination_(destination), : HControlInstruction(target, NULL), include_stack_check_(false) {
include_stack_check_(false) {} }
virtual HBasicBlock* FirstSuccessor() const { return destination_; }
void set_include_stack_check(bool include_stack_check) { void set_include_stack_check(bool include_stack_check) {
include_stack_check_ = include_stack_check; include_stack_check_ = include_stack_check;
} }
bool include_stack_check() const { return include_stack_check_; } bool include_stack_check() const { return include_stack_check_; }
virtual void PrintDataTo(StringStream* stream) const;
DECLARE_CONCRETE_INSTRUCTION(Goto, "goto") DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
private: private:
HBasicBlock* destination_;
bool include_stack_check_; bool include_stack_check_;
}; };
class HUnaryControlInstruction: public HControlInstruction { class HUnaryControlInstruction: public HControlInstruction {
public: public:
explicit HUnaryControlInstruction(HValue* value) { explicit HUnaryControlInstruction(HValue* value,
HBasicBlock* true_target,
HBasicBlock* false_target)
: HControlInstruction(true_target, false_target) {
SetOperandAt(0, value); SetOperandAt(0, value);
} }
@ -860,6 +871,8 @@ class HUnaryControlInstruction: public HControlInstruction {
return Representation::Tagged(); return Representation::Tagged();
} }
virtual void PrintDataTo(StringStream* stream) const;
HValue* value() const { return OperandAt(0); } HValue* value() const { return OperandAt(0); }
virtual int OperandCount() const { return 1; } virtual int OperandCount() const { return 1; }
virtual HValue* OperandAt(int index) const { return operands_[index]; } virtual HValue* OperandAt(int index) const { return operands_[index]; }
@ -876,73 +889,50 @@ class HUnaryControlInstruction: public HControlInstruction {
}; };
class HBranch: public HUnaryControlInstruction { class HTest: public HUnaryControlInstruction {
public: public:
HBranch(HBasicBlock* true_destination, HTest(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target)
HBasicBlock* false_destination, : HUnaryControlInstruction(value, true_target, false_target) {
HValue* boolean_value) ASSERT(true_target != NULL && false_target != NULL);
: HUnaryControlInstruction(boolean_value),
true_destination_(true_destination),
false_destination_(false_destination) {
ASSERT(true_destination != NULL && false_destination != NULL);
} }
virtual Representation RequiredInputRepresentation(int index) const { virtual Representation RequiredInputRepresentation(int index) const {
return Representation::None(); return Representation::None();
} }
virtual HBasicBlock* FirstSuccessor() const { return true_destination_; } DECLARE_CONCRETE_INSTRUCTION(Test, "test")
virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
virtual void PrintDataTo(StringStream* stream) const;
DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
private:
HBasicBlock* true_destination_;
HBasicBlock* false_destination_;
}; };
class HCompareMapAndBranch: public HUnaryControlInstruction { class HCompareMap: public HUnaryControlInstruction {
public: public:
HCompareMapAndBranch(HValue* result, HCompareMap(HValue* value,
Handle<Map> map, Handle<Map> map,
HBasicBlock* true_destination, HBasicBlock* true_target,
HBasicBlock* false_destination) HBasicBlock* false_target)
: HUnaryControlInstruction(result), : HUnaryControlInstruction(value, true_target, false_target),
map_(map), map_(map) {
true_destination_(true_destination), ASSERT(true_target != NULL);
false_destination_(false_destination) { ASSERT(false_target != NULL);
ASSERT(true_destination != NULL);
ASSERT(false_destination != NULL);
ASSERT(!map.is_null()); ASSERT(!map.is_null());
} }
virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
HBasicBlock* true_destination() const { return true_destination_; }
HBasicBlock* false_destination() const { return false_destination_; }
virtual void PrintDataTo(StringStream* stream) const; 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(CompareMap, "compare_map")
private: private:
Handle<Map> map_; Handle<Map> map_;
HBasicBlock* true_destination_;
HBasicBlock* false_destination_;
}; };
class HReturn: public HUnaryControlInstruction { class HReturn: public HUnaryControlInstruction {
public: public:
explicit HReturn(HValue* result) : HUnaryControlInstruction(result) { } explicit HReturn(HValue* value)
: HUnaryControlInstruction(value, NULL, NULL) {
virtual void PrintDataTo(StringStream* stream) const; }
DECLARE_CONCRETE_INSTRUCTION(Return, "return") DECLARE_CONCRETE_INSTRUCTION(Return, "return")
}; };
@ -950,9 +940,8 @@ class HReturn: public HUnaryControlInstruction {
class HThrow: public HUnaryControlInstruction { class HThrow: public HUnaryControlInstruction {
public: public:
explicit HThrow(HValue* value) : HUnaryControlInstruction(value) { } explicit HThrow(HValue* value)
: HUnaryControlInstruction(value, NULL, NULL) { }
virtual void PrintDataTo(StringStream* stream) const;
DECLARE_CONCRETE_INSTRUCTION(Throw, "throw") DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
}; };

View File

@ -505,19 +505,15 @@ HConstant* HGraph::GetConstantFalse() {
void HSubgraph::AppendOptional(HSubgraph* graph, void HSubgraph::AppendOptional(HSubgraph* graph,
bool on_true_branch, bool on_true_branch,
HValue* boolean_value) { HValue* value) {
ASSERT(HasExit() && graph->HasExit()); ASSERT(HasExit() && graph->HasExit());
HBasicBlock* other_block = graph_->CreateBasicBlock(); HBasicBlock* other_block = graph_->CreateBasicBlock();
HBasicBlock* join_block = graph_->CreateBasicBlock(); HBasicBlock* join_block = graph_->CreateBasicBlock();
HBasicBlock* true_branch = other_block; HTest* test = on_true_branch
HBasicBlock* false_branch = graph->entry_block(); ? new HTest(value, graph->entry_block(), other_block)
if (on_true_branch) { : new HTest(value, other_block, graph->entry_block());
true_branch = graph->entry_block(); exit_block_->Finish(test);
false_branch = other_block;
}
exit_block_->Finish(new HBranch(true_branch, false_branch, boolean_value));
other_block->Goto(join_block); other_block->Goto(join_block);
graph->exit_block()->Goto(join_block); graph->exit_block()->Goto(join_block);
exit_block_ = join_block; exit_block_ = join_block;
@ -935,7 +931,7 @@ class HRangeAnalysis BASE_EMBEDDED {
private: private:
void TraceRange(const char* msg, ...); void TraceRange(const char* msg, ...);
void Analyze(HBasicBlock* block); void Analyze(HBasicBlock* block);
void InferControlFlowRange(HBranch* branch, HBasicBlock* dest); void InferControlFlowRange(HTest* test, HBasicBlock* dest);
void InferControlFlowRange(Token::Value op, HValue* value, HValue* other); void InferControlFlowRange(Token::Value op, HValue* value, HValue* other);
void InferPhiRange(HPhi* phi); void InferPhiRange(HPhi* phi);
void InferRange(HValue* value); void InferRange(HValue* value);
@ -971,8 +967,8 @@ void HRangeAnalysis::Analyze(HBasicBlock* block) {
// Infer range based on control flow. // Infer range based on control flow.
if (block->predecessors()->length() == 1) { if (block->predecessors()->length() == 1) {
HBasicBlock* pred = block->predecessors()->first(); HBasicBlock* pred = block->predecessors()->first();
if (pred->end()->IsBranch()) { if (pred->end()->IsTest()) {
InferControlFlowRange(HBranch::cast(pred->end()), block); InferControlFlowRange(HTest::cast(pred->end()), block);
} }
} }
@ -998,14 +994,12 @@ void HRangeAnalysis::Analyze(HBasicBlock* block) {
} }
void HRangeAnalysis::InferControlFlowRange(HBranch* branch, HBasicBlock* dest) { void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) {
ASSERT(branch->FirstSuccessor() == dest || branch->SecondSuccessor() == dest); ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
ASSERT(branch->FirstSuccessor() != dest || branch->SecondSuccessor() != dest); if (test->value()->IsCompare()) {
HCompare* compare = HCompare::cast(test->value());
if (branch->value()->IsCompare()) {
HCompare* compare = HCompare::cast(branch->value());
Token::Value op = compare->token(); Token::Value op = compare->token();
if (branch->SecondSuccessor() == dest) { if (test->SecondSuccessor() == dest) {
op = Token::NegateCompareOp(op); op = Token::NegateCompareOp(op);
} }
Token::Value inverted_op = Token::InvertCompareOp(op); Token::Value inverted_op = Token::InvertCompareOp(op);
@ -2068,8 +2062,8 @@ void TestContext::BuildBranch(HValue* value) {
HGraphBuilder* builder = owner(); HGraphBuilder* builder = owner();
HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
HBranch* branch = new HBranch(empty_true, empty_false, value); HTest* test = new HTest(value, empty_true, empty_false);
builder->CurrentBlock()->Finish(branch); builder->CurrentBlock()->Finish(test);
HValue* const no_return_value = NULL; HValue* const no_return_value = NULL;
HBasicBlock* true_target = if_true(); HBasicBlock* true_target = if_true();
@ -2597,9 +2591,9 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block())); prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block()));
} else { } else {
HBasicBlock* empty = graph()->CreateBasicBlock(); HBasicBlock* empty = graph()->CreateBasicBlock();
prev_graph->exit_block()->Finish(new HBranch(empty, prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
subgraph->entry_block(), empty,
prev_compare_inst)); subgraph->entry_block()));
} }
// Build instructions for current subgraph. // Build instructions for current subgraph.
@ -2618,9 +2612,9 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
if (prev_graph != current_subgraph_) { if (prev_graph != current_subgraph_) {
last_false_block = graph()->CreateBasicBlock(); last_false_block = graph()->CreateBasicBlock();
HBasicBlock* empty = graph()->CreateBasicBlock(); HBasicBlock* empty = graph()->CreateBasicBlock();
prev_graph->exit_block()->Finish(new HBranch(empty, prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
last_false_block, empty,
prev_compare_inst)); last_false_block));
} }
// If we have a non-smi compare clause, we deoptimize after trying // If we have a non-smi compare clause, we deoptimize after trying
@ -2703,8 +2697,8 @@ void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) {
HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
HBasicBlock* osr_entry = graph()->CreateBasicBlock(); HBasicBlock* osr_entry = graph()->CreateBasicBlock();
HValue* true_value = graph()->GetConstantTrue(); HValue* true_value = graph()->GetConstantTrue();
HBranch* branch = new HBranch(non_osr_entry, osr_entry, true_value); HTest* test = new HTest(true_value, non_osr_entry, osr_entry);
exit_block()->Finish(branch); exit_block()->Finish(test);
HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
non_osr_entry->Goto(loop_predecessor); non_osr_entry->Goto(loop_predecessor);
@ -3106,11 +3100,11 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps,
(i == (maps->length() - 1)) (i == (maps->length() - 1))
? subgraphs->last() ? subgraphs->last()
: map_compare_subgraphs.last(); : map_compare_subgraphs.last();
current_subgraph_->exit_block()->Finish( HCompareMap* compare = new HCompareMap(receiver,
new HCompareMapAndBranch(receiver,
maps->at(i), maps->at(i),
subgraphs->at(i)->entry_block(), subgraphs->at(i)->entry_block(),
else_subgraph->entry_block())); else_subgraph->entry_block());
current_subgraph_->exit_block()->Finish(compare);
map_compare_subgraphs.Add(subgraph); map_compare_subgraphs.Add(subgraph);
} }
@ -3118,11 +3112,11 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps,
AddInstruction(new HCheckNonSmi(receiver)); AddInstruction(new HCheckNonSmi(receiver));
HSubgraph* else_subgraph = HSubgraph* else_subgraph =
(maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last(); (maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last();
current_subgraph_->exit_block()->Finish( HCompareMap* compare = new HCompareMap(receiver,
new HCompareMapAndBranch(receiver,
Handle<Map>(maps->first()), Handle<Map>(maps->first()),
subgraphs->first()->entry_block(), subgraphs->first()->entry_block(),
else_subgraph->entry_block())); else_subgraph->entry_block());
current_subgraph_->exit_block()->Finish(compare);
// Join all the call subgraphs in a new basic block and make // Join all the call subgraphs in a new basic block and make
// this basic block the current basic block. // this basic block the current basic block.
@ -4076,9 +4070,8 @@ bool HGraphBuilder::TryInline(Call* expr) {
// TODO(3168478): refactor to avoid this. // TODO(3168478): refactor to avoid this.
HBasicBlock* empty_true = graph()->CreateBasicBlock(); HBasicBlock* empty_true = graph()->CreateBasicBlock();
HBasicBlock* empty_false = graph()->CreateBasicBlock(); HBasicBlock* empty_false = graph()->CreateBasicBlock();
HBranch* branch = HTest* test = new HTest(return_value, empty_true, empty_false);
new HBranch(empty_true, empty_false, return_value); body->exit_block()->Finish(test);
body->exit_block()->Finish(branch);
HValue* const no_return_value = NULL; HValue* const no_return_value = NULL;
empty_true->AddLeaveInlined(no_return_value, test_context->if_true()); empty_true->AddLeaveInlined(no_return_value, test_context->if_true());

View File

@ -920,15 +920,15 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
if (FLAG_stress_environments && !instr->HasEnvironment()) { if (FLAG_stress_environments && !instr->HasEnvironment()) {
instr = AssignEnvironment(instr); instr = AssignEnvironment(instr);
} }
if (current->IsBranch() && !instr->IsGoto()) { if (current->IsTest() && !instr->IsGoto()) {
// TODO(fschneider): Handle branch instructions uniformly like // TODO(fschneider): Handle test instructions uniformly like
// other instructions. This requires us to generate the right // other instructions. This requires us to generate the right
// branch instruction already at the HIR level. // branch instruction already at the HIR level.
ASSERT(instr->IsControl()); ASSERT(instr->IsControl());
HBranch* branch = HBranch::cast(current); HTest* test = HTest::cast(current);
instr->set_hydrogen_value(branch->value()); instr->set_hydrogen_value(test->value());
HBasicBlock* first = branch->FirstSuccessor(); HBasicBlock* first = test->FirstSuccessor();
HBasicBlock* second = branch->SecondSuccessor(); HBasicBlock* second = test->SecondSuccessor();
ASSERT(first != NULL && second != NULL); ASSERT(first != NULL && second != NULL);
instr->SetBranchTargets(first->block_id(), second->block_id()); instr->SetBranchTargets(first->block_id(), second->block_id());
} else { } else {
@ -985,7 +985,7 @@ LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
} }
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { LInstruction* LChunkBuilder::DoTest(HTest* instr) {
HValue* v = instr->value(); HValue* v = instr->value();
if (v->EmitAtUses()) { if (v->EmitAtUses()) {
if (v->IsClassOfTest()) { if (v->IsClassOfTest()) {
@ -1087,8 +1087,7 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
} }
LInstruction* LChunkBuilder::DoCompareMapAndBranch( LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
HCompareMapAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged()); ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value()); LOperand* value = UseRegisterAtStart(instr->value());
return new LCmpMapAndBranch(value); return new LCmpMapAndBranch(value);

View File

@ -1049,16 +1049,16 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1> {
} }
DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch") DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
DECLARE_HYDROGEN_ACCESSOR(CompareMapAndBranch) DECLARE_HYDROGEN_ACCESSOR(CompareMap)
virtual bool IsControl() const { return true; } virtual bool IsControl() const { return true; }
Handle<Map> map() const { return hydrogen()->map(); } Handle<Map> map() const { return hydrogen()->map(); }
int true_block_id() const { int true_block_id() const {
return hydrogen()->true_destination()->block_id(); return hydrogen()->FirstSuccessor()->block_id();
} }
int false_block_id() const { int false_block_id() const {
return hydrogen()->false_destination()->block_id(); return hydrogen()->SecondSuccessor()->block_id();
} }
}; };

View File

@ -847,15 +847,15 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
if (FLAG_stress_environments && !instr->HasEnvironment()) { if (FLAG_stress_environments && !instr->HasEnvironment()) {
instr = AssignEnvironment(instr); instr = AssignEnvironment(instr);
} }
if (current->IsBranch() && !instr->IsGoto()) { if (current->IsTest() && !instr->IsGoto()) {
// TODO(fschneider): Handle branch instructions uniformly like // TODO(fschneider): Handle test instructions uniformly like
// other instructions. This requires us to generate the right // other instructions. This requires us to generate the right
// branch instruction already at the HIR level. // branch instruction already at the HIR level.
ASSERT(instr->IsControl()); ASSERT(instr->IsControl());
HBranch* branch = HBranch::cast(current); HTest* test = HTest::cast(current);
instr->set_hydrogen_value(branch->value()); instr->set_hydrogen_value(test->value());
HBasicBlock* first = branch->FirstSuccessor(); HBasicBlock* first = test->FirstSuccessor();
HBasicBlock* second = branch->SecondSuccessor(); HBasicBlock* second = test->SecondSuccessor();
ASSERT(first != NULL && second != NULL); ASSERT(first != NULL && second != NULL);
instr->SetBranchTargets(first->block_id(), second->block_id()); instr->SetBranchTargets(first->block_id(), second->block_id());
} else { } else {
@ -912,7 +912,7 @@ LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
} }
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { LInstruction* LChunkBuilder::DoTest(HTest* instr) {
HValue* v = instr->value(); HValue* v = instr->value();
if (v->EmitAtUses()) { if (v->EmitAtUses()) {
if (v->IsClassOfTest()) { if (v->IsClassOfTest()) {
@ -1013,9 +1013,8 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
} }
LInstruction* LChunkBuilder::DoCompareMapAndBranch( LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
HCompareMapAndBranch* instr) { Abort("Unimplemented: %s", "DoCompareMap");
Abort("Unimplemented: %s", "DoCompareMapAndBranch");
return NULL; return NULL;
} }

View File

@ -1046,16 +1046,16 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1> {
} }
DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch") DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
DECLARE_HYDROGEN_ACCESSOR(CompareMapAndBranch) DECLARE_HYDROGEN_ACCESSOR(CompareMap)
virtual bool IsControl() const { return true; } virtual bool IsControl() const { return true; }
Handle<Map> map() const { return hydrogen()->map(); } Handle<Map> map() const { return hydrogen()->map(); }
int true_block_id() const { int true_block_id() const {
return hydrogen()->true_destination()->block_id(); return hydrogen()->FirstSuccessor()->block_id();
} }
int false_block_id() const { int false_block_id() const {
return hydrogen()->false_destination()->block_id(); return hydrogen()->SecondSuccessor()->block_id();
} }
}; };