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:
parent
89e74000a0
commit
3d15b43393
@ -882,8 +882,8 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
|
||||
if (FLAG_stress_environments && !instr->HasEnvironment()) {
|
||||
instr = AssignEnvironment(instr);
|
||||
}
|
||||
if (current->IsBranch()) {
|
||||
instr->set_hydrogen_value(HBranch::cast(current)->value());
|
||||
if (current->IsTest()) {
|
||||
instr->set_hydrogen_value(HTest::cast(current)->value());
|
||||
} else {
|
||||
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();
|
||||
HBasicBlock* first = instr->FirstSuccessor();
|
||||
HBasicBlock* second = instr->SecondSuccessor();
|
||||
@ -1059,8 +1059,7 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMapAndBranch(
|
||||
HCompareMapAndBranch* instr) {
|
||||
LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
|
||||
ASSERT(instr->value()->representation().IsTagged());
|
||||
LOperand* value = UseRegisterAtStart(instr->value());
|
||||
LOperand* temp = TempRegister();
|
||||
|
@ -1082,17 +1082,17 @@ class LCmpMapAndBranch: public LUnaryOperation {
|
||||
: LUnaryOperation(value), temp_(temp) { }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMapAndBranch)
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMap)
|
||||
|
||||
virtual bool IsControl() const { return true; }
|
||||
|
||||
LOperand* temp() const { return temp_; }
|
||||
Handle<Map> map() const { return hydrogen()->map(); }
|
||||
int true_block_id() const {
|
||||
return hydrogen()->true_destination()->block_id();
|
||||
return hydrogen()->FirstSuccessor()->block_id();
|
||||
}
|
||||
int false_block_id() const {
|
||||
return hydrogen()->false_destination()->block_id();
|
||||
return hydrogen()->SecondSuccessor()->block_id();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -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();
|
||||
if (SecondSuccessor() == NULL) {
|
||||
stream->Add(" B%d", first_id);
|
||||
} else {
|
||||
int second_id = SecondSuccessor()->block_id();
|
||||
stream->Add("on ");
|
||||
value()->PrintNameTo(stream);
|
||||
stream->Add(" (B%d, B%d)", first_id, second_id);
|
||||
stream->Add(" goto (B%d, B%d)", first_id, second_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HCompareMapAndBranch::PrintDataTo(StringStream* stream) const {
|
||||
stream->Add("on ");
|
||||
void HUnaryControlInstruction::PrintDataTo(StringStream* stream) const {
|
||||
value()->PrintNameTo(stream);
|
||||
HControlInstruction::PrintDataTo(stream);
|
||||
}
|
||||
|
||||
|
||||
void HCompareMap::PrintDataTo(StringStream* stream) const {
|
||||
value()->PrintNameTo(stream);
|
||||
stream->Add(" (%p)", *map());
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
HControlInstruction::PrintDataTo(stream);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -99,9 +99,9 @@ class LChunkBuilder;
|
||||
// HDeoptimize
|
||||
// HGoto
|
||||
// HUnaryControlInstruction
|
||||
// HBranch
|
||||
// HCompareMapAndBranch
|
||||
// HCompareMap
|
||||
// HReturn
|
||||
// HTest
|
||||
// HThrow
|
||||
// HEnterInlined
|
||||
// HFunctionLiteral
|
||||
@ -183,7 +183,6 @@ class LChunkBuilder;
|
||||
V(BitXor) \
|
||||
V(BlockEntry) \
|
||||
V(BoundsCheck) \
|
||||
V(Branch) \
|
||||
V(CallConstantFunction) \
|
||||
V(CallFunction) \
|
||||
V(CallGlobal) \
|
||||
@ -202,7 +201,7 @@ class LChunkBuilder;
|
||||
V(CheckSmi) \
|
||||
V(Compare) \
|
||||
V(CompareJSObjectEq) \
|
||||
V(CompareMapAndBranch) \
|
||||
V(CompareMap) \
|
||||
V(Constant) \
|
||||
V(DeleteProperty) \
|
||||
V(Deoptimize) \
|
||||
@ -253,6 +252,7 @@ class LChunkBuilder;
|
||||
V(StringCharCodeAt) \
|
||||
V(StringLength) \
|
||||
V(Sub) \
|
||||
V(Test) \
|
||||
V(Throw) \
|
||||
V(Typeof) \
|
||||
V(TypeofIs) \
|
||||
@ -815,44 +815,55 @@ class HBlockEntry: public HInstruction {
|
||||
|
||||
class HControlInstruction: public HInstruction {
|
||||
public:
|
||||
virtual HBasicBlock* FirstSuccessor() const { return NULL; }
|
||||
virtual HBasicBlock* SecondSuccessor() const { return NULL; }
|
||||
HControlInstruction(HBasicBlock* first, HBasicBlock* second)
|
||||
: 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)
|
||||
|
||||
private:
|
||||
HBasicBlock* first_successor_;
|
||||
HBasicBlock* second_successor_;
|
||||
};
|
||||
|
||||
|
||||
class HDeoptimize: public HControlInstruction {
|
||||
public:
|
||||
HDeoptimize() : HControlInstruction(NULL, NULL) { }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
|
||||
};
|
||||
|
||||
|
||||
class HGoto: public HControlInstruction {
|
||||
public:
|
||||
explicit HGoto(HBasicBlock* destination)
|
||||
: destination_(destination),
|
||||
include_stack_check_(false) {}
|
||||
explicit HGoto(HBasicBlock* target)
|
||||
: HControlInstruction(target, NULL), include_stack_check_(false) {
|
||||
}
|
||||
|
||||
virtual HBasicBlock* FirstSuccessor() const { return destination_; }
|
||||
void set_include_stack_check(bool include_stack_check) {
|
||||
include_stack_check_ = include_stack_check;
|
||||
}
|
||||
bool include_stack_check() const { return include_stack_check_; }
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
|
||||
|
||||
private:
|
||||
HBasicBlock* destination_;
|
||||
bool include_stack_check_;
|
||||
};
|
||||
|
||||
|
||||
class HUnaryControlInstruction: public HControlInstruction {
|
||||
public:
|
||||
explicit HUnaryControlInstruction(HValue* value) {
|
||||
explicit HUnaryControlInstruction(HValue* value,
|
||||
HBasicBlock* true_target,
|
||||
HBasicBlock* false_target)
|
||||
: HControlInstruction(true_target, false_target) {
|
||||
SetOperandAt(0, value);
|
||||
}
|
||||
|
||||
@ -860,6 +871,8 @@ class HUnaryControlInstruction: public HControlInstruction {
|
||||
return Representation::Tagged();
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
|
||||
HValue* value() const { return OperandAt(0); }
|
||||
virtual int OperandCount() const { return 1; }
|
||||
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:
|
||||
HBranch(HBasicBlock* true_destination,
|
||||
HBasicBlock* false_destination,
|
||||
HValue* boolean_value)
|
||||
: HUnaryControlInstruction(boolean_value),
|
||||
true_destination_(true_destination),
|
||||
false_destination_(false_destination) {
|
||||
ASSERT(true_destination != NULL && false_destination != NULL);
|
||||
HTest(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target)
|
||||
: HUnaryControlInstruction(value, true_target, false_target) {
|
||||
ASSERT(true_target != NULL && false_target != NULL);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) const {
|
||||
return Representation::None();
|
||||
}
|
||||
|
||||
virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
|
||||
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_;
|
||||
DECLARE_CONCRETE_INSTRUCTION(Test, "test")
|
||||
};
|
||||
|
||||
|
||||
class HCompareMapAndBranch: public HUnaryControlInstruction {
|
||||
class HCompareMap: public HUnaryControlInstruction {
|
||||
public:
|
||||
HCompareMapAndBranch(HValue* result,
|
||||
HCompareMap(HValue* value,
|
||||
Handle<Map> map,
|
||||
HBasicBlock* true_destination,
|
||||
HBasicBlock* false_destination)
|
||||
: HUnaryControlInstruction(result),
|
||||
map_(map),
|
||||
true_destination_(true_destination),
|
||||
false_destination_(false_destination) {
|
||||
ASSERT(true_destination != NULL);
|
||||
ASSERT(false_destination != NULL);
|
||||
HBasicBlock* true_target,
|
||||
HBasicBlock* false_target)
|
||||
: HUnaryControlInstruction(value, true_target, false_target),
|
||||
map_(map) {
|
||||
ASSERT(true_target != NULL);
|
||||
ASSERT(false_target != 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;
|
||||
|
||||
Handle<Map> map() const { return map_; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch")
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMap, "compare_map")
|
||||
|
||||
private:
|
||||
Handle<Map> map_;
|
||||
HBasicBlock* true_destination_;
|
||||
HBasicBlock* false_destination_;
|
||||
};
|
||||
|
||||
|
||||
class HReturn: public HUnaryControlInstruction {
|
||||
public:
|
||||
explicit HReturn(HValue* result) : HUnaryControlInstruction(result) { }
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
explicit HReturn(HValue* value)
|
||||
: HUnaryControlInstruction(value, NULL, NULL) {
|
||||
}
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(Return, "return")
|
||||
};
|
||||
@ -950,9 +940,8 @@ class HReturn: public HUnaryControlInstruction {
|
||||
|
||||
class HThrow: public HUnaryControlInstruction {
|
||||
public:
|
||||
explicit HThrow(HValue* value) : HUnaryControlInstruction(value) { }
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) const;
|
||||
explicit HThrow(HValue* value)
|
||||
: HUnaryControlInstruction(value, NULL, NULL) { }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
|
||||
};
|
||||
|
@ -505,19 +505,15 @@ HConstant* HGraph::GetConstantFalse() {
|
||||
|
||||
void HSubgraph::AppendOptional(HSubgraph* graph,
|
||||
bool on_true_branch,
|
||||
HValue* boolean_value) {
|
||||
HValue* value) {
|
||||
ASSERT(HasExit() && graph->HasExit());
|
||||
HBasicBlock* other_block = graph_->CreateBasicBlock();
|
||||
HBasicBlock* join_block = graph_->CreateBasicBlock();
|
||||
|
||||
HBasicBlock* true_branch = other_block;
|
||||
HBasicBlock* false_branch = graph->entry_block();
|
||||
if (on_true_branch) {
|
||||
true_branch = graph->entry_block();
|
||||
false_branch = other_block;
|
||||
}
|
||||
|
||||
exit_block_->Finish(new HBranch(true_branch, false_branch, boolean_value));
|
||||
HTest* test = on_true_branch
|
||||
? new HTest(value, graph->entry_block(), other_block)
|
||||
: new HTest(value, other_block, graph->entry_block());
|
||||
exit_block_->Finish(test);
|
||||
other_block->Goto(join_block);
|
||||
graph->exit_block()->Goto(join_block);
|
||||
exit_block_ = join_block;
|
||||
@ -935,7 +931,7 @@ class HRangeAnalysis BASE_EMBEDDED {
|
||||
private:
|
||||
void TraceRange(const char* msg, ...);
|
||||
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 InferPhiRange(HPhi* phi);
|
||||
void InferRange(HValue* value);
|
||||
@ -971,8 +967,8 @@ void HRangeAnalysis::Analyze(HBasicBlock* block) {
|
||||
// Infer range based on control flow.
|
||||
if (block->predecessors()->length() == 1) {
|
||||
HBasicBlock* pred = block->predecessors()->first();
|
||||
if (pred->end()->IsBranch()) {
|
||||
InferControlFlowRange(HBranch::cast(pred->end()), block);
|
||||
if (pred->end()->IsTest()) {
|
||||
InferControlFlowRange(HTest::cast(pred->end()), block);
|
||||
}
|
||||
}
|
||||
|
||||
@ -998,14 +994,12 @@ void HRangeAnalysis::Analyze(HBasicBlock* block) {
|
||||
}
|
||||
|
||||
|
||||
void HRangeAnalysis::InferControlFlowRange(HBranch* branch, HBasicBlock* dest) {
|
||||
ASSERT(branch->FirstSuccessor() == dest || branch->SecondSuccessor() == dest);
|
||||
ASSERT(branch->FirstSuccessor() != dest || branch->SecondSuccessor() != dest);
|
||||
|
||||
if (branch->value()->IsCompare()) {
|
||||
HCompare* compare = HCompare::cast(branch->value());
|
||||
void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) {
|
||||
ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
|
||||
if (test->value()->IsCompare()) {
|
||||
HCompare* compare = HCompare::cast(test->value());
|
||||
Token::Value op = compare->token();
|
||||
if (branch->SecondSuccessor() == dest) {
|
||||
if (test->SecondSuccessor() == dest) {
|
||||
op = Token::NegateCompareOp(op);
|
||||
}
|
||||
Token::Value inverted_op = Token::InvertCompareOp(op);
|
||||
@ -2068,8 +2062,8 @@ void TestContext::BuildBranch(HValue* value) {
|
||||
HGraphBuilder* builder = owner();
|
||||
HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
|
||||
HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
|
||||
HBranch* branch = new HBranch(empty_true, empty_false, value);
|
||||
builder->CurrentBlock()->Finish(branch);
|
||||
HTest* test = new HTest(value, empty_true, empty_false);
|
||||
builder->CurrentBlock()->Finish(test);
|
||||
|
||||
HValue* const no_return_value = NULL;
|
||||
HBasicBlock* true_target = if_true();
|
||||
@ -2597,9 +2591,9 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block()));
|
||||
} else {
|
||||
HBasicBlock* empty = graph()->CreateBasicBlock();
|
||||
prev_graph->exit_block()->Finish(new HBranch(empty,
|
||||
subgraph->entry_block(),
|
||||
prev_compare_inst));
|
||||
prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
|
||||
empty,
|
||||
subgraph->entry_block()));
|
||||
}
|
||||
|
||||
// Build instructions for current subgraph.
|
||||
@ -2618,9 +2612,9 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
if (prev_graph != current_subgraph_) {
|
||||
last_false_block = graph()->CreateBasicBlock();
|
||||
HBasicBlock* empty = graph()->CreateBasicBlock();
|
||||
prev_graph->exit_block()->Finish(new HBranch(empty,
|
||||
last_false_block,
|
||||
prev_compare_inst));
|
||||
prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
|
||||
empty,
|
||||
last_false_block));
|
||||
}
|
||||
|
||||
// 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* osr_entry = graph()->CreateBasicBlock();
|
||||
HValue* true_value = graph()->GetConstantTrue();
|
||||
HBranch* branch = new HBranch(non_osr_entry, osr_entry, true_value);
|
||||
exit_block()->Finish(branch);
|
||||
HTest* test = new HTest(true_value, non_osr_entry, osr_entry);
|
||||
exit_block()->Finish(test);
|
||||
|
||||
HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
|
||||
non_osr_entry->Goto(loop_predecessor);
|
||||
@ -3106,11 +3100,11 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps,
|
||||
(i == (maps->length() - 1))
|
||||
? subgraphs->last()
|
||||
: map_compare_subgraphs.last();
|
||||
current_subgraph_->exit_block()->Finish(
|
||||
new HCompareMapAndBranch(receiver,
|
||||
HCompareMap* compare = new HCompareMap(receiver,
|
||||
maps->at(i),
|
||||
subgraphs->at(i)->entry_block(),
|
||||
else_subgraph->entry_block()));
|
||||
else_subgraph->entry_block());
|
||||
current_subgraph_->exit_block()->Finish(compare);
|
||||
map_compare_subgraphs.Add(subgraph);
|
||||
}
|
||||
|
||||
@ -3118,11 +3112,11 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps,
|
||||
AddInstruction(new HCheckNonSmi(receiver));
|
||||
HSubgraph* else_subgraph =
|
||||
(maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last();
|
||||
current_subgraph_->exit_block()->Finish(
|
||||
new HCompareMapAndBranch(receiver,
|
||||
HCompareMap* compare = new HCompareMap(receiver,
|
||||
Handle<Map>(maps->first()),
|
||||
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
|
||||
// this basic block the current basic block.
|
||||
@ -4076,9 +4070,8 @@ bool HGraphBuilder::TryInline(Call* expr) {
|
||||
// TODO(3168478): refactor to avoid this.
|
||||
HBasicBlock* empty_true = graph()->CreateBasicBlock();
|
||||
HBasicBlock* empty_false = graph()->CreateBasicBlock();
|
||||
HBranch* branch =
|
||||
new HBranch(empty_true, empty_false, return_value);
|
||||
body->exit_block()->Finish(branch);
|
||||
HTest* test = new HTest(return_value, empty_true, empty_false);
|
||||
body->exit_block()->Finish(test);
|
||||
|
||||
HValue* const no_return_value = NULL;
|
||||
empty_true->AddLeaveInlined(no_return_value, test_context->if_true());
|
||||
|
@ -920,15 +920,15 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
|
||||
if (FLAG_stress_environments && !instr->HasEnvironment()) {
|
||||
instr = AssignEnvironment(instr);
|
||||
}
|
||||
if (current->IsBranch() && !instr->IsGoto()) {
|
||||
// TODO(fschneider): Handle branch instructions uniformly like
|
||||
if (current->IsTest() && !instr->IsGoto()) {
|
||||
// TODO(fschneider): Handle test instructions uniformly like
|
||||
// other instructions. This requires us to generate the right
|
||||
// branch instruction already at the HIR level.
|
||||
ASSERT(instr->IsControl());
|
||||
HBranch* branch = HBranch::cast(current);
|
||||
instr->set_hydrogen_value(branch->value());
|
||||
HBasicBlock* first = branch->FirstSuccessor();
|
||||
HBasicBlock* second = branch->SecondSuccessor();
|
||||
HTest* test = HTest::cast(current);
|
||||
instr->set_hydrogen_value(test->value());
|
||||
HBasicBlock* first = test->FirstSuccessor();
|
||||
HBasicBlock* second = test->SecondSuccessor();
|
||||
ASSERT(first != NULL && second != NULL);
|
||||
instr->SetBranchTargets(first->block_id(), second->block_id());
|
||||
} else {
|
||||
@ -985,7 +985,7 @@ LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
|
||||
LInstruction* LChunkBuilder::DoTest(HTest* instr) {
|
||||
HValue* v = instr->value();
|
||||
if (v->EmitAtUses()) {
|
||||
if (v->IsClassOfTest()) {
|
||||
@ -1087,8 +1087,7 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMapAndBranch(
|
||||
HCompareMapAndBranch* instr) {
|
||||
LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
|
||||
ASSERT(instr->value()->representation().IsTagged());
|
||||
LOperand* value = UseRegisterAtStart(instr->value());
|
||||
return new LCmpMapAndBranch(value);
|
||||
|
@ -1049,16 +1049,16 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1> {
|
||||
}
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMapAndBranch)
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMap)
|
||||
|
||||
virtual bool IsControl() const { return true; }
|
||||
|
||||
Handle<Map> map() const { return hydrogen()->map(); }
|
||||
int true_block_id() const {
|
||||
return hydrogen()->true_destination()->block_id();
|
||||
return hydrogen()->FirstSuccessor()->block_id();
|
||||
}
|
||||
int false_block_id() const {
|
||||
return hydrogen()->false_destination()->block_id();
|
||||
return hydrogen()->SecondSuccessor()->block_id();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -847,15 +847,15 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
|
||||
if (FLAG_stress_environments && !instr->HasEnvironment()) {
|
||||
instr = AssignEnvironment(instr);
|
||||
}
|
||||
if (current->IsBranch() && !instr->IsGoto()) {
|
||||
// TODO(fschneider): Handle branch instructions uniformly like
|
||||
if (current->IsTest() && !instr->IsGoto()) {
|
||||
// TODO(fschneider): Handle test instructions uniformly like
|
||||
// other instructions. This requires us to generate the right
|
||||
// branch instruction already at the HIR level.
|
||||
ASSERT(instr->IsControl());
|
||||
HBranch* branch = HBranch::cast(current);
|
||||
instr->set_hydrogen_value(branch->value());
|
||||
HBasicBlock* first = branch->FirstSuccessor();
|
||||
HBasicBlock* second = branch->SecondSuccessor();
|
||||
HTest* test = HTest::cast(current);
|
||||
instr->set_hydrogen_value(test->value());
|
||||
HBasicBlock* first = test->FirstSuccessor();
|
||||
HBasicBlock* second = test->SecondSuccessor();
|
||||
ASSERT(first != NULL && second != NULL);
|
||||
instr->SetBranchTargets(first->block_id(), second->block_id());
|
||||
} else {
|
||||
@ -912,7 +912,7 @@ LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
|
||||
LInstruction* LChunkBuilder::DoTest(HTest* instr) {
|
||||
HValue* v = instr->value();
|
||||
if (v->EmitAtUses()) {
|
||||
if (v->IsClassOfTest()) {
|
||||
@ -1013,9 +1013,8 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMapAndBranch(
|
||||
HCompareMapAndBranch* instr) {
|
||||
Abort("Unimplemented: %s", "DoCompareMapAndBranch");
|
||||
LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
|
||||
Abort("Unimplemented: %s", "DoCompareMap");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1046,16 +1046,16 @@ class LCmpMapAndBranch: public LTemplateInstruction<0, 1> {
|
||||
}
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMapAndBranch)
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMap)
|
||||
|
||||
virtual bool IsControl() const { return true; }
|
||||
|
||||
Handle<Map> map() const { return hydrogen()->map(); }
|
||||
int true_block_id() const {
|
||||
return hydrogen()->true_destination()->block_id();
|
||||
return hydrogen()->FirstSuccessor()->block_id();
|
||||
}
|
||||
int false_block_id() const {
|
||||
return hydrogen()->false_destination()->block_id();
|
||||
return hydrogen()->SecondSuccessor()->block_id();
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user