Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
| 6 | 6 |
| 7 #include "vm/ast_printer.h" | 7 #include "vm/ast_printer.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/code_descriptors.h" | 9 #include "vm/code_descriptors.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 304 | 304 |
| 305 // Type nodes only occur as the right-hand side of instanceof comparisons, | 305 // Type nodes only occur as the right-hand side of instanceof comparisons, |
| 306 // and they are handled specially in that context. | 306 // and they are handled specially in that context. |
| 307 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } | 307 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } |
| 308 | 308 |
| 309 | 309 |
| 310 // Returns true if the type check can be skipped, for example, if the | 310 // Returns true if the type check can be skipped, for example, if the |
| 311 // destination type is Dynamic or if the static type of the value is a subtype | 311 // destination type is Dynamic or if the static type of the value is a subtype |
| 312 // of the destination type. | 312 // of the destination type. |
| 313 static bool CanSkipTypeCheck(Value* value, const AbstractType& dst_type) { | 313 static bool CanSkipTypeCheck(Value* value, const AbstractType& dst_type) { |
| 314 ASSERT(FLAG_enable_type_checks); | |
| 315 ASSERT(!dst_type.IsNull()); | 314 ASSERT(!dst_type.IsNull()); |
| 316 ASSERT(dst_type.IsFinalized()); | 315 ASSERT(dst_type.IsFinalized()); |
| 317 if (!FLAG_eliminate_type_checks) { | 316 if (!FLAG_eliminate_type_checks) { |
| 318 return false; | 317 return false; |
| 319 } | 318 } |
| 320 | 319 |
| 321 // Any expression is assignable to the Dynamic type and to the Object type. | 320 // Any expression is assignable to the Dynamic type and to the Object type. |
| 322 // Skip the test. | 321 // Skip the test. |
| 323 if (!dst_type.IsMalformed() && | 322 if (!dst_type.IsMalformed() && |
| 324 (dst_type.IsDynamicType() || dst_type.IsObjectType())) { | 323 (dst_type.IsDynamicType() || dst_type.IsObjectType())) { |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 650 return new AssertAssignableComp(token_pos, | 649 return new AssertAssignableComp(token_pos, |
| 651 owner()->try_index(), | 650 owner()->try_index(), |
| 652 value, | 651 value, |
| 653 instantiator, | 652 instantiator, |
| 654 instantiator_type_arguments, | 653 instantiator_type_arguments, |
| 655 dst_type, | 654 dst_type, |
| 656 dst_name); | 655 dst_name); |
| 657 } | 656 } |
| 658 | 657 |
| 659 | 658 |
| 660 // Used to to test assignments. | 659 // Used for type casts and to test assignments. |
| 661 Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_pos, | 660 Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_pos, |
| 662 Value* value, | 661 Value* value, |
| 663 const AbstractType& dst_type, | 662 const AbstractType& dst_type, |
| 664 const String& dst_name) { | 663 const String& dst_name) { |
| 665 if (CanSkipTypeCheck(value, dst_type)) { | 664 if (CanSkipTypeCheck(value, dst_type)) { |
| 666 return value; | 665 return value; |
| 667 } | 666 } |
| 668 AssertAssignableComp* comp = BuildAssertAssignable(token_pos, | 667 AssertAssignableComp* comp = BuildAssertAssignable(token_pos, |
| 669 value, | 668 value, |
| 670 dst_type, | 669 dst_type, |
| 671 dst_name); | 670 dst_name); |
| 672 BindInstr* assert_assignable = new BindInstr(comp); | 671 BindInstr* assert_assignable = new BindInstr(comp); |
| 673 AddInstruction(assert_assignable); | 672 AddInstruction(assert_assignable); |
| 674 return new UseVal(assert_assignable); | 673 return new UseVal(assert_assignable); |
| 675 } | 674 } |
| 676 | 675 |
| 677 | 676 |
| 678 void EffectGraphVisitor::BuildInstanceOf(ComparisonNode* node) { | 677 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) { |
| 679 ASSERT(Token::IsInstanceofOperator(node->kind())); | 678 ASSERT(Token::IsTypeTestOperator(node->kind())); |
| 680 EffectGraphVisitor for_left_value(owner(), temp_index()); | 679 EffectGraphVisitor for_left_value(owner(), temp_index()); |
| 681 node->left()->Visit(&for_left_value); | 680 node->left()->Visit(&for_left_value); |
| 682 Append(for_left_value); | 681 Append(for_left_value); |
| 683 } | 682 } |
| 684 | 683 |
| 685 | 684 |
| 686 void ValueGraphVisitor::BuildInstanceOf(ComparisonNode* node) { | 685 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { |
| 687 ASSERT(Token::IsInstanceofOperator(node->kind())); | 686 ASSERT(Token::IsTypeCastOperator(node->kind())); |
| 687 const AbstractType& type = node->right()->AsTypeNode()->type(); | |
| 688 ASSERT(type.IsFinalized()); // The type in a type cast may be malformed. | |
| 689 ValueGraphVisitor for_value(owner(), temp_index()); | |
| 690 node->left()->Visit(&for_value); | |
| 691 Append(for_value); | |
| 692 const String& dst_name = String::ZoneHandle(String::NewSymbol("type cast")); | |
|
srdjan
2012/06/23 00:04:29
Factor out the string "type cast" used at least in
regis
2012/06/25 17:34:56
Done.
| |
| 693 if (!CanSkipTypeCheck(for_value.value(), type)) { | |
| 694 AssertAssignableComp* assert_assignable = | |
| 695 BuildAssertAssignable(node->token_pos(), | |
| 696 for_value.value(), | |
| 697 type, | |
| 698 dst_name); | |
| 699 AddInstruction(new DoInstr(assert_assignable)); | |
| 700 } | |
| 701 } | |
| 702 | |
| 703 | |
| 704 void ValueGraphVisitor::BuildTypeTest(ComparisonNode* node) { | |
| 705 ASSERT(Token::IsTypeTestOperator(node->kind())); | |
| 688 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 706 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 689 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 707 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 690 const AbstractType& type = node->right()->AsTypeNode()->type(); | 708 const AbstractType& type = node->right()->AsTypeNode()->type(); |
| 691 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 709 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 692 const bool negate_result = (node->kind() == Token::kISNOT); | 710 const bool negate_result = (node->kind() == Token::kISNOT); |
| 693 // All objects are instances of type T if Object type is a subtype of type T. | 711 // All objects are instances of type T if Object type is a subtype of type T. |
| 694 const Type& object_type = | 712 const Type& object_type = Type::Handle(Type::ObjectType()); |
| 695 Type::Handle(Isolate::Current()->object_store()->object_type()); | |
| 696 Error& malformed_error = Error::Handle(); | 713 Error& malformed_error = Error::Handle(); |
| 697 if (type.IsInstantiated() && | 714 if (type.IsInstantiated() && |
| 698 object_type.IsSubtypeOf(type, &malformed_error)) { | 715 object_type.IsSubtypeOf(type, &malformed_error)) { |
| 699 // Must evaluate left side. | 716 // Must evaluate left side. |
| 700 EffectGraphVisitor for_left_value(owner(), temp_index()); | 717 EffectGraphVisitor for_left_value(owner(), temp_index()); |
| 701 node->left()->Visit(&for_left_value); | 718 node->left()->Visit(&for_left_value); |
| 702 Append(for_left_value); | 719 Append(for_left_value); |
| 703 ReturnComputation(new ConstantVal(negate_result ? bool_false : bool_true)); | 720 ReturnComputation(new ConstantVal(negate_result ? bool_false : bool_true)); |
| 704 return; | 721 return; |
| 705 } | 722 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 750 owner()->try_index(), | 767 owner()->try_index(), |
| 751 for_left_value.value(), | 768 for_left_value.value(), |
| 752 instantiator, | 769 instantiator, |
| 753 instantiator_type_arguments, | 770 instantiator_type_arguments, |
| 754 node->right()->AsTypeNode()->type(), | 771 node->right()->AsTypeNode()->type(), |
| 755 (node->kind() == Token::kISNOT)); | 772 (node->kind() == Token::kISNOT)); |
| 756 ReturnComputation(instance_of); | 773 ReturnComputation(instance_of); |
| 757 } | 774 } |
| 758 | 775 |
| 759 | 776 |
| 777 void ValueGraphVisitor::BuildTypeCast(ComparisonNode* node) { | |
| 778 ASSERT(Token::IsTypeCastOperator(node->kind())); | |
| 779 const AbstractType& type = node->right()->AsTypeNode()->type(); | |
| 780 ASSERT(type.IsFinalized()); // The type in a type cast may be malformed. | |
| 781 ValueGraphVisitor for_value(owner(), temp_index()); | |
| 782 node->left()->Visit(&for_value); | |
| 783 Append(for_value); | |
| 784 const String& dst_name = String::ZoneHandle(String::NewSymbol("type cast")); | |
| 785 ReturnValue(BuildAssignableValue(node->token_pos(), | |
| 786 for_value.value(), | |
| 787 type, | |
| 788 dst_name)); | |
| 789 } | |
| 790 | |
| 791 | |
| 760 // <Expression> :: Comparison { kind: Token::Kind | 792 // <Expression> :: Comparison { kind: Token::Kind |
| 761 // left: <Expression> | 793 // left: <Expression> |
| 762 // right: <Expression> } | 794 // right: <Expression> } |
| 763 // TODO(srdjan): Implement new equality. | 795 // TODO(srdjan): Implement new equality. |
| 764 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { | 796 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { |
| 765 if (Token::IsInstanceofOperator(node->kind())) { | 797 if (Token::IsTypeTestOperator(node->kind())) { |
| 766 BuildInstanceOf(node); | 798 BuildTypeTest(node); |
| 799 return; | |
| 800 } else if (Token::IsTypeCastOperator(node->kind())) { | |
|
srdjan
2012/06/23 00:04:29
No else needed.
regis
2012/06/25 17:34:56
Done.
| |
| 801 BuildTypeCast(node); | |
| 767 return; | 802 return; |
| 768 } | 803 } |
| 769 if ((node->kind() == Token::kEQ_STRICT) || | 804 if ((node->kind() == Token::kEQ_STRICT) || |
| 770 (node->kind() == Token::kNE_STRICT)) { | 805 (node->kind() == Token::kNE_STRICT)) { |
| 771 ValueGraphVisitor for_left_value(owner(), temp_index()); | 806 ValueGraphVisitor for_left_value(owner(), temp_index()); |
| 772 node->left()->Visit(&for_left_value); | 807 node->left()->Visit(&for_left_value); |
| 773 Append(for_left_value); | 808 Append(for_left_value); |
| 774 ValueGraphVisitor for_right_value(owner(), temp_index()); | 809 ValueGraphVisitor for_right_value(owner(), temp_index()); |
| 775 node->right()->Visit(&for_right_value); | 810 node->right()->Visit(&for_right_value); |
| 776 Append(for_right_value); | 811 Append(for_right_value); |
| (...skipping 1952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2729 char* chars = reinterpret_cast<char*>( | 2764 char* chars = reinterpret_cast<char*>( |
| 2730 Isolate::Current()->current_zone()->Allocate(len)); | 2765 Isolate::Current()->current_zone()->Allocate(len)); |
| 2731 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2766 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2732 const Error& error = Error::Handle( | 2767 const Error& error = Error::Handle( |
| 2733 LanguageError::New(String::Handle(String::New(chars)))); | 2768 LanguageError::New(String::Handle(String::New(chars)))); |
| 2734 Isolate::Current()->long_jump_base()->Jump(1, error); | 2769 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2735 } | 2770 } |
| 2736 | 2771 |
| 2737 | 2772 |
| 2738 } // namespace dart | 2773 } // namespace dart |
| OLD | NEW |