OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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/regexp_assembler.h" | 5 #include "vm/regexp_assembler.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/compiler.h" | 8 #include "vm/compiler.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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 stack_ = Local(Symbols::stack()); | 151 stack_ = Local(Symbols::stack()); |
152 current_character_ = Local(Symbols::current_character()); | 152 current_character_ = Local(Symbols::current_character()); |
153 current_position_ = Local(Symbols::current_position()); | 153 current_position_ = Local(Symbols::current_position()); |
154 string_param_length_ = Local(Symbols::string_param_length()); | 154 string_param_length_ = Local(Symbols::string_param_length()); |
155 capture_length_ = Local(Symbols::capture_length()); | 155 capture_length_ = Local(Symbols::capture_length()); |
156 match_start_index_ = Local(Symbols::match_start_index()); | 156 match_start_index_ = Local(Symbols::match_start_index()); |
157 capture_start_index_ = Local(Symbols::capture_start_index()); | 157 capture_start_index_ = Local(Symbols::capture_start_index()); |
158 match_end_index_ = Local(Symbols::match_end_index()); | 158 match_end_index_ = Local(Symbols::match_end_index()); |
159 char_in_capture_ = Local(Symbols::char_in_capture()); | 159 char_in_capture_ = Local(Symbols::char_in_capture()); |
160 char_in_match_ = Local(Symbols::char_in_match()); | 160 char_in_match_ = Local(Symbols::char_in_match()); |
| 161 index_temp_ = Local(Symbols::index_temp()); |
161 result_ = Local(Symbols::result()); | 162 result_ = Local(Symbols::result()); |
162 | 163 |
163 string_param_ = Parameter(Symbols::string_param(), 0); | 164 string_param_ = Parameter(Symbols::string_param(), 0); |
164 start_index_param_ = Parameter(Symbols::start_index_param(), 1); | 165 start_index_param_ = Parameter(Symbols::start_index_param(), 1); |
165 | 166 |
166 // Reserve space for all captured group positions. Note that more might | 167 // Reserve space for all captured group positions. Note that more might |
167 // be created on the fly for internal use. | 168 // be created on the fly for internal use. |
168 for (intptr_t i = 0; i < position_registers_count_; i++) { | 169 for (intptr_t i = 0; i < position_registers_count_; i++) { |
169 position_register(i); | 170 position_register(i); |
170 } | 171 } |
(...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 pos_push = PushLocal(match_start_index_); | 938 pos_push = PushLocal(match_start_index_); |
938 len_push = PushLocal(capture_length_); | 939 len_push = PushLocal(capture_length_); |
939 StoreLocal(match_end_index_, Bind(Add(pos_push, len_push))); | 940 StoreLocal(match_end_index_, Bind(Add(pos_push, len_push))); |
940 | 941 |
941 BlockLabel success; | 942 BlockLabel success; |
942 if (mode_ == ASCII) { | 943 if (mode_ == ASCII) { |
943 BlockLabel loop_increment; | 944 BlockLabel loop_increment; |
944 BlockLabel loop; | 945 BlockLabel loop; |
945 BindBlock(&loop); | 946 BindBlock(&loop); |
946 | 947 |
947 StoreLocal(char_in_capture_, CharacterAt(LoadLocal(capture_start_index_))); | 948 StoreLocal(char_in_capture_, CharacterAt(capture_start_index_)); |
948 StoreLocal(char_in_match_, CharacterAt(LoadLocal(match_start_index_))); | 949 StoreLocal(char_in_match_, CharacterAt(match_start_index_)); |
949 | 950 |
950 BranchOrBacktrack(Comparison(kEQ, | 951 BranchOrBacktrack(Comparison(kEQ, |
951 LoadLocal(char_in_capture_), | 952 LoadLocal(char_in_capture_), |
952 LoadLocal(char_in_match_)), | 953 LoadLocal(char_in_match_)), |
953 &loop_increment); | 954 &loop_increment); |
954 | 955 |
955 // Mismatch, try case-insensitive match (converting letters to lower-case). | 956 // Mismatch, try case-insensitive match (converting letters to lower-case). |
956 PushArgumentInstr* match_char_push = PushLocal(char_in_match_); | 957 PushArgumentInstr* match_char_push = PushLocal(char_in_match_); |
957 PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(0x20))); | 958 PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(0x20))); |
958 StoreLocal(char_in_match_, | 959 StoreLocal(char_in_match_, |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1098 len_push = PushLocal(string_param_length_); | 1099 len_push = PushLocal(string_param_length_); |
1099 StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push))); | 1100 StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push))); |
1100 | 1101 |
1101 pos_push = PushLocal(match_start_index_); | 1102 pos_push = PushLocal(match_start_index_); |
1102 len_push = PushLocal(capture_length_); | 1103 len_push = PushLocal(capture_length_); |
1103 StoreLocal(match_end_index_, Bind(Add(pos_push, len_push))); | 1104 StoreLocal(match_end_index_, Bind(Add(pos_push, len_push))); |
1104 | 1105 |
1105 BlockLabel loop; | 1106 BlockLabel loop; |
1106 BindBlock(&loop); | 1107 BindBlock(&loop); |
1107 | 1108 |
1108 StoreLocal(char_in_capture_, CharacterAt(LoadLocal(capture_start_index_))); | 1109 StoreLocal(char_in_capture_, CharacterAt(capture_start_index_)); |
1109 StoreLocal(char_in_match_, CharacterAt(LoadLocal(match_start_index_))); | 1110 StoreLocal(char_in_match_, CharacterAt(match_start_index_)); |
1110 | 1111 |
1111 BranchOrBacktrack(Comparison(kNE, | 1112 BranchOrBacktrack(Comparison(kNE, |
1112 LoadLocal(char_in_capture_), | 1113 LoadLocal(char_in_capture_), |
1113 LoadLocal(char_in_match_)), | 1114 LoadLocal(char_in_match_)), |
1114 on_no_match); | 1115 on_no_match); |
1115 | 1116 |
1116 // Increment indexes into capture and match strings. | 1117 // Increment indexes into capture and match strings. |
1117 PushArgumentInstr* index_push = PushLocal(capture_start_index_); | 1118 PushArgumentInstr* index_push = PushLocal(capture_start_index_); |
1118 PushArgumentInstr* inc_push = PushArgument(Bind(Uint64Constant(1))); | 1119 PushArgumentInstr* inc_push = PushArgument(Bind(Uint64Constant(1))); |
1119 StoreLocal(capture_start_index_, Bind(Add(index_push, inc_push))); | 1120 StoreLocal(capture_start_index_, Bind(Add(index_push, inc_push))); |
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1758 TAG(); | 1759 TAG(); |
1759 | 1760 |
1760 ASSERT(characters == 1 || CanReadUnaligned()); | 1761 ASSERT(characters == 1 || CanReadUnaligned()); |
1761 if (mode_ == ASCII) { | 1762 if (mode_ == ASCII) { |
1762 ASSERT(characters == 1 || characters == 2 || characters == 4); | 1763 ASSERT(characters == 1 || characters == 2 || characters == 4); |
1763 } else { | 1764 } else { |
1764 ASSERT(mode_ == UC16); | 1765 ASSERT(mode_ == UC16); |
1765 ASSERT(characters == 1 || characters == 2); | 1766 ASSERT(characters == 1 || characters == 2); |
1766 } | 1767 } |
1767 | 1768 |
1768 // Bind the pattern as the load receiver. | |
1769 Value* pattern = BindLoadLocal(*string_param_); | |
1770 | |
1771 // Calculate the addressed string index as: | 1769 // Calculate the addressed string index as: |
1772 // cp_offset + current_position_ + string_param_length_ | 1770 // cp_offset + current_position_ + string_param_length_ |
1773 // TODO(zerny): Avoid generating 'add' instance-calls here. | 1771 // TODO(zerny): Avoid generating 'add' instance-calls here. |
1774 PushArgumentInstr* off_arg = | 1772 PushArgumentInstr* off_arg = |
1775 PushArgument(Bind(Int64Constant(cp_offset))); | 1773 PushArgument(Bind(Int64Constant(cp_offset))); |
1776 PushArgumentInstr* pos_arg = | 1774 PushArgumentInstr* pos_arg = |
1777 PushArgument(BindLoadLocal(*current_position_)); | 1775 PushArgument(BindLoadLocal(*current_position_)); |
1778 PushArgumentInstr* off_pos_arg = | 1776 PushArgumentInstr* off_pos_arg = |
1779 PushArgument(Bind(Add(off_arg, pos_arg))); | 1777 PushArgument(Bind(Add(off_arg, pos_arg))); |
1780 PushArgumentInstr* len_arg = | 1778 PushArgumentInstr* len_arg = |
1781 PushArgument(BindLoadLocal(*string_param_length_)); | 1779 PushArgument(BindLoadLocal(*string_param_length_)); |
1782 Value* index = Bind(Add(off_pos_arg, len_arg)); | 1780 // Index is stored in a temporary local so that we can later load it safely. |
| 1781 StoreLocal(index_temp_, Bind(Add(off_pos_arg, len_arg))); |
1783 | 1782 |
1784 // Load and store the code units. | 1783 // Load and store the code units. |
1785 Value* code_unit_value = LoadCodeUnitsAt(pattern, index, characters); | 1784 Value* code_unit_value = LoadCodeUnitsAt(index_temp_, characters); |
1786 StoreLocal(current_character_, code_unit_value); | 1785 StoreLocal(current_character_, code_unit_value); |
1787 PRINT(PushLocal(current_character_)); | 1786 PRINT(PushLocal(current_character_)); |
1788 } | 1787 } |
1789 | 1788 |
1790 | 1789 |
1791 Value* IRRegExpMacroAssembler::CharacterAt(Definition* index) { | 1790 Value* IRRegExpMacroAssembler::CharacterAt(LocalVariable* index) { |
1792 Value* pattern_val = BindLoadLocal(*string_param_); | 1791 return LoadCodeUnitsAt(index, 1); |
1793 Value* index_val = Bind(index); | |
1794 return LoadCodeUnitsAt(pattern_val, index_val, 1); | |
1795 } | 1792 } |
1796 | 1793 |
1797 | 1794 |
1798 // Note: We can't replace pattern with a load-local of string_param_ | 1795 Value* IRRegExpMacroAssembler::LoadCodeUnitsAt(LocalVariable* index, |
1799 // because we need to maintain the stack discipline in unoptimized code. | |
1800 Value* IRRegExpMacroAssembler::LoadCodeUnitsAt(Value* pattern, | |
1801 Value* index, | |
1802 intptr_t characters) { | 1796 intptr_t characters) { |
| 1797 // Bind the pattern as the load receiver. |
| 1798 Value* pattern_val = BindLoadLocal(*string_param_); |
| 1799 if (RawObject::IsExternalStringClassId(specialization_cid_)) { |
| 1800 // The data of an external string is stored through two indirections. |
| 1801 intptr_t external_offset; |
| 1802 intptr_t data_offset; |
| 1803 if (specialization_cid_ == kExternalOneByteStringCid) { |
| 1804 external_offset = ExternalOneByteString::external_data_offset(); |
| 1805 data_offset = RawExternalOneByteString::ExternalData::data_offset(); |
| 1806 } else if (specialization_cid_ == kExternalTwoByteStringCid) { |
| 1807 external_offset = ExternalTwoByteString::external_data_offset(); |
| 1808 data_offset = RawExternalTwoByteString::ExternalData::data_offset(); |
| 1809 } else { |
| 1810 UNREACHABLE(); |
| 1811 } |
| 1812 // This pushes untagged values on the stack which are immediately consumed: |
| 1813 // the first value is consumed to obtain the second value which is consumed |
| 1814 // by LoadCodeUnitsAtInstr below. |
| 1815 Value* external_val = |
| 1816 Bind(new(I) LoadUntaggedInstr(pattern_val, external_offset)); |
| 1817 pattern_val = |
| 1818 Bind(new(I) LoadUntaggedInstr(external_val, data_offset)); |
| 1819 } |
| 1820 |
| 1821 // Here pattern_val might be untagged so this must not trigger a GC. |
| 1822 Value* index_val = BindLoadLocal(*index); |
| 1823 |
1803 return Bind(new(I) LoadCodeUnitsInstr( | 1824 return Bind(new(I) LoadCodeUnitsInstr( |
1804 pattern, | 1825 pattern_val, |
1805 index, | 1826 index_val, |
1806 characters, | 1827 characters, |
1807 specialization_cid_, | 1828 specialization_cid_, |
1808 Scanner::kNoSourcePos)); | 1829 Scanner::kNoSourcePos)); |
1809 } | 1830 } |
1810 | 1831 |
1811 | 1832 |
1812 #undef __ | 1833 #undef __ |
1813 | 1834 |
1814 } // namespace dart | 1835 } // namespace dart |
OLD | NEW |