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

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

Issue 8413047: Special code for equality comparison for Smi, allowing null on left or right without calling deop... (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 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
« no previous file with comments | « runtime/vm/opt_code_generator_ia32.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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/globals.h" // Needed here to get TARGET_ARCH_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/opt_code_generator.h" 8 #include "vm/opt_code_generator.h"
9 9
10 #include "vm/assembler_macros.h" 10 #include "vm/assembler_macros.h"
(...skipping 1406 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 __ j(condition, nInfo.true_label()); 1417 __ j(condition, nInfo.true_label());
1418 __ jmp(nInfo.false_label()); 1418 __ jmp(nInfo.false_label());
1419 } else if (nInfo.fallthrough_label() == nInfo.false_label()) { 1419 } else if (nInfo.fallthrough_label() == nInfo.false_label()) {
1420 __ j(condition, nInfo.true_label()); 1420 __ j(condition, nInfo.true_label());
1421 } else if (nInfo.fallthrough_label() == nInfo.true_label()) { 1421 } else if (nInfo.fallthrough_label() == nInfo.true_label()) {
1422 __ j(NegateCondition(condition), nInfo.false_label()); 1422 __ j(NegateCondition(condition), nInfo.false_label());
1423 } 1423 }
1424 } 1424 }
1425 1425
1426 1426
1427 // Return false if the code cannot be generated. 1427 // Generate code under assumption that it is common that a Smi
1428 // is compared with null.
1429 // Left argument can be Smi or null, otherwise deoptimize and collect more
1430 // type information.
1431 // Right operand can be Smi or null, otherwise call operator on Smi (e.g,
1432 // when compared with double).
1433 // This code will be more optimized once we collect types for two arguments.
1434 void OptimizingCodeGenerator::GenerateSmiEquality(ComparisonNode* node) {
1435 ASSERT((node->kind() == Token::kEQ) || (node->kind() == Token::kNE));
1436 CodeGenInfo left_info(node->left());
1437 CodeGenInfo right_info(node->right());
1438 VisitLoadTwo(node->left(), node->right(), EAX, EDX);
1439 if (!CodeGenerator::IsResultNeeded(node)) {
1440 return;
1441 }
1442 const Immediate raw_null =
1443 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1444 Label evaluate_comparison;
1445 if (!left_info.IsClass(smi_class_)) {
1446 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob(node, EAX, EDX);
1447 Label left_not_null;
1448 __ cmpl(EAX, raw_null);
1449 __ j(NOT_EQUAL, &left_not_null, Assembler::kNearJump);
1450
1451 // Left is null, strict compare.
1452 __ cmpl(EAX, EDX);
1453 __ jmp(&evaluate_comparison, Assembler::kNearJump);
1454
1455 // Deoptimize if left is not Smi.
1456 __ Bind(&left_not_null);
1457 __ testl(EAX, Immediate(kSmiTagMask));
1458 __ j(NOT_ZERO, deopt_blob->label());
1459 }
1460 Label done;
1461 if (right_info.IsClass(smi_class_)) {
1462 __ cmpl(EAX, EDX);
1463 // Fall through to evaluate comparison.
1464 } else {
1465 Label call_operator, inlined_compare;
1466 // Test right for being Smi.
1467 __ testl(EDX, Immediate(kSmiTagMask));
1468 __ j(ZERO, &inlined_compare, Assembler::kNearJump);
1469 // Right is not Smi, test it for being null; if so result is false which
1470 // is generated by comparing it to left. If right is not null call operator
1471 // (could be double).
1472 __ cmpl(EDX, raw_null);
1473 __ j(NOT_EQUAL, &call_operator, Assembler::kNearJump);
1474
1475 __ Bind(&inlined_compare);
1476 // Left is Smi, right is Smi or Null.
1477 __ cmpl(EAX, EDX);
1478 __ jmp(&evaluate_comparison);
1479
1480 __ Bind(&call_operator);
1481 // Left is Smi.
1482 const int kNumberOfArguments = 2;
1483 const Array& kNoArgumentNames = Array::Handle();
1484 __ pushl(EAX);
1485 __ pushl(EDX);
1486 GenerateCheckedInstanceCalls(node,
1487 node->left(),
1488 node->id(),
1489 node->token_index(),
1490 kNumberOfArguments,
1491 kNoArgumentNames);
1492 __ pushl(EAX);
1493 __ jmp(&done, Assembler::kNearJump);
1494 }
1495 __ Bind(&evaluate_comparison);
1496 // Condition is set by a previous comparison operation.
1497 Condition condition = OVERFLOW; // Initialize to something.
1498 bool ok = SupportedTokenKindToSmiCondition(node->kind(), &condition);
1499 ASSERT(ok);
1500 if (NodeInfoHasLabels(node)) {
1501 GenerateConditionalJumps(*(node->info()), condition);
1502 node->info()->set_labels_used(true);
1503 } else {
1504 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1505 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1506 Label true_label;
1507 __ j(condition, &true_label, Assembler::kNearJump);
1508 __ PushObject(bool_false);
1509 __ jmp(&done, Assembler::kNearJump);
1510 __ Bind(&true_label);
1511 __ PushObject(bool_true);
1512 }
1513 __ Bind(&done);
1514 }
1515
1516
1517 // Return false if the code cannot be generated. It is expected that
1518 // node->left() is Smi (or null for equality comparison).
1428 bool OptimizingCodeGenerator::GenerateSmiComparison(ComparisonNode* node) { 1519 bool OptimizingCodeGenerator::GenerateSmiComparison(ComparisonNode* node) {
1520 if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) {
1521 GenerateSmiEquality(node);
1522 return true;
1523 }
1429 Condition condition; 1524 Condition condition;
1430 if (!SupportedTokenKindToSmiCondition(node->kind(), &condition)) { 1525 if (!SupportedTokenKindToSmiCondition(node->kind(), &condition)) {
1431 return false; 1526 return false;
1432 } 1527 }
1433 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1528 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1434 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1529 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1435 CodeGenInfo left_info(node->left()); 1530 CodeGenInfo left_info(node->left());
1436 CodeGenInfo right_info(node->right()); 1531 CodeGenInfo right_info(node->right());
1437 VisitLoadTwo(node->left(), node->right(), EAX, EDX); 1532 VisitLoadTwo(node->left(), node->right(), EAX, EDX);
1438 if (!CodeGenerator::IsResultNeeded(node)) { 1533 if (!CodeGenerator::IsResultNeeded(node)) {
1439 return true; 1534 return true;
1440 } 1535 }
1441 Label two_smis;
1442 if (left_info.IsClass(smi_class_) && right_info.IsClass(smi_class_)) { 1536 if (left_info.IsClass(smi_class_) && right_info.IsClass(smi_class_)) {
1443 __ cmpl(EAX, EDX); 1537 __ cmpl(EAX, EDX);
1444 } else if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) { 1538 } else if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) {
1445 // One is Smi. 1539 // One is Smi.
1446 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob(node, EAX, EDX); 1540 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob(node, EAX, EDX);
1447 Register reg_to_test = left_info.IsClass(smi_class_) ? EDX : EAX; 1541 Register reg_to_test = left_info.IsClass(smi_class_) ? EDX : EAX;
1448 __ testl(reg_to_test, Immediate(kSmiTagMask)); 1542 __ testl(reg_to_test, Immediate(kSmiTagMask));
1449 __ j(NOT_ZERO, deopt_blob->label()); 1543 __ j(NOT_ZERO, deopt_blob->label());
1450 __ cmpl(EAX, EDX); 1544 __ cmpl(EAX, EDX);
1451 } else { 1545 } else {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1492 return true; 1586 return true;
1493 default: 1587 default:
1494 return false; 1588 return false;
1495 } 1589 }
1496 } 1590 }
1497 1591
1498 1592
1499 // Checks if an inlined equality/non-equality operation can be emitted: 1593 // Checks if an inlined equality/non-equality operation can be emitted:
1500 // - type feedback must exist. 1594 // - type feedback must exist.
1501 // - no class in type feedback list overrides '=='. 1595 // - no class in type feedback list overrides '=='.
1502 // - no Smi class in type feedback class list. 1596 // - no Smi class in type feedback class list (Smi overrides equality operator).
1503 bool OptimizingCodeGenerator::GenerateEqualityComparison(ComparisonNode* node) { 1597 bool OptimizingCodeGenerator::GenerateEqualityComparison(ComparisonNode* node) {
1504 ASSERT((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)); 1598 ASSERT((node->kind() == Token::kEQ) || (node->kind() == Token::kNE));
1505 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1599 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1506 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1600 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1507 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node); 1601 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
1508 if (classes == NULL) { 1602 if (classes == NULL) {
1509 return false; 1603 return false;
1510 } 1604 }
1511 const int num_classes = classes->length(); 1605 const int num_classes = classes->length();
1512 // 'num_classes' can be 0 if the receiver was always null. 1606 // 'num_classes' can be 0 if the receiver was always null.
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after
2177 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize)); 2271 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize));
2178 // Result is in EAX. 2272 // Result is in EAX.
2179 if (IsResultNeeded(node)) { 2273 if (IsResultNeeded(node)) {
2180 __ pushl(EAX); 2274 __ pushl(EAX);
2181 } 2275 }
2182 } 2276 }
2183 2277
2184 } // namespace dart 2278 } // namespace dart
2185 2279
2186 #endif // defined TARGET_ARCH_IA32 2280 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/opt_code_generator_ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698