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

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

Issue 105143011: Optimize one byte string comparisons. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years 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/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 1463 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 last->LinkTo(call); 1474 last->LinkTo(call);
1475 // Remove through the iterator. 1475 // Remove through the iterator.
1476 ASSERT(current_iterator()->Current() == call); 1476 ASSERT(current_iterator()->Current() == call);
1477 current_iterator()->RemoveCurrentFromGraph(); 1477 current_iterator()->RemoveCurrentFromGraph();
1478 call->set_previous(NULL); 1478 call->set_previous(NULL);
1479 call->set_next(NULL); 1479 call->set_next(NULL);
1480 return true; 1480 return true;
1481 } 1481 }
1482 1482
1483 1483
1484 // Return true if d is a string of length one (a constant or result from
1485 // from string-from-char-code instruction.
1486 static bool IsLengthOneString(Definition* d) {
1487 if (d->IsConstant()) {
1488 const Object& obj = d->AsConstant()->value();
1489 if (obj.IsString()) {
1490 return String::Cast(obj).Length() == 1;
1491 } else {
1492 return false;
1493 }
1494 } else {
1495 return d->IsStringFromCharCode();
1496 }
1497 }
1498
1499
1500 // Returns true if the string comparison was converted into char-code
1501 // comparison. Conversion is only possible for strings of length one.
1502 // E.g., detect str[x] == "x"; and use an integer comparison of char-codes.
1503 // TODO(srdjan): Expand for two-byte and external strings.
1504 bool FlowGraphOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call,
1505 Token::Kind op_kind) {
1506 ASSERT(HasOnlyTwoOf(*call->ic_data(), kOneByteStringCid));
1507 // Check that left and right are length one strings (either string constants
1508 // or results of string-from-char-code.
1509 Definition* left = call->ArgumentAt(0);
1510 Definition* right = call->ArgumentAt(1);
1511 Value* left_val = NULL;
1512 Definition* to_remove_left = NULL;
1513 if (IsLengthOneString(right)) {
1514 // Swap, since we know that both arguments are strings
1515 Definition* temp = left;
1516 left = right;
1517 right = temp;
1518 }
1519 if (IsLengthOneString(left)) {
1520 // Optimize if left is a string with length one (either constant or
1521 // result of string-from-char-code.
1522 if (left->IsConstant()) {
1523 ConstantInstr* left_const = left->AsConstant();
1524 const String& str = String::Cast(left_const->value());
1525 ASSERT(str.Length() == 1);
1526 ConstantInstr* char_code_left =
1527 flow_graph()->GetConstant(Smi::ZoneHandle(Smi::New(str.CharAt(0))));
1528 left_val = new Value(char_code_left);
1529 } else if (left->IsStringFromCharCode()) {
1530 // Use input of string-from-charcode as left value.
1531 StringFromCharCodeInstr* instr = left->AsStringFromCharCode();
1532 left_val = new Value(instr->char_code()->definition());
1533 to_remove_left = instr;
1534 } else {
1535 // IsLengthOneString(left) should have been false.
1536 UNREACHABLE();
1537 }
1538
1539 Definition* to_remove_right = NULL;
1540 Value* right_val = NULL;
1541 if (right->IsStringFromCharCode()) {
1542 // Skip string-from-char-code, and use its input as right value.
1543 StringFromCharCodeInstr* right_instr = right->AsStringFromCharCode();
1544 right_val = new Value(right_instr->char_code()->definition());
1545 to_remove_right = right_instr;
1546 } else {
1547 const ICData& unary_checks_1 =
1548 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1));
1549 AddCheckClass(right,
1550 unary_checks_1,
1551 call->deopt_id(),
1552 call->env(),
1553 call);
1554 // String-to-char-code instructions returns -1 (illegal charcode) if
1555 // string is not of length one.
1556 StringToCharCodeInstr* char_code_right =
1557 new StringToCharCodeInstr(new Value(right), kOneByteStringCid);
1558 InsertBefore(call, char_code_right, call->env(), Definition::kValue);
1559 right_val = new Value(char_code_right);
1560 }
1561
1562 // Comparing char-codes instead of strings.
1563 EqualityCompareInstr* comp =
1564 new EqualityCompareInstr(call->token_pos(),
1565 op_kind,
1566 left_val,
1567 right_val,
1568 kSmiCid,
1569 call->deopt_id());
1570 ReplaceCall(call, comp);
1571
1572 // Remove dead instructions.
1573 if ((to_remove_left != NULL) &&
1574 (to_remove_left->input_use_list() == NULL)) {
1575 to_remove_left->ReplaceUsesWith(flow_graph()->constant_null());
1576 to_remove_left->RemoveFromGraph();
1577 }
1578 if ((to_remove_right != NULL) &&
1579 (to_remove_right->input_use_list() == NULL)) {
1580 to_remove_right->ReplaceUsesWith(flow_graph()->constant_null());
1581 to_remove_right->RemoveFromGraph();
1582 }
1583 return true;
1584 }
1585 return false;
1586 }
1587
1588
1484 static bool SmiFitsInDouble() { return kSmiBits < 53; } 1589 static bool SmiFitsInDouble() { return kSmiBits < 53; }
1485 1590
1486 bool FlowGraphOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, 1591 bool FlowGraphOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
1487 Token::Kind op_kind) { 1592 Token::Kind op_kind) {
1488 const ICData& ic_data = *call->ic_data(); 1593 const ICData& ic_data = *call->ic_data();
1489 ASSERT(ic_data.num_args_tested() == 2); 1594 ASSERT(ic_data.num_args_tested() == 2);
1490 1595
1491 ASSERT(call->ArgumentCount() == 2); 1596 ASSERT(call->ArgumentCount() == 2);
1492 Definition* left = call->ArgumentAt(0); 1597 Definition* left = call->ArgumentAt(0);
1493 Definition* right = call->ArgumentAt(1); 1598 Definition* right = call->ArgumentAt(1);
1494 1599
1495 intptr_t cid = kIllegalCid; 1600 intptr_t cid = kIllegalCid;
1496 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1601 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
1602 if (TryStringLengthOneEquality(call, op_kind)) {
1603 return true;
1604 } else {
1605 return false;
1606 }
1607 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1497 InsertBefore(call, 1608 InsertBefore(call,
1498 new CheckSmiInstr(new Value(left), call->deopt_id()), 1609 new CheckSmiInstr(new Value(left), call->deopt_id()),
1499 call->env(), 1610 call->env(),
1500 Definition::kEffect); 1611 Definition::kEffect);
1501 InsertBefore(call, 1612 InsertBefore(call,
1502 new CheckSmiInstr(new Value(right), call->deopt_id()), 1613 new CheckSmiInstr(new Value(right), call->deopt_id()),
1503 call->env(), 1614 call->env(),
1504 Definition::kEffect); 1615 Definition::kEffect);
1505 cid = kSmiCid; 1616 cid = kSmiCid;
1506 } else if (HasTwoMintOrSmi(ic_data) && 1617 } else if (HasTwoMintOrSmi(ic_data) &&
(...skipping 5149 matching lines...) Expand 10 before | Expand all | Expand 10 after
6656 } 6767 }
6657 6768
6658 6769
6659 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { 6770 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) {
6660 SetValue(instr, non_constant_); 6771 SetValue(instr, non_constant_);
6661 } 6772 }
6662 6773
6663 6774
6664 void ConstantPropagator::VisitStringFromCharCode( 6775 void ConstantPropagator::VisitStringFromCharCode(
6665 StringFromCharCodeInstr* instr) { 6776 StringFromCharCodeInstr* instr) {
6666 SetValue(instr, non_constant_); 6777 const Object& o = instr->char_code()->definition()->constant_value();
6778 if (o.IsNull() || IsNonConstant(o)) {
6779 SetValue(instr, non_constant_);
6780 } else if (IsConstant(o)) {
6781 const intptr_t ch_code = Smi::Cast(o).Value();
6782 ASSERT(ch_code >= 0);
6783 if (ch_code < Symbols::kMaxOneCharCodeSymbol) {
6784 RawString** table = Symbols::PredefinedAddress();
6785 SetValue(instr, String::ZoneHandle(table[ch_code]));
6786 } else {
6787 SetValue(instr, non_constant_);
6788 }
6789 }
6667 } 6790 }
6668 6791
6669 6792
6793 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) {
6794 const Object& o = instr->str()->definition()->constant_value();
6795 if (o.IsNull() || IsNonConstant(o)) {
6796 SetValue(instr, non_constant_);
6797 } else if (IsConstant(o)) {
6798 const String& str = String::Cast(o);
6799 const intptr_t result = (str.Length() == 1) ? str.CharAt(0) : -1;
6800 SetValue(instr, Smi::ZoneHandle(Smi::New(result)));
6801 }
6802 }
6803
6804
6805
6806
6670 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { 6807 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) {
6671 SetValue(instr, non_constant_); 6808 SetValue(instr, non_constant_);
6672 return; 6809 return;
6673 } 6810 }
6674 6811
6675 6812
6676 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { 6813 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) {
6677 const Object& array_obj = instr->array()->definition()->constant_value(); 6814 const Object& array_obj = instr->array()->definition()->constant_value();
6678 const Object& index_obj = instr->index()->definition()->constant_value(); 6815 const Object& index_obj = instr->index()->definition()->constant_value();
6679 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { 6816 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) {
(...skipping 1466 matching lines...) Expand 10 before | Expand all | Expand 10 after
8146 } 8283 }
8147 8284
8148 // Insert materializations at environment uses. 8285 // Insert materializations at environment uses.
8149 for (intptr_t i = 0; i < exits.length(); i++) { 8286 for (intptr_t i = 0; i < exits.length(); i++) {
8150 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 8287 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
8151 } 8288 }
8152 } 8289 }
8153 8290
8154 8291
8155 } // namespace dart 8292 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698