Index: src/cfg.h |
=================================================================== |
--- src/cfg.h (revision 2994) |
+++ src/cfg.h (working copy) |
@@ -1,871 +0,0 @@ |
-// Copyright 2009 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_CFG_H_ |
-#define V8_CFG_H_ |
- |
-#include "ast.h" |
- |
-namespace v8 { |
-namespace internal { |
- |
-class ExitNode; |
-class Location; |
- |
-// Translate a source AST into a control-flow graph (CFG). The CFG contains |
-// single-entry, single-exit blocks of straight-line instructions and |
-// administrative nodes. |
-// |
-// Instructions are described by the following grammar. |
-// |
-// <Instruction> ::= |
-// Move <Location> <Value> |
-// | PropLoad <Location> <Value> <Value> |
-// | BinaryOp <Location> Token::Value <Value> <Value> |
-// | Return Nowhere <Value> |
-// | Position <Int> |
-// |
-// Values are trivial expressions: |
-// |
-// <Value> ::= Constant | <Location> |
-// |
-// Locations are storable values ('lvalues'). They can be slots, |
-// compiler-generated temporaries, or the special location 'Nowhere' |
-// indicating that no value is needed. |
-// |
-// <Location> ::= |
-// SlotLocation Slot::Type <Index> |
-// | TempLocation |
-// | Nowhere |
- |
- |
-// Administrative nodes: There are several types of 'administrative' nodes |
-// that do not contain instructions and do not necessarily have a single |
-// predecessor and a single successor. |
-// |
-// EntryNode: there is a distinguished entry node that has no predecessors |
-// and a single successor. |
-// |
-// ExitNode: there is a distinguished exit node that has arbitrarily many |
-// predecessors and no successor. |
-// |
-// JoinNode: join nodes have multiple predecessors and a single successor. |
-// |
-// BranchNode: branch nodes have a single predecessor and multiple |
-// successors. |
- |
- |
-// A convenient class to keep 'global' values when building a CFG. Since |
-// CFG construction can be invoked recursively, CFG globals are stacked. |
-class CfgGlobals BASE_EMBEDDED { |
- public: |
- explicit CfgGlobals(FunctionLiteral* fun); |
- |
- ~CfgGlobals() { top_ = previous_; } |
- |
- static CfgGlobals* current() { |
- ASSERT(top_ != NULL); |
- return top_; |
- } |
- |
- // The function currently being compiled. |
- FunctionLiteral* fun() { return global_fun_; } |
- |
- // The shared global exit node for all exits from the function. |
- ExitNode* exit() { return global_exit_; } |
- |
- // A singleton. |
- Location* nowhere() { return nowhere_; } |
- |
-#ifdef DEBUG |
- int next_node_number() { return node_counter_++; } |
- int next_temp_number() { return temp_counter_++; } |
-#endif |
- |
- private: |
- static CfgGlobals* top_; |
- FunctionLiteral* global_fun_; |
- ExitNode* global_exit_; |
- Location* nowhere_; |
- |
-#ifdef DEBUG |
- // Used to number nodes and temporaries when printing. |
- int node_counter_; |
- int temp_counter_; |
-#endif |
- |
- CfgGlobals* previous_; |
-}; |
- |
- |
-class SlotLocation; |
- |
-// Values represent trivial source expressions: ones with no side effects |
-// and that do not require code to be generated. |
-class Value : public ZoneObject { |
- public: |
- virtual ~Value() {} |
- |
- // Predicates: |
- |
- virtual bool is_temporary() { return false; } |
- virtual bool is_slot() { return false; } |
- virtual bool is_constant() { return false; } |
- |
- // True if the value is a temporary allocated to the stack in |
- // fast-compilation mode. |
- virtual bool is_on_stack() { return false; } |
- |
- // Support for fast-compilation mode: |
- |
- // Move the value into a register. |
- virtual void Get(MacroAssembler* masm, Register reg) = 0; |
- |
- // Push the value on the stack. |
- virtual void Push(MacroAssembler* masm) = 0; |
- |
- // Move the value into a slot location. |
- virtual void MoveToSlot(MacroAssembler* masm, SlotLocation* loc) = 0; |
- |
-#ifdef DEBUG |
- virtual void Print() = 0; |
-#endif |
-}; |
- |
- |
-// A compile-time constant that appeared as a literal in the source AST. |
-class Constant : public Value { |
- public: |
- explicit Constant(Handle<Object> handle) : handle_(handle) {} |
- |
- // Cast accessor. |
- static Constant* cast(Value* value) { |
- ASSERT(value->is_constant()); |
- return reinterpret_cast<Constant*>(value); |
- } |
- |
- // Accessors. |
- Handle<Object> handle() { return handle_; } |
- |
- // Predicates. |
- bool is_constant() { return true; } |
- |
- // Support for fast-compilation mode. |
- void Get(MacroAssembler* masm, Register reg); |
- void Push(MacroAssembler* masm); |
- void MoveToSlot(MacroAssembler* masm, SlotLocation* loc); |
- |
-#ifdef DEBUG |
- void Print(); |
-#endif |
- |
- private: |
- Handle<Object> handle_; |
-}; |
- |
- |
-// Locations are values that can be stored into ('lvalues'). |
-class Location : public Value { |
- public: |
- virtual ~Location() {} |
- |
- // Static factory function returning the singleton nowhere location. |
- static Location* Nowhere() { |
- return CfgGlobals::current()->nowhere(); |
- } |
- |
- // Support for fast-compilation mode: |
- |
- // Assumes temporaries have been allocated. |
- virtual void Get(MacroAssembler* masm, Register reg) = 0; |
- |
- // Store the value in a register to the location. Assumes temporaries |
- // have been allocated. |
- virtual void Set(MacroAssembler* masm, Register reg) = 0; |
- |
- // Assumes temporaries have been allocated, and if the value is a |
- // temporary it was not allocated to the stack. |
- virtual void Push(MacroAssembler* masm) = 0; |
- |
- // Emit code to move a value into this location. |
- virtual void Move(MacroAssembler* masm, Value* value) = 0; |
- |
-#ifdef DEBUG |
- virtual void Print() = 0; |
-#endif |
-}; |
- |
- |
-// Nowhere is a special (singleton) location that indicates the value of a |
-// computation is not needed (though its side effects are). |
-class Nowhere : public Location { |
- public: |
- // We should not try to emit code to read Nowhere. |
- void Get(MacroAssembler* masm, Register reg) { UNREACHABLE(); } |
- void Push(MacroAssembler* masm) { UNREACHABLE(); } |
- void MoveToSlot(MacroAssembler* masm, SlotLocation* loc) { UNREACHABLE(); } |
- |
- // Setting Nowhere is ignored. |
- void Set(MacroAssembler* masm, Register reg) {} |
- void Move(MacroAssembler* masm, Value* value) {} |
- |
-#ifdef DEBUG |
- void Print(); |
-#endif |
- |
- private: |
- Nowhere() {} |
- |
- friend class CfgGlobals; |
-}; |
- |
- |
-// SlotLocations represent parameters and stack-allocated (i.e., |
-// non-context) local variables. |
-class SlotLocation : public Location { |
- public: |
- SlotLocation(Slot::Type type, int index) : type_(type), index_(index) {} |
- |
- // Cast accessor. |
- static SlotLocation* cast(Value* value) { |
- ASSERT(value->is_slot()); |
- return reinterpret_cast<SlotLocation*>(value); |
- } |
- |
- // Accessors. |
- Slot::Type type() { return type_; } |
- int index() { return index_; } |
- |
- // Predicates. |
- bool is_slot() { return true; } |
- |
- // Support for fast-compilation mode. |
- void Get(MacroAssembler* masm, Register reg); |
- void Set(MacroAssembler* masm, Register reg); |
- void Push(MacroAssembler* masm); |
- void Move(MacroAssembler* masm, Value* value); |
- void MoveToSlot(MacroAssembler* masm, SlotLocation* loc); |
- |
-#ifdef DEBUG |
- void Print(); |
-#endif |
- |
- private: |
- Slot::Type type_; |
- int index_; |
-}; |
- |
- |
-// TempLocations represent compiler generated temporaries. They are |
-// allocated to registers or memory either before code generation (in the |
-// optimized-for-speed compiler) or on the fly during code generation (in |
-// the optimized-for-space compiler). |
-class TempLocation : public Location { |
- public: |
- // Fast-compilation mode allocation decisions. |
- enum Where { |
- NOT_ALLOCATED, // Not yet allocated. |
- ACCUMULATOR, // Allocated to the dedicated accumulator register. |
- STACK // " " " " stack. |
- }; |
- |
- TempLocation() : where_(NOT_ALLOCATED) { |
-#ifdef DEBUG |
- number_ = -1; |
-#endif |
- } |
- |
- // Cast accessor. |
- static TempLocation* cast(Value* value) { |
- ASSERT(value->is_temporary()); |
- return reinterpret_cast<TempLocation*>(value); |
- } |
- |
- // Accessors. |
- Where where() { return where_; } |
- void set_where(Where where) { |
- ASSERT(where_ == TempLocation::NOT_ALLOCATED); |
- where_ = where; |
- } |
- |
- // Predicates. |
- bool is_on_stack() { return where_ == STACK; } |
- bool is_temporary() { return true; } |
- |
- // Support for fast-compilation mode. Assume the temp has been allocated. |
- void Get(MacroAssembler* masm, Register reg); |
- void Set(MacroAssembler* masm, Register reg); |
- void Push(MacroAssembler* masm); |
- void Move(MacroAssembler* masm, Value* value); |
- void MoveToSlot(MacroAssembler* masm, SlotLocation* loc); |
- |
-#ifdef DEBUG |
- int number() { |
- if (number_ == -1) number_ = CfgGlobals::current()->next_temp_number(); |
- return number_; |
- } |
- |
- void Print(); |
-#endif |
- |
- private: |
- Where where_; |
- |
-#ifdef DEBUG |
- int number_; |
-#endif |
-}; |
- |
- |
-// Instructions are computations. The represent non-trivial source |
-// expressions: typically ones that have side effects and require code to |
-// be generated. |
-class Instruction : public ZoneObject { |
- public: |
- // Accessors. |
- Location* location() { return location_; } |
- void set_location(Location* location) { location_ = location; } |
- |
- // Support for fast-compilation mode: |
- |
- // Emit code to perform the instruction. |
- virtual void Compile(MacroAssembler* masm) = 0; |
- |
- // Allocate a temporary which is the result of the immediate predecessor |
- // instruction. It is allocated to the accumulator register if it is used |
- // as an operand to this instruction, otherwise to the stack. |
- virtual void FastAllocate(TempLocation* temp) = 0; |
- |
-#ifdef DEBUG |
- virtual void Print() = 0; |
-#endif |
- |
- protected: |
- // Every instruction has a location where its result is stored (which may |
- // be Nowhere). |
- explicit Instruction(Location* location) : location_(location) {} |
- |
- virtual ~Instruction() {} |
- |
- Location* location_; |
-}; |
- |
- |
-// Base class of instructions that have no input operands. |
-class ZeroOperandInstruction : public Instruction { |
- public: |
- // Support for fast-compilation mode: |
- virtual void Compile(MacroAssembler* masm) = 0; |
- void FastAllocate(TempLocation* temp); |
- |
-#ifdef DEBUG |
- // Printing support: print the operands (nothing). |
- virtual void Print() {} |
-#endif |
- |
- protected: |
- explicit ZeroOperandInstruction(Location* loc) : Instruction(loc) {} |
-}; |
- |
- |
-// Base class of instructions that have a single input operand. |
-class OneOperandInstruction : public Instruction { |
- public: |
- // Support for fast-compilation mode: |
- virtual void Compile(MacroAssembler* masm) = 0; |
- void FastAllocate(TempLocation* temp); |
- |
-#ifdef DEBUG |
- // Printing support: print the operands. |
- virtual void Print(); |
-#endif |
- |
- protected: |
- OneOperandInstruction(Location* loc, Value* value) |
- : Instruction(loc), value_(value) { |
- } |
- |
- Value* value_; |
-}; |
- |
- |
-// Base class of instructions that have two input operands. |
-class TwoOperandInstruction : public Instruction { |
- public: |
- // Support for fast-compilation mode: |
- virtual void Compile(MacroAssembler* masm) = 0; |
- void FastAllocate(TempLocation* temp); |
- |
-#ifdef DEBUG |
- // Printing support: print the operands. |
- virtual void Print(); |
-#endif |
- |
- protected: |
- TwoOperandInstruction(Location* loc, Value* value0, Value* value1) |
- : Instruction(loc), value0_(value0), value1_(value1) { |
- } |
- |
- Value* value0_; |
- Value* value1_; |
-}; |
- |
- |
-// A phantom instruction that indicates the start of a statement. It |
-// causes the statement position to be recorded in the relocation |
-// information but generates no code. |
-class PositionInstr : public ZeroOperandInstruction { |
- public: |
- explicit PositionInstr(int pos) |
- : ZeroOperandInstruction(CfgGlobals::current()->nowhere()), pos_(pos) { |
- } |
- |
- // Support for fast-compilation mode. |
- void Compile(MacroAssembler* masm); |
- |
- // This should not be called. The last instruction of the previous |
- // statement should not have a temporary as its location. |
- void FastAllocate(TempLocation* temp) { UNREACHABLE(); } |
- |
-#ifdef DEBUG |
- // Printing support. Print nothing. |
- void Print() {} |
-#endif |
- |
- private: |
- int pos_; |
-}; |
- |
- |
-// Move a value to a location. |
-class MoveInstr : public OneOperandInstruction { |
- public: |
- MoveInstr(Location* loc, Value* value) |
- : OneOperandInstruction(loc, value) { |
- } |
- |
- // Accessors. |
- Value* value() { return value_; } |
- |
- // Support for fast-compilation mode. |
- void Compile(MacroAssembler* masm); |
- |
-#ifdef DEBUG |
- // Printing support. |
- void Print(); |
-#endif |
-}; |
- |
- |
-// Load a property from a receiver, leaving the result in a location. |
-class PropLoadInstr : public TwoOperandInstruction { |
- public: |
- PropLoadInstr(Location* loc, Value* object, Value* key) |
- : TwoOperandInstruction(loc, object, key) { |
- } |
- |
- // Accessors. |
- Value* object() { return value0_; } |
- Value* key() { return value1_; } |
- |
- // Support for fast-compilation mode. |
- void Compile(MacroAssembler* masm); |
- |
-#ifdef DEBUG |
- void Print(); |
-#endif |
-}; |
- |
- |
-// Perform a (non-short-circuited) binary operation on a pair of values, |
-// leaving the result in a location. |
-class BinaryOpInstr : public TwoOperandInstruction { |
- public: |
- BinaryOpInstr(Location* loc, Token::Value op, Value* left, Value* right) |
- : TwoOperandInstruction(loc, left, right), op_(op) { |
- } |
- |
- // Accessors. |
- Value* left() { return value0_; } |
- Value* right() { return value1_; } |
- Token::Value op() { return op_; } |
- |
- // Support for fast-compilation mode. |
- void Compile(MacroAssembler* masm); |
- |
-#ifdef DEBUG |
- void Print(); |
-#endif |
- |
- private: |
- Token::Value op_; |
-}; |
- |
- |
-// Return a value. Has the side effect of moving its value into the return |
-// value register. Can only occur as the last instruction in an instruction |
-// block, and implies that the block is closed (cannot have instructions |
-// appended or graph fragments concatenated to the end) and that the block's |
-// successor is the global exit node for the current function. |
-class ReturnInstr : public OneOperandInstruction { |
- public: |
- explicit ReturnInstr(Value* value) |
- : OneOperandInstruction(CfgGlobals::current()->nowhere(), value) { |
- } |
- |
- virtual ~ReturnInstr() {} |
- |
- // Accessors. |
- Value* value() { return value_; } |
- |
- // Support for fast-compilation mode. |
- void Compile(MacroAssembler* masm); |
- |
-#ifdef DEBUG |
- void Print(); |
-#endif |
-}; |
- |
- |
-// Nodes make up control-flow graphs. |
-class CfgNode : public ZoneObject { |
- public: |
- CfgNode() : is_marked_(false) { |
-#ifdef DEBUG |
- number_ = -1; |
-#endif |
- } |
- |
- virtual ~CfgNode() {} |
- |
- // Because CFGs contain cycles, nodes support marking during traversal |
- // (e.g., for printing or compilation). The traversal functions will mark |
- // unmarked nodes and backtrack if they encounter a marked one. After a |
- // traversal, the graph should be explicitly unmarked by calling Unmark on |
- // the entry node. |
- bool is_marked() { return is_marked_; } |
- virtual void Unmark() = 0; |
- |
- // Predicates: |
- |
- // True if the node is an instruction block. |
- virtual bool is_block() { return false; } |
- |
- // Support for fast-compilation mode. Emit the instructions or control |
- // flow represented by the node. |
- virtual void Compile(MacroAssembler* masm) = 0; |
- |
-#ifdef DEBUG |
- int number() { |
- if (number_ == -1) number_ = CfgGlobals::current()->next_node_number(); |
- return number_; |
- } |
- |
- virtual void Print() = 0; |
-#endif |
- |
- protected: |
- bool is_marked_; |
- |
-#ifdef DEBUG |
- int number_; |
-#endif |
-}; |
- |
- |
-// A block is a single-entry, single-exit block of instructions. |
-class InstructionBlock : public CfgNode { |
- public: |
- InstructionBlock() : successor_(NULL), instructions_(4) {} |
- |
- virtual ~InstructionBlock() {} |
- |
- void Unmark(); |
- |
- // Cast accessor. |
- static InstructionBlock* cast(CfgNode* node) { |
- ASSERT(node->is_block()); |
- return reinterpret_cast<InstructionBlock*>(node); |
- } |
- |
- bool is_block() { return true; } |
- |
- // Accessors. |
- CfgNode* successor() { return successor_; } |
- |
- void set_successor(CfgNode* succ) { |
- ASSERT(successor_ == NULL); |
- successor_ = succ; |
- } |
- |
- ZoneList<Instruction*>* instructions() { return &instructions_; } |
- |
- // Support for fast-compilation mode. |
- void Compile(MacroAssembler* masm); |
- |
- // Add an instruction to the end of the block. |
- void Append(Instruction* instr) { instructions_.Add(instr); } |
- |
-#ifdef DEBUG |
- void Print(); |
-#endif |
- |
- private: |
- CfgNode* successor_; |
- ZoneList<Instruction*> instructions_; |
-}; |
- |
- |
-// An entry node (one per function). |
-class EntryNode : public CfgNode { |
- public: |
- explicit EntryNode(InstructionBlock* succ) : successor_(succ) {} |
- |
- virtual ~EntryNode() {} |
- |
- void Unmark(); |
- |
- // Support for fast-compilation mode. |
- void Compile(MacroAssembler* masm); |
- |
-#ifdef DEBUG |
- void Print(); |
-#endif |
- |
- private: |
- InstructionBlock* successor_; |
-}; |
- |
- |
-// An exit node (one per function). |
-class ExitNode : public CfgNode { |
- public: |
- ExitNode() {} |
- |
- virtual ~ExitNode() {} |
- |
- void Unmark(); |
- |
- // Support for fast-compilation mode. |
- void Compile(MacroAssembler* masm); |
- |
-#ifdef DEBUG |
- void Print(); |
-#endif |
-}; |
- |
- |
-// A CFG consists of a linked structure of nodes. Nodes are linked by |
-// pointing to their successors, always beginning with a (single) entry node |
-// (not necessarily of type EntryNode). If it is still possible to add |
-// nodes to the end of the graph (i.e., there is a (single) path that does |
-// not end with the global exit node), then the CFG has an exit node as |
-// well. |
-// |
-// The empty CFG is represented by a NULL entry and a NULL exit. |
-// |
-// We use the term 'open fragment' to mean a CFG whose entry and exits are |
-// both instruction blocks. It is always possible to add instructions and |
-// nodes to the beginning or end of an open fragment. |
-// |
-// We use the term 'closed fragment' to mean a CFG whose entry is an |
-// instruction block and whose exit is NULL (all paths go to the global |
-// exit). |
-// |
-// We use the term 'fragment' to refer to a CFG that is known to be an open |
-// or closed fragment. |
-class Cfg : public ZoneObject { |
- public: |
- // Create an empty CFG fragment. |
- Cfg() : entry_(NULL), exit_(NULL) {} |
- |
- // Build the CFG for a function. The returned CFG begins with an |
- // EntryNode and all paths end with the ExitNode. |
- static Cfg* Build(); |
- |
- // The entry and exit nodes of the CFG (not necessarily EntryNode and |
- // ExitNode). |
- CfgNode* entry() { return entry_; } |
- CfgNode* exit() { return exit_; } |
- |
- // True if the CFG has no nodes. |
- bool is_empty() { return entry_ == NULL; } |
- |
- // True if the CFG has an available exit node (i.e., it can be appended or |
- // concatenated to). |
- bool has_exit() { return exit_ != NULL; } |
- |
- // Add an EntryNode to a CFG fragment. It is no longer a fragment |
- // (instructions can no longer be prepended). |
- void PrependEntryNode(); |
- |
- // Append an instruction to the end of an open fragment. |
- void Append(Instruction* instr); |
- |
- // Appends a return instruction to the end of an open fragment and make |
- // it a closed fragment (the exit's successor becomes global exit node). |
- void AppendReturnInstruction(Value* value); |
- |
- // Glue an other CFG fragment to the end of this (open) fragment. |
- void Concatenate(Cfg* other); |
- |
- // Support for compilation. Compile the entire CFG. |
- Handle<Code> Compile(Handle<Script> script); |
- |
-#ifdef DEBUG |
- // Support for printing. |
- void Print(); |
-#endif |
- |
- private: |
- // Entry and exit nodes. |
- CfgNode* entry_; |
- CfgNode* exit_; |
-}; |
- |
- |
-// An implementation of a set of locations (currently slot locations), most |
-// of the operations are destructive. |
-class LocationSet BASE_EMBEDDED { |
- public: |
- // Construct an empty location set. |
- LocationSet() : parameters_(0), locals_(0) {} |
- |
- // Raw accessors. |
- uintptr_t parameters() { return parameters_; } |
- uintptr_t locals() { return locals_; } |
- |
- // Make this the empty set. |
- void Empty() { |
- parameters_ = locals_ = 0; |
- } |
- |
- // Insert an element. |
- void AddElement(SlotLocation* location) { |
- if (location->type() == Slot::PARAMETER) { |
- // Parameter indexes begin with -1 ('this'). |
- ASSERT(location->index() < kBitsPerPointer - 1); |
- parameters_ |= (1 << (location->index() + 1)); |
- } else { |
- ASSERT(location->type() == Slot::LOCAL); |
- ASSERT(location->index() < kBitsPerPointer); |
- locals_ |= (1 << location->index()); |
- } |
- } |
- |
- // (Destructively) compute the union with another set. |
- void Union(LocationSet* other) { |
- parameters_ |= other->parameters(); |
- locals_ |= other->locals(); |
- } |
- |
- bool Contains(SlotLocation* location) { |
- if (location->type() == Slot::PARAMETER) { |
- ASSERT(location->index() < kBitsPerPointer - 1); |
- return (parameters_ & (1 << (location->index() + 1))); |
- } else { |
- ASSERT(location->type() == Slot::LOCAL); |
- ASSERT(location->index() < kBitsPerPointer); |
- return (locals_ & (1 << location->index())); |
- } |
- } |
- |
- private: |
- uintptr_t parameters_; |
- uintptr_t locals_; |
-}; |
- |
- |
-// An ExpressionCfgBuilder traverses an expression and returns an open CFG |
-// fragment (currently a possibly empty list of instructions represented by |
-// a singleton instruction block) and the expression's value. |
-// |
-// Failure to build the CFG is indicated by a NULL CFG. |
-class ExpressionCfgBuilder : public AstVisitor { |
- public: |
- ExpressionCfgBuilder() : destination_(NULL), value_(NULL), graph_(NULL) {} |
- |
- // Result accessors. |
- Value* value() { return value_; } |
- Cfg* graph() { return graph_; } |
- LocationSet* assigned_vars() { return &assigned_vars_; } |
- |
- // Build the cfg for an expression and remember its value. The |
- // destination is a 'hint' where the value should go which may be ignored. |
- // NULL is used to indicate no preference. |
- // |
- // Concretely, if the expression needs to generate a temporary for its |
- // value, it should use the passed destination or generate one if NULL. |
- void Build(Expression* expr, Location* destination) { |
- value_ = NULL; |
- graph_ = new Cfg(); |
- assigned_vars_.Empty(); |
- destination_ = destination; |
- Visit(expr); |
- } |
- |
- // AST node visitors. |
-#define DECLARE_VISIT(type) void Visit##type(type* node); |
- AST_NODE_LIST(DECLARE_VISIT) |
-#undef DECLARE_VISIT |
- |
- private: |
- // State for the visitor. Input parameter: |
- Location* destination_; |
- |
- // Output parameters: |
- Value* value_; |
- Cfg* graph_; |
- LocationSet assigned_vars_; |
-}; |
- |
- |
-// A StatementCfgBuilder maintains a CFG fragment accumulator. When it |
-// visits a statement, it concatenates the CFG for the statement to the end |
-// of the accumulator. |
-class StatementCfgBuilder : public AstVisitor { |
- public: |
- StatementCfgBuilder() : graph_(new Cfg()) {} |
- |
- Cfg* graph() { return graph_; } |
- |
- void VisitStatements(ZoneList<Statement*>* stmts); |
- |
- // AST node visitors. |
-#define DECLARE_VISIT(type) void Visit##type(type* node); |
- AST_NODE_LIST(DECLARE_VISIT) |
-#undef DECLARE_VISIT |
- |
- private: |
- // State for the visitor. Input/output parameter: |
- Cfg* graph_; |
-}; |
- |
- |
-} } // namespace v8::internal |
- |
-#endif // V8_CFG_H_ |