| 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 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 } | 286 } |
| 287 } | 287 } |
| 288 // Add key to the table. | 288 // Add key to the table. |
| 289 table->Lookup(key, hash, true); | 289 table->Lookup(key, hash, true); |
| 290 } | 290 } |
| 291 } | 291 } |
| 292 | 292 |
| 293 | 293 |
| 294 void TargetCollector::AddTarget(Label* target) { | 294 void TargetCollector::AddTarget(Label* target) { |
| 295 // Add the label to the collector, but discard duplicates. | 295 // Add the label to the collector, but discard duplicates. |
| 296 int length = targets_->length(); | 296 int length = targets_.length(); |
| 297 for (int i = 0; i < length; i++) { | 297 for (int i = 0; i < length; i++) { |
| 298 if (targets_->at(i) == target) return; | 298 if (targets_[i] == target) return; |
| 299 } | 299 } |
| 300 targets_->Add(target); | 300 targets_.Add(target); |
| 301 } | 301 } |
| 302 | 302 |
| 303 | 303 |
| 304 bool UnaryOperation::ResultOverwriteAllowed() { | 304 bool UnaryOperation::ResultOverwriteAllowed() { |
| 305 switch (op_) { | 305 switch (op_) { |
| 306 case Token::BIT_NOT: | 306 case Token::BIT_NOT: |
| 307 case Token::SUB: | 307 case Token::SUB: |
| 308 return true; | 308 return true; |
| 309 default: | 309 default: |
| 310 return false; | 310 return false; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 330 case Token::DIV: | 330 case Token::DIV: |
| 331 case Token::MOD: | 331 case Token::MOD: |
| 332 return true; | 332 return true; |
| 333 default: | 333 default: |
| 334 UNREACHABLE(); | 334 UNREACHABLE(); |
| 335 } | 335 } |
| 336 return false; | 336 return false; |
| 337 } | 337 } |
| 338 | 338 |
| 339 | 339 |
| 340 bool CompareOperation::IsLiteralCompareTypeof(Expression** expr, |
| 341 Handle<String>* check) { |
| 342 if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return false; |
| 343 |
| 344 UnaryOperation* left_unary = left_->AsUnaryOperation(); |
| 345 UnaryOperation* right_unary = right_->AsUnaryOperation(); |
| 346 Literal* left_literal = left_->AsLiteral(); |
| 347 Literal* right_literal = right_->AsLiteral(); |
| 348 |
| 349 // Check for the pattern: typeof <expression> == <string literal>. |
| 350 if (left_unary != NULL && left_unary->op() == Token::TYPEOF && |
| 351 right_literal != NULL && right_literal->handle()->IsString()) { |
| 352 *expr = left_unary->expression(); |
| 353 *check = Handle<String>::cast(right_literal->handle()); |
| 354 return true; |
| 355 } |
| 356 |
| 357 // Check for the pattern: <string literal> == typeof <expression>. |
| 358 if (right_unary != NULL && right_unary->op() == Token::TYPEOF && |
| 359 left_literal != NULL && left_literal->handle()->IsString()) { |
| 360 *expr = right_unary->expression(); |
| 361 *check = Handle<String>::cast(left_literal->handle()); |
| 362 return true; |
| 363 } |
| 364 |
| 365 return false; |
| 366 } |
| 367 |
| 368 |
| 369 bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) { |
| 370 if (op_ != Token::EQ_STRICT) return false; |
| 371 |
| 372 UnaryOperation* left_unary = left_->AsUnaryOperation(); |
| 373 UnaryOperation* right_unary = right_->AsUnaryOperation(); |
| 374 |
| 375 // Check for the pattern: <expression> === void <literal>. |
| 376 if (right_unary != NULL && right_unary->op() == Token::VOID && |
| 377 right_unary->expression()->AsLiteral() != NULL) { |
| 378 *expr = left_; |
| 379 return true; |
| 380 } |
| 381 |
| 382 // Check for the pattern: void <literal> === <expression>. |
| 383 if (left_unary != NULL && left_unary->op() == Token::VOID && |
| 384 left_unary->expression()->AsLiteral() != NULL) { |
| 385 *expr = right_; |
| 386 return true; |
| 387 } |
| 388 |
| 389 return false; |
| 390 } |
| 391 |
| 392 |
| 340 // ---------------------------------------------------------------------------- | 393 // ---------------------------------------------------------------------------- |
| 341 // Inlining support | 394 // Inlining support |
| 342 | 395 |
| 343 bool Declaration::IsInlineable() const { | 396 bool Declaration::IsInlineable() const { |
| 344 UNREACHABLE(); | 397 return proxy()->var()->IsStackAllocated() && fun() == NULL; |
| 345 return false; | |
| 346 } | 398 } |
| 347 | 399 |
| 348 | 400 |
| 349 bool TargetCollector::IsInlineable() const { | 401 bool TargetCollector::IsInlineable() const { |
| 350 UNREACHABLE(); | 402 UNREACHABLE(); |
| 351 return false; | 403 return false; |
| 352 } | 404 } |
| 353 | 405 |
| 354 | 406 |
| 355 bool Slot::IsInlineable() const { | 407 bool Slot::IsInlineable() const { |
| 356 UNREACHABLE(); | 408 UNREACHABLE(); |
| 357 return false; | 409 return false; |
| 358 } | 410 } |
| 359 | 411 |
| 360 | 412 |
| 361 bool ForInStatement::IsInlineable() const { | 413 bool ForInStatement::IsInlineable() const { |
| 362 return false; | 414 return false; |
| 363 } | 415 } |
| 364 | 416 |
| 365 | 417 |
| 366 bool WithEnterStatement::IsInlineable() const { | 418 bool EnterWithContextStatement::IsInlineable() const { |
| 367 return false; | 419 return false; |
| 368 } | 420 } |
| 369 | 421 |
| 370 | 422 |
| 371 bool WithExitStatement::IsInlineable() const { | 423 bool ExitContextStatement::IsInlineable() const { |
| 372 return false; | 424 return false; |
| 373 } | 425 } |
| 374 | 426 |
| 375 | 427 |
| 376 bool SwitchStatement::IsInlineable() const { | 428 bool SwitchStatement::IsInlineable() const { |
| 377 return false; | 429 return false; |
| 378 } | 430 } |
| 379 | 431 |
| 380 | 432 |
| 381 bool TryStatement::IsInlineable() const { | 433 bool TryStatement::IsInlineable() const { |
| 382 return false; | 434 return false; |
| 383 } | 435 } |
| 384 | 436 |
| 385 | 437 |
| 386 bool TryCatchStatement::IsInlineable() const { | 438 bool TryCatchStatement::IsInlineable() const { |
| 387 return false; | 439 return false; |
| 388 } | 440 } |
| 389 | 441 |
| 390 | 442 |
| 391 bool TryFinallyStatement::IsInlineable() const { | 443 bool TryFinallyStatement::IsInlineable() const { |
| 392 return false; | 444 return false; |
| 393 } | 445 } |
| 394 | 446 |
| 395 | 447 |
| 396 bool CatchExtensionObject::IsInlineable() const { | |
| 397 return false; | |
| 398 } | |
| 399 | |
| 400 | |
| 401 bool DebuggerStatement::IsInlineable() const { | 448 bool DebuggerStatement::IsInlineable() const { |
| 402 return false; | 449 return false; |
| 403 } | 450 } |
| 404 | 451 |
| 405 | 452 |
| 406 bool Throw::IsInlineable() const { | 453 bool Throw::IsInlineable() const { |
| 407 return exception()->IsInlineable(); | 454 return exception()->IsInlineable(); |
| 408 } | 455 } |
| 409 | 456 |
| 410 | 457 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 if (!expression()->IsInlineable()) return false; | 584 if (!expression()->IsInlineable()) return false; |
| 538 const int count = arguments()->length(); | 585 const int count = arguments()->length(); |
| 539 for (int i = 0; i < count; ++i) { | 586 for (int i = 0; i < count; ++i) { |
| 540 if (!arguments()->at(i)->IsInlineable()) return false; | 587 if (!arguments()->at(i)->IsInlineable()) return false; |
| 541 } | 588 } |
| 542 return true; | 589 return true; |
| 543 } | 590 } |
| 544 | 591 |
| 545 | 592 |
| 546 bool CallRuntime::IsInlineable() const { | 593 bool CallRuntime::IsInlineable() const { |
| 594 // Don't try to inline JS runtime calls because we don't (currently) even |
| 595 // optimize them. |
| 596 if (is_jsruntime()) return false; |
| 597 // Don't inline the %_ArgumentsLength or %_Arguments because their |
| 598 // implementation will not work. There is no stack frame to get them |
| 599 // from. |
| 600 if (function()->intrinsic_type == Runtime::INLINE && |
| 601 (name()->IsEqualTo(CStrVector("_ArgumentsLength")) || |
| 602 name()->IsEqualTo(CStrVector("_Arguments")))) { |
| 603 return false; |
| 604 } |
| 547 const int count = arguments()->length(); | 605 const int count = arguments()->length(); |
| 548 for (int i = 0; i < count; ++i) { | 606 for (int i = 0; i < count; ++i) { |
| 549 if (!arguments()->at(i)->IsInlineable()) return false; | 607 if (!arguments()->at(i)->IsInlineable()) return false; |
| 550 } | 608 } |
| 551 return true; | 609 return true; |
| 552 } | 610 } |
| 553 | 611 |
| 554 | 612 |
| 555 bool UnaryOperation::IsInlineable() const { | 613 bool UnaryOperation::IsInlineable() const { |
| 556 return expression()->IsInlineable(); | 614 return expression()->IsInlineable(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 575 bool CountOperation::IsInlineable() const { | 633 bool CountOperation::IsInlineable() const { |
| 576 return expression()->IsInlineable(); | 634 return expression()->IsInlineable(); |
| 577 } | 635 } |
| 578 | 636 |
| 579 | 637 |
| 580 // ---------------------------------------------------------------------------- | 638 // ---------------------------------------------------------------------------- |
| 581 // Recording of type feedback | 639 // Recording of type feedback |
| 582 | 640 |
| 583 void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | 641 void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { |
| 584 // Record type feedback from the oracle in the AST. | 642 // Record type feedback from the oracle in the AST. |
| 585 is_monomorphic_ = oracle->LoadIsMonomorphic(this); | 643 is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this); |
| 586 if (key()->IsPropertyName()) { | 644 if (key()->IsPropertyName()) { |
| 587 if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) { | 645 if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) { |
| 588 is_array_length_ = true; | 646 is_array_length_ = true; |
| 589 } else if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_StringLength)) { | 647 } else if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_StringLength)) { |
| 590 is_string_length_ = true; | 648 is_string_length_ = true; |
| 591 } else if (oracle->LoadIsBuiltin(this, | 649 } else if (oracle->LoadIsBuiltin(this, |
| 592 Builtins::kLoadIC_FunctionPrototype)) { | 650 Builtins::kLoadIC_FunctionPrototype)) { |
| 593 is_function_prototype_ = true; | 651 is_function_prototype_ = true; |
| 594 } else { | 652 } else { |
| 595 Literal* lit_key = key()->AsLiteral(); | 653 Literal* lit_key = key()->AsLiteral(); |
| 596 ASSERT(lit_key != NULL && lit_key->handle()->IsString()); | 654 ASSERT(lit_key != NULL && lit_key->handle()->IsString()); |
| 597 Handle<String> name = Handle<String>::cast(lit_key->handle()); | 655 Handle<String> name = Handle<String>::cast(lit_key->handle()); |
| 598 ZoneMapList* types = oracle->LoadReceiverTypes(this, name); | 656 ZoneMapList* types = oracle->LoadReceiverTypes(this, name); |
| 599 receiver_types_ = types; | 657 receiver_types_ = types; |
| 600 } | 658 } |
| 601 } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) { | 659 } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) { |
| 602 is_string_access_ = true; | 660 is_string_access_ = true; |
| 603 } else if (is_monomorphic_) { | 661 } else if (is_monomorphic_) { |
| 604 monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this); | 662 monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this); |
| 605 if (monomorphic_receiver_type_->has_external_array_elements()) { | 663 } else if (oracle->LoadIsMegamorphicWithTypeInfo(this)) { |
| 606 set_external_array_type(oracle->GetKeyedLoadExternalArrayType(this)); | 664 receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism); |
| 607 } | 665 oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_); |
| 608 } | 666 } |
| 609 } | 667 } |
| 610 | 668 |
| 611 | 669 |
| 612 void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | 670 void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle) { |
| 613 Property* prop = target()->AsProperty(); | 671 Property* prop = target()->AsProperty(); |
| 614 ASSERT(prop != NULL); | 672 ASSERT(prop != NULL); |
| 615 is_monomorphic_ = oracle->StoreIsMonomorphic(this); | 673 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this); |
| 616 if (prop->key()->IsPropertyName()) { | 674 if (prop->key()->IsPropertyName()) { |
| 617 Literal* lit_key = prop->key()->AsLiteral(); | 675 Literal* lit_key = prop->key()->AsLiteral(); |
| 618 ASSERT(lit_key != NULL && lit_key->handle()->IsString()); | 676 ASSERT(lit_key != NULL && lit_key->handle()->IsString()); |
| 619 Handle<String> name = Handle<String>::cast(lit_key->handle()); | 677 Handle<String> name = Handle<String>::cast(lit_key->handle()); |
| 620 ZoneMapList* types = oracle->StoreReceiverTypes(this, name); | 678 ZoneMapList* types = oracle->StoreReceiverTypes(this, name); |
| 621 receiver_types_ = types; | 679 receiver_types_ = types; |
| 622 } else if (is_monomorphic_) { | 680 } else if (is_monomorphic_) { |
| 623 // Record receiver type for monomorphic keyed loads. | 681 // Record receiver type for monomorphic keyed stores. |
| 624 monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this); | 682 monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this); |
| 625 if (monomorphic_receiver_type_->has_external_array_elements()) { | 683 } else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) { |
| 626 set_external_array_type(oracle->GetKeyedStoreExternalArrayType(this)); | 684 receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism); |
| 627 } | 685 oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_); |
| 628 } | 686 } |
| 629 } | 687 } |
| 630 | 688 |
| 631 | 689 |
| 632 void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | 690 void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) { |
| 633 is_monomorphic_ = oracle->StoreIsMonomorphic(this); | 691 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this); |
| 634 if (is_monomorphic_) { | 692 if (is_monomorphic_) { |
| 635 // Record receiver type for monomorphic keyed loads. | 693 // Record receiver type for monomorphic keyed stores. |
| 636 monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this); | 694 monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this); |
| 637 if (monomorphic_receiver_type_->has_external_array_elements()) { | 695 } else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) { |
| 638 set_external_array_type(oracle->GetKeyedStoreExternalArrayType(this)); | 696 receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism); |
| 639 } | 697 oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_); |
| 640 } | 698 } |
| 641 } | 699 } |
| 642 | 700 |
| 643 | 701 |
| 644 void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | 702 void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) { |
| 645 TypeInfo info = oracle->SwitchType(this); | 703 TypeInfo info = oracle->SwitchType(this); |
| 646 if (info.IsSmi()) { | 704 if (info.IsSmi()) { |
| 647 compare_type_ = SMI_ONLY; | 705 compare_type_ = SMI_ONLY; |
| 648 } else if (info.IsNonPrimitive()) { | 706 } else if (info.IsNonPrimitive()) { |
| 649 compare_type_ = OBJECT_ONLY; | 707 compare_type_ = OBJECT_ONLY; |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1137 int pos) | 1195 int pos) |
| 1138 : label_(label), | 1196 : label_(label), |
| 1139 statements_(statements), | 1197 statements_(statements), |
| 1140 position_(pos), | 1198 position_(pos), |
| 1141 compare_type_(NONE), | 1199 compare_type_(NONE), |
| 1142 compare_id_(AstNode::GetNextId()), | 1200 compare_id_(AstNode::GetNextId()), |
| 1143 entry_id_(AstNode::GetNextId()) { | 1201 entry_id_(AstNode::GetNextId()) { |
| 1144 } | 1202 } |
| 1145 | 1203 |
| 1146 } } // namespace v8::internal | 1204 } } // namespace v8::internal |
| OLD | NEW |