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/jit_optimizer.h" | 5 #include "vm/jit_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 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 // from string-from-char-code instruction. | 748 // from string-from-char-code instruction. |
749 static bool IsLengthOneString(Definition* d) { | 749 static bool IsLengthOneString(Definition* d) { |
750 if (d->IsConstant()) { | 750 if (d->IsConstant()) { |
751 const Object& obj = d->AsConstant()->value(); | 751 const Object& obj = d->AsConstant()->value(); |
752 if (obj.IsString()) { | 752 if (obj.IsString()) { |
753 return String::Cast(obj).Length() == 1; | 753 return String::Cast(obj).Length() == 1; |
754 } else { | 754 } else { |
755 return false; | 755 return false; |
756 } | 756 } |
757 } else { | 757 } else { |
758 return d->IsStringFromCharCode(); | 758 return d->IsOneByteStringFromCharCode(); |
759 } | 759 } |
760 } | 760 } |
761 | 761 |
762 | 762 |
763 // Returns true if the string comparison was converted into char-code | 763 // Returns true if the string comparison was converted into char-code |
764 // comparison. Conversion is only possible for strings of length one. | 764 // comparison. Conversion is only possible for strings of length one. |
765 // E.g., detect str[x] == "x"; and use an integer comparison of char-codes. | 765 // E.g., detect str[x] == "x"; and use an integer comparison of char-codes. |
766 // TODO(srdjan): Expand for two-byte and external strings. | 766 // TODO(srdjan): Expand for two-byte and external strings. |
767 bool JitOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call, | 767 bool JitOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call, |
768 Token::Kind op_kind) { | 768 Token::Kind op_kind) { |
(...skipping 13 matching lines...) Expand all Loading... |
782 if (IsLengthOneString(left)) { | 782 if (IsLengthOneString(left)) { |
783 // Optimize if left is a string with length one (either constant or | 783 // Optimize if left is a string with length one (either constant or |
784 // result of string-from-char-code. | 784 // result of string-from-char-code. |
785 if (left->IsConstant()) { | 785 if (left->IsConstant()) { |
786 ConstantInstr* left_const = left->AsConstant(); | 786 ConstantInstr* left_const = left->AsConstant(); |
787 const String& str = String::Cast(left_const->value()); | 787 const String& str = String::Cast(left_const->value()); |
788 ASSERT(str.Length() == 1); | 788 ASSERT(str.Length() == 1); |
789 ConstantInstr* char_code_left = flow_graph()->GetConstant( | 789 ConstantInstr* char_code_left = flow_graph()->GetConstant( |
790 Smi::ZoneHandle(Z, Smi::New(static_cast<intptr_t>(str.CharAt(0))))); | 790 Smi::ZoneHandle(Z, Smi::New(static_cast<intptr_t>(str.CharAt(0))))); |
791 left_val = new(Z) Value(char_code_left); | 791 left_val = new(Z) Value(char_code_left); |
792 } else if (left->IsStringFromCharCode()) { | 792 } else if (left->IsOneByteStringFromCharCode()) { |
793 // Use input of string-from-charcode as left value. | 793 // Use input of string-from-charcode as left value. |
794 StringFromCharCodeInstr* instr = left->AsStringFromCharCode(); | 794 OneByteStringFromCharCodeInstr* instr = |
| 795 left->AsOneByteStringFromCharCode(); |
795 left_val = new(Z) Value(instr->char_code()->definition()); | 796 left_val = new(Z) Value(instr->char_code()->definition()); |
796 to_remove_left = instr; | 797 to_remove_left = instr; |
797 } else { | 798 } else { |
798 // IsLengthOneString(left) should have been false. | 799 // IsLengthOneString(left) should have been false. |
799 UNREACHABLE(); | 800 UNREACHABLE(); |
800 } | 801 } |
801 | 802 |
802 Definition* to_remove_right = NULL; | 803 Definition* to_remove_right = NULL; |
803 Value* right_val = NULL; | 804 Value* right_val = NULL; |
804 if (right->IsStringFromCharCode()) { | 805 if (right->IsOneByteStringFromCharCode()) { |
805 // Skip string-from-char-code, and use its input as right value. | 806 // Skip string-from-char-code, and use its input as right value. |
806 StringFromCharCodeInstr* right_instr = right->AsStringFromCharCode(); | 807 OneByteStringFromCharCodeInstr* right_instr = |
| 808 right->AsOneByteStringFromCharCode(); |
807 right_val = new(Z) Value(right_instr->char_code()->definition()); | 809 right_val = new(Z) Value(right_instr->char_code()->definition()); |
808 to_remove_right = right_instr; | 810 to_remove_right = right_instr; |
809 } else { | 811 } else { |
810 const ICData& unary_checks_1 = | 812 const ICData& unary_checks_1 = |
811 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); | 813 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); |
812 AddCheckClass(right, | 814 AddCheckClass(right, |
813 unary_checks_1, | 815 unary_checks_1, |
814 call->deopt_id(), | 816 call->deopt_id(), |
815 call->env(), | 817 call->env(), |
816 call); | 818 call); |
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1757 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( | 1759 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( |
1758 GrowableObjectArray::length_offset(), | 1760 GrowableObjectArray::length_offset(), |
1759 new(Z) Value(array), | 1761 new(Z) Value(array), |
1760 new(Z) Value(value), | 1762 new(Z) Value(value), |
1761 kNoStoreBarrier, | 1763 kNoStoreBarrier, |
1762 call->token_pos()); | 1764 call->token_pos()); |
1763 ReplaceCall(call, store); | 1765 ReplaceCall(call, store); |
1764 return true; | 1766 return true; |
1765 } | 1767 } |
1766 | 1768 |
1767 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 1769 if ((recognized_kind == MethodRecognizer::kOneByteStringCodeUnitAt) || |
1768 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 1770 (recognized_kind == MethodRecognizer::kTwoByteStringCodeUnitAt) || |
1769 (ic_data.NumberOfChecks() == 1) && | 1771 (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) || |
1770 ((class_ids[0] == kOneByteStringCid) || | 1772 (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt)) { |
1771 (class_ids[0] == kTwoByteStringCid))) { | 1773 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1774 ASSERT((class_ids[0] == kOneByteStringCid) || |
| 1775 (class_ids[0] == kTwoByteStringCid) || |
| 1776 (class_ids[0] == kExternalOneByteStringCid) || |
| 1777 (class_ids[0] == kExternalTwoByteStringCid)); |
1772 return TryReplaceInstanceCallWithInline(call); | 1778 return TryReplaceInstanceCallWithInline(call); |
1773 } | 1779 } |
1774 | 1780 |
| 1781 if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) && |
| 1782 (ic_data.NumberOfChecks() == 1)) { |
| 1783 ASSERT((class_ids[0] == kOneByteStringCid) || |
| 1784 (class_ids[0] == kTwoByteStringCid) || |
| 1785 (class_ids[0] == kExternalOneByteStringCid) || |
| 1786 (class_ids[0] == kExternalTwoByteStringCid)); |
| 1787 return TryReplaceInstanceCallWithInline(call); |
| 1788 } |
| 1789 |
1775 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 1790 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
1776 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 1791 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
1777 // This is an internal method, no need to check argument types nor | 1792 // This is an internal method, no need to check argument types nor |
1778 // range. | 1793 // range. |
1779 Definition* str = call->ArgumentAt(0); | 1794 Definition* str = call->ArgumentAt(0); |
1780 Definition* index = call->ArgumentAt(1); | 1795 Definition* index = call->ArgumentAt(1); |
1781 Definition* value = call->ArgumentAt(2); | 1796 Definition* value = call->ArgumentAt(2); |
1782 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr( | 1797 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr( |
1783 new(Z) Value(str), | 1798 new(Z) Value(str), |
1784 new(Z) Value(index), | 1799 new(Z) Value(index), |
(...skipping 1281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3066 | 3081 |
3067 // Discard the environment from the original instruction because the store | 3082 // Discard the environment from the original instruction because the store |
3068 // can't deoptimize. | 3083 // can't deoptimize. |
3069 instr->RemoveEnvironment(); | 3084 instr->RemoveEnvironment(); |
3070 ReplaceCall(instr, store); | 3085 ReplaceCall(instr, store); |
3071 return true; | 3086 return true; |
3072 } | 3087 } |
3073 | 3088 |
3074 | 3089 |
3075 } // namespace dart | 3090 } // namespace dart |
OLD | NEW |