| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 | 95 |
| 96 void Intersect(const BitVector& other) { | 96 void Intersect(const BitVector& other) { |
| 97 ASSERT(other.length() == length()); | 97 ASSERT(other.length() == length()); |
| 98 for (int i = 0; i < data_length_; i++) { | 98 for (int i = 0; i < data_length_; i++) { |
| 99 data_[i] &= other.data_[i]; | 99 data_[i] &= other.data_[i]; |
| 100 } | 100 } |
| 101 } | 101 } |
| 102 | 102 |
| 103 void Subtract(const BitVector& other) { |
| 104 ASSERT(other.length() == length()); |
| 105 for (int i = 0; i < data_length_; i++) { |
| 106 data_[i] &= ~other.data_[i]; |
| 107 } |
| 108 } |
| 109 |
| 103 void Clear() { | 110 void Clear() { |
| 104 for (int i = 0; i < data_length_; i++) { | 111 for (int i = 0; i < data_length_; i++) { |
| 105 data_[i] = 0; | 112 data_[i] = 0; |
| 106 } | 113 } |
| 107 } | 114 } |
| 108 | 115 |
| 109 bool IsEmpty() const { | 116 bool IsEmpty() const { |
| 110 for (int i = 0; i < data_length_; i++) { | 117 for (int i = 0; i < data_length_; i++) { |
| 111 if (data_[i] != 0) return false; | 118 if (data_[i] != 0) return false; |
| 112 } | 119 } |
| 113 return true; | 120 return true; |
| 114 } | 121 } |
| 115 | 122 |
| 123 bool Equals(const BitVector& other) { |
| 124 for (int i = 0; i < data_length_; i++) { |
| 125 if (data_[i] != other.data_[i]) return false; |
| 126 } |
| 127 return true; |
| 128 } |
| 129 |
| 116 int length() const { return length_; } | 130 int length() const { return length_; } |
| 117 | 131 |
| 132 #ifdef DEBUG |
| 133 void Print(); |
| 134 #endif |
| 135 |
| 118 private: | 136 private: |
| 119 int length_; | 137 int length_; |
| 120 int data_length_; | 138 int data_length_; |
| 121 uint32_t* data_; | 139 uint32_t* data_; |
| 122 }; | 140 }; |
| 123 | 141 |
| 124 | 142 |
| 125 // Forward declarations of Node types. | 143 // Simple fixed-capacity list-based worklist (managed as a queue) of |
| 126 class Node; | 144 // pointers to T. |
| 127 class BranchNode; | 145 template<typename T> |
| 128 class JoinNode; | 146 class WorkList BASE_EMBEDDED { |
| 147 public: |
| 148 // The worklist cannot grow bigger than size. We keep one item empty to |
| 149 // distinguish between empty and full. |
| 150 explicit WorkList(int size) |
| 151 : capacity_(size + 1), head_(0), tail_(0), queue_(capacity_) { |
| 152 for (int i = 0; i < capacity_; i++) queue_.Add(NULL); |
| 153 } |
| 129 | 154 |
| 130 // Flow graphs have a single entry and single exit. The empty flowgraph is | 155 bool is_empty() { return head_ == tail_; } |
| 131 // represented by both entry and exit being NULL. | |
| 132 class FlowGraph BASE_EMBEDDED { | |
| 133 public: | |
| 134 FlowGraph() : entry_(NULL), exit_(NULL) {} | |
| 135 | 156 |
| 136 static FlowGraph Empty() { return FlowGraph(); } | 157 bool is_full() { |
| 158 // The worklist is full if head is at 0 and tail is at capacity - 1: |
| 159 // head == 0 && tail == capacity-1 ==> tail - head == capacity - 1 |
| 160 // or if tail is immediately to the left of head: |
| 161 // tail+1 == head ==> tail - head == -1 |
| 162 int diff = tail_ - head_; |
| 163 return (diff == -1 || diff == capacity_ - 1); |
| 164 } |
| 137 | 165 |
| 138 bool is_empty() const { return entry_ == NULL; } | 166 void Insert(T* item) { |
| 139 Node* entry() const { return entry_; } | 167 ASSERT(!is_full()); |
| 140 Node* exit() const { return exit_; } | 168 queue_[tail_++] = item; |
| 169 if (tail_ == capacity_) tail_ = 0; |
| 170 } |
| 141 | 171 |
| 142 // Add a single instruction to the end of this flowgraph. | 172 T* Remove() { |
| 143 void AppendInstruction(AstNode* instruction); | 173 ASSERT(!is_empty()); |
| 144 | 174 T* item = queue_[head_++]; |
| 145 // Add a single node to the end of this flow graph. | 175 if (head_ == capacity_) head_ = 0; |
| 146 void AppendNode(Node* node); | 176 return item; |
| 147 | 177 } |
| 148 // Add a flow graph fragment to the end of this one. | |
| 149 void AppendGraph(FlowGraph* graph); | |
| 150 | |
| 151 // Concatenate an if-then-else flow-graph to this one. Control is split | |
| 152 // and merged, so the graph remains single-entry, single-exit. | |
| 153 void Split(BranchNode* branch, | |
| 154 FlowGraph* left, | |
| 155 FlowGraph* right, | |
| 156 JoinNode* merge); | |
| 157 | |
| 158 // Concatenate a forward loop (e.g., while or for loop) flow-graph to this | |
| 159 // one. Control is split by the condition and merged back from the back | |
| 160 // edge at end of the body to the beginning of the condition. The single | |
| 161 // (free) exit of the result graph is the right (false) arm of the branch | |
| 162 // node. | |
| 163 void Loop(JoinNode* merge, | |
| 164 FlowGraph* condition, | |
| 165 BranchNode* branch, | |
| 166 FlowGraph* body); | |
| 167 | |
| 168 #ifdef DEBUG | |
| 169 void PrintText(ZoneList<Node*>* postorder); | |
| 170 #endif | |
| 171 | 178 |
| 172 private: | 179 private: |
| 173 Node* entry_; | 180 int capacity_; // Including one empty slot. |
| 174 Node* exit_; | 181 int head_; // Where the first item is. |
| 182 int tail_; // Where the next inserted item will go. |
| 183 List<T*> queue_; |
| 175 }; | 184 }; |
| 176 | 185 |
| 177 | 186 |
| 187 struct ReachingDefinitionsData BASE_EMBEDDED { |
| 188 public: |
| 189 ReachingDefinitionsData() : rd_in_(NULL), kill_(NULL), gen_(NULL) {} |
| 190 |
| 191 void Initialize(int definition_count) { |
| 192 rd_in_ = new BitVector(definition_count); |
| 193 kill_ = new BitVector(definition_count); |
| 194 gen_ = new BitVector(definition_count); |
| 195 } |
| 196 |
| 197 BitVector* rd_in() { return rd_in_; } |
| 198 BitVector* kill() { return kill_; } |
| 199 BitVector* gen() { return gen_; } |
| 200 |
| 201 private: |
| 202 BitVector* rd_in_; |
| 203 BitVector* kill_; |
| 204 BitVector* gen_; |
| 205 }; |
| 206 |
| 207 |
| 178 // Flow-graph nodes. | 208 // Flow-graph nodes. |
| 179 class Node: public ZoneObject { | 209 class Node: public ZoneObject { |
| 180 public: | 210 public: |
| 181 Node() : number_(-1), mark_(false) {} | 211 Node() : number_(-1), mark_(false) {} |
| 182 | 212 |
| 183 virtual ~Node() {} | 213 virtual ~Node() {} |
| 184 | 214 |
| 215 virtual bool IsExitNode() { return false; } |
| 185 virtual bool IsBlockNode() { return false; } | 216 virtual bool IsBlockNode() { return false; } |
| 217 virtual bool IsBranchNode() { return false; } |
| 186 virtual bool IsJoinNode() { return false; } | 218 virtual bool IsJoinNode() { return false; } |
| 187 | 219 |
| 188 virtual void AddPredecessor(Node* predecessor) = 0; | 220 virtual void AddPredecessor(Node* predecessor) = 0; |
| 189 virtual void AddSuccessor(Node* successor) = 0; | 221 virtual void AddSuccessor(Node* successor) = 0; |
| 190 | 222 |
| 191 bool IsMarkedWith(bool mark) { return mark_ == mark; } | 223 bool IsMarkedWith(bool mark) { return mark_ == mark; } |
| 192 void MarkWith(bool mark) { mark_ = mark; } | 224 void MarkWith(bool mark) { mark_ = mark; } |
| 193 | 225 |
| 194 // Perform a depth first search and record preorder and postorder | 226 // Perform a depth first search and record preorder and postorder |
| 195 // traversal orders. | 227 // traversal orders. |
| 196 virtual void Traverse(bool mark, | 228 virtual void Traverse(bool mark, |
| 197 ZoneList<Node*>* preorder, | 229 ZoneList<Node*>* preorder, |
| 198 ZoneList<Node*>* postorder) = 0; | 230 ZoneList<Node*>* postorder) = 0; |
| 199 | 231 |
| 200 int number() { return number_; } | 232 int number() { return number_; } |
| 201 void set_number(int number) { number_ = number; } | 233 void set_number(int number) { number_ = number; } |
| 202 | 234 |
| 235 // Functions used by data-flow analyses. |
| 236 virtual void InitializeReachingDefinitions(int definition_count, |
| 237 List<BitVector*>* variables, |
| 238 WorkList<Node>* worklist, |
| 239 bool mark); |
| 240 virtual void ComputeRDOut(BitVector* result) = 0; |
| 241 virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark) = 0; |
| 242 virtual void PropagateReachingDefinitions(List<BitVector*>* variables); |
| 243 |
| 203 #ifdef DEBUG | 244 #ifdef DEBUG |
| 204 virtual void AssignNumbers(); | 245 void AssignNodeNumber(); |
| 246 void PrintReachingDefinitions(); |
| 205 virtual void PrintText() = 0; | 247 virtual void PrintText() = 0; |
| 206 #endif | 248 #endif |
| 207 | 249 |
| 250 protected: |
| 251 ReachingDefinitionsData rd_; |
| 252 |
| 208 private: | 253 private: |
| 209 int number_; | 254 int number_; |
| 210 bool mark_; | 255 bool mark_; |
| 211 | 256 |
| 212 DISALLOW_COPY_AND_ASSIGN(Node); | 257 DISALLOW_COPY_AND_ASSIGN(Node); |
| 213 }; | 258 }; |
| 214 | 259 |
| 215 | 260 |
| 216 // An entry node has no predecessors and a single successor. | |
| 217 class EntryNode: public Node { | |
| 218 public: | |
| 219 EntryNode() : successor_(NULL) {} | |
| 220 | |
| 221 void AddPredecessor(Node* predecessor) { UNREACHABLE(); } | |
| 222 | |
| 223 void AddSuccessor(Node* successor) { | |
| 224 ASSERT(successor_ == NULL && successor != NULL); | |
| 225 successor_ = successor; | |
| 226 } | |
| 227 | |
| 228 void Traverse(bool mark, | |
| 229 ZoneList<Node*>* preorder, | |
| 230 ZoneList<Node*>* postorder); | |
| 231 | |
| 232 #ifdef DEBUG | |
| 233 void PrintText(); | |
| 234 #endif | |
| 235 | |
| 236 private: | |
| 237 Node* successor_; | |
| 238 | |
| 239 DISALLOW_COPY_AND_ASSIGN(EntryNode); | |
| 240 }; | |
| 241 | |
| 242 | |
| 243 // An exit node has a arbitrarily many predecessors and no successors. | 261 // An exit node has a arbitrarily many predecessors and no successors. |
| 244 class ExitNode: public Node { | 262 class ExitNode: public Node { |
| 245 public: | 263 public: |
| 246 ExitNode() : predecessors_(4) {} | 264 ExitNode() : predecessors_(4) {} |
| 247 | 265 |
| 266 bool IsExitNode() { return true; } |
| 267 |
| 248 void AddPredecessor(Node* predecessor) { | 268 void AddPredecessor(Node* predecessor) { |
| 249 ASSERT(predecessor != NULL); | 269 ASSERT(predecessor != NULL); |
| 250 predecessors_.Add(predecessor); | 270 predecessors_.Add(predecessor); |
| 251 } | 271 } |
| 252 | 272 |
| 253 void AddSuccessor(Node* successor) { /* Do nothing. */ } | 273 void AddSuccessor(Node* successor) { UNREACHABLE(); } |
| 254 | 274 |
| 255 void Traverse(bool mark, | 275 void Traverse(bool mark, |
| 256 ZoneList<Node*>* preorder, | 276 ZoneList<Node*>* preorder, |
| 257 ZoneList<Node*>* postorder); | 277 ZoneList<Node*>* postorder); |
| 258 | 278 |
| 279 void ComputeRDOut(BitVector* result); |
| 280 void UpdateRDIn(WorkList<Node>* worklist, bool mark); |
| 281 |
| 259 #ifdef DEBUG | 282 #ifdef DEBUG |
| 260 void PrintText(); | 283 void PrintText(); |
| 261 #endif | 284 #endif |
| 262 | 285 |
| 263 private: | 286 private: |
| 264 ZoneList<Node*> predecessors_; | 287 ZoneList<Node*> predecessors_; |
| 265 | 288 |
| 266 DISALLOW_COPY_AND_ASSIGN(ExitNode); | 289 DISALLOW_COPY_AND_ASSIGN(ExitNode); |
| 267 }; | 290 }; |
| 268 | 291 |
| 269 | 292 |
| 270 // Block nodes have a single successor and predecessor and a list of | 293 // Block nodes have a single successor and predecessor and a list of |
| 271 // instructions. | 294 // instructions. |
| 272 class BlockNode: public Node { | 295 class BlockNode: public Node { |
| 273 public: | 296 public: |
| 274 BlockNode() : predecessor_(NULL), successor_(NULL), instructions_(4) {} | 297 BlockNode() : predecessor_(NULL), successor_(NULL), instructions_(4) {} |
| 275 | 298 |
| 276 static BlockNode* cast(Node* node) { | 299 static BlockNode* cast(Node* node) { |
| 277 ASSERT(node->IsBlockNode()); | 300 ASSERT(node->IsBlockNode()); |
| 278 return reinterpret_cast<BlockNode*>(node); | 301 return reinterpret_cast<BlockNode*>(node); |
| 279 } | 302 } |
| 280 | 303 |
| 281 bool IsBlockNode() { return true; } | 304 bool IsBlockNode() { return true; } |
| 282 | 305 |
| 306 bool is_empty() { return instructions_.is_empty(); } |
| 307 |
| 283 void AddPredecessor(Node* predecessor) { | 308 void AddPredecessor(Node* predecessor) { |
| 284 ASSERT(predecessor_ == NULL && predecessor != NULL); | 309 ASSERT(predecessor_ == NULL && predecessor != NULL); |
| 285 predecessor_ = predecessor; | 310 predecessor_ = predecessor; |
| 286 } | 311 } |
| 287 | 312 |
| 288 void AddSuccessor(Node* successor) { | 313 void AddSuccessor(Node* successor) { |
| 289 ASSERT(successor_ == NULL && successor != NULL); | 314 ASSERT(successor_ == NULL && successor != NULL); |
| 290 successor_ = successor; | 315 successor_ = successor; |
| 291 } | 316 } |
| 292 | 317 |
| 293 void AddInstruction(AstNode* instruction) { | 318 void AddInstruction(AstNode* instruction) { |
| 294 instructions_.Add(instruction); | 319 instructions_.Add(instruction); |
| 295 } | 320 } |
| 296 | 321 |
| 297 void Traverse(bool mark, | 322 void Traverse(bool mark, |
| 298 ZoneList<Node*>* preorder, | 323 ZoneList<Node*>* preorder, |
| 299 ZoneList<Node*>* postorder); | 324 ZoneList<Node*>* postorder); |
| 300 | 325 |
| 326 void InitializeReachingDefinitions(int definition_count, |
| 327 List<BitVector*>* variables, |
| 328 WorkList<Node>* worklist, |
| 329 bool mark); |
| 330 void ComputeRDOut(BitVector* result); |
| 331 void UpdateRDIn(WorkList<Node>* worklist, bool mark); |
| 332 void PropagateReachingDefinitions(List<BitVector*>* variables); |
| 333 |
| 301 #ifdef DEBUG | 334 #ifdef DEBUG |
| 302 void AssignNumbers(); | |
| 303 void PrintText(); | 335 void PrintText(); |
| 304 #endif | 336 #endif |
| 305 | 337 |
| 306 private: | 338 private: |
| 307 Node* predecessor_; | 339 Node* predecessor_; |
| 308 Node* successor_; | 340 Node* successor_; |
| 309 ZoneList<AstNode*> instructions_; | 341 ZoneList<AstNode*> instructions_; |
| 310 | 342 |
| 311 DISALLOW_COPY_AND_ASSIGN(BlockNode); | 343 DISALLOW_COPY_AND_ASSIGN(BlockNode); |
| 312 }; | 344 }; |
| 313 | 345 |
| 314 | 346 |
| 315 // Branch nodes have a single predecessor and a pair of successors. | 347 // Branch nodes have a single predecessor and a pair of successors. |
| 316 class BranchNode: public Node { | 348 class BranchNode: public Node { |
| 317 public: | 349 public: |
| 318 BranchNode() : predecessor_(NULL), successor0_(NULL), successor1_(NULL) {} | 350 BranchNode() : predecessor_(NULL), successor0_(NULL), successor1_(NULL) {} |
| 319 | 351 |
| 352 bool IsBranchNode() { return true; } |
| 353 |
| 320 void AddPredecessor(Node* predecessor) { | 354 void AddPredecessor(Node* predecessor) { |
| 321 ASSERT(predecessor_ == NULL && predecessor != NULL); | 355 ASSERT(predecessor_ == NULL && predecessor != NULL); |
| 322 predecessor_ = predecessor; | 356 predecessor_ = predecessor; |
| 323 } | 357 } |
| 324 | 358 |
| 325 void AddSuccessor(Node* successor) { | 359 void AddSuccessor(Node* successor) { |
| 326 ASSERT(successor1_ == NULL && successor != NULL); | 360 ASSERT(successor1_ == NULL && successor != NULL); |
| 327 if (successor0_ == NULL) { | 361 if (successor0_ == NULL) { |
| 328 successor0_ = successor; | 362 successor0_ = successor; |
| 329 } else { | 363 } else { |
| 330 successor1_ = successor; | 364 successor1_ = successor; |
| 331 } | 365 } |
| 332 } | 366 } |
| 333 | 367 |
| 334 void Traverse(bool mark, | 368 void Traverse(bool mark, |
| 335 ZoneList<Node*>* preorder, | 369 ZoneList<Node*>* preorder, |
| 336 ZoneList<Node*>* postorder); | 370 ZoneList<Node*>* postorder); |
| 337 | 371 |
| 372 void ComputeRDOut(BitVector* result); |
| 373 void UpdateRDIn(WorkList<Node>* worklist, bool mark); |
| 374 |
| 338 #ifdef DEBUG | 375 #ifdef DEBUG |
| 339 void PrintText(); | 376 void PrintText(); |
| 340 #endif | 377 #endif |
| 341 | 378 |
| 342 private: | 379 private: |
| 343 Node* predecessor_; | 380 Node* predecessor_; |
| 344 Node* successor0_; | 381 Node* successor0_; |
| 345 Node* successor1_; | 382 Node* successor1_; |
| 346 | 383 |
| 347 DISALLOW_COPY_AND_ASSIGN(BranchNode); | 384 DISALLOW_COPY_AND_ASSIGN(BranchNode); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 367 | 404 |
| 368 void AddSuccessor(Node* successor) { | 405 void AddSuccessor(Node* successor) { |
| 369 ASSERT(successor_ == NULL && successor != NULL); | 406 ASSERT(successor_ == NULL && successor != NULL); |
| 370 successor_ = successor; | 407 successor_ = successor; |
| 371 } | 408 } |
| 372 | 409 |
| 373 void Traverse(bool mark, | 410 void Traverse(bool mark, |
| 374 ZoneList<Node*>* preorder, | 411 ZoneList<Node*>* preorder, |
| 375 ZoneList<Node*>* postorder); | 412 ZoneList<Node*>* postorder); |
| 376 | 413 |
| 414 void ComputeRDOut(BitVector* result); |
| 415 void UpdateRDIn(WorkList<Node>* worklist, bool mark); |
| 416 |
| 377 #ifdef DEBUG | 417 #ifdef DEBUG |
| 378 void PrintText(); | 418 void PrintText(); |
| 379 #endif | 419 #endif |
| 380 | 420 |
| 381 private: | 421 private: |
| 382 ZoneList<Node*> predecessors_; | 422 ZoneList<Node*> predecessors_; |
| 383 Node* successor_; | 423 Node* successor_; |
| 384 | 424 |
| 385 DISALLOW_COPY_AND_ASSIGN(JoinNode); | 425 DISALLOW_COPY_AND_ASSIGN(JoinNode); |
| 386 }; | 426 }; |
| 387 | 427 |
| 388 | 428 |
| 429 // Flow graphs have a single entry and single exit. The empty flowgraph is |
| 430 // represented by both entry and exit being NULL. |
| 431 class FlowGraph BASE_EMBEDDED { |
| 432 public: |
| 433 static FlowGraph Empty() { |
| 434 FlowGraph graph; |
| 435 graph.entry_ = new BlockNode(); |
| 436 graph.exit_ = graph.entry_; |
| 437 return graph; |
| 438 } |
| 439 |
| 440 bool is_empty() const { |
| 441 return entry_ == exit_ && BlockNode::cast(entry_)->is_empty(); |
| 442 } |
| 443 Node* entry() const { return entry_; } |
| 444 Node* exit() const { return exit_; } |
| 445 |
| 446 // Add a single instruction to the end of this flowgraph. |
| 447 void AppendInstruction(AstNode* instruction); |
| 448 |
| 449 // Add a single node to the end of this flow graph. |
| 450 void AppendNode(Node* node); |
| 451 |
| 452 // Add a flow graph fragment to the end of this one. |
| 453 void AppendGraph(FlowGraph* graph); |
| 454 |
| 455 // Concatenate an if-then-else flow-graph to this one. Control is split |
| 456 // and merged, so the graph remains single-entry, single-exit. |
| 457 void Split(BranchNode* branch, |
| 458 FlowGraph* left, |
| 459 FlowGraph* right, |
| 460 JoinNode* merge); |
| 461 |
| 462 // Concatenate a forward loop (e.g., while or for loop) flow-graph to this |
| 463 // one. Control is split by the condition and merged back from the back |
| 464 // edge at end of the body to the beginning of the condition. The single |
| 465 // (free) exit of the result graph is the right (false) arm of the branch |
| 466 // node. |
| 467 void Loop(JoinNode* merge, |
| 468 FlowGraph* condition, |
| 469 BranchNode* branch, |
| 470 FlowGraph* body); |
| 471 |
| 472 #ifdef DEBUG |
| 473 void PrintText(FunctionLiteral* fun, ZoneList<Node*>* postorder); |
| 474 #endif |
| 475 |
| 476 private: |
| 477 FlowGraph() : entry_(NULL), exit_(NULL) {} |
| 478 |
| 479 Node* entry_; |
| 480 Node* exit_; |
| 481 }; |
| 482 |
| 483 |
| 389 // Construct a flow graph from a function literal. Build pre- and postorder | 484 // Construct a flow graph from a function literal. Build pre- and postorder |
| 390 // traversal orders as a byproduct. | 485 // traversal orders as a byproduct. |
| 391 class FlowGraphBuilder: public AstVisitor { | 486 class FlowGraphBuilder: public AstVisitor { |
| 392 public: | 487 public: |
| 393 FlowGraphBuilder() | 488 FlowGraphBuilder() |
| 394 : global_exit_(NULL), | 489 : graph_(FlowGraph::Empty()), |
| 490 global_exit_(NULL), |
| 395 preorder_(4), | 491 preorder_(4), |
| 396 postorder_(4), | 492 postorder_(4), |
| 397 definitions_(4) { | 493 definitions_(4) {} |
| 398 } | |
| 399 | 494 |
| 400 void Build(FunctionLiteral* lit); | 495 void Build(FunctionLiteral* lit); |
| 401 | 496 |
| 402 FlowGraph* graph() { return &graph_; } | 497 FlowGraph* graph() { return &graph_; } |
| 403 | |
| 404 ZoneList<Node*>* postorder() { return &postorder_; } | 498 ZoneList<Node*>* postorder() { return &postorder_; } |
| 499 ZoneList<Expression*>* definitions() { return &definitions_; } |
| 405 | 500 |
| 406 private: | 501 private: |
| 407 ExitNode* global_exit() { return global_exit_; } | 502 ExitNode* global_exit() { return global_exit_; } |
| 408 | 503 |
| 504 // Helpers to allow tranforming the ast during flow graph construction. |
| 505 void VisitStatements(ZoneList<Statement*>* stmts); |
| 506 Statement* ProcessStatement(Statement* stmt); |
| 507 |
| 409 // AST node visit functions. | 508 // AST node visit functions. |
| 410 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); | 509 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); |
| 411 AST_NODE_LIST(DECLARE_VISIT) | 510 AST_NODE_LIST(DECLARE_VISIT) |
| 412 #undef DECLARE_VISIT | 511 #undef DECLARE_VISIT |
| 413 | 512 |
| 414 FlowGraph graph_; | 513 FlowGraph graph_; |
| 415 ExitNode* global_exit_; | 514 ExitNode* global_exit_; |
| 416 ZoneList<Node*> preorder_; | 515 ZoneList<Node*> preorder_; |
| 417 ZoneList<Node*> postorder_; | 516 ZoneList<Node*> postorder_; |
| 418 | 517 |
| 419 // The flow graph builder collects a list of definitions (assignments and | 518 // The flow graph builder collects a list of definitions (assignments and |
| 420 // count operations) to stack-allocated variables to use for reaching | 519 // count operations) to stack-allocated variables to use for reaching |
| 421 // definitions analysis. | 520 // definitions analysis. AST node numbers in the AST are used to refer |
| 422 ZoneList<AstNode*> definitions_; | 521 // into this list. |
| 522 ZoneList<Expression*> definitions_; |
| 423 | 523 |
| 424 DISALLOW_COPY_AND_ASSIGN(FlowGraphBuilder); | 524 DISALLOW_COPY_AND_ASSIGN(FlowGraphBuilder); |
| 425 }; | 525 }; |
| 426 | 526 |
| 427 | 527 |
| 428 // This class is used to number all expressions in the AST according to | 528 // This class is used to number all expressions in the AST according to |
| 429 // their evaluation order (post-order left-to-right traversal). | 529 // their evaluation order (post-order left-to-right traversal). |
| 430 class AstLabeler: public AstVisitor { | 530 class AstLabeler: public AstVisitor { |
| 431 public: | 531 public: |
| 432 AstLabeler() : next_number_(0) {} | 532 AstLabeler() : next_number_(0) {} |
| (...skipping 13 matching lines...) Expand all Loading... |
| 446 | 546 |
| 447 // Traversal number for labelling AST nodes. | 547 // Traversal number for labelling AST nodes. |
| 448 int next_number_; | 548 int next_number_; |
| 449 | 549 |
| 450 CompilationInfo* info_; | 550 CompilationInfo* info_; |
| 451 | 551 |
| 452 DISALLOW_COPY_AND_ASSIGN(AstLabeler); | 552 DISALLOW_COPY_AND_ASSIGN(AstLabeler); |
| 453 }; | 553 }; |
| 454 | 554 |
| 455 | 555 |
| 456 class VarUseMap : public HashMap { | 556 // Computes the set of assigned variables and annotates variables proxies |
| 557 // that are trivial sub-expressions and for-loops where the loop variable |
| 558 // is guaranteed to be a smi. |
| 559 class AssignedVariablesAnalyzer : public AstVisitor { |
| 457 public: | 560 public: |
| 458 VarUseMap() : HashMap(VarMatch) {} | 561 explicit AssignedVariablesAnalyzer(FunctionLiteral* fun); |
| 459 | 562 |
| 460 ZoneList<Expression*>* Lookup(Variable* var); | 563 void Analyze(); |
| 461 | 564 |
| 462 private: | 565 private: |
| 463 static bool VarMatch(void* key1, void* key2) { return key1 == key2; } | 566 Variable* FindSmiLoopVariable(ForStatement* stmt); |
| 464 }; | |
| 465 | 567 |
| 568 int BitIndex(Variable* var); |
| 466 | 569 |
| 467 class DefinitionInfo : public ZoneObject { | 570 void RecordAssignedVar(Variable* var); |
| 468 public: | |
| 469 explicit DefinitionInfo() : last_use_(NULL) {} | |
| 470 | 571 |
| 471 Expression* last_use() { return last_use_; } | 572 void MarkIfTrivial(Expression* expr); |
| 472 void set_last_use(Expression* expr) { last_use_ = expr; } | |
| 473 | 573 |
| 474 private: | 574 // Visits an expression saving the accumulator before, clearing |
| 475 Expression* last_use_; | 575 // it before visting and restoring it after visiting. |
| 476 Register location_; | 576 void ProcessExpression(Expression* expr); |
| 477 }; | |
| 478 | |
| 479 | |
| 480 class LivenessAnalyzer : public AstVisitor { | |
| 481 public: | |
| 482 LivenessAnalyzer() {} | |
| 483 | |
| 484 void Analyze(FunctionLiteral* fun); | |
| 485 | |
| 486 private: | |
| 487 void VisitStatements(ZoneList<Statement*>* stmts); | |
| 488 | |
| 489 void RecordUse(Variable* var, Expression* expr); | |
| 490 void RecordDef(Variable* var, Expression* expr); | |
| 491 | |
| 492 | 577 |
| 493 // AST node visit functions. | 578 // AST node visit functions. |
| 494 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); | 579 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); |
| 495 AST_NODE_LIST(DECLARE_VISIT) | 580 AST_NODE_LIST(DECLARE_VISIT) |
| 496 #undef DECLARE_VISIT | 581 #undef DECLARE_VISIT |
| 497 | 582 |
| 498 // Map for tracking the live variables. | 583 FunctionLiteral* fun_; |
| 499 VarUseMap live_vars_; | |
| 500 | 584 |
| 501 DISALLOW_COPY_AND_ASSIGN(LivenessAnalyzer); | 585 // Accumulator for assigned variables set. |
| 586 BitVector av_; |
| 587 |
| 588 DISALLOW_COPY_AND_ASSIGN(AssignedVariablesAnalyzer); |
| 502 }; | 589 }; |
| 503 | 590 |
| 504 | 591 |
| 592 class ReachingDefinitions BASE_EMBEDDED { |
| 593 public: |
| 594 ReachingDefinitions(ZoneList<Node*>* postorder, |
| 595 ZoneList<Expression*>* definitions, |
| 596 int variable_count) |
| 597 : postorder_(postorder), |
| 598 definitions_(definitions), |
| 599 variables_(variable_count) { |
| 600 int definition_count = definitions->length(); |
| 601 for (int i = 0; i < variable_count; i++) { |
| 602 variables_.Add(new BitVector(definition_count)); |
| 603 } |
| 604 } |
| 605 |
| 606 static int IndexFor(Variable* var, int variable_count); |
| 607 |
| 608 void Compute(); |
| 609 |
| 610 private: |
| 611 // A (postorder) list of flow-graph nodes in the body. |
| 612 ZoneList<Node*>* postorder_; |
| 613 |
| 614 // A list of all the definitions in the body. |
| 615 ZoneList<Expression*>* definitions_; |
| 616 |
| 617 // For each variable, the set of all its definitions. |
| 618 List<BitVector*> variables_; |
| 619 |
| 620 DISALLOW_COPY_AND_ASSIGN(ReachingDefinitions); |
| 621 }; |
| 622 |
| 623 |
| 505 } } // namespace v8::internal | 624 } } // namespace v8::internal |
| 506 | 625 |
| 507 | 626 |
| 508 #endif // V8_DATAFLOW_H_ | 627 #endif // V8_DATAFLOW_H_ |
| OLD | NEW |