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 "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 return CreateSuccessorFor(true_successor_addresses_); | 882 return CreateSuccessorFor(true_successor_addresses_); |
883 } | 883 } |
884 | 884 |
885 | 885 |
886 BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const { | 886 BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const { |
887 return CreateSuccessorFor(false_successor_addresses_); | 887 return CreateSuccessorFor(false_successor_addresses_); |
888 } | 888 } |
889 | 889 |
890 | 890 |
891 void TestGraphVisitor::ReturnValue(Value* value) { | 891 void TestGraphVisitor::ReturnValue(Value* value) { |
892 if (FLAG_enable_type_checks || FLAG_enable_asserts) { | 892 if (Isolate::Current()->TypeChecksEnabled() || |
| 893 Isolate::Current()->AssertsEnabled()) { |
893 value = Bind(new(I) AssertBooleanInstr(condition_token_pos(), value)); | 894 value = Bind(new(I) AssertBooleanInstr(condition_token_pos(), value)); |
894 } | 895 } |
895 Value* constant_true = Bind(new(I) ConstantInstr(Bool::True())); | 896 Value* constant_true = Bind(new(I) ConstantInstr(Bool::True())); |
896 StrictCompareInstr* comp = | 897 StrictCompareInstr* comp = |
897 new(I) StrictCompareInstr(condition_token_pos(), | 898 new(I) StrictCompareInstr(condition_token_pos(), |
898 Token::kEQ_STRICT, | 899 Token::kEQ_STRICT, |
899 value, | 900 value, |
900 constant_true, | 901 constant_true, |
901 false); // No number check. | 902 false); // No number check. |
902 BranchInstr* branch = new(I) BranchInstr(comp); | 903 BranchInstr* branch = new(I) BranchInstr(comp); |
(...skipping 14 matching lines...) Expand all Loading... |
917 (comp->left()->BindsToConstantNull() || | 918 (comp->left()->BindsToConstantNull() || |
918 comp->right()->BindsToConstantNull())) { | 919 comp->right()->BindsToConstantNull())) { |
919 branch = new(I) BranchInstr(new(I) StrictCompareInstr( | 920 branch = new(I) BranchInstr(new(I) StrictCompareInstr( |
920 comp->token_pos(), | 921 comp->token_pos(), |
921 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, | 922 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, |
922 comp->left(), | 923 comp->left(), |
923 comp->right(), | 924 comp->right(), |
924 false)); // No number check. | 925 false)); // No number check. |
925 } else { | 926 } else { |
926 branch = new(I) BranchInstr(comp); | 927 branch = new(I) BranchInstr(comp); |
927 branch->set_is_checked(FLAG_enable_type_checks); | 928 branch->set_is_checked(Isolate::Current()->TypeChecksEnabled()); |
928 } | 929 } |
929 AddInstruction(branch); | 930 AddInstruction(branch); |
930 CloseFragment(); | 931 CloseFragment(); |
931 true_successor_addresses_.Add(branch->true_successor_address()); | 932 true_successor_addresses_.Add(branch->true_successor_address()); |
932 false_successor_addresses_.Add(branch->false_successor_address()); | 933 false_successor_addresses_.Add(branch->false_successor_address()); |
933 } | 934 } |
934 | 935 |
935 | 936 |
936 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { | 937 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { |
937 ASSERT(!FLAG_enable_type_checks); | 938 ASSERT(!Isolate::Current()->TypeChecksEnabled()); |
938 Value* constant_true = Bind(new(I) ConstantInstr(Bool::True())); | 939 Value* constant_true = Bind(new(I) ConstantInstr(Bool::True())); |
939 StrictCompareInstr* comp = | 940 StrictCompareInstr* comp = |
940 new(I) StrictCompareInstr(condition_token_pos(), | 941 new(I) StrictCompareInstr(condition_token_pos(), |
941 Token::kNE_STRICT, | 942 Token::kNE_STRICT, |
942 neg->value(), | 943 neg->value(), |
943 constant_true, | 944 constant_true, |
944 false); // No number check. | 945 false); // No number check. |
945 BranchInstr* branch = new(I) BranchInstr(comp); | 946 BranchInstr* branch = new(I) BranchInstr(comp); |
946 AddInstruction(branch); | 947 AddInstruction(branch); |
947 CloseFragment(); | 948 CloseFragment(); |
948 true_successor_addresses_.Add(branch->true_successor_address()); | 949 true_successor_addresses_.Add(branch->true_successor_address()); |
949 false_successor_addresses_.Add(branch->false_successor_address()); | 950 false_successor_addresses_.Add(branch->false_successor_address()); |
950 } | 951 } |
951 | 952 |
952 | 953 |
953 void TestGraphVisitor::ReturnDefinition(Definition* definition) { | 954 void TestGraphVisitor::ReturnDefinition(Definition* definition) { |
954 ComparisonInstr* comp = definition->AsComparison(); | 955 ComparisonInstr* comp = definition->AsComparison(); |
955 if (comp != NULL) { | 956 if (comp != NULL) { |
956 MergeBranchWithComparison(comp); | 957 MergeBranchWithComparison(comp); |
957 return; | 958 return; |
958 } | 959 } |
959 if (!FLAG_enable_type_checks) { | 960 if (!Isolate::Current()->TypeChecksEnabled()) { |
960 BooleanNegateInstr* neg = definition->AsBooleanNegate(); | 961 BooleanNegateInstr* neg = definition->AsBooleanNegate(); |
961 if (neg != NULL) { | 962 if (neg != NULL) { |
962 MergeBranchWithNegate(neg); | 963 MergeBranchWithNegate(neg); |
963 return; | 964 return; |
964 } | 965 } |
965 } | 966 } |
966 ReturnValue(Bind(definition)); | 967 ReturnValue(Bind(definition)); |
967 } | 968 } |
968 | 969 |
969 | 970 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1038 // step mode. This call must happen before the contexts are | 1039 // step mode. This call must happen before the contexts are |
1039 // unchained so that captured variables can be inspected. | 1040 // unchained so that captured variables can be inspected. |
1040 // No debugger check is done in native functions or for return | 1041 // No debugger check is done in native functions or for return |
1041 // statements for which there is no associated source position. | 1042 // statements for which there is no associated source position. |
1042 const Function& function = owner()->function(); | 1043 const Function& function = owner()->function(); |
1043 if ((node->token_pos() != Scanner::kNoSourcePos) && !function.is_native()) { | 1044 if ((node->token_pos() != Scanner::kNoSourcePos) && !function.is_native()) { |
1044 AddInstruction(new(I) DebugStepCheckInstr(node->token_pos(), | 1045 AddInstruction(new(I) DebugStepCheckInstr(node->token_pos(), |
1045 RawPcDescriptors::kRuntimeCall)); | 1046 RawPcDescriptors::kRuntimeCall)); |
1046 } | 1047 } |
1047 | 1048 |
1048 if (FLAG_enable_type_checks) { | 1049 if (Isolate::Current()->TypeChecksEnabled()) { |
1049 const bool is_implicit_dynamic_getter = | 1050 const bool is_implicit_dynamic_getter = |
1050 (!function.is_static() && | 1051 (!function.is_static() && |
1051 ((function.kind() == RawFunction::kImplicitGetter) || | 1052 ((function.kind() == RawFunction::kImplicitGetter) || |
1052 (function.kind() == RawFunction::kImplicitStaticFinalGetter))); | 1053 (function.kind() == RawFunction::kImplicitStaticFinalGetter))); |
1053 // Implicit getters do not need a type check at return, unless they compute | 1054 // Implicit getters do not need a type check at return, unless they compute |
1054 // the initial value of a static field. | 1055 // the initial value of a static field. |
1055 // The body of a constructor cannot modify the type of the | 1056 // The body of a constructor cannot modify the type of the |
1056 // constructed instance, which is passed in as an implicit parameter. | 1057 // constructed instance, which is passed in as an implicit parameter. |
1057 // However, factories may create an instance of the wrong type. | 1058 // However, factories may create an instance of the wrong type. |
1058 if (!is_implicit_dynamic_getter && !function.IsConstructor()) { | 1059 if (!is_implicit_dynamic_getter && !function.IsConstructor()) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1237 // left: <Expression> | 1238 // left: <Expression> |
1238 // right: <Expression> } | 1239 // right: <Expression> } |
1239 void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { | 1240 void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
1240 // Operators "&&" and "||" cannot be overloaded therefore do not call | 1241 // Operators "&&" and "||" cannot be overloaded therefore do not call |
1241 // operator. | 1242 // operator. |
1242 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 1243 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
1243 // See ValueGraphVisitor::VisitBinaryOpNode. | 1244 // See ValueGraphVisitor::VisitBinaryOpNode. |
1244 TestGraphVisitor for_left(owner(), node->left()->token_pos()); | 1245 TestGraphVisitor for_left(owner(), node->left()->token_pos()); |
1245 node->left()->Visit(&for_left); | 1246 node->left()->Visit(&for_left); |
1246 EffectGraphVisitor empty(owner()); | 1247 EffectGraphVisitor empty(owner()); |
1247 if (FLAG_enable_type_checks || FLAG_enable_asserts) { | 1248 if (Isolate::Current()->TypeChecksEnabled() || |
| 1249 Isolate::Current()->AssertsEnabled()) { |
1248 ValueGraphVisitor for_right(owner()); | 1250 ValueGraphVisitor for_right(owner()); |
1249 node->right()->Visit(&for_right); | 1251 node->right()->Visit(&for_right); |
1250 Value* right_value = for_right.value(); | 1252 Value* right_value = for_right.value(); |
1251 for_right.Do(new(I) AssertBooleanInstr(node->right()->token_pos(), | 1253 for_right.Do(new(I) AssertBooleanInstr(node->right()->token_pos(), |
1252 right_value)); | 1254 right_value)); |
1253 if (node->kind() == Token::kAND) { | 1255 if (node->kind() == Token::kAND) { |
1254 Join(for_left, for_right, empty); | 1256 Join(for_left, for_right, empty); |
1255 } else { | 1257 } else { |
1256 Join(for_left, empty, for_right); | 1258 Join(for_left, empty, for_right); |
1257 } | 1259 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1302 // of left is sufficient. | 1304 // of left is sufficient. |
1303 // AND: left ? right === true : false; | 1305 // AND: left ? right === true : false; |
1304 // OR: left ? true : right === true; | 1306 // OR: left ? true : right === true; |
1305 | 1307 |
1306 TestGraphVisitor for_test(owner(), node->left()->token_pos()); | 1308 TestGraphVisitor for_test(owner(), node->left()->token_pos()); |
1307 node->left()->Visit(&for_test); | 1309 node->left()->Visit(&for_test); |
1308 | 1310 |
1309 ValueGraphVisitor for_right(owner()); | 1311 ValueGraphVisitor for_right(owner()); |
1310 node->right()->Visit(&for_right); | 1312 node->right()->Visit(&for_right); |
1311 Value* right_value = for_right.value(); | 1313 Value* right_value = for_right.value(); |
1312 if (FLAG_enable_type_checks|| FLAG_enable_asserts) { | 1314 if (Isolate::Current()->TypeChecksEnabled() || |
| 1315 Isolate::Current()->AssertsEnabled()) { |
1313 right_value = | 1316 right_value = |
1314 for_right.Bind(new(I) AssertBooleanInstr(node->right()->token_pos(), | 1317 for_right.Bind(new(I) AssertBooleanInstr(node->right()->token_pos(), |
1315 right_value)); | 1318 right_value)); |
1316 } | 1319 } |
1317 Value* constant_true = for_right.Bind(new(I) ConstantInstr(Bool::True())); | 1320 Value* constant_true = for_right.Bind(new(I) ConstantInstr(Bool::True())); |
1318 Value* compare = | 1321 Value* compare = |
1319 for_right.Bind(new(I) StrictCompareInstr(node->token_pos(), | 1322 for_right.Bind(new(I) StrictCompareInstr(node->token_pos(), |
1320 Token::kEQ_STRICT, | 1323 Token::kEQ_STRICT, |
1321 right_value, | 1324 right_value, |
1322 constant_true, | 1325 constant_true, |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1775 | 1778 |
1776 Definition* result = new(I) InstanceCallInstr( | 1779 Definition* result = new(I) InstanceCallInstr( |
1777 node->token_pos(), | 1780 node->token_pos(), |
1778 Symbols::EqualOperator(), | 1781 Symbols::EqualOperator(), |
1779 Token::kEQ, // Result is negated later for kNE. | 1782 Token::kEQ, // Result is negated later for kNE. |
1780 arguments, | 1783 arguments, |
1781 Object::null_array(), | 1784 Object::null_array(), |
1782 2, | 1785 2, |
1783 owner()->ic_data_array()); | 1786 owner()->ic_data_array()); |
1784 if (node->kind() == Token::kNE) { | 1787 if (node->kind() == Token::kNE) { |
1785 if (FLAG_enable_type_checks || FLAG_enable_asserts) { | 1788 if (Isolate::Current()->TypeChecksEnabled() || |
| 1789 Isolate::Current()->AssertsEnabled()) { |
1786 Value* value = Bind(result); | 1790 Value* value = Bind(result); |
1787 result = new(I) AssertBooleanInstr(node->token_pos(), value); | 1791 result = new(I) AssertBooleanInstr(node->token_pos(), value); |
1788 } | 1792 } |
1789 Value* value = Bind(result); | 1793 Value* value = Bind(result); |
1790 result = new(I) BooleanNegateInstr(value); | 1794 result = new(I) BooleanNegateInstr(value); |
1791 } | 1795 } |
1792 ReturnDefinition(result); | 1796 ReturnDefinition(result); |
1793 return; | 1797 return; |
1794 } | 1798 } |
1795 | 1799 |
(...skipping 25 matching lines...) Expand all Loading... |
1821 } | 1825 } |
1822 | 1826 |
1823 | 1827 |
1824 void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { | 1828 void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { |
1825 // "!" cannot be overloaded, therefore do not call operator. | 1829 // "!" cannot be overloaded, therefore do not call operator. |
1826 if (node->kind() == Token::kNOT) { | 1830 if (node->kind() == Token::kNOT) { |
1827 ValueGraphVisitor for_value(owner()); | 1831 ValueGraphVisitor for_value(owner()); |
1828 node->operand()->Visit(&for_value); | 1832 node->operand()->Visit(&for_value); |
1829 Append(for_value); | 1833 Append(for_value); |
1830 Value* value = for_value.value(); | 1834 Value* value = for_value.value(); |
1831 if (FLAG_enable_type_checks || FLAG_enable_asserts) { | 1835 if (Isolate::Current()->TypeChecksEnabled() || |
| 1836 Isolate::Current()->AssertsEnabled()) { |
1832 value = | 1837 value = |
1833 Bind(new(I) AssertBooleanInstr(node->operand()->token_pos(), value)); | 1838 Bind(new(I) AssertBooleanInstr(node->operand()->token_pos(), value)); |
1834 } | 1839 } |
1835 BooleanNegateInstr* negate = new(I) BooleanNegateInstr(value); | 1840 BooleanNegateInstr* negate = new(I) BooleanNegateInstr(value); |
1836 ReturnDefinition(negate); | 1841 ReturnDefinition(negate); |
1837 return; | 1842 return; |
1838 } | 1843 } |
1839 | 1844 |
1840 ValueGraphVisitor for_value(owner()); | 1845 ValueGraphVisitor for_value(owner()); |
1841 node->operand()->Visit(&for_value); | 1846 node->operand()->Visit(&for_value); |
(...skipping 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3424 node->value()->IsLoadLocalNode() || | 3429 node->value()->IsLoadLocalNode() || |
3425 node->value()->IsClosureNode()) { | 3430 node->value()->IsClosureNode()) { |
3426 AddInstruction(new(I) DebugStepCheckInstr( | 3431 AddInstruction(new(I) DebugStepCheckInstr( |
3427 node->token_pos(), RawPcDescriptors::kRuntimeCall)); | 3432 node->token_pos(), RawPcDescriptors::kRuntimeCall)); |
3428 } | 3433 } |
3429 | 3434 |
3430 ValueGraphVisitor for_value(owner()); | 3435 ValueGraphVisitor for_value(owner()); |
3431 node->value()->Visit(&for_value); | 3436 node->value()->Visit(&for_value); |
3432 Append(for_value); | 3437 Append(for_value); |
3433 Value* store_value = for_value.value(); | 3438 Value* store_value = for_value.value(); |
3434 if (FLAG_enable_type_checks) { | 3439 if (Isolate::Current()->TypeChecksEnabled()) { |
3435 store_value = BuildAssignableValue(node->value()->token_pos(), | 3440 store_value = BuildAssignableValue(node->value()->token_pos(), |
3436 store_value, | 3441 store_value, |
3437 node->local().type(), | 3442 node->local().type(), |
3438 node->local().name()); | 3443 node->local().name()); |
3439 } | 3444 } |
3440 Definition* store = BuildStoreLocal(node->local(), store_value); | 3445 Definition* store = BuildStoreLocal(node->local(), store_value); |
3441 ReturnDefinition(store); | 3446 ReturnDefinition(store); |
3442 } | 3447 } |
3443 | 3448 |
3444 | 3449 |
(...skipping 20 matching lines...) Expand all Loading... |
3465 | 3470 |
3466 void EffectGraphVisitor::VisitStoreInstanceFieldNode( | 3471 void EffectGraphVisitor::VisitStoreInstanceFieldNode( |
3467 StoreInstanceFieldNode* node) { | 3472 StoreInstanceFieldNode* node) { |
3468 ValueGraphVisitor for_instance(owner()); | 3473 ValueGraphVisitor for_instance(owner()); |
3469 node->instance()->Visit(&for_instance); | 3474 node->instance()->Visit(&for_instance); |
3470 Append(for_instance); | 3475 Append(for_instance); |
3471 ValueGraphVisitor for_value(owner()); | 3476 ValueGraphVisitor for_value(owner()); |
3472 node->value()->Visit(&for_value); | 3477 node->value()->Visit(&for_value); |
3473 Append(for_value); | 3478 Append(for_value); |
3474 Value* store_value = for_value.value(); | 3479 Value* store_value = for_value.value(); |
3475 if (FLAG_enable_type_checks) { | 3480 if (Isolate::Current()->TypeChecksEnabled()) { |
3476 const AbstractType& type = | 3481 const AbstractType& type = |
3477 AbstractType::ZoneHandle(I, node->field().type()); | 3482 AbstractType::ZoneHandle(I, node->field().type()); |
3478 const String& dst_name = String::ZoneHandle(I, node->field().name()); | 3483 const String& dst_name = String::ZoneHandle(I, node->field().name()); |
3479 store_value = BuildAssignableValue(node->value()->token_pos(), | 3484 store_value = BuildAssignableValue(node->value()->token_pos(), |
3480 store_value, | 3485 store_value, |
3481 type, | 3486 type, |
3482 dst_name); | 3487 dst_name); |
3483 } | 3488 } |
3484 | 3489 |
3485 store_value = Bind(BuildStoreExprTemp(store_value)); | 3490 store_value = Bind(BuildStoreExprTemp(store_value)); |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3827 CheckStackOverflowInstr* check = | 3832 CheckStackOverflowInstr* check = |
3828 new(I) CheckStackOverflowInstr(function.token_pos(), 0); | 3833 new(I) CheckStackOverflowInstr(function.token_pos(), 0); |
3829 // If we are inlining don't actually attach the stack check. We must still | 3834 // If we are inlining don't actually attach the stack check. We must still |
3830 // create the stack check in order to allocate a deopt id. | 3835 // create the stack check in order to allocate a deopt id. |
3831 if (!owner()->IsInlining()) { | 3836 if (!owner()->IsInlining()) { |
3832 AddInstruction(check); | 3837 AddInstruction(check); |
3833 } | 3838 } |
3834 } | 3839 } |
3835 } | 3840 } |
3836 | 3841 |
3837 if (FLAG_enable_type_checks && is_top_level_sequence) { | 3842 if (Isolate::Current()->TypeChecksEnabled() && is_top_level_sequence) { |
3838 const Function& function = owner()->function(); | 3843 const Function& function = owner()->function(); |
3839 const int num_params = function.NumParameters(); | 3844 const int num_params = function.NumParameters(); |
3840 int pos = 0; | 3845 int pos = 0; |
3841 if (function.IsConstructor()) { | 3846 if (function.IsConstructor()) { |
3842 // Skip type checking of receiver and phase for constructor functions. | 3847 // Skip type checking of receiver and phase for constructor functions. |
3843 pos = 2; | 3848 pos = 2; |
3844 } else if (function.IsFactory() || function.IsDynamicFunction()) { | 3849 } else if (function.IsFactory() || function.IsDynamicFunction()) { |
3845 // Skip type checking of type arguments for factory functions. | 3850 // Skip type checking of type arguments for factory functions. |
3846 // Skip type checking of receiver for instance functions. | 3851 // Skip type checking of receiver for instance functions. |
3847 pos = 1; | 3852 pos = 1; |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4328 Report::MessageF(Report::kBailout, | 4333 Report::MessageF(Report::kBailout, |
4329 Script::Handle(function.script()), | 4334 Script::Handle(function.script()), |
4330 function.token_pos(), | 4335 function.token_pos(), |
4331 "FlowGraphBuilder Bailout: %s %s", | 4336 "FlowGraphBuilder Bailout: %s %s", |
4332 String::Handle(function.name()).ToCString(), | 4337 String::Handle(function.name()).ToCString(), |
4333 reason); | 4338 reason); |
4334 UNREACHABLE(); | 4339 UNREACHABLE(); |
4335 } | 4340 } |
4336 | 4341 |
4337 } // namespace dart | 4342 } // namespace dart |
OLD | NEW |