| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 164 |
| 165 int FunctionLiteral::end_position() const { | 165 int FunctionLiteral::end_position() const { |
| 166 return scope()->end_position(); | 166 return scope()->end_position(); |
| 167 } | 167 } |
| 168 | 168 |
| 169 | 169 |
| 170 StrictModeFlag FunctionLiteral::strict_mode_flag() const { | 170 StrictModeFlag FunctionLiteral::strict_mode_flag() const { |
| 171 return scope()->strict_mode_flag(); | 171 return scope()->strict_mode_flag(); |
| 172 } | 172 } |
| 173 | 173 |
| 174 void FunctionLiteral::ComputeAstNodeCountAndInlineableFlags() { |
| 175 is_function_inlineable_ = false; |
| 176 is_function_primitive_ = true; |
| 177 // All declarations must be inlineable. |
| 178 ZoneList<Declaration*>* decls = scope()->declarations(); |
| 179 int decl_count = decls->length(); |
| 180 for (int i = 0; i < decl_count; ++i) { |
| 181 if (!decls->at(i)->IsInlineable(this)) { |
| 182 is_function_primitive_ = false; |
| 183 return; |
| 184 } |
| 185 } |
| 186 // All statements in the body must be inlineable. |
| 187 for (int i = 0, count = body()->length(); i < count; ++i) { |
| 188 if (!body()->at(i)->IsInlineable(this)) { |
| 189 is_function_primitive_ = false; |
| 190 return; |
| 191 } |
| 192 } |
| 193 is_function_inlineable_ = true; |
| 194 } |
| 195 |
| 174 | 196 |
| 175 ObjectLiteral::Property::Property(Literal* key, Expression* value) { | 197 ObjectLiteral::Property::Property(Literal* key, Expression* value) { |
| 176 emit_store_ = true; | 198 emit_store_ = true; |
| 177 key_ = key; | 199 key_ = key; |
| 178 value_ = value; | 200 value_ = value; |
| 179 Object* k = *key->handle(); | 201 Object* k = *key->handle(); |
| 180 if (k->IsSymbol() && HEAP->Proto_symbol()->Equals(String::cast(k))) { | 202 if (k->IsSymbol() && HEAP->Proto_symbol()->Equals(String::cast(k))) { |
| 181 kind_ = PROTOTYPE; | 203 kind_ = PROTOTYPE; |
| 182 } else if (value_->AsMaterializedLiteral() != NULL) { | 204 } else if (value_->AsMaterializedLiteral() != NULL) { |
| 183 kind_ = MATERIALIZED_LITERAL; | 205 kind_ = MATERIALIZED_LITERAL; |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 | 434 |
| 413 bool CompareOperation::IsLiteralCompareNull(Expression** expr) { | 435 bool CompareOperation::IsLiteralCompareNull(Expression** expr) { |
| 414 return MatchLiteralCompareNull(left_, op_, right_, expr) || | 436 return MatchLiteralCompareNull(left_, op_, right_, expr) || |
| 415 MatchLiteralCompareNull(right_, op_, left_, expr); | 437 MatchLiteralCompareNull(right_, op_, left_, expr); |
| 416 } | 438 } |
| 417 | 439 |
| 418 | 440 |
| 419 // ---------------------------------------------------------------------------- | 441 // ---------------------------------------------------------------------------- |
| 420 // Inlining support | 442 // Inlining support |
| 421 | 443 |
| 422 bool Declaration::IsInlineable() const { | 444 bool Declaration::IsInlineable(FunctionLiteral* function) const { |
| 423 return proxy()->var()->IsStackAllocated() && fun() == NULL; | 445 function->increment_ast_node_count(); |
| 424 } | 446 return (proxy()->var()->IsStackAllocated() && fun() == NULL); |
| 425 | 447 } |
| 426 | 448 |
| 427 bool TargetCollector::IsInlineable() const { | 449 |
| 450 bool TargetCollector::IsInlineable(FunctionLiteral* function) const { |
| 428 UNREACHABLE(); | 451 UNREACHABLE(); |
| 429 return false; | 452 return false; |
| 430 } | 453 } |
| 431 | 454 |
| 432 | 455 |
| 433 bool ForInStatement::IsInlineable() const { | 456 bool ForInStatement::IsInlineable(FunctionLiteral* function) const { |
| 434 return false; | 457 return false; |
| 435 } | 458 } |
| 436 | 459 |
| 437 | 460 |
| 438 bool WithStatement::IsInlineable() const { | 461 bool WithStatement::IsInlineable(FunctionLiteral* function) const { |
| 439 return false; | 462 return false; |
| 440 } | 463 } |
| 441 | 464 |
| 442 | 465 |
| 443 bool SwitchStatement::IsInlineable() const { | 466 bool SwitchStatement::IsInlineable(FunctionLiteral* function) const { |
| 444 return false; | 467 return false; |
| 445 } | 468 } |
| 446 | 469 |
| 447 | 470 |
| 448 bool TryStatement::IsInlineable() const { | 471 bool TryStatement::IsInlineable(FunctionLiteral* function) const { |
| 449 return false; | 472 return false; |
| 450 } | 473 } |
| 451 | 474 |
| 452 | 475 |
| 453 bool TryCatchStatement::IsInlineable() const { | 476 bool TryCatchStatement::IsInlineable(FunctionLiteral* function) const { |
| 454 return false; | 477 return false; |
| 455 } | 478 } |
| 456 | 479 |
| 457 | 480 |
| 458 bool TryFinallyStatement::IsInlineable() const { | 481 bool TryFinallyStatement::IsInlineable(FunctionLiteral* function) const { |
| 459 return false; | 482 return false; |
| 460 } | 483 } |
| 461 | 484 |
| 462 | 485 |
| 463 bool DebuggerStatement::IsInlineable() const { | 486 bool DebuggerStatement::IsInlineable(FunctionLiteral* function) const { |
| 464 return false; | 487 return false; |
| 465 } | 488 } |
| 466 | 489 |
| 467 | 490 |
| 468 bool Throw::IsInlineable() const { | 491 bool Throw::IsInlineable(FunctionLiteral* function) const { |
| 469 return exception()->IsInlineable(); | 492 function->increment_ast_node_count(); |
| 470 } | 493 return exception()->IsInlineable(function); |
| 471 | 494 } |
| 472 | 495 |
| 473 bool MaterializedLiteral::IsInlineable() const { | 496 |
| 497 bool MaterializedLiteral::IsInlineable(FunctionLiteral* function) const { |
| 474 // TODO(1322): Allow materialized literals. | 498 // TODO(1322): Allow materialized literals. |
| 475 return false; | 499 return false; |
| 476 } | 500 } |
| 477 | 501 |
| 478 | 502 |
| 479 bool FunctionLiteral::IsInlineable() const { | 503 bool FunctionLiteral::IsInlineable(FunctionLiteral* function) const { |
| 480 // TODO(1322): Allow materialized literals. | 504 // TODO(1322): Allow materialized literals. |
| 481 return false; | 505 return false; |
| 482 } | 506 } |
| 483 | 507 |
| 484 | 508 |
| 485 bool ThisFunction::IsInlineable() const { | 509 bool ThisFunction::IsInlineable(FunctionLiteral* function) const { |
| 486 return true; | 510 function->increment_ast_node_count(); |
| 487 } | 511 return true; |
| 488 | 512 } |
| 489 | 513 |
| 490 bool SharedFunctionInfoLiteral::IsInlineable() const { | 514 |
| 491 return false; | 515 bool SharedFunctionInfoLiteral::IsInlineable(FunctionLiteral* function) const { |
| 492 } | 516 return false; |
| 493 | 517 } |
| 494 | 518 |
| 495 bool ForStatement::IsInlineable() const { | 519 |
| 496 return (init() == NULL || init()->IsInlineable()) | 520 bool ForStatement::IsInlineable(FunctionLiteral* function) const { |
| 497 && (cond() == NULL || cond()->IsInlineable()) | 521 function->mark_as_not_primitive(); |
| 498 && (next() == NULL || next()->IsInlineable()) | 522 function->increment_ast_node_count(); |
| 499 && body()->IsInlineable(); | 523 return (init() == NULL || init()->IsInlineable(function)) |
| 500 } | 524 && (cond() == NULL || cond()->IsInlineable(function)) |
| 501 | 525 && (next() == NULL || next()->IsInlineable(function)) |
| 502 | 526 && body()->IsInlineable(function); |
| 503 bool WhileStatement::IsInlineable() const { | 527 } |
| 504 return cond()->IsInlineable() | 528 |
| 505 && body()->IsInlineable(); | 529 |
| 506 } | 530 bool WhileStatement::IsInlineable(FunctionLiteral* function) const { |
| 507 | 531 function->mark_as_not_primitive(); |
| 508 | 532 function->increment_ast_node_count(); |
| 509 bool DoWhileStatement::IsInlineable() const { | 533 return cond()->IsInlineable(function) |
| 510 return cond()->IsInlineable() | 534 && body()->IsInlineable(function); |
| 511 && body()->IsInlineable(); | 535 } |
| 512 } | 536 |
| 513 | 537 |
| 514 | 538 bool DoWhileStatement::IsInlineable(FunctionLiteral* function) const { |
| 515 bool ContinueStatement::IsInlineable() const { | 539 function->mark_as_not_primitive(); |
| 516 return true; | 540 function->increment_ast_node_count(); |
| 517 } | 541 return cond()->IsInlineable(function) |
| 518 | 542 && body()->IsInlineable(function); |
| 519 | 543 } |
| 520 bool BreakStatement::IsInlineable() const { | 544 |
| 521 return true; | 545 |
| 522 } | 546 bool ContinueStatement::IsInlineable(FunctionLiteral* function) const { |
| 523 | 547 function->increment_ast_node_count(); |
| 524 | 548 return true; |
| 525 bool EmptyStatement::IsInlineable() const { | 549 } |
| 526 return true; | 550 |
| 527 } | 551 |
| 528 | 552 bool BreakStatement::IsInlineable(FunctionLiteral* function) const { |
| 529 | 553 function->increment_ast_node_count(); |
| 530 bool Literal::IsInlineable() const { | 554 return true; |
| 531 return true; | 555 } |
| 532 } | 556 |
| 533 | 557 |
| 534 | 558 bool EmptyStatement::IsInlineable(FunctionLiteral* function) const { |
| 535 bool Block::IsInlineable() const { | 559 function->increment_ast_node_count(); |
| 560 return true; |
| 561 } |
| 562 |
| 563 |
| 564 bool Literal::IsInlineable(FunctionLiteral* function) const { |
| 565 function->increment_ast_node_count(); |
| 566 return true; |
| 567 } |
| 568 |
| 569 |
| 570 bool Block::IsInlineable(FunctionLiteral* function) const { |
| 571 function->increment_ast_node_count(); |
| 536 const int count = statements_.length(); | 572 const int count = statements_.length(); |
| 537 for (int i = 0; i < count; ++i) { | 573 for (int i = 0; i < count; ++i) { |
| 538 if (!statements_[i]->IsInlineable()) return false; | 574 if (!statements_[i]->IsInlineable(function)) return false; |
| 539 } | 575 } |
| 540 return true; | 576 return true; |
| 541 } | 577 } |
| 542 | 578 |
| 543 | 579 |
| 544 bool ExpressionStatement::IsInlineable() const { | 580 bool ExpressionStatement::IsInlineable(FunctionLiteral* function) const { |
| 545 return expression()->IsInlineable(); | 581 function->increment_ast_node_count(); |
| 546 } | 582 return expression()->IsInlineable(function); |
| 547 | 583 } |
| 548 | 584 |
| 549 bool IfStatement::IsInlineable() const { | 585 |
| 550 return condition()->IsInlineable() | 586 bool IfStatement::IsInlineable(FunctionLiteral* function) const { |
| 551 && then_statement()->IsInlineable() | 587 function->increment_ast_node_count(); |
| 552 && else_statement()->IsInlineable(); | 588 return condition()->IsInlineable(function) |
| 553 } | 589 && then_statement()->IsInlineable(function) |
| 554 | 590 && else_statement()->IsInlineable(function); |
| 555 | 591 } |
| 556 bool ReturnStatement::IsInlineable() const { | 592 |
| 557 return expression()->IsInlineable(); | 593 |
| 558 } | 594 bool ReturnStatement::IsInlineable(FunctionLiteral* function) const { |
| 559 | 595 function->increment_ast_node_count(); |
| 560 | 596 return expression()->IsInlineable(function); |
| 561 bool Conditional::IsInlineable() const { | 597 } |
| 562 return condition()->IsInlineable() && then_expression()->IsInlineable() && | 598 |
| 563 else_expression()->IsInlineable(); | 599 |
| 564 } | 600 bool Conditional::IsInlineable(FunctionLiteral* function) const { |
| 565 | 601 function->increment_ast_node_count(); |
| 566 | 602 return condition()->IsInlineable(function) |
| 567 bool VariableProxy::IsInlineable() const { | 603 && then_expression()->IsInlineable(function) |
| 604 && else_expression()->IsInlineable(function); |
| 605 } |
| 606 |
| 607 |
| 608 bool VariableProxy::IsInlineable(FunctionLiteral* function) const { |
| 609 function->increment_ast_node_count(); |
| 568 return var()->IsUnallocated() | 610 return var()->IsUnallocated() |
| 569 || var()->IsStackAllocated() | 611 || var()->IsStackAllocated() |
| 570 || var()->IsContextSlot(); | 612 || var()->IsContextSlot(); |
| 571 } | 613 } |
| 572 | 614 |
| 573 | 615 |
| 574 bool Assignment::IsInlineable() const { | 616 bool Assignment::IsInlineable(FunctionLiteral* function) const { |
| 575 return target()->IsInlineable() && value()->IsInlineable(); | 617 function->increment_ast_node_count(); |
| 576 } | 618 return target()->IsInlineable(function) |
| 577 | 619 && value()->IsInlineable(function); |
| 578 | 620 } |
| 579 bool Property::IsInlineable() const { | 621 |
| 580 return obj()->IsInlineable() && key()->IsInlineable(); | 622 |
| 581 } | 623 bool Property::IsInlineable(FunctionLiteral* function) const { |
| 582 | 624 function->increment_ast_node_count(); |
| 583 | 625 return obj()->IsInlineable(function) |
| 584 bool Call::IsInlineable() const { | 626 && key()->IsInlineable(function); |
| 585 if (!expression()->IsInlineable()) return false; | 627 } |
| 628 |
| 629 |
| 630 bool Call::IsInlineable(FunctionLiteral* function) const { |
| 631 function->increment_ast_node_count(); |
| 632 function->mark_as_not_primitive(); |
| 633 if (!expression()->IsInlineable(function)) return false; |
| 586 const int count = arguments()->length(); | 634 const int count = arguments()->length(); |
| 587 for (int i = 0; i < count; ++i) { | 635 for (int i = 0; i < count; ++i) { |
| 588 if (!arguments()->at(i)->IsInlineable()) return false; | 636 if (!arguments()->at(i)->IsInlineable(function)) { |
| 637 return false; |
| 638 } |
| 589 } | 639 } |
| 590 return true; | 640 return true; |
| 591 } | 641 } |
| 592 | 642 |
| 593 | 643 |
| 594 bool CallNew::IsInlineable() const { | 644 bool CallNew::IsInlineable(FunctionLiteral* function) const { |
| 595 if (!expression()->IsInlineable()) return false; | 645 function->increment_ast_node_count(); |
| 646 function->mark_as_not_primitive(); |
| 647 if (!expression()->IsInlineable(function)) return false; |
| 596 const int count = arguments()->length(); | 648 const int count = arguments()->length(); |
| 597 for (int i = 0; i < count; ++i) { | 649 for (int i = 0; i < count; ++i) { |
| 598 if (!arguments()->at(i)->IsInlineable()) return false; | 650 if (!arguments()->at(i)->IsInlineable(function)) { |
| 651 return false; |
| 652 } |
| 599 } | 653 } |
| 600 return true; | 654 return true; |
| 601 } | 655 } |
| 602 | 656 |
| 603 | 657 |
| 604 bool CallRuntime::IsInlineable() const { | 658 bool CallRuntime::IsInlineable(FunctionLiteral* function_literal) const { |
| 605 // Don't try to inline JS runtime calls because we don't (currently) even | 659 // Don't try to inline JS runtime calls because we don't (currently) even |
| 606 // optimize them. | 660 // optimize them. |
| 607 if (is_jsruntime()) return false; | 661 if (is_jsruntime()) return false; |
| 608 // Don't inline the %_ArgumentsLength or %_Arguments because their | 662 // Don't inline the %_ArgumentsLength or %_Arguments because their |
| 609 // implementation will not work. There is no stack frame to get them | 663 // implementation will not work. There is no stack frame to get them |
| 610 // from. | 664 // from. |
| 611 if (function()->intrinsic_type == Runtime::INLINE && | 665 if (function()->intrinsic_type == Runtime::INLINE && |
| 612 (name()->IsEqualTo(CStrVector("_ArgumentsLength")) || | 666 (name()->IsEqualTo(CStrVector("_ArgumentsLength")) || |
| 613 name()->IsEqualTo(CStrVector("_Arguments")))) { | 667 name()->IsEqualTo(CStrVector("_Arguments")))) { |
| 614 return false; | 668 return false; |
| 615 } | 669 } |
| 670 function_literal->increment_ast_node_count(); |
| 671 function_literal->mark_as_not_primitive(); |
| 616 const int count = arguments()->length(); | 672 const int count = arguments()->length(); |
| 617 for (int i = 0; i < count; ++i) { | 673 for (int i = 0; i < count; ++i) { |
| 618 if (!arguments()->at(i)->IsInlineable()) return false; | 674 if (!arguments()->at(i)->IsInlineable(function_literal)) { |
| 675 return false; |
| 676 } |
| 619 } | 677 } |
| 620 return true; | 678 return true; |
| 621 } | 679 } |
| 622 | 680 |
| 623 | 681 |
| 624 bool UnaryOperation::IsInlineable() const { | 682 bool UnaryOperation::IsInlineable(FunctionLiteral* function) const { |
| 625 return expression()->IsInlineable(); | 683 function->increment_ast_node_count(); |
| 684 return expression()->IsInlineable(function); |
| 626 } | 685 } |
| 627 | 686 |
| 628 | 687 |
| 629 bool BinaryOperation::IsInlineable() const { | 688 bool BinaryOperation::IsInlineable(FunctionLiteral* function) const { |
| 630 return left()->IsInlineable() && right()->IsInlineable(); | 689 function->increment_ast_node_count(); |
| 690 return left()->IsInlineable(function) |
| 691 && right()->IsInlineable(function); |
| 631 } | 692 } |
| 632 | 693 |
| 633 | 694 |
| 634 bool CompareOperation::IsInlineable() const { | 695 bool CompareOperation::IsInlineable(FunctionLiteral* function) const { |
| 635 return left()->IsInlineable() && right()->IsInlineable(); | 696 function->increment_ast_node_count(); |
| 697 return left()->IsInlineable(function) |
| 698 && right()->IsInlineable(function); |
| 636 } | 699 } |
| 637 | 700 |
| 638 | 701 |
| 639 bool CountOperation::IsInlineable() const { | 702 bool CountOperation::IsInlineable(FunctionLiteral* function) const { |
| 640 return expression()->IsInlineable(); | 703 function->increment_ast_node_count(); |
| 704 return expression()->IsInlineable(function); |
| 641 } | 705 } |
| 642 | 706 |
| 643 | 707 |
| 644 // ---------------------------------------------------------------------------- | 708 // ---------------------------------------------------------------------------- |
| 645 // Recording of type feedback | 709 // Recording of type feedback |
| 646 | 710 |
| 647 void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | 711 void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { |
| 648 // Record type feedback from the oracle in the AST. | 712 // Record type feedback from the oracle in the AST. |
| 649 is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this); | 713 is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this); |
| 650 receiver_types_.Clear(); | 714 receiver_types_.Clear(); |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1208 int pos) | 1272 int pos) |
| 1209 : label_(label), | 1273 : label_(label), |
| 1210 statements_(statements), | 1274 statements_(statements), |
| 1211 position_(pos), | 1275 position_(pos), |
| 1212 compare_type_(NONE), | 1276 compare_type_(NONE), |
| 1213 compare_id_(AstNode::GetNextId(isolate)), | 1277 compare_id_(AstNode::GetNextId(isolate)), |
| 1214 entry_id_(AstNode::GetNextId(isolate)) { | 1278 entry_id_(AstNode::GetNextId(isolate)) { |
| 1215 } | 1279 } |
| 1216 | 1280 |
| 1217 } } // namespace v8::internal | 1281 } } // namespace v8::internal |
| OLD | NEW |