| OLD | NEW |
| 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/aot_optimizer.h" | 5 #include "vm/aot_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
| 9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 // from string-from-char-code instruction. | 782 // from string-from-char-code instruction. |
| 783 static bool IsLengthOneString(Definition* d) { | 783 static bool IsLengthOneString(Definition* d) { |
| 784 if (d->IsConstant()) { | 784 if (d->IsConstant()) { |
| 785 const Object& obj = d->AsConstant()->value(); | 785 const Object& obj = d->AsConstant()->value(); |
| 786 if (obj.IsString()) { | 786 if (obj.IsString()) { |
| 787 return String::Cast(obj).Length() == 1; | 787 return String::Cast(obj).Length() == 1; |
| 788 } else { | 788 } else { |
| 789 return false; | 789 return false; |
| 790 } | 790 } |
| 791 } else { | 791 } else { |
| 792 return d->IsStringFromCharCode(); | 792 return d->IsOneByteStringFromCharCode(); |
| 793 } | 793 } |
| 794 } | 794 } |
| 795 | 795 |
| 796 | 796 |
| 797 // Returns true if the string comparison was converted into char-code | 797 // Returns true if the string comparison was converted into char-code |
| 798 // comparison. Conversion is only possible for strings of length one. | 798 // comparison. Conversion is only possible for strings of length one. |
| 799 // E.g., detect str[x] == "x"; and use an integer comparison of char-codes. | 799 // E.g., detect str[x] == "x"; and use an integer comparison of char-codes. |
| 800 // TODO(srdjan): Expand for two-byte and external strings. | 800 // TODO(srdjan): Expand for two-byte and external strings. |
| 801 bool AotOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call, | 801 bool AotOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call, |
| 802 Token::Kind op_kind) { | 802 Token::Kind op_kind) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 816 if (IsLengthOneString(left)) { | 816 if (IsLengthOneString(left)) { |
| 817 // Optimize if left is a string with length one (either constant or | 817 // Optimize if left is a string with length one (either constant or |
| 818 // result of string-from-char-code. | 818 // result of string-from-char-code. |
| 819 if (left->IsConstant()) { | 819 if (left->IsConstant()) { |
| 820 ConstantInstr* left_const = left->AsConstant(); | 820 ConstantInstr* left_const = left->AsConstant(); |
| 821 const String& str = String::Cast(left_const->value()); | 821 const String& str = String::Cast(left_const->value()); |
| 822 ASSERT(str.Length() == 1); | 822 ASSERT(str.Length() == 1); |
| 823 ConstantInstr* char_code_left = flow_graph()->GetConstant( | 823 ConstantInstr* char_code_left = flow_graph()->GetConstant( |
| 824 Smi::ZoneHandle(Z, Smi::New(static_cast<intptr_t>(str.CharAt(0))))); | 824 Smi::ZoneHandle(Z, Smi::New(static_cast<intptr_t>(str.CharAt(0))))); |
| 825 left_val = new(Z) Value(char_code_left); | 825 left_val = new(Z) Value(char_code_left); |
| 826 } else if (left->IsStringFromCharCode()) { | 826 } else if (left->IsOneByteStringFromCharCode()) { |
| 827 // Use input of string-from-charcode as left value. | 827 // Use input of string-from-charcode as left value. |
| 828 StringFromCharCodeInstr* instr = left->AsStringFromCharCode(); | 828 OneByteStringFromCharCodeInstr* instr = |
| 829 left->AsOneByteStringFromCharCode(); |
| 829 left_val = new(Z) Value(instr->char_code()->definition()); | 830 left_val = new(Z) Value(instr->char_code()->definition()); |
| 830 to_remove_left = instr; | 831 to_remove_left = instr; |
| 831 } else { | 832 } else { |
| 832 // IsLengthOneString(left) should have been false. | 833 // IsLengthOneString(left) should have been false. |
| 833 UNREACHABLE(); | 834 UNREACHABLE(); |
| 834 } | 835 } |
| 835 | 836 |
| 836 Definition* to_remove_right = NULL; | 837 Definition* to_remove_right = NULL; |
| 837 Value* right_val = NULL; | 838 Value* right_val = NULL; |
| 838 if (right->IsStringFromCharCode()) { | 839 if (right->IsOneByteStringFromCharCode()) { |
| 839 // Skip string-from-char-code, and use its input as right value. | 840 // Skip string-from-char-code, and use its input as right value. |
| 840 StringFromCharCodeInstr* right_instr = right->AsStringFromCharCode(); | 841 OneByteStringFromCharCodeInstr* right_instr = |
| 842 right->AsOneByteStringFromCharCode(); |
| 841 right_val = new(Z) Value(right_instr->char_code()->definition()); | 843 right_val = new(Z) Value(right_instr->char_code()->definition()); |
| 842 to_remove_right = right_instr; | 844 to_remove_right = right_instr; |
| 843 } else { | 845 } else { |
| 844 const ICData& unary_checks_1 = | 846 const ICData& unary_checks_1 = |
| 845 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); | 847 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); |
| 846 AddCheckClass(right, | 848 AddCheckClass(right, |
| 847 unary_checks_1, | 849 unary_checks_1, |
| 848 call->deopt_id(), | 850 call->deopt_id(), |
| 849 call->env(), | 851 call->env(), |
| 850 call); | 852 call); |
| (...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1780 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( | 1782 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( |
| 1781 GrowableObjectArray::length_offset(), | 1783 GrowableObjectArray::length_offset(), |
| 1782 new(Z) Value(array), | 1784 new(Z) Value(array), |
| 1783 new(Z) Value(value), | 1785 new(Z) Value(value), |
| 1784 kNoStoreBarrier, | 1786 kNoStoreBarrier, |
| 1785 call->token_pos()); | 1787 call->token_pos()); |
| 1786 ReplaceCall(call, store); | 1788 ReplaceCall(call, store); |
| 1787 return true; | 1789 return true; |
| 1788 } | 1790 } |
| 1789 | 1791 |
| 1790 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 1792 if ((recognized_kind == MethodRecognizer::kOneByteStringCodeUnitAt) || |
| 1791 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 1793 (recognized_kind == MethodRecognizer::kTwoByteStringCodeUnitAt) || |
| 1792 (ic_data.NumberOfChecks() == 1) && | 1794 (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) || |
| 1793 ((class_ids[0] == kOneByteStringCid) || | 1795 (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt)) { |
| 1794 (class_ids[0] == kTwoByteStringCid))) { | 1796 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1797 ASSERT((class_ids[0] == kOneByteStringCid) || |
| 1798 (class_ids[0] == kTwoByteStringCid) || |
| 1799 (class_ids[0] == kExternalOneByteStringCid) || |
| 1800 (class_ids[0] == kExternalTwoByteStringCid)); |
| 1795 return TryReplaceInstanceCallWithInline(call); | 1801 return TryReplaceInstanceCallWithInline(call); |
| 1796 } | 1802 } |
| 1797 | 1803 |
| 1804 if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) && |
| 1805 (ic_data.NumberOfChecks() == 1)) { |
| 1806 ASSERT((class_ids[0] == kOneByteStringCid) || |
| 1807 (class_ids[0] == kTwoByteStringCid) || |
| 1808 (class_ids[0] == kExternalOneByteStringCid) || |
| 1809 (class_ids[0] == kExternalTwoByteStringCid)); |
| 1810 return TryReplaceInstanceCallWithInline(call); |
| 1811 } |
| 1812 |
| 1798 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 1813 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
| 1799 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 1814 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
| 1800 // This is an internal method, no need to check argument types nor | 1815 // This is an internal method, no need to check argument types nor |
| 1801 // range. | 1816 // range. |
| 1802 Definition* str = call->ArgumentAt(0); | 1817 Definition* str = call->ArgumentAt(0); |
| 1803 Definition* index = call->ArgumentAt(1); | 1818 Definition* index = call->ArgumentAt(1); |
| 1804 Definition* value = call->ArgumentAt(2); | 1819 Definition* value = call->ArgumentAt(2); |
| 1805 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr( | 1820 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr( |
| 1806 new(Z) Value(str), | 1821 new(Z) Value(str), |
| 1807 new(Z) Value(index), | 1822 new(Z) Value(index), |
| (...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2756 | 2771 |
| 2757 // Discard the environment from the original instruction because the store | 2772 // Discard the environment from the original instruction because the store |
| 2758 // can't deoptimize. | 2773 // can't deoptimize. |
| 2759 instr->RemoveEnvironment(); | 2774 instr->RemoveEnvironment(); |
| 2760 ReplaceCall(instr, store); | 2775 ReplaceCall(instr, store); |
| 2761 return true; | 2776 return true; |
| 2762 } | 2777 } |
| 2763 | 2778 |
| 2764 | 2779 |
| 2765 } // namespace dart | 2780 } // namespace dart |
| OLD | NEW |