OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 25 matching lines...) Expand all Loading... |
36 class ExitNode; | 36 class ExitNode; |
37 class Location; | 37 class Location; |
38 | 38 |
39 // Translate a source AST into a control-flow graph (CFG). The CFG contains | 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 | 40 // single-entry, single-exit blocks of straight-line instructions and |
41 // administrative nodes. | 41 // administrative nodes. |
42 // | 42 // |
43 // Instructions are described by the following grammar. | 43 // Instructions are described by the following grammar. |
44 // | 44 // |
45 // <Instruction> ::= | 45 // <Instruction> ::= |
46 // BinaryOpInstr <Location> Token::Value <Value> <Value> | 46 // MoveInstr <Location> <Value> |
47 // | ReturnInstr Effect <Value> | 47 // | BinaryOpInstr <Location> Token::Value <Value> <Value> |
| 48 // | ReturnInstr Nowhere <Value> |
| 49 // | PositionInstr <Int> |
48 // | 50 // |
49 // Values are trivial expressions: | 51 // Values are trivial expressions: |
50 // | 52 // |
51 // <Value> ::= Constant | <Location> | 53 // <Value> ::= Constant | <Location> |
52 // | 54 // |
53 // Locations are storable values ('lvalues'). They can be slots, | 55 // Locations are storable values ('lvalues'). They can be slots, |
54 // compiler-generated temporaries, or the special location 'Effect' | 56 // compiler-generated temporaries, or the special location 'Nowhere' |
55 // indicating that no value is needed. | 57 // indicating that no value is needed. |
56 // | 58 // |
57 // <Location> ::= | 59 // <Location> ::= |
58 // SlotLocation Slot::Type <Index> | 60 // SlotLocation Slot::Type <Index> |
59 // | TempLocation | 61 // | TempLocation |
60 // | Effect | 62 // | Nowhere |
61 | 63 |
62 | 64 |
63 // Administrative nodes: There are several types of 'administrative' nodes | 65 // Administrative nodes: There are several types of 'administrative' nodes |
64 // that do not contain instructions and do not necessarily have a single | 66 // that do not contain instructions and do not necessarily have a single |
65 // predecessor and a single successor. | 67 // predecessor and a single successor. |
66 // | 68 // |
67 // EntryNode: there is a distinguished entry node that has no predecessors | 69 // EntryNode: there is a distinguished entry node that has no predecessors |
68 // and a single successor. | 70 // and a single successor. |
69 // | 71 // |
70 // ExitNode: there is a distinguished exit node that has arbitrarily many | 72 // ExitNode: there is a distinguished exit node that has arbitrarily many |
(...skipping 17 matching lines...) Expand all Loading... |
88 ASSERT(top_ != NULL); | 90 ASSERT(top_ != NULL); |
89 return top_; | 91 return top_; |
90 } | 92 } |
91 | 93 |
92 // The function currently being compiled. | 94 // The function currently being compiled. |
93 FunctionLiteral* fun() { return global_fun_; } | 95 FunctionLiteral* fun() { return global_fun_; } |
94 | 96 |
95 // The shared global exit node for all exits from the function. | 97 // The shared global exit node for all exits from the function. |
96 ExitNode* exit() { return global_exit_; } | 98 ExitNode* exit() { return global_exit_; } |
97 | 99 |
98 // A singleton effect location. | 100 // A singleton. |
99 Location* effect_location() { return effect_; } | 101 Location* nowhere() { return nowhere_; } |
100 | 102 |
101 #ifdef DEBUG | 103 #ifdef DEBUG |
102 int next_node_number() { return node_counter_++; } | 104 int next_node_number() { return node_counter_++; } |
103 int next_temp_number() { return temp_counter_++; } | 105 int next_temp_number() { return temp_counter_++; } |
104 #endif | 106 #endif |
105 | 107 |
106 private: | 108 private: |
107 static CfgGlobals* top_; | 109 static CfgGlobals* top_; |
108 FunctionLiteral* global_fun_; | 110 FunctionLiteral* global_fun_; |
109 ExitNode* global_exit_; | 111 ExitNode* global_exit_; |
110 Location* effect_; | 112 Location* nowhere_; |
111 | 113 |
112 #ifdef DEBUG | 114 #ifdef DEBUG |
113 // Used to number nodes and temporaries when printing. | 115 // Used to number nodes and temporaries when printing. |
114 int node_counter_; | 116 int node_counter_; |
115 int temp_counter_; | 117 int temp_counter_; |
116 #endif | 118 #endif |
117 | 119 |
118 CfgGlobals* previous_; | 120 CfgGlobals* previous_; |
119 }; | 121 }; |
120 | 122 |
121 | 123 |
| 124 class SlotLocation; |
| 125 |
122 // Values represent trivial source expressions: ones with no side effects | 126 // Values represent trivial source expressions: ones with no side effects |
123 // and that do not require code to be generated. | 127 // and that do not require code to be generated. |
124 class Value : public ZoneObject { | 128 class Value : public ZoneObject { |
125 public: | 129 public: |
126 virtual ~Value() {} | 130 virtual ~Value() {} |
127 | 131 |
128 // Predicates: | 132 // Predicates: |
129 | 133 |
130 // True if the value is a temporary allocated to the stack in | 134 // True if the value is a temporary allocated to the stack in |
131 // fast-compilation mode. | 135 // fast-compilation mode. |
132 virtual bool is_on_stack() { return false; } | 136 virtual bool is_on_stack() { return false; } |
133 | 137 |
134 // True if the value is a compiler-generated temporary location. | 138 // True if the value is a compiler-generated temporary location. |
135 virtual bool is_temporary() { return false; } | 139 virtual bool is_temporary() { return false; } |
136 | 140 |
| 141 // True if the value is a slot location. |
| 142 virtual bool is_slot() { return false; } |
| 143 |
137 // Support for fast-compilation mode: | 144 // Support for fast-compilation mode: |
138 | 145 |
139 // Move the value into a register. | 146 // Move the value into a register. |
140 virtual void Get(MacroAssembler* masm, Register reg) = 0; | 147 virtual void Get(MacroAssembler* masm, Register reg) = 0; |
141 | 148 |
142 // Push the value on the stack. | 149 // Push the value on the stack. |
143 virtual void Push(MacroAssembler* masm) = 0; | 150 virtual void Push(MacroAssembler* masm) = 0; |
144 | 151 |
| 152 // Move the value into a slot location. |
| 153 virtual void MoveToSlot(MacroAssembler* masm, SlotLocation* loc) = 0; |
| 154 |
145 #ifdef DEBUG | 155 #ifdef DEBUG |
146 virtual void Print() = 0; | 156 virtual void Print() = 0; |
147 #endif | 157 #endif |
148 }; | 158 }; |
149 | 159 |
150 | 160 |
151 // A compile-time constant that appeared as a literal in the source AST. | 161 // A compile-time constant that appeared as a literal in the source AST. |
152 class Constant : public Value { | 162 class Constant : public Value { |
153 public: | 163 public: |
154 explicit Constant(Handle<Object> handle) : handle_(handle) {} | 164 explicit Constant(Handle<Object> handle) : handle_(handle) {} |
155 | 165 |
156 virtual ~Constant() {} | 166 virtual ~Constant() {} |
157 | 167 |
158 // Support for fast-compilation mode. | 168 // Support for fast-compilation mode. |
159 void Get(MacroAssembler* masm, Register reg); | 169 void Get(MacroAssembler* masm, Register reg); |
160 void Push(MacroAssembler* masm); | 170 void Push(MacroAssembler* masm); |
| 171 void MoveToSlot(MacroAssembler* masm, SlotLocation* loc); |
161 | 172 |
162 #ifdef DEBUG | 173 #ifdef DEBUG |
163 void Print(); | 174 void Print(); |
164 #endif | 175 #endif |
165 | 176 |
166 private: | 177 private: |
167 Handle<Object> handle_; | 178 Handle<Object> handle_; |
168 }; | 179 }; |
169 | 180 |
170 | 181 |
171 // Locations are values that can be stored into ('lvalues'). | 182 // Locations are values that can be stored into ('lvalues'). |
172 class Location : public Value { | 183 class Location : public Value { |
173 public: | 184 public: |
174 virtual ~Location() {} | 185 virtual ~Location() {} |
175 | 186 |
176 // Static factory function returning the singleton effect location. | 187 // Static factory function returning the singleton nowhere location. |
177 static Location* Effect() { | 188 static Location* Nowhere() { |
178 return CfgGlobals::current()->effect_location(); | 189 return CfgGlobals::current()->nowhere(); |
179 } | 190 } |
180 | 191 |
181 // Support for fast-compilation mode: | 192 // Support for fast-compilation mode: |
182 | 193 |
183 // Assumes temporaries have been allocated. | 194 // Assumes temporaries have been allocated. |
184 virtual void Get(MacroAssembler* masm, Register reg) = 0; | 195 virtual void Get(MacroAssembler* masm, Register reg) = 0; |
185 | 196 |
186 // Store the value in a register to the location. Assumes temporaries | 197 // Store the value in a register to the location. Assumes temporaries |
187 // have been allocated. | 198 // have been allocated. |
188 virtual void Set(MacroAssembler* masm, Register reg) = 0; | 199 virtual void Set(MacroAssembler* masm, Register reg) = 0; |
189 | 200 |
190 // Assumes temporaries have been allocated, and if the value is a | 201 // Assumes temporaries have been allocated, and if the value is a |
191 // temporary it was not allocated to the stack. | 202 // temporary it was not allocated to the stack. |
192 virtual void Push(MacroAssembler* masm) = 0; | 203 virtual void Push(MacroAssembler* masm) = 0; |
193 | 204 |
| 205 // Emit code to move a value into this location. |
| 206 virtual void Move(MacroAssembler* masm, Value* value) = 0; |
| 207 |
194 #ifdef DEBUG | 208 #ifdef DEBUG |
195 virtual void Print() = 0; | 209 virtual void Print() = 0; |
196 #endif | 210 #endif |
197 }; | 211 }; |
198 | 212 |
199 | 213 |
200 // Effect is a special (singleton) location that indicates the value of a | 214 // Nowhere is a special (singleton) location that indicates the value of a |
201 // computation is not needed (though its side effects are). | 215 // computation is not needed (though its side effects are). |
202 class Effect : public Location { | 216 class Nowhere : public Location { |
203 public: | 217 public: |
204 // We should not try to emit code to read Effect. | 218 // We should not try to emit code to read Nowhere. |
205 void Get(MacroAssembler* masm, Register reg) { UNREACHABLE(); } | 219 void Get(MacroAssembler* masm, Register reg) { UNREACHABLE(); } |
206 void Push(MacroAssembler* masm) { UNREACHABLE(); } | 220 void Push(MacroAssembler* masm) { UNREACHABLE(); } |
| 221 void MoveToSlot(MacroAssembler* masm, SlotLocation* loc) { UNREACHABLE(); } |
207 | 222 |
208 // Setting Effect is ignored. | 223 // Setting Nowhere is ignored. |
209 void Set(MacroAssembler* masm, Register reg) {} | 224 void Set(MacroAssembler* masm, Register reg) {} |
| 225 void Move(MacroAssembler* masm, Value* value) {} |
210 | 226 |
211 #ifdef DEBUG | 227 #ifdef DEBUG |
212 void Print(); | 228 void Print(); |
213 #endif | 229 #endif |
214 | 230 |
215 private: | 231 private: |
216 Effect() {} | 232 Nowhere() {} |
217 | 233 |
218 friend class CfgGlobals; | 234 friend class CfgGlobals; |
219 }; | 235 }; |
220 | 236 |
221 | 237 |
222 // SlotLocations represent parameters and stack-allocated (i.e., | 238 // SlotLocations represent parameters and stack-allocated (i.e., |
223 // non-context) local variables. | 239 // non-context) local variables. |
224 class SlotLocation : public Location { | 240 class SlotLocation : public Location { |
225 public: | 241 public: |
226 SlotLocation(Slot::Type type, int index) : type_(type), index_(index) {} | 242 SlotLocation(Slot::Type type, int index) : type_(type), index_(index) {} |
227 | 243 |
| 244 // Cast accessor. |
| 245 static SlotLocation* cast(Value* value) { |
| 246 ASSERT(value->is_slot()); |
| 247 return reinterpret_cast<SlotLocation*>(value); |
| 248 } |
| 249 |
228 // Accessors. | 250 // Accessors. |
229 Slot::Type type() { return type_; } | 251 Slot::Type type() { return type_; } |
230 int index() { return index_; } | 252 int index() { return index_; } |
231 | 253 |
| 254 // Predicates. |
| 255 bool is_slot() { return true; } |
| 256 |
232 // Support for fast-compilation mode. | 257 // Support for fast-compilation mode. |
233 void Get(MacroAssembler* masm, Register reg); | 258 void Get(MacroAssembler* masm, Register reg); |
234 void Set(MacroAssembler* masm, Register reg); | 259 void Set(MacroAssembler* masm, Register reg); |
235 void Push(MacroAssembler* masm); | 260 void Push(MacroAssembler* masm); |
| 261 void Move(MacroAssembler* masm, Value* value); |
| 262 void MoveToSlot(MacroAssembler* masm, SlotLocation* loc); |
236 | 263 |
237 #ifdef DEBUG | 264 #ifdef DEBUG |
238 void Print(); | 265 void Print(); |
239 #endif | 266 #endif |
240 | 267 |
241 private: | 268 private: |
242 Slot::Type type_; | 269 Slot::Type type_; |
243 int index_; | 270 int index_; |
244 }; | 271 }; |
245 | 272 |
246 | 273 |
247 // TempLocations represent compiler generated temporaries. They are | 274 // TempLocations represent compiler generated temporaries. They are |
248 // allocated to registers or memory either before code generation (in the | 275 // allocated to registers or memory either before code generation (in the |
249 // optimized-for-speed compiler) or on the fly during code generation (in | 276 // optimized-for-speed compiler) or on the fly during code generation (in |
250 // the optimized-for-space compiler). | 277 // the optimized-for-space compiler). |
251 class TempLocation : public Location { | 278 class TempLocation : public Location { |
252 public: | 279 public: |
253 // Fast-compilation mode allocation decisions. | 280 // Fast-compilation mode allocation decisions. |
254 enum Where { | 281 enum Where { |
255 NOWHERE, // Not yet allocated. | 282 NOT_ALLOCATED, // Not yet allocated. |
256 ACCUMULATOR, // Allocated to the dedicated accumulator register. | 283 ACCUMULATOR, // Allocated to the dedicated accumulator register. |
257 STACK // " " " " stack. | 284 STACK // " " " " stack. |
258 }; | 285 }; |
259 | 286 |
260 TempLocation() : where_(NOWHERE) { | 287 TempLocation() : where_(NOT_ALLOCATED) { |
261 #ifdef DEBUG | 288 #ifdef DEBUG |
262 number_ = -1; | 289 number_ = -1; |
263 #endif | 290 #endif |
264 } | 291 } |
265 | 292 |
266 // Cast accessor. | 293 // Cast accessor. |
267 static TempLocation* cast(Location* loc) { | 294 static TempLocation* cast(Value* value) { |
268 ASSERT(loc->is_temporary()); | 295 ASSERT(value->is_temporary()); |
269 return reinterpret_cast<TempLocation*>(loc); | 296 return reinterpret_cast<TempLocation*>(value); |
270 } | 297 } |
271 | 298 |
272 // Accessors. | 299 // Accessors. |
273 Where where() { return where_; } | 300 Where where() { return where_; } |
274 void set_where(Where where) { where_ = where; } | 301 void set_where(Where where) { where_ = where; } |
275 | 302 |
276 // Predicates. | 303 // Predicates. |
277 bool is_on_stack() { return where_ == STACK; } | 304 bool is_on_stack() { return where_ == STACK; } |
278 bool is_temporary() { return true; } | 305 bool is_temporary() { return true; } |
279 | 306 |
280 // Support for fast-compilation mode. Assume the temp has been allocated. | 307 // Support for fast-compilation mode. Assume the temp has been allocated. |
281 void Get(MacroAssembler* masm, Register reg); | 308 void Get(MacroAssembler* masm, Register reg); |
282 void Set(MacroAssembler* masm, Register reg); | 309 void Set(MacroAssembler* masm, Register reg); |
283 void Push(MacroAssembler* masm); | 310 void Push(MacroAssembler* masm); |
| 311 void Move(MacroAssembler* masm, Value* value); |
| 312 void MoveToSlot(MacroAssembler* masm, SlotLocation* loc); |
284 | 313 |
285 #ifdef DEBUG | 314 #ifdef DEBUG |
286 int number() { | 315 int number() { |
287 if (number_ == -1) number_ = CfgGlobals::current()->next_temp_number(); | 316 if (number_ == -1) number_ = CfgGlobals::current()->next_temp_number(); |
288 return number_; | 317 return number_; |
289 } | 318 } |
290 | 319 |
291 void Print(); | 320 void Print(); |
292 #endif | 321 #endif |
293 | 322 |
294 private: | 323 private: |
295 Where where_; | 324 Where where_; |
296 | 325 |
297 #ifdef DEBUG | 326 #ifdef DEBUG |
298 int number_; | 327 int number_; |
299 #endif | 328 #endif |
300 }; | 329 }; |
301 | 330 |
302 | 331 |
303 // Instructions are computations. The represent non-trivial source | 332 // Instructions are computations. The represent non-trivial source |
304 // expressions: typically ones that have side effects and require code to | 333 // expressions: typically ones that have side effects and require code to |
305 // be generated. | 334 // be generated. |
306 class Instruction : public ZoneObject { | 335 class Instruction : public ZoneObject { |
307 public: | 336 public: |
308 // Every instruction has a location where its result is stored (which may | 337 // Every instruction has a location where its result is stored (which may |
309 // be Effect, the default). | 338 // be Nowhere, the default). |
310 Instruction() : loc_(CfgGlobals::current()->effect_location()) {} | 339 Instruction() : location_(CfgGlobals::current()->nowhere()) {} |
311 | 340 |
312 explicit Instruction(Location* loc) : loc_(loc) {} | 341 explicit Instruction(Location* location) : location_(location) {} |
313 | 342 |
314 virtual ~Instruction() {} | 343 virtual ~Instruction() {} |
315 | 344 |
316 // Accessors. | 345 // Accessors. |
317 Location* location() { return loc_; } | 346 Location* location() { return location_; } |
318 void set_location(Location* loc) { loc_ = loc; } | 347 void set_location(Location* location) { location_ = location; } |
319 | 348 |
320 // Support for fast-compilation mode: | 349 // Support for fast-compilation mode: |
321 | 350 |
322 // Emit code to perform the instruction. | 351 // Emit code to perform the instruction. |
323 virtual void Compile(MacroAssembler* masm) = 0; | 352 virtual void Compile(MacroAssembler* masm) = 0; |
324 | 353 |
325 // Allocate a temporary which is the result of the immediate predecessor | 354 // Allocate a temporary which is the result of the immediate predecessor |
326 // instruction. It is allocated to the accumulator register if it is used | 355 // instruction. It is allocated to the accumulator register if it is used |
327 // as an operand to this instruction, otherwise to the stack. | 356 // as an operand to this instruction, otherwise to the stack. |
328 virtual void FastAllocate(TempLocation* temp) = 0; | 357 virtual void FastAllocate(TempLocation* temp) = 0; |
329 | 358 |
330 #ifdef DEBUG | 359 #ifdef DEBUG |
331 virtual void Print() = 0; | 360 virtual void Print() = 0; |
332 #endif | 361 #endif |
333 | 362 |
334 protected: | 363 protected: |
335 Location* loc_; | 364 Location* location_; |
336 }; | 365 }; |
337 | 366 |
338 | 367 |
339 // A phantom instruction that indicates the start of a statement. It | 368 // A phantom instruction that indicates the start of a statement. It |
340 // causes the statement position to be recorded in the relocation | 369 // causes the statement position to be recorded in the relocation |
341 // information but generates no code. | 370 // information but generates no code. |
342 class PositionInstr : public Instruction { | 371 class PositionInstr : public Instruction { |
343 public: | 372 public: |
344 explicit PositionInstr(int pos) : pos_(pos) {} | 373 explicit PositionInstr(int pos) : pos_(pos) {} |
345 | 374 |
346 // Support for fast-compilation mode. | 375 // Support for fast-compilation mode. |
347 void Compile(MacroAssembler* masm); | 376 void Compile(MacroAssembler* masm); |
348 | 377 |
349 // This should not be called. The last instruction of the previous | 378 // This should not be called. The last instruction of the previous |
350 // statement should not have a temporary as its location. | 379 // statement should not have a temporary as its location. |
351 void FastAllocate(TempLocation* temp) { UNREACHABLE(); } | 380 void FastAllocate(TempLocation* temp) { UNREACHABLE(); } |
352 | 381 |
353 #ifdef DEBUG | 382 #ifdef DEBUG |
354 // Printing support. Print nothing. | 383 // Printing support. Print nothing. |
355 void Print() {} | 384 void Print() {} |
356 #endif | 385 #endif |
357 | 386 |
358 private: | 387 private: |
359 int pos_; | 388 int pos_; |
360 }; | 389 }; |
361 | 390 |
362 | 391 |
| 392 // Move a value to a location. |
| 393 class MoveInstr : public Instruction { |
| 394 public: |
| 395 MoveInstr(Location* loc, Value* value) : Instruction(loc), value_(value) {} |
| 396 |
| 397 // Accessors. |
| 398 Value* value() { return value_; } |
| 399 |
| 400 // Support for fast-compilation mode. |
| 401 void Compile(MacroAssembler* masm); |
| 402 void FastAllocate(TempLocation* temp); |
| 403 |
| 404 #ifdef DEBUG |
| 405 void Print(); |
| 406 #endif |
| 407 |
| 408 private: |
| 409 Value* value_; |
| 410 }; |
| 411 |
| 412 |
363 // Perform a (non-short-circuited) binary operation on a pair of values, | 413 // Perform a (non-short-circuited) binary operation on a pair of values, |
364 // leaving the result in a location. | 414 // leaving the result in a location. |
365 class BinaryOpInstr : public Instruction { | 415 class BinaryOpInstr : public Instruction { |
366 public: | 416 public: |
367 BinaryOpInstr(Location* loc, Token::Value op, Value* val0, Value* val1) | 417 BinaryOpInstr(Location* loc, Token::Value op, Value* value0, Value* value1) |
368 : Instruction(loc), op_(op), val0_(val0), val1_(val1) { | 418 : Instruction(loc), op_(op), value0_(value0), value1_(value1) { |
369 } | 419 } |
370 | 420 |
| 421 // Accessors. |
| 422 Token::Value op() { return op_; } |
| 423 Value* value0() { return value0_; } |
| 424 Value* value1() { return value1_; } |
| 425 |
371 // Support for fast-compilation mode. | 426 // Support for fast-compilation mode. |
372 void Compile(MacroAssembler* masm); | 427 void Compile(MacroAssembler* masm); |
373 void FastAllocate(TempLocation* temp); | 428 void FastAllocate(TempLocation* temp); |
374 | 429 |
375 #ifdef DEBUG | 430 #ifdef DEBUG |
376 void Print(); | 431 void Print(); |
377 #endif | 432 #endif |
378 | 433 |
379 private: | 434 private: |
380 Token::Value op_; | 435 Token::Value op_; |
381 Value* val0_; | 436 Value* value0_; |
382 Value* val1_; | 437 Value* value1_; |
383 }; | 438 }; |
384 | 439 |
385 | 440 |
386 // Return a value. Has the side effect of moving its value into the return | 441 // Return a value. Has the side effect of moving its value into the return |
387 // value register. Can only occur as the last instruction in an instruction | 442 // value register. Can only occur as the last instruction in an instruction |
388 // block, and implies that the block is closed (cannot have instructions | 443 // block, and implies that the block is closed (cannot have instructions |
389 // appended or graph fragments concatenated to the end) and that the block's | 444 // appended or graph fragments concatenated to the end) and that the block's |
390 // successor is the global exit node for the current function. | 445 // successor is the global exit node for the current function. |
391 class ReturnInstr : public Instruction { | 446 class ReturnInstr : public Instruction { |
392 public: | 447 public: |
393 // Location is always Effect. | |
394 explicit ReturnInstr(Value* value) : value_(value) {} | 448 explicit ReturnInstr(Value* value) : value_(value) {} |
395 | 449 |
396 virtual ~ReturnInstr() {} | 450 virtual ~ReturnInstr() {} |
397 | 451 |
398 // Support for fast-compilation mode. | 452 // Support for fast-compilation mode. |
399 void Compile(MacroAssembler* masm); | 453 void Compile(MacroAssembler* masm); |
400 void FastAllocate(TempLocation* temp); | 454 void FastAllocate(TempLocation* temp); |
401 | 455 |
402 #ifdef DEBUG | 456 #ifdef DEBUG |
403 void Print(); | 457 void Print(); |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 void Print(); | 652 void Print(); |
599 #endif | 653 #endif |
600 | 654 |
601 private: | 655 private: |
602 // Entry and exit nodes. | 656 // Entry and exit nodes. |
603 CfgNode* entry_; | 657 CfgNode* entry_; |
604 CfgNode* exit_; | 658 CfgNode* exit_; |
605 }; | 659 }; |
606 | 660 |
607 | 661 |
| 662 // An implementation of a set of locations (currently slot locations). |
| 663 class LocationSet BASE_EMBEDDED { |
| 664 public: |
| 665 // Construct an empty location set. |
| 666 LocationSet() : parameters_(0), locals_(0) {} |
| 667 |
| 668 // Raw accessors. |
| 669 uintptr_t parameters() { return parameters_; } |
| 670 uintptr_t locals() { return locals_; } |
| 671 |
| 672 // Insert an element. |
| 673 void AddElement(SlotLocation* location) { |
| 674 if (location->type() == Slot::PARAMETER) { |
| 675 // Parameter indexes begin with -1 ('this'). |
| 676 ASSERT(location->index() < kPointerSize - 1); |
| 677 parameters_ |= (1 << (location->index() + 1)); |
| 678 } else { |
| 679 ASSERT(location->type() == Slot::LOCAL); |
| 680 ASSERT(location->index() < kPointerSize); |
| 681 locals_ |= (1 << location->index()); |
| 682 } |
| 683 } |
| 684 |
| 685 // (Destructively) compute the union with another set. |
| 686 void Union(LocationSet* other) { |
| 687 parameters_ |= other->parameters(); |
| 688 locals_ |= other->locals(); |
| 689 } |
| 690 |
| 691 bool Contains(SlotLocation* location) { |
| 692 if (location->type() == Slot::PARAMETER) { |
| 693 ASSERT(location->index() < kPointerSize - 1); |
| 694 return (parameters_ & (1 << (location->index() + 1))); |
| 695 } else { |
| 696 ASSERT(location->type() == Slot::LOCAL); |
| 697 ASSERT(location->index() < kPointerSize); |
| 698 return (locals_ & (1 << location->index())); |
| 699 } |
| 700 } |
| 701 |
| 702 private: |
| 703 uintptr_t parameters_; |
| 704 uintptr_t locals_; |
| 705 }; |
| 706 |
| 707 |
608 // An ExpressionBuilder traverses an expression and returns an open CFG | 708 // An ExpressionBuilder traverses an expression and returns an open CFG |
609 // fragment (currently a possibly empty list of instructions represented by | 709 // fragment (currently a possibly empty list of instructions represented by |
610 // a singleton instruction block) and the expression's value. | 710 // a singleton instruction block) and the expression's value. |
611 // | 711 // |
612 // Failure is to build the CFG is indicated by a NULL CFG. | 712 // Failure is to build the CFG is indicated by a NULL CFG. |
613 class ExpressionBuilder : public AstVisitor { | 713 class ExpressionBuilder : public AstVisitor { |
614 public: | 714 public: |
615 ExpressionBuilder() : value_(NULL), cfg_(NULL) {} | 715 ExpressionBuilder() : value_(NULL), graph_(NULL), destination_(NULL) {} |
616 | 716 |
617 // Result accessors. | 717 // Result accessors. |
618 Value* value() { return value_; } | 718 Value* value() { return value_; } |
619 Cfg* cfg() { return cfg_; } | 719 Cfg* graph() { return graph_; } |
| 720 LocationSet* assigned_vars() { return &assigned_vars_; } |
620 | 721 |
621 void Build(Expression* expr) { | 722 // Build the cfg for an expression and remember its value. The |
| 723 // destination is a 'hint' where the value should go which may be ignored. |
| 724 // NULL is used to indicate no preference. |
| 725 // |
| 726 // Concretely, if the expression needs to generate a temporary for its |
| 727 // value, it should use the passed destination or generate one if NULL. |
| 728 void Build(Expression* expr, Location* destination) { |
622 value_ = NULL; | 729 value_ = NULL; |
623 cfg_ = new Cfg(); | 730 graph_ = new Cfg(); |
| 731 destination_ = destination; |
624 Visit(expr); | 732 Visit(expr); |
625 } | 733 } |
626 | 734 |
627 // AST node visitors. | 735 // AST node visitors. |
628 #define DECLARE_VISIT(type) void Visit##type(type* node); | 736 #define DECLARE_VISIT(type) void Visit##type(type* node); |
629 AST_NODE_LIST(DECLARE_VISIT) | 737 AST_NODE_LIST(DECLARE_VISIT) |
630 #undef DECLARE_VISIT | 738 #undef DECLARE_VISIT |
631 | 739 |
632 private: | 740 private: |
| 741 // State for the visitor. Output parameters. |
633 Value* value_; | 742 Value* value_; |
634 Cfg* cfg_; | 743 Cfg* graph_; |
| 744 LocationSet assigned_vars_; |
| 745 |
| 746 // Input parameters. |
| 747 Location* destination_; |
635 }; | 748 }; |
636 | 749 |
637 | 750 |
638 // A StatementBuilder maintains a CFG fragment accumulator. When it visits | 751 // A StatementBuilder maintains a CFG fragment accumulator. When it visits |
639 // a statement, it concatenates the CFG for the statement to the end of the | 752 // a statement, it concatenates the CFG for the statement to the end of the |
640 // accumulator. | 753 // accumulator. |
641 class StatementBuilder : public AstVisitor { | 754 class StatementBuilder : public AstVisitor { |
642 public: | 755 public: |
643 StatementBuilder() : cfg_(new Cfg()) {} | 756 StatementBuilder() : graph_(new Cfg()) {} |
644 | 757 |
645 Cfg* cfg() { return cfg_; } | 758 Cfg* graph() { return graph_; } |
646 | 759 |
647 void VisitStatements(ZoneList<Statement*>* stmts); | 760 void VisitStatements(ZoneList<Statement*>* stmts); |
648 | 761 |
649 // AST node visitors. | 762 // AST node visitors. |
650 #define DECLARE_VISIT(type) void Visit##type(type* node); | 763 #define DECLARE_VISIT(type) void Visit##type(type* node); |
651 AST_NODE_LIST(DECLARE_VISIT) | 764 AST_NODE_LIST(DECLARE_VISIT) |
652 #undef DECLARE_VISIT | 765 #undef DECLARE_VISIT |
653 | 766 |
654 private: | 767 private: |
655 Cfg* cfg_; | 768 Cfg* graph_; |
656 }; | 769 }; |
657 | 770 |
658 | 771 |
659 } } // namespace v8::internal | 772 } } // namespace v8::internal |
660 | 773 |
661 #endif // V8_CFG_H_ | 774 #endif // V8_CFG_H_ |
OLD | NEW |