Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(383)

Side by Side Diff: runtime/vm/flow_graph_builder.cc

Issue 27307005: Change == into an instance call to allow polymorphic inlining of ==. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698