OLD | NEW |
(Empty) | |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are |
| 4 // met: |
| 5 // |
| 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. |
| 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 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. |
| 27 |
| 28 #include "flow-graph.h" |
| 29 |
| 30 namespace v8 { |
| 31 namespace internal { |
| 32 |
| 33 void FlowGraph::AppendInstruction(AstNode* instruction) { |
| 34 // Add a (non-null) AstNode to the end of the graph fragment. |
| 35 ASSERT(instruction != NULL); |
| 36 if (exit()->IsExitNode()) return; |
| 37 if (!exit()->IsBlockNode()) AppendNode(new BlockNode()); |
| 38 BlockNode::cast(exit())->AddInstruction(instruction); |
| 39 } |
| 40 |
| 41 |
| 42 void FlowGraph::AppendNode(Node* node) { |
| 43 // Add a node to the end of the graph. An empty block is added to |
| 44 // maintain edge-split form (that no join nodes or exit nodes as |
| 45 // successors to branch nodes). |
| 46 ASSERT(node != NULL); |
| 47 if (exit()->IsExitNode()) return; |
| 48 if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) { |
| 49 AppendNode(new BlockNode()); |
| 50 } |
| 51 exit()->AddSuccessor(node); |
| 52 node->AddPredecessor(exit()); |
| 53 exit_ = node; |
| 54 } |
| 55 |
| 56 |
| 57 void FlowGraph::AppendGraph(FlowGraph* graph) { |
| 58 // Add a flow graph fragment to the end of this one. An empty block is |
| 59 // added to maintain edge-split form (that no join nodes or exit nodes as |
| 60 // successors to branch nodes). |
| 61 ASSERT(graph != NULL); |
| 62 if (exit()->IsExitNode()) return; |
| 63 Node* node = graph->entry(); |
| 64 if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) { |
| 65 AppendNode(new BlockNode()); |
| 66 } |
| 67 exit()->AddSuccessor(node); |
| 68 node->AddPredecessor(exit()); |
| 69 exit_ = graph->exit(); |
| 70 } |
| 71 |
| 72 |
| 73 void FlowGraph::Split(BranchNode* branch, |
| 74 FlowGraph* left, |
| 75 FlowGraph* right, |
| 76 JoinNode* join) { |
| 77 // Add the branch node, left flowgraph, join node. |
| 78 AppendNode(branch); |
| 79 AppendGraph(left); |
| 80 AppendNode(join); |
| 81 |
| 82 // Splice in the right flowgraph. |
| 83 right->AppendNode(join); |
| 84 branch->AddSuccessor(right->entry()); |
| 85 right->entry()->AddPredecessor(branch); |
| 86 } |
| 87 |
| 88 |
| 89 void FlowGraph::Loop(JoinNode* join, |
| 90 FlowGraph* condition, |
| 91 BranchNode* branch, |
| 92 FlowGraph* body) { |
| 93 // Add the join, condition and branch. Add join's predecessors in |
| 94 // left-to-right order. |
| 95 AppendNode(join); |
| 96 body->AppendNode(join); |
| 97 AppendGraph(condition); |
| 98 AppendNode(branch); |
| 99 |
| 100 // Splice in the body flowgraph. |
| 101 branch->AddSuccessor(body->entry()); |
| 102 body->entry()->AddPredecessor(branch); |
| 103 } |
| 104 |
| 105 |
| 106 void ExitNode::Traverse(bool mark, |
| 107 ZoneList<Node*>* preorder, |
| 108 ZoneList<Node*>* postorder) { |
| 109 preorder->Add(this); |
| 110 postorder->Add(this); |
| 111 } |
| 112 |
| 113 |
| 114 void BlockNode::Traverse(bool mark, |
| 115 ZoneList<Node*>* preorder, |
| 116 ZoneList<Node*>* postorder) { |
| 117 ASSERT(successor_ != NULL); |
| 118 preorder->Add(this); |
| 119 if (!successor_->IsMarkedWith(mark)) { |
| 120 successor_->MarkWith(mark); |
| 121 successor_->Traverse(mark, preorder, postorder); |
| 122 } |
| 123 postorder->Add(this); |
| 124 } |
| 125 |
| 126 |
| 127 void BranchNode::Traverse(bool mark, |
| 128 ZoneList<Node*>* preorder, |
| 129 ZoneList<Node*>* postorder) { |
| 130 ASSERT(successor0_ != NULL && successor1_ != NULL); |
| 131 preorder->Add(this); |
| 132 if (!successor1_->IsMarkedWith(mark)) { |
| 133 successor1_->MarkWith(mark); |
| 134 successor1_->Traverse(mark, preorder, postorder); |
| 135 } |
| 136 if (!successor0_->IsMarkedWith(mark)) { |
| 137 successor0_->MarkWith(mark); |
| 138 successor0_->Traverse(mark, preorder, postorder); |
| 139 } |
| 140 postorder->Add(this); |
| 141 } |
| 142 |
| 143 |
| 144 void JoinNode::Traverse(bool mark, |
| 145 ZoneList<Node*>* preorder, |
| 146 ZoneList<Node*>* postorder) { |
| 147 ASSERT(successor_ != NULL); |
| 148 preorder->Add(this); |
| 149 if (!successor_->IsMarkedWith(mark)) { |
| 150 successor_->MarkWith(mark); |
| 151 successor_->Traverse(mark, preorder, postorder); |
| 152 } |
| 153 postorder->Add(this); |
| 154 } |
| 155 |
| 156 |
| 157 void FlowGraphBuilder::Build(FunctionLiteral* lit) { |
| 158 global_exit_ = new ExitNode(); |
| 159 VisitStatements(lit->body()); |
| 160 |
| 161 if (HasStackOverflow()) return; |
| 162 |
| 163 // The graph can end with a branch node (if the function ended with a |
| 164 // loop). Maintain edge-split form (no join nodes or exit nodes as |
| 165 // successors to branch nodes). |
| 166 if (graph_.exit()->IsBranchNode()) graph_.AppendNode(new BlockNode()); |
| 167 graph_.AppendNode(global_exit_); |
| 168 |
| 169 // Build preorder and postorder traversal orders. All the nodes in |
| 170 // the graph have the same mark flag. For the traversal, use that |
| 171 // flag's negation. Traversal will flip all the flags. |
| 172 bool mark = graph_.entry()->IsMarkedWith(false); |
| 173 graph_.entry()->MarkWith(mark); |
| 174 graph_.entry()->Traverse(mark, &preorder_, &postorder_); |
| 175 } |
| 176 |
| 177 |
| 178 // This function peels off one iteration of a for-loop. The return value |
| 179 // is either a block statement containing the peeled loop or NULL in case |
| 180 // there is a stack overflow. |
| 181 static Statement* PeelForLoop(ForStatement* stmt) { |
| 182 // Mark this for-statement as processed. |
| 183 stmt->set_peel_this_loop(false); |
| 184 |
| 185 // Create new block containing the init statement of the for-loop and |
| 186 // an if-statement containing the peeled iteration and the original |
| 187 // loop without the init-statement. |
| 188 Block* block = new Block(NULL, 2, false); |
| 189 if (stmt->init() != NULL) { |
| 190 Statement* init = stmt->init(); |
| 191 // The init statement gets the statement position of the for-loop |
| 192 // to make debugging of peeled loops possible. |
| 193 init->set_statement_pos(stmt->statement_pos()); |
| 194 block->AddStatement(init); |
| 195 } |
| 196 |
| 197 // Copy the condition. |
| 198 CopyAstVisitor copy_visitor; |
| 199 Expression* cond_copy = stmt->cond() != NULL |
| 200 ? copy_visitor.DeepCopyExpr(stmt->cond()) |
| 201 : new Literal(Factory::true_value()); |
| 202 if (copy_visitor.HasStackOverflow()) return NULL; |
| 203 |
| 204 // Construct a block with the peeled body and the rest of the for-loop. |
| 205 Statement* body_copy = copy_visitor.DeepCopyStmt(stmt->body()); |
| 206 if (copy_visitor.HasStackOverflow()) return NULL; |
| 207 |
| 208 Statement* next_copy = stmt->next() != NULL |
| 209 ? copy_visitor.DeepCopyStmt(stmt->next()) |
| 210 : new EmptyStatement(); |
| 211 if (copy_visitor.HasStackOverflow()) return NULL; |
| 212 |
| 213 Block* peeled_body = new Block(NULL, 3, false); |
| 214 peeled_body->AddStatement(body_copy); |
| 215 peeled_body->AddStatement(next_copy); |
| 216 peeled_body->AddStatement(stmt); |
| 217 |
| 218 // Remove the duplicated init statement from the for-statement. |
| 219 stmt->set_init(NULL); |
| 220 |
| 221 // Create new test at the top and add it to the newly created block. |
| 222 IfStatement* test = new IfStatement(cond_copy, |
| 223 peeled_body, |
| 224 new EmptyStatement()); |
| 225 block->AddStatement(test); |
| 226 return block; |
| 227 } |
| 228 |
| 229 |
| 230 void FlowGraphBuilder::VisitStatements(ZoneList<Statement*>* stmts) { |
| 231 for (int i = 0, len = stmts->length(); i < len; i++) { |
| 232 stmts->at(i) = ProcessStatement(stmts->at(i)); |
| 233 } |
| 234 } |
| 235 |
| 236 |
| 237 Statement* FlowGraphBuilder::ProcessStatement(Statement* stmt) { |
| 238 if (FLAG_loop_peeling && |
| 239 stmt->AsForStatement() != NULL && |
| 240 stmt->AsForStatement()->peel_this_loop()) { |
| 241 Statement* tmp_stmt = PeelForLoop(stmt->AsForStatement()); |
| 242 if (tmp_stmt == NULL) { |
| 243 SetStackOverflow(); |
| 244 } else { |
| 245 stmt = tmp_stmt; |
| 246 } |
| 247 } |
| 248 Visit(stmt); |
| 249 return stmt; |
| 250 } |
| 251 |
| 252 |
| 253 void FlowGraphBuilder::VisitDeclaration(Declaration* decl) { |
| 254 UNREACHABLE(); |
| 255 } |
| 256 |
| 257 |
| 258 void FlowGraphBuilder::VisitBlock(Block* stmt) { |
| 259 VisitStatements(stmt->statements()); |
| 260 } |
| 261 |
| 262 |
| 263 void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 264 Visit(stmt->expression()); |
| 265 } |
| 266 |
| 267 |
| 268 void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { |
| 269 // Nothing to do. |
| 270 } |
| 271 |
| 272 |
| 273 void FlowGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
| 274 Visit(stmt->condition()); |
| 275 |
| 276 BranchNode* branch = new BranchNode(); |
| 277 FlowGraph original = graph_; |
| 278 graph_ = FlowGraph::Empty(); |
| 279 stmt->set_then_statement(ProcessStatement(stmt->then_statement())); |
| 280 |
| 281 FlowGraph left = graph_; |
| 282 graph_ = FlowGraph::Empty(); |
| 283 stmt->set_else_statement(ProcessStatement(stmt->else_statement())); |
| 284 |
| 285 if (HasStackOverflow()) return; |
| 286 JoinNode* join = new JoinNode(); |
| 287 original.Split(branch, &left, &graph_, join); |
| 288 graph_ = original; |
| 289 } |
| 290 |
| 291 |
| 292 void FlowGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
| 293 SetStackOverflow(); |
| 294 } |
| 295 |
| 296 |
| 297 void FlowGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
| 298 SetStackOverflow(); |
| 299 } |
| 300 |
| 301 |
| 302 void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| 303 SetStackOverflow(); |
| 304 } |
| 305 |
| 306 |
| 307 void FlowGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { |
| 308 SetStackOverflow(); |
| 309 } |
| 310 |
| 311 |
| 312 void FlowGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { |
| 313 SetStackOverflow(); |
| 314 } |
| 315 |
| 316 |
| 317 void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
| 318 SetStackOverflow(); |
| 319 } |
| 320 |
| 321 |
| 322 void FlowGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 323 SetStackOverflow(); |
| 324 } |
| 325 |
| 326 |
| 327 void FlowGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| 328 SetStackOverflow(); |
| 329 } |
| 330 |
| 331 |
| 332 void FlowGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| 333 if (stmt->init() != NULL) stmt->set_init(ProcessStatement(stmt->init())); |
| 334 |
| 335 JoinNode* join = new JoinNode(); |
| 336 FlowGraph original = graph_; |
| 337 graph_ = FlowGraph::Empty(); |
| 338 if (stmt->cond() != NULL) Visit(stmt->cond()); |
| 339 |
| 340 BranchNode* branch = new BranchNode(); |
| 341 FlowGraph condition = graph_; |
| 342 graph_ = FlowGraph::Empty(); |
| 343 stmt->set_body(ProcessStatement(stmt->body())); |
| 344 |
| 345 if (stmt->next() != NULL) stmt->set_next(ProcessStatement(stmt->next())); |
| 346 |
| 347 if (HasStackOverflow()) return; |
| 348 original.Loop(join, &condition, branch, &graph_); |
| 349 graph_ = original; |
| 350 } |
| 351 |
| 352 |
| 353 void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| 354 SetStackOverflow(); |
| 355 } |
| 356 |
| 357 |
| 358 void FlowGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 359 SetStackOverflow(); |
| 360 } |
| 361 |
| 362 |
| 363 void FlowGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 364 SetStackOverflow(); |
| 365 } |
| 366 |
| 367 |
| 368 void FlowGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 369 SetStackOverflow(); |
| 370 } |
| 371 |
| 372 |
| 373 void FlowGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 374 SetStackOverflow(); |
| 375 } |
| 376 |
| 377 |
| 378 void FlowGraphBuilder::VisitSharedFunctionInfoLiteral( |
| 379 SharedFunctionInfoLiteral* expr) { |
| 380 SetStackOverflow(); |
| 381 } |
| 382 |
| 383 |
| 384 void FlowGraphBuilder::VisitConditional(Conditional* expr) { |
| 385 SetStackOverflow(); |
| 386 } |
| 387 |
| 388 |
| 389 void FlowGraphBuilder::VisitSlot(Slot* expr) { |
| 390 UNREACHABLE(); |
| 391 } |
| 392 |
| 393 |
| 394 void FlowGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 395 graph_.AppendInstruction(expr); |
| 396 } |
| 397 |
| 398 |
| 399 void FlowGraphBuilder::VisitLiteral(Literal* expr) { |
| 400 graph_.AppendInstruction(expr); |
| 401 } |
| 402 |
| 403 |
| 404 void FlowGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 405 SetStackOverflow(); |
| 406 } |
| 407 |
| 408 |
| 409 void FlowGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 410 SetStackOverflow(); |
| 411 } |
| 412 |
| 413 |
| 414 void FlowGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 415 SetStackOverflow(); |
| 416 } |
| 417 |
| 418 |
| 419 void FlowGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| 420 SetStackOverflow(); |
| 421 } |
| 422 |
| 423 |
| 424 void FlowGraphBuilder::VisitAssignment(Assignment* expr) { |
| 425 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
| 426 Property* prop = expr->target()->AsProperty(); |
| 427 // Left-hand side can be a variable or property (or reference error) but |
| 428 // not both. |
| 429 ASSERT(var == NULL || prop == NULL); |
| 430 if (var != NULL) { |
| 431 if (expr->is_compound()) Visit(expr->target()); |
| 432 Visit(expr->value()); |
| 433 if (var->IsStackAllocated()) { |
| 434 // The first definition in the body is numbered n, where n is the |
| 435 // number of parameters and stack-allocated locals. |
| 436 expr->set_num(body_definitions_.length() + variable_count_); |
| 437 body_definitions_.Add(expr); |
| 438 } |
| 439 |
| 440 } else if (prop != NULL) { |
| 441 Visit(prop->obj()); |
| 442 if (!prop->key()->IsPropertyName()) Visit(prop->key()); |
| 443 Visit(expr->value()); |
| 444 } |
| 445 |
| 446 if (HasStackOverflow()) return; |
| 447 graph_.AppendInstruction(expr); |
| 448 } |
| 449 |
| 450 |
| 451 void FlowGraphBuilder::VisitThrow(Throw* expr) { |
| 452 SetStackOverflow(); |
| 453 } |
| 454 |
| 455 |
| 456 void FlowGraphBuilder::VisitProperty(Property* expr) { |
| 457 Visit(expr->obj()); |
| 458 if (!expr->key()->IsPropertyName()) Visit(expr->key()); |
| 459 |
| 460 if (HasStackOverflow()) return; |
| 461 graph_.AppendInstruction(expr); |
| 462 } |
| 463 |
| 464 |
| 465 void FlowGraphBuilder::VisitCall(Call* expr) { |
| 466 Visit(expr->expression()); |
| 467 ZoneList<Expression*>* arguments = expr->arguments(); |
| 468 for (int i = 0, len = arguments->length(); i < len; i++) { |
| 469 Visit(arguments->at(i)); |
| 470 } |
| 471 |
| 472 if (HasStackOverflow()) return; |
| 473 graph_.AppendInstruction(expr); |
| 474 } |
| 475 |
| 476 |
| 477 void FlowGraphBuilder::VisitCallNew(CallNew* expr) { |
| 478 SetStackOverflow(); |
| 479 } |
| 480 |
| 481 |
| 482 void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 483 SetStackOverflow(); |
| 484 } |
| 485 |
| 486 |
| 487 void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| 488 switch (expr->op()) { |
| 489 case Token::NOT: |
| 490 case Token::BIT_NOT: |
| 491 case Token::DELETE: |
| 492 case Token::TYPEOF: |
| 493 case Token::VOID: |
| 494 SetStackOverflow(); |
| 495 break; |
| 496 |
| 497 case Token::ADD: |
| 498 case Token::SUB: |
| 499 Visit(expr->expression()); |
| 500 if (HasStackOverflow()) return; |
| 501 graph_.AppendInstruction(expr); |
| 502 break; |
| 503 |
| 504 default: |
| 505 UNREACHABLE(); |
| 506 } |
| 507 } |
| 508 |
| 509 |
| 510 void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| 511 Visit(expr->expression()); |
| 512 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| 513 if (var != NULL && var->IsStackAllocated()) { |
| 514 // The first definition in the body is numbered n, where n is the number |
| 515 // of parameters and stack-allocated locals. |
| 516 expr->set_num(body_definitions_.length() + variable_count_); |
| 517 body_definitions_.Add(expr); |
| 518 } |
| 519 |
| 520 if (HasStackOverflow()) return; |
| 521 graph_.AppendInstruction(expr); |
| 522 } |
| 523 |
| 524 |
| 525 void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| 526 switch (expr->op()) { |
| 527 case Token::COMMA: |
| 528 case Token::OR: |
| 529 case Token::AND: |
| 530 SetStackOverflow(); |
| 531 break; |
| 532 |
| 533 case Token::BIT_OR: |
| 534 case Token::BIT_XOR: |
| 535 case Token::BIT_AND: |
| 536 case Token::SHL: |
| 537 case Token::SHR: |
| 538 case Token::ADD: |
| 539 case Token::SUB: |
| 540 case Token::MUL: |
| 541 case Token::DIV: |
| 542 case Token::MOD: |
| 543 case Token::SAR: |
| 544 Visit(expr->left()); |
| 545 Visit(expr->right()); |
| 546 if (HasStackOverflow()) return; |
| 547 graph_.AppendInstruction(expr); |
| 548 break; |
| 549 |
| 550 default: |
| 551 UNREACHABLE(); |
| 552 } |
| 553 } |
| 554 |
| 555 |
| 556 void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 557 switch (expr->op()) { |
| 558 case Token::EQ: |
| 559 case Token::NE: |
| 560 case Token::EQ_STRICT: |
| 561 case Token::NE_STRICT: |
| 562 case Token::INSTANCEOF: |
| 563 case Token::IN: |
| 564 SetStackOverflow(); |
| 565 break; |
| 566 |
| 567 case Token::LT: |
| 568 case Token::GT: |
| 569 case Token::LTE: |
| 570 case Token::GTE: |
| 571 Visit(expr->left()); |
| 572 Visit(expr->right()); |
| 573 if (HasStackOverflow()) return; |
| 574 graph_.AppendInstruction(expr); |
| 575 break; |
| 576 |
| 577 default: |
| 578 UNREACHABLE(); |
| 579 } |
| 580 } |
| 581 |
| 582 |
| 583 void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 584 SetStackOverflow(); |
| 585 } |
| 586 |
| 587 |
| 588 } } // namespace v8::internal |
OLD | NEW |