| 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 10 matching lines...) Expand all Loading... |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "data-flow.h" | 30 #include "data-flow.h" |
| 31 #include "scopes.h" |
| 31 | 32 |
| 32 namespace v8 { | 33 namespace v8 { |
| 33 namespace internal { | 34 namespace internal { |
| 34 | 35 |
| 35 | 36 |
| 37 #ifdef DEBUG |
| 38 void BitVector::Print() { |
| 39 bool first = true; |
| 40 PrintF("{"); |
| 41 for (int i = 0; i < length(); i++) { |
| 42 if (Contains(i)) { |
| 43 if (!first) PrintF(","); |
| 44 first = false; |
| 45 PrintF("%d"); |
| 46 } |
| 47 } |
| 48 PrintF("}"); |
| 49 } |
| 50 #endif |
| 51 |
| 52 |
| 36 void FlowGraph::AppendInstruction(AstNode* instruction) { | 53 void FlowGraph::AppendInstruction(AstNode* instruction) { |
| 54 // Add a (non-null) AstNode to the end of the graph fragment. |
| 37 ASSERT(instruction != NULL); | 55 ASSERT(instruction != NULL); |
| 38 if (is_empty() || !exit()->IsBlockNode()) { | 56 if (exit()->IsExitNode()) return; |
| 39 AppendNode(new BlockNode()); | 57 if (!exit()->IsBlockNode()) AppendNode(new BlockNode()); |
| 40 } | |
| 41 BlockNode::cast(exit())->AddInstruction(instruction); | 58 BlockNode::cast(exit())->AddInstruction(instruction); |
| 42 } | 59 } |
| 43 | 60 |
| 44 | 61 |
| 45 void FlowGraph::AppendNode(Node* node) { | 62 void FlowGraph::AppendNode(Node* node) { |
| 63 // Add a node to the end of the graph. An empty block is added to |
| 64 // maintain edge-split form (that no join nodes or exit nodes as |
| 65 // successors to branch nodes). |
| 46 ASSERT(node != NULL); | 66 ASSERT(node != NULL); |
| 47 if (is_empty()) { | 67 if (exit()->IsExitNode()) return; |
| 48 entry_ = exit_ = node; | 68 if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) { |
| 49 } else { | 69 AppendNode(new BlockNode()); |
| 50 exit()->AddSuccessor(node); | |
| 51 node->AddPredecessor(exit()); | |
| 52 exit_ = node; | |
| 53 } | 70 } |
| 71 exit()->AddSuccessor(node); |
| 72 node->AddPredecessor(exit()); |
| 73 exit_ = node; |
| 54 } | 74 } |
| 55 | 75 |
| 56 | 76 |
| 57 void FlowGraph::AppendGraph(FlowGraph* graph) { | 77 void FlowGraph::AppendGraph(FlowGraph* graph) { |
| 58 ASSERT(!graph->is_empty()); | 78 // Add a flow graph fragment to the end of this one. An empty block is |
| 59 if (is_empty()) { | 79 // added to maintain edge-split form (that no join nodes or exit nodes as |
| 60 entry_ = graph->entry(); | 80 // successors to branch nodes). |
| 61 exit_ = graph->exit(); | 81 ASSERT(graph != NULL); |
| 62 } else { | 82 if (exit()->IsExitNode()) return; |
| 63 exit()->AddSuccessor(graph->entry()); | 83 Node* node = graph->entry(); |
| 64 graph->entry()->AddPredecessor(exit()); | 84 if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) { |
| 65 exit_ = graph->exit(); | 85 AppendNode(new BlockNode()); |
| 66 } | 86 } |
| 87 exit()->AddSuccessor(node); |
| 88 node->AddPredecessor(exit()); |
| 89 exit_ = graph->exit(); |
| 67 } | 90 } |
| 68 | 91 |
| 69 | 92 |
| 70 void FlowGraph::Split(BranchNode* branch, | 93 void FlowGraph::Split(BranchNode* branch, |
| 71 FlowGraph* left, | 94 FlowGraph* left, |
| 72 FlowGraph* right, | 95 FlowGraph* right, |
| 73 JoinNode* merge) { | 96 JoinNode* join) { |
| 74 // Graphs are in edge split form. Add empty blocks if necessary. | 97 // Add the branch node, left flowgraph, join node. |
| 75 if (left->is_empty()) left->AppendNode(new BlockNode()); | |
| 76 if (right->is_empty()) right->AppendNode(new BlockNode()); | |
| 77 | |
| 78 // Add the branch, left flowgraph and merge. | |
| 79 AppendNode(branch); | 98 AppendNode(branch); |
| 80 AppendGraph(left); | 99 AppendGraph(left); |
| 81 AppendNode(merge); | 100 AppendNode(join); |
| 82 | 101 |
| 83 // Splice in the right flowgraph. | 102 // Splice in the right flowgraph. |
| 84 right->AppendNode(merge); | 103 right->AppendNode(join); |
| 85 branch->AddSuccessor(right->entry()); | 104 branch->AddSuccessor(right->entry()); |
| 86 right->entry()->AddPredecessor(branch); | 105 right->entry()->AddPredecessor(branch); |
| 87 } | 106 } |
| 88 | 107 |
| 89 | 108 |
| 90 void FlowGraph::Loop(JoinNode* merge, | 109 void FlowGraph::Loop(JoinNode* join, |
| 91 FlowGraph* condition, | 110 FlowGraph* condition, |
| 92 BranchNode* branch, | 111 BranchNode* branch, |
| 93 FlowGraph* body) { | 112 FlowGraph* body) { |
| 94 // Add the merge, condition and branch. Add merge's predecessors in | 113 // Add the join, condition and branch. Add join's predecessors in |
| 95 // left-to-right order. | 114 // left-to-right order. |
| 96 AppendNode(merge); | 115 AppendNode(join); |
| 97 body->AppendNode(merge); | 116 body->AppendNode(join); |
| 98 AppendGraph(condition); | 117 AppendGraph(condition); |
| 99 AppendNode(branch); | 118 AppendNode(branch); |
| 100 | 119 |
| 101 // Splice in the body flowgraph. | 120 // Splice in the body flowgraph. |
| 102 branch->AddSuccessor(body->entry()); | 121 branch->AddSuccessor(body->entry()); |
| 103 body->entry()->AddPredecessor(branch); | 122 body->entry()->AddPredecessor(branch); |
| 104 } | 123 } |
| 105 | 124 |
| 106 | 125 |
| 107 void EntryNode::Traverse(bool mark, | |
| 108 ZoneList<Node*>* preorder, | |
| 109 ZoneList<Node*>* postorder) { | |
| 110 ASSERT(successor_ != NULL); | |
| 111 preorder->Add(this); | |
| 112 if (!successor_->IsMarkedWith(mark)) { | |
| 113 successor_->MarkWith(mark); | |
| 114 successor_->Traverse(mark, preorder, postorder); | |
| 115 } | |
| 116 postorder->Add(this); | |
| 117 } | |
| 118 | |
| 119 | |
| 120 void ExitNode::Traverse(bool mark, | 126 void ExitNode::Traverse(bool mark, |
| 121 ZoneList<Node*>* preorder, | 127 ZoneList<Node*>* preorder, |
| 122 ZoneList<Node*>* postorder) { | 128 ZoneList<Node*>* postorder) { |
| 123 preorder->Add(this); | 129 preorder->Add(this); |
| 124 postorder->Add(this); | 130 postorder->Add(this); |
| 125 } | 131 } |
| 126 | 132 |
| 127 | 133 |
| 128 void BlockNode::Traverse(bool mark, | 134 void BlockNode::Traverse(bool mark, |
| 129 ZoneList<Node*>* preorder, | 135 ZoneList<Node*>* preorder, |
| 130 ZoneList<Node*>* postorder) { | 136 ZoneList<Node*>* postorder) { |
| 131 ASSERT(successor_ != NULL); | 137 ASSERT(successor_ != NULL); |
| 132 preorder->Add(this); | 138 preorder->Add(this); |
| 133 if (!successor_->IsMarkedWith(mark)) { | 139 if (!successor_->IsMarkedWith(mark)) { |
| 134 successor_->MarkWith(mark); | 140 successor_->MarkWith(mark); |
| 135 successor_->Traverse(mark, preorder, postorder); | 141 successor_->Traverse(mark, preorder, postorder); |
| 136 } | 142 } |
| 137 postorder->Add(this); | 143 postorder->Add(this); |
| 138 } | 144 } |
| 139 | 145 |
| 140 | 146 |
| 141 void BranchNode::Traverse(bool mark, | 147 void BranchNode::Traverse(bool mark, |
| 142 ZoneList<Node*>* preorder, | 148 ZoneList<Node*>* preorder, |
| 143 ZoneList<Node*>* postorder) { | 149 ZoneList<Node*>* postorder) { |
| 144 ASSERT(successor0_ != NULL && successor1_ != NULL); | 150 ASSERT(successor0_ != NULL && successor1_ != NULL); |
| 145 preorder->Add(this); | 151 preorder->Add(this); |
| 152 if (!successor1_->IsMarkedWith(mark)) { |
| 153 successor1_->MarkWith(mark); |
| 154 successor1_->Traverse(mark, preorder, postorder); |
| 155 } |
| 146 if (!successor0_->IsMarkedWith(mark)) { | 156 if (!successor0_->IsMarkedWith(mark)) { |
| 147 successor0_->MarkWith(mark); | 157 successor0_->MarkWith(mark); |
| 148 successor0_->Traverse(mark, preorder, postorder); | 158 successor0_->Traverse(mark, preorder, postorder); |
| 149 } | 159 } |
| 150 if (!successor1_->IsMarkedWith(mark)) { | |
| 151 successor1_->MarkWith(mark); | |
| 152 successor1_->Traverse(mark, preorder, postorder); | |
| 153 } | |
| 154 postorder->Add(this); | 160 postorder->Add(this); |
| 155 } | 161 } |
| 156 | 162 |
| 157 | 163 |
| 158 void JoinNode::Traverse(bool mark, | 164 void JoinNode::Traverse(bool mark, |
| 159 ZoneList<Node*>* preorder, | 165 ZoneList<Node*>* preorder, |
| 160 ZoneList<Node*>* postorder) { | 166 ZoneList<Node*>* postorder) { |
| 161 ASSERT(successor_ != NULL); | 167 ASSERT(successor_ != NULL); |
| 162 preorder->Add(this); | 168 preorder->Add(this); |
| 163 if (!successor_->IsMarkedWith(mark)) { | 169 if (!successor_->IsMarkedWith(mark)) { |
| 164 successor_->MarkWith(mark); | 170 successor_->MarkWith(mark); |
| 165 successor_->Traverse(mark, preorder, postorder); | 171 successor_->Traverse(mark, preorder, postorder); |
| 166 } | 172 } |
| 167 postorder->Add(this); | 173 postorder->Add(this); |
| 168 } | 174 } |
| 169 | 175 |
| 170 | 176 |
| 171 void FlowGraphBuilder::Build(FunctionLiteral* lit) { | 177 void FlowGraphBuilder::Build(FunctionLiteral* lit) { |
| 172 graph_ = FlowGraph::Empty(); | |
| 173 graph_.AppendNode(new EntryNode()); | |
| 174 global_exit_ = new ExitNode(); | 178 global_exit_ = new ExitNode(); |
| 175 VisitStatements(lit->body()); | 179 VisitStatements(lit->body()); |
| 176 | 180 |
| 177 if (HasStackOverflow()) { | 181 if (HasStackOverflow()) return; |
| 178 graph_ = FlowGraph::Empty(); | |
| 179 return; | |
| 180 } | |
| 181 | 182 |
| 183 // The graph can end with a branch node (if the function ended with a |
| 184 // loop). Maintain edge-split form (no join nodes or exit nodes as |
| 185 // successors to branch nodes). |
| 186 if (graph_.exit()->IsBranchNode()) graph_.AppendNode(new BlockNode()); |
| 182 graph_.AppendNode(global_exit_); | 187 graph_.AppendNode(global_exit_); |
| 183 | 188 |
| 184 // Build preorder and postorder traversal orders. All the nodes in | 189 // Build preorder and postorder traversal orders. All the nodes in |
| 185 // the graph have the same mark flag. For the traversal, use that | 190 // the graph have the same mark flag. For the traversal, use that |
| 186 // flag's negation. Traversal will flip all the flags. | 191 // flag's negation. Traversal will flip all the flags. |
| 187 bool mark = graph_.entry()->IsMarkedWith(false); | 192 bool mark = graph_.entry()->IsMarkedWith(false); |
| 188 graph_.entry()->MarkWith(mark); | 193 graph_.entry()->MarkWith(mark); |
| 189 graph_.entry()->Traverse(mark, &preorder_, &postorder_); | 194 graph_.entry()->Traverse(mark, &preorder_, &postorder_); |
| 190 } | 195 } |
| 191 | 196 |
| 192 | 197 |
| 198 // This function peels off one iteration of a for-loop. The return value |
| 199 // is either a block statement containing the peeled loop or NULL in case |
| 200 // there is a stack overflow. |
| 201 static Statement* PeelForLoop(ForStatement* stmt) { |
| 202 // Mark this for-statement as processed. |
| 203 stmt->set_peel_this_loop(false); |
| 204 |
| 205 // Create new block containing the init statement of the for-loop and |
| 206 // an if-statement containing the peeled iteration and the original |
| 207 // loop without the init-statement. |
| 208 Block* block = new Block(NULL, 2, false); |
| 209 if (stmt->init() != NULL) { |
| 210 Statement* init = stmt->init(); |
| 211 // The init statement gets the statement position of the for-loop |
| 212 // to make debugging of peeled loops possible. |
| 213 init->set_statement_pos(stmt->statement_pos()); |
| 214 block->AddStatement(init); |
| 215 } |
| 216 |
| 217 // Copy the condition. |
| 218 CopyAstVisitor copy_visitor; |
| 219 Expression* cond_copy = stmt->cond() != NULL |
| 220 ? copy_visitor.DeepCopyExpr(stmt->cond()) |
| 221 : new Literal(Factory::true_value()); |
| 222 if (copy_visitor.HasStackOverflow()) return NULL; |
| 223 |
| 224 // Construct a block with the peeled body and the rest of the for-loop. |
| 225 Statement* body_copy = copy_visitor.DeepCopyStmt(stmt->body()); |
| 226 if (copy_visitor.HasStackOverflow()) return NULL; |
| 227 |
| 228 Statement* next_copy = stmt->next() != NULL |
| 229 ? copy_visitor.DeepCopyStmt(stmt->next()) |
| 230 : new EmptyStatement(); |
| 231 if (copy_visitor.HasStackOverflow()) return NULL; |
| 232 |
| 233 Block* peeled_body = new Block(NULL, 3, false); |
| 234 peeled_body->AddStatement(body_copy); |
| 235 peeled_body->AddStatement(next_copy); |
| 236 peeled_body->AddStatement(stmt); |
| 237 |
| 238 // Remove the duplicated init statement from the for-statement. |
| 239 stmt->set_init(NULL); |
| 240 |
| 241 // Create new test at the top and add it to the newly created block. |
| 242 IfStatement* test = new IfStatement(cond_copy, |
| 243 peeled_body, |
| 244 new EmptyStatement()); |
| 245 block->AddStatement(test); |
| 246 return block; |
| 247 } |
| 248 |
| 249 |
| 250 void FlowGraphBuilder::VisitStatements(ZoneList<Statement*>* stmts) { |
| 251 for (int i = 0, len = stmts->length(); i < len; i++) { |
| 252 stmts->at(i) = ProcessStatement(stmts->at(i)); |
| 253 } |
| 254 } |
| 255 |
| 256 |
| 257 Statement* FlowGraphBuilder::ProcessStatement(Statement* stmt) { |
| 258 if (FLAG_loop_peeling && |
| 259 stmt->AsForStatement() != NULL && |
| 260 stmt->AsForStatement()->peel_this_loop()) { |
| 261 Statement* tmp_stmt = PeelForLoop(stmt->AsForStatement()); |
| 262 if (tmp_stmt == NULL) { |
| 263 SetStackOverflow(); |
| 264 } else { |
| 265 stmt = tmp_stmt; |
| 266 } |
| 267 } |
| 268 Visit(stmt); |
| 269 return stmt; |
| 270 } |
| 271 |
| 272 |
| 193 void FlowGraphBuilder::VisitDeclaration(Declaration* decl) { | 273 void FlowGraphBuilder::VisitDeclaration(Declaration* decl) { |
| 194 UNREACHABLE(); | 274 UNREACHABLE(); |
| 195 } | 275 } |
| 196 | 276 |
| 197 | 277 |
| 198 void FlowGraphBuilder::VisitBlock(Block* stmt) { | 278 void FlowGraphBuilder::VisitBlock(Block* stmt) { |
| 199 VisitStatements(stmt->statements()); | 279 VisitStatements(stmt->statements()); |
| 200 } | 280 } |
| 201 | 281 |
| 202 | 282 |
| 203 void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { | 283 void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 204 Visit(stmt->expression()); | 284 Visit(stmt->expression()); |
| 205 } | 285 } |
| 206 | 286 |
| 207 | 287 |
| 208 void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { | 288 void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { |
| 209 // Nothing to do. | 289 // Nothing to do. |
| 210 } | 290 } |
| 211 | 291 |
| 212 | 292 |
| 213 void FlowGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 293 void FlowGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
| 214 Visit(stmt->condition()); | 294 Visit(stmt->condition()); |
| 215 | 295 |
| 216 BranchNode* branch = new BranchNode(); | 296 BranchNode* branch = new BranchNode(); |
| 217 FlowGraph original = graph_; | 297 FlowGraph original = graph_; |
| 218 graph_ = FlowGraph::Empty(); | 298 graph_ = FlowGraph::Empty(); |
| 219 Visit(stmt->then_statement()); | 299 stmt->set_then_statement(ProcessStatement(stmt->then_statement())); |
| 220 | 300 |
| 221 FlowGraph left = graph_; | 301 FlowGraph left = graph_; |
| 222 graph_ = FlowGraph::Empty(); | 302 graph_ = FlowGraph::Empty(); |
| 223 Visit(stmt->else_statement()); | 303 stmt->set_else_statement(ProcessStatement(stmt->else_statement())); |
| 224 | 304 |
| 305 if (HasStackOverflow()) return; |
| 225 JoinNode* join = new JoinNode(); | 306 JoinNode* join = new JoinNode(); |
| 226 original.Split(branch, &left, &graph_, join); | 307 original.Split(branch, &left, &graph_, join); |
| 227 graph_ = original; | 308 graph_ = original; |
| 228 } | 309 } |
| 229 | 310 |
| 230 | 311 |
| 231 void FlowGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 312 void FlowGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
| 232 SetStackOverflow(); | 313 SetStackOverflow(); |
| 233 } | 314 } |
| 234 | 315 |
| 235 | 316 |
| 236 void FlowGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 317 void FlowGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
| 237 SetStackOverflow(); | 318 SetStackOverflow(); |
| 238 } | 319 } |
| 239 | 320 |
| 240 | 321 |
| 241 void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 322 void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| 242 Visit(stmt->expression()); | 323 SetStackOverflow(); |
| 243 graph_.AppendInstruction(stmt); | |
| 244 graph_.AppendNode(global_exit()); | |
| 245 } | 324 } |
| 246 | 325 |
| 247 | 326 |
| 248 void FlowGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { | 327 void FlowGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { |
| 249 Visit(stmt->expression()); | 328 SetStackOverflow(); |
| 250 graph_.AppendInstruction(stmt); | |
| 251 } | 329 } |
| 252 | 330 |
| 253 | 331 |
| 254 void FlowGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { | 332 void FlowGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { |
| 255 graph_.AppendInstruction(stmt); | 333 SetStackOverflow(); |
| 256 } | 334 } |
| 257 | 335 |
| 258 | 336 |
| 259 void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 337 void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
| 260 SetStackOverflow(); | 338 SetStackOverflow(); |
| 261 } | 339 } |
| 262 | 340 |
| 263 | 341 |
| 264 void FlowGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 342 void FlowGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 265 JoinNode* join = new JoinNode(); | 343 SetStackOverflow(); |
| 266 FlowGraph original = graph_; | |
| 267 graph_ = FlowGraph::Empty(); | |
| 268 Visit(stmt->body()); | |
| 269 | |
| 270 FlowGraph body = graph_; | |
| 271 graph_ = FlowGraph::Empty(); | |
| 272 Visit(stmt->cond()); | |
| 273 | |
| 274 BranchNode* branch = new BranchNode(); | |
| 275 | |
| 276 // Add body, condition and branch. | |
| 277 original.AppendNode(join); | |
| 278 original.AppendGraph(&body); | |
| 279 original.AppendGraph(&graph_); // The condition. | |
| 280 original.AppendNode(branch); | |
| 281 | |
| 282 // Tie the knot. | |
| 283 branch->AddSuccessor(join); | |
| 284 join->AddPredecessor(branch); | |
| 285 | |
| 286 graph_ = original; | |
| 287 } | 344 } |
| 288 | 345 |
| 289 | 346 |
| 290 void FlowGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 347 void FlowGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| 291 JoinNode* join = new JoinNode(); | 348 SetStackOverflow(); |
| 292 FlowGraph original = graph_; | |
| 293 graph_ = FlowGraph::Empty(); | |
| 294 Visit(stmt->cond()); | |
| 295 | |
| 296 BranchNode* branch = new BranchNode(); | |
| 297 FlowGraph condition = graph_; | |
| 298 graph_ = FlowGraph::Empty(); | |
| 299 Visit(stmt->body()); | |
| 300 | |
| 301 original.Loop(join, &condition, branch, &graph_); | |
| 302 graph_ = original; | |
| 303 } | 349 } |
| 304 | 350 |
| 305 | 351 |
| 306 void FlowGraphBuilder::VisitForStatement(ForStatement* stmt) { | 352 void FlowGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| 307 if (stmt->init() != NULL) Visit(stmt->init()); | 353 if (stmt->init() != NULL) stmt->set_init(ProcessStatement(stmt->init())); |
| 308 | 354 |
| 309 JoinNode* join = new JoinNode(); | 355 JoinNode* join = new JoinNode(); |
| 310 FlowGraph original = graph_; | 356 FlowGraph original = graph_; |
| 311 graph_ = FlowGraph::Empty(); | 357 graph_ = FlowGraph::Empty(); |
| 312 if (stmt->cond() != NULL) Visit(stmt->cond()); | 358 if (stmt->cond() != NULL) Visit(stmt->cond()); |
| 313 | 359 |
| 314 BranchNode* branch = new BranchNode(); | 360 BranchNode* branch = new BranchNode(); |
| 315 FlowGraph condition = graph_; | 361 FlowGraph condition = graph_; |
| 316 graph_ = FlowGraph::Empty(); | 362 graph_ = FlowGraph::Empty(); |
| 317 Visit(stmt->body()); | 363 stmt->set_body(ProcessStatement(stmt->body())); |
| 318 | 364 |
| 319 if (stmt->next() != NULL) Visit(stmt->next()); | 365 if (stmt->next() != NULL) stmt->set_next(ProcessStatement(stmt->next())); |
| 320 | 366 |
| 367 if (HasStackOverflow()) return; |
| 321 original.Loop(join, &condition, branch, &graph_); | 368 original.Loop(join, &condition, branch, &graph_); |
| 322 graph_ = original; | 369 graph_ = original; |
| 323 } | 370 } |
| 324 | 371 |
| 325 | 372 |
| 326 void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 373 void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| 327 Visit(stmt->enumerable()); | 374 SetStackOverflow(); |
| 328 | |
| 329 JoinNode* join = new JoinNode(); | |
| 330 FlowGraph empty; | |
| 331 BranchNode* branch = new BranchNode(); | |
| 332 FlowGraph original = graph_; | |
| 333 graph_ = FlowGraph::Empty(); | |
| 334 Visit(stmt->body()); | |
| 335 | |
| 336 original.Loop(join, &empty, branch, &graph_); | |
| 337 graph_ = original; | |
| 338 } | 375 } |
| 339 | 376 |
| 340 | 377 |
| 341 void FlowGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 378 void FlowGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 342 SetStackOverflow(); | 379 SetStackOverflow(); |
| 343 } | 380 } |
| 344 | 381 |
| 345 | 382 |
| 346 void FlowGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 383 void FlowGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 347 SetStackOverflow(); | 384 SetStackOverflow(); |
| 348 } | 385 } |
| 349 | 386 |
| 350 | 387 |
| 351 void FlowGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 388 void FlowGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 352 graph_.AppendInstruction(stmt); | 389 SetStackOverflow(); |
| 353 } | 390 } |
| 354 | 391 |
| 355 | 392 |
| 356 void FlowGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 393 void FlowGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 357 graph_.AppendInstruction(expr); | 394 SetStackOverflow(); |
| 358 } | 395 } |
| 359 | 396 |
| 360 | 397 |
| 361 void FlowGraphBuilder::VisitFunctionBoilerplateLiteral( | 398 void FlowGraphBuilder::VisitFunctionBoilerplateLiteral( |
| 362 FunctionBoilerplateLiteral* expr) { | 399 FunctionBoilerplateLiteral* expr) { |
| 363 graph_.AppendInstruction(expr); | 400 SetStackOverflow(); |
| 364 } | 401 } |
| 365 | 402 |
| 366 | 403 |
| 367 void FlowGraphBuilder::VisitConditional(Conditional* expr) { | 404 void FlowGraphBuilder::VisitConditional(Conditional* expr) { |
| 368 Visit(expr->condition()); | 405 SetStackOverflow(); |
| 369 | |
| 370 BranchNode* branch = new BranchNode(); | |
| 371 FlowGraph original = graph_; | |
| 372 graph_ = FlowGraph::Empty(); | |
| 373 Visit(expr->then_expression()); | |
| 374 | |
| 375 FlowGraph left = graph_; | |
| 376 graph_ = FlowGraph::Empty(); | |
| 377 Visit(expr->else_expression()); | |
| 378 | |
| 379 JoinNode* join = new JoinNode(); | |
| 380 original.Split(branch, &left, &graph_, join); | |
| 381 graph_ = original; | |
| 382 } | 406 } |
| 383 | 407 |
| 384 | 408 |
| 385 void FlowGraphBuilder::VisitSlot(Slot* expr) { | 409 void FlowGraphBuilder::VisitSlot(Slot* expr) { |
| 386 UNREACHABLE(); | 410 UNREACHABLE(); |
| 387 } | 411 } |
| 388 | 412 |
| 389 | 413 |
| 390 void FlowGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 414 void FlowGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 391 graph_.AppendInstruction(expr); | 415 graph_.AppendInstruction(expr); |
| 392 } | 416 } |
| 393 | 417 |
| 394 | 418 |
| 395 void FlowGraphBuilder::VisitLiteral(Literal* expr) { | 419 void FlowGraphBuilder::VisitLiteral(Literal* expr) { |
| 396 graph_.AppendInstruction(expr); | 420 graph_.AppendInstruction(expr); |
| 397 } | 421 } |
| 398 | 422 |
| 399 | 423 |
| 400 void FlowGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 424 void FlowGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 401 graph_.AppendInstruction(expr); | 425 SetStackOverflow(); |
| 402 } | 426 } |
| 403 | 427 |
| 404 | 428 |
| 405 void FlowGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 429 void FlowGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 406 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); | 430 SetStackOverflow(); |
| 407 for (int i = 0, len = properties->length(); i < len; i++) { | |
| 408 Visit(properties->at(i)->value()); | |
| 409 } | |
| 410 graph_.AppendInstruction(expr); | |
| 411 } | 431 } |
| 412 | 432 |
| 413 | 433 |
| 414 void FlowGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 434 void FlowGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 415 ZoneList<Expression*>* values = expr->values(); | 435 SetStackOverflow(); |
| 416 for (int i = 0, len = values->length(); i < len; i++) { | |
| 417 Visit(values->at(i)); | |
| 418 } | |
| 419 graph_.AppendInstruction(expr); | |
| 420 } | 436 } |
| 421 | 437 |
| 422 | 438 |
| 423 void FlowGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 439 void FlowGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| 424 graph_.AppendInstruction(expr); | 440 SetStackOverflow(); |
| 425 } | 441 } |
| 426 | 442 |
| 427 | 443 |
| 428 void FlowGraphBuilder::VisitAssignment(Assignment* expr) { | 444 void FlowGraphBuilder::VisitAssignment(Assignment* expr) { |
| 429 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 445 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
| 430 Property* prop = expr->target()->AsProperty(); | 446 Property* prop = expr->target()->AsProperty(); |
| 431 // Left-hand side can be a variable or property (or reference error) but | 447 // Left-hand side can be a variable or property (or reference error) but |
| 432 // not both. | 448 // not both. |
| 433 ASSERT(var == NULL || prop == NULL); | 449 ASSERT(var == NULL || prop == NULL); |
| 434 if (var != NULL) { | 450 if (var != NULL) { |
| 451 if (expr->is_compound()) Visit(expr->target()); |
| 435 Visit(expr->value()); | 452 Visit(expr->value()); |
| 436 if (var->IsStackAllocated()) definitions_.Add(expr); | 453 if (var->IsStackAllocated()) { |
| 454 expr->set_num(definitions_.length()); |
| 455 definitions_.Add(expr); |
| 456 } |
| 437 | 457 |
| 438 } else if (prop != NULL) { | 458 } else if (prop != NULL) { |
| 439 Visit(prop->obj()); | 459 Visit(prop->obj()); |
| 440 if (!prop->key()->IsPropertyName()) Visit(prop->key()); | 460 if (!prop->key()->IsPropertyName()) Visit(prop->key()); |
| 441 Visit(expr->value()); | 461 Visit(expr->value()); |
| 442 } | 462 } |
| 463 |
| 464 if (HasStackOverflow()) return; |
| 443 graph_.AppendInstruction(expr); | 465 graph_.AppendInstruction(expr); |
| 444 } | 466 } |
| 445 | 467 |
| 446 | 468 |
| 447 void FlowGraphBuilder::VisitThrow(Throw* expr) { | 469 void FlowGraphBuilder::VisitThrow(Throw* expr) { |
| 448 Visit(expr->exception()); | 470 SetStackOverflow(); |
| 449 graph_.AppendInstruction(expr); | |
| 450 } | 471 } |
| 451 | 472 |
| 452 | 473 |
| 453 void FlowGraphBuilder::VisitProperty(Property* expr) { | 474 void FlowGraphBuilder::VisitProperty(Property* expr) { |
| 454 Visit(expr->obj()); | 475 Visit(expr->obj()); |
| 455 if (!expr->key()->IsPropertyName()) Visit(expr->key()); | 476 if (!expr->key()->IsPropertyName()) Visit(expr->key()); |
| 477 |
| 478 if (HasStackOverflow()) return; |
| 456 graph_.AppendInstruction(expr); | 479 graph_.AppendInstruction(expr); |
| 457 } | 480 } |
| 458 | 481 |
| 459 | 482 |
| 460 void FlowGraphBuilder::VisitCall(Call* expr) { | 483 void FlowGraphBuilder::VisitCall(Call* expr) { |
| 461 Visit(expr->expression()); | 484 Visit(expr->expression()); |
| 462 ZoneList<Expression*>* arguments = expr->arguments(); | 485 ZoneList<Expression*>* arguments = expr->arguments(); |
| 463 for (int i = 0, len = arguments->length(); i < len; i++) { | 486 for (int i = 0, len = arguments->length(); i < len; i++) { |
| 464 Visit(arguments->at(i)); | 487 Visit(arguments->at(i)); |
| 465 } | 488 } |
| 489 |
| 490 if (HasStackOverflow()) return; |
| 466 graph_.AppendInstruction(expr); | 491 graph_.AppendInstruction(expr); |
| 467 } | 492 } |
| 468 | 493 |
| 469 | 494 |
| 470 void FlowGraphBuilder::VisitCallNew(CallNew* expr) { | 495 void FlowGraphBuilder::VisitCallNew(CallNew* expr) { |
| 471 Visit(expr->expression()); | 496 SetStackOverflow(); |
| 472 ZoneList<Expression*>* arguments = expr->arguments(); | |
| 473 for (int i = 0, len = arguments->length(); i < len; i++) { | |
| 474 Visit(arguments->at(i)); | |
| 475 } | |
| 476 graph_.AppendInstruction(expr); | |
| 477 } | 497 } |
| 478 | 498 |
| 479 | 499 |
| 480 void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 500 void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 481 ZoneList<Expression*>* arguments = expr->arguments(); | 501 SetStackOverflow(); |
| 482 for (int i = 0, len = arguments->length(); i < len; i++) { | |
| 483 Visit(arguments->at(i)); | |
| 484 } | |
| 485 graph_.AppendInstruction(expr); | |
| 486 } | 502 } |
| 487 | 503 |
| 488 | 504 |
| 489 void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 505 void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| 490 Visit(expr->expression()); | 506 switch (expr->op()) { |
| 491 graph_.AppendInstruction(expr); | 507 case Token::NOT: |
| 508 case Token::BIT_NOT: |
| 509 case Token::DELETE: |
| 510 case Token::TYPEOF: |
| 511 case Token::VOID: |
| 512 SetStackOverflow(); |
| 513 break; |
| 514 |
| 515 case Token::ADD: |
| 516 case Token::SUB: |
| 517 Visit(expr->expression()); |
| 518 if (HasStackOverflow()) return; |
| 519 graph_.AppendInstruction(expr); |
| 520 break; |
| 521 |
| 522 default: |
| 523 UNREACHABLE(); |
| 524 } |
| 492 } | 525 } |
| 493 | 526 |
| 494 | 527 |
| 495 void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) { | 528 void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| 496 Visit(expr->expression()); | 529 Visit(expr->expression()); |
| 497 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 530 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| 498 if (var != NULL && var->IsStackAllocated()) { | 531 if (var != NULL && var->IsStackAllocated()) { |
| 532 expr->set_num(definitions_.length()); |
| 499 definitions_.Add(expr); | 533 definitions_.Add(expr); |
| 500 } | 534 } |
| 535 |
| 536 if (HasStackOverflow()) return; |
| 501 graph_.AppendInstruction(expr); | 537 graph_.AppendInstruction(expr); |
| 502 } | 538 } |
| 503 | 539 |
| 504 | 540 |
| 505 void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 541 void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| 506 Visit(expr->left()); | |
| 507 | |
| 508 switch (expr->op()) { | 542 switch (expr->op()) { |
| 509 case Token::COMMA: | 543 case Token::COMMA: |
| 510 Visit(expr->right()); | 544 case Token::OR: |
| 545 case Token::AND: |
| 546 SetStackOverflow(); |
| 511 break; | 547 break; |
| 512 | 548 |
| 513 case Token::OR: { | |
| 514 BranchNode* branch = new BranchNode(); | |
| 515 FlowGraph original = graph_; | |
| 516 graph_ = FlowGraph::Empty(); | |
| 517 Visit(expr->right()); | |
| 518 FlowGraph empty; | |
| 519 JoinNode* join = new JoinNode(); | |
| 520 original.Split(branch, &empty, &graph_, join); | |
| 521 graph_ = original; | |
| 522 break; | |
| 523 } | |
| 524 | |
| 525 case Token::AND: { | |
| 526 BranchNode* branch = new BranchNode(); | |
| 527 FlowGraph original = graph_; | |
| 528 graph_ = FlowGraph::Empty(); | |
| 529 Visit(expr->right()); | |
| 530 FlowGraph empty; | |
| 531 JoinNode* join = new JoinNode(); | |
| 532 original.Split(branch, &graph_, &empty, join); | |
| 533 graph_ = original; | |
| 534 break; | |
| 535 } | |
| 536 | |
| 537 case Token::BIT_OR: | 549 case Token::BIT_OR: |
| 538 case Token::BIT_XOR: | 550 case Token::BIT_XOR: |
| 539 case Token::BIT_AND: | 551 case Token::BIT_AND: |
| 540 case Token::SHL: | 552 case Token::SHL: |
| 541 case Token::SAR: | |
| 542 case Token::SHR: | 553 case Token::SHR: |
| 543 case Token::ADD: | 554 case Token::ADD: |
| 544 case Token::SUB: | 555 case Token::SUB: |
| 545 case Token::MUL: | 556 case Token::MUL: |
| 546 case Token::DIV: | 557 case Token::DIV: |
| 547 case Token::MOD: | 558 case Token::MOD: |
| 559 case Token::SAR: |
| 560 Visit(expr->left()); |
| 548 Visit(expr->right()); | 561 Visit(expr->right()); |
| 562 if (HasStackOverflow()) return; |
| 549 graph_.AppendInstruction(expr); | 563 graph_.AppendInstruction(expr); |
| 550 break; | 564 break; |
| 551 | 565 |
| 552 default: | 566 default: |
| 553 UNREACHABLE(); | 567 UNREACHABLE(); |
| 554 } | 568 } |
| 555 } | 569 } |
| 556 | 570 |
| 557 | 571 |
| 558 void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 572 void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 559 Visit(expr->left()); | 573 switch (expr->op()) { |
| 560 Visit(expr->right()); | 574 case Token::EQ: |
| 561 graph_.AppendInstruction(expr); | 575 case Token::NE: |
| 576 case Token::EQ_STRICT: |
| 577 case Token::NE_STRICT: |
| 578 case Token::INSTANCEOF: |
| 579 case Token::IN: |
| 580 SetStackOverflow(); |
| 581 break; |
| 582 |
| 583 case Token::LT: |
| 584 case Token::GT: |
| 585 case Token::LTE: |
| 586 case Token::GTE: |
| 587 Visit(expr->left()); |
| 588 Visit(expr->right()); |
| 589 if (HasStackOverflow()) return; |
| 590 graph_.AppendInstruction(expr); |
| 591 break; |
| 592 |
| 593 default: |
| 594 UNREACHABLE(); |
| 595 } |
| 562 } | 596 } |
| 563 | 597 |
| 564 | 598 |
| 565 void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 599 void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 566 graph_.AppendInstruction(expr); | 600 SetStackOverflow(); |
| 567 } | 601 } |
| 568 | 602 |
| 569 | 603 |
| 570 void AstLabeler::Label(CompilationInfo* info) { | 604 void AstLabeler::Label(CompilationInfo* info) { |
| 571 info_ = info; | 605 info_ = info; |
| 572 VisitStatements(info_->function()->body()); | 606 VisitStatements(info_->function()->body()); |
| 573 } | 607 } |
| 574 | 608 |
| 575 | 609 |
| 576 void AstLabeler::VisitStatements(ZoneList<Statement*>* stmts) { | 610 void AstLabeler::VisitStatements(ZoneList<Statement*>* stmts) { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 void AstLabeler::VisitThisFunction(ThisFunction* expr) { | 838 void AstLabeler::VisitThisFunction(ThisFunction* expr) { |
| 805 UNREACHABLE(); | 839 UNREACHABLE(); |
| 806 } | 840 } |
| 807 | 841 |
| 808 | 842 |
| 809 void AstLabeler::VisitDeclaration(Declaration* decl) { | 843 void AstLabeler::VisitDeclaration(Declaration* decl) { |
| 810 UNREACHABLE(); | 844 UNREACHABLE(); |
| 811 } | 845 } |
| 812 | 846 |
| 813 | 847 |
| 814 ZoneList<Expression*>* VarUseMap::Lookup(Variable* var) { | 848 AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(FunctionLiteral* fun) |
| 815 HashMap::Entry* entry = HashMap::Lookup(var, var->name()->Hash(), true); | 849 : fun_(fun), |
| 816 if (entry->value == NULL) { | 850 av_(fun->scope()->num_parameters() + fun->scope()->num_stack_slots()) {} |
| 817 entry->value = new ZoneList<Expression*>(1); | 851 |
| 818 } | 852 |
| 819 return reinterpret_cast<ZoneList<Expression*>*>(entry->value); | 853 void AssignedVariablesAnalyzer::Analyze() { |
| 820 } | 854 ASSERT(av_.length() > 0); |
| 821 | 855 VisitStatements(fun_->body()); |
| 822 | 856 } |
| 823 void LivenessAnalyzer::Analyze(FunctionLiteral* fun) { | 857 |
| 824 // Process the function body. | 858 |
| 825 VisitStatements(fun->body()); | 859 Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) { |
| 826 | 860 // The loop must have all necessary parts. |
| 827 // All variables are implicitly defined at the function start. | 861 if (stmt->init() == NULL || stmt->cond() == NULL || stmt->next() == NULL) { |
| 828 // Record a definition of all variables live at function entry. | 862 return NULL; |
| 829 for (HashMap::Entry* p = live_vars_.Start(); | 863 } |
| 830 p != NULL; | 864 // The initialization statement has to be a simple assignment. |
| 831 p = live_vars_.Next(p)) { | 865 Assignment* init = stmt->init()->StatementAsSimpleAssignment(); |
| 832 Variable* var = reinterpret_cast<Variable*>(p->key); | 866 if (init == NULL) return NULL; |
| 833 RecordDef(var, fun); | 867 |
| 834 } | 868 // We only deal with local variables. |
| 835 } | 869 Variable* loop_var = init->target()->AsVariableProxy()->AsVariable(); |
| 836 | 870 if (loop_var == NULL || !loop_var->IsStackAllocated()) return NULL; |
| 837 | 871 |
| 838 void LivenessAnalyzer::VisitStatements(ZoneList<Statement*>* stmts) { | 872 // The initial value has to be a smi. |
| 839 // Visit statements right-to-left. | 873 Literal* init_lit = init->value()->AsLiteral(); |
| 840 for (int i = stmts->length() - 1; i >= 0; i--) { | 874 if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL; |
| 841 Visit(stmts->at(i)); | 875 int init_value = Smi::cast(*init_lit->handle())->value(); |
| 842 } | 876 |
| 843 } | 877 // The condition must be a compare of variable with <, <=, >, or >=. |
| 844 | 878 CompareOperation* cond = stmt->cond()->AsCompareOperation(); |
| 845 | 879 if (cond == NULL) return NULL; |
| 846 void LivenessAnalyzer::RecordUse(Variable* var, Expression* expr) { | 880 if (cond->op() != Token::LT |
| 847 ASSERT(var->is_global() || var->is_this()); | 881 && cond->op() != Token::LTE |
| 848 ZoneList<Expression*>* uses = live_vars_.Lookup(var); | 882 && cond->op() != Token::GT |
| 849 uses->Add(expr); | 883 && cond->op() != Token::GTE) return NULL; |
| 850 } | 884 |
| 851 | 885 // The lhs must be the same variable as in the init expression. |
| 852 | 886 if (cond->left()->AsVariableProxy()->AsVariable() != loop_var) return NULL; |
| 853 void LivenessAnalyzer::RecordDef(Variable* var, Expression* expr) { | 887 |
| 854 ASSERT(var->is_global() || var->is_this()); | 888 // The rhs must be a smi. |
| 855 | 889 Literal* term_lit = cond->right()->AsLiteral(); |
| 856 // We do not support other expressions that can define variables. | 890 if (term_lit == NULL || !term_lit->handle()->IsSmi()) return NULL; |
| 857 ASSERT(expr->AsFunctionLiteral() != NULL); | 891 int term_value = Smi::cast(*term_lit->handle())->value(); |
| 858 | 892 |
| 859 // Add the variable to the list of defined variables. | 893 // The count operation updates the same variable as in the init expression. |
| 860 if (expr->defined_vars() == NULL) { | 894 CountOperation* update = stmt->next()->StatementAsCountOperation(); |
| 861 expr->set_defined_vars(new ZoneList<DefinitionInfo*>(1)); | 895 if (update == NULL) return NULL; |
| 862 } | 896 if (update->expression()->AsVariableProxy()->AsVariable() != loop_var) { |
| 863 DefinitionInfo* def = new DefinitionInfo(); | 897 return NULL; |
| 864 expr->AsFunctionLiteral()->defined_vars()->Add(def); | 898 } |
| 865 | 899 |
| 866 // Compute the last use of the definition. The variable uses are | 900 // The direction of the count operation must agree with the start and the end |
| 867 // inserted in reversed evaluation order. The first element | 901 // value. We currently do not allow the initial value to be the same as the |
| 868 // in the list of live uses is the last use. | 902 // terminal value. This _would_ be ok as long as the loop body never executes |
| 869 ZoneList<Expression*>* uses = live_vars_.Lookup(var); | 903 // or executes exactly one time. |
| 870 while (uses->length() > 0) { | 904 if (init_value == term_value) return NULL; |
| 871 Expression* use_site = uses->RemoveLast(); | 905 if (init_value < term_value && update->op() != Token::INC) return NULL; |
| 872 use_site->set_var_def(def); | 906 if (init_value > term_value && update->op() != Token::DEC) return NULL; |
| 873 if (uses->length() == 0) { | 907 |
| 874 def->set_last_use(use_site); | 908 // Check that the update operation cannot overflow the smi range. This can |
| 909 // occur in the two cases where the loop bound is equal to the largest or |
| 910 // smallest smi. |
| 911 if (update->op() == Token::INC && term_value == Smi::kMaxValue) return NULL; |
| 912 if (update->op() == Token::DEC && term_value == Smi::kMinValue) return NULL; |
| 913 |
| 914 // Found a smi loop variable. |
| 915 return loop_var; |
| 916 } |
| 917 |
| 918 int AssignedVariablesAnalyzer::BitIndex(Variable* var) { |
| 919 ASSERT(var != NULL); |
| 920 ASSERT(var->IsStackAllocated()); |
| 921 Slot* slot = var->slot(); |
| 922 if (slot->type() == Slot::PARAMETER) { |
| 923 return slot->index(); |
| 924 } else { |
| 925 return fun_->scope()->num_parameters() + slot->index(); |
| 926 } |
| 927 } |
| 928 |
| 929 |
| 930 void AssignedVariablesAnalyzer::RecordAssignedVar(Variable* var) { |
| 931 ASSERT(var != NULL); |
| 932 if (var->IsStackAllocated()) { |
| 933 av_.Add(BitIndex(var)); |
| 934 } |
| 935 } |
| 936 |
| 937 |
| 938 void AssignedVariablesAnalyzer::MarkIfTrivial(Expression* expr) { |
| 939 Variable* var = expr->AsVariableProxy()->AsVariable(); |
| 940 if (var != NULL && |
| 941 var->IsStackAllocated() && |
| 942 !var->is_arguments() && |
| 943 var->mode() != Variable::CONST && |
| 944 (var->is_this() || !av_.Contains(BitIndex(var)))) { |
| 945 expr->AsVariableProxy()->set_is_trivial(true); |
| 946 } |
| 947 } |
| 948 |
| 949 |
| 950 void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) { |
| 951 BitVector saved_av(av_); |
| 952 av_.Clear(); |
| 953 Visit(expr); |
| 954 av_.Union(saved_av); |
| 955 } |
| 956 |
| 957 void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) { |
| 958 VisitStatements(stmt->statements()); |
| 959 } |
| 960 |
| 961 |
| 962 void AssignedVariablesAnalyzer::VisitExpressionStatement( |
| 963 ExpressionStatement* stmt) { |
| 964 ProcessExpression(stmt->expression()); |
| 965 } |
| 966 |
| 967 |
| 968 void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) { |
| 969 // Do nothing. |
| 970 } |
| 971 |
| 972 |
| 973 void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) { |
| 974 ProcessExpression(stmt->condition()); |
| 975 Visit(stmt->then_statement()); |
| 976 Visit(stmt->else_statement()); |
| 977 } |
| 978 |
| 979 |
| 980 void AssignedVariablesAnalyzer::VisitContinueStatement( |
| 981 ContinueStatement* stmt) { |
| 982 // Nothing to do. |
| 983 } |
| 984 |
| 985 |
| 986 void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) { |
| 987 // Nothing to do. |
| 988 } |
| 989 |
| 990 |
| 991 void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) { |
| 992 ProcessExpression(stmt->expression()); |
| 993 } |
| 994 |
| 995 |
| 996 void AssignedVariablesAnalyzer::VisitWithEnterStatement( |
| 997 WithEnterStatement* stmt) { |
| 998 ProcessExpression(stmt->expression()); |
| 999 } |
| 1000 |
| 1001 |
| 1002 void AssignedVariablesAnalyzer::VisitWithExitStatement( |
| 1003 WithExitStatement* stmt) { |
| 1004 // Nothing to do. |
| 1005 } |
| 1006 |
| 1007 |
| 1008 void AssignedVariablesAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) { |
| 1009 BitVector result(av_); |
| 1010 av_.Clear(); |
| 1011 Visit(stmt->tag()); |
| 1012 result.Union(av_); |
| 1013 for (int i = 0; i < stmt->cases()->length(); i++) { |
| 1014 CaseClause* clause = stmt->cases()->at(i); |
| 1015 if (!clause->is_default()) { |
| 1016 av_.Clear(); |
| 1017 Visit(clause->label()); |
| 1018 result.Union(av_); |
| 875 } | 1019 } |
| 876 } | 1020 VisitStatements(clause->statements()); |
| 877 } | 1021 } |
| 878 | 1022 av_.Union(result); |
| 879 | 1023 } |
| 880 // Visitor functions for live variable analysis. | 1024 |
| 881 void LivenessAnalyzer::VisitDeclaration(Declaration* decl) { | 1025 |
| 1026 void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 1027 ProcessExpression(stmt->cond()); |
| 1028 Visit(stmt->body()); |
| 1029 } |
| 1030 |
| 1031 |
| 1032 void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) { |
| 1033 ProcessExpression(stmt->cond()); |
| 1034 Visit(stmt->body()); |
| 1035 } |
| 1036 |
| 1037 |
| 1038 void AssignedVariablesAnalyzer::VisitForStatement(ForStatement* stmt) { |
| 1039 if (stmt->init() != NULL) Visit(stmt->init()); |
| 1040 |
| 1041 if (stmt->cond() != NULL) ProcessExpression(stmt->cond()); |
| 1042 |
| 1043 if (stmt->next() != NULL) Visit(stmt->next()); |
| 1044 |
| 1045 // Process loop body. After visiting the loop body av_ contains |
| 1046 // the assigned variables of the loop body. |
| 1047 BitVector saved_av(av_); |
| 1048 av_.Clear(); |
| 1049 Visit(stmt->body()); |
| 1050 |
| 1051 Variable* var = FindSmiLoopVariable(stmt); |
| 1052 if (var != NULL && !av_.Contains(BitIndex(var))) { |
| 1053 stmt->set_loop_variable(var); |
| 1054 } |
| 1055 |
| 1056 av_.Union(saved_av); |
| 1057 } |
| 1058 |
| 1059 |
| 1060 void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) { |
| 1061 ProcessExpression(stmt->each()); |
| 1062 ProcessExpression(stmt->enumerable()); |
| 1063 Visit(stmt->body()); |
| 1064 } |
| 1065 |
| 1066 |
| 1067 void AssignedVariablesAnalyzer::VisitTryCatchStatement( |
| 1068 TryCatchStatement* stmt) { |
| 1069 Visit(stmt->try_block()); |
| 1070 Visit(stmt->catch_block()); |
| 1071 } |
| 1072 |
| 1073 |
| 1074 void AssignedVariablesAnalyzer::VisitTryFinallyStatement( |
| 1075 TryFinallyStatement* stmt) { |
| 1076 Visit(stmt->try_block()); |
| 1077 Visit(stmt->finally_block()); |
| 1078 } |
| 1079 |
| 1080 |
| 1081 void AssignedVariablesAnalyzer::VisitDebuggerStatement( |
| 1082 DebuggerStatement* stmt) { |
| 1083 // Nothing to do. |
| 1084 } |
| 1085 |
| 1086 |
| 1087 void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 1088 // Nothing to do. |
| 1089 ASSERT(av_.IsEmpty()); |
| 1090 } |
| 1091 |
| 1092 |
| 1093 void AssignedVariablesAnalyzer::VisitFunctionBoilerplateLiteral( |
| 1094 FunctionBoilerplateLiteral* expr) { |
| 1095 // Nothing to do. |
| 1096 ASSERT(av_.IsEmpty()); |
| 1097 } |
| 1098 |
| 1099 |
| 1100 void AssignedVariablesAnalyzer::VisitConditional(Conditional* expr) { |
| 1101 ASSERT(av_.IsEmpty()); |
| 1102 |
| 1103 Visit(expr->condition()); |
| 1104 |
| 1105 BitVector result(av_); |
| 1106 av_.Clear(); |
| 1107 Visit(expr->then_expression()); |
| 1108 result.Union(av_); |
| 1109 |
| 1110 av_.Clear(); |
| 1111 Visit(expr->else_expression()); |
| 1112 av_.Union(result); |
| 1113 } |
| 1114 |
| 1115 |
| 1116 void AssignedVariablesAnalyzer::VisitSlot(Slot* expr) { |
| 882 UNREACHABLE(); | 1117 UNREACHABLE(); |
| 883 } | 1118 } |
| 884 | 1119 |
| 885 | 1120 |
| 886 void LivenessAnalyzer::VisitBlock(Block* stmt) { | 1121 void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) { |
| 887 VisitStatements(stmt->statements()); | 1122 // Nothing to do. |
| 888 } | 1123 ASSERT(av_.IsEmpty()); |
| 889 | 1124 } |
| 890 | 1125 |
| 891 void LivenessAnalyzer::VisitExpressionStatement( | 1126 |
| 892 ExpressionStatement* stmt) { | 1127 void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) { |
| 893 Visit(stmt->expression()); | 1128 // Nothing to do. |
| 894 } | 1129 ASSERT(av_.IsEmpty()); |
| 895 | 1130 } |
| 896 | 1131 |
| 897 void LivenessAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) { | 1132 |
| 898 // Do nothing. | 1133 void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 899 } | 1134 // Nothing to do. |
| 900 | 1135 ASSERT(av_.IsEmpty()); |
| 901 | 1136 } |
| 902 void LivenessAnalyzer::VisitIfStatement(IfStatement* stmt) { | 1137 |
| 1138 |
| 1139 void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) { |
| 1140 ASSERT(av_.IsEmpty()); |
| 1141 BitVector result(av_.length()); |
| 1142 for (int i = 0; i < expr->properties()->length(); i++) { |
| 1143 Visit(expr->properties()->at(i)->value()); |
| 1144 result.Union(av_); |
| 1145 av_.Clear(); |
| 1146 } |
| 1147 av_ = result; |
| 1148 } |
| 1149 |
| 1150 |
| 1151 void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) { |
| 1152 ASSERT(av_.IsEmpty()); |
| 1153 BitVector result(av_.length()); |
| 1154 for (int i = 0; i < expr->values()->length(); i++) { |
| 1155 Visit(expr->values()->at(i)); |
| 1156 result.Union(av_); |
| 1157 av_.Clear(); |
| 1158 } |
| 1159 av_ = result; |
| 1160 } |
| 1161 |
| 1162 |
| 1163 void AssignedVariablesAnalyzer::VisitCatchExtensionObject( |
| 1164 CatchExtensionObject* expr) { |
| 1165 ASSERT(av_.IsEmpty()); |
| 1166 Visit(expr->key()); |
| 1167 ProcessExpression(expr->value()); |
| 1168 } |
| 1169 |
| 1170 |
| 1171 void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) { |
| 1172 ASSERT(av_.IsEmpty()); |
| 1173 |
| 1174 if (expr->target()->AsProperty() != NULL) { |
| 1175 // Visit receiver and key of property store and rhs. |
| 1176 Visit(expr->target()->AsProperty()->obj()); |
| 1177 ProcessExpression(expr->target()->AsProperty()->key()); |
| 1178 ProcessExpression(expr->value()); |
| 1179 |
| 1180 // If we have a variable as a receiver in a property store, check if |
| 1181 // we can mark it as trivial. |
| 1182 MarkIfTrivial(expr->target()->AsProperty()->obj()); |
| 1183 } else { |
| 1184 Visit(expr->target()); |
| 1185 ProcessExpression(expr->value()); |
| 1186 |
| 1187 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
| 1188 if (var != NULL) RecordAssignedVar(var); |
| 1189 } |
| 1190 } |
| 1191 |
| 1192 |
| 1193 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) { |
| 1194 ASSERT(av_.IsEmpty()); |
| 1195 Visit(expr->exception()); |
| 1196 } |
| 1197 |
| 1198 |
| 1199 void AssignedVariablesAnalyzer::VisitProperty(Property* expr) { |
| 1200 ASSERT(av_.IsEmpty()); |
| 1201 Visit(expr->obj()); |
| 1202 ProcessExpression(expr->key()); |
| 1203 |
| 1204 // In case we have a variable as a receiver, check if we can mark |
| 1205 // it as trivial. |
| 1206 MarkIfTrivial(expr->obj()); |
| 1207 } |
| 1208 |
| 1209 |
| 1210 void AssignedVariablesAnalyzer::VisitCall(Call* expr) { |
| 1211 ASSERT(av_.IsEmpty()); |
| 1212 Visit(expr->expression()); |
| 1213 BitVector result(av_); |
| 1214 for (int i = 0; i < expr->arguments()->length(); i++) { |
| 1215 av_.Clear(); |
| 1216 Visit(expr->arguments()->at(i)); |
| 1217 result.Union(av_); |
| 1218 } |
| 1219 av_ = result; |
| 1220 } |
| 1221 |
| 1222 |
| 1223 void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) { |
| 1224 ASSERT(av_.IsEmpty()); |
| 1225 Visit(expr->expression()); |
| 1226 BitVector result(av_); |
| 1227 for (int i = 0; i < expr->arguments()->length(); i++) { |
| 1228 av_.Clear(); |
| 1229 Visit(expr->arguments()->at(i)); |
| 1230 result.Union(av_); |
| 1231 } |
| 1232 av_ = result; |
| 1233 } |
| 1234 |
| 1235 |
| 1236 void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) { |
| 1237 ASSERT(av_.IsEmpty()); |
| 1238 BitVector result(av_); |
| 1239 for (int i = 0; i < expr->arguments()->length(); i++) { |
| 1240 av_.Clear(); |
| 1241 Visit(expr->arguments()->at(i)); |
| 1242 result.Union(av_); |
| 1243 } |
| 1244 av_ = result; |
| 1245 } |
| 1246 |
| 1247 |
| 1248 void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) { |
| 1249 ASSERT(av_.IsEmpty()); |
| 1250 Visit(expr->expression()); |
| 1251 } |
| 1252 |
| 1253 |
| 1254 void AssignedVariablesAnalyzer::VisitCountOperation(CountOperation* expr) { |
| 1255 ASSERT(av_.IsEmpty()); |
| 1256 |
| 1257 Visit(expr->expression()); |
| 1258 |
| 1259 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| 1260 if (var != NULL) RecordAssignedVar(var); |
| 1261 } |
| 1262 |
| 1263 |
| 1264 void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) { |
| 1265 ASSERT(av_.IsEmpty()); |
| 1266 Visit(expr->left()); |
| 1267 |
| 1268 ProcessExpression(expr->right()); |
| 1269 |
| 1270 // In case we have a variable on the left side, check if we can mark |
| 1271 // it as trivial. |
| 1272 MarkIfTrivial(expr->left()); |
| 1273 } |
| 1274 |
| 1275 |
| 1276 void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) { |
| 1277 ASSERT(av_.IsEmpty()); |
| 1278 Visit(expr->left()); |
| 1279 |
| 1280 ProcessExpression(expr->right()); |
| 1281 |
| 1282 // In case we have a variable on the left side, check if we can mark |
| 1283 // it as trivial. |
| 1284 MarkIfTrivial(expr->left()); |
| 1285 } |
| 1286 |
| 1287 |
| 1288 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) { |
| 1289 // Nothing to do. |
| 1290 ASSERT(av_.IsEmpty()); |
| 1291 } |
| 1292 |
| 1293 |
| 1294 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) { |
| 903 UNREACHABLE(); | 1295 UNREACHABLE(); |
| 904 } | 1296 } |
| 905 | 1297 |
| 906 | |
| 907 void LivenessAnalyzer::VisitContinueStatement(ContinueStatement* stmt) { | |
| 908 UNREACHABLE(); | |
| 909 } | |
| 910 | |
| 911 | |
| 912 void LivenessAnalyzer::VisitBreakStatement(BreakStatement* stmt) { | |
| 913 UNREACHABLE(); | |
| 914 } | |
| 915 | |
| 916 | |
| 917 void LivenessAnalyzer::VisitReturnStatement(ReturnStatement* stmt) { | |
| 918 UNREACHABLE(); | |
| 919 } | |
| 920 | |
| 921 | |
| 922 void LivenessAnalyzer::VisitWithEnterStatement( | |
| 923 WithEnterStatement* stmt) { | |
| 924 UNREACHABLE(); | |
| 925 } | |
| 926 | |
| 927 | |
| 928 void LivenessAnalyzer::VisitWithExitStatement(WithExitStatement* stmt) { | |
| 929 UNREACHABLE(); | |
| 930 } | |
| 931 | |
| 932 | |
| 933 void LivenessAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) { | |
| 934 UNREACHABLE(); | |
| 935 } | |
| 936 | |
| 937 | |
| 938 void LivenessAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) { | |
| 939 UNREACHABLE(); | |
| 940 } | |
| 941 | |
| 942 | |
| 943 void LivenessAnalyzer::VisitWhileStatement(WhileStatement* stmt) { | |
| 944 UNREACHABLE(); | |
| 945 } | |
| 946 | |
| 947 | |
| 948 void LivenessAnalyzer::VisitForStatement(ForStatement* stmt) { | |
| 949 UNREACHABLE(); | |
| 950 } | |
| 951 | |
| 952 | |
| 953 void LivenessAnalyzer::VisitForInStatement(ForInStatement* stmt) { | |
| 954 UNREACHABLE(); | |
| 955 } | |
| 956 | |
| 957 | |
| 958 void LivenessAnalyzer::VisitTryCatchStatement(TryCatchStatement* stmt) { | |
| 959 UNREACHABLE(); | |
| 960 } | |
| 961 | |
| 962 | |
| 963 void LivenessAnalyzer::VisitTryFinallyStatement( | |
| 964 TryFinallyStatement* stmt) { | |
| 965 UNREACHABLE(); | |
| 966 } | |
| 967 | |
| 968 | |
| 969 void LivenessAnalyzer::VisitDebuggerStatement( | |
| 970 DebuggerStatement* stmt) { | |
| 971 UNREACHABLE(); | |
| 972 } | |
| 973 | |
| 974 | |
| 975 void LivenessAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) { | |
| 976 UNREACHABLE(); | |
| 977 } | |
| 978 | |
| 979 | |
| 980 void LivenessAnalyzer::VisitFunctionBoilerplateLiteral( | |
| 981 FunctionBoilerplateLiteral* expr) { | |
| 982 UNREACHABLE(); | |
| 983 } | |
| 984 | |
| 985 | |
| 986 void LivenessAnalyzer::VisitConditional(Conditional* expr) { | |
| 987 UNREACHABLE(); | |
| 988 } | |
| 989 | |
| 990 | |
| 991 void LivenessAnalyzer::VisitSlot(Slot* expr) { | |
| 992 UNREACHABLE(); | |
| 993 } | |
| 994 | |
| 995 | |
| 996 void LivenessAnalyzer::VisitVariableProxy(VariableProxy* expr) { | |
| 997 Variable* var = expr->var(); | |
| 998 ASSERT(var->is_global()); | |
| 999 ASSERT(!var->is_this()); | |
| 1000 RecordUse(var, expr); | |
| 1001 } | |
| 1002 | |
| 1003 | |
| 1004 void LivenessAnalyzer::VisitLiteral(Literal* expr) { | |
| 1005 UNREACHABLE(); | |
| 1006 } | |
| 1007 | |
| 1008 | |
| 1009 void LivenessAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) { | |
| 1010 UNREACHABLE(); | |
| 1011 } | |
| 1012 | |
| 1013 | |
| 1014 void LivenessAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) { | |
| 1015 UNREACHABLE(); | |
| 1016 } | |
| 1017 | |
| 1018 | |
| 1019 void LivenessAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) { | |
| 1020 UNREACHABLE(); | |
| 1021 } | |
| 1022 | |
| 1023 | |
| 1024 void LivenessAnalyzer::VisitCatchExtensionObject( | |
| 1025 CatchExtensionObject* expr) { | |
| 1026 UNREACHABLE(); | |
| 1027 } | |
| 1028 | |
| 1029 | |
| 1030 void LivenessAnalyzer::VisitAssignment(Assignment* expr) { | |
| 1031 Property* prop = expr->target()->AsProperty(); | |
| 1032 ASSERT(prop != NULL); | |
| 1033 ASSERT(prop->key()->IsPropertyName()); | |
| 1034 VariableProxy* proxy = prop->obj()->AsVariableProxy(); | |
| 1035 ASSERT(proxy != NULL && proxy->var()->is_this()); | |
| 1036 | |
| 1037 // Record use of this at the assignment node. Assignments to | |
| 1038 // this-properties are treated like unary operations. | |
| 1039 RecordUse(proxy->var(), expr); | |
| 1040 | |
| 1041 // Visit right-hand side. | |
| 1042 Visit(expr->value()); | |
| 1043 } | |
| 1044 | |
| 1045 | |
| 1046 void LivenessAnalyzer::VisitThrow(Throw* expr) { | |
| 1047 UNREACHABLE(); | |
| 1048 } | |
| 1049 | |
| 1050 | |
| 1051 void LivenessAnalyzer::VisitProperty(Property* expr) { | |
| 1052 ASSERT(expr->key()->IsPropertyName()); | |
| 1053 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | |
| 1054 ASSERT(proxy != NULL && proxy->var()->is_this()); | |
| 1055 RecordUse(proxy->var(), expr); | |
| 1056 } | |
| 1057 | |
| 1058 | |
| 1059 void LivenessAnalyzer::VisitCall(Call* expr) { | |
| 1060 UNREACHABLE(); | |
| 1061 } | |
| 1062 | |
| 1063 | |
| 1064 void LivenessAnalyzer::VisitCallNew(CallNew* expr) { | |
| 1065 UNREACHABLE(); | |
| 1066 } | |
| 1067 | |
| 1068 | |
| 1069 void LivenessAnalyzer::VisitCallRuntime(CallRuntime* expr) { | |
| 1070 UNREACHABLE(); | |
| 1071 } | |
| 1072 | |
| 1073 | |
| 1074 void LivenessAnalyzer::VisitUnaryOperation(UnaryOperation* expr) { | |
| 1075 UNREACHABLE(); | |
| 1076 } | |
| 1077 | |
| 1078 | |
| 1079 void LivenessAnalyzer::VisitCountOperation(CountOperation* expr) { | |
| 1080 UNREACHABLE(); | |
| 1081 } | |
| 1082 | |
| 1083 | |
| 1084 void LivenessAnalyzer::VisitBinaryOperation(BinaryOperation* expr) { | |
| 1085 // Visit child nodes in reverse evaluation order. | |
| 1086 Visit(expr->right()); | |
| 1087 Visit(expr->left()); | |
| 1088 } | |
| 1089 | |
| 1090 | |
| 1091 void LivenessAnalyzer::VisitCompareOperation(CompareOperation* expr) { | |
| 1092 UNREACHABLE(); | |
| 1093 } | |
| 1094 | |
| 1095 | |
| 1096 void LivenessAnalyzer::VisitThisFunction(ThisFunction* expr) { | |
| 1097 UNREACHABLE(); | |
| 1098 } | |
| 1099 | |
| 1100 | 1298 |
| 1101 #ifdef DEBUG | 1299 #ifdef DEBUG |
| 1102 | 1300 |
| 1103 // Print a textual representation of an instruction in a flow graph. Using | 1301 // Print a textual representation of an instruction in a flow graph. Using |
| 1104 // the AstVisitor is overkill because there is no recursion here. It is | 1302 // the AstVisitor is overkill because there is no recursion here. It is |
| 1105 // only used for printing in debug mode. | 1303 // only used for printing in debug mode. |
| 1106 class TextInstructionPrinter: public AstVisitor { | 1304 class TextInstructionPrinter: public AstVisitor { |
| 1107 public: | 1305 public: |
| 1108 TextInstructionPrinter() {} | 1306 TextInstructionPrinter() : number_(0) {} |
| 1307 |
| 1308 int NextNumber() { return number_; } |
| 1309 void AssignNumber(AstNode* node) { node->set_num(number_++); } |
| 1109 | 1310 |
| 1110 private: | 1311 private: |
| 1111 // AST node visit functions. | 1312 // AST node visit functions. |
| 1112 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); | 1313 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); |
| 1113 AST_NODE_LIST(DECLARE_VISIT) | 1314 AST_NODE_LIST(DECLARE_VISIT) |
| 1114 #undef DECLARE_VISIT | 1315 #undef DECLARE_VISIT |
| 1115 | 1316 |
| 1317 int number_; |
| 1318 |
| 1116 DISALLOW_COPY_AND_ASSIGN(TextInstructionPrinter); | 1319 DISALLOW_COPY_AND_ASSIGN(TextInstructionPrinter); |
| 1117 }; | 1320 }; |
| 1118 | 1321 |
| 1119 | 1322 |
| 1120 void TextInstructionPrinter::VisitDeclaration(Declaration* decl) { | 1323 void TextInstructionPrinter::VisitDeclaration(Declaration* decl) { |
| 1121 UNREACHABLE(); | 1324 UNREACHABLE(); |
| 1122 } | 1325 } |
| 1123 | 1326 |
| 1124 | 1327 |
| 1125 void TextInstructionPrinter::VisitBlock(Block* stmt) { | 1328 void TextInstructionPrinter::VisitBlock(Block* stmt) { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1226 | 1429 |
| 1227 | 1430 |
| 1228 void TextInstructionPrinter::VisitSlot(Slot* expr) { | 1431 void TextInstructionPrinter::VisitSlot(Slot* expr) { |
| 1229 UNREACHABLE(); | 1432 UNREACHABLE(); |
| 1230 } | 1433 } |
| 1231 | 1434 |
| 1232 | 1435 |
| 1233 void TextInstructionPrinter::VisitVariableProxy(VariableProxy* expr) { | 1436 void TextInstructionPrinter::VisitVariableProxy(VariableProxy* expr) { |
| 1234 Variable* var = expr->AsVariable(); | 1437 Variable* var = expr->AsVariable(); |
| 1235 if (var != NULL) { | 1438 if (var != NULL) { |
| 1236 SmartPointer<char> name = var->name()->ToCString(); | 1439 PrintF("%s", *var->name()->ToCString()); |
| 1237 PrintF("%s", *name); | 1440 if (var->IsStackAllocated() && expr->reaching_definitions() != NULL) { |
| 1441 expr->reaching_definitions()->Print(); |
| 1442 } |
| 1238 } else { | 1443 } else { |
| 1239 ASSERT(expr->AsProperty() != NULL); | 1444 ASSERT(expr->AsProperty() != NULL); |
| 1240 VisitProperty(expr->AsProperty()); | 1445 VisitProperty(expr->AsProperty()); |
| 1241 } | 1446 } |
| 1242 } | 1447 } |
| 1243 | 1448 |
| 1244 | 1449 |
| 1245 void TextInstructionPrinter::VisitLiteral(Literal* expr) { | 1450 void TextInstructionPrinter::VisitLiteral(Literal* expr) { |
| 1246 expr->handle()->ShortPrint(); | 1451 expr->handle()->ShortPrint(); |
| 1247 } | 1452 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1265 void TextInstructionPrinter::VisitCatchExtensionObject( | 1470 void TextInstructionPrinter::VisitCatchExtensionObject( |
| 1266 CatchExtensionObject* expr) { | 1471 CatchExtensionObject* expr) { |
| 1267 PrintF("CatchExtensionObject"); | 1472 PrintF("CatchExtensionObject"); |
| 1268 } | 1473 } |
| 1269 | 1474 |
| 1270 | 1475 |
| 1271 void TextInstructionPrinter::VisitAssignment(Assignment* expr) { | 1476 void TextInstructionPrinter::VisitAssignment(Assignment* expr) { |
| 1272 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 1477 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
| 1273 Property* prop = expr->target()->AsProperty(); | 1478 Property* prop = expr->target()->AsProperty(); |
| 1274 | 1479 |
| 1480 if (var == NULL && prop == NULL) { |
| 1481 // Throw reference error. |
| 1482 Visit(expr->target()); |
| 1483 return; |
| 1484 } |
| 1485 |
| 1486 // Print the left-hand side. |
| 1275 if (var != NULL) { | 1487 if (var != NULL) { |
| 1276 SmartPointer<char> name = var->name()->ToCString(); | 1488 PrintF("%s", *var->name()->ToCString()); |
| 1277 PrintF("%s %s @%d", | |
| 1278 *name, | |
| 1279 Token::String(expr->op()), | |
| 1280 expr->value()->num()); | |
| 1281 } else if (prop != NULL) { | 1489 } else if (prop != NULL) { |
| 1490 PrintF("@%d", prop->obj()->num()); |
| 1282 if (prop->key()->IsPropertyName()) { | 1491 if (prop->key()->IsPropertyName()) { |
| 1283 PrintF("@%d.", prop->obj()->num()); | 1492 PrintF("."); |
| 1284 ASSERT(prop->key()->AsLiteral() != NULL); | 1493 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1285 prop->key()->AsLiteral()->handle()->Print(); | 1494 prop->key()->AsLiteral()->handle()->Print(); |
| 1286 PrintF(" %s @%d", | |
| 1287 Token::String(expr->op()), | |
| 1288 expr->value()->num()); | |
| 1289 } else { | 1495 } else { |
| 1290 PrintF("@%d[@%d] %s @%d", | 1496 PrintF("[@%d]", prop->key()->num()); |
| 1291 prop->obj()->num(), | |
| 1292 prop->key()->num(), | |
| 1293 Token::String(expr->op()), | |
| 1294 expr->value()->num()); | |
| 1295 } | 1497 } |
| 1498 } |
| 1499 |
| 1500 // Print the operation. |
| 1501 if (expr->is_compound()) { |
| 1502 PrintF(" = "); |
| 1503 // Print the left-hand side again when compound. |
| 1504 if (var != NULL) { |
| 1505 PrintF("@%d", expr->target()->num()); |
| 1506 } else { |
| 1507 PrintF("@%d", prop->obj()->num()); |
| 1508 if (prop->key()->IsPropertyName()) { |
| 1509 PrintF("."); |
| 1510 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1511 prop->key()->AsLiteral()->handle()->Print(); |
| 1512 } else { |
| 1513 PrintF("[@%d]", prop->key()->num()); |
| 1514 } |
| 1515 } |
| 1516 // Print the corresponding binary operator. |
| 1517 PrintF(" %s ", Token::String(expr->binary_op())); |
| 1296 } else { | 1518 } else { |
| 1297 // Throw reference error. | 1519 PrintF(" %s ", Token::String(expr->op())); |
| 1298 Visit(expr->target()); | 1520 } |
| 1521 |
| 1522 // Print the right-hand side. |
| 1523 PrintF("@%d", expr->value()->num()); |
| 1524 |
| 1525 if (expr->num() != AstNode::kNoNumber) { |
| 1526 PrintF(" ;; D%d", expr->num()); |
| 1299 } | 1527 } |
| 1300 } | 1528 } |
| 1301 | 1529 |
| 1302 | 1530 |
| 1303 void TextInstructionPrinter::VisitThrow(Throw* expr) { | 1531 void TextInstructionPrinter::VisitThrow(Throw* expr) { |
| 1304 PrintF("throw @%d", expr->exception()->num()); | 1532 PrintF("throw @%d", expr->exception()->num()); |
| 1305 } | 1533 } |
| 1306 | 1534 |
| 1307 | 1535 |
| 1308 void TextInstructionPrinter::VisitProperty(Property* expr) { | 1536 void TextInstructionPrinter::VisitProperty(Property* expr) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1332 ZoneList<Expression*>* arguments = expr->arguments(); | 1560 ZoneList<Expression*>* arguments = expr->arguments(); |
| 1333 for (int i = 0, len = arguments->length(); i < len; i++) { | 1561 for (int i = 0, len = arguments->length(); i < len; i++) { |
| 1334 if (i != 0) PrintF(", "); | 1562 if (i != 0) PrintF(", "); |
| 1335 PrintF("@%d", arguments->at(i)->num()); | 1563 PrintF("@%d", arguments->at(i)->num()); |
| 1336 } | 1564 } |
| 1337 PrintF(")"); | 1565 PrintF(")"); |
| 1338 } | 1566 } |
| 1339 | 1567 |
| 1340 | 1568 |
| 1341 void TextInstructionPrinter::VisitCallRuntime(CallRuntime* expr) { | 1569 void TextInstructionPrinter::VisitCallRuntime(CallRuntime* expr) { |
| 1342 SmartPointer<char> name = expr->name()->ToCString(); | 1570 PrintF("%s(", *expr->name()->ToCString()); |
| 1343 PrintF("%s(", *name); | |
| 1344 ZoneList<Expression*>* arguments = expr->arguments(); | 1571 ZoneList<Expression*>* arguments = expr->arguments(); |
| 1345 for (int i = 0, len = arguments->length(); i < len; i++) { | 1572 for (int i = 0, len = arguments->length(); i < len; i++) { |
| 1346 if (i != 0) PrintF(", "); | 1573 if (i != 0) PrintF(", "); |
| 1347 PrintF("@%d", arguments->at(i)->num()); | 1574 PrintF("@%d", arguments->at(i)->num()); |
| 1348 } | 1575 } |
| 1349 PrintF(")"); | 1576 PrintF(")"); |
| 1350 } | 1577 } |
| 1351 | 1578 |
| 1352 | 1579 |
| 1353 void TextInstructionPrinter::VisitUnaryOperation(UnaryOperation* expr) { | 1580 void TextInstructionPrinter::VisitUnaryOperation(UnaryOperation* expr) { |
| 1354 PrintF("%s(@%d)", Token::String(expr->op()), expr->expression()->num()); | 1581 PrintF("%s(@%d)", Token::String(expr->op()), expr->expression()->num()); |
| 1355 } | 1582 } |
| 1356 | 1583 |
| 1357 | 1584 |
| 1358 void TextInstructionPrinter::VisitCountOperation(CountOperation* expr) { | 1585 void TextInstructionPrinter::VisitCountOperation(CountOperation* expr) { |
| 1359 if (expr->is_prefix()) { | 1586 if (expr->is_prefix()) { |
| 1360 PrintF("%s@%d", Token::String(expr->op()), expr->expression()->num()); | 1587 PrintF("%s@%d", Token::String(expr->op()), expr->expression()->num()); |
| 1361 } else { | 1588 } else { |
| 1362 PrintF("@%d%s", expr->expression()->num(), Token::String(expr->op())); | 1589 PrintF("@%d%s", expr->expression()->num(), Token::String(expr->op())); |
| 1363 } | 1590 } |
| 1591 |
| 1592 if (expr->num() != AstNode::kNoNumber) { |
| 1593 PrintF(" ;; D%d", expr->num()); |
| 1594 } |
| 1364 } | 1595 } |
| 1365 | 1596 |
| 1366 | 1597 |
| 1367 void TextInstructionPrinter::VisitBinaryOperation(BinaryOperation* expr) { | 1598 void TextInstructionPrinter::VisitBinaryOperation(BinaryOperation* expr) { |
| 1368 ASSERT(expr->op() != Token::COMMA); | 1599 ASSERT(expr->op() != Token::COMMA); |
| 1369 ASSERT(expr->op() != Token::OR); | 1600 ASSERT(expr->op() != Token::OR); |
| 1370 ASSERT(expr->op() != Token::AND); | 1601 ASSERT(expr->op() != Token::AND); |
| 1371 PrintF("@%d %s @%d", | 1602 PrintF("@%d %s @%d", |
| 1372 expr->left()->num(), | 1603 expr->left()->num(), |
| 1373 Token::String(expr->op()), | 1604 Token::String(expr->op()), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1385 | 1616 |
| 1386 void TextInstructionPrinter::VisitThisFunction(ThisFunction* expr) { | 1617 void TextInstructionPrinter::VisitThisFunction(ThisFunction* expr) { |
| 1387 PrintF("ThisFunction"); | 1618 PrintF("ThisFunction"); |
| 1388 } | 1619 } |
| 1389 | 1620 |
| 1390 | 1621 |
| 1391 static int node_count = 0; | 1622 static int node_count = 0; |
| 1392 static int instruction_count = 0; | 1623 static int instruction_count = 0; |
| 1393 | 1624 |
| 1394 | 1625 |
| 1395 void Node::AssignNumbers() { | 1626 void Node::AssignNodeNumber() { |
| 1396 set_number(node_count++); | 1627 set_number(node_count++); |
| 1397 } | 1628 } |
| 1398 | 1629 |
| 1399 | 1630 |
| 1400 void BlockNode::AssignNumbers() { | 1631 void Node::PrintReachingDefinitions() { |
| 1401 set_number(node_count++); | 1632 if (rd_.rd_in() != NULL) { |
| 1402 for (int i = 0, len = instructions_.length(); i < len; i++) { | 1633 ASSERT(rd_.kill() != NULL && rd_.gen() != NULL); |
| 1403 instructions_[i]->set_num(instruction_count++); | 1634 |
| 1635 PrintF("RD_in = "); |
| 1636 rd_.rd_in()->Print(); |
| 1637 PrintF("\n"); |
| 1638 |
| 1639 PrintF("RD_kill = "); |
| 1640 rd_.kill()->Print(); |
| 1641 PrintF("\n"); |
| 1642 |
| 1643 PrintF("RD_gen = "); |
| 1644 rd_.gen()->Print(); |
| 1645 PrintF("\n"); |
| 1404 } | 1646 } |
| 1405 } | 1647 } |
| 1406 | 1648 |
| 1407 | 1649 |
| 1408 void EntryNode::PrintText() { | |
| 1409 PrintF("L%d: Entry\n", number()); | |
| 1410 PrintF("goto L%d\n\n", successor_->number()); | |
| 1411 } | |
| 1412 | |
| 1413 void ExitNode::PrintText() { | 1650 void ExitNode::PrintText() { |
| 1651 PrintReachingDefinitions(); |
| 1414 PrintF("L%d: Exit\n\n", number()); | 1652 PrintF("L%d: Exit\n\n", number()); |
| 1415 } | 1653 } |
| 1416 | 1654 |
| 1417 | 1655 |
| 1418 void BlockNode::PrintText() { | 1656 void BlockNode::PrintText() { |
| 1657 PrintReachingDefinitions(); |
| 1419 // Print the instructions in the block. | 1658 // Print the instructions in the block. |
| 1420 PrintF("L%d: Block\n", number()); | 1659 PrintF("L%d: Block\n", number()); |
| 1421 TextInstructionPrinter printer; | 1660 TextInstructionPrinter printer; |
| 1422 for (int i = 0, len = instructions_.length(); i < len; i++) { | 1661 for (int i = 0, len = instructions_.length(); i < len; i++) { |
| 1423 PrintF("%d ", instructions_[i]->num()); | 1662 PrintF("%d ", printer.NextNumber()); |
| 1424 printer.Visit(instructions_[i]); | 1663 printer.Visit(instructions_[i]); |
| 1664 printer.AssignNumber(instructions_[i]); |
| 1425 PrintF("\n"); | 1665 PrintF("\n"); |
| 1426 } | 1666 } |
| 1427 PrintF("goto L%d\n\n", successor_->number()); | 1667 PrintF("goto L%d\n\n", successor_->number()); |
| 1428 } | 1668 } |
| 1429 | 1669 |
| 1430 | 1670 |
| 1431 void BranchNode::PrintText() { | 1671 void BranchNode::PrintText() { |
| 1672 PrintReachingDefinitions(); |
| 1432 PrintF("L%d: Branch\n", number()); | 1673 PrintF("L%d: Branch\n", number()); |
| 1433 PrintF("goto (L%d, L%d)\n\n", successor0_->number(), successor1_->number()); | 1674 PrintF("goto (L%d, L%d)\n\n", successor0_->number(), successor1_->number()); |
| 1434 } | 1675 } |
| 1435 | 1676 |
| 1436 | 1677 |
| 1437 void JoinNode::PrintText() { | 1678 void JoinNode::PrintText() { |
| 1679 PrintReachingDefinitions(); |
| 1438 PrintF("L%d: Join(", number()); | 1680 PrintF("L%d: Join(", number()); |
| 1439 for (int i = 0, len = predecessors_.length(); i < len; i++) { | 1681 for (int i = 0, len = predecessors_.length(); i < len; i++) { |
| 1440 if (i != 0) PrintF(", "); | 1682 if (i != 0) PrintF(", "); |
| 1441 PrintF("L%d", predecessors_[i]->number()); | 1683 PrintF("L%d", predecessors_[i]->number()); |
| 1442 } | 1684 } |
| 1443 PrintF(")\ngoto L%d\n\n", successor_->number()); | 1685 PrintF(")\ngoto L%d\n\n", successor_->number()); |
| 1444 } | 1686 } |
| 1445 | 1687 |
| 1446 | 1688 |
| 1447 void FlowGraph::PrintText(ZoneList<Node*>* postorder) { | 1689 void FlowGraph::PrintText(FunctionLiteral* fun, ZoneList<Node*>* postorder) { |
| 1448 PrintF("\n========\n"); | 1690 PrintF("\n========\n"); |
| 1691 PrintF("name = %s\n", *fun->name()->ToCString()); |
| 1449 | 1692 |
| 1450 // Number nodes and instructions in reverse postorder. | 1693 // Number nodes and instructions in reverse postorder. |
| 1451 node_count = 0; | 1694 node_count = 0; |
| 1452 instruction_count = 0; | 1695 instruction_count = 0; |
| 1453 for (int i = postorder->length() - 1; i >= 0; i--) { | 1696 for (int i = postorder->length() - 1; i >= 0; i--) { |
| 1454 postorder->at(i)->AssignNumbers(); | 1697 postorder->at(i)->AssignNodeNumber(); |
| 1455 } | 1698 } |
| 1456 | 1699 |
| 1457 // Print basic blocks in reverse postorder. | 1700 // Print basic blocks in reverse postorder. |
| 1458 for (int i = postorder->length() - 1; i >= 0; i--) { | 1701 for (int i = postorder->length() - 1; i >= 0; i--) { |
| 1459 postorder->at(i)->PrintText(); | 1702 postorder->at(i)->PrintText(); |
| 1460 } | 1703 } |
| 1461 } | 1704 } |
| 1462 | 1705 |
| 1463 | 1706 |
| 1464 #endif // defined(DEBUG) | 1707 #endif // defined(DEBUG) |
| 1465 | 1708 |
| 1466 | 1709 |
| 1710 int ReachingDefinitions::IndexFor(Variable* var, int variable_count) { |
| 1711 // Parameters are numbered left-to-right from the beginning of the bit |
| 1712 // set. Stack-allocated locals are allocated right-to-left from the end. |
| 1713 ASSERT(var != NULL && var->IsStackAllocated()); |
| 1714 Slot* slot = var->slot(); |
| 1715 if (slot->type() == Slot::PARAMETER) { |
| 1716 return slot->index(); |
| 1717 } else { |
| 1718 return (variable_count - 1) - slot->index(); |
| 1719 } |
| 1720 } |
| 1721 |
| 1722 |
| 1723 void Node::InitializeReachingDefinitions(int definition_count, |
| 1724 List<BitVector*>* variables, |
| 1725 WorkList<Node>* worklist, |
| 1726 bool mark) { |
| 1727 ASSERT(!IsMarkedWith(mark)); |
| 1728 rd_.Initialize(definition_count); |
| 1729 MarkWith(mark); |
| 1730 worklist->Insert(this); |
| 1731 } |
| 1732 |
| 1733 |
| 1734 void BlockNode::InitializeReachingDefinitions(int definition_count, |
| 1735 List<BitVector*>* variables, |
| 1736 WorkList<Node>* worklist, |
| 1737 bool mark) { |
| 1738 ASSERT(!IsMarkedWith(mark)); |
| 1739 int instruction_count = instructions_.length(); |
| 1740 int variable_count = variables->length(); |
| 1741 |
| 1742 rd_.Initialize(definition_count); |
| 1743 |
| 1744 for (int i = 0; i < instruction_count; i++) { |
| 1745 Expression* expr = instructions_[i]->AsExpression(); |
| 1746 if (expr == NULL) continue; |
| 1747 Variable* var = expr->AssignedVar(); |
| 1748 if (var == NULL || !var->IsStackAllocated()) continue; |
| 1749 |
| 1750 // All definitions of this variable are killed. |
| 1751 BitVector* def_set = |
| 1752 variables->at(ReachingDefinitions::IndexFor(var, variable_count)); |
| 1753 rd_.kill()->Union(*def_set); |
| 1754 |
| 1755 // All previously generated definitions are not generated. |
| 1756 rd_.gen()->Subtract(*def_set); |
| 1757 |
| 1758 // This one is generated. |
| 1759 rd_.gen()->Add(expr->num()); |
| 1760 } |
| 1761 |
| 1762 // Add all blocks except the entry node to the worklist. |
| 1763 if (predecessor_ != NULL) { |
| 1764 MarkWith(mark); |
| 1765 worklist->Insert(this); |
| 1766 } |
| 1767 } |
| 1768 |
| 1769 |
| 1770 void ExitNode::ComputeRDOut(BitVector* result) { |
| 1771 // Should not be the predecessor of any node. |
| 1772 UNREACHABLE(); |
| 1773 } |
| 1774 |
| 1775 |
| 1776 void BlockNode::ComputeRDOut(BitVector* result) { |
| 1777 // All definitions reaching this block ... |
| 1778 *result = *rd_.rd_in(); |
| 1779 // ... except those killed by the block ... |
| 1780 result->Subtract(*rd_.kill()); |
| 1781 // ... but including those generated by the block. |
| 1782 result->Union(*rd_.gen()); |
| 1783 } |
| 1784 |
| 1785 |
| 1786 void BranchNode::ComputeRDOut(BitVector* result) { |
| 1787 // Branch nodes don't kill or generate definitions. |
| 1788 *result = *rd_.rd_in(); |
| 1789 } |
| 1790 |
| 1791 |
| 1792 void JoinNode::ComputeRDOut(BitVector* result) { |
| 1793 // Join nodes don't kill or generate definitions. |
| 1794 *result = *rd_.rd_in(); |
| 1795 } |
| 1796 |
| 1797 |
| 1798 void ExitNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) { |
| 1799 // The exit node has no successors so we can just update in place. New |
| 1800 // RD_in is the union over all predecessors. |
| 1801 int definition_count = rd_.rd_in()->length(); |
| 1802 rd_.rd_in()->Clear(); |
| 1803 |
| 1804 BitVector temp(definition_count); |
| 1805 for (int i = 0, len = predecessors_.length(); i < len; i++) { |
| 1806 // Because ComputeRDOut always overwrites temp and its value is |
| 1807 // always read out before calling ComputeRDOut again, we do not |
| 1808 // have to clear it on each iteration of the loop. |
| 1809 predecessors_[i]->ComputeRDOut(&temp); |
| 1810 rd_.rd_in()->Union(temp); |
| 1811 } |
| 1812 } |
| 1813 |
| 1814 |
| 1815 void BlockNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) { |
| 1816 // The entry block has no predecessor. Its RD_in does not change. |
| 1817 if (predecessor_ == NULL) return; |
| 1818 |
| 1819 BitVector new_rd_in(rd_.rd_in()->length()); |
| 1820 predecessor_->ComputeRDOut(&new_rd_in); |
| 1821 |
| 1822 if (rd_.rd_in()->Equals(new_rd_in)) return; |
| 1823 |
| 1824 // Update RD_in. |
| 1825 *rd_.rd_in() = new_rd_in; |
| 1826 // Add the successor to the worklist if not already present. |
| 1827 if (!successor_->IsMarkedWith(mark)) { |
| 1828 successor_->MarkWith(mark); |
| 1829 worklist->Insert(successor_); |
| 1830 } |
| 1831 } |
| 1832 |
| 1833 |
| 1834 void BranchNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) { |
| 1835 BitVector new_rd_in(rd_.rd_in()->length()); |
| 1836 predecessor_->ComputeRDOut(&new_rd_in); |
| 1837 |
| 1838 if (rd_.rd_in()->Equals(new_rd_in)) return; |
| 1839 |
| 1840 // Update RD_in. |
| 1841 *rd_.rd_in() = new_rd_in; |
| 1842 // Add the successors to the worklist if not already present. |
| 1843 if (!successor0_->IsMarkedWith(mark)) { |
| 1844 successor0_->MarkWith(mark); |
| 1845 worklist->Insert(successor0_); |
| 1846 } |
| 1847 if (!successor1_->IsMarkedWith(mark)) { |
| 1848 successor1_->MarkWith(mark); |
| 1849 worklist->Insert(successor1_); |
| 1850 } |
| 1851 } |
| 1852 |
| 1853 |
| 1854 void JoinNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) { |
| 1855 int definition_count = rd_.rd_in()->length(); |
| 1856 BitVector new_rd_in(definition_count); |
| 1857 |
| 1858 // New RD_in is the union over all predecessors. |
| 1859 BitVector temp(definition_count); |
| 1860 for (int i = 0, len = predecessors_.length(); i < len; i++) { |
| 1861 predecessors_[i]->ComputeRDOut(&temp); |
| 1862 new_rd_in.Union(temp); |
| 1863 } |
| 1864 |
| 1865 if (rd_.rd_in()->Equals(new_rd_in)) return; |
| 1866 |
| 1867 // Update RD_in. |
| 1868 *rd_.rd_in() = new_rd_in; |
| 1869 // Add the successor to the worklist if not already present. |
| 1870 if (!successor_->IsMarkedWith(mark)) { |
| 1871 successor_->MarkWith(mark); |
| 1872 worklist->Insert(successor_); |
| 1873 } |
| 1874 } |
| 1875 |
| 1876 |
| 1877 void Node::PropagateReachingDefinitions(List<BitVector*>* variables) { |
| 1878 // Nothing to do. |
| 1879 } |
| 1880 |
| 1881 |
| 1882 void BlockNode::PropagateReachingDefinitions(List<BitVector*>* variables) { |
| 1883 // Propagate RD_in from the start of the block to all the variable |
| 1884 // references. |
| 1885 int variable_count = variables->length(); |
| 1886 BitVector rd = *rd_.rd_in(); |
| 1887 for (int i = 0, len = instructions_.length(); i < len; i++) { |
| 1888 Expression* expr = instructions_[i]->AsExpression(); |
| 1889 if (expr == NULL) continue; |
| 1890 |
| 1891 // Look for a variable reference to record its reaching definitions. |
| 1892 VariableProxy* proxy = expr->AsVariableProxy(); |
| 1893 if (proxy == NULL) { |
| 1894 // Not a VariableProxy? Maybe it's a count operation. |
| 1895 CountOperation* count_operation = expr->AsCountOperation(); |
| 1896 if (count_operation != NULL) { |
| 1897 proxy = count_operation->expression()->AsVariableProxy(); |
| 1898 } |
| 1899 } |
| 1900 if (proxy == NULL) { |
| 1901 // OK, Maybe it's a compound assignment. |
| 1902 Assignment* assignment = expr->AsAssignment(); |
| 1903 if (assignment != NULL && assignment->is_compound()) { |
| 1904 proxy = assignment->target()->AsVariableProxy(); |
| 1905 } |
| 1906 } |
| 1907 |
| 1908 if (proxy != NULL && |
| 1909 proxy->var()->IsStackAllocated() && |
| 1910 !proxy->var()->is_this()) { |
| 1911 // All definitions for this variable. |
| 1912 BitVector* definitions = |
| 1913 variables->at(ReachingDefinitions::IndexFor(proxy->var(), |
| 1914 variable_count)); |
| 1915 BitVector* reaching_definitions = new BitVector(*definitions); |
| 1916 // Intersected with all definitions (of any variable) reaching this |
| 1917 // instruction. |
| 1918 reaching_definitions->Intersect(rd); |
| 1919 proxy->set_reaching_definitions(reaching_definitions); |
| 1920 } |
| 1921 |
| 1922 // It may instead (or also) be a definition. If so update the running |
| 1923 // value of reaching definitions for the block. |
| 1924 Variable* var = expr->AssignedVar(); |
| 1925 if (var == NULL || !var->IsStackAllocated()) continue; |
| 1926 |
| 1927 // All definitions of this variable are killed. |
| 1928 BitVector* def_set = |
| 1929 variables->at(ReachingDefinitions::IndexFor(var, variable_count)); |
| 1930 rd.Subtract(*def_set); |
| 1931 // This definition is generated. |
| 1932 rd.Add(expr->num()); |
| 1933 } |
| 1934 } |
| 1935 |
| 1936 |
| 1937 void ReachingDefinitions::Compute() { |
| 1938 ASSERT(!definitions_->is_empty()); |
| 1939 |
| 1940 int variable_count = variables_.length(); |
| 1941 int definition_count = definitions_->length(); |
| 1942 int node_count = postorder_->length(); |
| 1943 |
| 1944 // Step 1: For each variable, identify the set of all its definitions in |
| 1945 // the body. |
| 1946 for (int i = 0; i < definition_count; i++) { |
| 1947 Variable* var = definitions_->at(i)->AssignedVar(); |
| 1948 variables_[IndexFor(var, variable_count)]->Add(i); |
| 1949 } |
| 1950 |
| 1951 if (FLAG_print_graph_text) { |
| 1952 for (int i = 0; i < variable_count; i++) { |
| 1953 BitVector* def_set = variables_[i]; |
| 1954 if (!def_set->IsEmpty()) { |
| 1955 // At least one definition. |
| 1956 bool first = true; |
| 1957 for (int j = 0; j < definition_count; j++) { |
| 1958 if (def_set->Contains(j)) { |
| 1959 if (first) { |
| 1960 Variable* var = definitions_->at(j)->AssignedVar(); |
| 1961 ASSERT(var != NULL); |
| 1962 PrintF("Def[%s] = {%d", *var->name()->ToCString(), j); |
| 1963 first = false; |
| 1964 } else { |
| 1965 PrintF(",%d", j); |
| 1966 } |
| 1967 } |
| 1968 } |
| 1969 PrintF("}\n"); |
| 1970 } |
| 1971 } |
| 1972 } |
| 1973 |
| 1974 // Step 2: Compute KILL and GEN for each block node, initialize RD_in for |
| 1975 // all nodes, and mark and add all nodes to the worklist in reverse |
| 1976 // postorder. All nodes should currently have the same mark. |
| 1977 bool mark = postorder_->at(0)->IsMarkedWith(false); // Negation of current. |
| 1978 WorkList<Node> worklist(node_count); |
| 1979 for (int i = node_count - 1; i >= 0; i--) { |
| 1980 postorder_->at(i)->InitializeReachingDefinitions(definition_count, |
| 1981 &variables_, |
| 1982 &worklist, |
| 1983 mark); |
| 1984 } |
| 1985 |
| 1986 // Step 3: Until the worklist is empty, remove an item compute and update |
| 1987 // its rd_in based on its predecessor's rd_out. If rd_in has changed, add |
| 1988 // all necessary successors to the worklist. |
| 1989 while (!worklist.is_empty()) { |
| 1990 Node* node = worklist.Remove(); |
| 1991 node->MarkWith(!mark); |
| 1992 node->UpdateRDIn(&worklist, mark); |
| 1993 } |
| 1994 |
| 1995 // Step 4: Based on RD_in for block nodes, propagate reaching definitions |
| 1996 // to all variable uses in the block. |
| 1997 for (int i = 0; i < node_count; i++) { |
| 1998 postorder_->at(i)->PropagateReachingDefinitions(&variables_); |
| 1999 } |
| 2000 } |
| 2001 |
| 2002 |
| 1467 } } // namespace v8::internal | 2003 } } // namespace v8::internal |
| OLD | NEW |