| 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 |