| 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/code_descriptors.h" | 8 #include "vm/code_descriptors.h" |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flags.h" | 10 #include "vm/flags.h" |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 | 357 |
| 358 BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const { | 358 BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const { |
| 359 return CreateSuccessorFor(false_successor_addresses_); | 359 return CreateSuccessorFor(false_successor_addresses_); |
| 360 } | 360 } |
| 361 | 361 |
| 362 | 362 |
| 363 void TestGraphVisitor::ReturnValue(Value* value) { | 363 void TestGraphVisitor::ReturnValue(Value* value) { |
| 364 if (FLAG_enable_type_checks) { | 364 if (FLAG_enable_type_checks) { |
| 365 value = Bind(new AssertBooleanInstr(condition_token_pos(), value)); | 365 value = Bind(new AssertBooleanInstr(condition_token_pos(), value)); |
| 366 } | 366 } |
| 367 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 367 Value* constant_true = Bind(new ConstantInstr(Bool::True())); |
| 368 Value* constant_true = Bind(new ConstantInstr(bool_true)); | |
| 369 StrictCompareInstr* comp = | 368 StrictCompareInstr* comp = |
| 370 new StrictCompareInstr(Token::kEQ_STRICT, value, constant_true); | 369 new StrictCompareInstr(Token::kEQ_STRICT, value, constant_true); |
| 371 BranchInstr* branch = new BranchInstr(comp); | 370 BranchInstr* branch = new BranchInstr(comp); |
| 372 AddInstruction(branch); | 371 AddInstruction(branch); |
| 373 CloseFragment(); | 372 CloseFragment(); |
| 374 | 373 |
| 375 true_successor_addresses_.Add(branch->true_successor_address()); | 374 true_successor_addresses_.Add(branch->true_successor_address()); |
| 376 false_successor_addresses_.Add(branch->false_successor_address()); | 375 false_successor_addresses_.Add(branch->false_successor_address()); |
| 377 } | 376 } |
| 378 | 377 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 395 } | 394 } |
| 396 AddInstruction(branch); | 395 AddInstruction(branch); |
| 397 CloseFragment(); | 396 CloseFragment(); |
| 398 true_successor_addresses_.Add(branch->true_successor_address()); | 397 true_successor_addresses_.Add(branch->true_successor_address()); |
| 399 false_successor_addresses_.Add(branch->false_successor_address()); | 398 false_successor_addresses_.Add(branch->false_successor_address()); |
| 400 } | 399 } |
| 401 | 400 |
| 402 | 401 |
| 403 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { | 402 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { |
| 404 ASSERT(!FLAG_enable_type_checks); | 403 ASSERT(!FLAG_enable_type_checks); |
| 405 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 404 Value* constant_true = Bind(new ConstantInstr(Bool::True())); |
| 406 Value* constant_true = Bind(new ConstantInstr(bool_true)); | |
| 407 BranchInstr* branch = new BranchInstr( | 405 BranchInstr* branch = new BranchInstr( |
| 408 new StrictCompareInstr(Token::kNE_STRICT, neg->value(), constant_true)); | 406 new StrictCompareInstr(Token::kNE_STRICT, neg->value(), constant_true)); |
| 409 AddInstruction(branch); | 407 AddInstruction(branch); |
| 410 CloseFragment(); | 408 CloseFragment(); |
| 411 true_successor_addresses_.Add(branch->true_successor_address()); | 409 true_successor_addresses_.Add(branch->true_successor_address()); |
| 412 false_successor_addresses_.Add(branch->false_successor_address()); | 410 false_successor_addresses_.Add(branch->false_successor_address()); |
| 413 } | 411 } |
| 414 | 412 |
| 415 | 413 |
| 416 void TestGraphVisitor::ReturnDefinition(Definition* definition) { | 414 void TestGraphVisitor::ReturnDefinition(Definition* definition) { |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 | 692 |
| 695 // Special handling for AND/OR. | 693 // Special handling for AND/OR. |
| 696 void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { | 694 void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
| 697 // Operators "&&" and "||" cannot be overloaded therefore do not call | 695 // Operators "&&" and "||" cannot be overloaded therefore do not call |
| 698 // operator. | 696 // operator. |
| 699 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 697 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
| 700 // Implement short-circuit logic: do not evaluate right if evaluation | 698 // Implement short-circuit logic: do not evaluate right if evaluation |
| 701 // of left is sufficient. | 699 // of left is sufficient. |
| 702 // AND: left ? right === true : false; | 700 // AND: left ? right === true : false; |
| 703 // OR: left ? true : right === true; | 701 // OR: left ? true : right === true; |
| 704 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 705 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 706 | 702 |
| 707 TestGraphVisitor for_test(owner(), | 703 TestGraphVisitor for_test(owner(), |
| 708 temp_index(), | 704 temp_index(), |
| 709 loop_depth(), | 705 loop_depth(), |
| 710 node->left()->token_pos()); | 706 node->left()->token_pos()); |
| 711 node->left()->Visit(&for_test); | 707 node->left()->Visit(&for_test); |
| 712 | 708 |
| 713 ValueGraphVisitor for_right(owner(), temp_index(), loop_depth()); | 709 ValueGraphVisitor for_right(owner(), temp_index(), loop_depth()); |
| 714 node->right()->Visit(&for_right); | 710 node->right()->Visit(&for_right); |
| 715 Value* right_value = for_right.value(); | 711 Value* right_value = for_right.value(); |
| 716 if (FLAG_enable_type_checks) { | 712 if (FLAG_enable_type_checks) { |
| 717 right_value = | 713 right_value = |
| 718 for_right.Bind(new AssertBooleanInstr(node->right()->token_pos(), | 714 for_right.Bind(new AssertBooleanInstr(node->right()->token_pos(), |
| 719 right_value)); | 715 right_value)); |
| 720 } | 716 } |
| 721 Value* constant_true = for_right.Bind(new ConstantInstr(bool_true)); | 717 Value* constant_true = for_right.Bind(new ConstantInstr(Bool::True())); |
| 722 Value* compare = | 718 Value* compare = |
| 723 for_right.Bind(new StrictCompareInstr(Token::kEQ_STRICT, | 719 for_right.Bind(new StrictCompareInstr(Token::kEQ_STRICT, |
| 724 right_value, | 720 right_value, |
| 725 constant_true)); | 721 constant_true)); |
| 726 for_right.Do(BuildStoreExprTemp(compare)); | 722 for_right.Do(BuildStoreExprTemp(compare)); |
| 727 | 723 |
| 728 if (node->kind() == Token::kAND) { | 724 if (node->kind() == Token::kAND) { |
| 729 ValueGraphVisitor for_false(owner(), temp_index(), loop_depth()); | 725 ValueGraphVisitor for_false(owner(), temp_index(), loop_depth()); |
| 730 Value* constant_false = for_false.Bind(new ConstantInstr(bool_false)); | 726 Value* constant_false = for_false.Bind(new ConstantInstr(Bool::False())); |
| 731 for_false.Do(BuildStoreExprTemp(constant_false)); | 727 for_false.Do(BuildStoreExprTemp(constant_false)); |
| 732 Join(for_test, for_right, for_false); | 728 Join(for_test, for_right, for_false); |
| 733 } else { | 729 } else { |
| 734 ASSERT(node->kind() == Token::kOR); | 730 ASSERT(node->kind() == Token::kOR); |
| 735 ValueGraphVisitor for_true(owner(), temp_index(), loop_depth()); | 731 ValueGraphVisitor for_true(owner(), temp_index(), loop_depth()); |
| 736 Value* constant_true = for_true.Bind(new ConstantInstr(bool_true)); | 732 Value* constant_true = for_true.Bind(new ConstantInstr(Bool::True())); |
| 737 for_true.Do(BuildStoreExprTemp(constant_true)); | 733 for_true.Do(BuildStoreExprTemp(constant_true)); |
| 738 Join(for_test, for_true, for_right); | 734 Join(for_test, for_true, for_right); |
| 739 } | 735 } |
| 740 ReturnDefinition(BuildLoadExprTemp()); | 736 ReturnDefinition(BuildLoadExprTemp()); |
| 741 return; | 737 return; |
| 742 } | 738 } |
| 743 EffectGraphVisitor::VisitBinaryOpNode(node); | 739 EffectGraphVisitor::VisitBinaryOpNode(node); |
| 744 } | 740 } |
| 745 | 741 |
| 746 | 742 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 if (!CanSkipTypeCheck(node->token_pos(), for_value.value(), type, dst_name)) { | 858 if (!CanSkipTypeCheck(node->token_pos(), for_value.value(), type, dst_name)) { |
| 863 Append(for_value); | 859 Append(for_value); |
| 864 Do(BuildAssertAssignable( | 860 Do(BuildAssertAssignable( |
| 865 node->token_pos(), for_value.value(), type, dst_name)); | 861 node->token_pos(), for_value.value(), type, dst_name)); |
| 866 } | 862 } |
| 867 } | 863 } |
| 868 | 864 |
| 869 | 865 |
| 870 void ValueGraphVisitor::BuildTypeTest(ComparisonNode* node) { | 866 void ValueGraphVisitor::BuildTypeTest(ComparisonNode* node) { |
| 871 ASSERT(Token::IsTypeTestOperator(node->kind())); | 867 ASSERT(Token::IsTypeTestOperator(node->kind())); |
| 872 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 873 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 874 const AbstractType& type = node->right()->AsTypeNode()->type(); | 868 const AbstractType& type = node->right()->AsTypeNode()->type(); |
| 875 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 869 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 876 const bool negate_result = (node->kind() == Token::kISNOT); | 870 const bool negate_result = (node->kind() == Token::kISNOT); |
| 877 // All objects are instances of type T if Object type is a subtype of type T. | 871 // All objects are instances of type T if Object type is a subtype of type T. |
| 878 const Type& object_type = Type::Handle(Type::ObjectType()); | 872 const Type& object_type = Type::Handle(Type::ObjectType()); |
| 879 if (type.IsInstantiated() && object_type.IsSubtypeOf(type, NULL)) { | 873 if (type.IsInstantiated() && object_type.IsSubtypeOf(type, NULL)) { |
| 880 // Must evaluate left side. | 874 // Must evaluate left side. |
| 881 EffectGraphVisitor for_left_value(owner(), temp_index(), loop_depth()); | 875 EffectGraphVisitor for_left_value(owner(), temp_index(), loop_depth()); |
| 882 node->left()->Visit(&for_left_value); | 876 node->left()->Visit(&for_left_value); |
| 883 Append(for_left_value); | 877 Append(for_left_value); |
| 884 ReturnDefinition(new ConstantInstr(negate_result ? bool_false : bool_true)); | 878 ReturnDefinition(new ConstantInstr(negate_result ? |
| 879 Bool::False() : Bool::True())); |
| 885 return; | 880 return; |
| 886 } | 881 } |
| 887 | 882 |
| 888 // Eliminate the test if it can be performed successfully at compile time. | 883 // Eliminate the test if it can be performed successfully at compile time. |
| 889 if ((node->left() != NULL) && | 884 if ((node->left() != NULL) && |
| 890 node->left()->IsLiteralNode() && | 885 node->left()->IsLiteralNode() && |
| 891 type.IsInstantiated()) { | 886 type.IsInstantiated()) { |
| 892 const Instance& literal_value = node->left()->AsLiteralNode()->literal(); | 887 const Instance& literal_value = node->left()->AsLiteralNode()->literal(); |
| 893 const Class& cls = Class::Handle(literal_value.clazz()); | 888 const Class& cls = Class::Handle(literal_value.clazz()); |
| 894 ConstantInstr* result = NULL; | 889 ConstantInstr* result = NULL; |
| 895 if (cls.IsNullClass()) { | 890 if (cls.IsNullClass()) { |
| 896 // A null object is only an instance of Object and dynamic, which has | 891 // A null object is only an instance of Object and dynamic, which has |
| 897 // already been checked above (if the type is instantiated). So we can | 892 // already been checked above (if the type is instantiated). So we can |
| 898 // return false here if the instance is null (and if the type is | 893 // return false here if the instance is null (and if the type is |
| 899 // instantiated). | 894 // instantiated). |
| 900 result = new ConstantInstr(negate_result ? bool_true : bool_false); | 895 result = new ConstantInstr(negate_result ? Bool::True() : Bool::False()); |
| 901 } else { | 896 } else { |
| 902 if (literal_value.IsInstanceOf(type, TypeArguments::Handle(), NULL)) { | 897 if (literal_value.IsInstanceOf(type, TypeArguments::Handle(), NULL)) { |
| 903 result = new ConstantInstr(negate_result ? bool_false : bool_true); | 898 result = new ConstantInstr(negate_result ? |
| 899 Bool::False() : Bool::True()); |
| 904 } else { | 900 } else { |
| 905 result = new ConstantInstr(negate_result ? bool_true : bool_false); | 901 result = new ConstantInstr(negate_result ? |
| 902 Bool::True() : Bool::False()); |
| 906 } | 903 } |
| 907 } | 904 } |
| 908 ReturnDefinition(result); | 905 ReturnDefinition(result); |
| 909 return; | 906 return; |
| 910 } | 907 } |
| 911 | 908 |
| 912 ValueGraphVisitor for_left_value(owner(), temp_index(), loop_depth()); | 909 ValueGraphVisitor for_left_value(owner(), temp_index(), loop_depth()); |
| 913 node->left()->Visit(&for_left_value); | 910 node->left()->Visit(&for_left_value); |
| 914 Append(for_left_value); | 911 Append(for_left_value); |
| 915 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 912 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 926 const String& name = String::ZoneHandle(Symbols::New("_instanceOf")); | 923 const String& name = String::ZoneHandle(Symbols::New("_instanceOf")); |
| 927 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 924 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 928 new ZoneGrowableArray<PushArgumentInstr*>(5); | 925 new ZoneGrowableArray<PushArgumentInstr*>(5); |
| 929 arguments->Add(push_left); | 926 arguments->Add(push_left); |
| 930 arguments->Add(push_instantiator); | 927 arguments->Add(push_instantiator); |
| 931 arguments->Add(push_type_args); | 928 arguments->Add(push_type_args); |
| 932 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); | 929 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); |
| 933 Value* type_arg = Bind( | 930 Value* type_arg = Bind( |
| 934 new ConstantInstr(node->right()->AsTypeNode()->type())); | 931 new ConstantInstr(node->right()->AsTypeNode()->type())); |
| 935 arguments->Add(PushArgument(type_arg)); | 932 arguments->Add(PushArgument(type_arg)); |
| 936 const Bool& negate = Bool::ZoneHandle(node->kind() == Token::kISNOT ? | 933 const Bool& negate = (node->kind() == Token::kISNOT) ? Bool::True() : |
| 937 Bool::True() : Bool::False()); | 934 Bool::False(); |
| 938 Value* negate_arg = Bind(new ConstantInstr(negate)); | 935 Value* negate_arg = Bind(new ConstantInstr(negate)); |
| 939 arguments->Add(PushArgument(negate_arg)); | 936 arguments->Add(PushArgument(negate_arg)); |
| 940 const intptr_t kNumArgsChecked = 1; | 937 const intptr_t kNumArgsChecked = 1; |
| 941 InstanceCallInstr* call = new InstanceCallInstr(node->token_pos(), | 938 InstanceCallInstr* call = new InstanceCallInstr(node->token_pos(), |
| 942 name, | 939 name, |
| 943 node->kind(), | 940 node->kind(), |
| 944 arguments, | 941 arguments, |
| 945 Array::ZoneHandle(), | 942 Array::ZoneHandle(), |
| 946 kNumArgsChecked); | 943 kNumArgsChecked); |
| 947 ReturnDefinition(call); | 944 ReturnDefinition(call); |
| (...skipping 2126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3074 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 3071 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 3075 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 3072 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 3076 OS::SNPrint(chars, len, kFormat, function_name, reason); | 3073 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 3077 const Error& error = Error::Handle( | 3074 const Error& error = Error::Handle( |
| 3078 LanguageError::New(String::Handle(String::New(chars)))); | 3075 LanguageError::New(String::Handle(String::New(chars)))); |
| 3079 Isolate::Current()->long_jump_base()->Jump(1, error); | 3076 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 3080 } | 3077 } |
| 3081 | 3078 |
| 3082 | 3079 |
| 3083 } // namespace dart | 3080 } // namespace dart |
| OLD | NEW |