OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/crankshaft/typing.h" | 5 #include "src/crankshaft/typing.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/frames.h" | 8 #include "src/frames.h" |
9 #include "src/frames-inl.h" | 9 #include "src/frames-inl.h" |
10 #include "src/ostreams.h" | 10 #include "src/ostreams.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 var->name()->Print(os); | 38 var->name()->Print(os); |
39 os << " : " << Brief(value) << " -> "; | 39 os << " : " << Brief(value) << " -> "; |
40 type->PrintTo(os); | 40 type->PrintTo(os); |
41 os << std::endl; | 41 os << std::endl; |
42 } | 42 } |
43 #endif // OBJECT_PRINT | 43 #endif // OBJECT_PRINT |
44 | 44 |
45 | 45 |
46 Effect AstTyper::ObservedOnStack(Object* value) { | 46 Effect AstTyper::ObservedOnStack(Object* value) { |
47 Type* lower = Type::NowOf(value, zone()); | 47 Type* lower = Type::NowOf(value, zone()); |
48 return Effect(Bounds(lower, Type::Any(zone()))); | 48 return Effect(Bounds(lower, Type::Any())); |
49 } | 49 } |
50 | 50 |
51 | 51 |
52 void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) { | 52 void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) { |
53 if (stmt->OsrEntryId() != osr_ast_id_) return; | 53 if (stmt->OsrEntryId() != osr_ast_id_) return; |
54 | 54 |
55 DisallowHeapAllocation no_gc; | 55 DisallowHeapAllocation no_gc; |
56 JavaScriptFrameIterator it(isolate_); | 56 JavaScriptFrameIterator it(isolate_); |
57 JavaScriptFrame* frame = it.frame(); | 57 JavaScriptFrame* frame = it.frame(); |
58 | 58 |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 | 386 |
387 | 387 |
388 void AstTyper::VisitLiteral(Literal* expr) { | 388 void AstTyper::VisitLiteral(Literal* expr) { |
389 Type* type = Type::Constant(expr->value(), zone()); | 389 Type* type = Type::Constant(expr->value(), zone()); |
390 NarrowType(expr, Bounds(type)); | 390 NarrowType(expr, Bounds(type)); |
391 } | 391 } |
392 | 392 |
393 | 393 |
394 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) { | 394 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) { |
395 // TODO(rossberg): Reintroduce RegExp type. | 395 // TODO(rossberg): Reintroduce RegExp type. |
396 NarrowType(expr, Bounds(Type::Object(zone()))); | 396 NarrowType(expr, Bounds(Type::Object())); |
397 } | 397 } |
398 | 398 |
399 | 399 |
400 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) { | 400 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) { |
401 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); | 401 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); |
402 for (int i = 0; i < properties->length(); ++i) { | 402 for (int i = 0; i < properties->length(); ++i) { |
403 ObjectLiteral::Property* prop = properties->at(i); | 403 ObjectLiteral::Property* prop = properties->at(i); |
404 | 404 |
405 // Collect type feedback. | 405 // Collect type feedback. |
406 if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL && | 406 if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL && |
407 !CompileTimeValue::IsCompileTimeValue(prop->value())) || | 407 !CompileTimeValue::IsCompileTimeValue(prop->value())) || |
408 prop->kind() == ObjectLiteral::Property::COMPUTED) { | 408 prop->kind() == ObjectLiteral::Property::COMPUTED) { |
409 if (!prop->is_computed_name() && | 409 if (!prop->is_computed_name() && |
410 prop->key()->AsLiteral()->value()->IsInternalizedString() && | 410 prop->key()->AsLiteral()->value()->IsInternalizedString() && |
411 prop->emit_store()) { | 411 prop->emit_store()) { |
412 // Record type feed back for the property. | 412 // Record type feed back for the property. |
413 FeedbackVectorSlot slot = prop->GetSlot(); | 413 FeedbackVectorSlot slot = prop->GetSlot(); |
414 SmallMapList maps; | 414 SmallMapList maps; |
415 oracle()->CollectReceiverTypes(slot, &maps); | 415 oracle()->CollectReceiverTypes(slot, &maps); |
416 prop->set_receiver_type(maps.length() == 1 ? maps.at(0) | 416 prop->set_receiver_type(maps.length() == 1 ? maps.at(0) |
417 : Handle<Map>::null()); | 417 : Handle<Map>::null()); |
418 } | 418 } |
419 } | 419 } |
420 | 420 |
421 RECURSE(Visit(prop->value())); | 421 RECURSE(Visit(prop->value())); |
422 } | 422 } |
423 | 423 |
424 NarrowType(expr, Bounds(Type::Object(zone()))); | 424 NarrowType(expr, Bounds(Type::Object())); |
425 } | 425 } |
426 | 426 |
427 | 427 |
428 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) { | 428 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) { |
429 ZoneList<Expression*>* values = expr->values(); | 429 ZoneList<Expression*>* values = expr->values(); |
430 for (int i = 0; i < values->length(); ++i) { | 430 for (int i = 0; i < values->length(); ++i) { |
431 Expression* value = values->at(i); | 431 Expression* value = values->at(i); |
432 RECURSE(Visit(value)); | 432 RECURSE(Visit(value)); |
433 } | 433 } |
434 | 434 |
435 NarrowType(expr, Bounds(Type::Object(zone()))); | 435 NarrowType(expr, Bounds(Type::Object())); |
436 } | 436 } |
437 | 437 |
438 | 438 |
439 void AstTyper::VisitAssignment(Assignment* expr) { | 439 void AstTyper::VisitAssignment(Assignment* expr) { |
440 // Collect type feedback. | 440 // Collect type feedback. |
441 Property* prop = expr->target()->AsProperty(); | 441 Property* prop = expr->target()->AsProperty(); |
442 if (prop != NULL) { | 442 if (prop != NULL) { |
443 FeedbackVectorSlot slot = expr->AssignmentSlot(); | 443 FeedbackVectorSlot slot = expr->AssignmentSlot(); |
444 expr->set_is_uninitialized(oracle()->StoreIsUninitialized(slot)); | 444 expr->set_is_uninitialized(oracle()->StoreIsUninitialized(slot)); |
445 if (!expr->IsUninitialized()) { | 445 if (!expr->IsUninitialized()) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 RECURSE(Visit(expr->expression())); | 478 RECURSE(Visit(expr->expression())); |
479 | 479 |
480 // We don't know anything about the result type. | 480 // We don't know anything about the result type. |
481 } | 481 } |
482 | 482 |
483 | 483 |
484 void AstTyper::VisitThrow(Throw* expr) { | 484 void AstTyper::VisitThrow(Throw* expr) { |
485 RECURSE(Visit(expr->exception())); | 485 RECURSE(Visit(expr->exception())); |
486 // TODO(rossberg): is it worth having a non-termination effect? | 486 // TODO(rossberg): is it worth having a non-termination effect? |
487 | 487 |
488 NarrowType(expr, Bounds(Type::None(zone()))); | 488 NarrowType(expr, Bounds(Type::None())); |
489 } | 489 } |
490 | 490 |
491 | 491 |
492 void AstTyper::VisitProperty(Property* expr) { | 492 void AstTyper::VisitProperty(Property* expr) { |
493 // Collect type feedback. | 493 // Collect type feedback. |
494 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); | 494 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); |
495 expr->set_inline_cache_state(oracle()->LoadInlineCacheState(slot)); | 495 expr->set_inline_cache_state(oracle()->LoadInlineCacheState(slot)); |
496 | 496 |
497 if (!expr->IsUninitialized()) { | 497 if (!expr->IsUninitialized()) { |
498 if (expr->key()->IsPropertyName()) { | 498 if (expr->key()->IsPropertyName()) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 expr->set_target(oracle()->GetCallNewTarget(expr->CallNewFeedbackSlot())); | 562 expr->set_target(oracle()->GetCallNewTarget(expr->CallNewFeedbackSlot())); |
563 } | 563 } |
564 | 564 |
565 RECURSE(Visit(expr->expression())); | 565 RECURSE(Visit(expr->expression())); |
566 ZoneList<Expression*>* args = expr->arguments(); | 566 ZoneList<Expression*>* args = expr->arguments(); |
567 for (int i = 0; i < args->length(); ++i) { | 567 for (int i = 0; i < args->length(); ++i) { |
568 Expression* arg = args->at(i); | 568 Expression* arg = args->at(i); |
569 RECURSE(Visit(arg)); | 569 RECURSE(Visit(arg)); |
570 } | 570 } |
571 | 571 |
572 NarrowType(expr, Bounds(Type::None(zone()), Type::Receiver(zone()))); | 572 NarrowType(expr, Bounds(Type::None(), Type::Receiver())); |
573 } | 573 } |
574 | 574 |
575 | 575 |
576 void AstTyper::VisitCallRuntime(CallRuntime* expr) { | 576 void AstTyper::VisitCallRuntime(CallRuntime* expr) { |
577 ZoneList<Expression*>* args = expr->arguments(); | 577 ZoneList<Expression*>* args = expr->arguments(); |
578 for (int i = 0; i < args->length(); ++i) { | 578 for (int i = 0; i < args->length(); ++i) { |
579 Expression* arg = args->at(i); | 579 Expression* arg = args->at(i); |
580 RECURSE(Visit(arg)); | 580 RECURSE(Visit(arg)); |
581 } | 581 } |
582 | 582 |
583 // We don't know anything about the result type. | 583 // We don't know anything about the result type. |
584 } | 584 } |
585 | 585 |
586 | 586 |
587 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) { | 587 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) { |
588 // Collect type feedback. | 588 // Collect type feedback. |
589 if (expr->op() == Token::NOT) { | 589 if (expr->op() == Token::NOT) { |
590 // TODO(rossberg): only do in test or value context. | 590 // TODO(rossberg): only do in test or value context. |
591 expr->expression()->RecordToBooleanTypeFeedback(oracle()); | 591 expr->expression()->RecordToBooleanTypeFeedback(oracle()); |
592 } | 592 } |
593 | 593 |
594 RECURSE(Visit(expr->expression())); | 594 RECURSE(Visit(expr->expression())); |
595 | 595 |
596 switch (expr->op()) { | 596 switch (expr->op()) { |
597 case Token::NOT: | 597 case Token::NOT: |
598 case Token::DELETE: | 598 case Token::DELETE: |
599 NarrowType(expr, Bounds(Type::Boolean(zone()))); | 599 NarrowType(expr, Bounds(Type::Boolean())); |
600 break; | 600 break; |
601 case Token::VOID: | 601 case Token::VOID: |
602 NarrowType(expr, Bounds(Type::Undefined(zone()))); | 602 NarrowType(expr, Bounds(Type::Undefined())); |
603 break; | 603 break; |
604 case Token::TYPEOF: | 604 case Token::TYPEOF: |
605 NarrowType(expr, Bounds(Type::InternalizedString(zone()))); | 605 NarrowType(expr, Bounds(Type::InternalizedString())); |
606 break; | 606 break; |
607 default: | 607 default: |
608 UNREACHABLE(); | 608 UNREACHABLE(); |
609 } | 609 } |
610 } | 610 } |
611 | 611 |
612 | 612 |
613 void AstTyper::VisitCountOperation(CountOperation* expr) { | 613 void AstTyper::VisitCountOperation(CountOperation* expr) { |
614 // Collect type feedback. | 614 // Collect type feedback. |
615 FeedbackVectorSlot slot = expr->CountSlot(); | 615 FeedbackVectorSlot slot = expr->CountSlot(); |
616 KeyedAccessStoreMode store_mode; | 616 KeyedAccessStoreMode store_mode; |
617 IcCheckType key_type; | 617 IcCheckType key_type; |
618 oracle()->GetStoreModeAndKeyType(slot, &store_mode, &key_type); | 618 oracle()->GetStoreModeAndKeyType(slot, &store_mode, &key_type); |
619 oracle()->CountReceiverTypes(slot, expr->GetReceiverTypes()); | 619 oracle()->CountReceiverTypes(slot, expr->GetReceiverTypes()); |
620 expr->set_store_mode(store_mode); | 620 expr->set_store_mode(store_mode); |
621 expr->set_key_type(key_type); | 621 expr->set_key_type(key_type); |
622 expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId())); | 622 expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId())); |
623 // TODO(rossberg): merge the count type with the generic expression type. | 623 // TODO(rossberg): merge the count type with the generic expression type. |
624 | 624 |
625 RECURSE(Visit(expr->expression())); | 625 RECURSE(Visit(expr->expression())); |
626 | 626 |
627 NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone()))); | 627 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Number())); |
628 | 628 |
629 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 629 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
630 if (proxy != NULL && proxy->var()->IsStackAllocated()) { | 630 if (proxy != NULL && proxy->var()->IsStackAllocated()) { |
631 store_.Seq(variable_index(proxy->var()), Effect(expr->bounds())); | 631 store_.Seq(variable_index(proxy->var()), Effect(expr->bounds())); |
632 } | 632 } |
633 } | 633 } |
634 | 634 |
635 | 635 |
636 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { | 636 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { |
637 // Collect type feedback. | 637 // Collect type feedback. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 NarrowType(expr, Bounds::Either( | 672 NarrowType(expr, Bounds::Either( |
673 expr->left()->bounds(), expr->right()->bounds(), zone())); | 673 expr->left()->bounds(), expr->right()->bounds(), zone())); |
674 break; | 674 break; |
675 } | 675 } |
676 case Token::BIT_OR: | 676 case Token::BIT_OR: |
677 case Token::BIT_AND: { | 677 case Token::BIT_AND: { |
678 RECURSE(Visit(expr->left())); | 678 RECURSE(Visit(expr->left())); |
679 RECURSE(Visit(expr->right())); | 679 RECURSE(Visit(expr->right())); |
680 Type* upper = Type::Union( | 680 Type* upper = Type::Union( |
681 expr->left()->bounds().upper, expr->right()->bounds().upper, zone()); | 681 expr->left()->bounds().upper, expr->right()->bounds().upper, zone()); |
682 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); | 682 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(); |
683 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); | 683 Type* lower = Type::Intersect(Type::SignedSmall(), upper, zone()); |
684 NarrowType(expr, Bounds(lower, upper)); | 684 NarrowType(expr, Bounds(lower, upper)); |
685 break; | 685 break; |
686 } | 686 } |
687 case Token::BIT_XOR: | 687 case Token::BIT_XOR: |
688 case Token::SHL: | 688 case Token::SHL: |
689 case Token::SAR: | 689 case Token::SAR: |
690 RECURSE(Visit(expr->left())); | 690 RECURSE(Visit(expr->left())); |
691 RECURSE(Visit(expr->right())); | 691 RECURSE(Visit(expr->right())); |
692 NarrowType(expr, | 692 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Signed32())); |
693 Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()))); | |
694 break; | 693 break; |
695 case Token::SHR: | 694 case Token::SHR: |
696 RECURSE(Visit(expr->left())); | 695 RECURSE(Visit(expr->left())); |
697 RECURSE(Visit(expr->right())); | 696 RECURSE(Visit(expr->right())); |
698 // TODO(rossberg): The upper bound would be Unsigned32, but since there | 697 // TODO(rossberg): The upper bound would be Unsigned32, but since there |
699 // is no 'positive Smi' type for the lower bound, we use the smallest | 698 // is no 'positive Smi' type for the lower bound, we use the smallest |
700 // union of Smi and Unsigned32 as upper bound instead. | 699 // union of Smi and Unsigned32 as upper bound instead. |
701 NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone()))); | 700 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Number())); |
702 break; | 701 break; |
703 case Token::ADD: { | 702 case Token::ADD: { |
704 RECURSE(Visit(expr->left())); | 703 RECURSE(Visit(expr->left())); |
705 RECURSE(Visit(expr->right())); | 704 RECURSE(Visit(expr->right())); |
706 Bounds l = expr->left()->bounds(); | 705 Bounds l = expr->left()->bounds(); |
707 Bounds r = expr->right()->bounds(); | 706 Bounds r = expr->right()->bounds(); |
708 Type* lower = | 707 Type* lower = |
709 !l.lower->IsInhabited() || !r.lower->IsInhabited() ? | 708 !l.lower->IsInhabited() || !r.lower->IsInhabited() |
710 Type::None(zone()) : | 709 ? Type::None() |
711 l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ? | 710 : l.lower->Is(Type::String()) || r.lower->Is(Type::String()) |
712 Type::String(zone()) : | 711 ? Type::String() |
713 l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ? | 712 : l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) |
714 Type::SignedSmall(zone()) : Type::None(zone()); | 713 ? Type::SignedSmall() |
| 714 : Type::None(); |
715 Type* upper = | 715 Type* upper = |
716 l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ? | 716 l.upper->Is(Type::String()) || r.upper->Is(Type::String()) |
717 Type::String(zone()) : | 717 ? Type::String() |
718 l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ? | 718 : l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) |
719 Type::Number(zone()) : Type::NumberOrString(zone()); | 719 ? Type::Number() |
| 720 : Type::NumberOrString(); |
720 NarrowType(expr, Bounds(lower, upper)); | 721 NarrowType(expr, Bounds(lower, upper)); |
721 break; | 722 break; |
722 } | 723 } |
723 case Token::SUB: | 724 case Token::SUB: |
724 case Token::MUL: | 725 case Token::MUL: |
725 case Token::DIV: | 726 case Token::DIV: |
726 case Token::MOD: | 727 case Token::MOD: |
727 RECURSE(Visit(expr->left())); | 728 RECURSE(Visit(expr->left())); |
728 RECURSE(Visit(expr->right())); | 729 RECURSE(Visit(expr->right())); |
729 NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone()))); | 730 NarrowType(expr, Bounds(Type::SignedSmall(), Type::Number())); |
730 break; | 731 break; |
731 default: | 732 default: |
732 UNREACHABLE(); | 733 UNREACHABLE(); |
733 } | 734 } |
734 } | 735 } |
735 | 736 |
736 | 737 |
737 void AstTyper::VisitCompareOperation(CompareOperation* expr) { | 738 void AstTyper::VisitCompareOperation(CompareOperation* expr) { |
738 // Collect type feedback. | 739 // Collect type feedback. |
739 Type* left_type; | 740 Type* left_type; |
740 Type* right_type; | 741 Type* right_type; |
741 Type* combined_type; | 742 Type* combined_type; |
742 oracle()->CompareType(expr->CompareOperationFeedbackId(), | 743 oracle()->CompareType(expr->CompareOperationFeedbackId(), |
743 &left_type, &right_type, &combined_type); | 744 &left_type, &right_type, &combined_type); |
744 NarrowLowerType(expr->left(), left_type); | 745 NarrowLowerType(expr->left(), left_type); |
745 NarrowLowerType(expr->right(), right_type); | 746 NarrowLowerType(expr->right(), right_type); |
746 expr->set_combined_type(combined_type); | 747 expr->set_combined_type(combined_type); |
747 | 748 |
748 RECURSE(Visit(expr->left())); | 749 RECURSE(Visit(expr->left())); |
749 RECURSE(Visit(expr->right())); | 750 RECURSE(Visit(expr->right())); |
750 | 751 |
751 NarrowType(expr, Bounds(Type::Boolean(zone()))); | 752 NarrowType(expr, Bounds(Type::Boolean())); |
752 } | 753 } |
753 | 754 |
754 | 755 |
755 void AstTyper::VisitSpread(Spread* expr) { UNREACHABLE(); } | 756 void AstTyper::VisitSpread(Spread* expr) { UNREACHABLE(); } |
756 | 757 |
757 | 758 |
758 void AstTyper::VisitEmptyParentheses(EmptyParentheses* expr) { | 759 void AstTyper::VisitEmptyParentheses(EmptyParentheses* expr) { |
759 UNREACHABLE(); | 760 UNREACHABLE(); |
760 } | 761 } |
761 | 762 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 void AstTyper::VisitImportDeclaration(ImportDeclaration* declaration) { | 796 void AstTyper::VisitImportDeclaration(ImportDeclaration* declaration) { |
796 } | 797 } |
797 | 798 |
798 | 799 |
799 void AstTyper::VisitExportDeclaration(ExportDeclaration* declaration) { | 800 void AstTyper::VisitExportDeclaration(ExportDeclaration* declaration) { |
800 } | 801 } |
801 | 802 |
802 | 803 |
803 } // namespace internal | 804 } // namespace internal |
804 } // namespace v8 | 805 } // namespace v8 |
OLD | NEW |