OLD | NEW |
1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 class JumpTarget : public ZoneObject { // Shadows are dynamically allocated. | 51 class JumpTarget : public ZoneObject { // Shadows are dynamically allocated. |
52 public: | 52 public: |
53 // Forward-only jump targets can only be reached by forward CFG edges. | 53 // Forward-only jump targets can only be reached by forward CFG edges. |
54 enum Directionality { FORWARD_ONLY, BIDIRECTIONAL }; | 54 enum Directionality { FORWARD_ONLY, BIDIRECTIONAL }; |
55 | 55 |
56 // Construct a jump target with a given code generator used to generate | 56 // Construct a jump target with a given code generator used to generate |
57 // code and to provide access to a current frame. | 57 // code and to provide access to a current frame. |
58 explicit JumpTarget(CodeGenerator* cgen, | 58 explicit JumpTarget(CodeGenerator* cgen, |
59 Directionality direction = FORWARD_ONLY); | 59 Directionality direction = FORWARD_ONLY); |
60 | 60 |
61 // Construct a jump target without a code generator. A code generator | |
62 // must be supplied before using the jump target as a label. This is | |
63 // useful, eg, when jump targets are embedded in AST nodes. | |
64 JumpTarget(); | |
65 | |
66 virtual ~JumpTarget() { Unuse(); } | 61 virtual ~JumpTarget() { Unuse(); } |
67 | 62 |
68 // Supply a code generator and directionality to an already | |
69 // constructed jump target. This function expects to be given a | |
70 // non-null code generator, and to be called only when the code | |
71 // generator is not yet set. | |
72 void Initialize(CodeGenerator* cgen, | |
73 Directionality direction = FORWARD_ONLY); | |
74 | |
75 // Accessors. | 63 // Accessors. |
76 CodeGenerator* code_generator() const { return cgen_; } | 64 CodeGenerator* code_generator() const { return cgen_; } |
77 | 65 |
78 Label* entry_label() { return &entry_label_; } | 66 Label* entry_label() { return &entry_label_; } |
79 | 67 |
80 VirtualFrame* entry_frame() const { return entry_frame_; } | 68 VirtualFrame* entry_frame() const { return entry_frame_; } |
81 void set_entry_frame(VirtualFrame* frame) { | 69 void set_entry_frame(VirtualFrame* frame) { |
82 entry_frame_ = frame; | 70 entry_frame_ = frame; |
83 } | 71 } |
84 | 72 |
| 73 void make_bidirectional() { direction_ = BIDIRECTIONAL; } |
| 74 |
85 // Predicates testing the state of the encapsulated label. | 75 // Predicates testing the state of the encapsulated label. |
86 bool is_bound() const { return is_bound_; } | 76 bool is_bound() const { return is_bound_; } |
87 bool is_linked() const { return is_linked_; } | 77 bool is_linked() const { return is_linked_; } |
88 bool is_unused() const { return !is_bound() && !is_linked(); } | 78 bool is_unused() const { return !is_bound() && !is_linked(); } |
89 | 79 |
90 // Treat the jump target as a fresh one. The expected frame if any | 80 // Treat the jump target as a fresh one. The expected frame if any |
91 // will be deallocated and there should be no dangling jumps to the | 81 // will be deallocated and there should be no dangling jumps to the |
92 // target (thus no reaching frames). | 82 // target (thus no reaching frames). |
93 void Unuse(); | 83 void Unuse(); |
94 | 84 |
95 // Reset the internal state of this jump target. Pointed-to virtual | 85 // Reset the internal state of this jump target. Pointed-to virtual |
96 // frames are not deallocated and dangling jumps to the target are | 86 // frames are not deallocated and dangling jumps to the target are |
97 // left dangling. | 87 // left dangling. |
98 void Reset(); | 88 void Reset(); |
99 | 89 |
100 // Copy the state of this jump target to the destination. The lists | |
101 // of forward-reaching frames and merge-point labels are copied. | |
102 // All virtual frame pointers are copied, not the pointed-to frames. | |
103 // The previous state of the destination is overwritten, without | |
104 // deallocating pointed-to virtual frames. | |
105 void CopyTo(JumpTarget* destination); | |
106 | |
107 // Emit a jump to the target. There must be a current frame at the | 90 // Emit a jump to the target. There must be a current frame at the |
108 // jump and there will be no current frame after the jump. | 91 // jump and there will be no current frame after the jump. |
109 void Jump(); | 92 void Jump(); |
110 void Jump(Result* arg); | 93 void Jump(Result* arg); |
111 void Jump(Result* arg0, Result* arg1); | 94 void Jump(Result* arg0, Result* arg1); |
112 void Jump(Result* arg0, Result* arg1, Result* arg2); | 95 void Jump(Result* arg0, Result* arg1, Result* arg2); |
113 | 96 |
114 // Emit a conditional branch to the target. There must be a current | 97 // Emit a conditional branch to the target. There must be a current |
115 // frame at the branch. The current frame will fall through to the | 98 // frame at the branch. The current frame will fall through to the |
116 // code after the branch. | 99 // code after the branch. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 | 146 |
164 static const int kAllElements = -1; // Not a valid number of elements. | 147 static const int kAllElements = -1; // Not a valid number of elements. |
165 | 148 |
166 protected: | 149 protected: |
167 // The code generator gives access to its current frame. | 150 // The code generator gives access to its current frame. |
168 CodeGenerator* cgen_; | 151 CodeGenerator* cgen_; |
169 | 152 |
170 // Used to emit code. | 153 // Used to emit code. |
171 MacroAssembler* masm_; | 154 MacroAssembler* masm_; |
172 | 155 |
173 private: | |
174 // Directionality flag set at initialization time. | 156 // Directionality flag set at initialization time. |
175 Directionality direction_; | 157 Directionality direction_; |
176 | 158 |
177 // A list of frames reaching this block via forward jumps. | 159 // A list of frames reaching this block via forward jumps. |
178 List<VirtualFrame*> reaching_frames_; | 160 List<VirtualFrame*> reaching_frames_; |
179 | 161 |
180 // A parallel list of labels for merge code. | 162 // A parallel list of labels for merge code. |
181 List<Label> merge_labels_; | 163 List<Label> merge_labels_; |
182 | 164 |
183 // The frame used on entry to the block and expected at backward | 165 // The frame used on entry to the block and expected at backward |
184 // jumps to the block. Set when the jump target is bound, but may | 166 // jumps to the block. Set when the jump target is bound, but may |
185 // or may not be set for forward-only blocks. | 167 // or may not be set for forward-only blocks. |
186 VirtualFrame* entry_frame_; | 168 VirtualFrame* entry_frame_; |
187 | 169 |
188 // The actual entry label of the block. | 170 // The actual entry label of the block. |
189 Label entry_label_; | 171 Label entry_label_; |
190 | 172 |
191 // A target is bound if its Bind member function has been called. | 173 // A target is bound if its Bind member function has been called. |
192 // It is linked if it is not bound but its Jump, Branch, or Call | 174 // It is linked if it is not bound but its Jump, Branch, or Call |
193 // member functions have been called. | 175 // member functions have been called. |
194 bool is_bound_; | 176 bool is_bound_; |
195 bool is_linked_; | 177 bool is_linked_; |
196 | 178 |
| 179 private: |
197 // Add a virtual frame reaching this labeled block via a forward | 180 // Add a virtual frame reaching this labeled block via a forward |
198 // jump, and a fresh label for its merge code. | 181 // jump, and a fresh label for its merge code. |
199 void AddReachingFrame(VirtualFrame* frame); | 182 void AddReachingFrame(VirtualFrame* frame); |
200 | 183 |
201 // Choose an element from a pair of frame elements to be in the | 184 // Choose an element from a pair of frame elements to be in the |
202 // expected frame. Return null if they are incompatible. | 185 // expected frame. Return null if they are incompatible. |
203 FrameElement* Combine(FrameElement* left, FrameElement* right); | 186 FrameElement* Combine(FrameElement* left, FrameElement* right); |
204 | 187 |
205 // Compute a frame to use for entry to this block. Mergable | 188 // Compute a frame to use for entry to this block. Mergable |
206 // elements is as described for the Bind function. | 189 // elements is as described for the Bind function. |
207 void ComputeEntryFrame(int mergable_elements); | 190 void ComputeEntryFrame(int mergable_elements); |
208 | 191 |
209 DISALLOW_COPY_AND_ASSIGN(JumpTarget); | 192 DISALLOW_COPY_AND_ASSIGN(JumpTarget); |
210 }; | 193 }; |
211 | 194 |
212 | 195 |
213 // ------------------------------------------------------------------------- | 196 // ------------------------------------------------------------------------- |
214 // Shadow jump targets | 197 // Break targets |
215 // | 198 // |
216 // Shadow jump targets represent a jump target that is temporarily shadowed | 199 // A break target is a jump target that can be used to break out of a |
217 // by another one (represented by the original during shadowing). They are | 200 // statement that keeps extra state on the stack (eg, for/in or |
218 // used to catch jumps to labels in certain contexts, e.g. try blocks. | 201 // try/finally). They know the expected stack height at the target |
219 // After shadowing ends, the formerly shadowed target is again represented | 202 // and will drop state from nested statements as part of merging. |
220 // by the original and the ShadowTarget can be used as a jump target in its | 203 // |
221 // own right, representing the formerly shadowing target. | 204 // Break targets are used for return, break, and continue targets. |
222 | 205 |
223 class ShadowTarget : public JumpTarget { | 206 class BreakTarget : public JumpTarget { |
| 207 public: |
| 208 // Construct a break target without a code generator. A code |
| 209 // generator must be supplied before using the break target as a |
| 210 // label. This is useful, eg, when break targets are embedded in AST |
| 211 // nodes. |
| 212 BreakTarget(); |
| 213 |
| 214 // Supply a code generator and directionality to an already |
| 215 // constructed jump target. This function expects to be given a |
| 216 // non-null code generator, and to be called only when the code |
| 217 // generator is not yet set. |
| 218 void Initialize(CodeGenerator* cgen, |
| 219 Directionality direction = FORWARD_ONLY); |
| 220 |
| 221 // Copy the state of this break target to the destination. The |
| 222 // lists of forward-reaching frames and merge-point labels are |
| 223 // copied. All virtual frame pointers are copied, not the |
| 224 // pointed-to frames. The previous state of the destination is |
| 225 // overwritten, without deallocating pointed-to virtual frames. |
| 226 void CopyTo(BreakTarget* destination); |
| 227 |
| 228 private: |
| 229 DISALLOW_COPY_AND_ASSIGN(BreakTarget); |
| 230 }; |
| 231 |
| 232 |
| 233 // ------------------------------------------------------------------------- |
| 234 // Shadow break targets |
| 235 // |
| 236 // A shadow break target represents a break target that is temporarily |
| 237 // shadowed by another one (represented by the original during |
| 238 // shadowing). They are used to catch jumps to labels in certain |
| 239 // contexts, e.g. try blocks. After shadowing ends, the formerly |
| 240 // shadowed target is again represented by the original and the |
| 241 // ShadowTarget can be used as a jump target in its own right, |
| 242 // representing the formerly shadowing target. |
| 243 |
| 244 class ShadowTarget : public BreakTarget { |
224 public: | 245 public: |
225 // Construct a shadow jump target. After construction the shadow | 246 // Construct a shadow jump target. After construction the shadow |
226 // target object holds the state of the original jump target, and | 247 // target object holds the state of the original target, and the |
227 // the original target is actually a fresh one that intercepts jumps | 248 // original target is actually a fresh one that intercepts control |
228 // intended for the shadowed one. | 249 // flow intended for the shadowed one. |
229 explicit ShadowTarget(JumpTarget* shadowed); | 250 explicit ShadowTarget(BreakTarget* shadowed); |
230 | 251 |
231 virtual ~ShadowTarget() { | 252 virtual ~ShadowTarget() { |
232 ASSERT(!is_shadowing_); | 253 ASSERT(!is_shadowing_); |
233 } | 254 } |
234 | 255 |
235 // End shadowing. After shadowing ends, the original jump target | 256 // End shadowing. After shadowing ends, the original jump target |
236 // again gives access to the formerly shadowed target and the shadow | 257 // again gives access to the formerly shadowed target and the shadow |
237 // target object gives access to the formerly shadowing target. | 258 // target object gives access to the formerly shadowing target. |
238 void StopShadowing(); | 259 void StopShadowing(); |
239 | 260 |
240 // During shadowing, the currently shadowing target. After | 261 // During shadowing, the currently shadowing target. After |
241 // shadowing, the target that was shadowed. | 262 // shadowing, the target that was shadowed. |
242 JumpTarget* other_target() const { return other_target_; } | 263 BreakTarget* other_target() const { return other_target_; } |
243 | 264 |
244 private: | 265 private: |
245 // During shadowing, the currently shadowing target. After | 266 // During shadowing, the currently shadowing target. After |
246 // shadowing, the target that was shadowed. | 267 // shadowing, the target that was shadowed. |
247 JumpTarget* other_target_; | 268 BreakTarget* other_target_; |
248 | 269 |
249 #ifdef DEBUG | 270 #ifdef DEBUG |
250 bool is_shadowing_; | 271 bool is_shadowing_; |
251 #endif | 272 #endif |
252 | 273 |
253 DISALLOW_COPY_AND_ASSIGN(ShadowTarget); | 274 DISALLOW_COPY_AND_ASSIGN(ShadowTarget); |
254 }; | 275 }; |
255 | 276 |
256 | 277 |
257 } } // namespace v8::internal | 278 } } // namespace v8::internal |
258 | 279 |
259 #endif // V8_JUMP_TARGET_H_ | 280 #endif // V8_JUMP_TARGET_H_ |
OLD | NEW |