Chromium Code Reviews| 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 |