• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_CFG_H_
29 #define V8_CFG_H_
30 
31 #include "ast.h"
32 
33 namespace v8 {
34 namespace internal {
35 
36 class ExitNode;
37 class Location;
38 
39 // Translate a source AST into a control-flow graph (CFG).  The CFG contains
40 // single-entry, single-exit blocks of straight-line instructions and
41 // administrative nodes.
42 //
43 // Instructions are described by the following grammar.
44 //
45 // <Instruction> ::=
46 //     Move <Location> <Value>
47 //   | PropLoad <Location> <Value> <Value>
48 //   | BinaryOp <Location> Token::Value <Value> <Value>
49 //   | Return Nowhere <Value>
50 //   | Position <Int>
51 //
52 // Values are trivial expressions:
53 //
54 // <Value> ::= Constant | <Location>
55 //
56 // Locations are storable values ('lvalues').  They can be slots,
57 // compiler-generated temporaries, or the special location 'Nowhere'
58 // indicating that no value is needed.
59 //
60 // <Location> ::=
61 //     SlotLocation Slot::Type <Index>
62 //   | TempLocation
63 //   | Nowhere
64 
65 
66 // Administrative nodes: There are several types of 'administrative' nodes
67 // that do not contain instructions and do not necessarily have a single
68 // predecessor and a single successor.
69 //
70 // EntryNode: there is a distinguished entry node that has no predecessors
71 // and a single successor.
72 //
73 // ExitNode: there is a distinguished exit node that has arbitrarily many
74 // predecessors and no successor.
75 //
76 // JoinNode: join nodes have multiple predecessors and a single successor.
77 //
78 // BranchNode: branch nodes have a single predecessor and multiple
79 // successors.
80 
81 
82 // A convenient class to keep 'global' values when building a CFG.  Since
83 // CFG construction can be invoked recursively, CFG globals are stacked.
84 class CfgGlobals BASE_EMBEDDED {
85  public:
86   explicit CfgGlobals(FunctionLiteral* fun);
87 
~CfgGlobals()88   ~CfgGlobals() { top_ = previous_; }
89 
current()90   static CfgGlobals* current() {
91     ASSERT(top_ != NULL);
92     return top_;
93   }
94 
95   // The function currently being compiled.
fun()96   FunctionLiteral* fun() { return global_fun_; }
97 
98   // The shared global exit node for all exits from the function.
exit()99   ExitNode* exit() { return global_exit_; }
100 
101   // A singleton.
nowhere()102   Location* nowhere() { return nowhere_; }
103 
104 #ifdef DEBUG
next_node_number()105   int next_node_number() { return node_counter_++; }
next_temp_number()106   int next_temp_number() { return temp_counter_++; }
107 #endif
108 
109  private:
110   static CfgGlobals* top_;
111   FunctionLiteral* global_fun_;
112   ExitNode* global_exit_;
113   Location* nowhere_;
114 
115 #ifdef DEBUG
116   // Used to number nodes and temporaries when printing.
117   int node_counter_;
118   int temp_counter_;
119 #endif
120 
121   CfgGlobals* previous_;
122 };
123 
124 
125 class SlotLocation;
126 
127 // Values represent trivial source expressions: ones with no side effects
128 // and that do not require code to be generated.
129 class Value : public ZoneObject {
130  public:
~Value()131   virtual ~Value() {}
132 
133   // Predicates:
134 
is_temporary()135   virtual bool is_temporary() { return false; }
is_slot()136   virtual bool is_slot() { return false; }
is_constant()137   virtual bool is_constant() { return false; }
138 
139   // True if the value is a temporary allocated to the stack in
140   // fast-compilation mode.
is_on_stack()141   virtual bool is_on_stack() { return false; }
142 
143   // Support for fast-compilation mode:
144 
145   // Move the value into a register.
146   virtual void Get(MacroAssembler* masm, Register reg) = 0;
147 
148   // Push the value on the stack.
149   virtual void Push(MacroAssembler* masm) = 0;
150 
151   // Move the value into a slot location.
152   virtual void MoveToSlot(MacroAssembler* masm, SlotLocation* loc) = 0;
153 
154 #ifdef DEBUG
155   virtual void Print() = 0;
156 #endif
157 };
158 
159 
160 // A compile-time constant that appeared as a literal in the source AST.
161 class Constant : public Value {
162  public:
Constant(Handle<Object> handle)163   explicit Constant(Handle<Object> handle) : handle_(handle) {}
164 
165   // Cast accessor.
cast(Value * value)166   static Constant* cast(Value* value) {
167     ASSERT(value->is_constant());
168     return reinterpret_cast<Constant*>(value);
169   }
170 
171   // Accessors.
handle()172   Handle<Object> handle() { return handle_; }
173 
174   // Predicates.
is_constant()175   bool is_constant() { return true; }
176 
177   // Support for fast-compilation mode.
178   void Get(MacroAssembler* masm, Register reg);
179   void Push(MacroAssembler* masm);
180   void MoveToSlot(MacroAssembler* masm, SlotLocation* loc);
181 
182 #ifdef DEBUG
183   void Print();
184 #endif
185 
186  private:
187   Handle<Object> handle_;
188 };
189 
190 
191 // Locations are values that can be stored into ('lvalues').
192 class Location : public Value {
193  public:
~Location()194   virtual ~Location() {}
195 
196   // Static factory function returning the singleton nowhere location.
Nowhere()197   static Location* Nowhere() {
198     return CfgGlobals::current()->nowhere();
199   }
200 
201   // Support for fast-compilation mode:
202 
203   // Assumes temporaries have been allocated.
204   virtual void Get(MacroAssembler* masm, Register reg) = 0;
205 
206   // Store the value in a register to the location.  Assumes temporaries
207   // have been allocated.
208   virtual void Set(MacroAssembler* masm, Register reg) = 0;
209 
210   // Assumes temporaries have been allocated, and if the value is a
211   // temporary it was not allocated to the stack.
212   virtual void Push(MacroAssembler* masm) = 0;
213 
214   // Emit code to move a value into this location.
215   virtual void Move(MacroAssembler* masm, Value* value) = 0;
216 
217 #ifdef DEBUG
218   virtual void Print() = 0;
219 #endif
220 };
221 
222 
223 // Nowhere is a special (singleton) location that indicates the value of a
224 // computation is not needed (though its side effects are).
225 class Nowhere : public Location {
226  public:
227   // We should not try to emit code to read Nowhere.
Get(MacroAssembler * masm,Register reg)228   void Get(MacroAssembler* masm, Register reg) { UNREACHABLE(); }
Push(MacroAssembler * masm)229   void Push(MacroAssembler* masm) { UNREACHABLE(); }
MoveToSlot(MacroAssembler * masm,SlotLocation * loc)230   void MoveToSlot(MacroAssembler* masm, SlotLocation* loc) { UNREACHABLE(); }
231 
232   // Setting Nowhere is ignored.
Set(MacroAssembler * masm,Register reg)233   void Set(MacroAssembler* masm, Register reg) {}
Move(MacroAssembler * masm,Value * value)234   void Move(MacroAssembler* masm, Value* value) {}
235 
236 #ifdef DEBUG
237   void Print();
238 #endif
239 
240  private:
Nowhere()241   Nowhere() {}
242 
243   friend class CfgGlobals;
244 };
245 
246 
247 // SlotLocations represent parameters and stack-allocated (i.e.,
248 // non-context) local variables.
249 class SlotLocation : public Location {
250  public:
SlotLocation(Slot::Type type,int index)251   SlotLocation(Slot::Type type, int index) : type_(type), index_(index) {}
252 
253   // Cast accessor.
cast(Value * value)254   static SlotLocation* cast(Value* value) {
255     ASSERT(value->is_slot());
256     return reinterpret_cast<SlotLocation*>(value);
257   }
258 
259   // Accessors.
type()260   Slot::Type type() { return type_; }
index()261   int index() { return index_; }
262 
263   // Predicates.
is_slot()264   bool is_slot() { return true; }
265 
266   // Support for fast-compilation mode.
267   void Get(MacroAssembler* masm, Register reg);
268   void Set(MacroAssembler* masm, Register reg);
269   void Push(MacroAssembler* masm);
270   void Move(MacroAssembler* masm, Value* value);
271   void MoveToSlot(MacroAssembler* masm, SlotLocation* loc);
272 
273 #ifdef DEBUG
274   void Print();
275 #endif
276 
277  private:
278   Slot::Type type_;
279   int index_;
280 };
281 
282 
283 // TempLocations represent compiler generated temporaries.  They are
284 // allocated to registers or memory either before code generation (in the
285 // optimized-for-speed compiler) or on the fly during code generation (in
286 // the optimized-for-space compiler).
287 class TempLocation : public Location {
288  public:
289   // Fast-compilation mode allocation decisions.
290   enum Where {
291     NOT_ALLOCATED,  // Not yet allocated.
292     ACCUMULATOR,    // Allocated to the dedicated accumulator register.
293     STACK           //   "   "   "   "  stack.
294   };
295 
TempLocation()296   TempLocation() : where_(NOT_ALLOCATED) {
297 #ifdef DEBUG
298     number_ = -1;
299 #endif
300   }
301 
302   // Cast accessor.
cast(Value * value)303   static TempLocation* cast(Value* value) {
304     ASSERT(value->is_temporary());
305     return reinterpret_cast<TempLocation*>(value);
306   }
307 
308   // Accessors.
where()309   Where where() { return where_; }
set_where(Where where)310   void set_where(Where where) {
311     ASSERT(where_ == TempLocation::NOT_ALLOCATED);
312     where_ = where;
313   }
314 
315   // Predicates.
is_on_stack()316   bool is_on_stack() { return where_ == STACK; }
is_temporary()317   bool is_temporary() { return true; }
318 
319   // Support for fast-compilation mode.  Assume the temp has been allocated.
320   void Get(MacroAssembler* masm, Register reg);
321   void Set(MacroAssembler* masm, Register reg);
322   void Push(MacroAssembler* masm);
323   void Move(MacroAssembler* masm, Value* value);
324   void MoveToSlot(MacroAssembler* masm, SlotLocation* loc);
325 
326 #ifdef DEBUG
number()327   int number() {
328     if (number_ == -1) number_ = CfgGlobals::current()->next_temp_number();
329     return number_;
330   }
331 
332   void Print();
333 #endif
334 
335  private:
336   Where where_;
337 
338 #ifdef DEBUG
339   int number_;
340 #endif
341 };
342 
343 
344 // Instructions are computations.  The represent non-trivial source
345 // expressions: typically ones that have side effects and require code to
346 // be generated.
347 class Instruction : public ZoneObject {
348  public:
349   // Accessors.
location()350   Location* location() { return location_; }
set_location(Location * location)351   void set_location(Location* location) { location_ = location; }
352 
353   // Support for fast-compilation mode:
354 
355   // Emit code to perform the instruction.
356   virtual void Compile(MacroAssembler* masm) = 0;
357 
358   // Allocate a temporary which is the result of the immediate predecessor
359   // instruction.  It is allocated to the accumulator register if it is used
360   // as an operand to this instruction, otherwise to the stack.
361   virtual void FastAllocate(TempLocation* temp) = 0;
362 
363 #ifdef DEBUG
364   virtual void Print() = 0;
365 #endif
366 
367  protected:
368   // Every instruction has a location where its result is stored (which may
369   // be Nowhere).
Instruction(Location * location)370   explicit Instruction(Location* location) : location_(location) {}
371 
~Instruction()372   virtual ~Instruction() {}
373 
374   Location* location_;
375 };
376 
377 
378 // Base class of instructions that have no input operands.
379 class ZeroOperandInstruction : public Instruction {
380  public:
381   // Support for fast-compilation mode:
382   virtual void Compile(MacroAssembler* masm) = 0;
383   void FastAllocate(TempLocation* temp);
384 
385 #ifdef DEBUG
386   // Printing support: print the operands (nothing).
Print()387   virtual void Print() {}
388 #endif
389 
390  protected:
ZeroOperandInstruction(Location * loc)391   explicit ZeroOperandInstruction(Location* loc) : Instruction(loc) {}
392 };
393 
394 
395 // Base class of instructions that have a single input operand.
396 class OneOperandInstruction : public Instruction {
397  public:
398   // Support for fast-compilation mode:
399   virtual void Compile(MacroAssembler* masm) = 0;
400   void FastAllocate(TempLocation* temp);
401 
402 #ifdef DEBUG
403   // Printing support: print the operands.
404   virtual void Print();
405 #endif
406 
407  protected:
OneOperandInstruction(Location * loc,Value * value)408   OneOperandInstruction(Location* loc, Value* value)
409       : Instruction(loc), value_(value) {
410   }
411 
412   Value* value_;
413 };
414 
415 
416 // Base class of instructions that have two input operands.
417 class TwoOperandInstruction : public Instruction {
418  public:
419   // Support for fast-compilation mode:
420   virtual void Compile(MacroAssembler* masm) = 0;
421   void FastAllocate(TempLocation* temp);
422 
423 #ifdef DEBUG
424   // Printing support: print the operands.
425   virtual void Print();
426 #endif
427 
428  protected:
TwoOperandInstruction(Location * loc,Value * value0,Value * value1)429   TwoOperandInstruction(Location* loc, Value* value0, Value* value1)
430       : Instruction(loc), value0_(value0), value1_(value1) {
431   }
432 
433   Value* value0_;
434   Value* value1_;
435 };
436 
437 
438 // A phantom instruction that indicates the start of a statement.  It
439 // causes the statement position to be recorded in the relocation
440 // information but generates no code.
441 class PositionInstr : public ZeroOperandInstruction {
442  public:
PositionInstr(int pos)443   explicit PositionInstr(int pos)
444       : ZeroOperandInstruction(CfgGlobals::current()->nowhere()), pos_(pos) {
445   }
446 
447   // Support for fast-compilation mode.
448   void Compile(MacroAssembler* masm);
449 
450   // This should not be called.  The last instruction of the previous
451   // statement should not have a temporary as its location.
FastAllocate(TempLocation * temp)452   void FastAllocate(TempLocation* temp) { UNREACHABLE(); }
453 
454 #ifdef DEBUG
455   // Printing support.  Print nothing.
Print()456   void Print() {}
457 #endif
458 
459  private:
460   int pos_;
461 };
462 
463 
464 // Move a value to a location.
465 class MoveInstr : public OneOperandInstruction {
466  public:
MoveInstr(Location * loc,Value * value)467   MoveInstr(Location* loc, Value* value)
468       : OneOperandInstruction(loc, value) {
469   }
470 
471   // Accessors.
value()472   Value* value() { return value_; }
473 
474   // Support for fast-compilation mode.
475   void Compile(MacroAssembler* masm);
476 
477 #ifdef DEBUG
478   // Printing support.
479   void Print();
480 #endif
481 };
482 
483 
484 // Load a property from a receiver, leaving the result in a location.
485 class PropLoadInstr : public TwoOperandInstruction {
486  public:
PropLoadInstr(Location * loc,Value * object,Value * key)487   PropLoadInstr(Location* loc, Value* object, Value* key)
488       : TwoOperandInstruction(loc, object, key) {
489   }
490 
491   // Accessors.
object()492   Value* object() { return value0_; }
key()493   Value* key() { return value1_; }
494 
495   // Support for fast-compilation mode.
496   void Compile(MacroAssembler* masm);
497 
498 #ifdef DEBUG
499   void Print();
500 #endif
501 };
502 
503 
504 // Perform a (non-short-circuited) binary operation on a pair of values,
505 // leaving the result in a location.
506 class BinaryOpInstr : public TwoOperandInstruction {
507  public:
BinaryOpInstr(Location * loc,Token::Value op,Value * left,Value * right)508   BinaryOpInstr(Location* loc, Token::Value op, Value* left, Value* right)
509       : TwoOperandInstruction(loc, left, right), op_(op) {
510   }
511 
512   // Accessors.
left()513   Value* left() { return value0_; }
right()514   Value* right() { return value1_; }
op()515   Token::Value op() { return op_; }
516 
517   // Support for fast-compilation mode.
518   void Compile(MacroAssembler* masm);
519 
520 #ifdef DEBUG
521   void Print();
522 #endif
523 
524  private:
525   Token::Value op_;
526 };
527 
528 
529 // Return a value.  Has the side effect of moving its value into the return
530 // value register.  Can only occur as the last instruction in an instruction
531 // block, and implies that the block is closed (cannot have instructions
532 // appended or graph fragments concatenated to the end) and that the block's
533 // successor is the global exit node for the current function.
534 class ReturnInstr : public OneOperandInstruction {
535  public:
ReturnInstr(Value * value)536   explicit ReturnInstr(Value* value)
537       : OneOperandInstruction(CfgGlobals::current()->nowhere(), value) {
538   }
539 
~ReturnInstr()540   virtual ~ReturnInstr() {}
541 
542   // Accessors.
value()543   Value* value() { return value_; }
544 
545   // Support for fast-compilation mode.
546   void Compile(MacroAssembler* masm);
547 
548 #ifdef DEBUG
549   void Print();
550 #endif
551 };
552 
553 
554 // Nodes make up control-flow graphs.
555 class CfgNode : public ZoneObject {
556  public:
CfgNode()557   CfgNode() : is_marked_(false) {
558 #ifdef DEBUG
559     number_ = -1;
560 #endif
561   }
562 
~CfgNode()563   virtual ~CfgNode() {}
564 
565   // Because CFGs contain cycles, nodes support marking during traversal
566   // (e.g., for printing or compilation).  The traversal functions will mark
567   // unmarked nodes and backtrack if they encounter a marked one.  After a
568   // traversal, the graph should be explicitly unmarked by calling Unmark on
569   // the entry node.
is_marked()570   bool is_marked() { return is_marked_; }
571   virtual void Unmark() = 0;
572 
573   // Predicates:
574 
575   // True if the node is an instruction block.
is_block()576   virtual bool is_block() { return false; }
577 
578   // Support for fast-compilation mode.  Emit the instructions or control
579   // flow represented by the node.
580   virtual void Compile(MacroAssembler* masm) = 0;
581 
582 #ifdef DEBUG
number()583   int number() {
584     if (number_ == -1) number_ = CfgGlobals::current()->next_node_number();
585     return number_;
586   }
587 
588   virtual void Print() = 0;
589 #endif
590 
591  protected:
592   bool is_marked_;
593 
594 #ifdef DEBUG
595   int number_;
596 #endif
597 };
598 
599 
600 // A block is a single-entry, single-exit block of instructions.
601 class InstructionBlock : public CfgNode {
602  public:
InstructionBlock()603   InstructionBlock() : successor_(NULL), instructions_(4) {}
604 
~InstructionBlock()605   virtual ~InstructionBlock() {}
606 
607   void Unmark();
608 
609   // Cast accessor.
cast(CfgNode * node)610   static InstructionBlock* cast(CfgNode* node) {
611     ASSERT(node->is_block());
612     return reinterpret_cast<InstructionBlock*>(node);
613   }
614 
is_block()615   bool is_block() { return true; }
616 
617   // Accessors.
successor()618   CfgNode* successor() { return successor_; }
619 
set_successor(CfgNode * succ)620   void set_successor(CfgNode* succ) {
621     ASSERT(successor_ == NULL);
622     successor_ = succ;
623   }
624 
instructions()625   ZoneList<Instruction*>* instructions() { return &instructions_; }
626 
627   // Support for fast-compilation mode.
628   void Compile(MacroAssembler* masm);
629 
630   // Add an instruction to the end of the block.
Append(Instruction * instr)631   void Append(Instruction* instr) { instructions_.Add(instr); }
632 
633 #ifdef DEBUG
634   void Print();
635 #endif
636 
637  private:
638   CfgNode* successor_;
639   ZoneList<Instruction*> instructions_;
640 };
641 
642 
643 // An entry node (one per function).
644 class EntryNode : public CfgNode {
645  public:
EntryNode(InstructionBlock * succ)646   explicit EntryNode(InstructionBlock* succ) : successor_(succ) {}
647 
~EntryNode()648   virtual ~EntryNode() {}
649 
650   void Unmark();
651 
652   // Support for fast-compilation mode.
653   void Compile(MacroAssembler* masm);
654 
655 #ifdef DEBUG
656   void Print();
657 #endif
658 
659  private:
660   InstructionBlock* successor_;
661 };
662 
663 
664 // An exit node (one per function).
665 class ExitNode : public CfgNode {
666  public:
ExitNode()667   ExitNode() {}
668 
~ExitNode()669   virtual ~ExitNode() {}
670 
671   void Unmark();
672 
673   // Support for fast-compilation mode.
674   void Compile(MacroAssembler* masm);
675 
676 #ifdef DEBUG
677   void Print();
678 #endif
679 };
680 
681 
682 // A CFG consists of a linked structure of nodes.  Nodes are linked by
683 // pointing to their successors, always beginning with a (single) entry node
684 // (not necessarily of type EntryNode).  If it is still possible to add
685 // nodes to the end of the graph (i.e., there is a (single) path that does
686 // not end with the global exit node), then the CFG has an exit node as
687 // well.
688 //
689 // The empty CFG is represented by a NULL entry and a NULL exit.
690 //
691 // We use the term 'open fragment' to mean a CFG whose entry and exits are
692 // both instruction blocks.  It is always possible to add instructions and
693 // nodes to the beginning or end of an open fragment.
694 //
695 // We use the term 'closed fragment' to mean a CFG whose entry is an
696 // instruction block and whose exit is NULL (all paths go to the global
697 // exit).
698 //
699 // We use the term 'fragment' to refer to a CFG that is known to be an open
700 // or closed fragment.
701 class Cfg : public ZoneObject {
702  public:
703   // Create an empty CFG fragment.
Cfg()704   Cfg() : entry_(NULL), exit_(NULL) {}
705 
706   // Build the CFG for a function.  The returned CFG begins with an
707   // EntryNode and all paths end with the ExitNode.
708   static Cfg* Build();
709 
710   // The entry and exit nodes of the CFG (not necessarily EntryNode and
711   // ExitNode).
entry()712   CfgNode* entry() { return entry_; }
exit()713   CfgNode* exit() { return exit_; }
714 
715   // True if the CFG has no nodes.
is_empty()716   bool is_empty() { return entry_ == NULL; }
717 
718   // True if the CFG has an available exit node (i.e., it can be appended or
719   // concatenated to).
has_exit()720   bool has_exit() { return exit_ != NULL; }
721 
722   // Add an EntryNode to a CFG fragment.  It is no longer a fragment
723   // (instructions can no longer be prepended).
724   void PrependEntryNode();
725 
726   // Append an instruction to the end of an open fragment.
727   void Append(Instruction* instr);
728 
729   // Appends a return instruction to the end of an open fragment and make
730   // it a closed fragment (the exit's successor becomes global exit node).
731   void AppendReturnInstruction(Value* value);
732 
733   // Glue an other CFG fragment to the end of this (open) fragment.
734   void Concatenate(Cfg* other);
735 
736   // Support for compilation.  Compile the entire CFG.
737   Handle<Code> Compile(Handle<Script> script);
738 
739 #ifdef DEBUG
740   // Support for printing.
741   void Print();
742 #endif
743 
744  private:
745   // Entry and exit nodes.
746   CfgNode* entry_;
747   CfgNode* exit_;
748 };
749 
750 
751 // An implementation of a set of locations (currently slot locations), most
752 // of the operations are destructive.
753 class LocationSet BASE_EMBEDDED {
754  public:
755   // Construct an empty location set.
LocationSet()756   LocationSet() : parameters_(0), locals_(0) {}
757 
758   // Raw accessors.
parameters()759   uintptr_t parameters() { return parameters_; }
locals()760   uintptr_t locals() { return locals_; }
761 
762   // Make this the empty set.
Empty()763   void Empty() {
764     parameters_ = locals_ = 0;
765   }
766 
767   // Insert an element.
AddElement(SlotLocation * location)768   void AddElement(SlotLocation* location) {
769     if (location->type() == Slot::PARAMETER) {
770       // Parameter indexes begin with -1 ('this').
771       ASSERT(location->index() < kBitsPerPointer - 1);
772       parameters_ |= (1 << (location->index() + 1));
773     } else {
774       ASSERT(location->type() == Slot::LOCAL);
775       ASSERT(location->index() < kBitsPerPointer);
776       locals_ |= (1 << location->index());
777     }
778   }
779 
780   // (Destructively) compute the union with another set.
Union(LocationSet * other)781   void Union(LocationSet* other) {
782     parameters_ |= other->parameters();
783     locals_ |= other->locals();
784   }
785 
Contains(SlotLocation * location)786   bool Contains(SlotLocation* location) {
787     if (location->type() == Slot::PARAMETER) {
788       ASSERT(location->index() < kBitsPerPointer - 1);
789       return (parameters_ & (1 << (location->index() + 1)));
790     } else {
791       ASSERT(location->type() == Slot::LOCAL);
792       ASSERT(location->index() < kBitsPerPointer);
793       return (locals_ & (1 << location->index()));
794     }
795   }
796 
797  private:
798   uintptr_t parameters_;
799   uintptr_t locals_;
800 };
801 
802 
803 // An ExpressionCfgBuilder traverses an expression and returns an open CFG
804 // fragment (currently a possibly empty list of instructions represented by
805 // a singleton instruction block) and the expression's value.
806 //
807 // Failure to build the CFG is indicated by a NULL CFG.
808 class ExpressionCfgBuilder : public AstVisitor {
809  public:
ExpressionCfgBuilder()810   ExpressionCfgBuilder() : destination_(NULL), value_(NULL), graph_(NULL) {}
811 
812   // Result accessors.
value()813   Value* value() { return value_; }
graph()814   Cfg* graph() { return graph_; }
assigned_vars()815   LocationSet* assigned_vars() { return &assigned_vars_; }
816 
817   // Build the cfg for an expression and remember its value.  The
818   // destination is a 'hint' where the value should go which may be ignored.
819   // NULL is used to indicate no preference.
820   //
821   // Concretely, if the expression needs to generate a temporary for its
822   // value, it should use the passed destination or generate one if NULL.
Build(Expression * expr,Location * destination)823   void Build(Expression* expr, Location* destination) {
824     value_ = NULL;
825     graph_ = new Cfg();
826     assigned_vars_.Empty();
827     destination_ = destination;
828     Visit(expr);
829   }
830 
831   // AST node visitors.
832 #define DECLARE_VISIT(type) void Visit##type(type* node);
833   AST_NODE_LIST(DECLARE_VISIT)
834 #undef DECLARE_VISIT
835 
836  private:
837   // State for the visitor.  Input parameter:
838   Location* destination_;
839 
840   // Output parameters:
841   Value* value_;
842   Cfg* graph_;
843   LocationSet assigned_vars_;
844 };
845 
846 
847 // A StatementCfgBuilder maintains a CFG fragment accumulator.  When it
848 // visits a statement, it concatenates the CFG for the statement to the end
849 // of the accumulator.
850 class StatementCfgBuilder : public AstVisitor {
851  public:
StatementCfgBuilder()852   StatementCfgBuilder() : graph_(new Cfg()) {}
853 
graph()854   Cfg* graph() { return graph_; }
855 
856   void VisitStatements(ZoneList<Statement*>* stmts);
857 
858   // AST node visitors.
859 #define DECLARE_VISIT(type) void Visit##type(type* node);
860   AST_NODE_LIST(DECLARE_VISIT)
861 #undef DECLARE_VISIT
862 
863  private:
864   // State for the visitor.  Input/output parameter:
865   Cfg* graph_;
866 };
867 
868 
869 } }  // namespace v8::internal
870 
871 #endif  // V8_CFG_H_
872