Revision: 4246
Author: [email protected]
Date: Wed Mar 24 03:36:18 2010
Log: Initial support for marking live code.
As part of aggressive dead code elimination, we initially assume all
flow-graph instructions are not live. We mark those that are critical
and recursively all their children. The children of variable
references (VariableProxies occurring as rvalues) include all their
reaching definitions.
Review URL: http://codereview.chromium.org/1159005
http://code.google.com/p/v8/source/detail?r=4246
Modified:
/branches/bleeding_edge/src/ast.cc
/branches/bleeding_edge/src/ast.h
/branches/bleeding_edge/src/compiler.cc
/branches/bleeding_edge/src/data-flow.cc
/branches/bleeding_edge/src/data-flow.h
=======================================
--- /branches/bleeding_edge/src/ast.cc Tue Mar 23 06:36:38 2010
+++ /branches/bleeding_edge/src/ast.cc Wed Mar 24 03:36:18 2010
@@ -28,6 +28,7 @@
#include "v8.h"
#include "ast.h"
+#include "data-flow.h"
#include "parser.h"
#include "scopes.h"
#include "string-stream.h"
@@ -598,6 +599,199 @@
// Compare operations always express Boolean values.
bool CompareOperation::IsPrimitive() { return true; }
+
+
+// Overridden IsCritical member functions. IsCritical is true for AST
nodes
+// whose evaluation is absolutely required (they are never dead) because
+// they are externally visible.
+
+// References to global variables or lookup slots are critical because they
+// may have getters. All others, including parameters rewritten to
explicit
+// property references, are not critical.
+bool VariableProxy::IsCritical() {
+ Variable* var = AsVariable();
+ return var != NULL &&
+ (var->slot() == NULL || var->slot()->type() == Slot::LOOKUP);
+}
+
+
+// Literals are never critical.
+bool Literal::IsCritical() { return false; }
+
+
+// Property assignments and throwing of reference errors are always
+// critical. Assignments to escaping variables are also critical. In
+// addition the operation of compound assignments is critical if either of
+// its operands is non-primitive (the arithmetic operations all use one of
+// ToPrimitive, ToNumber, ToInt32, or ToUint32 on each of their operands).
+// In this case, we mark the entire AST node as critical because there is
+// no binary operation node to mark.
+bool Assignment::IsCritical() {
+ Variable* var = AssignedVariable();
+ return var == NULL ||
+ !var->IsStackAllocated() ||
+ (is_compound() && (!target()->IsPrimitive() |
| !value()->IsPrimitive()));
+}
+
+
+// Property references are always critical, because they may have getters.
+bool Property::IsCritical() { return true; }
+
+
+// Calls are always critical.
+bool Call::IsCritical() { return true; }
+
+
+// +,- use ToNumber on the value of their operand.
+bool UnaryOperation::IsCritical() {
+ ASSERT(op() == Token::ADD || op() == Token::SUB);
+ return !expression()->IsPrimitive();
+}
+
+
+// Count operations targeting properties and reference errors are always
+// critical. Count operations on escaping variables are critical. Count
+// operations targeting non-primitives are also critical because they use
+// ToNumber.
+bool CountOperation::IsCritical() {
+ Variable* var = AssignedVariable();
+ return var == NULL ||
+ !var->IsStackAllocated() ||
+ !expression()->IsPrimitive();
+}
+
+
+// Arithmetic operations all use one of ToPrimitive, ToNumber, ToInt32, or
+// ToUint32 on each of their operands.
+bool BinaryOperation::IsCritical() {
+ ASSERT(op() != Token::COMMA);
+ ASSERT(op() != Token::OR);
+ ASSERT(op() != Token::AND);
+ return !left()->IsPrimitive() || !right()->IsPrimitive();
+}
+
+
+// <, >, <=, and >= all use ToPrimitive on both their operands.
+bool CompareOperation::IsCritical() {
+ ASSERT(op() != Token::EQ);
+ ASSERT(op() != Token::NE);
+ ASSERT(op() != Token::EQ_STRICT);
+ ASSERT(op() != Token::NE_STRICT);
+ ASSERT(op() != Token::INSTANCEOF);
+ ASSERT(op() != Token::IN);
+ return !left()->IsPrimitive() || !right()->IsPrimitive();
+}
+
+
+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
=======================================
--- /branches/bleeding_edge/src/ast.h Tue Mar 23 06:36:38 2010
+++ /branches/bleeding_edge/src/ast.h Wed Mar 24 03:36:18 2010
@@ -151,6 +151,10 @@
virtual ObjectLiteral* AsObjectLiteral() { return NULL; }
virtual ArrayLiteral* AsArrayLiteral() { return NULL; }
virtual CompareOperation* AsCompareOperation() { return NULL; }
+
+ // True if the AST node is critical (its execution is needed or
externally
+ // visible in some way).
+ virtual bool IsCritical() { UNREACHABLE(); return true; }
int num() { return num_; }
void set_num(int n) { num_ = n; }
@@ -211,7 +215,7 @@
virtual bool IsValidLeftHandSide() { return false; }
- virtual Variable* AssignedVar() { return NULL; }
+ virtual Variable* AssignedVariable() { return NULL; }
// Symbols that cannot be parsed as array indices are considered property
// names. We do not treat symbols that can be array indexes as property
@@ -282,6 +286,19 @@
num_bit_ops = Min(num_bit_ops, kMaxNumBitOps);
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;
@@ -295,6 +312,7 @@
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> {};
};
@@ -881,6 +899,11 @@
virtual bool IsLeaf() { return true; }
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()); }
@@ -1087,6 +1110,11 @@
virtual bool IsTrivial() { return is_trivial_; }
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; }
@@ -1224,6 +1252,11 @@
virtual bool IsValidLeftHandSide() { return true; }
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_; }
@@ -1258,6 +1291,11 @@
virtual Call* AsCall() { return this; }
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_; }
@@ -1336,6 +1374,11 @@
virtual UnaryOperation* AsUnaryOperation() { return this; }
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_; }
@@ -1361,6 +1404,11 @@
virtual BinaryOperation* AsBinaryOperation() { return this; }
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.
@@ -1412,11 +1460,16 @@
virtual CountOperation* AsCountOperation() { return this; }
- virtual Variable* AssignedVar() {
+ virtual Variable* AssignedVariable() {
return expression()->AsVariableProxy()->AsVariable();
}
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_; }
@@ -1449,6 +1502,11 @@
virtual void Accept(AstVisitor* v);
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_; }
@@ -1502,10 +1560,15 @@
virtual Assignment* AsAssignment() { return this; }
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; }
- virtual Variable* AssignedVar() {
+ virtual Variable* AssignedVariable() {
return target()->AsVariableProxy()->AsVariable();
}
=======================================
--- /branches/bleeding_edge/src/compiler.cc Tue Mar 23 06:01:37 2010
+++ /branches/bleeding_edge/src/compiler.cc Wed Mar 24 03:36:18 2010
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 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:
@@ -106,6 +106,10 @@
variable_count,
function->num_parameters());
ta.Compute();
+
+ MarkLiveCode(builder.preorder(),
+ builder.body_definitions(),
+ variable_count);
}
}
@@ -521,6 +525,10 @@
variable_count,
literal->num_parameters());
ta.Compute();
+
+ MarkLiveCode(builder.preorder(),
+ builder.body_definitions(),
+ variable_count);
}
}
=======================================
--- /branches/bleeding_edge/src/data-flow.cc Tue Mar 23 06:01:37 2010
+++ /branches/bleeding_edge/src/data-flow.cc Wed Mar 24 03:36:18 2010
@@ -1663,9 +1663,16 @@
PrintF("L%d: Block\n", number());
TextInstructionPrinter printer;
for (int i = 0, len = instructions_.length(); i < len; i++) {
+ AstNode* instr = instructions_[i];
+ // Print a star next to dead instructions.
+ if (instr->AsExpression() != NULL && instr->AsExpression()->is_live())
{
+ PrintF(" ");
+ } else {
+ PrintF("* ");
+ }
PrintF("%d ", printer.NextNumber());
- printer.Visit(instructions_[i]);
- printer.AssignNumber(instructions_[i]);
+ printer.Visit(instr);
+ printer.AssignNumber(instr);
PrintF("\n");
}
PrintF("goto L%d\n\n", successor_->number());
@@ -1753,7 +1760,7 @@
for (int i = 0; i < instruction_count; i++) {
Expression* expr = instructions_[i]->AsExpression();
if (expr == NULL) continue;
- Variable* var = expr->AssignedVar();
+ Variable* var = expr->AssignedVariable();
if (var == NULL || !var->IsStackAllocated()) continue;
// All definitions of this variable are killed.
@@ -1930,7 +1937,7 @@
// It may instead (or also) be a definition. If so update the running
// value of reaching definitions for the block.
- Variable* var = expr->AssignedVar();
+ Variable* var = expr->AssignedVariable();
if (var == NULL || !var->IsStackAllocated()) continue;
// All definitions of this variable are killed.
@@ -1961,7 +1968,7 @@
for (int i = 0, len = body_definitions_->length(); i < len; i++) {
// Account for each definition in the body as a definition of the
// defined variable.
- Variable* var = body_definitions_->at(i)->AssignedVar();
+ Variable* var = body_definitions_->at(i)->AssignedVariable();
variables[IndexFor(var, variable_count_)]->Add(i + variable_count_);
}
@@ -2044,6 +2051,52 @@
}
} while (changed);
}
+
+
+void Node::MarkCriticalInstructions(
+ List<AstNode*>* stack,
+ ZoneList<Expression*>* body_definitions,
+ int variable_count) {
+}
+
+
+void BlockNode::MarkCriticalInstructions(
+ List<AstNode*>* stack,
+ ZoneList<Expression*>* body_definitions,
+ int variable_count) {
+ for (int i = instructions_.length() - 1; i >= 0; i--) {
+ // Only expressions can appear in the flow graph for now.
+ Expression* expr = instructions_[i]->AsExpression();
+ if (expr != NULL && !expr->is_live() &&
+ (expr->is_loop_condition() || expr->IsCritical())) {
+ expr->mark_as_live();
+ expr->ProcessNonLiveChildren(stack, body_definitions,
variable_count);
+ }
+ }
+}
+
+
+void MarkLiveCode(ZoneList<Node*>* nodes,
+ ZoneList<Expression*>* body_definitions,
+ int variable_count) {
+ List<AstNode*> stack(20);
+
+ // Mark the critical AST nodes as live; mark their dependencies and
+ // add them to the marking stack.
+ for (int i = nodes->length() - 1; i >= 0; i--) {
+ nodes->at(i)->MarkCriticalInstructions(&stack, body_definitions,
+ variable_count);
+ }
+
+ // Continue marking dependencies until no more.
+ while (!stack.is_empty()) {
+ // Only expressions can appear in the flow graph for now.
+ Expression* expr = stack.RemoveLast()->AsExpression();
+ if (expr != NULL) {
+ expr->ProcessNonLiveChildren(&stack, body_definitions,
variable_count);
+ }
+ }
+}
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/data-flow.h Tue Mar 23 06:01:37 2010
+++ /branches/bleeding_edge/src/data-flow.h Wed Mar 24 03:36:18 2010
@@ -241,6 +241,12 @@
virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark) = 0;
virtual void PropagateReachingDefinitions(List<BitVector*>* variables);
+ // Functions used by dead-code elimination.
+ virtual void MarkCriticalInstructions(
+ List<AstNode*>* stack,
+ ZoneList<Expression*>* body_definitions,
+ int variable_count);
+
#ifdef DEBUG
void AssignNodeNumber();
void PrintReachingDefinitions();
@@ -263,24 +269,24 @@
public:
ExitNode() : predecessors_(4) {}
- bool IsExitNode() { return true; }
-
- void AddPredecessor(Node* predecessor) {
+ virtual bool IsExitNode() { return true; }
+
+ virtual void AddPredecessor(Node* predecessor) {
ASSERT(predecessor != NULL);
predecessors_.Add(predecessor);
}
- void AddSuccessor(Node* successor) { UNREACHABLE(); }
-
- void Traverse(bool mark,
- ZoneList<Node*>* preorder,
- ZoneList<Node*>* postorder);
-
- void ComputeRDOut(BitVector* result);
- void UpdateRDIn(WorkList<Node>* worklist, bool mark);
+ virtual void AddSuccessor(Node* successor) { UNREACHABLE(); }
+
+ virtual void Traverse(bool mark,
+ ZoneList<Node*>* preorder,
+ ZoneList<Node*>* postorder);
+
+ virtual void ComputeRDOut(BitVector* result);
+ virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark);
#ifdef DEBUG
- void PrintText();
+ virtual void PrintText();
#endif
private:
@@ -301,18 +307,18 @@
return reinterpret_cast<BlockNode*>(node);
}
- bool IsBlockNode() { return true; }
+ virtual bool IsBlockNode() { return true; }
bool is_empty() { return instructions_.is_empty(); }
ZoneList<AstNode*>* instructions() { return &instructions_; }
- void AddPredecessor(Node* predecessor) {
+ virtual void AddPredecessor(Node* predecessor) {
ASSERT(predecessor_ == NULL && predecessor != NULL);
predecessor_ = predecessor;
}
- void AddSuccessor(Node* successor) {
+ virtual void AddSuccessor(Node* successor) {
ASSERT(successor_ == NULL && successor != NULL);
successor_ = successor;
}
@@ -321,20 +327,25 @@
instructions_.Add(instruction);
}
- void Traverse(bool mark,
- ZoneList<Node*>* preorder,
- ZoneList<Node*>* postorder);
-
- void InitializeReachingDefinitions(int definition_count,
- List<BitVector*>* variables,
- WorkList<Node>* worklist,
- bool mark);
- void ComputeRDOut(BitVector* result);
- void UpdateRDIn(WorkList<Node>* worklist, bool mark);
- void PropagateReachingDefinitions(List<BitVector*>* variables);
+ virtual void Traverse(bool mark,
+ ZoneList<Node*>* preorder,
+ ZoneList<Node*>* postorder);
+
+ virtual void InitializeReachingDefinitions(int definition_count,
+ List<BitVector*>* variables,
+ WorkList<Node>* worklist,
+ bool mark);
+ virtual void ComputeRDOut(BitVector* result);
+ virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark);
+ virtual void PropagateReachingDefinitions(List<BitVector*>* variables);
+
+ virtual void MarkCriticalInstructions(
+ List<AstNode*>* stack,
+ ZoneList<Expression*>* body_definitions,
+ int variable_count);
#ifdef DEBUG
- void PrintText();
+ virtual void PrintText();
#endif
private:
@@ -351,14 +362,14 @@
public:
BranchNode() : predecessor_(NULL), successor0_(NULL), successor1_(NULL)
{}
- bool IsBranchNode() { return true; }
-
- void AddPredecessor(Node* predecessor) {
+ virtual bool IsBranchNode() { return true; }
+
+ virtual void AddPredecessor(Node* predecessor) {
ASSERT(predecessor_ == NULL && predecessor != NULL);
predecessor_ = predecessor;
}
- void AddSuccessor(Node* successor) {
+ virtual void AddSuccessor(Node* successor) {
ASSERT(successor1_ == NULL && successor != NULL);
if (successor0_ == NULL) {
successor0_ = successor;
@@ -367,15 +378,15 @@
}
}
- void Traverse(bool mark,
- ZoneList<Node*>* preorder,
- ZoneList<Node*>* postorder);
-
- void ComputeRDOut(BitVector* result);
- void UpdateRDIn(WorkList<Node>* worklist, bool mark);
+ virtual void Traverse(bool mark,
+ ZoneList<Node*>* preorder,
+ ZoneList<Node*>* postorder);
+
+ virtual void ComputeRDOut(BitVector* result);
+ virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark);
#ifdef DEBUG
- void PrintText();
+ virtual void PrintText();
#endif
private:
@@ -397,27 +408,27 @@
return reinterpret_cast<JoinNode*>(node);
}
- bool IsJoinNode() { return true; }
-
- void AddPredecessor(Node* predecessor) {
+ virtual bool IsJoinNode() { return true; }
+
+ virtual void AddPredecessor(Node* predecessor) {
ASSERT(predecessor != NULL);
predecessors_.Add(predecessor);
}
- void AddSuccessor(Node* successor) {
+ virtual void AddSuccessor(Node* successor) {
ASSERT(successor_ == NULL && successor != NULL);
successor_ = successor;
}
- void Traverse(bool mark,
- ZoneList<Node*>* preorder,
- ZoneList<Node*>* postorder);
-
- void ComputeRDOut(BitVector* result);
- void UpdateRDIn(WorkList<Node>* worklist, bool mark);
+ virtual void Traverse(bool mark,
+ ZoneList<Node*>* preorder,
+ ZoneList<Node*>* postorder);
+
+ virtual void ComputeRDOut(BitVector* result);
+ virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark);
#ifdef DEBUG
- void PrintText();
+ virtual void PrintText();
#endif
private:
@@ -499,6 +510,7 @@
void Build(FunctionLiteral* lit);
FlowGraph* graph() { return &graph_; }
+ ZoneList<Node*>* preorder() { return &preorder_; }
ZoneList<Node*>* postorder() { return &postorder_; }
ZoneList<Expression*>* body_definitions() { return &body_definitions_; }
@@ -622,7 +634,6 @@
};
-
class TypeAnalyzer BASE_EMBEDDED {
public:
TypeAnalyzer(ZoneList<Node*>* postorder,
@@ -645,8 +656,16 @@
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
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
To unsubscribe from this group, send email to v8-dev+unsubscribegooglegroups.com or reply
to this email with the words "REMOVE ME" as the subject.