1// Copyright 2006-2008 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 "v8.h" 29 30#include "ast.h" 31#include "func-name-inferrer.h" 32#include "scopes.h" 33#include "rewriter.h" 34 35namespace v8 { 36namespace internal { 37 38 39class AstOptimizer: public AstVisitor { 40 public: 41 explicit AstOptimizer() : has_function_literal_(false) {} 42 explicit AstOptimizer(Handle<String> enclosing_name) 43 : has_function_literal_(false) { 44 func_name_inferrer_.PushEnclosingName(enclosing_name); 45 } 46 47 void Optimize(ZoneList<Statement*>* statements); 48 49 private: 50 // Used for loop condition analysis. Cleared before visiting a loop 51 // condition, set when a function literal is visited. 52 bool has_function_literal_; 53 // Helper object for function name inferring. 54 FuncNameInferrer func_name_inferrer_; 55 56 // Helpers 57 void OptimizeArguments(ZoneList<Expression*>* arguments); 58 59 // Node visitors. 60#define DEF_VISIT(type) \ 61 virtual void Visit##type(type* node); 62 AST_NODE_LIST(DEF_VISIT) 63#undef DEF_VISIT 64 65 DISALLOW_COPY_AND_ASSIGN(AstOptimizer); 66}; 67 68 69void AstOptimizer::Optimize(ZoneList<Statement*>* statements) { 70 int len = statements->length(); 71 for (int i = 0; i < len; i++) { 72 Visit(statements->at(i)); 73 } 74} 75 76 77void AstOptimizer::OptimizeArguments(ZoneList<Expression*>* arguments) { 78 for (int i = 0; i < arguments->length(); i++) { 79 Visit(arguments->at(i)); 80 } 81} 82 83 84void AstOptimizer::VisitBlock(Block* node) { 85 Optimize(node->statements()); 86} 87 88 89void AstOptimizer::VisitExpressionStatement(ExpressionStatement* node) { 90 Visit(node->expression()); 91} 92 93 94void AstOptimizer::VisitIfStatement(IfStatement* node) { 95 Visit(node->condition()); 96 Visit(node->then_statement()); 97 if (node->HasElseStatement()) { 98 Visit(node->else_statement()); 99 } 100} 101 102 103void AstOptimizer::VisitDoWhileStatement(DoWhileStatement* node) { 104 Visit(node->cond()); 105 Visit(node->body()); 106} 107 108 109void AstOptimizer::VisitWhileStatement(WhileStatement* node) { 110 has_function_literal_ = false; 111 Visit(node->cond()); 112 node->may_have_function_literal_ = has_function_literal_; 113 Visit(node->body()); 114} 115 116 117void AstOptimizer::VisitForStatement(ForStatement* node) { 118 if (node->init() != NULL) { 119 Visit(node->init()); 120 } 121 if (node->cond() != NULL) { 122 has_function_literal_ = false; 123 Visit(node->cond()); 124 node->may_have_function_literal_ = has_function_literal_; 125 } 126 Visit(node->body()); 127 if (node->next() != NULL) { 128 Visit(node->next()); 129 } 130} 131 132 133void AstOptimizer::VisitForInStatement(ForInStatement* node) { 134 Visit(node->each()); 135 Visit(node->enumerable()); 136 Visit(node->body()); 137} 138 139 140void AstOptimizer::VisitTryCatchStatement(TryCatchStatement* node) { 141 Visit(node->try_block()); 142 Visit(node->catch_var()); 143 Visit(node->catch_block()); 144} 145 146 147void AstOptimizer::VisitTryFinallyStatement(TryFinallyStatement* node) { 148 Visit(node->try_block()); 149 Visit(node->finally_block()); 150} 151 152 153void AstOptimizer::VisitSwitchStatement(SwitchStatement* node) { 154 Visit(node->tag()); 155 for (int i = 0; i < node->cases()->length(); i++) { 156 CaseClause* clause = node->cases()->at(i); 157 if (!clause->is_default()) { 158 Visit(clause->label()); 159 } 160 Optimize(clause->statements()); 161 } 162} 163 164 165void AstOptimizer::VisitContinueStatement(ContinueStatement* node) { 166 USE(node); 167} 168 169 170void AstOptimizer::VisitBreakStatement(BreakStatement* node) { 171 USE(node); 172} 173 174 175void AstOptimizer::VisitDeclaration(Declaration* node) { 176 // Will not be reached by the current optimizations. 177 USE(node); 178} 179 180 181void AstOptimizer::VisitEmptyStatement(EmptyStatement* node) { 182 USE(node); 183} 184 185 186void AstOptimizer::VisitReturnStatement(ReturnStatement* node) { 187 Visit(node->expression()); 188} 189 190 191void AstOptimizer::VisitWithEnterStatement(WithEnterStatement* node) { 192 Visit(node->expression()); 193} 194 195 196void AstOptimizer::VisitWithExitStatement(WithExitStatement* node) { 197 USE(node); 198} 199 200 201void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) { 202 USE(node); 203} 204 205 206void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) { 207 has_function_literal_ = true; 208 209 if (node->name()->length() == 0) { 210 // Anonymous function. 211 func_name_inferrer_.AddFunction(node); 212 } 213} 214 215 216void AstOptimizer::VisitFunctionBoilerplateLiteral( 217 FunctionBoilerplateLiteral* node) { 218 USE(node); 219} 220 221 222void AstOptimizer::VisitConditional(Conditional* node) { 223 Visit(node->condition()); 224 Visit(node->then_expression()); 225 Visit(node->else_expression()); 226} 227 228 229void AstOptimizer::VisitSlot(Slot* node) { 230 USE(node); 231} 232 233 234void AstOptimizer::VisitVariableProxy(VariableProxy* node) { 235 Variable* var = node->AsVariable(); 236 if (var != NULL) { 237 if (var->type()->IsKnown()) { 238 node->type()->CopyFrom(var->type()); 239 } else if (node->type()->IsLikelySmi()) { 240 var->type()->SetAsLikelySmi(); 241 } 242 243 if (!var->is_this() && 244 !Heap::result_symbol()->Equals(*var->name())) { 245 func_name_inferrer_.PushName(var->name()); 246 } 247 } 248} 249 250 251void AstOptimizer::VisitLiteral(Literal* node) { 252 Handle<Object> literal = node->handle(); 253 if (literal->IsSmi()) { 254 node->type()->SetAsLikelySmi(); 255 } else if (literal->IsString()) { 256 Handle<String> lit_str(Handle<String>::cast(literal)); 257 if (!Heap::prototype_symbol()->Equals(*lit_str)) { 258 func_name_inferrer_.PushName(lit_str); 259 } 260 } 261} 262 263 264void AstOptimizer::VisitRegExpLiteral(RegExpLiteral* node) { 265 USE(node); 266} 267 268 269void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) { 270 for (int i = 0; i < node->values()->length(); i++) { 271 Visit(node->values()->at(i)); 272 } 273} 274 275void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) { 276 for (int i = 0; i < node->properties()->length(); i++) { 277 ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_); 278 scoped_fni.Enter(); 279 Visit(node->properties()->at(i)->key()); 280 Visit(node->properties()->at(i)->value()); 281 } 282} 283 284 285void AstOptimizer::VisitCatchExtensionObject(CatchExtensionObject* node) { 286 Visit(node->key()); 287 Visit(node->value()); 288} 289 290 291void AstOptimizer::VisitAssignment(Assignment* node) { 292 ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_); 293 switch (node->op()) { 294 case Token::INIT_VAR: 295 case Token::INIT_CONST: 296 case Token::ASSIGN: 297 // No type can be infered from the general assignment. 298 299 // Don't infer if it is "a = function(){...}();"-like expression. 300 if (node->value()->AsCall() == NULL) { 301 scoped_fni.Enter(); 302 } 303 break; 304 case Token::ASSIGN_BIT_OR: 305 case Token::ASSIGN_BIT_XOR: 306 case Token::ASSIGN_BIT_AND: 307 case Token::ASSIGN_SHL: 308 case Token::ASSIGN_SAR: 309 case Token::ASSIGN_SHR: 310 node->type()->SetAsLikelySmiIfUnknown(); 311 node->target()->type()->SetAsLikelySmiIfUnknown(); 312 node->value()->type()->SetAsLikelySmiIfUnknown(); 313 break; 314 case Token::ASSIGN_ADD: 315 case Token::ASSIGN_SUB: 316 case Token::ASSIGN_MUL: 317 case Token::ASSIGN_DIV: 318 case Token::ASSIGN_MOD: 319 if (node->type()->IsLikelySmi()) { 320 node->target()->type()->SetAsLikelySmiIfUnknown(); 321 node->value()->type()->SetAsLikelySmiIfUnknown(); 322 } 323 break; 324 default: 325 UNREACHABLE(); 326 break; 327 } 328 329 Visit(node->target()); 330 Visit(node->value()); 331 332 switch (node->op()) { 333 case Token::INIT_VAR: 334 case Token::INIT_CONST: 335 case Token::ASSIGN: 336 // Pure assignment copies the type from the value. 337 node->type()->CopyFrom(node->value()->type()); 338 break; 339 case Token::ASSIGN_BIT_OR: 340 case Token::ASSIGN_BIT_XOR: 341 case Token::ASSIGN_BIT_AND: 342 case Token::ASSIGN_SHL: 343 case Token::ASSIGN_SAR: 344 case Token::ASSIGN_SHR: 345 // Should have been setup above already. 346 break; 347 case Token::ASSIGN_ADD: 348 case Token::ASSIGN_SUB: 349 case Token::ASSIGN_MUL: 350 case Token::ASSIGN_DIV: 351 case Token::ASSIGN_MOD: 352 if (node->type()->IsUnknown()) { 353 if (node->target()->type()->IsLikelySmi() || 354 node->value()->type()->IsLikelySmi()) { 355 node->type()->SetAsLikelySmi(); 356 } 357 } 358 break; 359 default: 360 UNREACHABLE(); 361 break; 362 } 363 364 // Since this is an assignment. We have to propagate this node's type to the 365 // variable. 366 VariableProxy* proxy = node->target()->AsVariableProxy(); 367 if (proxy != NULL) { 368 Variable* var = proxy->AsVariable(); 369 if (var != NULL) { 370 StaticType* var_type = var->type(); 371 if (var_type->IsUnknown()) { 372 var_type->CopyFrom(node->type()); 373 } else if (var_type->IsLikelySmi()) { 374 // We do not reset likely types to Unknown. 375 } 376 } 377 } 378} 379 380 381void AstOptimizer::VisitThrow(Throw* node) { 382 Visit(node->exception()); 383} 384 385 386void AstOptimizer::VisitProperty(Property* node) { 387 Visit(node->obj()); 388 Visit(node->key()); 389} 390 391 392void AstOptimizer::VisitCall(Call* node) { 393 Visit(node->expression()); 394 OptimizeArguments(node->arguments()); 395} 396 397 398void AstOptimizer::VisitCallNew(CallNew* node) { 399 Visit(node->expression()); 400 OptimizeArguments(node->arguments()); 401} 402 403 404void AstOptimizer::VisitCallRuntime(CallRuntime* node) { 405 ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_); 406 if (Factory::InitializeVarGlobal_symbol()->Equals(*node->name()) && 407 node->arguments()->length() >= 2 && 408 node->arguments()->at(1)->AsFunctionLiteral() != NULL) { 409 scoped_fni.Enter(); 410 } 411 OptimizeArguments(node->arguments()); 412} 413 414 415void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) { 416 Visit(node->expression()); 417} 418 419 420void AstOptimizer::VisitCountOperation(CountOperation* node) { 421 // Count operations assume that they work on Smis. 422 node->type()->SetAsLikelySmiIfUnknown(); 423 node->expression()->type()->SetAsLikelySmiIfUnknown(); 424 Visit(node->expression()); 425} 426 427 428void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) { 429 // Depending on the operation we can propagate this node's type down the 430 // AST nodes. 431 switch (node->op()) { 432 case Token::COMMA: 433 case Token::OR: 434 case Token::AND: 435 break; 436 case Token::BIT_OR: 437 case Token::BIT_XOR: 438 case Token::BIT_AND: 439 case Token::SHL: 440 case Token::SAR: 441 case Token::SHR: 442 node->type()->SetAsLikelySmiIfUnknown(); 443 node->left()->type()->SetAsLikelySmiIfUnknown(); 444 node->right()->type()->SetAsLikelySmiIfUnknown(); 445 break; 446 case Token::ADD: 447 case Token::SUB: 448 case Token::MUL: 449 case Token::DIV: 450 case Token::MOD: 451 if (node->type()->IsLikelySmi()) { 452 node->left()->type()->SetAsLikelySmiIfUnknown(); 453 node->right()->type()->SetAsLikelySmiIfUnknown(); 454 } 455 break; 456 default: 457 UNREACHABLE(); 458 break; 459 } 460 461 Visit(node->left()); 462 Visit(node->right()); 463 464 // After visiting the operand nodes we have to check if this node's type 465 // can be updated. If it does, then we can push that information down 466 // towards the leafs again if the new information is an upgrade over the 467 // previous type of the operand nodes. 468 if (node->type()->IsUnknown()) { 469 if (node->left()->type()->IsLikelySmi() || 470 node->right()->type()->IsLikelySmi()) { 471 node->type()->SetAsLikelySmi(); 472 } 473 if (node->type()->IsLikelySmi()) { 474 // The type of this node changed to LIKELY_SMI. Propagate this knowledge 475 // down through the nodes. 476 if (node->left()->type()->IsUnknown()) { 477 node->left()->type()->SetAsLikelySmi(); 478 Visit(node->left()); 479 } 480 if (node->right()->type()->IsUnknown()) { 481 node->right()->type()->SetAsLikelySmi(); 482 Visit(node->right()); 483 } 484 } 485 } 486} 487 488 489void AstOptimizer::VisitCompareOperation(CompareOperation* node) { 490 if (node->type()->IsKnown()) { 491 // Propagate useful information down towards the leafs. 492 node->left()->type()->SetAsLikelySmiIfUnknown(); 493 node->right()->type()->SetAsLikelySmiIfUnknown(); 494 } 495 496 Visit(node->left()); 497 Visit(node->right()); 498 499 // After visiting the operand nodes we have to check if this node's type 500 // can be updated. If it does, then we can push that information down 501 // towards the leafs again if the new information is an upgrade over the 502 // previous type of the operand nodes. 503 if (node->type()->IsUnknown()) { 504 if (node->left()->type()->IsLikelySmi() || 505 node->right()->type()->IsLikelySmi()) { 506 node->type()->SetAsLikelySmi(); 507 } 508 if (node->type()->IsLikelySmi()) { 509 // The type of this node changed to LIKELY_SMI. Propagate this knowledge 510 // down through the nodes. 511 if (node->left()->type()->IsUnknown()) { 512 node->left()->type()->SetAsLikelySmi(); 513 Visit(node->left()); 514 } 515 if (node->right()->type()->IsUnknown()) { 516 node->right()->type()->SetAsLikelySmi(); 517 Visit(node->right()); 518 } 519 } 520 } 521} 522 523 524void AstOptimizer::VisitThisFunction(ThisFunction* node) { 525 USE(node); 526} 527 528 529class Processor: public AstVisitor { 530 public: 531 explicit Processor(VariableProxy* result) 532 : result_(result), 533 result_assigned_(false), 534 is_set_(false), 535 in_try_(false) { 536 } 537 538 void Process(ZoneList<Statement*>* statements); 539 bool result_assigned() const { return result_assigned_; } 540 541 private: 542 VariableProxy* result_; 543 544 // We are not tracking result usage via the result_'s use 545 // counts (we leave the accurate computation to the 546 // usage analyzer). Instead we simple remember if 547 // there was ever an assignment to result_. 548 bool result_assigned_; 549 550 // To avoid storing to .result all the time, we eliminate some of 551 // the stores by keeping track of whether or not we're sure .result 552 // will be overwritten anyway. This is a bit more tricky than what I 553 // was hoping for 554 bool is_set_; 555 bool in_try_; 556 557 Expression* SetResult(Expression* value) { 558 result_assigned_ = true; 559 return new Assignment(Token::ASSIGN, result_, value, 560 RelocInfo::kNoPosition); 561 } 562 563 // Node visitors. 564#define DEF_VISIT(type) \ 565 virtual void Visit##type(type* node); 566 AST_NODE_LIST(DEF_VISIT) 567#undef DEF_VISIT 568 569 void VisitIterationStatement(IterationStatement* stmt); 570}; 571 572 573void Processor::Process(ZoneList<Statement*>* statements) { 574 for (int i = statements->length() - 1; i >= 0; --i) { 575 Visit(statements->at(i)); 576 } 577} 578 579 580void Processor::VisitBlock(Block* node) { 581 // An initializer block is the rewritten form of a variable declaration 582 // with initialization expressions. The initializer block contains the 583 // list of assignments corresponding to the initialization expressions. 584 // While unclear from the spec (ECMA-262, 3rd., 12.2), the value of 585 // a variable declaration with initialization expression is 'undefined' 586 // with some JS VMs: For instance, using smjs, print(eval('var x = 7')) 587 // returns 'undefined'. To obtain the same behavior with v8, we need 588 // to prevent rewriting in that case. 589 if (!node->is_initializer_block()) Process(node->statements()); 590} 591 592 593void Processor::VisitExpressionStatement(ExpressionStatement* node) { 594 // Rewrite : <x>; -> .result = <x>; 595 if (!is_set_) { 596 node->set_expression(SetResult(node->expression())); 597 if (!in_try_) is_set_ = true; 598 } 599} 600 601 602void Processor::VisitIfStatement(IfStatement* node) { 603 // Rewrite both then and else parts (reversed). 604 bool save = is_set_; 605 Visit(node->else_statement()); 606 bool set_after_then = is_set_; 607 is_set_ = save; 608 Visit(node->then_statement()); 609 is_set_ = is_set_ && set_after_then; 610} 611 612 613void Processor::VisitIterationStatement(IterationStatement* node) { 614 // Rewrite the body. 615 bool set_after_loop = is_set_; 616 Visit(node->body()); 617 is_set_ = is_set_ && set_after_loop; 618} 619 620 621void Processor::VisitDoWhileStatement(DoWhileStatement* node) { 622 VisitIterationStatement(node); 623} 624 625 626void Processor::VisitWhileStatement(WhileStatement* node) { 627 VisitIterationStatement(node); 628} 629 630 631void Processor::VisitForStatement(ForStatement* node) { 632 VisitIterationStatement(node); 633} 634 635 636void Processor::VisitForInStatement(ForInStatement* node) { 637 VisitIterationStatement(node); 638} 639 640 641void Processor::VisitTryCatchStatement(TryCatchStatement* node) { 642 // Rewrite both try and catch blocks (reversed order). 643 bool set_after_catch = is_set_; 644 Visit(node->catch_block()); 645 is_set_ = is_set_ && set_after_catch; 646 bool save = in_try_; 647 in_try_ = true; 648 Visit(node->try_block()); 649 in_try_ = save; 650} 651 652 653void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { 654 // Rewrite both try and finally block (reversed order). 655 Visit(node->finally_block()); 656 bool save = in_try_; 657 in_try_ = true; 658 Visit(node->try_block()); 659 in_try_ = save; 660} 661 662 663void Processor::VisitSwitchStatement(SwitchStatement* node) { 664 // Rewrite statements in all case clauses in reversed order. 665 ZoneList<CaseClause*>* clauses = node->cases(); 666 bool set_after_switch = is_set_; 667 for (int i = clauses->length() - 1; i >= 0; --i) { 668 CaseClause* clause = clauses->at(i); 669 Process(clause->statements()); 670 } 671 is_set_ = is_set_ && set_after_switch; 672} 673 674 675void Processor::VisitContinueStatement(ContinueStatement* node) { 676 is_set_ = false; 677} 678 679 680void Processor::VisitBreakStatement(BreakStatement* node) { 681 is_set_ = false; 682} 683 684 685// Do nothing: 686void Processor::VisitDeclaration(Declaration* node) {} 687void Processor::VisitEmptyStatement(EmptyStatement* node) {} 688void Processor::VisitReturnStatement(ReturnStatement* node) {} 689void Processor::VisitWithEnterStatement(WithEnterStatement* node) {} 690void Processor::VisitWithExitStatement(WithExitStatement* node) {} 691void Processor::VisitDebuggerStatement(DebuggerStatement* node) {} 692 693 694// Expressions are never visited yet. 695void Processor::VisitFunctionLiteral(FunctionLiteral* node) { 696 USE(node); 697 UNREACHABLE(); 698} 699 700 701void Processor::VisitFunctionBoilerplateLiteral( 702 FunctionBoilerplateLiteral* node) { 703 USE(node); 704 UNREACHABLE(); 705} 706 707 708void Processor::VisitConditional(Conditional* node) { 709 USE(node); 710 UNREACHABLE(); 711} 712 713 714void Processor::VisitSlot(Slot* node) { 715 USE(node); 716 UNREACHABLE(); 717} 718 719 720void Processor::VisitVariableProxy(VariableProxy* node) { 721 USE(node); 722 UNREACHABLE(); 723} 724 725 726void Processor::VisitLiteral(Literal* node) { 727 USE(node); 728 UNREACHABLE(); 729} 730 731 732void Processor::VisitRegExpLiteral(RegExpLiteral* node) { 733 USE(node); 734 UNREACHABLE(); 735} 736 737 738void Processor::VisitArrayLiteral(ArrayLiteral* node) { 739 USE(node); 740 UNREACHABLE(); 741} 742 743 744void Processor::VisitObjectLiteral(ObjectLiteral* node) { 745 USE(node); 746 UNREACHABLE(); 747} 748 749 750void Processor::VisitCatchExtensionObject(CatchExtensionObject* node) { 751 USE(node); 752 UNREACHABLE(); 753} 754 755 756void Processor::VisitAssignment(Assignment* node) { 757 USE(node); 758 UNREACHABLE(); 759} 760 761 762void Processor::VisitThrow(Throw* node) { 763 USE(node); 764 UNREACHABLE(); 765} 766 767 768void Processor::VisitProperty(Property* node) { 769 USE(node); 770 UNREACHABLE(); 771} 772 773 774void Processor::VisitCall(Call* node) { 775 USE(node); 776 UNREACHABLE(); 777} 778 779 780void Processor::VisitCallNew(CallNew* node) { 781 USE(node); 782 UNREACHABLE(); 783} 784 785 786void Processor::VisitCallRuntime(CallRuntime* node) { 787 USE(node); 788 UNREACHABLE(); 789} 790 791 792void Processor::VisitUnaryOperation(UnaryOperation* node) { 793 USE(node); 794 UNREACHABLE(); 795} 796 797 798void Processor::VisitCountOperation(CountOperation* node) { 799 USE(node); 800 UNREACHABLE(); 801} 802 803 804void Processor::VisitBinaryOperation(BinaryOperation* node) { 805 USE(node); 806 UNREACHABLE(); 807} 808 809 810void Processor::VisitCompareOperation(CompareOperation* node) { 811 USE(node); 812 UNREACHABLE(); 813} 814 815 816void Processor::VisitThisFunction(ThisFunction* node) { 817 USE(node); 818 UNREACHABLE(); 819} 820 821 822bool Rewriter::Process(FunctionLiteral* function) { 823 HistogramTimerScope timer(&Counters::rewriting); 824 Scope* scope = function->scope(); 825 if (scope->is_function_scope()) return true; 826 827 ZoneList<Statement*>* body = function->body(); 828 if (body->is_empty()) return true; 829 830 VariableProxy* result = scope->NewTemporary(Factory::result_symbol()); 831 Processor processor(result); 832 processor.Process(body); 833 if (processor.HasStackOverflow()) return false; 834 835 if (processor.result_assigned()) body->Add(new ReturnStatement(result)); 836 return true; 837} 838 839 840bool Rewriter::Optimize(FunctionLiteral* function) { 841 ZoneList<Statement*>* body = function->body(); 842 843 if (FLAG_optimize_ast && !body->is_empty()) { 844 HistogramTimerScope timer(&Counters::ast_optimization); 845 AstOptimizer optimizer(function->name()); 846 optimizer.Optimize(body); 847 if (optimizer.HasStackOverflow()) { 848 return false; 849 } 850 } 851 return true; 852} 853 854 855} } // namespace v8::internal 856