First steps towards better code generation for LBranch:
* AST Expression nodes get a separate testing ID to record type info in ToBooleanStub later. This is necessary to avoid clashes with other uses of already existing IDs. * In order to avoid threading the condition expression through tons of places, TestContexts carry it now with them. Note that we will probably only need the testing ID of the expression, but having the whole thing at hand makes debugging easier. Probably we will change this later... Review URL: http://codereview.chromium.org/7046073 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8274 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
906fc4cd01
commit
a4cf7be941
@ -383,7 +383,7 @@ void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
|
||||
// For simplicity we always test the accumulator register.
|
||||
codegen()->Move(result_register(), slot);
|
||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
|
||||
|
||||
@ -417,7 +417,7 @@ void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
|
||||
if (true_label_ != fall_through_) __ b(true_label_);
|
||||
} else {
|
||||
__ LoadRoot(result_register(), index);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -464,7 +464,7 @@ void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
|
||||
} else {
|
||||
// For simplicity we always test the accumulator register.
|
||||
__ mov(result_register(), Operand(lit));
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -500,7 +500,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
|
||||
__ Drop(count);
|
||||
__ Move(result_register(), reg);
|
||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
|
||||
|
||||
@ -578,7 +578,8 @@ void FullCodeGenerator::TestContext::Plug(bool flag) const {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::DoTest(Label* if_true,
|
||||
void FullCodeGenerator::DoTest(Expression* condition,
|
||||
Label* if_true,
|
||||
Label* if_false,
|
||||
Label* fall_through) {
|
||||
if (CpuFeatures::IsSupported(VFP3)) {
|
||||
|
@ -210,7 +210,7 @@ class Expression: public AstNode {
|
||||
kTest
|
||||
};
|
||||
|
||||
Expression() : id_(GetNextId()) {}
|
||||
Expression() : id_(GetNextId()), test_id_(GetNextId()) {}
|
||||
|
||||
virtual int position() const {
|
||||
UNREACHABLE();
|
||||
@ -262,9 +262,11 @@ class Expression: public AstNode {
|
||||
}
|
||||
|
||||
unsigned id() const { return id_; }
|
||||
unsigned test_id() const { return test_id_; }
|
||||
|
||||
private:
|
||||
unsigned id_;
|
||||
unsigned test_id_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -441,7 +441,7 @@ void FullCodeGenerator::TestContext::Plug(Register reg) const {
|
||||
// For simplicity we always test the accumulator register.
|
||||
__ Move(result_register(), reg);
|
||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
|
||||
|
||||
@ -463,7 +463,7 @@ void FullCodeGenerator::TestContext::PlugTOS() const {
|
||||
// For simplicity we always test the accumulator register.
|
||||
__ pop(result_register());
|
||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
|
||||
|
||||
@ -513,6 +513,14 @@ void FullCodeGenerator::TestContext::PrepareTest(
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::DoTest(const TestContext* context) {
|
||||
DoTest(context->condition(),
|
||||
context->true_label(),
|
||||
context->false_label(),
|
||||
context->fall_through());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitDeclarations(
|
||||
ZoneList<Declaration*>* declarations) {
|
||||
int length = declarations->length();
|
||||
@ -734,9 +742,9 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
|
||||
Label discard, restore;
|
||||
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
||||
if (is_logical_and) {
|
||||
DoTest(&discard, &restore, &restore);
|
||||
DoTest(left, &discard, &restore, &restore);
|
||||
} else {
|
||||
DoTest(&restore, &discard, &restore);
|
||||
DoTest(left, &restore, &discard, &restore);
|
||||
}
|
||||
__ bind(&restore);
|
||||
__ pop(result_register());
|
||||
@ -753,9 +761,9 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
|
||||
Label discard;
|
||||
PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
||||
if (is_logical_and) {
|
||||
DoTest(&discard, &done, &discard);
|
||||
DoTest(left, &discard, &done, &discard);
|
||||
} else {
|
||||
DoTest(&done, &discard, &discard);
|
||||
DoTest(left, &done, &discard, &discard);
|
||||
}
|
||||
__ bind(&discard);
|
||||
__ Drop(1);
|
||||
|
@ -113,6 +113,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
class TryFinally;
|
||||
class Finally;
|
||||
class ForIn;
|
||||
class TestContext;
|
||||
|
||||
class NestedStatement BASE_EMBEDDED {
|
||||
public:
|
||||
@ -298,7 +299,11 @@ class FullCodeGenerator: public AstVisitor {
|
||||
// Helper function to convert a pure value into a test context. The value
|
||||
// is expected on the stack or the accumulator, depending on the platform.
|
||||
// See the platform-specific implementation for details.
|
||||
void DoTest(Label* if_true, Label* if_false, Label* fall_through);
|
||||
void DoTest(Expression* condition,
|
||||
Label* if_true,
|
||||
Label* if_false,
|
||||
Label* fall_through);
|
||||
void DoTest(const TestContext* context);
|
||||
|
||||
// Helper function to split control flow and avoid a branch to the
|
||||
// fall-through label if it is set up.
|
||||
@ -347,7 +352,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
Label* if_true,
|
||||
Label* if_false,
|
||||
Label* fall_through) {
|
||||
TestContext context(this, if_true, if_false, fall_through);
|
||||
TestContext context(this, expr, if_true, if_false, fall_through);
|
||||
VisitInCurrentContext(expr);
|
||||
}
|
||||
|
||||
@ -670,11 +675,13 @@ class FullCodeGenerator: public AstVisitor {
|
||||
|
||||
class TestContext : public ExpressionContext {
|
||||
public:
|
||||
explicit TestContext(FullCodeGenerator* codegen,
|
||||
Label* true_label,
|
||||
Label* false_label,
|
||||
Label* fall_through)
|
||||
TestContext(FullCodeGenerator* codegen,
|
||||
Expression* condition,
|
||||
Label* true_label,
|
||||
Label* false_label,
|
||||
Label* fall_through)
|
||||
: ExpressionContext(codegen),
|
||||
condition_(condition),
|
||||
true_label_(true_label),
|
||||
false_label_(false_label),
|
||||
fall_through_(fall_through) { }
|
||||
@ -684,6 +691,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
return reinterpret_cast<const TestContext*>(context);
|
||||
}
|
||||
|
||||
Expression* condition() const { return condition_; }
|
||||
Label* true_label() const { return true_label_; }
|
||||
Label* false_label() const { return false_label_; }
|
||||
Label* fall_through() const { return fall_through_; }
|
||||
@ -704,6 +712,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
virtual bool IsTest() const { return true; }
|
||||
|
||||
private:
|
||||
Expression* condition_;
|
||||
Label* true_label_;
|
||||
Label* false_label_;
|
||||
Label* fall_through_;
|
||||
|
@ -2007,9 +2007,10 @@ FunctionState::FunctionState(HGraphBuilder* owner,
|
||||
HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
|
||||
if_true->MarkAsInlineReturnTarget();
|
||||
if_false->MarkAsInlineReturnTarget();
|
||||
Expression* cond = TestContext::cast(owner->ast_context())->condition();
|
||||
// The AstContext constructor pushed on the context stack. This newed
|
||||
// instance is the reason that AstContext can't be BASE_EMBEDDED.
|
||||
test_context_ = new TestContext(owner, if_true, if_false);
|
||||
test_context_ = new TestContext(owner, cond, if_true, if_false);
|
||||
} else {
|
||||
function_return_ = owner->graph()->CreateBasicBlock();
|
||||
function_return()->MarkAsInlineReturnTarget();
|
||||
@ -2179,7 +2180,7 @@ void HGraphBuilder::VisitForTypeOf(Expression* expr) {
|
||||
void HGraphBuilder::VisitForControl(Expression* expr,
|
||||
HBasicBlock* true_block,
|
||||
HBasicBlock* false_block) {
|
||||
TestContext for_test(this, true_block, false_block);
|
||||
TestContext for_test(this, expr, true_block, false_block);
|
||||
Visit(expr);
|
||||
}
|
||||
|
||||
|
@ -551,9 +551,11 @@ class ValueContext: public AstContext {
|
||||
class TestContext: public AstContext {
|
||||
public:
|
||||
TestContext(HGraphBuilder* owner,
|
||||
Expression* condition,
|
||||
HBasicBlock* if_true,
|
||||
HBasicBlock* if_false)
|
||||
: AstContext(owner, Expression::kTest),
|
||||
condition_(condition),
|
||||
if_true_(if_true),
|
||||
if_false_(if_false) {
|
||||
}
|
||||
@ -566,6 +568,7 @@ class TestContext: public AstContext {
|
||||
return reinterpret_cast<TestContext*>(context);
|
||||
}
|
||||
|
||||
Expression* condition() const { return condition_; }
|
||||
HBasicBlock* if_true() const { return if_true_; }
|
||||
HBasicBlock* if_false() const { return if_false_; }
|
||||
|
||||
@ -574,6 +577,7 @@ class TestContext: public AstContext {
|
||||
// control flow.
|
||||
void BuildBranch(HValue* value);
|
||||
|
||||
Expression* condition_;
|
||||
HBasicBlock* if_true_;
|
||||
HBasicBlock* if_false_;
|
||||
};
|
||||
|
@ -374,7 +374,7 @@ void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
|
||||
// For simplicity we always test the accumulator register.
|
||||
codegen()->Move(result_register(), slot);
|
||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
|
||||
|
||||
@ -448,7 +448,7 @@ void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
|
||||
} else {
|
||||
// For simplicity we always test the accumulator register.
|
||||
__ mov(result_register(), lit);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -484,7 +484,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
|
||||
__ Drop(count);
|
||||
__ Move(result_register(), reg);
|
||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
|
||||
|
||||
@ -561,7 +561,8 @@ void FullCodeGenerator::TestContext::Plug(bool flag) const {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::DoTest(Label* if_true,
|
||||
void FullCodeGenerator::DoTest(Expression* condition,
|
||||
Label* if_true,
|
||||
Label* if_false,
|
||||
Label* fall_through) {
|
||||
ToBooleanStub stub;
|
||||
|
@ -377,7 +377,7 @@ void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
|
||||
void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
|
||||
codegen()->Move(result_register(), slot);
|
||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
|
||||
|
||||
@ -410,7 +410,7 @@ void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
|
||||
if (true_label_ != fall_through_) __ jmp(true_label_);
|
||||
} else {
|
||||
__ LoadRoot(result_register(), index);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,7 +455,7 @@ void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
|
||||
} else {
|
||||
// For simplicity we always test the accumulator register.
|
||||
__ Move(result_register(), lit);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -491,7 +491,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
|
||||
__ Drop(count);
|
||||
__ Move(result_register(), reg);
|
||||
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
|
||||
codegen()->DoTest(true_label_, false_label_, fall_through_);
|
||||
codegen()->DoTest(this);
|
||||
}
|
||||
|
||||
|
||||
@ -566,7 +566,8 @@ void FullCodeGenerator::TestContext::Plug(bool flag) const {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::DoTest(Label* if_true,
|
||||
void FullCodeGenerator::DoTest(Expression* condition,
|
||||
Label* if_true,
|
||||
Label* if_false,
|
||||
Label* fall_through) {
|
||||
ToBooleanStub stub;
|
||||
|
Loading…
Reference in New Issue
Block a user