2010-03-25 16:22:48 +00:00
|
|
|
// 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:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above
|
|
|
|
// copyright notice, this list of conditions and the following
|
|
|
|
// disclaimer in the documentation and/or other materials provided
|
|
|
|
// with the distribution.
|
|
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
|
|
// contributors may be used to endorse or promote products derived
|
|
|
|
// from this software without specific prior written permission.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
#ifndef V8_FLOW_GRAPH_H_
|
|
|
|
#define V8_FLOW_GRAPH_H_
|
|
|
|
|
|
|
|
#include "v8.h"
|
|
|
|
|
|
|
|
#include "data-flow.h"
|
|
|
|
#include "zone.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
// The nodes of a flow graph are basic blocks. Basic blocks consist of
|
|
|
|
// instructions represented as pointers to AST nodes in the order that they
|
|
|
|
// would be visited by the code generator. A block can have arbitrarily many
|
|
|
|
// (even zero) predecessors and up to two successors. Blocks with multiple
|
|
|
|
// predecessors are "join nodes" and blocks with multiple successors are
|
|
|
|
// "branch nodes". A block can be both a branch and a join node.
|
|
|
|
//
|
|
|
|
// Flow graphs are in edge split form: a branch node is never the
|
|
|
|
// predecessor of a merge node. Empty basic blocks are inserted to maintain
|
|
|
|
// edge split form.
|
|
|
|
class BasicBlock: public ZoneObject {
|
2010-03-25 16:22:48 +00:00
|
|
|
public:
|
2010-03-29 14:23:55 +00:00
|
|
|
// Construct a basic block with a given predecessor. NULL indicates no
|
|
|
|
// predecessor or that the predecessor will be set later.
|
|
|
|
explicit BasicBlock(BasicBlock* predecessor)
|
|
|
|
: predecessors_(2),
|
|
|
|
instructions_(8),
|
|
|
|
left_successor_(NULL),
|
|
|
|
right_successor_(NULL),
|
|
|
|
mark_(false) {
|
|
|
|
if (predecessor != NULL) AddPredecessor(predecessor);
|
|
|
|
}
|
2010-03-25 16:22:48 +00:00
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
bool HasPredecessor() { return !predecessors_.is_empty(); }
|
|
|
|
bool HasSuccessor() { return left_successor_ != NULL; }
|
2010-03-25 16:22:48 +00:00
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
// Add a given basic block as a predecessor of this block. This function
|
|
|
|
// also adds this block as a successor of the given block.
|
|
|
|
void AddPredecessor(BasicBlock* predecessor) {
|
2010-03-25 16:22:48 +00:00
|
|
|
ASSERT(predecessor != NULL);
|
|
|
|
predecessors_.Add(predecessor);
|
2010-03-29 14:23:55 +00:00
|
|
|
predecessor->AddSuccessor(this);
|
2010-03-25 16:22:48 +00:00
|
|
|
}
|
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
// Add an instruction to the end of this block. The block must be "open"
|
|
|
|
// by not having a successor yet.
|
2010-03-25 16:22:48 +00:00
|
|
|
void AddInstruction(AstNode* instruction) {
|
2010-03-29 14:23:55 +00:00
|
|
|
ASSERT(!HasSuccessor() && instruction != NULL);
|
2010-03-25 16:22:48 +00:00
|
|
|
instructions_.Add(instruction);
|
|
|
|
}
|
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
// Perform a depth-first traversal of graph rooted at this node,
|
|
|
|
// accumulating pre- and postorder traversal orders. Visited nodes are
|
|
|
|
// marked with mark.
|
|
|
|
void BuildTraversalOrder(ZoneList<BasicBlock*>* preorder,
|
|
|
|
ZoneList<BasicBlock*>* postorder,
|
|
|
|
bool mark);
|
|
|
|
bool GetMark() { return mark_; }
|
2010-03-25 16:22:48 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2010-03-29 14:23:55 +00:00
|
|
|
// In debug mode, blocks are numbered in reverse postorder to help with
|
|
|
|
// printing.
|
|
|
|
int number() { return number_; }
|
|
|
|
void set_number(int n) { number_ = n; }
|
|
|
|
|
|
|
|
// Print a basic block, given the number of the first instruction.
|
|
|
|
// Returns the next number after the number of the last instruction.
|
|
|
|
int PrintAsText(int instruction_number);
|
2010-03-25 16:22:48 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
private:
|
2010-03-29 14:23:55 +00:00
|
|
|
// Add a given basic block as successor to this block. This function does
|
|
|
|
// not add this block as a predecessor of the given block so as to avoid
|
|
|
|
// circularity.
|
|
|
|
void AddSuccessor(BasicBlock* successor) {
|
|
|
|
ASSERT(right_successor_ == NULL && successor != NULL);
|
|
|
|
if (HasSuccessor()) {
|
|
|
|
right_successor_ = successor;
|
2010-03-25 16:22:48 +00:00
|
|
|
} else {
|
2010-03-29 14:23:55 +00:00
|
|
|
left_successor_ = successor;
|
2010-03-25 16:22:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
ZoneList<BasicBlock*> predecessors_;
|
|
|
|
ZoneList<AstNode*> instructions_;
|
|
|
|
BasicBlock* left_successor_;
|
|
|
|
BasicBlock* right_successor_;
|
2010-03-25 16:22:48 +00:00
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
// Support for graph traversal. Before traversal, all nodes in the graph
|
|
|
|
// have the same mark (true or false). Traversal marks already-visited
|
|
|
|
// nodes with the opposite mark. After traversal, all nodes again have
|
|
|
|
// the same mark. Traversal of the same graph is not reentrant.
|
|
|
|
bool mark_;
|
2010-03-25 16:22:48 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2010-03-29 14:23:55 +00:00
|
|
|
int number_;
|
2010-03-25 16:22:48 +00:00
|
|
|
#endif
|
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(BasicBlock);
|
2010-03-25 16:22:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
// A flow graph has distinguished entry and exit blocks. The entry block is
|
|
|
|
// the only one with no predecessors and the exit block is the only one with
|
|
|
|
// no successors.
|
|
|
|
class FlowGraph: public ZoneObject {
|
2010-03-25 16:22:48 +00:00
|
|
|
public:
|
2010-03-29 14:23:55 +00:00
|
|
|
FlowGraph(BasicBlock* entry, BasicBlock* exit)
|
|
|
|
: entry_(entry), exit_(exit), preorder_(8), postorder_(8) {
|
2010-03-25 16:22:48 +00:00
|
|
|
}
|
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
ZoneList<BasicBlock*>* preorder() { return &preorder_; }
|
|
|
|
ZoneList<BasicBlock*>* postorder() { return &postorder_; }
|
2010-03-25 16:22:48 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2010-03-29 14:23:55 +00:00
|
|
|
void PrintAsText(Handle<String> name);
|
2010-03-25 16:22:48 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
private:
|
2010-03-29 14:23:55 +00:00
|
|
|
BasicBlock* entry_;
|
|
|
|
BasicBlock* exit_;
|
|
|
|
ZoneList<BasicBlock*> preorder_;
|
|
|
|
ZoneList<BasicBlock*> postorder_;
|
2010-03-25 16:22:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
// The flow graph builder walks the AST adding reachable AST nodes to the
|
|
|
|
// flow graph as instructions. It remembers the entry and exit nodes of the
|
|
|
|
// graph, and keeps a pointer to the current block being constructed.
|
2010-03-25 16:22:48 +00:00
|
|
|
class FlowGraphBuilder: public AstVisitor {
|
|
|
|
public:
|
2010-03-29 14:23:55 +00:00
|
|
|
FlowGraphBuilder() {}
|
2010-03-25 16:22:48 +00:00
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
FlowGraph* Build(FunctionLiteral* lit);
|
2010-03-25 16:22:48 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
// AST node visit functions.
|
|
|
|
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
|
|
|
|
AST_NODE_LIST(DECLARE_VISIT)
|
|
|
|
#undef DECLARE_VISIT
|
|
|
|
|
2010-03-29 14:23:55 +00:00
|
|
|
BasicBlock* entry_;
|
|
|
|
BasicBlock* exit_;
|
|
|
|
BasicBlock* current_;
|
2010-03-25 16:22:48 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(FlowGraphBuilder);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
} } // namespace v8::internal
|
|
|
|
|
|
|
|
#endif // V8_FLOW_GRAPH_H_
|