• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
6 #define V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
7 
8 #include "src/interpreter/bytecode-array-builder.h"
9 
10 #include "src/zone-containers.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace interpreter {
15 
16 class ControlFlowBuilder BASE_EMBEDDED {
17  public:
ControlFlowBuilder(BytecodeArrayBuilder * builder)18   explicit ControlFlowBuilder(BytecodeArrayBuilder* builder)
19       : builder_(builder) {}
~ControlFlowBuilder()20   virtual ~ControlFlowBuilder() {}
21 
22  protected:
builder()23   BytecodeArrayBuilder* builder() const { return builder_; }
24 
25  private:
26   BytecodeArrayBuilder* builder_;
27 
28   DISALLOW_COPY_AND_ASSIGN(ControlFlowBuilder);
29 };
30 
31 class BreakableControlFlowBuilder : public ControlFlowBuilder {
32  public:
BreakableControlFlowBuilder(BytecodeArrayBuilder * builder)33   explicit BreakableControlFlowBuilder(BytecodeArrayBuilder* builder)
34       : ControlFlowBuilder(builder),
35         break_sites_(builder->zone()) {}
36   virtual ~BreakableControlFlowBuilder();
37 
38   // This method should be called by the control flow owner before
39   // destruction to update sites that emit jumps for break.
40   void SetBreakTarget(const BytecodeLabel& break_target);
41 
42   // This method is called when visiting break statements in the AST.
43   // Inserts a jump to a unbound label that is patched when the corresponding
44   // SetBreakTarget is called.
Break()45   void Break() { EmitJump(&break_sites_); }
BreakIfTrue()46   void BreakIfTrue() { EmitJumpIfTrue(&break_sites_); }
BreakIfFalse()47   void BreakIfFalse() { EmitJumpIfFalse(&break_sites_); }
BreakIfUndefined()48   void BreakIfUndefined() { EmitJumpIfUndefined(&break_sites_); }
BreakIfNull()49   void BreakIfNull() { EmitJumpIfNull(&break_sites_); }
50 
51  protected:
52   void EmitJump(ZoneVector<BytecodeLabel>* labels);
53   void EmitJump(ZoneVector<BytecodeLabel>* labels, int index);
54   void EmitJumpIfTrue(ZoneVector<BytecodeLabel>* labels);
55   void EmitJumpIfTrue(ZoneVector<BytecodeLabel>* labels, int index);
56   void EmitJumpIfFalse(ZoneVector<BytecodeLabel>* labels);
57   void EmitJumpIfFalse(ZoneVector<BytecodeLabel>* labels, int index);
58   void EmitJumpIfUndefined(ZoneVector<BytecodeLabel>* labels);
59   void EmitJumpIfNull(ZoneVector<BytecodeLabel>* labels);
60 
61   void BindLabels(const BytecodeLabel& target, ZoneVector<BytecodeLabel>* site);
62 
63   // Unbound labels that identify jumps for break statements in the code.
64   ZoneVector<BytecodeLabel> break_sites_;
65 };
66 
67 
68 // Class to track control flow for block statements (which can break in JS).
69 class BlockBuilder final : public BreakableControlFlowBuilder {
70  public:
BlockBuilder(BytecodeArrayBuilder * builder)71   explicit BlockBuilder(BytecodeArrayBuilder* builder)
72       : BreakableControlFlowBuilder(builder) {}
73 
74   void EndBlock();
75 
76  private:
77   BytecodeLabel block_end_;
78 };
79 
80 
81 // A class to help with co-ordinating break and continue statements with
82 // their loop.
83 class LoopBuilder final : public BreakableControlFlowBuilder {
84  public:
LoopBuilder(BytecodeArrayBuilder * builder)85   explicit LoopBuilder(BytecodeArrayBuilder* builder)
86       : BreakableControlFlowBuilder(builder),
87         continue_sites_(builder->zone()) {}
88   ~LoopBuilder();
89 
90   void LoopHeader();
Condition()91   void Condition() { builder()->Bind(&condition_); }
Next()92   void Next() { builder()->Bind(&next_); }
JumpToHeader()93   void JumpToHeader() { builder()->Jump(&loop_header_); }
JumpToHeaderIfTrue()94   void JumpToHeaderIfTrue() { builder()->JumpIfTrue(&loop_header_); }
95   void EndLoop();
96 
97   // This method is called when visiting continue statements in the AST.
98   // Inserts a jump to a unbound label that is patched when the corresponding
99   // SetContinueTarget is called.
Continue()100   void Continue() { EmitJump(&continue_sites_); }
ContinueIfTrue()101   void ContinueIfTrue() { EmitJumpIfTrue(&continue_sites_); }
ContinueIfUndefined()102   void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_sites_); }
ContinueIfNull()103   void ContinueIfNull() { EmitJumpIfNull(&continue_sites_); }
104 
105  private:
106   void SetContinueTarget(const BytecodeLabel& continue_target);
107 
108   BytecodeLabel loop_header_;
109   BytecodeLabel condition_;
110   BytecodeLabel next_;
111   BytecodeLabel loop_end_;
112 
113   // Unbound labels that identify jumps for continue statements in the code.
114   ZoneVector<BytecodeLabel> continue_sites_;
115 };
116 
117 
118 // A class to help with co-ordinating break statements with their switch.
119 class SwitchBuilder final : public BreakableControlFlowBuilder {
120  public:
SwitchBuilder(BytecodeArrayBuilder * builder,int number_of_cases)121   explicit SwitchBuilder(BytecodeArrayBuilder* builder, int number_of_cases)
122       : BreakableControlFlowBuilder(builder),
123         case_sites_(builder->zone()) {
124     case_sites_.resize(number_of_cases);
125   }
126   ~SwitchBuilder();
127 
128   // This method should be called by the SwitchBuilder owner when the case
129   // statement with |index| is emitted to update the case jump site.
130   void SetCaseTarget(int index);
131 
132   // This method is called when visiting case comparison operation for |index|.
133   // Inserts a JumpIfTrue to a unbound label that is patched when the
134   // corresponding SetCaseTarget is called.
Case(int index)135   void Case(int index) { EmitJumpIfTrue(&case_sites_, index); }
136 
137   // This method is called when all cases comparisons have been emitted if there
138   // is a default case statement. Inserts a Jump to a unbound label that is
139   // patched when the corresponding SetCaseTarget is called.
DefaultAt(int index)140   void DefaultAt(int index) { EmitJump(&case_sites_, index); }
141 
142  private:
143   // Unbound labels that identify jumps for case statements in the code.
144   ZoneVector<BytecodeLabel> case_sites_;
145 };
146 
147 }  // namespace interpreter
148 }  // namespace internal
149 }  // namespace v8
150 
151 #endif  // V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
152