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 | 6 |
7 #include "src/builtins/builtins-constructor.h" | 7 #include "src/builtins/builtins-constructor.h" |
8 #include "src/builtins/builtins-utils.h" | 8 #include "src/builtins/builtins-utils.h" |
9 #include "src/builtins/builtins.h" | 9 #include "src/builtins/builtins.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), &out, | 209 Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), &out, |
210 &loop); | 210 &loop); |
211 } | 211 } |
212 } | 212 } |
213 | 213 |
214 Bind(&out); | 214 Bind(&out); |
215 return result; | 215 return result; |
216 } | 216 } |
217 | 217 |
218 void RegExpBuiltinsAssembler::GetStringPointers( | 218 void RegExpBuiltinsAssembler::GetStringPointers( |
219 Node* const string, Node* const offset, Node* const last_index, | 219 Node* const string_data, Node* const offset, Node* const last_index, |
220 Node* const string_length, bool is_one_byte, Variable* var_string_start, | 220 Node* const string_length, String::Encoding encoding, |
221 Variable* var_string_end) { | 221 Variable* var_string_start, Variable* var_string_end) { |
222 DCHECK_EQ(var_string_start->rep(), MachineType::PointerRepresentation()); | 222 DCHECK_EQ(var_string_start->rep(), MachineType::PointerRepresentation()); |
223 DCHECK_EQ(var_string_end->rep(), MachineType::PointerRepresentation()); | 223 DCHECK_EQ(var_string_end->rep(), MachineType::PointerRepresentation()); |
224 | 224 |
225 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 225 const ElementsKind kind = (encoding == String::ONE_BYTE_ENCODING) |
226 const int kHeaderSize = SeqOneByteString::kHeaderSize - kHeapObjectTag; | 226 ? UINT8_ELEMENTS |
227 const ElementsKind kind = is_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS; | 227 : UINT16_ELEMENTS; |
228 | 228 |
229 Node* const from_offset = ElementOffsetFromIndex( | 229 Node* const from_offset = ElementOffsetFromIndex( |
230 IntPtrAdd(offset, last_index), kind, INTPTR_PARAMETERS, kHeaderSize); | 230 IntPtrAdd(offset, last_index), kind, INTPTR_PARAMETERS); |
231 var_string_start->Bind(IntPtrAdd(string, from_offset)); | 231 var_string_start->Bind(IntPtrAdd(string_data, from_offset)); |
232 | 232 |
233 Node* const to_offset = ElementOffsetFromIndex( | 233 Node* const to_offset = ElementOffsetFromIndex( |
234 IntPtrAdd(offset, string_length), kind, INTPTR_PARAMETERS, kHeaderSize); | 234 IntPtrAdd(offset, string_length), kind, INTPTR_PARAMETERS); |
235 var_string_end->Bind(IntPtrAdd(string, to_offset)); | 235 var_string_end->Bind(IntPtrAdd(string_data, to_offset)); |
236 } | 236 } |
237 | 237 |
238 Node* RegExpBuiltinsAssembler::IrregexpExec(Node* const context, | 238 Node* RegExpBuiltinsAssembler::IrregexpExec(Node* const context, |
239 Node* const regexp, | 239 Node* const regexp, |
240 Node* const string, | 240 Node* const string, |
241 Node* const last_index, | 241 Node* const last_index, |
242 Node* const match_info) { | 242 Node* const match_info) { |
243 // Just jump directly to runtime if native RegExp is not selected at compile | 243 // Just jump directly to runtime if native RegExp is not selected at compile |
244 // time or if regexp entry in generated code is turned off runtime switch or | 244 // time or if regexp entry in generated code is turned off runtime switch or |
245 // at compilation. | 245 // at compilation. |
246 #ifdef V8_INTERPRETED_REGEXP | 246 #ifdef V8_INTERPRETED_REGEXP |
247 return CallRuntime(Runtime::kRegExpExec, context, regexp, string, last_index, | 247 return CallRuntime(Runtime::kRegExpExec, context, regexp, string, last_index, |
248 match_info); | 248 match_info); |
249 #else // V8_INTERPRETED_REGEXP | 249 #else // V8_INTERPRETED_REGEXP |
250 CSA_ASSERT(this, TaggedIsNotSmi(regexp)); | 250 CSA_ASSERT(this, TaggedIsNotSmi(regexp)); |
251 CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE)); | 251 CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE)); |
252 | 252 |
253 CSA_ASSERT(this, TaggedIsNotSmi(string)); | 253 CSA_ASSERT(this, TaggedIsNotSmi(string)); |
254 CSA_ASSERT(this, IsString(string)); | 254 CSA_ASSERT(this, IsString(string)); |
255 | 255 |
256 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(last_index))); | 256 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(last_index))); |
257 CSA_ASSERT(this, IsFixedArrayMap(LoadReceiverMap(match_info))); | 257 CSA_ASSERT(this, IsFixedArrayMap(LoadReceiverMap(match_info))); |
258 | 258 |
259 Node* const int_zero = IntPtrConstant(0); | 259 Node* const int_zero = IntPtrConstant(0); |
260 | 260 |
| 261 ToDirectStringAssembler to_direct(state(), string); |
| 262 |
261 Variable var_result(this, MachineRepresentation::kTagged); | 263 Variable var_result(this, MachineRepresentation::kTagged); |
262 Variable var_string(this, MachineType::PointerRepresentation(), int_zero); | |
263 Variable var_string_offset(this, MachineType::PointerRepresentation(), | |
264 int_zero); | |
265 Variable var_string_instance_type(this, MachineRepresentation::kWord32, | |
266 Int32Constant(0)); | |
267 | |
268 Label out(this), runtime(this, Label::kDeferred); | 264 Label out(this), runtime(this, Label::kDeferred); |
269 | 265 |
270 // External constants. | 266 // External constants. |
271 Node* const regexp_stack_memory_size_address = ExternalConstant( | 267 Node* const regexp_stack_memory_size_address = ExternalConstant( |
272 ExternalReference::address_of_regexp_stack_memory_size(isolate())); | 268 ExternalReference::address_of_regexp_stack_memory_size(isolate())); |
273 Node* const static_offsets_vector_address = ExternalConstant( | 269 Node* const static_offsets_vector_address = ExternalConstant( |
274 ExternalReference::address_of_static_offsets_vector(isolate())); | 270 ExternalReference::address_of_static_offsets_vector(isolate())); |
275 Node* const pending_exception_address = ExternalConstant( | 271 Node* const pending_exception_address = ExternalConstant( |
276 ExternalReference(Isolate::kPendingExceptionAddress, isolate())); | 272 ExternalReference(Isolate::kPendingExceptionAddress, isolate())); |
277 | 273 |
(...skipping 23 matching lines...) Expand all Loading... |
301 | 297 |
302 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); | 298 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
303 GotoIf(SmiAbove( | 299 GotoIf(SmiAbove( |
304 capture_count, | 300 capture_count, |
305 SmiConstant(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)), | 301 SmiConstant(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)), |
306 &runtime); | 302 &runtime); |
307 } | 303 } |
308 | 304 |
309 // Unpack the string if possible. | 305 // Unpack the string if possible. |
310 | 306 |
311 var_string.Bind(BitcastTaggedToWord(string)); | 307 to_direct.TryToDirect(&runtime); |
312 var_string_offset.Bind(int_zero); | |
313 var_string_instance_type.Bind(LoadInstanceType(string)); | |
314 | |
315 { | |
316 TryUnpackString(&var_string, &var_string_offset, &var_string_instance_type, | |
317 &runtime); | |
318 | |
319 // At this point, {var_string} may contain a faked sequential string (i.e. | |
320 // an external string with an adjusted offset) so we cannot assert | |
321 // IsString({var_string}). We also cannot allocate after this point since | |
322 // GC could move {var_string}'s underlying string. | |
323 } | |
324 | 308 |
325 Node* const smi_string_length = LoadStringLength(string); | 309 Node* const smi_string_length = LoadStringLength(string); |
326 | 310 |
327 // Bail out to runtime for invalid {last_index} values. | 311 // Bail out to runtime for invalid {last_index} values. |
328 GotoIfNot(TaggedIsSmi(last_index), &runtime); | 312 GotoIfNot(TaggedIsSmi(last_index), &runtime); |
329 GotoIf(SmiAboveOrEqual(last_index, smi_string_length), &runtime); | 313 GotoIf(SmiAboveOrEqual(last_index, smi_string_length), &runtime); |
330 | 314 |
331 // Load the irregexp code object and offsets into the subject string. Both | 315 // Load the irregexp code object and offsets into the subject string. Both |
332 // depend on whether the string is one- or two-byte. | 316 // depend on whether the string is one- or two-byte. |
333 | 317 |
334 Node* const int_last_index = SmiUntag(last_index); | 318 Node* const int_last_index = SmiUntag(last_index); |
335 | 319 |
336 Variable var_string_start(this, MachineType::PointerRepresentation()); | 320 Variable var_string_start(this, MachineType::PointerRepresentation()); |
337 Variable var_string_end(this, MachineType::PointerRepresentation()); | 321 Variable var_string_end(this, MachineType::PointerRepresentation()); |
338 Variable var_code(this, MachineRepresentation::kTagged); | 322 Variable var_code(this, MachineRepresentation::kTagged); |
339 | 323 |
340 { | 324 { |
341 Node* const int_string_length = SmiUntag(smi_string_length); | 325 Node* const int_string_length = SmiUntag(smi_string_length); |
342 | 326 Node* const direct_string_data = to_direct.PointerToData(&runtime); |
343 Node* const string_instance_type = var_string_instance_type.value(); | |
344 CSA_ASSERT(this, IsSequentialStringInstanceType(string_instance_type)); | |
345 | 327 |
346 Label next(this), if_isonebyte(this), if_istwobyte(this, Label::kDeferred); | 328 Label next(this), if_isonebyte(this), if_istwobyte(this, Label::kDeferred); |
347 Branch(IsOneByteStringInstanceType(string_instance_type), &if_isonebyte, | 329 Branch(IsOneByteStringInstanceType(to_direct.instance_type()), |
348 &if_istwobyte); | 330 &if_isonebyte, &if_istwobyte); |
349 | 331 |
350 Bind(&if_isonebyte); | 332 Bind(&if_isonebyte); |
351 { | 333 { |
352 const bool kIsOneByte = true; | 334 GetStringPointers(direct_string_data, to_direct.offset(), int_last_index, |
353 GetStringPointers(var_string.value(), var_string_offset.value(), | 335 int_string_length, String::ONE_BYTE_ENCODING, |
354 int_last_index, int_string_length, kIsOneByte, | |
355 &var_string_start, &var_string_end); | 336 &var_string_start, &var_string_end); |
356 var_code.Bind( | 337 var_code.Bind( |
357 LoadFixedArrayElement(data, JSRegExp::kIrregexpLatin1CodeIndex)); | 338 LoadFixedArrayElement(data, JSRegExp::kIrregexpLatin1CodeIndex)); |
358 Goto(&next); | 339 Goto(&next); |
359 } | 340 } |
360 | 341 |
361 Bind(&if_istwobyte); | 342 Bind(&if_istwobyte); |
362 { | 343 { |
363 const bool kIsOneByte = false; | 344 GetStringPointers(direct_string_data, to_direct.offset(), int_last_index, |
364 GetStringPointers(var_string.value(), var_string_offset.value(), | 345 int_string_length, String::TWO_BYTE_ENCODING, |
365 int_last_index, int_string_length, kIsOneByte, | |
366 &var_string_start, &var_string_end); | 346 &var_string_start, &var_string_end); |
367 var_code.Bind( | 347 var_code.Bind( |
368 LoadFixedArrayElement(data, JSRegExp::kIrregexpUC16CodeIndex)); | 348 LoadFixedArrayElement(data, JSRegExp::kIrregexpUC16CodeIndex)); |
369 Goto(&next); | 349 Goto(&next); |
370 } | 350 } |
371 | 351 |
372 Bind(&next); | 352 Bind(&next); |
373 } | 353 } |
374 | 354 |
375 // Check that the irregexp code has been generated for the actual string | 355 // Check that the irregexp code has been generated for the actual string |
(...skipping 2465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2841 Bind(&if_matched); | 2821 Bind(&if_matched); |
2842 { | 2822 { |
2843 Node* result = | 2823 Node* result = |
2844 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); | 2824 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
2845 Return(result); | 2825 Return(result); |
2846 } | 2826 } |
2847 } | 2827 } |
2848 | 2828 |
2849 } // namespace internal | 2829 } // namespace internal |
2850 } // namespace v8 | 2830 } // namespace v8 |
OLD | NEW |