| 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 |