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 |