説明を見る。00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "ast.h"
00031 #include "scopes.h"
00032 #include "rewriter.h"
00033
00034 namespace v8 { namespace internal {
00035
00036
00037 class AstOptimizer: public Visitor {
00038 public:
00039 explicit AstOptimizer() {
00040 }
00041
00042 void Optimize(ZoneList<Statement*>* statements);
00043
00044 private:
00045
00046 void OptimizeArguments(ZoneList<Expression*>* arguments);
00047
00048
00049 #define DEF_VISIT(type) \
00050 virtual void Visit##type(type* node);
00051 NODE_LIST(DEF_VISIT)
00052 #undef DEF_VISIT
00053
00054 DISALLOW_COPY_AND_ASSIGN(AstOptimizer);
00055 };
00056
00057
00058 void AstOptimizer::Optimize(ZoneList<Statement*>* statements) {
00059 int len = statements->length();
00060 for (int i = 0; i < len; i++) {
00061 Visit(statements->at(i));
00062 }
00063 }
00064
00065
00066 void AstOptimizer::OptimizeArguments(ZoneList<Expression*>* arguments) {
00067 for (int i = 0; i < arguments->length(); i++) {
00068 Visit(arguments->at(i));
00069 }
00070 }
00071
00072
00073 void AstOptimizer::VisitBlock(Block* node) {
00074 Optimize(node->statements());
00075 }
00076
00077
00078 void AstOptimizer::VisitExpressionStatement(ExpressionStatement* node) {
00079 Visit(node->expression());
00080 }
00081
00082
00083 void AstOptimizer::VisitIfStatement(IfStatement* node) {
00084 Visit(node->condition());
00085 Visit(node->then_statement());
00086 if (node->HasElseStatement()) {
00087 Visit(node->else_statement());
00088 }
00089 }
00090
00091
00092
00093
00094 void AstOptimizer::VisitLoopStatement(LoopStatement* node) {
00095 if (node->init() != NULL) {
00096 Visit(node->init());
00097 }
00098 if (node->cond() != NULL) {
00099 Visit(node->cond());
00100 }
00101 if (node->body() != NULL) {
00102 Visit(node->body());
00103 }
00104 if (node->next() != NULL) {
00105 Visit(node->next());
00106 }
00107 }
00108
00109
00110 void AstOptimizer::VisitForInStatement(ForInStatement* node) {
00111 Visit(node->each());
00112 Visit(node->enumerable());
00113 Visit(node->body());
00114 }
00115
00116
00117 void AstOptimizer::VisitTryCatch(TryCatch* node) {
00118 Visit(node->try_block());
00119 Visit(node->catch_var());
00120 Visit(node->catch_block());
00121 }
00122
00123
00124 void AstOptimizer::VisitTryFinally(TryFinally* node) {
00125 Visit(node->try_block());
00126 Visit(node->finally_block());
00127 }
00128
00129
00130 void AstOptimizer::VisitSwitchStatement(SwitchStatement* node) {
00131 Visit(node->tag());
00132 for (int i = 0; i < node->cases()->length(); i++) {
00133 CaseClause* clause = node->cases()->at(i);
00134 if (!clause->is_default()) {
00135 Visit(clause->label());
00136 }
00137 Optimize(clause->statements());
00138 }
00139 }
00140
00141
00142 void AstOptimizer::VisitContinueStatement(ContinueStatement* node) {
00143 USE(node);
00144 }
00145
00146
00147 void AstOptimizer::VisitBreakStatement(BreakStatement* node) {
00148 USE(node);
00149 }
00150
00151
00152 void AstOptimizer::VisitDeclaration(Declaration* node) {
00153
00154 USE(node);
00155 }
00156
00157
00158 void AstOptimizer::VisitEmptyStatement(EmptyStatement* node) {
00159 USE(node);
00160 }
00161
00162
00163 void AstOptimizer::VisitReturnStatement(ReturnStatement* node) {
00164 Visit(node->expression());
00165 }
00166
00167
00168 void AstOptimizer::VisitWithEnterStatement(WithEnterStatement* node) {
00169 Visit(node->expression());
00170 }
00171
00172
00173 void AstOptimizer::VisitWithExitStatement(WithExitStatement* node) {
00174 USE(node);
00175 }
00176
00177
00178 void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) {
00179 USE(node);
00180 }
00181
00182
00183 void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) {
00184 USE(node);
00185 }
00186
00187
00188 void AstOptimizer::VisitFunctionBoilerplateLiteral(
00189 FunctionBoilerplateLiteral* node) {
00190 USE(node);
00191 }
00192
00193
00194 void AstOptimizer::VisitConditional(Conditional* node) {
00195 Visit(node->condition());
00196 Visit(node->then_expression());
00197 Visit(node->else_expression());
00198 }
00199
00200
00201 void AstOptimizer::VisitSlot(Slot* node) {
00202 USE(node);
00203 }
00204
00205
00206 void AstOptimizer::VisitVariableProxy(VariableProxy* node) {
00207 Variable* var = node->AsVariable();
00208 if (var != NULL) {
00209 if (var->type()->IsKnown()) {
00210 node->type()->CopyFrom(var->type());
00211 } else if (node->type()->IsLikelySmi()) {
00212 var->type()->SetAsLikelySmi();
00213 }
00214 }
00215 }
00216
00217
00218 void AstOptimizer::VisitLiteral(Literal* node) {
00219 Handle<Object> literal = node->handle();
00220 if (literal->IsSmi()) {
00221 node->type()->SetAsLikelySmi();
00222 }
00223 }
00224
00225
00226 void AstOptimizer::VisitRegExpLiteral(RegExpLiteral* node) {
00227 USE(node);
00228 }
00229
00230
00231 void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) {
00232 for (int i = 0; i < node->values()->length(); i++) {
00233 Visit(node->values()->at(i));
00234 }
00235 }
00236
00237
00238 void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) {
00239 for (int i = 0; i < node->properties()->length(); i++) {
00240 Visit(node->properties()->at(i)->key());
00241 Visit(node->properties()->at(i)->value());
00242 }
00243 }
00244
00245
00246 void AstOptimizer::VisitAssignment(Assignment* node) {
00247 switch (node->op()) {
00248 case Token::INIT_VAR:
00249 case Token::INIT_CONST:
00250 case Token::ASSIGN:
00251
00252 break;
00253 case Token::ASSIGN_BIT_OR:
00254 case Token::ASSIGN_BIT_XOR:
00255 case Token::ASSIGN_BIT_AND:
00256 case Token::ASSIGN_SHL:
00257 case Token::ASSIGN_SAR:
00258 case Token::ASSIGN_SHR:
00259 node->type()->SetAsLikelySmiIfUnknown();
00260 node->target()->type()->SetAsLikelySmiIfUnknown();
00261 node->value()->type()->SetAsLikelySmiIfUnknown();
00262 break;
00263 case Token::ASSIGN_ADD:
00264 case Token::ASSIGN_SUB:
00265 case Token::ASSIGN_MUL:
00266 case Token::ASSIGN_DIV:
00267 case Token::ASSIGN_MOD:
00268 if (node->type()->IsLikelySmi()) {
00269 node->target()->type()->SetAsLikelySmiIfUnknown();
00270 node->value()->type()->SetAsLikelySmiIfUnknown();
00271 }
00272 break;
00273 default:
00274 UNREACHABLE();
00275 break;
00276 }
00277
00278 Visit(node->target());
00279 Visit(node->value());
00280
00281 switch (node->op()) {
00282 case Token::INIT_VAR:
00283 case Token::INIT_CONST:
00284 case Token::ASSIGN:
00285
00286 node->type()->CopyFrom(node->value()->type());
00287 break;
00288 case Token::ASSIGN_BIT_OR:
00289 case Token::ASSIGN_BIT_XOR:
00290 case Token::ASSIGN_BIT_AND:
00291 case Token::ASSIGN_SHL:
00292 case Token::ASSIGN_SAR:
00293 case Token::ASSIGN_SHR:
00294
00295 break;
00296 case Token::ASSIGN_ADD:
00297 case Token::ASSIGN_SUB:
00298 case Token::ASSIGN_MUL:
00299 case Token::ASSIGN_DIV:
00300 case Token::ASSIGN_MOD:
00301 if (node->type()->IsUnknown()) {
00302 if (node->target()->type()->IsLikelySmi() ||
00303 node->value()->type()->IsLikelySmi()) {
00304 node->type()->SetAsLikelySmi();
00305 }
00306 }
00307 break;
00308 default:
00309 UNREACHABLE();
00310 break;
00311 }
00312
00313
00314
00315 VariableProxy* proxy = node->target()->AsVariableProxy();
00316 if (proxy != NULL) {
00317 Variable* var = proxy->AsVariable();
00318 if (var != NULL) {
00319 StaticType* var_type = var->type();
00320 if (var_type->IsUnknown()) {
00321 var_type->CopyFrom(node->type());
00322 } else if (var_type->IsLikelySmi()) {
00323
00324 }
00325 }
00326 }
00327 }
00328
00329
00330 void AstOptimizer::VisitThrow(Throw* node) {
00331 Visit(node->exception());
00332 }
00333
00334
00335 void AstOptimizer::VisitProperty(Property* node) {
00336 Visit(node->obj());
00337 Visit(node->key());
00338 }
00339
00340
00341 void AstOptimizer::VisitCall(Call* node) {
00342 Visit(node->expression());
00343 OptimizeArguments(node->arguments());
00344 }
00345
00346
00347 void AstOptimizer::VisitCallNew(CallNew* node) {
00348 Visit(node->expression());
00349 OptimizeArguments(node->arguments());
00350 }
00351
00352
00353 void AstOptimizer::VisitCallRuntime(CallRuntime* node) {
00354 OptimizeArguments(node->arguments());
00355 }
00356
00357
00358 void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) {
00359 Visit(node->expression());
00360 }
00361
00362
00363 void AstOptimizer::VisitCountOperation(CountOperation* node) {
00364
00365 node->type()->SetAsLikelySmiIfUnknown();
00366 node->expression()->type()->SetAsLikelySmiIfUnknown();
00367 Visit(node->expression());
00368 }
00369
00370
00371 void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) {
00372
00373
00374 switch (node->op()) {
00375 case Token::COMMA:
00376 case Token::OR:
00377 case Token::AND:
00378 break;
00379 case Token::BIT_OR:
00380 case Token::BIT_XOR:
00381 case Token::BIT_AND:
00382 case Token::SHL:
00383 case Token::SAR:
00384 case Token::SHR:
00385 node->type()->SetAsLikelySmiIfUnknown();
00386 node->left()->type()->SetAsLikelySmiIfUnknown();
00387 node->right()->type()->SetAsLikelySmiIfUnknown();
00388 break;
00389 case Token::ADD:
00390 case Token::SUB:
00391 case Token::MUL:
00392 case Token::DIV:
00393 case Token::MOD:
00394 if (node->type()->IsLikelySmi()) {
00395 node->left()->type()->SetAsLikelySmiIfUnknown();
00396 node->right()->type()->SetAsLikelySmiIfUnknown();
00397 }
00398 break;
00399 default:
00400 UNREACHABLE();
00401 break;
00402 }
00403
00404 Visit(node->left());
00405 Visit(node->right());
00406
00407
00408
00409
00410
00411 if (node->type()->IsUnknown()) {
00412 if (node->left()->type()->IsLikelySmi() ||
00413 node->right()->type()->IsLikelySmi()) {
00414 node->type()->SetAsLikelySmi();
00415 }
00416 if (node->type()->IsLikelySmi()) {
00417
00418
00419 if (node->left()->type()->IsUnknown()) {
00420 node->left()->type()->SetAsLikelySmi();
00421 Visit(node->left());
00422 }
00423 if (node->right()->type()->IsUnknown()) {
00424 node->right()->type()->SetAsLikelySmi();
00425 Visit(node->right());
00426 }
00427 }
00428 }
00429 }
00430
00431
00432 void AstOptimizer::VisitCompareOperation(CompareOperation* node) {
00433 if (node->type()->IsKnown()) {
00434
00435 node->left()->type()->SetAsLikelySmiIfUnknown();
00436 node->right()->type()->SetAsLikelySmiIfUnknown();
00437 }
00438
00439 Visit(node->left());
00440 Visit(node->right());
00441
00442
00443
00444
00445
00446 if (node->type()->IsUnknown()) {
00447 if (node->left()->type()->IsLikelySmi() ||
00448 node->right()->type()->IsLikelySmi()) {
00449 node->type()->SetAsLikelySmi();
00450 }
00451 if (node->type()->IsLikelySmi()) {
00452
00453
00454 if (node->left()->type()->IsUnknown()) {
00455 node->left()->type()->SetAsLikelySmi();
00456 Visit(node->left());
00457 }
00458 if (node->right()->type()->IsUnknown()) {
00459 node->right()->type()->SetAsLikelySmi();
00460 Visit(node->right());
00461 }
00462 }
00463 }
00464 }
00465
00466
00467 void AstOptimizer::VisitThisFunction(ThisFunction* node) {
00468 USE(node);
00469 }
00470
00471
00472 class Processor: public Visitor {
00473 public:
00474 explicit Processor(VariableProxy* result)
00475 : result_(result),
00476 result_assigned_(false),
00477 is_set_(false),
00478 in_try_(false) {
00479 }
00480
00481 void Process(ZoneList<Statement*>* statements);
00482 bool result_assigned() const { return result_assigned_; }
00483
00484 private:
00485 VariableProxy* result_;
00486
00487
00488
00489
00490
00491 bool result_assigned_;
00492
00493
00494
00495
00496
00497 bool is_set_;
00498 bool in_try_;
00499
00500 Expression* SetResult(Expression* value) {
00501 result_assigned_ = true;
00502 return new Assignment(Token::ASSIGN, result_, value,
00503 RelocInfo::kNoPosition);
00504 }
00505
00506
00507 #define DEF_VISIT(type) \
00508 virtual void Visit##type(type* node);
00509 NODE_LIST(DEF_VISIT)
00510 #undef DEF_VISIT
00511 };
00512
00513
00514 void Processor::Process(ZoneList<Statement*>* statements) {
00515 for (int i = statements->length() - 1; i >= 0; --i) {
00516 Visit(statements->at(i));
00517 }
00518 }
00519
00520
00521 void Processor::VisitBlock(Block* node) {
00522
00523
00524
00525
00526
00527
00528
00529
00530 if (!node->is_initializer_block()) Process(node->statements());
00531 }
00532
00533
00534 void Processor::VisitExpressionStatement(ExpressionStatement* node) {
00535
00536 if (!is_set_) {
00537 node->set_expression(SetResult(node->expression()));
00538 if (!in_try_) is_set_ = true;
00539 }
00540 }
00541
00542
00543 void Processor::VisitIfStatement(IfStatement* node) {
00544
00545 bool save = is_set_;
00546 Visit(node->else_statement());
00547 bool set_after_then = is_set_;
00548 is_set_ = save;
00549 Visit(node->then_statement());
00550 is_set_ = is_set_ && set_after_then;
00551 }
00552
00553
00554
00555
00556 void Processor::VisitLoopStatement(LoopStatement* node) {
00557
00558 bool set_after_loop = is_set_;
00559 Visit(node->body());
00560 is_set_ = is_set_ && set_after_loop;
00561 }
00562
00563
00564 void Processor::VisitForInStatement(ForInStatement* node) {
00565
00566 bool set_after_for = is_set_;
00567 Visit(node->body());
00568 is_set_ = is_set_ && set_after_for;
00569 }
00570
00571
00572 void Processor::VisitTryCatch(TryCatch* node) {
00573
00574 bool set_after_catch = is_set_;
00575 Visit(node->catch_block());
00576 is_set_ = is_set_ && set_after_catch;
00577 bool save = in_try_;
00578 in_try_ = true;
00579 Visit(node->try_block());
00580 in_try_ = save;
00581 }
00582
00583
00584 void Processor::VisitTryFinally(TryFinally* node) {
00585
00586 Visit(node->finally_block());
00587 bool save = in_try_;
00588 in_try_ = true;
00589 Visit(node->try_block());
00590 in_try_ = save;
00591 }
00592
00593
00594 void Processor::VisitSwitchStatement(SwitchStatement* node) {
00595
00596 ZoneList<CaseClause*>* clauses = node->cases();
00597 bool set_after_switch = is_set_;
00598 for (int i = clauses->length() - 1; i >= 0; --i) {
00599 CaseClause* clause = clauses->at(i);
00600 Process(clause->statements());
00601 }
00602 is_set_ = is_set_ && set_after_switch;
00603 }
00604
00605
00606 void Processor::VisitContinueStatement(ContinueStatement* node) {
00607 is_set_ = false;
00608 }
00609
00610
00611 void Processor::VisitBreakStatement(BreakStatement* node) {
00612 is_set_ = false;
00613 }
00614
00615
00616
00617 void Processor::VisitDeclaration(Declaration* node) {}
00618 void Processor::VisitEmptyStatement(EmptyStatement* node) {}
00619 void Processor::VisitReturnStatement(ReturnStatement* node) {}
00620 void Processor::VisitWithEnterStatement(WithEnterStatement* node) {}
00621 void Processor::VisitWithExitStatement(WithExitStatement* node) {}
00622 void Processor::VisitDebuggerStatement(DebuggerStatement* node) {}
00623
00624
00625
00626 void Processor::VisitFunctionLiteral(FunctionLiteral* node) {
00627 USE(node);
00628 UNREACHABLE();
00629 }
00630
00631
00632 void Processor::VisitFunctionBoilerplateLiteral(
00633 FunctionBoilerplateLiteral* node) {
00634 USE(node);
00635 UNREACHABLE();
00636 }
00637
00638
00639 void Processor::VisitConditional(Conditional* node) {
00640 USE(node);
00641 UNREACHABLE();
00642 }
00643
00644
00645 void Processor::VisitSlot(Slot* node) {
00646 USE(node);
00647 UNREACHABLE();
00648 }
00649
00650
00651 void Processor::VisitVariableProxy(VariableProxy* node) {
00652 USE(node);
00653 UNREACHABLE();
00654 }
00655
00656
00657 void Processor::VisitLiteral(Literal* node) {
00658 USE(node);
00659 UNREACHABLE();
00660 }
00661
00662
00663 void Processor::VisitRegExpLiteral(RegExpLiteral* node) {
00664 USE(node);
00665 UNREACHABLE();
00666 }
00667
00668
00669 void Processor::VisitArrayLiteral(ArrayLiteral* node) {
00670 USE(node);
00671 UNREACHABLE();
00672 }
00673
00674
00675 void Processor::VisitObjectLiteral(ObjectLiteral* node) {
00676 USE(node);
00677 UNREACHABLE();
00678 }
00679
00680
00681 void Processor::VisitAssignment(Assignment* node) {
00682 USE(node);
00683 UNREACHABLE();
00684 }
00685
00686
00687 void Processor::VisitThrow(Throw* node) {
00688 USE(node);
00689 UNREACHABLE();
00690 }
00691
00692
00693 void Processor::VisitProperty(Property* node) {
00694 USE(node);
00695 UNREACHABLE();
00696 }
00697
00698
00699 void Processor::VisitCall(Call* node) {
00700 USE(node);
00701 UNREACHABLE();
00702 }
00703
00704
00705 void Processor::VisitCallNew(CallNew* node) {
00706 USE(node);
00707 UNREACHABLE();
00708 }
00709
00710
00711 void Processor::VisitCallRuntime(CallRuntime* node) {
00712 USE(node);
00713 UNREACHABLE();
00714 }
00715
00716
00717 void Processor::VisitUnaryOperation(UnaryOperation* node) {
00718 USE(node);
00719 UNREACHABLE();
00720 }
00721
00722
00723 void Processor::VisitCountOperation(CountOperation* node) {
00724 USE(node);
00725 UNREACHABLE();
00726 }
00727
00728
00729 void Processor::VisitBinaryOperation(BinaryOperation* node) {
00730 USE(node);
00731 UNREACHABLE();
00732 }
00733
00734
00735 void Processor::VisitCompareOperation(CompareOperation* node) {
00736 USE(node);
00737 UNREACHABLE();
00738 }
00739
00740
00741 void Processor::VisitThisFunction(ThisFunction* node) {
00742 USE(node);
00743 UNREACHABLE();
00744 }
00745
00746
00747 bool Rewriter::Process(FunctionLiteral* function) {
00748 Scope* scope = function->scope();
00749 if (scope->is_function_scope()) return true;
00750
00751 ZoneList<Statement*>* body = function->body();
00752 if (body->is_empty()) return true;
00753
00754 VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
00755 Processor processor(result);
00756 processor.Process(body);
00757 if (processor.HasStackOverflow()) return false;
00758
00759 if (processor.result_assigned()) body->Add(new ReturnStatement(result));
00760 return true;
00761 }
00762
00763
00764 void Rewriter::Optimize(FunctionLiteral* function) {
00765 ZoneList<Statement*>* body = function->body();
00766 if (body->is_empty()) return;
00767
00768 if (FLAG_optimize_ast) {
00769 Scope* scope = function->scope();
00770 if (!scope->is_global_scope()) {
00771 AstOptimizer optimizer;
00772 optimizer.Optimize(body);
00773 }
00774 }
00775 }
00776
00777
00778 } }