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 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
663 void TestGraphVisitor::ReturnValue(Value* value) { | 663 void TestGraphVisitor::ReturnValue(Value* value) { |
664 if (FLAG_enable_type_checks) { | 664 if (FLAG_enable_type_checks) { |
665 value = Bind(new AssertBooleanInstr(condition_token_pos(), value)); | 665 value = Bind(new AssertBooleanInstr(condition_token_pos(), value)); |
666 } | 666 } |
667 Value* constant_true = Bind(new ConstantInstr(Bool::True())); | 667 Value* constant_true = Bind(new ConstantInstr(Bool::True())); |
668 StrictCompareInstr* comp = | 668 StrictCompareInstr* comp = |
669 new StrictCompareInstr(condition_token_pos(), | 669 new StrictCompareInstr(condition_token_pos(), |
670 Token::kEQ_STRICT, | 670 Token::kEQ_STRICT, |
671 value, | 671 value, |
672 constant_true); | 672 constant_true); |
673 comp->set_needs_number_check(false); | |
673 BranchInstr* branch = new BranchInstr(comp); | 674 BranchInstr* branch = new BranchInstr(comp); |
674 AddInstruction(branch); | 675 AddInstruction(branch); |
675 CloseFragment(); | 676 CloseFragment(); |
676 | 677 |
677 true_successor_addresses_.Add(branch->true_successor_address()); | 678 true_successor_addresses_.Add(branch->true_successor_address()); |
678 false_successor_addresses_.Add(branch->false_successor_address()); | 679 false_successor_addresses_.Add(branch->false_successor_address()); |
679 } | 680 } |
680 | 681 |
681 | 682 |
682 void TestGraphVisitor::MergeBranchWithComparison(ComparisonInstr* comp) { | 683 void TestGraphVisitor::MergeBranchWithComparison(ComparisonInstr* comp) { |
683 BranchInstr* branch; | 684 BranchInstr* branch; |
684 if (Token::IsStrictEqualityOperator(comp->kind())) { | 685 if (Token::IsStrictEqualityOperator(comp->kind())) { |
685 branch = new BranchInstr(new StrictCompareInstr(comp->token_pos(), | 686 ASSERT(comp->IsStrictCompare()); |
686 comp->kind(), | 687 branch = new BranchInstr(comp); |
687 comp->left(), | |
688 comp->right())); | |
689 } else if (Token::IsEqualityOperator(comp->kind()) && | 688 } else if (Token::IsEqualityOperator(comp->kind()) && |
690 (comp->left()->BindsToConstantNull() || | 689 (comp->left()->BindsToConstantNull() || |
691 comp->right()->BindsToConstantNull())) { | 690 comp->right()->BindsToConstantNull())) { |
692 branch = new BranchInstr(new StrictCompareInstr( | 691 branch = new BranchInstr(new StrictCompareInstr( |
693 comp->token_pos(), | 692 comp->token_pos(), |
694 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, | 693 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, |
695 comp->left(), | 694 comp->left(), |
696 comp->right())); | 695 comp->right())); |
697 } else { | 696 } else { |
698 branch = new BranchInstr(comp, FLAG_enable_type_checks); | 697 branch = new BranchInstr(comp, FLAG_enable_type_checks); |
699 } | 698 } |
700 AddInstruction(branch); | 699 AddInstruction(branch); |
701 CloseFragment(); | 700 CloseFragment(); |
702 true_successor_addresses_.Add(branch->true_successor_address()); | 701 true_successor_addresses_.Add(branch->true_successor_address()); |
703 false_successor_addresses_.Add(branch->false_successor_address()); | 702 false_successor_addresses_.Add(branch->false_successor_address()); |
704 } | 703 } |
705 | 704 |
706 | 705 |
707 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { | 706 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { |
708 ASSERT(!FLAG_enable_type_checks); | 707 ASSERT(!FLAG_enable_type_checks); |
709 Value* constant_true = Bind(new ConstantInstr(Bool::True())); | 708 Value* constant_true = Bind(new ConstantInstr(Bool::True())); |
710 BranchInstr* branch = new BranchInstr( | 709 StrictCompareInstr* comp = |
711 new StrictCompareInstr(condition_token_pos(), | 710 new StrictCompareInstr(condition_token_pos(), |
712 Token::kNE_STRICT, | 711 Token::kNE_STRICT, |
713 neg->value(), | 712 neg->value(), |
714 constant_true)); | 713 constant_true); |
714 comp->set_needs_number_check(false); | |
715 BranchInstr* branch = new BranchInstr(comp); | |
715 AddInstruction(branch); | 716 AddInstruction(branch); |
716 CloseFragment(); | 717 CloseFragment(); |
717 true_successor_addresses_.Add(branch->true_successor_address()); | 718 true_successor_addresses_.Add(branch->true_successor_address()); |
718 false_successor_addresses_.Add(branch->false_successor_address()); | 719 false_successor_addresses_.Add(branch->false_successor_address()); |
719 } | 720 } |
720 | 721 |
721 | 722 |
722 void TestGraphVisitor::ReturnDefinition(Definition* definition) { | 723 void TestGraphVisitor::ReturnDefinition(Definition* definition) { |
723 ComparisonInstr* comp = definition->AsComparison(); | 724 ComparisonInstr* comp = definition->AsComparison(); |
724 if (comp != NULL) { | 725 if (comp != NULL) { |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1352 Library::PrivateCoreLibName(Symbols::_as()), | 1353 Library::PrivateCoreLibName(Symbols::_as()), |
1353 node->kind(), | 1354 node->kind(), |
1354 arguments, | 1355 arguments, |
1355 Object::null_array(), // No argument names. | 1356 Object::null_array(), // No argument names. |
1356 kNumArgsChecked, | 1357 kNumArgsChecked, |
1357 owner()->ic_data_array()); | 1358 owner()->ic_data_array()); |
1358 ReturnDefinition(call); | 1359 ReturnDefinition(call); |
1359 } | 1360 } |
1360 | 1361 |
1361 | 1362 |
1363 StrictCompareInstr* EffectGraphVisitor::BuildStrictCompare(AstNode* left, | |
1364 AstNode* right, | |
1365 Token::Kind kind, | |
1366 intptr_t token_pos) { | |
srdjan
2013/10/28 21:02:25
Should you assert that kind is in valid range?
Florian Schneider
2013/11/04 10:39:54
I could do it here, but the constructor of StrictC
| |
1367 ValueGraphVisitor for_left_value(owner(), temp_index()); | |
1368 left->Visit(&for_left_value); | |
1369 Append(for_left_value); | |
1370 ValueGraphVisitor for_right_value(owner(), temp_index()); | |
1371 right->Visit(&for_right_value); | |
1372 Append(for_right_value); | |
1373 StrictCompareInstr* comp = new StrictCompareInstr(token_pos, | |
1374 kind, | |
1375 for_left_value.value(), | |
1376 for_right_value.value()); | |
1377 return comp; | |
1378 } | |
1379 | |
1380 | |
1362 // <Expression> :: Comparison { kind: Token::Kind | 1381 // <Expression> :: Comparison { kind: Token::Kind |
1363 // left: <Expression> | 1382 // left: <Expression> |
1364 // right: <Expression> } | 1383 // right: <Expression> } |
1365 // TODO(srdjan): Implement new equality. | 1384 // TODO(srdjan): Implement new equality. |
1366 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { | 1385 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { |
1367 if (Token::IsTypeTestOperator(node->kind())) { | 1386 if (Token::IsTypeTestOperator(node->kind())) { |
1368 BuildTypeTest(node); | 1387 BuildTypeTest(node); |
1369 return; | 1388 return; |
1370 } | 1389 } |
1371 if (Token::IsTypeCastOperator(node->kind())) { | 1390 if (Token::IsTypeCastOperator(node->kind())) { |
1372 BuildTypeCast(node); | 1391 BuildTypeCast(node); |
1373 return; | 1392 return; |
1374 } | 1393 } |
1394 | |
1375 if ((node->kind() == Token::kEQ_STRICT) || | 1395 if ((node->kind() == Token::kEQ_STRICT) || |
1376 (node->kind() == Token::kNE_STRICT)) { | 1396 (node->kind() == Token::kNE_STRICT)) { |
1377 ValueGraphVisitor for_left_value(owner(), temp_index()); | 1397 ReturnDefinition(BuildStrictCompare(node->left(), node->right(), |
1378 node->left()->Visit(&for_left_value); | 1398 node->kind(), node->token_pos())); |
1379 Append(for_left_value); | |
1380 ValueGraphVisitor for_right_value(owner(), temp_index()); | |
1381 node->right()->Visit(&for_right_value); | |
1382 Append(for_right_value); | |
1383 StrictCompareInstr* comp = new StrictCompareInstr(node->token_pos(), | |
1384 node->kind(), | |
1385 for_left_value.value(), | |
1386 for_right_value.value()); | |
1387 ReturnDefinition(comp); | |
1388 return; | 1399 return; |
1389 } | 1400 } |
1390 | 1401 |
1391 if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { | 1402 if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { |
1403 // Eagerly fold null-comparisons. | |
1404 LiteralNode* left_lit = node->left()->AsLiteralNode(); | |
1405 LiteralNode* right_lit = node->right()->AsLiteralNode(); | |
1406 if (((left_lit != NULL) && left_lit->literal().IsNull()) || | |
1407 ((right_lit != NULL) && right_lit->literal().IsNull())) { | |
1408 Token::Kind kind = | |
1409 (node->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT; | |
1410 StrictCompareInstr* compare = | |
1411 BuildStrictCompare(node->left(), node->right(), | |
1412 kind, node->token_pos()); | |
1413 ReturnDefinition(compare); | |
1414 return; | |
1415 } | |
1416 | |
1417 ZoneGrowableArray<PushArgumentInstr*>* arguments = | |
1418 new ZoneGrowableArray<PushArgumentInstr*>(2); | |
1419 | |
1392 ValueGraphVisitor for_left_value(owner(), temp_index()); | 1420 ValueGraphVisitor for_left_value(owner(), temp_index()); |
1393 node->left()->Visit(&for_left_value); | 1421 node->left()->Visit(&for_left_value); |
1394 Append(for_left_value); | 1422 Append(for_left_value); |
1423 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | |
1424 arguments->Add(push_left); | |
1425 | |
1395 ValueGraphVisitor for_right_value(owner(), temp_index()); | 1426 ValueGraphVisitor for_right_value(owner(), temp_index()); |
1396 node->right()->Visit(&for_right_value); | 1427 node->right()->Visit(&for_right_value); |
1397 Append(for_right_value); | 1428 Append(for_right_value); |
1429 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); | |
1430 arguments->Add(push_right); | |
1431 | |
1432 Definition* result = | |
1433 new InstanceCallInstr(node->token_pos(), | |
1434 Symbols::EqualOperator(), | |
1435 Token::kEQ, // Result is negated later for kNE. | |
1436 arguments, | |
1437 Object::null_array(), | |
1438 2, | |
1439 owner()->ic_data_array()); | |
1398 if (FLAG_enable_type_checks) { | 1440 if (FLAG_enable_type_checks) { |
1399 EqualityCompareInstr* comp = new EqualityCompareInstr( | 1441 Value* value = Bind(result); |
1400 node->token_pos(), | 1442 result = new AssertBooleanInstr(node->token_pos(), value); |
1401 Token::kEQ, | |
1402 for_left_value.value(), | |
1403 for_right_value.value(), | |
1404 owner()->ic_data_array()); | |
1405 if (node->kind() == Token::kEQ) { | |
1406 ReturnDefinition(comp); | |
1407 } else { | |
1408 Value* eq_result = Bind(comp); | |
1409 eq_result = Bind(new AssertBooleanInstr(node->token_pos(), eq_result)); | |
1410 ReturnDefinition(new BooleanNegateInstr(eq_result)); | |
1411 } | |
1412 } else { | |
1413 EqualityCompareInstr* comp = new EqualityCompareInstr( | |
1414 node->token_pos(), | |
1415 node->kind(), | |
1416 for_left_value.value(), | |
1417 for_right_value.value(), | |
1418 owner()->ic_data_array()); | |
1419 ReturnDefinition(comp); | |
1420 } | 1443 } |
1444 | |
1445 if (node->kind() == Token::kNE) { | |
1446 Value* value = Bind(result); | |
1447 result = new BooleanNegateInstr(value); | |
1448 } | |
1449 ReturnDefinition(result); | |
1421 return; | 1450 return; |
1422 } | 1451 } |
1423 | 1452 |
1424 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1453 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1425 new ZoneGrowableArray<PushArgumentInstr*>(2); | 1454 new ZoneGrowableArray<PushArgumentInstr*>(2); |
1426 | 1455 |
1427 ValueGraphVisitor for_left_value(owner(), temp_index()); | 1456 ValueGraphVisitor for_left_value(owner(), temp_index()); |
1428 node->left()->Visit(&for_left_value); | 1457 node->left()->Visit(&for_left_value); |
1429 Append(for_left_value); | 1458 Append(for_left_value); |
1430 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 1459 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
(...skipping 1479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2910 true); // Test only. | 2939 true); // Test only. |
2911 return new LoadLocalInstr(*receiver_var); | 2940 return new LoadLocalInstr(*receiver_var); |
2912 } | 2941 } |
2913 | 2942 |
2914 | 2943 |
2915 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { | 2944 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { |
2916 const Function& function = owner()->parsed_function()->function(); | 2945 const Function& function = owner()->parsed_function()->function(); |
2917 if (!function.IsClosureFunction()) { | 2946 if (!function.IsClosureFunction()) { |
2918 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); | 2947 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); |
2919 switch (kind) { | 2948 switch (kind) { |
2949 case MethodRecognizer::kObjectEquals: { | |
2950 Value* receiver = Bind(BuildLoadThisVar(node->scope())); | |
2951 LocalVariable* other_var = | |
2952 node->scope()->LookupVariable(Symbols::Other(), | |
2953 true); // Test only. | |
2954 Value* other = Bind(new LoadLocalInstr(*other_var)); | |
2955 StrictCompareInstr* compare = | |
2956 new StrictCompareInstr(node->token_pos(), | |
2957 Token::kEQ_STRICT, | |
2958 receiver, | |
2959 other); | |
2960 // Receiver is not a number because numbers override equality. | |
Florian Schneider
2013/10/28 13:34:19
I moved the implementation of Object.== here so th
| |
2961 compare->set_needs_number_check(false); | |
2962 return ReturnDefinition(compare); | |
2963 } | |
2920 case MethodRecognizer::kStringBaseLength: | 2964 case MethodRecognizer::kStringBaseLength: |
2921 case MethodRecognizer::kStringBaseIsEmpty: { | 2965 case MethodRecognizer::kStringBaseIsEmpty: { |
2922 Value* receiver = Bind(BuildLoadThisVar(node->scope())); | 2966 Value* receiver = Bind(BuildLoadThisVar(node->scope())); |
2923 // Treat length loads as mutable (i.e. affected by side effects) to | 2967 // Treat length loads as mutable (i.e. affected by side effects) to |
2924 // avoid hoisting them since we can't hoist the preceding class-check. | 2968 // avoid hoisting them since we can't hoist the preceding class-check. |
2925 // This is because of externalization of strings that affects their | 2969 // This is because of externalization of strings that affects their |
2926 // class-id. | 2970 // class-id. |
2927 const bool is_immutable = false; | 2971 const bool is_immutable = false; |
2928 LoadFieldInstr* load = new LoadFieldInstr( | 2972 LoadFieldInstr* load = new LoadFieldInstr( |
2929 receiver, | 2973 receiver, |
(...skipping 919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3849 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 3893 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
3850 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 3894 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
3851 OS::SNPrint(chars, len, kFormat, function_name, reason); | 3895 OS::SNPrint(chars, len, kFormat, function_name, reason); |
3852 const Error& error = Error::Handle( | 3896 const Error& error = Error::Handle( |
3853 LanguageError::New(String::Handle(String::New(chars)))); | 3897 LanguageError::New(String::Handle(String::New(chars)))); |
3854 Isolate::Current()->long_jump_base()->Jump(1, error); | 3898 Isolate::Current()->long_jump_base()->Jump(1, error); |
3855 } | 3899 } |
3856 | 3900 |
3857 | 3901 |
3858 } // namespace dart | 3902 } // namespace dart |
OLD | NEW |