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

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

Issue 119673004: Version 1.1.0-dev.5.2 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 11 months 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 | « dart/runtime/vm/flow_graph_optimizer.h ('k') | dart/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 23 matching lines...) Expand all
34 "Print constant propagation and useless code elimination."); 34 "Print constant propagation and useless code elimination.");
35 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); 35 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details.");
36 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); 36 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress");
37 DEFINE_FLAG(bool, truncating_left_shift, true, 37 DEFINE_FLAG(bool, truncating_left_shift, true,
38 "Optimize left shift to truncate if possible"); 38 "Optimize left shift to truncate if possible");
39 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); 39 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis.");
40 DEFINE_FLAG(bool, trace_load_optimization, false, 40 DEFINE_FLAG(bool, trace_load_optimization, false,
41 "Print live sets for load optimization pass."); 41 "Print live sets for load optimization pass.");
42 DEFINE_FLAG(bool, enable_simd_inline, true, 42 DEFINE_FLAG(bool, enable_simd_inline, true,
43 "Enable inlining of SIMD related method calls."); 43 "Enable inlining of SIMD related method calls.");
44 DEFINE_FLAG(int, getter_setter_ratio, 10, 44 DEFINE_FLAG(int, getter_setter_ratio, 13,
45 "Ratio of getter/setter usage used for double field unboxing heuristics"); 45 "Ratio of getter/setter usage used for double field unboxing heuristics");
46 DECLARE_FLAG(bool, eliminate_type_checks); 46 DECLARE_FLAG(bool, eliminate_type_checks);
47 DECLARE_FLAG(bool, enable_type_checks); 47 DECLARE_FLAG(bool, enable_type_checks);
48 DECLARE_FLAG(bool, trace_type_check_elimination); 48 DECLARE_FLAG(bool, trace_type_check_elimination);
49 49
50 50
51 static bool ShouldInlineSimd() { 51 static bool ShouldInlineSimd() {
52 #if defined(TARGET_ARCH_MIPS) 52 #if defined(TARGET_ARCH_MIPS)
53 return false; 53 return false;
54 #elif defined(TARGET_ARCH_ARM) 54 #elif defined(TARGET_ARCH_ARM)
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 } 117 }
118 GrowableArray<intptr_t> class_ids(call->ic_data()->num_args_tested()); 118 GrowableArray<intptr_t> class_ids(call->ic_data()->num_args_tested());
119 ASSERT(call->ic_data()->num_args_tested() <= call->ArgumentCount()); 119 ASSERT(call->ic_data()->num_args_tested() <= call->ArgumentCount());
120 for (intptr_t i = 0; i < call->ic_data()->num_args_tested(); i++) { 120 for (intptr_t i = 0; i < call->ic_data()->num_args_tested(); i++) {
121 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid(); 121 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid();
122 class_ids.Add(cid); 122 class_ids.Add(cid);
123 } 123 }
124 124
125 const Token::Kind op_kind = call->token_kind(); 125 const Token::Kind op_kind = call->token_kind();
126 if (Token::IsRelationalOperator(op_kind) || 126 if (Token::IsRelationalOperator(op_kind) ||
127 Token::IsRelationalOperator(op_kind) || 127 Token::IsEqualityOperator(op_kind) ||
128 Token::IsBinaryOperator(op_kind)) { 128 Token::IsBinaryOperator(op_kind)) {
129 // Guess cid: if one of the inputs is a number assume that the other 129 // Guess cid: if one of the inputs is a number assume that the other
130 // is a number of same type. 130 // is a number of same type.
131 const intptr_t cid_0 = class_ids[0]; 131 const intptr_t cid_0 = class_ids[0];
132 const intptr_t cid_1 = class_ids[1]; 132 const intptr_t cid_1 = class_ids[1];
133 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { 133 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) {
134 class_ids[0] = cid_1; 134 class_ids[0] = cid_1;
135 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { 135 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) {
136 class_ids[1] = cid_0; 136 class_ids[1] = cid_0;
137 } 137 }
(...skipping 1336 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 1799 matching lines...) Expand 10 before | Expand all | Expand 10 after
3306 if (as_bool.raw() == Bool::True().raw()) { 3417 if (as_bool.raw() == Bool::True().raw()) {
3307 AddReceiverCheck(call); 3418 AddReceiverCheck(call);
3308 // Remove the original push arguments. 3419 // Remove the original push arguments.
3309 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 3420 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
3310 PushArgumentInstr* push = call->PushArgumentAt(i); 3421 PushArgumentInstr* push = call->PushArgumentAt(i);
3311 push->ReplaceUsesWith(push->value()->definition()); 3422 push->ReplaceUsesWith(push->value()->definition());
3312 push->RemoveFromGraph(); 3423 push->RemoveFromGraph();
3313 } 3424 }
3314 // Remove call, replace it with 'left'. 3425 // Remove call, replace it with 'left'.
3315 call->ReplaceUsesWith(left); 3426 call->ReplaceUsesWith(left);
3316 call->RemoveFromGraph(); 3427 ASSERT(current_iterator()->Current() == call);
3428 current_iterator()->RemoveCurrentFromGraph();
3317 return; 3429 return;
3318 } 3430 }
3319 } 3431 }
3320 const String& dst_name = String::ZoneHandle( 3432 const String& dst_name = String::ZoneHandle(
3321 Symbols::New(Exceptions::kCastErrorDstName)); 3433 Symbols::New(Exceptions::kCastErrorDstName));
3322 AssertAssignableInstr* assert_as = 3434 AssertAssignableInstr* assert_as =
3323 new AssertAssignableInstr(call->token_pos(), 3435 new AssertAssignableInstr(call->token_pos(),
3324 new Value(left), 3436 new Value(left),
3325 new Value(instantiator), 3437 new Value(instantiator),
3326 new Value(type_args), 3438 new Value(type_args),
(...skipping 3327 matching lines...) Expand 10 before | Expand all | Expand 10 after
6654 } 6766 }
6655 } 6767 }
6656 } 6768 }
6657 6769
6658 6770
6659 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { 6771 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) {
6660 SetValue(instr, non_constant_); 6772 SetValue(instr, non_constant_);
6661 } 6773 }
6662 6774
6663 6775
6776 void ConstantPropagator::VisitDebugStepCheck(DebugStepCheckInstr* instr) {
6777 // Nothing to do.
6778 }
6779
6780
6664 void ConstantPropagator::VisitStringFromCharCode( 6781 void ConstantPropagator::VisitStringFromCharCode(
6665 StringFromCharCodeInstr* instr) { 6782 StringFromCharCodeInstr* instr) {
6666 SetValue(instr, non_constant_); 6783 const Object& o = instr->char_code()->definition()->constant_value();
6784 if (o.IsNull() || IsNonConstant(o)) {
6785 SetValue(instr, non_constant_);
6786 } else if (IsConstant(o)) {
6787 const intptr_t ch_code = Smi::Cast(o).Value();
6788 ASSERT(ch_code >= 0);
6789 if (ch_code < Symbols::kMaxOneCharCodeSymbol) {
6790 RawString** table = Symbols::PredefinedAddress();
6791 SetValue(instr, String::ZoneHandle(table[ch_code]));
6792 } else {
6793 SetValue(instr, non_constant_);
6794 }
6795 }
6667 } 6796 }
6668 6797
6669 6798
6799 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) {
6800 const Object& o = instr->str()->definition()->constant_value();
6801 if (o.IsNull() || IsNonConstant(o)) {
6802 SetValue(instr, non_constant_);
6803 } else if (IsConstant(o)) {
6804 const String& str = String::Cast(o);
6805 const intptr_t result = (str.Length() == 1) ? str.CharAt(0) : -1;
6806 SetValue(instr, Smi::ZoneHandle(Smi::New(result)));
6807 }
6808 }
6809
6810
6811
6812
6670 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { 6813 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) {
6671 SetValue(instr, non_constant_); 6814 SetValue(instr, non_constant_);
6672 return; 6815 return;
6673 } 6816 }
6674 6817
6675 6818
6676 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { 6819 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) {
6677 const Object& array_obj = instr->array()->definition()->constant_value(); 6820 const Object& array_obj = instr->array()->definition()->constant_value();
6678 const Object& index_obj = instr->index()->definition()->constant_value(); 6821 const Object& index_obj = instr->index()->definition()->constant_value();
6679 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { 6822 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) {
(...skipping 1466 matching lines...) Expand 10 before | Expand all | Expand 10 after
8146 } 8289 }
8147 8290
8148 // Insert materializations at environment uses. 8291 // Insert materializations at environment uses.
8149 for (intptr_t i = 0; i < exits.length(); i++) { 8292 for (intptr_t i = 0; i < exits.length(); i++) {
8150 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 8293 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
8151 } 8294 }
8152 } 8295 }
8153 8296
8154 8297
8155 } // namespace dart 8298 } // namespace dart
OLDNEW
« no previous file with comments | « dart/runtime/vm/flow_graph_optimizer.h ('k') | dart/runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698