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/code_descriptors.h" | 10 #include "vm/code_descriptors.h" |
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 void TestGraphVisitor::ReturnValue(Value* value) { | 664 void TestGraphVisitor::ReturnValue(Value* value) { |
665 if (FLAG_enable_type_checks) { | 665 if (FLAG_enable_type_checks) { |
666 value = Bind(new AssertBooleanInstr(condition_token_pos(), value)); | 666 value = Bind(new AssertBooleanInstr(condition_token_pos(), value)); |
667 } | 667 } |
668 Value* constant_true = Bind(new ConstantInstr(Bool::True())); | 668 Value* constant_true = Bind(new ConstantInstr(Bool::True())); |
669 StrictCompareInstr* comp = | 669 StrictCompareInstr* comp = |
670 new StrictCompareInstr(condition_token_pos(), | 670 new StrictCompareInstr(condition_token_pos(), |
671 Token::kEQ_STRICT, | 671 Token::kEQ_STRICT, |
672 value, | 672 value, |
673 constant_true); | 673 constant_true); |
| 674 comp->set_needs_number_check(false); |
674 BranchInstr* branch = new BranchInstr(comp); | 675 BranchInstr* branch = new BranchInstr(comp); |
675 AddInstruction(branch); | 676 AddInstruction(branch); |
676 CloseFragment(); | 677 CloseFragment(); |
677 | 678 |
678 true_successor_addresses_.Add(branch->true_successor_address()); | 679 true_successor_addresses_.Add(branch->true_successor_address()); |
679 false_successor_addresses_.Add(branch->false_successor_address()); | 680 false_successor_addresses_.Add(branch->false_successor_address()); |
680 } | 681 } |
681 | 682 |
682 | 683 |
683 void TestGraphVisitor::MergeBranchWithComparison(ComparisonInstr* comp) { | 684 void TestGraphVisitor::MergeBranchWithComparison(ComparisonInstr* comp) { |
684 BranchInstr* branch; | 685 BranchInstr* branch; |
685 if (Token::IsStrictEqualityOperator(comp->kind())) { | 686 if (Token::IsStrictEqualityOperator(comp->kind())) { |
686 branch = new BranchInstr(new StrictCompareInstr(comp->token_pos(), | 687 ASSERT(comp->IsStrictCompare()); |
687 comp->kind(), | 688 branch = new BranchInstr(comp); |
688 comp->left(), | |
689 comp->right())); | |
690 } else if (Token::IsEqualityOperator(comp->kind()) && | 689 } else if (Token::IsEqualityOperator(comp->kind()) && |
691 (comp->left()->BindsToConstantNull() || | 690 (comp->left()->BindsToConstantNull() || |
692 comp->right()->BindsToConstantNull())) { | 691 comp->right()->BindsToConstantNull())) { |
693 branch = new BranchInstr(new StrictCompareInstr( | 692 branch = new BranchInstr(new StrictCompareInstr( |
694 comp->token_pos(), | 693 comp->token_pos(), |
695 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, | 694 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, |
696 comp->left(), | 695 comp->left(), |
697 comp->right())); | 696 comp->right())); |
698 } else { | 697 } else { |
699 branch = new BranchInstr(comp, FLAG_enable_type_checks); | 698 branch = new BranchInstr(comp, FLAG_enable_type_checks); |
700 } | 699 } |
701 AddInstruction(branch); | 700 AddInstruction(branch); |
702 CloseFragment(); | 701 CloseFragment(); |
703 true_successor_addresses_.Add(branch->true_successor_address()); | 702 true_successor_addresses_.Add(branch->true_successor_address()); |
704 false_successor_addresses_.Add(branch->false_successor_address()); | 703 false_successor_addresses_.Add(branch->false_successor_address()); |
705 } | 704 } |
706 | 705 |
707 | 706 |
708 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { | 707 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { |
709 ASSERT(!FLAG_enable_type_checks); | 708 ASSERT(!FLAG_enable_type_checks); |
710 Value* constant_true = Bind(new ConstantInstr(Bool::True())); | 709 Value* constant_true = Bind(new ConstantInstr(Bool::True())); |
711 BranchInstr* branch = new BranchInstr( | 710 StrictCompareInstr* comp = |
712 new StrictCompareInstr(condition_token_pos(), | 711 new StrictCompareInstr(condition_token_pos(), |
713 Token::kNE_STRICT, | 712 Token::kNE_STRICT, |
714 neg->value(), | 713 neg->value(), |
715 constant_true)); | 714 constant_true); |
| 715 comp->set_needs_number_check(false); |
| 716 BranchInstr* branch = new BranchInstr(comp); |
716 AddInstruction(branch); | 717 AddInstruction(branch); |
717 CloseFragment(); | 718 CloseFragment(); |
718 true_successor_addresses_.Add(branch->true_successor_address()); | 719 true_successor_addresses_.Add(branch->true_successor_address()); |
719 false_successor_addresses_.Add(branch->false_successor_address()); | 720 false_successor_addresses_.Add(branch->false_successor_address()); |
720 } | 721 } |
721 | 722 |
722 | 723 |
723 void TestGraphVisitor::ReturnDefinition(Definition* definition) { | 724 void TestGraphVisitor::ReturnDefinition(Definition* definition) { |
724 ComparisonInstr* comp = definition->AsComparison(); | 725 ComparisonInstr* comp = definition->AsComparison(); |
725 if (comp != NULL) { | 726 if (comp != NULL) { |
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1359 Library::PrivateCoreLibName(Symbols::_as()), | 1360 Library::PrivateCoreLibName(Symbols::_as()), |
1360 node->kind(), | 1361 node->kind(), |
1361 arguments, | 1362 arguments, |
1362 Object::null_array(), // No argument names. | 1363 Object::null_array(), // No argument names. |
1363 kNumArgsChecked, | 1364 kNumArgsChecked, |
1364 owner()->ic_data_array()); | 1365 owner()->ic_data_array()); |
1365 ReturnDefinition(call); | 1366 ReturnDefinition(call); |
1366 } | 1367 } |
1367 | 1368 |
1368 | 1369 |
| 1370 StrictCompareInstr* EffectGraphVisitor::BuildStrictCompare(AstNode* left, |
| 1371 AstNode* right, |
| 1372 Token::Kind kind, |
| 1373 intptr_t token_pos) { |
| 1374 ValueGraphVisitor for_left_value(owner(), temp_index()); |
| 1375 left->Visit(&for_left_value); |
| 1376 Append(for_left_value); |
| 1377 ValueGraphVisitor for_right_value(owner(), temp_index()); |
| 1378 right->Visit(&for_right_value); |
| 1379 Append(for_right_value); |
| 1380 StrictCompareInstr* comp = new StrictCompareInstr(token_pos, |
| 1381 kind, |
| 1382 for_left_value.value(), |
| 1383 for_right_value.value()); |
| 1384 return comp; |
| 1385 } |
| 1386 |
| 1387 |
1369 // <Expression> :: Comparison { kind: Token::Kind | 1388 // <Expression> :: Comparison { kind: Token::Kind |
1370 // left: <Expression> | 1389 // left: <Expression> |
1371 // right: <Expression> } | 1390 // right: <Expression> } |
1372 // TODO(srdjan): Implement new equality. | 1391 // TODO(srdjan): Implement new equality. |
1373 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { | 1392 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { |
1374 if (Token::IsTypeTestOperator(node->kind())) { | 1393 if (Token::IsTypeTestOperator(node->kind())) { |
1375 BuildTypeTest(node); | 1394 BuildTypeTest(node); |
1376 return; | 1395 return; |
1377 } | 1396 } |
1378 if (Token::IsTypeCastOperator(node->kind())) { | 1397 if (Token::IsTypeCastOperator(node->kind())) { |
1379 BuildTypeCast(node); | 1398 BuildTypeCast(node); |
1380 return; | 1399 return; |
1381 } | 1400 } |
| 1401 |
1382 if ((node->kind() == Token::kEQ_STRICT) || | 1402 if ((node->kind() == Token::kEQ_STRICT) || |
1383 (node->kind() == Token::kNE_STRICT)) { | 1403 (node->kind() == Token::kNE_STRICT)) { |
1384 ValueGraphVisitor for_left_value(owner(), temp_index()); | 1404 ReturnDefinition(BuildStrictCompare(node->left(), node->right(), |
1385 node->left()->Visit(&for_left_value); | 1405 node->kind(), node->token_pos())); |
1386 Append(for_left_value); | |
1387 ValueGraphVisitor for_right_value(owner(), temp_index()); | |
1388 node->right()->Visit(&for_right_value); | |
1389 Append(for_right_value); | |
1390 StrictCompareInstr* comp = new StrictCompareInstr(node->token_pos(), | |
1391 node->kind(), | |
1392 for_left_value.value(), | |
1393 for_right_value.value()); | |
1394 ReturnDefinition(comp); | |
1395 return; | 1406 return; |
1396 } | 1407 } |
1397 | 1408 |
1398 if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { | 1409 if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { |
| 1410 // Eagerly fold null-comparisons. |
| 1411 LiteralNode* left_lit = node->left()->AsLiteralNode(); |
| 1412 LiteralNode* right_lit = node->right()->AsLiteralNode(); |
| 1413 if (((left_lit != NULL) && left_lit->literal().IsNull()) || |
| 1414 ((right_lit != NULL) && right_lit->literal().IsNull())) { |
| 1415 Token::Kind kind = |
| 1416 (node->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT; |
| 1417 StrictCompareInstr* compare = |
| 1418 BuildStrictCompare(node->left(), node->right(), |
| 1419 kind, node->token_pos()); |
| 1420 ReturnDefinition(compare); |
| 1421 return; |
| 1422 } |
| 1423 |
| 1424 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 1425 new ZoneGrowableArray<PushArgumentInstr*>(2); |
| 1426 |
1399 ValueGraphVisitor for_left_value(owner(), temp_index()); | 1427 ValueGraphVisitor for_left_value(owner(), temp_index()); |
1400 node->left()->Visit(&for_left_value); | 1428 node->left()->Visit(&for_left_value); |
1401 Append(for_left_value); | 1429 Append(for_left_value); |
| 1430 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
| 1431 arguments->Add(push_left); |
| 1432 |
1402 ValueGraphVisitor for_right_value(owner(), temp_index()); | 1433 ValueGraphVisitor for_right_value(owner(), temp_index()); |
1403 node->right()->Visit(&for_right_value); | 1434 node->right()->Visit(&for_right_value); |
1404 Append(for_right_value); | 1435 Append(for_right_value); |
| 1436 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); |
| 1437 arguments->Add(push_right); |
| 1438 |
| 1439 Definition* result = |
| 1440 new InstanceCallInstr(node->token_pos(), |
| 1441 Symbols::EqualOperator(), |
| 1442 Token::kEQ, // Result is negated later for kNE. |
| 1443 arguments, |
| 1444 Object::null_array(), |
| 1445 2, |
| 1446 owner()->ic_data_array()); |
1405 if (FLAG_enable_type_checks) { | 1447 if (FLAG_enable_type_checks) { |
1406 EqualityCompareInstr* comp = new EqualityCompareInstr( | 1448 Value* value = Bind(result); |
1407 node->token_pos(), | 1449 result = new AssertBooleanInstr(node->token_pos(), value); |
1408 Token::kEQ, | |
1409 for_left_value.value(), | |
1410 for_right_value.value(), | |
1411 owner()->ic_data_array()); | |
1412 if (node->kind() == Token::kEQ) { | |
1413 ReturnDefinition(comp); | |
1414 } else { | |
1415 Value* eq_result = Bind(comp); | |
1416 eq_result = Bind(new AssertBooleanInstr(node->token_pos(), eq_result)); | |
1417 ReturnDefinition(new BooleanNegateInstr(eq_result)); | |
1418 } | |
1419 } else { | |
1420 EqualityCompareInstr* comp = new EqualityCompareInstr( | |
1421 node->token_pos(), | |
1422 node->kind(), | |
1423 for_left_value.value(), | |
1424 for_right_value.value(), | |
1425 owner()->ic_data_array()); | |
1426 ReturnDefinition(comp); | |
1427 } | 1450 } |
| 1451 |
| 1452 if (node->kind() == Token::kNE) { |
| 1453 Value* value = Bind(result); |
| 1454 result = new BooleanNegateInstr(value); |
| 1455 } |
| 1456 ReturnDefinition(result); |
1428 return; | 1457 return; |
1429 } | 1458 } |
1430 | 1459 |
1431 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1460 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1432 new ZoneGrowableArray<PushArgumentInstr*>(2); | 1461 new ZoneGrowableArray<PushArgumentInstr*>(2); |
1433 | 1462 |
1434 ValueGraphVisitor for_left_value(owner(), temp_index()); | 1463 ValueGraphVisitor for_left_value(owner(), temp_index()); |
1435 node->left()->Visit(&for_left_value); | 1464 node->left()->Visit(&for_left_value); |
1436 Append(for_left_value); | 1465 Append(for_left_value); |
1437 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 1466 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
(...skipping 1480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2918 true); // Test only. | 2947 true); // Test only. |
2919 return new LoadLocalInstr(*receiver_var); | 2948 return new LoadLocalInstr(*receiver_var); |
2920 } | 2949 } |
2921 | 2950 |
2922 | 2951 |
2923 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { | 2952 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { |
2924 const Function& function = owner()->parsed_function()->function(); | 2953 const Function& function = owner()->parsed_function()->function(); |
2925 if (!function.IsClosureFunction()) { | 2954 if (!function.IsClosureFunction()) { |
2926 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); | 2955 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); |
2927 switch (kind) { | 2956 switch (kind) { |
| 2957 case MethodRecognizer::kObjectEquals: { |
| 2958 Value* receiver = Bind(BuildLoadThisVar(node->scope())); |
| 2959 LocalVariable* other_var = |
| 2960 node->scope()->LookupVariable(Symbols::Other(), |
| 2961 true); // Test only. |
| 2962 Value* other = Bind(new LoadLocalInstr(*other_var)); |
| 2963 StrictCompareInstr* compare = |
| 2964 new StrictCompareInstr(node->token_pos(), |
| 2965 Token::kEQ_STRICT, |
| 2966 receiver, |
| 2967 other); |
| 2968 // Receiver is not a number because numbers override equality. |
| 2969 compare->set_needs_number_check(false); |
| 2970 return ReturnDefinition(compare); |
| 2971 } |
2928 case MethodRecognizer::kStringBaseLength: | 2972 case MethodRecognizer::kStringBaseLength: |
2929 case MethodRecognizer::kStringBaseIsEmpty: { | 2973 case MethodRecognizer::kStringBaseIsEmpty: { |
2930 Value* receiver = Bind(BuildLoadThisVar(node->scope())); | 2974 Value* receiver = Bind(BuildLoadThisVar(node->scope())); |
2931 // Treat length loads as mutable (i.e. affected by side effects) to | 2975 // Treat length loads as mutable (i.e. affected by side effects) to |
2932 // avoid hoisting them since we can't hoist the preceding class-check. | 2976 // avoid hoisting them since we can't hoist the preceding class-check. |
2933 // This is because of externalization of strings that affects their | 2977 // This is because of externalization of strings that affects their |
2934 // class-id. | 2978 // class-id. |
2935 const bool is_immutable = false; | 2979 const bool is_immutable = false; |
2936 LoadFieldInstr* load = new LoadFieldInstr( | 2980 LoadFieldInstr* load = new LoadFieldInstr( |
2937 receiver, | 2981 receiver, |
(...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3858 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 3902 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
3859 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 3903 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
3860 OS::SNPrint(chars, len, kFormat, function_name, reason); | 3904 OS::SNPrint(chars, len, kFormat, function_name, reason); |
3861 const Error& error = Error::Handle( | 3905 const Error& error = Error::Handle( |
3862 LanguageError::New(String::Handle(String::New(chars)))); | 3906 LanguageError::New(String::Handle(String::New(chars)))); |
3863 Isolate::Current()->long_jump_base()->Jump(1, error); | 3907 Isolate::Current()->long_jump_base()->Jump(1, error); |
3864 } | 3908 } |
3865 | 3909 |
3866 | 3910 |
3867 } // namespace dart | 3911 } // namespace dart |
OLD | NEW |