OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/builtins/builtins-regexp.h" | 5 #include "src/builtins/builtins-regexp.h" |
6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
7 #include "src/builtins/builtins.h" | 7 #include "src/builtins/builtins.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stub-assembler.h" | 9 #include "src/code-stub-assembler.h" |
10 #include "src/regexp/regexp-utils.h" | 10 #include "src/regexp/regexp-utils.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 typedef CodeStubAssembler::ResultMode ResultMode; | 15 typedef CodeStubAssembler::ResultMode ResultMode; |
16 typedef CodeStubAssembler::RelationalComparisonMode RelationalComparisonMode; | 16 typedef CodeStubAssembler::RelationalComparisonMode RelationalComparisonMode; |
17 | 17 |
18 class StringBuiltinsAssembler : public CodeStubAssembler { | 18 class StringBuiltinsAssembler : public CodeStubAssembler { |
19 public: | 19 public: |
20 explicit StringBuiltinsAssembler(compiler::CodeAssemblerState* state) | 20 explicit StringBuiltinsAssembler(compiler::CodeAssemblerState* state) |
21 : CodeStubAssembler(state) {} | 21 : CodeStubAssembler(state) {} |
22 | 22 |
23 protected: | 23 protected: |
| 24 Node* DirectStringData(Node* string, Node* string_instance_type) { |
| 25 // Compute the effective offset of the first character. |
| 26 Variable var_data(this, MachineType::PointerRepresentation()); |
| 27 Label if_sequential(this), if_external(this), if_join(this); |
| 28 Branch(Word32Equal(Word32And(string_instance_type, |
| 29 Int32Constant(kStringRepresentationMask)), |
| 30 Int32Constant(kSeqStringTag)), |
| 31 &if_sequential, &if_external); |
| 32 |
| 33 Bind(&if_sequential); |
| 34 { |
| 35 var_data.Bind(IntPtrAdd( |
| 36 IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), |
| 37 BitcastTaggedToWord(string))); |
| 38 Goto(&if_join); |
| 39 } |
| 40 |
| 41 Bind(&if_external); |
| 42 { |
| 43 // This is only valid for ExternalStrings where the resource data |
| 44 // pointer is cached (i.e. no short external strings). |
| 45 CSA_ASSERT(this, Word32NotEqual( |
| 46 Word32And(string_instance_type, |
| 47 Int32Constant(kShortExternalStringMask)), |
| 48 Int32Constant(kShortExternalStringTag))); |
| 49 var_data.Bind(LoadObjectField(string, ExternalString::kResourceDataOffset, |
| 50 MachineType::Pointer())); |
| 51 Goto(&if_join); |
| 52 } |
| 53 |
| 54 Bind(&if_join); |
| 55 return var_data.value(); |
| 56 } |
| 57 |
24 Node* LoadOneByteChar(Node* string, Node* index) { | 58 Node* LoadOneByteChar(Node* string, Node* index) { |
25 return Load(MachineType::Uint8(), string, OneByteCharOffset(index)); | 59 return Load(MachineType::Uint8(), string, OneByteCharOffset(index)); |
26 } | 60 } |
27 | 61 |
28 Node* OneByteCharAddress(Node* string, Node* index) { | 62 Node* OneByteCharAddress(Node* string, Node* index) { |
29 Node* offset = OneByteCharOffset(index); | 63 Node* offset = OneByteCharOffset(index); |
30 return IntPtrAdd(BitcastTaggedToWord(string), offset); | 64 return IntPtrAdd(BitcastTaggedToWord(string), offset); |
31 } | 65 } |
32 | 66 |
33 Node* OneByteCharOffset(Node* index) { | 67 Node* OneByteCharOffset(Node* index) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 // Check if both {lhs} and {rhs} are internalized. Since we already know | 182 // Check if both {lhs} and {rhs} are internalized. Since we already know |
149 // that they're not the same object, they're not equal in that case. | 183 // that they're not the same object, they're not equal in that case. |
150 int const kBothInternalizedMask = | 184 int const kBothInternalizedMask = |
151 kIsNotInternalizedMask | (kIsNotInternalizedMask << 8); | 185 kIsNotInternalizedMask | (kIsNotInternalizedMask << 8); |
152 int const kBothInternalizedTag = kInternalizedTag | (kInternalizedTag << 8); | 186 int const kBothInternalizedTag = kInternalizedTag | (kInternalizedTag << 8); |
153 GotoIf(Word32Equal(Word32And(both_instance_types, | 187 GotoIf(Word32Equal(Word32And(both_instance_types, |
154 Int32Constant(kBothInternalizedMask)), | 188 Int32Constant(kBothInternalizedMask)), |
155 Int32Constant(kBothInternalizedTag)), | 189 Int32Constant(kBothInternalizedTag)), |
156 &if_notequal); | 190 &if_notequal); |
157 | 191 |
158 // Check that both {lhs} and {rhs} are flat one-byte strings. | 192 // Check that both {lhs} and {rhs} are flat one-byte strings, and that |
159 int const kBothSeqOneByteStringMask = | 193 // in case of ExternalStrings the data pointer is cached.. |
160 kStringEncodingMask | kStringRepresentationMask | | 194 STATIC_ASSERT(kShortExternalStringTag != 0); |
161 ((kStringEncodingMask | kStringRepresentationMask) << 8); | 195 int const kBothDirectOneByteStringMask = |
162 int const kBothSeqOneByteStringTag = | 196 kStringEncodingMask | kIsIndirectStringMask | kShortExternalStringMask | |
163 kOneByteStringTag | kSeqStringTag | | 197 ((kStringEncodingMask | kIsIndirectStringMask | kShortExternalStringMask) |
164 ((kOneByteStringTag | kSeqStringTag) << 8); | 198 << 8); |
165 Label if_bothonebyteseqstrings(this), if_notbothonebyteseqstrings(this); | 199 int const kBothDirectOneByteStringTag = |
| 200 kOneByteStringTag | (kOneByteStringTag << 8); |
| 201 Label if_bothdirectonebytestrings(this), if_notbothdirectonebytestrings(this); |
166 Branch(Word32Equal(Word32And(both_instance_types, | 202 Branch(Word32Equal(Word32And(both_instance_types, |
167 Int32Constant(kBothSeqOneByteStringMask)), | 203 Int32Constant(kBothDirectOneByteStringMask)), |
168 Int32Constant(kBothSeqOneByteStringTag)), | 204 Int32Constant(kBothDirectOneByteStringTag)), |
169 &if_bothonebyteseqstrings, &if_notbothonebyteseqstrings); | 205 &if_bothdirectonebytestrings, &if_notbothdirectonebytestrings); |
170 | 206 |
171 Bind(&if_bothonebyteseqstrings); | 207 Bind(&if_bothdirectonebytestrings); |
172 { | 208 { |
173 // Compute the effective offset of the first character. | 209 // Compute the effective offset of the first character. |
174 Node* begin = | 210 Node* lhs_data = DirectStringData(lhs, lhs_instance_type); |
175 IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag); | 211 Node* rhs_data = DirectStringData(rhs, rhs_instance_type); |
176 | 212 |
177 // Compute the first offset after the string from the length. | 213 // Compute the first offset after the string from the length. |
178 Node* end = IntPtrAdd(begin, SmiUntag(lhs_length)); | 214 Node* length = SmiUntag(lhs_length); |
179 | 215 |
180 // Loop over the {lhs} and {rhs} strings to see if they are equal. | 216 // Loop over the {lhs} and {rhs} strings to see if they are equal. |
181 Variable var_offset(this, MachineType::PointerRepresentation()); | 217 Variable var_offset(this, MachineType::PointerRepresentation()); |
182 Label loop(this, &var_offset); | 218 Label loop(this, &var_offset); |
183 var_offset.Bind(begin); | 219 var_offset.Bind(IntPtrConstant(0)); |
184 Goto(&loop); | 220 Goto(&loop); |
185 Bind(&loop); | 221 Bind(&loop); |
186 { | 222 { |
187 // If {offset} equals {end}, no difference was found, so the | 223 // If {offset} equals {end}, no difference was found, so the |
188 // strings are equal. | 224 // strings are equal. |
189 Node* offset = var_offset.value(); | 225 Node* offset = var_offset.value(); |
190 GotoIf(WordEqual(offset, end), &if_equal); | 226 GotoIf(WordEqual(offset, length), &if_equal); |
191 | 227 |
192 // Load the next characters from {lhs} and {rhs}. | 228 // Load the next characters from {lhs} and {rhs}. |
193 Node* lhs_value = Load(MachineType::Uint8(), lhs, offset); | 229 Node* lhs_value = Load(MachineType::Uint8(), lhs_data, offset); |
194 Node* rhs_value = Load(MachineType::Uint8(), rhs, offset); | 230 Node* rhs_value = Load(MachineType::Uint8(), rhs_data, offset); |
195 | 231 |
196 // Check if the characters match. | 232 // Check if the characters match. |
197 GotoIf(Word32NotEqual(lhs_value, rhs_value), &if_notequal); | 233 GotoIf(Word32NotEqual(lhs_value, rhs_value), &if_notequal); |
198 | 234 |
199 // Advance to next character. | 235 // Advance to next character. |
200 var_offset.Bind(IntPtrAdd(offset, IntPtrConstant(1))); | 236 var_offset.Bind(IntPtrAdd(offset, IntPtrConstant(1))); |
201 Goto(&loop); | 237 Goto(&loop); |
202 } | 238 } |
203 } | 239 } |
204 | 240 |
205 Bind(&if_notbothonebyteseqstrings); | 241 Bind(&if_notbothdirectonebytestrings); |
206 { | 242 { |
207 // Try to unwrap indirect strings, restart the above attempt on success. | 243 // Try to unwrap indirect strings, restart the above attempt on success. |
208 MaybeDerefIndirectStrings(&var_left, lhs_instance_type, &var_right, | 244 MaybeDerefIndirectStrings(&var_left, lhs_instance_type, &var_right, |
209 rhs_instance_type, &restart); | 245 rhs_instance_type, &restart); |
210 // TODO(bmeurer): Add support for two byte string equality checks. | 246 // TODO(bmeurer): Add support for two byte string equality checks. |
211 | 247 |
212 Runtime::FunctionId function_id = (mode == ResultMode::kDontNegateResult) | 248 Runtime::FunctionId function_id = (mode == ResultMode::kDontNegateResult) |
213 ? Runtime::kStringEqual | 249 ? Runtime::kStringEqual |
214 : Runtime::kStringNotEqual; | 250 : Runtime::kStringNotEqual; |
215 TailCallRuntime(function_id, context, lhs, rhs); | 251 TailCallRuntime(function_id, context, lhs, rhs); |
(...skipping 1655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1871 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, | 1907 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, |
1872 HeapConstant(factory()->NewStringFromAsciiChecked( | 1908 HeapConstant(factory()->NewStringFromAsciiChecked( |
1873 "String Iterator.prototype.next", TENURED)), | 1909 "String Iterator.prototype.next", TENURED)), |
1874 iterator); | 1910 iterator); |
1875 Return(result); // Never reached. | 1911 Return(result); // Never reached. |
1876 } | 1912 } |
1877 } | 1913 } |
1878 | 1914 |
1879 } // namespace internal | 1915 } // namespace internal |
1880 } // namespace v8 | 1916 } // namespace v8 |
OLD | NEW |