Rework flow graph construction.

The flow graph has been simplified to remove the special branch, join,
and exit nodes.  All nodes are now basic blocks (possibly empty to
preserve edge-split form) with a distinguished entry and exit block.

Most trivial expressions are not added to the flow graph as
instructions.  The assigned variable analyzer has been changed to
sometimes work right-to-left so that right subexpressions can be
marked as trivial.

The reaching definitions analysis has been temporarily removed, and
the analyses that depended on it (primitivity analysis, dead code
marking) as well.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4307 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 30efbb06
......@@ -749,117 +749,6 @@ bool CompareOperation::IsCritical() {
}
static inline void MarkIfNotLive(Expression* expr, List<AstNode*>* stack) {
if (!expr->is_live()) {
expr->mark_as_live();
stack->Add(expr);
}
}
// Overloaded functions for marking children of live code as live.
void VariableProxy::ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count) {
// A reference to a stack-allocated variable depends on all the
// definitions reaching it.
BitVector* defs = reaching_definitions();
if (defs != NULL) {
ASSERT(var()->IsStackAllocated());
// The first variable_count definitions are the initial parameter and
// local declarations.
for (int i = variable_count; i < defs->length(); i++) {
if (defs->Contains(i)) {
MarkIfNotLive(body_definitions->at(i - variable_count), stack);
}
}
}
}
void Literal::ProcessNonLiveChildren(List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count) {
// Leaf node, no children.
}
void Assignment::ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count) {
Property* prop = target()->AsProperty();
VariableProxy* proxy = target()->AsVariableProxy();
if (prop != NULL) {
if (!prop->key()->IsPropertyName()) MarkIfNotLive(prop->key(), stack);
MarkIfNotLive(prop->obj(), stack);
} else if (proxy == NULL) {
// Must be a reference error.
ASSERT(!target()->IsValidLeftHandSide());
MarkIfNotLive(target(), stack);
} else if (is_compound()) {
// A variable assignment so lhs is an operand to the operation.
MarkIfNotLive(target(), stack);
}
MarkIfNotLive(value(), stack);
}
void Property::ProcessNonLiveChildren(List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count) {
if (!key()->IsPropertyName()) MarkIfNotLive(key(), stack);
MarkIfNotLive(obj(), stack);
}
void Call::ProcessNonLiveChildren(List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count) {
ZoneList<Expression*>* args = arguments();
for (int i = args->length() - 1; i >= 0; i--) {
MarkIfNotLive(args->at(i), stack);
}
MarkIfNotLive(expression(), stack);
}
void UnaryOperation::ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count) {
MarkIfNotLive(expression(), stack);
}
void CountOperation::ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count) {
MarkIfNotLive(expression(), stack);
}
void BinaryOperation::ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count) {
MarkIfNotLive(right(), stack);
MarkIfNotLive(left(), stack);
}
void CompareOperation::ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count) {
MarkIfNotLive(right(), stack);
MarkIfNotLive(left(), stack);
}
// Implementation of a copy visitor. The visitor create a deep copy
// of ast nodes. Nodes that do not require a deep copy are copied
// with the default copy constructor.
......
......@@ -294,19 +294,6 @@ class Expression: public AstNode {
bitfields_ |= NumBitOpsField::encode(num_bit_ops);
}
// Functions used for dead-code elimination. Predicate is true if the
// expression is not dead code.
int is_live() const { return LiveField::decode(bitfields_); }
void mark_as_live() { bitfields_ |= LiveField::encode(true); }
// Mark non-live children as live and push them on a stack for further
// processing.
virtual void ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count) {
}
private:
static const int kMaxNumBitOps = (1 << 5) - 1;
......@@ -319,7 +306,6 @@ class Expression: public AstNode {
class ToInt32Field : public BitField<bool, 2, 1> {};
class NumBitOpsField : public BitField<int, 3, 5> {};
class LoopConditionField: public BitField<bool, 8, 1> {};
class LiveField: public BitField<bool, 9, 1> {};
};
......@@ -907,10 +893,6 @@ class Literal: public Expression {
virtual bool IsTrivial() { return true; }
virtual bool IsPrimitive();
virtual bool IsCritical();
virtual void ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count);
// Identity testers.
bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); }
......@@ -1118,10 +1100,6 @@ class VariableProxy: public Expression {
virtual bool IsPrimitive();
virtual bool IsCritical();
virtual void ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count);
void SetIsPrimitive(bool value) { is_primitive_ = value; }
......@@ -1260,10 +1238,6 @@ class Property: public Expression {
virtual bool IsPrimitive();
virtual bool IsCritical();
virtual void ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count);
Expression* obj() const { return obj_; }
Expression* key() const { return key_; }
......@@ -1299,10 +1273,6 @@ class Call: public Expression {
virtual bool IsPrimitive();
virtual bool IsCritical();
virtual void ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count);
Expression* expression() const { return expression_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
......@@ -1382,10 +1352,6 @@ class UnaryOperation: public Expression {
virtual bool IsPrimitive();
virtual bool IsCritical();
virtual void ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count);
Token::Value op() const { return op_; }
Expression* expression() const { return expression_; }
......@@ -1412,10 +1378,6 @@ class BinaryOperation: public Expression {
virtual bool IsPrimitive();
virtual bool IsCritical();
virtual void ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count);
// True iff the result can be safely overwritten (to avoid allocation).
// False for operations that can return one of their operands.
......@@ -1473,10 +1435,6 @@ class CountOperation: public Expression {
virtual bool IsPrimitive();
virtual bool IsCritical();
virtual void ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count);
bool is_prefix() const { return is_prefix_; }
bool is_postfix() const { return !is_prefix_; }
......@@ -1510,10 +1468,6 @@ class CompareOperation: public Expression {
virtual bool IsPrimitive();
virtual bool IsCritical();
virtual void ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count);
Token::Value op() const { return op_; }
Expression* left() const { return left_; }
......@@ -1568,10 +1522,6 @@ class Assignment: public Expression {
virtual bool IsPrimitive();
virtual bool IsCritical();
virtual void ProcessNonLiveChildren(
List<AstNode*>* stack,
ZoneList<Expression*>* body_definitions,
int variable_count);
Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; }
......
......@@ -90,33 +90,13 @@ static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
}
if (FLAG_use_flow_graph) {
int variable_count =
function->num_parameters() + function->scope()->num_stack_slots();
FlowGraphBuilder builder(variable_count);
builder.Build(function);
if (!builder.HasStackOverflow()) {
if (variable_count > 0) {
ReachingDefinitions rd(builder.postorder(),
builder.body_definitions(),
variable_count);
rd.Compute();
TypeAnalyzer ta(builder.postorder(),
builder.body_definitions(),
variable_count,
function->num_parameters());
ta.Compute();
MarkLiveCode(builder.preorder(),
builder.body_definitions(),
variable_count);
}
}
FlowGraphBuilder builder;
FlowGraph* graph = builder.Build(function);
USE(graph);
#ifdef DEBUG
if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
builder.graph()->PrintText(function, builder.postorder());
graph->PrintAsText(function->name());
}
#endif
}
......@@ -499,33 +479,13 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
}
if (FLAG_use_flow_graph) {
int variable_count =
literal->num_parameters() + literal->scope()->num_stack_slots();
FlowGraphBuilder builder(variable_count);
builder.Build(literal);
if (!builder.HasStackOverflow()) {
if (variable_count > 0) {
ReachingDefinitions rd(builder.postorder(),
builder.body_definitions(),
variable_count);
rd.Compute();
TypeAnalyzer ta(builder.postorder(),
builder.body_definitions(),
variable_count,
literal->num_parameters());
ta.Compute();
MarkLiveCode(builder.preorder(),
builder.body_definitions(),
variable_count);
}
}
FlowGraphBuilder builder;
FlowGraph* graph = builder.Build(literal);
USE(graph);
#ifdef DEBUG
if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
builder.graph()->PrintText(literal, builder.postorder());
graph->PrintAsText(literal->name());
}
#endif
}
......
......@@ -138,10 +138,7 @@ class CompilationInfo BASE_EMBEDDED {
// There should always be a function literal, but it may be set after
// construction (for lazy compilation).
FunctionLiteral* function() { return function_; }
void set_function(FunctionLiteral* literal) {
ASSERT(function_ == NULL);
function_ = literal;
}
void set_function(FunctionLiteral* literal) { function_ = literal; }
// Simple accessors.
bool is_eval() { return is_eval_; }
......
This diff is collapsed.
......@@ -272,65 +272,6 @@ class AssignedVariablesAnalyzer : public AstVisitor {
};
class ReachingDefinitions BASE_EMBEDDED {
public:
ReachingDefinitions(ZoneList<Node*>* postorder,
ZoneList<Expression*>* body_definitions,
int variable_count)
: postorder_(postorder),
body_definitions_(body_definitions),
variable_count_(variable_count) {
}
static int IndexFor(Variable* var, int variable_count);
void Compute();
private:
// A (postorder) list of flow-graph nodes in the body.
ZoneList<Node*>* postorder_;
// A list of all the definitions in the body.
ZoneList<Expression*>* body_definitions_;
int variable_count_;
DISALLOW_COPY_AND_ASSIGN(ReachingDefinitions);
};
class TypeAnalyzer BASE_EMBEDDED {
public:
TypeAnalyzer(ZoneList<Node*>* postorder,
ZoneList<Expression*>* body_definitions,
int variable_count,
int param_count)
: postorder_(postorder),
body_definitions_(body_definitions),
variable_count_(variable_count),
param_count_(param_count) {}
void Compute();
private:
// Get the primitity of definition number i. Definitions are numbered
// by the flow graph builder.
bool IsPrimitiveDef(int def_num);
ZoneList<Node*>* postorder_;
ZoneList<Expression*>* body_definitions_;
int variable_count_;
int param_count_;
DISALLOW_COPY_AND_ASSIGN(TypeAnalyzer);
};
void MarkLiveCode(ZoneList<Node*>* nodes,
ZoneList<Expression*>* body_definitions,
int variable_count);
} } // namespace v8::internal
......
This diff is collapsed.
This diff is collapsed.
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