| 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 |