• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2008 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_JUMP_TARGET_H_
29 #define V8_JUMP_TARGET_H_
30 
31 namespace v8 {
32 namespace internal {
33 
34 // Forward declarations.
35 class FrameElement;
36 class Result;
37 class VirtualFrame;
38 
39 // -------------------------------------------------------------------------
40 // Jump targets
41 //
42 // A jump target is an abstraction of a basic-block entry in generated
43 // code.  It collects all the virtual frames reaching the block by
44 // forward jumps and pairs them with labels for the merge code along
45 // all forward-reaching paths.  When bound, an expected frame for the
46 // block is determined and code is generated to merge to the expected
47 // frame.  For backward jumps, the merge code is generated at the edge
48 // leaving the predecessor block.
49 //
50 // A jump target must have been reached via control flow (either by
51 // jumping, branching, or falling through) at the time it is bound.
52 // In particular, this means that at least one of the control-flow
53 // graph edges reaching the target must be a forward edge.
54 
55 class JumpTarget : public ZoneObject {  // Shadows are dynamically allocated.
56  public:
57   // Forward-only jump targets can only be reached by forward CFG edges.
58   enum Directionality { FORWARD_ONLY, BIDIRECTIONAL };
59 
60   // Construct a jump target used to generate code and to provide
61   // access to a current frame.
JumpTarget(Directionality direction)62   explicit JumpTarget(Directionality direction)
63       : direction_(direction),
64         reaching_frames_(0),
65         merge_labels_(0),
66         entry_frame_(NULL) {
67   }
68 
69   // Construct a jump target.
JumpTarget()70   JumpTarget()
71       : direction_(FORWARD_ONLY),
72         reaching_frames_(0),
73         merge_labels_(0),
74         entry_frame_(NULL) {
75   }
76 
~JumpTarget()77   virtual ~JumpTarget() {}
78 
79   // Set the direction of the jump target.
set_direction(Directionality direction)80   virtual void set_direction(Directionality direction) {
81     direction_ = direction;
82   }
83 
84   // Treat the jump target as a fresh one.  The state is reset.
85   void Unuse();
86 
87   inline CodeGenerator* cgen();
88 
entry_label()89   Label* entry_label() { return &entry_label_; }
90 
entry_frame()91   VirtualFrame* entry_frame() const { return entry_frame_; }
set_entry_frame(VirtualFrame * frame)92   void set_entry_frame(VirtualFrame* frame) {
93     entry_frame_ = frame;
94   }
95 
96   // Predicates testing the state of the encapsulated label.
is_bound()97   bool is_bound() const { return entry_label_.is_bound(); }
is_linked()98   bool is_linked() const {
99     return !is_bound() && !reaching_frames_.is_empty();
100   }
is_unused()101   bool is_unused() const {
102     // This is !is_bound() && !is_linked().
103     return !is_bound() && reaching_frames_.is_empty();
104   }
105 
106   // Emit a jump to the target.  There must be a current frame at the
107   // jump and there will be no current frame after the jump.
108   virtual void Jump();
109   virtual void Jump(Result* arg);
110 
111   // Emit a conditional branch to the target.  There must be a current
112   // frame at the branch.  The current frame will fall through to the
113   // code after the branch.
114   virtual void Branch(Condition cc, Hint hint = no_hint);
115   virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
116 
117   // Bind a jump target.  If there is no current frame at the binding
118   // site, there must be at least one frame reaching via a forward
119   // jump.
120   virtual void Bind();
121   virtual void Bind(Result* arg);
122 
123   // Emit a call to a jump target.  There must be a current frame at
124   // the call.  The frame at the target is the same as the current
125   // frame except for an extra return address on top of it.  The frame
126   // after the call is the same as the frame before the call.
127   void Call();
128 
set_compiling_deferred_code(bool flag)129   static void set_compiling_deferred_code(bool flag) {
130     compiling_deferred_code_ = flag;
131   }
132 
133  protected:
134   // Directionality flag set at initialization time.
135   Directionality direction_;
136 
137   // A list of frames reaching this block via forward jumps.
138   ZoneList<VirtualFrame*> reaching_frames_;
139 
140   // A parallel list of labels for merge code.
141   ZoneList<Label> merge_labels_;
142 
143   // The frame used on entry to the block and expected at backward
144   // jumps to the block.  Set when the jump target is bound, but may
145   // or may not be set for forward-only blocks.
146   VirtualFrame* entry_frame_;
147 
148   // The actual entry label of the block.
149   Label entry_label_;
150 
151   // Implementations of Jump, Branch, and Bind with all arguments and
152   // return values using the virtual frame.
153   void DoJump();
154   void DoBranch(Condition cc, Hint hint);
155   void DoBind();
156 
157  private:
158   static bool compiling_deferred_code_;
159 
160   // Add a virtual frame reaching this labeled block via a forward jump,
161   // and a corresponding merge code label.
162   void AddReachingFrame(VirtualFrame* frame);
163 
164   // Perform initialization required during entry frame computation
165   // after setting the virtual frame element at index in frame to be
166   // target.
167   inline void InitializeEntryElement(int index, FrameElement* target);
168 
169   // Compute a frame to use for entry to this block.
170   void ComputeEntryFrame();
171 
172   DISALLOW_COPY_AND_ASSIGN(JumpTarget);
173 };
174 
175 
176 // -------------------------------------------------------------------------
177 // Break targets
178 //
179 // A break target is a jump target that can be used to break out of a
180 // statement that keeps extra state on the stack (eg, for/in or
181 // try/finally).  They know the expected stack height at the target
182 // and will drop state from nested statements as part of merging.
183 //
184 // Break targets are used for return, break, and continue targets.
185 
186 class BreakTarget : public JumpTarget {
187  public:
188   // Construct a break target.
BreakTarget()189   BreakTarget() {}
190 
~BreakTarget()191   virtual ~BreakTarget() {}
192 
193   // Set the direction of the break target.
194   virtual void set_direction(Directionality direction);
195 
196   // Copy the state of this break target to the destination.  The
197   // lists of forward-reaching frames and merge-point labels are
198   // copied.  All virtual frame pointers are copied, not the
199   // pointed-to frames.  The previous state of the destination is
200   // overwritten, without deallocating pointed-to virtual frames.
201   void CopyTo(BreakTarget* destination);
202 
203   // Emit a jump to the target.  There must be a current frame at the
204   // jump and there will be no current frame after the jump.
205   virtual void Jump();
206   virtual void Jump(Result* arg);
207 
208   // Emit a conditional branch to the target.  There must be a current
209   // frame at the branch.  The current frame will fall through to the
210   // code after the branch.
211   virtual void Branch(Condition cc, Hint hint = no_hint);
212   virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
213 
214   // Bind a break target.  If there is no current frame at the binding
215   // site, there must be at least one frame reaching via a forward
216   // jump.
217   virtual void Bind();
218   virtual void Bind(Result* arg);
219 
220   // Setter for expected height.
set_expected_height(int expected)221   void set_expected_height(int expected) { expected_height_ = expected; }
222 
223  private:
224   // The expected height of the expression stack where the target will
225   // be bound, statically known at initialization time.
226   int expected_height_;
227 
228   DISALLOW_COPY_AND_ASSIGN(BreakTarget);
229 };
230 
231 
232 // -------------------------------------------------------------------------
233 // Shadow break targets
234 //
235 // A shadow break target represents a break target that is temporarily
236 // shadowed by another one (represented by the original during
237 // shadowing).  They are used to catch jumps to labels in certain
238 // contexts, e.g. try blocks.  After shadowing ends, the formerly
239 // shadowed target is again represented by the original and the
240 // ShadowTarget can be used as a jump target in its own right,
241 // representing the formerly shadowing target.
242 
243 class ShadowTarget : public BreakTarget {
244  public:
245   // Construct a shadow jump target.  After construction the shadow
246   // target object holds the state of the original target, and the
247   // original target is actually a fresh one that intercepts control
248   // flow intended for the shadowed one.
249   explicit ShadowTarget(BreakTarget* shadowed);
250 
~ShadowTarget()251   virtual ~ShadowTarget() {}
252 
253   // End shadowing.  After shadowing ends, the original jump target
254   // again gives access to the formerly shadowed target and the shadow
255   // target object gives access to the formerly shadowing target.
256   void StopShadowing();
257 
258   // During shadowing, the currently shadowing target.  After
259   // shadowing, the target that was shadowed.
other_target()260   BreakTarget* other_target() const { return other_target_; }
261 
262  private:
263   // During shadowing, the currently shadowing target.  After
264   // shadowing, the target that was shadowed.
265   BreakTarget* other_target_;
266 
267 #ifdef DEBUG
268   bool is_shadowing_;
269 #endif
270 
271   DISALLOW_COPY_AND_ASSIGN(ShadowTarget);
272 };
273 
274 
275 } }  // namespace v8::internal
276 
277 #endif  // V8_JUMP_TARGET_H_
278