OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/ast.h" | 7 #include "src/ast.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/compilation-cache.h" | 9 #include "src/compilation-cache.h" |
10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); | 90 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); |
91 Handle<Object> regexp_err = factory->NewSyntaxError(message, array); | 91 Handle<Object> regexp_err = factory->NewSyntaxError(message, array); |
92 return isolate->Throw<Object>(regexp_err); | 92 return isolate->Throw<Object>(regexp_err); |
93 } | 93 } |
94 | 94 |
95 | 95 |
96 ContainedInLattice AddRange(ContainedInLattice containment, | 96 ContainedInLattice AddRange(ContainedInLattice containment, |
97 const int* ranges, | 97 const int* ranges, |
98 int ranges_length, | 98 int ranges_length, |
99 Interval new_range) { | 99 Interval new_range) { |
100 ASSERT((ranges_length & 1) == 1); | 100 DCHECK((ranges_length & 1) == 1); |
101 ASSERT(ranges[ranges_length - 1] == String::kMaxUtf16CodeUnit + 1); | 101 DCHECK(ranges[ranges_length - 1] == String::kMaxUtf16CodeUnit + 1); |
102 if (containment == kLatticeUnknown) return containment; | 102 if (containment == kLatticeUnknown) return containment; |
103 bool inside = false; | 103 bool inside = false; |
104 int last = 0; | 104 int last = 0; |
105 for (int i = 0; i < ranges_length; inside = !inside, last = ranges[i], i++) { | 105 for (int i = 0; i < ranges_length; inside = !inside, last = ranges[i], i++) { |
106 // Consider the range from last to ranges[i]. | 106 // Consider the range from last to ranges[i]. |
107 // We haven't got to the new range yet. | 107 // We haven't got to the new range yet. |
108 if (ranges[i] <= new_range.from()) continue; | 108 if (ranges[i] <= new_range.from()) continue; |
109 // New range is wholly inside last-ranges[i]. Note that new_range.to() is | 109 // New range is wholly inside last-ranges[i]. Note that new_range.to() is |
110 // inclusive, but the values in ranges are not. | 110 // inclusive, but the values in ranges are not. |
111 if (last <= new_range.from() && new_range.to() < ranges[i]) { | 111 if (last <= new_range.from() && new_range.to() < ranges[i]) { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 isolate->factory()->NewStringFromTwoByte(atom_pattern), | 200 isolate->factory()->NewStringFromTwoByte(atom_pattern), |
201 Object); | 201 Object); |
202 if (!HasFewDifferentCharacters(atom_string)) { | 202 if (!HasFewDifferentCharacters(atom_string)) { |
203 AtomCompile(re, pattern, flags, atom_string); | 203 AtomCompile(re, pattern, flags, atom_string); |
204 has_been_compiled = true; | 204 has_been_compiled = true; |
205 } | 205 } |
206 } | 206 } |
207 if (!has_been_compiled) { | 207 if (!has_been_compiled) { |
208 IrregexpInitialize(re, pattern, flags, parse_result.capture_count); | 208 IrregexpInitialize(re, pattern, flags, parse_result.capture_count); |
209 } | 209 } |
210 ASSERT(re->data()->IsFixedArray()); | 210 DCHECK(re->data()->IsFixedArray()); |
211 // Compilation succeeded so the data is set on the regexp | 211 // Compilation succeeded so the data is set on the regexp |
212 // and we can store it in the cache. | 212 // and we can store it in the cache. |
213 Handle<FixedArray> data(FixedArray::cast(re->data())); | 213 Handle<FixedArray> data(FixedArray::cast(re->data())); |
214 compilation_cache->PutRegExp(pattern, flags, data); | 214 compilation_cache->PutRegExp(pattern, flags, data); |
215 | 215 |
216 return re; | 216 return re; |
217 } | 217 } |
218 | 218 |
219 | 219 |
220 MaybeHandle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp, | 220 MaybeHandle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 } | 262 } |
263 | 263 |
264 | 264 |
265 int RegExpImpl::AtomExecRaw(Handle<JSRegExp> regexp, | 265 int RegExpImpl::AtomExecRaw(Handle<JSRegExp> regexp, |
266 Handle<String> subject, | 266 Handle<String> subject, |
267 int index, | 267 int index, |
268 int32_t* output, | 268 int32_t* output, |
269 int output_size) { | 269 int output_size) { |
270 Isolate* isolate = regexp->GetIsolate(); | 270 Isolate* isolate = regexp->GetIsolate(); |
271 | 271 |
272 ASSERT(0 <= index); | 272 DCHECK(0 <= index); |
273 ASSERT(index <= subject->length()); | 273 DCHECK(index <= subject->length()); |
274 | 274 |
275 subject = String::Flatten(subject); | 275 subject = String::Flatten(subject); |
276 DisallowHeapAllocation no_gc; // ensure vectors stay valid | 276 DisallowHeapAllocation no_gc; // ensure vectors stay valid |
277 | 277 |
278 String* needle = String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)); | 278 String* needle = String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)); |
279 int needle_len = needle->length(); | 279 int needle_len = needle->length(); |
280 ASSERT(needle->IsFlat()); | 280 DCHECK(needle->IsFlat()); |
281 ASSERT_LT(0, needle_len); | 281 DCHECK_LT(0, needle_len); |
282 | 282 |
283 if (index + needle_len > subject->length()) { | 283 if (index + needle_len > subject->length()) { |
284 return RegExpImpl::RE_FAILURE; | 284 return RegExpImpl::RE_FAILURE; |
285 } | 285 } |
286 | 286 |
287 for (int i = 0; i < output_size; i += 2) { | 287 for (int i = 0; i < output_size; i += 2) { |
288 String::FlatContent needle_content = needle->GetFlatContent(); | 288 String::FlatContent needle_content = needle->GetFlatContent(); |
289 String::FlatContent subject_content = subject->GetFlatContent(); | 289 String::FlatContent subject_content = subject->GetFlatContent(); |
290 ASSERT(needle_content.IsFlat()); | 290 DCHECK(needle_content.IsFlat()); |
291 ASSERT(subject_content.IsFlat()); | 291 DCHECK(subject_content.IsFlat()); |
292 // dispatch on type of strings | 292 // dispatch on type of strings |
293 index = (needle_content.IsAscii() | 293 index = (needle_content.IsAscii() |
294 ? (subject_content.IsAscii() | 294 ? (subject_content.IsAscii() |
295 ? SearchString(isolate, | 295 ? SearchString(isolate, |
296 subject_content.ToOneByteVector(), | 296 subject_content.ToOneByteVector(), |
297 needle_content.ToOneByteVector(), | 297 needle_content.ToOneByteVector(), |
298 index) | 298 index) |
299 : SearchString(isolate, | 299 : SearchString(isolate, |
300 subject_content.ToUC16Vector(), | 300 subject_content.ToUC16Vector(), |
301 needle_content.ToOneByteVector(), | 301 needle_content.ToOneByteVector(), |
(...skipping 26 matching lines...) Expand all Loading... |
328 Isolate* isolate = re->GetIsolate(); | 328 Isolate* isolate = re->GetIsolate(); |
329 | 329 |
330 static const int kNumRegisters = 2; | 330 static const int kNumRegisters = 2; |
331 STATIC_ASSERT(kNumRegisters <= Isolate::kJSRegexpStaticOffsetsVectorSize); | 331 STATIC_ASSERT(kNumRegisters <= Isolate::kJSRegexpStaticOffsetsVectorSize); |
332 int32_t* output_registers = isolate->jsregexp_static_offsets_vector(); | 332 int32_t* output_registers = isolate->jsregexp_static_offsets_vector(); |
333 | 333 |
334 int res = AtomExecRaw(re, subject, index, output_registers, kNumRegisters); | 334 int res = AtomExecRaw(re, subject, index, output_registers, kNumRegisters); |
335 | 335 |
336 if (res == RegExpImpl::RE_FAILURE) return isolate->factory()->null_value(); | 336 if (res == RegExpImpl::RE_FAILURE) return isolate->factory()->null_value(); |
337 | 337 |
338 ASSERT_EQ(res, RegExpImpl::RE_SUCCESS); | 338 DCHECK_EQ(res, RegExpImpl::RE_SUCCESS); |
339 SealHandleScope shs(isolate); | 339 SealHandleScope shs(isolate); |
340 FixedArray* array = FixedArray::cast(last_match_info->elements()); | 340 FixedArray* array = FixedArray::cast(last_match_info->elements()); |
341 SetAtomLastCapture(array, *subject, output_registers[0], output_registers[1]); | 341 SetAtomLastCapture(array, *subject, output_registers[0], output_registers[1]); |
342 return last_match_info; | 342 return last_match_info; |
343 } | 343 } |
344 | 344 |
345 | 345 |
346 // Irregexp implementation. | 346 // Irregexp implementation. |
347 | 347 |
348 // Ensures that the regexp object contains a compiled version of the | 348 // Ensures that the regexp object contains a compiled version of the |
349 // source for either ASCII or non-ASCII strings. | 349 // source for either ASCII or non-ASCII strings. |
350 // If the compiled version doesn't already exist, it is compiled | 350 // If the compiled version doesn't already exist, it is compiled |
351 // from the source pattern. | 351 // from the source pattern. |
352 // If compilation fails, an exception is thrown and this function | 352 // If compilation fails, an exception is thrown and this function |
353 // returns false. | 353 // returns false. |
354 bool RegExpImpl::EnsureCompiledIrregexp( | 354 bool RegExpImpl::EnsureCompiledIrregexp( |
355 Handle<JSRegExp> re, Handle<String> sample_subject, bool is_ascii) { | 355 Handle<JSRegExp> re, Handle<String> sample_subject, bool is_ascii) { |
356 Object* compiled_code = re->DataAt(JSRegExp::code_index(is_ascii)); | 356 Object* compiled_code = re->DataAt(JSRegExp::code_index(is_ascii)); |
357 #ifdef V8_INTERPRETED_REGEXP | 357 #ifdef V8_INTERPRETED_REGEXP |
358 if (compiled_code->IsByteArray()) return true; | 358 if (compiled_code->IsByteArray()) return true; |
359 #else // V8_INTERPRETED_REGEXP (RegExp native code) | 359 #else // V8_INTERPRETED_REGEXP (RegExp native code) |
360 if (compiled_code->IsCode()) return true; | 360 if (compiled_code->IsCode()) return true; |
361 #endif | 361 #endif |
362 // We could potentially have marked this as flushable, but have kept | 362 // We could potentially have marked this as flushable, but have kept |
363 // a saved version if we did not flush it yet. | 363 // a saved version if we did not flush it yet. |
364 Object* saved_code = re->DataAt(JSRegExp::saved_code_index(is_ascii)); | 364 Object* saved_code = re->DataAt(JSRegExp::saved_code_index(is_ascii)); |
365 if (saved_code->IsCode()) { | 365 if (saved_code->IsCode()) { |
366 // Reinstate the code in the original place. | 366 // Reinstate the code in the original place. |
367 re->SetDataAt(JSRegExp::code_index(is_ascii), saved_code); | 367 re->SetDataAt(JSRegExp::code_index(is_ascii), saved_code); |
368 ASSERT(compiled_code->IsSmi()); | 368 DCHECK(compiled_code->IsSmi()); |
369 return true; | 369 return true; |
370 } | 370 } |
371 return CompileIrregexp(re, sample_subject, is_ascii); | 371 return CompileIrregexp(re, sample_subject, is_ascii); |
372 } | 372 } |
373 | 373 |
374 | 374 |
375 static bool CreateRegExpErrorObjectAndThrow(Handle<JSRegExp> re, | 375 static bool CreateRegExpErrorObjectAndThrow(Handle<JSRegExp> re, |
376 bool is_ascii, | 376 bool is_ascii, |
377 Handle<String> error_message, | 377 Handle<String> error_message, |
378 Isolate* isolate) { | 378 Isolate* isolate) { |
(...skipping 15 matching lines...) Expand all Loading... |
394 // Compile the RegExp. | 394 // Compile the RegExp. |
395 Isolate* isolate = re->GetIsolate(); | 395 Isolate* isolate = re->GetIsolate(); |
396 Zone zone(isolate); | 396 Zone zone(isolate); |
397 PostponeInterruptsScope postpone(isolate); | 397 PostponeInterruptsScope postpone(isolate); |
398 // If we had a compilation error the last time this is saved at the | 398 // If we had a compilation error the last time this is saved at the |
399 // saved code index. | 399 // saved code index. |
400 Object* entry = re->DataAt(JSRegExp::code_index(is_ascii)); | 400 Object* entry = re->DataAt(JSRegExp::code_index(is_ascii)); |
401 // When arriving here entry can only be a smi, either representing an | 401 // When arriving here entry can only be a smi, either representing an |
402 // uncompiled regexp, a previous compilation error, or code that has | 402 // uncompiled regexp, a previous compilation error, or code that has |
403 // been flushed. | 403 // been flushed. |
404 ASSERT(entry->IsSmi()); | 404 DCHECK(entry->IsSmi()); |
405 int entry_value = Smi::cast(entry)->value(); | 405 int entry_value = Smi::cast(entry)->value(); |
406 ASSERT(entry_value == JSRegExp::kUninitializedValue || | 406 DCHECK(entry_value == JSRegExp::kUninitializedValue || |
407 entry_value == JSRegExp::kCompilationErrorValue || | 407 entry_value == JSRegExp::kCompilationErrorValue || |
408 (entry_value < JSRegExp::kCodeAgeMask && entry_value >= 0)); | 408 (entry_value < JSRegExp::kCodeAgeMask && entry_value >= 0)); |
409 | 409 |
410 if (entry_value == JSRegExp::kCompilationErrorValue) { | 410 if (entry_value == JSRegExp::kCompilationErrorValue) { |
411 // A previous compilation failed and threw an error which we store in | 411 // A previous compilation failed and threw an error which we store in |
412 // the saved code index (we store the error message, not the actual | 412 // the saved code index (we store the error message, not the actual |
413 // error). Recreate the error object and throw it. | 413 // error). Recreate the error object and throw it. |
414 Object* error_string = re->DataAt(JSRegExp::saved_code_index(is_ascii)); | 414 Object* error_string = re->DataAt(JSRegExp::saved_code_index(is_ascii)); |
415 ASSERT(error_string->IsString()); | 415 DCHECK(error_string->IsString()); |
416 Handle<String> error_message(String::cast(error_string)); | 416 Handle<String> error_message(String::cast(error_string)); |
417 CreateRegExpErrorObjectAndThrow(re, is_ascii, error_message, isolate); | 417 CreateRegExpErrorObjectAndThrow(re, is_ascii, error_message, isolate); |
418 return false; | 418 return false; |
419 } | 419 } |
420 | 420 |
421 JSRegExp::Flags flags = re->GetFlags(); | 421 JSRegExp::Flags flags = re->GetFlags(); |
422 | 422 |
423 Handle<String> pattern(re->Pattern()); | 423 Handle<String> pattern(re->Pattern()); |
424 pattern = String::Flatten(pattern); | 424 pattern = String::Flatten(pattern); |
425 RegExpCompileData compile_data; | 425 RegExpCompileData compile_data; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 | 532 |
533 int RegExpImpl::IrregexpExecRaw(Handle<JSRegExp> regexp, | 533 int RegExpImpl::IrregexpExecRaw(Handle<JSRegExp> regexp, |
534 Handle<String> subject, | 534 Handle<String> subject, |
535 int index, | 535 int index, |
536 int32_t* output, | 536 int32_t* output, |
537 int output_size) { | 537 int output_size) { |
538 Isolate* isolate = regexp->GetIsolate(); | 538 Isolate* isolate = regexp->GetIsolate(); |
539 | 539 |
540 Handle<FixedArray> irregexp(FixedArray::cast(regexp->data()), isolate); | 540 Handle<FixedArray> irregexp(FixedArray::cast(regexp->data()), isolate); |
541 | 541 |
542 ASSERT(index >= 0); | 542 DCHECK(index >= 0); |
543 ASSERT(index <= subject->length()); | 543 DCHECK(index <= subject->length()); |
544 ASSERT(subject->IsFlat()); | 544 DCHECK(subject->IsFlat()); |
545 | 545 |
546 bool is_ascii = subject->IsOneByteRepresentationUnderneath(); | 546 bool is_ascii = subject->IsOneByteRepresentationUnderneath(); |
547 | 547 |
548 #ifndef V8_INTERPRETED_REGEXP | 548 #ifndef V8_INTERPRETED_REGEXP |
549 ASSERT(output_size >= (IrregexpNumberOfCaptures(*irregexp) + 1) * 2); | 549 DCHECK(output_size >= (IrregexpNumberOfCaptures(*irregexp) + 1) * 2); |
550 do { | 550 do { |
551 EnsureCompiledIrregexp(regexp, subject, is_ascii); | 551 EnsureCompiledIrregexp(regexp, subject, is_ascii); |
552 Handle<Code> code(IrregexpNativeCode(*irregexp, is_ascii), isolate); | 552 Handle<Code> code(IrregexpNativeCode(*irregexp, is_ascii), isolate); |
553 // The stack is used to allocate registers for the compiled regexp code. | 553 // The stack is used to allocate registers for the compiled regexp code. |
554 // This means that in case of failure, the output registers array is left | 554 // This means that in case of failure, the output registers array is left |
555 // untouched and contains the capture results from the previous successful | 555 // untouched and contains the capture results from the previous successful |
556 // match. We can use that to set the last match info lazily. | 556 // match. We can use that to set the last match info lazily. |
557 NativeRegExpMacroAssembler::Result res = | 557 NativeRegExpMacroAssembler::Result res = |
558 NativeRegExpMacroAssembler::Match(code, | 558 NativeRegExpMacroAssembler::Match(code, |
559 subject, | 559 subject, |
560 output, | 560 output, |
561 output_size, | 561 output_size, |
562 index, | 562 index, |
563 isolate); | 563 isolate); |
564 if (res != NativeRegExpMacroAssembler::RETRY) { | 564 if (res != NativeRegExpMacroAssembler::RETRY) { |
565 ASSERT(res != NativeRegExpMacroAssembler::EXCEPTION || | 565 DCHECK(res != NativeRegExpMacroAssembler::EXCEPTION || |
566 isolate->has_pending_exception()); | 566 isolate->has_pending_exception()); |
567 STATIC_ASSERT( | 567 STATIC_ASSERT( |
568 static_cast<int>(NativeRegExpMacroAssembler::SUCCESS) == RE_SUCCESS); | 568 static_cast<int>(NativeRegExpMacroAssembler::SUCCESS) == RE_SUCCESS); |
569 STATIC_ASSERT( | 569 STATIC_ASSERT( |
570 static_cast<int>(NativeRegExpMacroAssembler::FAILURE) == RE_FAILURE); | 570 static_cast<int>(NativeRegExpMacroAssembler::FAILURE) == RE_FAILURE); |
571 STATIC_ASSERT(static_cast<int>(NativeRegExpMacroAssembler::EXCEPTION) | 571 STATIC_ASSERT(static_cast<int>(NativeRegExpMacroAssembler::EXCEPTION) |
572 == RE_EXCEPTION); | 572 == RE_EXCEPTION); |
573 return static_cast<IrregexpResult>(res); | 573 return static_cast<IrregexpResult>(res); |
574 } | 574 } |
575 // If result is RETRY, the string has changed representation, and we | 575 // If result is RETRY, the string has changed representation, and we |
576 // must restart from scratch. | 576 // must restart from scratch. |
577 // In this case, it means we must make sure we are prepared to handle | 577 // In this case, it means we must make sure we are prepared to handle |
578 // the, potentially, different subject (the string can switch between | 578 // the, potentially, different subject (the string can switch between |
579 // being internal and external, and even between being ASCII and UC16, | 579 // being internal and external, and even between being ASCII and UC16, |
580 // but the characters are always the same). | 580 // but the characters are always the same). |
581 IrregexpPrepare(regexp, subject); | 581 IrregexpPrepare(regexp, subject); |
582 is_ascii = subject->IsOneByteRepresentationUnderneath(); | 582 is_ascii = subject->IsOneByteRepresentationUnderneath(); |
583 } while (true); | 583 } while (true); |
584 UNREACHABLE(); | 584 UNREACHABLE(); |
585 return RE_EXCEPTION; | 585 return RE_EXCEPTION; |
586 #else // V8_INTERPRETED_REGEXP | 586 #else // V8_INTERPRETED_REGEXP |
587 | 587 |
588 ASSERT(output_size >= IrregexpNumberOfRegisters(*irregexp)); | 588 DCHECK(output_size >= IrregexpNumberOfRegisters(*irregexp)); |
589 // We must have done EnsureCompiledIrregexp, so we can get the number of | 589 // We must have done EnsureCompiledIrregexp, so we can get the number of |
590 // registers. | 590 // registers. |
591 int number_of_capture_registers = | 591 int number_of_capture_registers = |
592 (IrregexpNumberOfCaptures(*irregexp) + 1) * 2; | 592 (IrregexpNumberOfCaptures(*irregexp) + 1) * 2; |
593 int32_t* raw_output = &output[number_of_capture_registers]; | 593 int32_t* raw_output = &output[number_of_capture_registers]; |
594 // We do not touch the actual capture result registers until we know there | 594 // We do not touch the actual capture result registers until we know there |
595 // has been a match so that we can use those capture results to set the | 595 // has been a match so that we can use those capture results to set the |
596 // last match info. | 596 // last match info. |
597 for (int i = number_of_capture_registers - 1; i >= 0; i--) { | 597 for (int i = number_of_capture_registers - 1; i >= 0; i--) { |
598 raw_output[i] = -1; | 598 raw_output[i] = -1; |
599 } | 599 } |
600 Handle<ByteArray> byte_codes(IrregexpByteCode(*irregexp, is_ascii), isolate); | 600 Handle<ByteArray> byte_codes(IrregexpByteCode(*irregexp, is_ascii), isolate); |
601 | 601 |
602 IrregexpResult result = IrregexpInterpreter::Match(isolate, | 602 IrregexpResult result = IrregexpInterpreter::Match(isolate, |
603 byte_codes, | 603 byte_codes, |
604 subject, | 604 subject, |
605 raw_output, | 605 raw_output, |
606 index); | 606 index); |
607 if (result == RE_SUCCESS) { | 607 if (result == RE_SUCCESS) { |
608 // Copy capture results to the start of the registers array. | 608 // Copy capture results to the start of the registers array. |
609 MemCopy(output, raw_output, number_of_capture_registers * sizeof(int32_t)); | 609 MemCopy(output, raw_output, number_of_capture_registers * sizeof(int32_t)); |
610 } | 610 } |
611 if (result == RE_EXCEPTION) { | 611 if (result == RE_EXCEPTION) { |
612 ASSERT(!isolate->has_pending_exception()); | 612 DCHECK(!isolate->has_pending_exception()); |
613 isolate->StackOverflow(); | 613 isolate->StackOverflow(); |
614 } | 614 } |
615 return result; | 615 return result; |
616 #endif // V8_INTERPRETED_REGEXP | 616 #endif // V8_INTERPRETED_REGEXP |
617 } | 617 } |
618 | 618 |
619 | 619 |
620 MaybeHandle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp, | 620 MaybeHandle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp, |
621 Handle<String> subject, | 621 Handle<String> subject, |
622 int previous_index, | 622 int previous_index, |
623 Handle<JSArray> last_match_info) { | 623 Handle<JSArray> last_match_info) { |
624 Isolate* isolate = regexp->GetIsolate(); | 624 Isolate* isolate = regexp->GetIsolate(); |
625 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); | 625 DCHECK_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); |
626 | 626 |
627 // Prepare space for the return values. | 627 // Prepare space for the return values. |
628 #if defined(V8_INTERPRETED_REGEXP) && defined(DEBUG) | 628 #if defined(V8_INTERPRETED_REGEXP) && defined(DEBUG) |
629 if (FLAG_trace_regexp_bytecodes) { | 629 if (FLAG_trace_regexp_bytecodes) { |
630 String* pattern = regexp->Pattern(); | 630 String* pattern = regexp->Pattern(); |
631 PrintF("\n\nRegexp match: /%s/\n\n", pattern->ToCString().get()); | 631 PrintF("\n\nRegexp match: /%s/\n\n", pattern->ToCString().get()); |
632 PrintF("\n\nSubject string: '%s'\n\n", subject->ToCString().get()); | 632 PrintF("\n\nSubject string: '%s'\n\n", subject->ToCString().get()); |
633 } | 633 } |
634 #endif | 634 #endif |
635 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); | 635 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); |
636 if (required_registers < 0) { | 636 if (required_registers < 0) { |
637 // Compiling failed with an exception. | 637 // Compiling failed with an exception. |
638 ASSERT(isolate->has_pending_exception()); | 638 DCHECK(isolate->has_pending_exception()); |
639 return MaybeHandle<Object>(); | 639 return MaybeHandle<Object>(); |
640 } | 640 } |
641 | 641 |
642 int32_t* output_registers = NULL; | 642 int32_t* output_registers = NULL; |
643 if (required_registers > Isolate::kJSRegexpStaticOffsetsVectorSize) { | 643 if (required_registers > Isolate::kJSRegexpStaticOffsetsVectorSize) { |
644 output_registers = NewArray<int32_t>(required_registers); | 644 output_registers = NewArray<int32_t>(required_registers); |
645 } | 645 } |
646 SmartArrayPointer<int32_t> auto_release(output_registers); | 646 SmartArrayPointer<int32_t> auto_release(output_registers); |
647 if (output_registers == NULL) { | 647 if (output_registers == NULL) { |
648 output_registers = isolate->jsregexp_static_offsets_vector(); | 648 output_registers = isolate->jsregexp_static_offsets_vector(); |
649 } | 649 } |
650 | 650 |
651 int res = RegExpImpl::IrregexpExecRaw( | 651 int res = RegExpImpl::IrregexpExecRaw( |
652 regexp, subject, previous_index, output_registers, required_registers); | 652 regexp, subject, previous_index, output_registers, required_registers); |
653 if (res == RE_SUCCESS) { | 653 if (res == RE_SUCCESS) { |
654 int capture_count = | 654 int capture_count = |
655 IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())); | 655 IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())); |
656 return SetLastMatchInfo( | 656 return SetLastMatchInfo( |
657 last_match_info, subject, capture_count, output_registers); | 657 last_match_info, subject, capture_count, output_registers); |
658 } | 658 } |
659 if (res == RE_EXCEPTION) { | 659 if (res == RE_EXCEPTION) { |
660 ASSERT(isolate->has_pending_exception()); | 660 DCHECK(isolate->has_pending_exception()); |
661 return MaybeHandle<Object>(); | 661 return MaybeHandle<Object>(); |
662 } | 662 } |
663 ASSERT(res == RE_FAILURE); | 663 DCHECK(res == RE_FAILURE); |
664 return isolate->factory()->null_value(); | 664 return isolate->factory()->null_value(); |
665 } | 665 } |
666 | 666 |
667 | 667 |
668 Handle<JSArray> RegExpImpl::SetLastMatchInfo(Handle<JSArray> last_match_info, | 668 Handle<JSArray> RegExpImpl::SetLastMatchInfo(Handle<JSArray> last_match_info, |
669 Handle<String> subject, | 669 Handle<String> subject, |
670 int capture_count, | 670 int capture_count, |
671 int32_t* match) { | 671 int32_t* match) { |
672 ASSERT(last_match_info->HasFastObjectElements()); | 672 DCHECK(last_match_info->HasFastObjectElements()); |
673 int capture_register_count = (capture_count + 1) * 2; | 673 int capture_register_count = (capture_count + 1) * 2; |
674 JSArray::EnsureSize(last_match_info, | 674 JSArray::EnsureSize(last_match_info, |
675 capture_register_count + kLastMatchOverhead); | 675 capture_register_count + kLastMatchOverhead); |
676 DisallowHeapAllocation no_allocation; | 676 DisallowHeapAllocation no_allocation; |
677 FixedArray* array = FixedArray::cast(last_match_info->elements()); | 677 FixedArray* array = FixedArray::cast(last_match_info->elements()); |
678 if (match != NULL) { | 678 if (match != NULL) { |
679 for (int i = 0; i < capture_register_count; i += 2) { | 679 for (int i = 0; i < capture_register_count; i += 2) { |
680 SetCapture(array, i, match[i]); | 680 SetCapture(array, i, match[i]); |
681 SetCapture(array, i + 1, match[i + 1]); | 681 SetCapture(array, i + 1, match[i + 1]); |
682 } | 682 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 if (register_array_size_ > Isolate::kJSRegexpStaticOffsetsVectorSize) { | 729 if (register_array_size_ > Isolate::kJSRegexpStaticOffsetsVectorSize) { |
730 register_array_ = NewArray<int32_t>(register_array_size_); | 730 register_array_ = NewArray<int32_t>(register_array_size_); |
731 } else { | 731 } else { |
732 register_array_ = isolate->jsregexp_static_offsets_vector(); | 732 register_array_ = isolate->jsregexp_static_offsets_vector(); |
733 } | 733 } |
734 | 734 |
735 // Set state so that fetching the results the first time triggers a call | 735 // Set state so that fetching the results the first time triggers a call |
736 // to the compiled regexp. | 736 // to the compiled regexp. |
737 current_match_index_ = max_matches_ - 1; | 737 current_match_index_ = max_matches_ - 1; |
738 num_matches_ = max_matches_; | 738 num_matches_ = max_matches_; |
739 ASSERT(registers_per_match_ >= 2); // Each match has at least one capture. | 739 DCHECK(registers_per_match_ >= 2); // Each match has at least one capture. |
740 ASSERT_GE(register_array_size_, registers_per_match_); | 740 DCHECK_GE(register_array_size_, registers_per_match_); |
741 int32_t* last_match = | 741 int32_t* last_match = |
742 ®ister_array_[current_match_index_ * registers_per_match_]; | 742 ®ister_array_[current_match_index_ * registers_per_match_]; |
743 last_match[0] = -1; | 743 last_match[0] = -1; |
744 last_match[1] = 0; | 744 last_match[1] = 0; |
745 } | 745 } |
746 | 746 |
747 | 747 |
748 // ------------------------------------------------------------------- | 748 // ------------------------------------------------------------------- |
749 // Implementation of the Irregexp regular expression engine. | 749 // Implementation of the Irregexp regular expression engine. |
750 // | 750 // |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 | 959 |
960 void CountCharacter(int character) { | 960 void CountCharacter(int character) { |
961 int index = (character & RegExpMacroAssembler::kTableMask); | 961 int index = (character & RegExpMacroAssembler::kTableMask); |
962 frequencies_[index].Increment(); | 962 frequencies_[index].Increment(); |
963 total_samples_++; | 963 total_samples_++; |
964 } | 964 } |
965 | 965 |
966 // Does not measure in percent, but rather per-128 (the table size from the | 966 // Does not measure in percent, but rather per-128 (the table size from the |
967 // regexp macro assembler). | 967 // regexp macro assembler). |
968 int Frequency(int in_character) { | 968 int Frequency(int in_character) { |
969 ASSERT((in_character & RegExpMacroAssembler::kTableMask) == in_character); | 969 DCHECK((in_character & RegExpMacroAssembler::kTableMask) == in_character); |
970 if (total_samples_ < 1) return 1; // Division by zero. | 970 if (total_samples_ < 1) return 1; // Division by zero. |
971 int freq_in_per128 = | 971 int freq_in_per128 = |
972 (frequencies_[in_character].counter() * 128) / total_samples_; | 972 (frequencies_[in_character].counter() * 128) / total_samples_; |
973 return freq_in_per128; | 973 return freq_in_per128; |
974 } | 974 } |
975 | 975 |
976 private: | 976 private: |
977 class CharacterFrequency { | 977 class CharacterFrequency { |
978 public: | 978 public: |
979 CharacterFrequency() : counter_(0), character_(-1) { } | 979 CharacterFrequency() : counter_(0), character_(-1) { } |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1081 : next_register_(2 * (capture_count + 1)), | 1081 : next_register_(2 * (capture_count + 1)), |
1082 work_list_(NULL), | 1082 work_list_(NULL), |
1083 recursion_depth_(0), | 1083 recursion_depth_(0), |
1084 ignore_case_(ignore_case), | 1084 ignore_case_(ignore_case), |
1085 ascii_(ascii), | 1085 ascii_(ascii), |
1086 reg_exp_too_big_(false), | 1086 reg_exp_too_big_(false), |
1087 current_expansion_factor_(1), | 1087 current_expansion_factor_(1), |
1088 frequency_collator_(), | 1088 frequency_collator_(), |
1089 zone_(zone) { | 1089 zone_(zone) { |
1090 accept_ = new(zone) EndNode(EndNode::ACCEPT, zone); | 1090 accept_ = new(zone) EndNode(EndNode::ACCEPT, zone); |
1091 ASSERT(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister); | 1091 DCHECK(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister); |
1092 } | 1092 } |
1093 | 1093 |
1094 | 1094 |
1095 RegExpEngine::CompilationResult RegExpCompiler::Assemble( | 1095 RegExpEngine::CompilationResult RegExpCompiler::Assemble( |
1096 RegExpMacroAssembler* macro_assembler, | 1096 RegExpMacroAssembler* macro_assembler, |
1097 RegExpNode* start, | 1097 RegExpNode* start, |
1098 int capture_count, | 1098 int capture_count, |
1099 Handle<String> pattern) { | 1099 Handle<String> pattern) { |
1100 Heap* heap = pattern->GetHeap(); | 1100 Heap* heap = pattern->GetHeap(); |
1101 | 1101 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1161 action != NULL; | 1161 action != NULL; |
1162 action = action->next()) { | 1162 action = action->next()) { |
1163 if (action->Mentions(reg)) | 1163 if (action->Mentions(reg)) |
1164 return true; | 1164 return true; |
1165 } | 1165 } |
1166 return false; | 1166 return false; |
1167 } | 1167 } |
1168 | 1168 |
1169 | 1169 |
1170 bool Trace::GetStoredPosition(int reg, int* cp_offset) { | 1170 bool Trace::GetStoredPosition(int reg, int* cp_offset) { |
1171 ASSERT_EQ(0, *cp_offset); | 1171 DCHECK_EQ(0, *cp_offset); |
1172 for (DeferredAction* action = actions_; | 1172 for (DeferredAction* action = actions_; |
1173 action != NULL; | 1173 action != NULL; |
1174 action = action->next()) { | 1174 action = action->next()) { |
1175 if (action->Mentions(reg)) { | 1175 if (action->Mentions(reg)) { |
1176 if (action->action_type() == ActionNode::STORE_POSITION) { | 1176 if (action->action_type() == ActionNode::STORE_POSITION) { |
1177 *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset(); | 1177 *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset(); |
1178 return true; | 1178 return true; |
1179 } else { | 1179 } else { |
1180 return false; | 1180 return false; |
1181 } | 1181 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 if (!absolute) { | 1263 if (!absolute) { |
1264 value += psr->value(); | 1264 value += psr->value(); |
1265 absolute = true; | 1265 absolute = true; |
1266 } | 1266 } |
1267 // SET_REGISTER is currently only used for newly introduced loop | 1267 // SET_REGISTER is currently only used for newly introduced loop |
1268 // counters. They can have a significant previous value if they | 1268 // counters. They can have a significant previous value if they |
1269 // occour in a loop. TODO(lrn): Propagate this information, so | 1269 // occour in a loop. TODO(lrn): Propagate this information, so |
1270 // we can set undo_action to IGNORE if we know there is no value to | 1270 // we can set undo_action to IGNORE if we know there is no value to |
1271 // restore. | 1271 // restore. |
1272 undo_action = RESTORE; | 1272 undo_action = RESTORE; |
1273 ASSERT_EQ(store_position, -1); | 1273 DCHECK_EQ(store_position, -1); |
1274 ASSERT(!clear); | 1274 DCHECK(!clear); |
1275 break; | 1275 break; |
1276 } | 1276 } |
1277 case ActionNode::INCREMENT_REGISTER: | 1277 case ActionNode::INCREMENT_REGISTER: |
1278 if (!absolute) { | 1278 if (!absolute) { |
1279 value++; | 1279 value++; |
1280 } | 1280 } |
1281 ASSERT_EQ(store_position, -1); | 1281 DCHECK_EQ(store_position, -1); |
1282 ASSERT(!clear); | 1282 DCHECK(!clear); |
1283 undo_action = RESTORE; | 1283 undo_action = RESTORE; |
1284 break; | 1284 break; |
1285 case ActionNode::STORE_POSITION: { | 1285 case ActionNode::STORE_POSITION: { |
1286 Trace::DeferredCapture* pc = | 1286 Trace::DeferredCapture* pc = |
1287 static_cast<Trace::DeferredCapture*>(action); | 1287 static_cast<Trace::DeferredCapture*>(action); |
1288 if (!clear && store_position == -1) { | 1288 if (!clear && store_position == -1) { |
1289 store_position = pc->cp_offset(); | 1289 store_position = pc->cp_offset(); |
1290 } | 1290 } |
1291 | 1291 |
1292 // For captures we know that stores and clears alternate. | 1292 // For captures we know that stores and clears alternate. |
1293 // Other register, are never cleared, and if the occur | 1293 // Other register, are never cleared, and if the occur |
1294 // inside a loop, they might be assigned more than once. | 1294 // inside a loop, they might be assigned more than once. |
1295 if (reg <= 1) { | 1295 if (reg <= 1) { |
1296 // Registers zero and one, aka "capture zero", is | 1296 // Registers zero and one, aka "capture zero", is |
1297 // always set correctly if we succeed. There is no | 1297 // always set correctly if we succeed. There is no |
1298 // need to undo a setting on backtrack, because we | 1298 // need to undo a setting on backtrack, because we |
1299 // will set it again or fail. | 1299 // will set it again or fail. |
1300 undo_action = IGNORE; | 1300 undo_action = IGNORE; |
1301 } else { | 1301 } else { |
1302 undo_action = pc->is_capture() ? CLEAR : RESTORE; | 1302 undo_action = pc->is_capture() ? CLEAR : RESTORE; |
1303 } | 1303 } |
1304 ASSERT(!absolute); | 1304 DCHECK(!absolute); |
1305 ASSERT_EQ(value, 0); | 1305 DCHECK_EQ(value, 0); |
1306 break; | 1306 break; |
1307 } | 1307 } |
1308 case ActionNode::CLEAR_CAPTURES: { | 1308 case ActionNode::CLEAR_CAPTURES: { |
1309 // Since we're scanning in reverse order, if we've already | 1309 // Since we're scanning in reverse order, if we've already |
1310 // set the position we have to ignore historically earlier | 1310 // set the position we have to ignore historically earlier |
1311 // clearing operations. | 1311 // clearing operations. |
1312 if (store_position == -1) { | 1312 if (store_position == -1) { |
1313 clear = true; | 1313 clear = true; |
1314 } | 1314 } |
1315 undo_action = RESTORE; | 1315 undo_action = RESTORE; |
1316 ASSERT(!absolute); | 1316 DCHECK(!absolute); |
1317 ASSERT_EQ(value, 0); | 1317 DCHECK_EQ(value, 0); |
1318 break; | 1318 break; |
1319 } | 1319 } |
1320 default: | 1320 default: |
1321 UNREACHABLE(); | 1321 UNREACHABLE(); |
1322 break; | 1322 break; |
1323 } | 1323 } |
1324 } | 1324 } |
1325 } | 1325 } |
1326 // Prepare for the undo-action (e.g., push if it's going to be popped). | 1326 // Prepare for the undo-action (e.g., push if it's going to be popped). |
1327 if (undo_action == RESTORE) { | 1327 if (undo_action == RESTORE) { |
(...skipping 24 matching lines...) Expand all Loading... |
1352 } | 1352 } |
1353 } | 1353 } |
1354 | 1354 |
1355 | 1355 |
1356 // This is called as we come into a loop choice node and some other tricky | 1356 // This is called as we come into a loop choice node and some other tricky |
1357 // nodes. It normalizes the state of the code generator to ensure we can | 1357 // nodes. It normalizes the state of the code generator to ensure we can |
1358 // generate generic code. | 1358 // generate generic code. |
1359 void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) { | 1359 void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) { |
1360 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 1360 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
1361 | 1361 |
1362 ASSERT(!is_trivial()); | 1362 DCHECK(!is_trivial()); |
1363 | 1363 |
1364 if (actions_ == NULL && backtrack() == NULL) { | 1364 if (actions_ == NULL && backtrack() == NULL) { |
1365 // Here we just have some deferred cp advances to fix and we are back to | 1365 // Here we just have some deferred cp advances to fix and we are back to |
1366 // a normal situation. We may also have to forget some information gained | 1366 // a normal situation. We may also have to forget some information gained |
1367 // through a quick check that was already performed. | 1367 // through a quick check that was already performed. |
1368 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_); | 1368 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_); |
1369 // Create a new trivial state and generate the node with that. | 1369 // Create a new trivial state and generate the node with that. |
1370 Trace new_state; | 1370 Trace new_state; |
1371 successor->Emit(compiler, &new_state); | 1371 successor->Emit(compiler, &new_state); |
1372 return; | 1372 return; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1569 | 1569 |
1570 // ------------------------------------------------------------------- | 1570 // ------------------------------------------------------------------- |
1571 // Emit code. | 1571 // Emit code. |
1572 | 1572 |
1573 | 1573 |
1574 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler, | 1574 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler, |
1575 Guard* guard, | 1575 Guard* guard, |
1576 Trace* trace) { | 1576 Trace* trace) { |
1577 switch (guard->op()) { | 1577 switch (guard->op()) { |
1578 case Guard::LT: | 1578 case Guard::LT: |
1579 ASSERT(!trace->mentions_reg(guard->reg())); | 1579 DCHECK(!trace->mentions_reg(guard->reg())); |
1580 macro_assembler->IfRegisterGE(guard->reg(), | 1580 macro_assembler->IfRegisterGE(guard->reg(), |
1581 guard->value(), | 1581 guard->value(), |
1582 trace->backtrack()); | 1582 trace->backtrack()); |
1583 break; | 1583 break; |
1584 case Guard::GEQ: | 1584 case Guard::GEQ: |
1585 ASSERT(!trace->mentions_reg(guard->reg())); | 1585 DCHECK(!trace->mentions_reg(guard->reg())); |
1586 macro_assembler->IfRegisterLT(guard->reg(), | 1586 macro_assembler->IfRegisterLT(guard->reg(), |
1587 guard->value(), | 1587 guard->value(), |
1588 trace->backtrack()); | 1588 trace->backtrack()); |
1589 break; | 1589 break; |
1590 } | 1590 } |
1591 } | 1591 } |
1592 | 1592 |
1593 | 1593 |
1594 // Returns the number of characters in the equivalence class, omitting those | 1594 // Returns the number of characters in the equivalence class, omitting those |
1595 // that cannot occur in the source string because it is ASCII. | 1595 // that cannot occur in the source string because it is ASCII. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1679 if (ascii) { | 1679 if (ascii) { |
1680 char_mask = String::kMaxOneByteCharCode; | 1680 char_mask = String::kMaxOneByteCharCode; |
1681 } else { | 1681 } else { |
1682 char_mask = String::kMaxUtf16CodeUnit; | 1682 char_mask = String::kMaxUtf16CodeUnit; |
1683 } | 1683 } |
1684 uc16 exor = c1 ^ c2; | 1684 uc16 exor = c1 ^ c2; |
1685 // Check whether exor has only one bit set. | 1685 // Check whether exor has only one bit set. |
1686 if (((exor - 1) & exor) == 0) { | 1686 if (((exor - 1) & exor) == 0) { |
1687 // If c1 and c2 differ only by one bit. | 1687 // If c1 and c2 differ only by one bit. |
1688 // Ecma262UnCanonicalize always gives the highest number last. | 1688 // Ecma262UnCanonicalize always gives the highest number last. |
1689 ASSERT(c2 > c1); | 1689 DCHECK(c2 > c1); |
1690 uc16 mask = char_mask ^ exor; | 1690 uc16 mask = char_mask ^ exor; |
1691 macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure); | 1691 macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure); |
1692 return true; | 1692 return true; |
1693 } | 1693 } |
1694 ASSERT(c2 > c1); | 1694 DCHECK(c2 > c1); |
1695 uc16 diff = c2 - c1; | 1695 uc16 diff = c2 - c1; |
1696 if (((diff - 1) & diff) == 0 && c1 >= diff) { | 1696 if (((diff - 1) & diff) == 0 && c1 >= diff) { |
1697 // If the characters differ by 2^n but don't differ by one bit then | 1697 // If the characters differ by 2^n but don't differ by one bit then |
1698 // subtract the difference from the found character, then do the or | 1698 // subtract the difference from the found character, then do the or |
1699 // trick. We avoid the theoretical case where negative numbers are | 1699 // trick. We avoid the theoretical case where negative numbers are |
1700 // involved in order to simplify code generation. | 1700 // involved in order to simplify code generation. |
1701 uc16 mask = char_mask ^ diff; | 1701 uc16 mask = char_mask ^ diff; |
1702 macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff, | 1702 macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff, |
1703 diff, | 1703 diff, |
1704 mask, | 1704 mask, |
(...skipping 25 matching lines...) Expand all Loading... |
1730 bool ascii = compiler->ascii(); | 1730 bool ascii = compiler->ascii(); |
1731 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; | 1731 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; |
1732 int length = GetCaseIndependentLetters(isolate, c, ascii, chars); | 1732 int length = GetCaseIndependentLetters(isolate, c, ascii, chars); |
1733 if (length <= 1) return false; | 1733 if (length <= 1) return false; |
1734 // We may not need to check against the end of the input string | 1734 // We may not need to check against the end of the input string |
1735 // if this character lies before a character that matched. | 1735 // if this character lies before a character that matched. |
1736 if (!preloaded) { | 1736 if (!preloaded) { |
1737 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check); | 1737 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check); |
1738 } | 1738 } |
1739 Label ok; | 1739 Label ok; |
1740 ASSERT(unibrow::Ecma262UnCanonicalize::kMaxWidth == 4); | 1740 DCHECK(unibrow::Ecma262UnCanonicalize::kMaxWidth == 4); |
1741 switch (length) { | 1741 switch (length) { |
1742 case 2: { | 1742 case 2: { |
1743 if (ShortCutEmitCharacterPair(macro_assembler, | 1743 if (ShortCutEmitCharacterPair(macro_assembler, |
1744 ascii, | 1744 ascii, |
1745 chars[0], | 1745 chars[0], |
1746 chars[1], | 1746 chars[1], |
1747 on_failure)) { | 1747 on_failure)) { |
1748 } else { | 1748 } else { |
1749 macro_assembler->CheckCharacter(chars[0], &ok); | 1749 macro_assembler->CheckCharacter(chars[0], &ok); |
1750 macro_assembler->CheckNotCharacter(chars[1], on_failure); | 1750 macro_assembler->CheckNotCharacter(chars[1], on_failure); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1818 Label* even_label, | 1818 Label* even_label, |
1819 Label* odd_label) { | 1819 Label* odd_label) { |
1820 static const int kSize = RegExpMacroAssembler::kTableSize; | 1820 static const int kSize = RegExpMacroAssembler::kTableSize; |
1821 static const int kMask = RegExpMacroAssembler::kTableMask; | 1821 static const int kMask = RegExpMacroAssembler::kTableMask; |
1822 | 1822 |
1823 int base = (min_char & ~kMask); | 1823 int base = (min_char & ~kMask); |
1824 USE(base); | 1824 USE(base); |
1825 | 1825 |
1826 // Assert that everything is on one kTableSize page. | 1826 // Assert that everything is on one kTableSize page. |
1827 for (int i = start_index; i <= end_index; i++) { | 1827 for (int i = start_index; i <= end_index; i++) { |
1828 ASSERT_EQ(ranges->at(i) & ~kMask, base); | 1828 DCHECK_EQ(ranges->at(i) & ~kMask, base); |
1829 } | 1829 } |
1830 ASSERT(start_index == 0 || (ranges->at(start_index - 1) & ~kMask) <= base); | 1830 DCHECK(start_index == 0 || (ranges->at(start_index - 1) & ~kMask) <= base); |
1831 | 1831 |
1832 char templ[kSize]; | 1832 char templ[kSize]; |
1833 Label* on_bit_set; | 1833 Label* on_bit_set; |
1834 Label* on_bit_clear; | 1834 Label* on_bit_clear; |
1835 int bit; | 1835 int bit; |
1836 if (even_label == fall_through) { | 1836 if (even_label == fall_through) { |
1837 on_bit_set = odd_label; | 1837 on_bit_set = odd_label; |
1838 on_bit_clear = even_label; | 1838 on_bit_clear = even_label; |
1839 bit = 1; | 1839 bit = 1; |
1840 } else { | 1840 } else { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1876 Label* odd_label) { | 1876 Label* odd_label) { |
1877 bool odd = (((cut_index - start_index) & 1) == 1); | 1877 bool odd = (((cut_index - start_index) & 1) == 1); |
1878 Label* in_range_label = odd ? odd_label : even_label; | 1878 Label* in_range_label = odd ? odd_label : even_label; |
1879 Label dummy; | 1879 Label dummy; |
1880 EmitDoubleBoundaryTest(masm, | 1880 EmitDoubleBoundaryTest(masm, |
1881 ranges->at(cut_index), | 1881 ranges->at(cut_index), |
1882 ranges->at(cut_index + 1) - 1, | 1882 ranges->at(cut_index + 1) - 1, |
1883 &dummy, | 1883 &dummy, |
1884 in_range_label, | 1884 in_range_label, |
1885 &dummy); | 1885 &dummy); |
1886 ASSERT(!dummy.is_linked()); | 1886 DCHECK(!dummy.is_linked()); |
1887 // Cut out the single range by rewriting the array. This creates a new | 1887 // Cut out the single range by rewriting the array. This creates a new |
1888 // range that is a merger of the two ranges on either side of the one we | 1888 // range that is a merger of the two ranges on either side of the one we |
1889 // are cutting out. The oddity of the labels is preserved. | 1889 // are cutting out. The oddity of the labels is preserved. |
1890 for (int j = cut_index; j > start_index; j--) { | 1890 for (int j = cut_index; j > start_index; j--) { |
1891 ranges->at(j) = ranges->at(j - 1); | 1891 ranges->at(j) = ranges->at(j - 1); |
1892 } | 1892 } |
1893 for (int j = cut_index + 1; j < end_index; j++) { | 1893 for (int j = cut_index + 1; j < end_index; j++) { |
1894 ranges->at(j) = ranges->at(j + 1); | 1894 ranges->at(j) = ranges->at(j + 1); |
1895 } | 1895 } |
1896 } | 1896 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1943 while (scan_forward_for_section_border < end_index) { | 1943 while (scan_forward_for_section_border < end_index) { |
1944 if (ranges->at(scan_forward_for_section_border) > new_border) { | 1944 if (ranges->at(scan_forward_for_section_border) > new_border) { |
1945 *new_start_index = scan_forward_for_section_border; | 1945 *new_start_index = scan_forward_for_section_border; |
1946 *border = new_border; | 1946 *border = new_border; |
1947 break; | 1947 break; |
1948 } | 1948 } |
1949 scan_forward_for_section_border++; | 1949 scan_forward_for_section_border++; |
1950 } | 1950 } |
1951 } | 1951 } |
1952 | 1952 |
1953 ASSERT(*new_start_index > start_index); | 1953 DCHECK(*new_start_index > start_index); |
1954 *new_end_index = *new_start_index - 1; | 1954 *new_end_index = *new_start_index - 1; |
1955 if (ranges->at(*new_end_index) == *border) { | 1955 if (ranges->at(*new_end_index) == *border) { |
1956 (*new_end_index)--; | 1956 (*new_end_index)--; |
1957 } | 1957 } |
1958 if (*border >= ranges->at(end_index)) { | 1958 if (*border >= ranges->at(end_index)) { |
1959 *border = ranges->at(end_index); | 1959 *border = ranges->at(end_index); |
1960 *new_start_index = end_index; // Won't be used. | 1960 *new_start_index = end_index; // Won't be used. |
1961 *new_end_index = end_index - 1; | 1961 *new_end_index = end_index - 1; |
1962 } | 1962 } |
1963 } | 1963 } |
(...skipping 10 matching lines...) Expand all Loading... |
1974 int start_index, | 1974 int start_index, |
1975 int end_index, | 1975 int end_index, |
1976 uc16 min_char, | 1976 uc16 min_char, |
1977 uc16 max_char, | 1977 uc16 max_char, |
1978 Label* fall_through, | 1978 Label* fall_through, |
1979 Label* even_label, | 1979 Label* even_label, |
1980 Label* odd_label) { | 1980 Label* odd_label) { |
1981 int first = ranges->at(start_index); | 1981 int first = ranges->at(start_index); |
1982 int last = ranges->at(end_index) - 1; | 1982 int last = ranges->at(end_index) - 1; |
1983 | 1983 |
1984 ASSERT_LT(min_char, first); | 1984 DCHECK_LT(min_char, first); |
1985 | 1985 |
1986 // Just need to test if the character is before or on-or-after | 1986 // Just need to test if the character is before or on-or-after |
1987 // a particular character. | 1987 // a particular character. |
1988 if (start_index == end_index) { | 1988 if (start_index == end_index) { |
1989 EmitBoundaryTest(masm, first, fall_through, even_label, odd_label); | 1989 EmitBoundaryTest(masm, first, fall_through, even_label, odd_label); |
1990 return; | 1990 return; |
1991 } | 1991 } |
1992 | 1992 |
1993 // Another almost trivial case: There is one interval in the middle that is | 1993 // Another almost trivial case: There is one interval in the middle that is |
1994 // different from the end intervals. | 1994 // different from the end intervals. |
(...skipping 12 matching lines...) Expand all Loading... |
2007 int cut = kNoCutIndex; | 2007 int cut = kNoCutIndex; |
2008 for (int i = start_index; i < end_index; i++) { | 2008 for (int i = start_index; i < end_index; i++) { |
2009 if (ranges->at(i) == ranges->at(i + 1) - 1) { | 2009 if (ranges->at(i) == ranges->at(i + 1) - 1) { |
2010 cut = i; | 2010 cut = i; |
2011 break; | 2011 break; |
2012 } | 2012 } |
2013 } | 2013 } |
2014 if (cut == kNoCutIndex) cut = start_index; | 2014 if (cut == kNoCutIndex) cut = start_index; |
2015 CutOutRange( | 2015 CutOutRange( |
2016 masm, ranges, start_index, end_index, cut, even_label, odd_label); | 2016 masm, ranges, start_index, end_index, cut, even_label, odd_label); |
2017 ASSERT_GE(end_index - start_index, 2); | 2017 DCHECK_GE(end_index - start_index, 2); |
2018 GenerateBranches(masm, | 2018 GenerateBranches(masm, |
2019 ranges, | 2019 ranges, |
2020 start_index + 1, | 2020 start_index + 1, |
2021 end_index - 1, | 2021 end_index - 1, |
2022 min_char, | 2022 min_char, |
2023 max_char, | 2023 max_char, |
2024 fall_through, | 2024 fall_through, |
2025 even_label, | 2025 even_label, |
2026 odd_label); | 2026 odd_label); |
2027 return; | 2027 return; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2067 &new_start_index, | 2067 &new_start_index, |
2068 &new_end_index, | 2068 &new_end_index, |
2069 &border); | 2069 &border); |
2070 | 2070 |
2071 Label handle_rest; | 2071 Label handle_rest; |
2072 Label* above = &handle_rest; | 2072 Label* above = &handle_rest; |
2073 if (border == last + 1) { | 2073 if (border == last + 1) { |
2074 // We didn't find any section that started after the limit, so everything | 2074 // We didn't find any section that started after the limit, so everything |
2075 // above the border is one of the terminal labels. | 2075 // above the border is one of the terminal labels. |
2076 above = (end_index & 1) != (start_index & 1) ? odd_label : even_label; | 2076 above = (end_index & 1) != (start_index & 1) ? odd_label : even_label; |
2077 ASSERT(new_end_index == end_index - 1); | 2077 DCHECK(new_end_index == end_index - 1); |
2078 } | 2078 } |
2079 | 2079 |
2080 ASSERT_LE(start_index, new_end_index); | 2080 DCHECK_LE(start_index, new_end_index); |
2081 ASSERT_LE(new_start_index, end_index); | 2081 DCHECK_LE(new_start_index, end_index); |
2082 ASSERT_LT(start_index, new_start_index); | 2082 DCHECK_LT(start_index, new_start_index); |
2083 ASSERT_LT(new_end_index, end_index); | 2083 DCHECK_LT(new_end_index, end_index); |
2084 ASSERT(new_end_index + 1 == new_start_index || | 2084 DCHECK(new_end_index + 1 == new_start_index || |
2085 (new_end_index + 2 == new_start_index && | 2085 (new_end_index + 2 == new_start_index && |
2086 border == ranges->at(new_end_index + 1))); | 2086 border == ranges->at(new_end_index + 1))); |
2087 ASSERT_LT(min_char, border - 1); | 2087 DCHECK_LT(min_char, border - 1); |
2088 ASSERT_LT(border, max_char); | 2088 DCHECK_LT(border, max_char); |
2089 ASSERT_LT(ranges->at(new_end_index), border); | 2089 DCHECK_LT(ranges->at(new_end_index), border); |
2090 ASSERT(border < ranges->at(new_start_index) || | 2090 DCHECK(border < ranges->at(new_start_index) || |
2091 (border == ranges->at(new_start_index) && | 2091 (border == ranges->at(new_start_index) && |
2092 new_start_index == end_index && | 2092 new_start_index == end_index && |
2093 new_end_index == end_index - 1 && | 2093 new_end_index == end_index - 1 && |
2094 border == last + 1)); | 2094 border == last + 1)); |
2095 ASSERT(new_start_index == 0 || border >= ranges->at(new_start_index - 1)); | 2095 DCHECK(new_start_index == 0 || border >= ranges->at(new_start_index - 1)); |
2096 | 2096 |
2097 masm->CheckCharacterGT(border - 1, above); | 2097 masm->CheckCharacterGT(border - 1, above); |
2098 Label dummy; | 2098 Label dummy; |
2099 GenerateBranches(masm, | 2099 GenerateBranches(masm, |
2100 ranges, | 2100 ranges, |
2101 start_index, | 2101 start_index, |
2102 new_end_index, | 2102 new_end_index, |
2103 min_char, | 2103 min_char, |
2104 border - 1, | 2104 border - 1, |
2105 &dummy, | 2105 &dummy, |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2202 // was already one there we fall through for success on that entry. | 2202 // was already one there we fall through for success on that entry. |
2203 // Subsequent entries have alternating meaning (success/failure). | 2203 // Subsequent entries have alternating meaning (success/failure). |
2204 ZoneList<int>* range_boundaries = | 2204 ZoneList<int>* range_boundaries = |
2205 new(zone) ZoneList<int>(last_valid_range, zone); | 2205 new(zone) ZoneList<int>(last_valid_range, zone); |
2206 | 2206 |
2207 bool zeroth_entry_is_failure = !cc->is_negated(); | 2207 bool zeroth_entry_is_failure = !cc->is_negated(); |
2208 | 2208 |
2209 for (int i = 0; i <= last_valid_range; i++) { | 2209 for (int i = 0; i <= last_valid_range; i++) { |
2210 CharacterRange& range = ranges->at(i); | 2210 CharacterRange& range = ranges->at(i); |
2211 if (range.from() == 0) { | 2211 if (range.from() == 0) { |
2212 ASSERT_EQ(i, 0); | 2212 DCHECK_EQ(i, 0); |
2213 zeroth_entry_is_failure = !zeroth_entry_is_failure; | 2213 zeroth_entry_is_failure = !zeroth_entry_is_failure; |
2214 } else { | 2214 } else { |
2215 range_boundaries->Add(range.from(), zone); | 2215 range_boundaries->Add(range.from(), zone); |
2216 } | 2216 } |
2217 range_boundaries->Add(range.to() + 1, zone); | 2217 range_boundaries->Add(range.to() + 1, zone); |
2218 } | 2218 } |
2219 int end_index = range_boundaries->length() - 1; | 2219 int end_index = range_boundaries->length() - 1; |
2220 if (range_boundaries->at(end_index) > max_char) { | 2220 if (range_boundaries->at(end_index) > max_char) { |
2221 end_index--; | 2221 end_index--; |
2222 } | 2222 } |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2459 Trace* trace, | 2459 Trace* trace, |
2460 bool preload_has_checked_bounds, | 2460 bool preload_has_checked_bounds, |
2461 Label* on_possible_success, | 2461 Label* on_possible_success, |
2462 QuickCheckDetails* details, | 2462 QuickCheckDetails* details, |
2463 bool fall_through_on_failure) { | 2463 bool fall_through_on_failure) { |
2464 if (details->characters() == 0) return false; | 2464 if (details->characters() == 0) return false; |
2465 GetQuickCheckDetails( | 2465 GetQuickCheckDetails( |
2466 details, compiler, 0, trace->at_start() == Trace::FALSE_VALUE); | 2466 details, compiler, 0, trace->at_start() == Trace::FALSE_VALUE); |
2467 if (details->cannot_match()) return false; | 2467 if (details->cannot_match()) return false; |
2468 if (!details->Rationalize(compiler->ascii())) return false; | 2468 if (!details->Rationalize(compiler->ascii())) return false; |
2469 ASSERT(details->characters() == 1 || | 2469 DCHECK(details->characters() == 1 || |
2470 compiler->macro_assembler()->CanReadUnaligned()); | 2470 compiler->macro_assembler()->CanReadUnaligned()); |
2471 uint32_t mask = details->mask(); | 2471 uint32_t mask = details->mask(); |
2472 uint32_t value = details->value(); | 2472 uint32_t value = details->value(); |
2473 | 2473 |
2474 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 2474 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
2475 | 2475 |
2476 if (trace->characters_preloaded() != details->characters()) { | 2476 if (trace->characters_preloaded() != details->characters()) { |
2477 assembler->LoadCurrentCharacter(trace->cp_offset(), | 2477 assembler->LoadCurrentCharacter(trace->cp_offset(), |
2478 trace->backtrack(), | 2478 trace->backtrack(), |
2479 !preload_has_checked_bounds, | 2479 !preload_has_checked_bounds, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2529 // We iterate along the text object, building up for each character a | 2529 // We iterate along the text object, building up for each character a |
2530 // mask and value that can be used to test for a quick failure to match. | 2530 // mask and value that can be used to test for a quick failure to match. |
2531 // The masks and values for the positions will be combined into a single | 2531 // The masks and values for the positions will be combined into a single |
2532 // machine word for the current character width in order to be used in | 2532 // machine word for the current character width in order to be used in |
2533 // generating a quick check. | 2533 // generating a quick check. |
2534 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details, | 2534 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details, |
2535 RegExpCompiler* compiler, | 2535 RegExpCompiler* compiler, |
2536 int characters_filled_in, | 2536 int characters_filled_in, |
2537 bool not_at_start) { | 2537 bool not_at_start) { |
2538 Isolate* isolate = compiler->macro_assembler()->zone()->isolate(); | 2538 Isolate* isolate = compiler->macro_assembler()->zone()->isolate(); |
2539 ASSERT(characters_filled_in < details->characters()); | 2539 DCHECK(characters_filled_in < details->characters()); |
2540 int characters = details->characters(); | 2540 int characters = details->characters(); |
2541 int char_mask; | 2541 int char_mask; |
2542 if (compiler->ascii()) { | 2542 if (compiler->ascii()) { |
2543 char_mask = String::kMaxOneByteCharCode; | 2543 char_mask = String::kMaxOneByteCharCode; |
2544 } else { | 2544 } else { |
2545 char_mask = String::kMaxUtf16CodeUnit; | 2545 char_mask = String::kMaxUtf16CodeUnit; |
2546 } | 2546 } |
2547 for (int k = 0; k < elms_->length(); k++) { | 2547 for (int k = 0; k < elms_->length(); k++) { |
2548 TextElement elm = elms_->at(k); | 2548 TextElement elm = elms_->at(k); |
2549 if (elm.text_type() == TextElement::ATOM) { | 2549 if (elm.text_type() == TextElement::ATOM) { |
2550 Vector<const uc16> quarks = elm.atom()->data(); | 2550 Vector<const uc16> quarks = elm.atom()->data(); |
2551 for (int i = 0; i < characters && i < quarks.length(); i++) { | 2551 for (int i = 0; i < characters && i < quarks.length(); i++) { |
2552 QuickCheckDetails::Position* pos = | 2552 QuickCheckDetails::Position* pos = |
2553 details->positions(characters_filled_in); | 2553 details->positions(characters_filled_in); |
2554 uc16 c = quarks[i]; | 2554 uc16 c = quarks[i]; |
2555 if (c > char_mask) { | 2555 if (c > char_mask) { |
2556 // If we expect a non-ASCII character from an ASCII string, | 2556 // If we expect a non-ASCII character from an ASCII string, |
2557 // there is no way we can match. Not even case independent | 2557 // there is no way we can match. Not even case independent |
2558 // matching can turn an ASCII character into non-ASCII or | 2558 // matching can turn an ASCII character into non-ASCII or |
2559 // vice versa. | 2559 // vice versa. |
2560 details->set_cannot_match(); | 2560 details->set_cannot_match(); |
2561 pos->determines_perfectly = false; | 2561 pos->determines_perfectly = false; |
2562 return; | 2562 return; |
2563 } | 2563 } |
2564 if (compiler->ignore_case()) { | 2564 if (compiler->ignore_case()) { |
2565 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; | 2565 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; |
2566 int length = GetCaseIndependentLetters(isolate, c, compiler->ascii(), | 2566 int length = GetCaseIndependentLetters(isolate, c, compiler->ascii(), |
2567 chars); | 2567 chars); |
2568 ASSERT(length != 0); // Can only happen if c > char_mask (see above). | 2568 DCHECK(length != 0); // Can only happen if c > char_mask (see above). |
2569 if (length == 1) { | 2569 if (length == 1) { |
2570 // This letter has no case equivalents, so it's nice and simple | 2570 // This letter has no case equivalents, so it's nice and simple |
2571 // and the mask-compare will determine definitely whether we have | 2571 // and the mask-compare will determine definitely whether we have |
2572 // a match at this character position. | 2572 // a match at this character position. |
2573 pos->mask = char_mask; | 2573 pos->mask = char_mask; |
2574 pos->value = c; | 2574 pos->value = c; |
2575 pos->determines_perfectly = true; | 2575 pos->determines_perfectly = true; |
2576 } else { | 2576 } else { |
2577 uint32_t common_bits = char_mask; | 2577 uint32_t common_bits = char_mask; |
2578 uint32_t bits = chars[0]; | 2578 uint32_t bits = chars[0]; |
(...skipping 15 matching lines...) Expand all Loading... |
2594 } | 2594 } |
2595 } else { | 2595 } else { |
2596 // Don't ignore case. Nice simple case where the mask-compare will | 2596 // Don't ignore case. Nice simple case where the mask-compare will |
2597 // determine definitely whether we have a match at this character | 2597 // determine definitely whether we have a match at this character |
2598 // position. | 2598 // position. |
2599 pos->mask = char_mask; | 2599 pos->mask = char_mask; |
2600 pos->value = c; | 2600 pos->value = c; |
2601 pos->determines_perfectly = true; | 2601 pos->determines_perfectly = true; |
2602 } | 2602 } |
2603 characters_filled_in++; | 2603 characters_filled_in++; |
2604 ASSERT(characters_filled_in <= details->characters()); | 2604 DCHECK(characters_filled_in <= details->characters()); |
2605 if (characters_filled_in == details->characters()) { | 2605 if (characters_filled_in == details->characters()) { |
2606 return; | 2606 return; |
2607 } | 2607 } |
2608 } | 2608 } |
2609 } else { | 2609 } else { |
2610 QuickCheckDetails::Position* pos = | 2610 QuickCheckDetails::Position* pos = |
2611 details->positions(characters_filled_in); | 2611 details->positions(characters_filled_in); |
2612 RegExpCharacterClass* tree = elm.char_class(); | 2612 RegExpCharacterClass* tree = elm.char_class(); |
2613 ZoneList<CharacterRange>* ranges = tree->ranges(zone()); | 2613 ZoneList<CharacterRange>* ranges = tree->ranges(zone()); |
2614 if (tree->is_negated()) { | 2614 if (tree->is_negated()) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2660 common_bits &= new_common_bits; | 2660 common_bits &= new_common_bits; |
2661 bits &= new_common_bits; | 2661 bits &= new_common_bits; |
2662 uint32_t differing_bits = (from & common_bits) ^ bits; | 2662 uint32_t differing_bits = (from & common_bits) ^ bits; |
2663 common_bits ^= differing_bits; | 2663 common_bits ^= differing_bits; |
2664 bits &= common_bits; | 2664 bits &= common_bits; |
2665 } | 2665 } |
2666 pos->mask = common_bits; | 2666 pos->mask = common_bits; |
2667 pos->value = bits; | 2667 pos->value = bits; |
2668 } | 2668 } |
2669 characters_filled_in++; | 2669 characters_filled_in++; |
2670 ASSERT(characters_filled_in <= details->characters()); | 2670 DCHECK(characters_filled_in <= details->characters()); |
2671 if (characters_filled_in == details->characters()) { | 2671 if (characters_filled_in == details->characters()) { |
2672 return; | 2672 return; |
2673 } | 2673 } |
2674 } | 2674 } |
2675 } | 2675 } |
2676 ASSERT(characters_filled_in != details->characters()); | 2676 DCHECK(characters_filled_in != details->characters()); |
2677 if (!details->cannot_match()) { | 2677 if (!details->cannot_match()) { |
2678 on_success()-> GetQuickCheckDetails(details, | 2678 on_success()-> GetQuickCheckDetails(details, |
2679 compiler, | 2679 compiler, |
2680 characters_filled_in, | 2680 characters_filled_in, |
2681 true); | 2681 true); |
2682 } | 2682 } |
2683 } | 2683 } |
2684 | 2684 |
2685 | 2685 |
2686 void QuickCheckDetails::Clear() { | 2686 void QuickCheckDetails::Clear() { |
2687 for (int i = 0; i < characters_; i++) { | 2687 for (int i = 0; i < characters_; i++) { |
2688 positions_[i].mask = 0; | 2688 positions_[i].mask = 0; |
2689 positions_[i].value = 0; | 2689 positions_[i].value = 0; |
2690 positions_[i].determines_perfectly = false; | 2690 positions_[i].determines_perfectly = false; |
2691 } | 2691 } |
2692 characters_ = 0; | 2692 characters_ = 0; |
2693 } | 2693 } |
2694 | 2694 |
2695 | 2695 |
2696 void QuickCheckDetails::Advance(int by, bool ascii) { | 2696 void QuickCheckDetails::Advance(int by, bool ascii) { |
2697 ASSERT(by >= 0); | 2697 DCHECK(by >= 0); |
2698 if (by >= characters_) { | 2698 if (by >= characters_) { |
2699 Clear(); | 2699 Clear(); |
2700 return; | 2700 return; |
2701 } | 2701 } |
2702 for (int i = 0; i < characters_ - by; i++) { | 2702 for (int i = 0; i < characters_ - by; i++) { |
2703 positions_[i] = positions_[by + i]; | 2703 positions_[i] = positions_[by + i]; |
2704 } | 2704 } |
2705 for (int i = characters_ - by; i < characters_; i++) { | 2705 for (int i = characters_ - by; i < characters_; i++) { |
2706 positions_[i].mask = 0; | 2706 positions_[i].mask = 0; |
2707 positions_[i].value = 0; | 2707 positions_[i].value = 0; |
2708 positions_[i].determines_perfectly = false; | 2708 positions_[i].determines_perfectly = false; |
2709 } | 2709 } |
2710 characters_ -= by; | 2710 characters_ -= by; |
2711 // We could change mask_ and value_ here but we would never advance unless | 2711 // We could change mask_ and value_ here but we would never advance unless |
2712 // they had already been used in a check and they won't be used again because | 2712 // they had already been used in a check and they won't be used again because |
2713 // it would gain us nothing. So there's no point. | 2713 // it would gain us nothing. So there's no point. |
2714 } | 2714 } |
2715 | 2715 |
2716 | 2716 |
2717 void QuickCheckDetails::Merge(QuickCheckDetails* other, int from_index) { | 2717 void QuickCheckDetails::Merge(QuickCheckDetails* other, int from_index) { |
2718 ASSERT(characters_ == other->characters_); | 2718 DCHECK(characters_ == other->characters_); |
2719 if (other->cannot_match_) { | 2719 if (other->cannot_match_) { |
2720 return; | 2720 return; |
2721 } | 2721 } |
2722 if (cannot_match_) { | 2722 if (cannot_match_) { |
2723 *this = *other; | 2723 *this = *other; |
2724 return; | 2724 return; |
2725 } | 2725 } |
2726 for (int i = from_index; i < characters_; i++) { | 2726 for (int i = from_index; i < characters_; i++) { |
2727 QuickCheckDetails::Position* pos = positions(i); | 2727 QuickCheckDetails::Position* pos = positions(i); |
2728 QuickCheckDetails::Position* other_pos = other->positions(i); | 2728 QuickCheckDetails::Position* other_pos = other->positions(i); |
(...skipping 10 matching lines...) Expand all Loading... |
2739 uc16 differing_bits = (pos->value ^ other_pos->value); | 2739 uc16 differing_bits = (pos->value ^ other_pos->value); |
2740 pos->mask &= ~differing_bits; | 2740 pos->mask &= ~differing_bits; |
2741 pos->value &= pos->mask; | 2741 pos->value &= pos->mask; |
2742 } | 2742 } |
2743 } | 2743 } |
2744 | 2744 |
2745 | 2745 |
2746 class VisitMarker { | 2746 class VisitMarker { |
2747 public: | 2747 public: |
2748 explicit VisitMarker(NodeInfo* info) : info_(info) { | 2748 explicit VisitMarker(NodeInfo* info) : info_(info) { |
2749 ASSERT(!info->visited); | 2749 DCHECK(!info->visited); |
2750 info->visited = true; | 2750 info->visited = true; |
2751 } | 2751 } |
2752 ~VisitMarker() { | 2752 ~VisitMarker() { |
2753 info_->visited = false; | 2753 info_->visited = false; |
2754 } | 2754 } |
2755 private: | 2755 private: |
2756 NodeInfo* info_; | 2756 NodeInfo* info_; |
2757 }; | 2757 }; |
2758 | 2758 |
2759 | 2759 |
2760 RegExpNode* SeqRegExpNode::FilterASCII(int depth, bool ignore_case) { | 2760 RegExpNode* SeqRegExpNode::FilterASCII(int depth, bool ignore_case) { |
2761 if (info()->replacement_calculated) return replacement(); | 2761 if (info()->replacement_calculated) return replacement(); |
2762 if (depth < 0) return this; | 2762 if (depth < 0) return this; |
2763 ASSERT(!info()->visited); | 2763 DCHECK(!info()->visited); |
2764 VisitMarker marker(info()); | 2764 VisitMarker marker(info()); |
2765 return FilterSuccessor(depth - 1, ignore_case); | 2765 return FilterSuccessor(depth - 1, ignore_case); |
2766 } | 2766 } |
2767 | 2767 |
2768 | 2768 |
2769 RegExpNode* SeqRegExpNode::FilterSuccessor(int depth, bool ignore_case) { | 2769 RegExpNode* SeqRegExpNode::FilterSuccessor(int depth, bool ignore_case) { |
2770 RegExpNode* next = on_success_->FilterASCII(depth - 1, ignore_case); | 2770 RegExpNode* next = on_success_->FilterASCII(depth - 1, ignore_case); |
2771 if (next == NULL) return set_replacement(NULL); | 2771 if (next == NULL) return set_replacement(NULL); |
2772 on_success_ = next; | 2772 on_success_ = next; |
2773 return set_replacement(this); | 2773 return set_replacement(this); |
(...skipping 13 matching lines...) Expand all Loading... |
2787 // TODO(dcarney): this could be a lot more efficient. | 2787 // TODO(dcarney): this could be a lot more efficient. |
2788 if (RangeContainsLatin1Equivalents(ranges->at(i))) return true; | 2788 if (RangeContainsLatin1Equivalents(ranges->at(i))) return true; |
2789 } | 2789 } |
2790 return false; | 2790 return false; |
2791 } | 2791 } |
2792 | 2792 |
2793 | 2793 |
2794 RegExpNode* TextNode::FilterASCII(int depth, bool ignore_case) { | 2794 RegExpNode* TextNode::FilterASCII(int depth, bool ignore_case) { |
2795 if (info()->replacement_calculated) return replacement(); | 2795 if (info()->replacement_calculated) return replacement(); |
2796 if (depth < 0) return this; | 2796 if (depth < 0) return this; |
2797 ASSERT(!info()->visited); | 2797 DCHECK(!info()->visited); |
2798 VisitMarker marker(info()); | 2798 VisitMarker marker(info()); |
2799 int element_count = elms_->length(); | 2799 int element_count = elms_->length(); |
2800 for (int i = 0; i < element_count; i++) { | 2800 for (int i = 0; i < element_count; i++) { |
2801 TextElement elm = elms_->at(i); | 2801 TextElement elm = elms_->at(i); |
2802 if (elm.text_type() == TextElement::ATOM) { | 2802 if (elm.text_type() == TextElement::ATOM) { |
2803 Vector<const uc16> quarks = elm.atom()->data(); | 2803 Vector<const uc16> quarks = elm.atom()->data(); |
2804 for (int j = 0; j < quarks.length(); j++) { | 2804 for (int j = 0; j < quarks.length(); j++) { |
2805 uint16_t c = quarks[j]; | 2805 uint16_t c = quarks[j]; |
2806 if (c <= String::kMaxOneByteCharCode) continue; | 2806 if (c <= String::kMaxOneByteCharCode) continue; |
2807 if (!ignore_case) return set_replacement(NULL); | 2807 if (!ignore_case) return set_replacement(NULL); |
2808 // Here, we need to check for characters whose upper and lower cases | 2808 // Here, we need to check for characters whose upper and lower cases |
2809 // are outside the Latin-1 range. | 2809 // are outside the Latin-1 range. |
2810 uint16_t converted = unibrow::Latin1::ConvertNonLatin1ToLatin1(c); | 2810 uint16_t converted = unibrow::Latin1::ConvertNonLatin1ToLatin1(c); |
2811 // Character is outside Latin-1 completely | 2811 // Character is outside Latin-1 completely |
2812 if (converted == 0) return set_replacement(NULL); | 2812 if (converted == 0) return set_replacement(NULL); |
2813 // Convert quark to Latin-1 in place. | 2813 // Convert quark to Latin-1 in place. |
2814 uint16_t* copy = const_cast<uint16_t*>(quarks.start()); | 2814 uint16_t* copy = const_cast<uint16_t*>(quarks.start()); |
2815 copy[j] = converted; | 2815 copy[j] = converted; |
2816 } | 2816 } |
2817 } else { | 2817 } else { |
2818 ASSERT(elm.text_type() == TextElement::CHAR_CLASS); | 2818 DCHECK(elm.text_type() == TextElement::CHAR_CLASS); |
2819 RegExpCharacterClass* cc = elm.char_class(); | 2819 RegExpCharacterClass* cc = elm.char_class(); |
2820 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); | 2820 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); |
2821 if (!CharacterRange::IsCanonical(ranges)) { | 2821 if (!CharacterRange::IsCanonical(ranges)) { |
2822 CharacterRange::Canonicalize(ranges); | 2822 CharacterRange::Canonicalize(ranges); |
2823 } | 2823 } |
2824 // Now they are in order so we only need to look at the first. | 2824 // Now they are in order so we only need to look at the first. |
2825 int range_count = ranges->length(); | 2825 int range_count = ranges->length(); |
2826 if (cc->is_negated()) { | 2826 if (cc->is_negated()) { |
2827 if (range_count != 0 && | 2827 if (range_count != 0 && |
2828 ranges->at(0).from() == 0 && | 2828 ranges->at(0).from() == 0 && |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2877 return this; | 2877 return this; |
2878 } | 2878 } |
2879 } | 2879 } |
2880 | 2880 |
2881 int surviving = 0; | 2881 int surviving = 0; |
2882 RegExpNode* survivor = NULL; | 2882 RegExpNode* survivor = NULL; |
2883 for (int i = 0; i < choice_count; i++) { | 2883 for (int i = 0; i < choice_count; i++) { |
2884 GuardedAlternative alternative = alternatives_->at(i); | 2884 GuardedAlternative alternative = alternatives_->at(i); |
2885 RegExpNode* replacement = | 2885 RegExpNode* replacement = |
2886 alternative.node()->FilterASCII(depth - 1, ignore_case); | 2886 alternative.node()->FilterASCII(depth - 1, ignore_case); |
2887 ASSERT(replacement != this); // No missing EMPTY_MATCH_CHECK. | 2887 DCHECK(replacement != this); // No missing EMPTY_MATCH_CHECK. |
2888 if (replacement != NULL) { | 2888 if (replacement != NULL) { |
2889 alternatives_->at(i).set_node(replacement); | 2889 alternatives_->at(i).set_node(replacement); |
2890 surviving++; | 2890 surviving++; |
2891 survivor = replacement; | 2891 survivor = replacement; |
2892 } | 2892 } |
2893 } | 2893 } |
2894 if (surviving < 2) return set_replacement(survivor); | 2894 if (surviving < 2) return set_replacement(survivor); |
2895 | 2895 |
2896 set_replacement(this); | 2896 set_replacement(this); |
2897 if (surviving == choice_count) { | 2897 if (surviving == choice_count) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2963 SaveBMInfo(bm, not_at_start, offset); | 2963 SaveBMInfo(bm, not_at_start, offset); |
2964 } | 2964 } |
2965 | 2965 |
2966 | 2966 |
2967 void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details, | 2967 void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details, |
2968 RegExpCompiler* compiler, | 2968 RegExpCompiler* compiler, |
2969 int characters_filled_in, | 2969 int characters_filled_in, |
2970 bool not_at_start) { | 2970 bool not_at_start) { |
2971 not_at_start = (not_at_start || not_at_start_); | 2971 not_at_start = (not_at_start || not_at_start_); |
2972 int choice_count = alternatives_->length(); | 2972 int choice_count = alternatives_->length(); |
2973 ASSERT(choice_count > 0); | 2973 DCHECK(choice_count > 0); |
2974 alternatives_->at(0).node()->GetQuickCheckDetails(details, | 2974 alternatives_->at(0).node()->GetQuickCheckDetails(details, |
2975 compiler, | 2975 compiler, |
2976 characters_filled_in, | 2976 characters_filled_in, |
2977 not_at_start); | 2977 not_at_start); |
2978 for (int i = 1; i < choice_count; i++) { | 2978 for (int i = 1; i < choice_count; i++) { |
2979 QuickCheckDetails new_details(details->characters()); | 2979 QuickCheckDetails new_details(details->characters()); |
2980 RegExpNode* node = alternatives_->at(i).node(); | 2980 RegExpNode* node = alternatives_->at(i).node(); |
2981 node->GetQuickCheckDetails(&new_details, compiler, | 2981 node->GetQuickCheckDetails(&new_details, compiler, |
2982 characters_filled_in, | 2982 characters_filled_in, |
2983 not_at_start); | 2983 not_at_start); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3087 Label ok; | 3087 Label ok; |
3088 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord); | 3088 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord); |
3089 assembler->GoTo(&ok); | 3089 assembler->GoTo(&ok); |
3090 | 3090 |
3091 assembler->Bind(&before_word); | 3091 assembler->Bind(&before_word); |
3092 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord); | 3092 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord); |
3093 assembler->Bind(&ok); | 3093 assembler->Bind(&ok); |
3094 } else if (next_is_word_character == Trace::TRUE_VALUE) { | 3094 } else if (next_is_word_character == Trace::TRUE_VALUE) { |
3095 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord); | 3095 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord); |
3096 } else { | 3096 } else { |
3097 ASSERT(next_is_word_character == Trace::FALSE_VALUE); | 3097 DCHECK(next_is_word_character == Trace::FALSE_VALUE); |
3098 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord); | 3098 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord); |
3099 } | 3099 } |
3100 } | 3100 } |
3101 | 3101 |
3102 | 3102 |
3103 void AssertionNode::BacktrackIfPrevious( | 3103 void AssertionNode::BacktrackIfPrevious( |
3104 RegExpCompiler* compiler, | 3104 RegExpCompiler* compiler, |
3105 Trace* trace, | 3105 Trace* trace, |
3106 AssertionNode::IfPrevious backtrack_if_previous) { | 3106 AssertionNode::IfPrevious backtrack_if_previous) { |
3107 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 3107 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3243 TextElement elm = elms_->at(i); | 3243 TextElement elm = elms_->at(i); |
3244 int cp_offset = trace->cp_offset() + elm.cp_offset(); | 3244 int cp_offset = trace->cp_offset() + elm.cp_offset(); |
3245 if (elm.text_type() == TextElement::ATOM) { | 3245 if (elm.text_type() == TextElement::ATOM) { |
3246 Vector<const uc16> quarks = elm.atom()->data(); | 3246 Vector<const uc16> quarks = elm.atom()->data(); |
3247 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { | 3247 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { |
3248 if (first_element_checked && i == 0 && j == 0) continue; | 3248 if (first_element_checked && i == 0 && j == 0) continue; |
3249 if (DeterminedAlready(quick_check, elm.cp_offset() + j)) continue; | 3249 if (DeterminedAlready(quick_check, elm.cp_offset() + j)) continue; |
3250 EmitCharacterFunction* emit_function = NULL; | 3250 EmitCharacterFunction* emit_function = NULL; |
3251 switch (pass) { | 3251 switch (pass) { |
3252 case NON_ASCII_MATCH: | 3252 case NON_ASCII_MATCH: |
3253 ASSERT(ascii); | 3253 DCHECK(ascii); |
3254 if (quarks[j] > String::kMaxOneByteCharCode) { | 3254 if (quarks[j] > String::kMaxOneByteCharCode) { |
3255 assembler->GoTo(backtrack); | 3255 assembler->GoTo(backtrack); |
3256 return; | 3256 return; |
3257 } | 3257 } |
3258 break; | 3258 break; |
3259 case NON_LETTER_CHARACTER_MATCH: | 3259 case NON_LETTER_CHARACTER_MATCH: |
3260 emit_function = &EmitAtomNonLetter; | 3260 emit_function = &EmitAtomNonLetter; |
3261 break; | 3261 break; |
3262 case SIMPLE_CHARACTER_MATCH: | 3262 case SIMPLE_CHARACTER_MATCH: |
3263 emit_function = &EmitSimpleCharacter; | 3263 emit_function = &EmitSimpleCharacter; |
3264 break; | 3264 break; |
3265 case CASE_CHARACTER_MATCH: | 3265 case CASE_CHARACTER_MATCH: |
3266 emit_function = &EmitAtomLetter; | 3266 emit_function = &EmitAtomLetter; |
3267 break; | 3267 break; |
3268 default: | 3268 default: |
3269 break; | 3269 break; |
3270 } | 3270 } |
3271 if (emit_function != NULL) { | 3271 if (emit_function != NULL) { |
3272 bool bound_checked = emit_function(isolate, | 3272 bool bound_checked = emit_function(isolate, |
3273 compiler, | 3273 compiler, |
3274 quarks[j], | 3274 quarks[j], |
3275 backtrack, | 3275 backtrack, |
3276 cp_offset + j, | 3276 cp_offset + j, |
3277 *checked_up_to < cp_offset + j, | 3277 *checked_up_to < cp_offset + j, |
3278 preloaded); | 3278 preloaded); |
3279 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to); | 3279 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to); |
3280 } | 3280 } |
3281 } | 3281 } |
3282 } else { | 3282 } else { |
3283 ASSERT_EQ(TextElement::CHAR_CLASS, elm.text_type()); | 3283 DCHECK_EQ(TextElement::CHAR_CLASS, elm.text_type()); |
3284 if (pass == CHARACTER_CLASS_MATCH) { | 3284 if (pass == CHARACTER_CLASS_MATCH) { |
3285 if (first_element_checked && i == 0) continue; | 3285 if (first_element_checked && i == 0) continue; |
3286 if (DeterminedAlready(quick_check, elm.cp_offset())) continue; | 3286 if (DeterminedAlready(quick_check, elm.cp_offset())) continue; |
3287 RegExpCharacterClass* cc = elm.char_class(); | 3287 RegExpCharacterClass* cc = elm.char_class(); |
3288 EmitCharClass(assembler, | 3288 EmitCharClass(assembler, |
3289 cc, | 3289 cc, |
3290 ascii, | 3290 ascii, |
3291 backtrack, | 3291 backtrack, |
3292 cp_offset, | 3292 cp_offset, |
3293 *checked_up_to < cp_offset, | 3293 *checked_up_to < cp_offset, |
3294 preloaded, | 3294 preloaded, |
3295 zone()); | 3295 zone()); |
3296 UpdateBoundsCheck(cp_offset, checked_up_to); | 3296 UpdateBoundsCheck(cp_offset, checked_up_to); |
3297 } | 3297 } |
3298 } | 3298 } |
3299 } | 3299 } |
3300 } | 3300 } |
3301 | 3301 |
3302 | 3302 |
3303 int TextNode::Length() { | 3303 int TextNode::Length() { |
3304 TextElement elm = elms_->last(); | 3304 TextElement elm = elms_->last(); |
3305 ASSERT(elm.cp_offset() >= 0); | 3305 DCHECK(elm.cp_offset() >= 0); |
3306 return elm.cp_offset() + elm.length(); | 3306 return elm.cp_offset() + elm.length(); |
3307 } | 3307 } |
3308 | 3308 |
3309 | 3309 |
3310 bool TextNode::SkipPass(int int_pass, bool ignore_case) { | 3310 bool TextNode::SkipPass(int int_pass, bool ignore_case) { |
3311 TextEmitPassType pass = static_cast<TextEmitPassType>(int_pass); | 3311 TextEmitPassType pass = static_cast<TextEmitPassType>(int_pass); |
3312 if (ignore_case) { | 3312 if (ignore_case) { |
3313 return pass == SIMPLE_CHARACTER_MATCH; | 3313 return pass == SIMPLE_CHARACTER_MATCH; |
3314 } else { | 3314 } else { |
3315 return pass == NON_LETTER_CHARACTER_MATCH || pass == CASE_CHARACTER_MATCH; | 3315 return pass == NON_LETTER_CHARACTER_MATCH || pass == CASE_CHARACTER_MATCH; |
3316 } | 3316 } |
3317 } | 3317 } |
3318 | 3318 |
3319 | 3319 |
3320 // This generates the code to match a text node. A text node can contain | 3320 // This generates the code to match a text node. A text node can contain |
3321 // straight character sequences (possibly to be matched in a case-independent | 3321 // straight character sequences (possibly to be matched in a case-independent |
3322 // way) and character classes. For efficiency we do not do this in a single | 3322 // way) and character classes. For efficiency we do not do this in a single |
3323 // pass from left to right. Instead we pass over the text node several times, | 3323 // pass from left to right. Instead we pass over the text node several times, |
3324 // emitting code for some character positions every time. See the comment on | 3324 // emitting code for some character positions every time. See the comment on |
3325 // TextEmitPass for details. | 3325 // TextEmitPass for details. |
3326 void TextNode::Emit(RegExpCompiler* compiler, Trace* trace) { | 3326 void TextNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
3327 LimitResult limit_result = LimitVersions(compiler, trace); | 3327 LimitResult limit_result = LimitVersions(compiler, trace); |
3328 if (limit_result == DONE) return; | 3328 if (limit_result == DONE) return; |
3329 ASSERT(limit_result == CONTINUE); | 3329 DCHECK(limit_result == CONTINUE); |
3330 | 3330 |
3331 if (trace->cp_offset() + Length() > RegExpMacroAssembler::kMaxCPOffset) { | 3331 if (trace->cp_offset() + Length() > RegExpMacroAssembler::kMaxCPOffset) { |
3332 compiler->SetRegExpTooBig(); | 3332 compiler->SetRegExpTooBig(); |
3333 return; | 3333 return; |
3334 } | 3334 } |
3335 | 3335 |
3336 if (compiler->ascii()) { | 3336 if (compiler->ascii()) { |
3337 int dummy = 0; | 3337 int dummy = 0; |
3338 TextEmitPass(compiler, NON_ASCII_MATCH, false, trace, false, &dummy); | 3338 TextEmitPass(compiler, NON_ASCII_MATCH, false, trace, false, &dummy); |
3339 } | 3339 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3376 on_success()->Emit(compiler, &successor_trace); | 3376 on_success()->Emit(compiler, &successor_trace); |
3377 } | 3377 } |
3378 | 3378 |
3379 | 3379 |
3380 void Trace::InvalidateCurrentCharacter() { | 3380 void Trace::InvalidateCurrentCharacter() { |
3381 characters_preloaded_ = 0; | 3381 characters_preloaded_ = 0; |
3382 } | 3382 } |
3383 | 3383 |
3384 | 3384 |
3385 void Trace::AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler) { | 3385 void Trace::AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler) { |
3386 ASSERT(by > 0); | 3386 DCHECK(by > 0); |
3387 // We don't have an instruction for shifting the current character register | 3387 // We don't have an instruction for shifting the current character register |
3388 // down or for using a shifted value for anything so lets just forget that | 3388 // down or for using a shifted value for anything so lets just forget that |
3389 // we preloaded any characters into it. | 3389 // we preloaded any characters into it. |
3390 characters_preloaded_ = 0; | 3390 characters_preloaded_ = 0; |
3391 // Adjust the offsets of the quick check performed information. This | 3391 // Adjust the offsets of the quick check performed information. This |
3392 // information is used to find out what we already determined about the | 3392 // information is used to find out what we already determined about the |
3393 // characters by means of mask and compare. | 3393 // characters by means of mask and compare. |
3394 quick_check_performed_.Advance(by, compiler->ascii()); | 3394 quick_check_performed_.Advance(by, compiler->ascii()); |
3395 cp_offset_ += by; | 3395 cp_offset_ += by; |
3396 if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) { | 3396 if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3471 } | 3471 } |
3472 length += node_length; | 3472 length += node_length; |
3473 SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node); | 3473 SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node); |
3474 node = seq_node->on_success(); | 3474 node = seq_node->on_success(); |
3475 } | 3475 } |
3476 return length; | 3476 return length; |
3477 } | 3477 } |
3478 | 3478 |
3479 | 3479 |
3480 void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) { | 3480 void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) { |
3481 ASSERT_EQ(loop_node_, NULL); | 3481 DCHECK_EQ(loop_node_, NULL); |
3482 AddAlternative(alt); | 3482 AddAlternative(alt); |
3483 loop_node_ = alt.node(); | 3483 loop_node_ = alt.node(); |
3484 } | 3484 } |
3485 | 3485 |
3486 | 3486 |
3487 void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) { | 3487 void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) { |
3488 ASSERT_EQ(continue_node_, NULL); | 3488 DCHECK_EQ(continue_node_, NULL); |
3489 AddAlternative(alt); | 3489 AddAlternative(alt); |
3490 continue_node_ = alt.node(); | 3490 continue_node_ = alt.node(); |
3491 } | 3491 } |
3492 | 3492 |
3493 | 3493 |
3494 void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { | 3494 void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
3495 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); | 3495 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); |
3496 if (trace->stop_node() == this) { | 3496 if (trace->stop_node() == this) { |
3497 int text_length = | 3497 int text_length = |
3498 GreedyLoopTextLengthForAlternative(&(alternatives_->at(0))); | 3498 GreedyLoopTextLengthForAlternative(&(alternatives_->at(0))); |
3499 ASSERT(text_length != kNodeIsTooComplexForGreedyLoops); | 3499 DCHECK(text_length != kNodeIsTooComplexForGreedyLoops); |
3500 // Update the counter-based backtracking info on the stack. This is an | 3500 // Update the counter-based backtracking info on the stack. This is an |
3501 // optimization for greedy loops (see below). | 3501 // optimization for greedy loops (see below). |
3502 ASSERT(trace->cp_offset() == text_length); | 3502 DCHECK(trace->cp_offset() == text_length); |
3503 macro_assembler->AdvanceCurrentPosition(text_length); | 3503 macro_assembler->AdvanceCurrentPosition(text_length); |
3504 macro_assembler->GoTo(trace->loop_label()); | 3504 macro_assembler->GoTo(trace->loop_label()); |
3505 return; | 3505 return; |
3506 } | 3506 } |
3507 ASSERT(trace->stop_node() == NULL); | 3507 DCHECK(trace->stop_node() == NULL); |
3508 if (!trace->is_trivial()) { | 3508 if (!trace->is_trivial()) { |
3509 trace->Flush(compiler, this); | 3509 trace->Flush(compiler, this); |
3510 return; | 3510 return; |
3511 } | 3511 } |
3512 ChoiceNode::Emit(compiler, trace); | 3512 ChoiceNode::Emit(compiler, trace); |
3513 } | 3513 } |
3514 | 3514 |
3515 | 3515 |
3516 int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler, | 3516 int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler, |
3517 int eats_at_least) { | 3517 int eats_at_least) { |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3807 masm->AdvanceCurrentPosition(lookahead_width); | 3807 masm->AdvanceCurrentPosition(lookahead_width); |
3808 masm->GoTo(&again); | 3808 masm->GoTo(&again); |
3809 masm->Bind(&cont); | 3809 masm->Bind(&cont); |
3810 return true; | 3810 return true; |
3811 } | 3811 } |
3812 | 3812 |
3813 Factory* factory = masm->zone()->isolate()->factory(); | 3813 Factory* factory = masm->zone()->isolate()->factory(); |
3814 Handle<ByteArray> boolean_skip_table = factory->NewByteArray(kSize, TENURED); | 3814 Handle<ByteArray> boolean_skip_table = factory->NewByteArray(kSize, TENURED); |
3815 int skip_distance = GetSkipTable( | 3815 int skip_distance = GetSkipTable( |
3816 min_lookahead, max_lookahead, boolean_skip_table); | 3816 min_lookahead, max_lookahead, boolean_skip_table); |
3817 ASSERT(skip_distance != 0); | 3817 DCHECK(skip_distance != 0); |
3818 | 3818 |
3819 Label cont, again; | 3819 Label cont, again; |
3820 masm->Bind(&again); | 3820 masm->Bind(&again); |
3821 masm->LoadCurrentCharacter(max_lookahead, &cont, true); | 3821 masm->LoadCurrentCharacter(max_lookahead, &cont, true); |
3822 masm->CheckBitInTable(boolean_skip_table, &cont); | 3822 masm->CheckBitInTable(boolean_skip_table, &cont); |
3823 masm->AdvanceCurrentPosition(skip_distance); | 3823 masm->AdvanceCurrentPosition(skip_distance); |
3824 masm->GoTo(&again); | 3824 masm->GoTo(&again); |
3825 masm->Bind(&cont); | 3825 masm->Bind(&cont); |
3826 | 3826 |
3827 return true; | 3827 return true; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3908 | 3908 |
3909 void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { | 3909 void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
3910 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); | 3910 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); |
3911 int choice_count = alternatives_->length(); | 3911 int choice_count = alternatives_->length(); |
3912 #ifdef DEBUG | 3912 #ifdef DEBUG |
3913 for (int i = 0; i < choice_count - 1; i++) { | 3913 for (int i = 0; i < choice_count - 1; i++) { |
3914 GuardedAlternative alternative = alternatives_->at(i); | 3914 GuardedAlternative alternative = alternatives_->at(i); |
3915 ZoneList<Guard*>* guards = alternative.guards(); | 3915 ZoneList<Guard*>* guards = alternative.guards(); |
3916 int guard_count = (guards == NULL) ? 0 : guards->length(); | 3916 int guard_count = (guards == NULL) ? 0 : guards->length(); |
3917 for (int j = 0; j < guard_count; j++) { | 3917 for (int j = 0; j < guard_count; j++) { |
3918 ASSERT(!trace->mentions_reg(guards->at(j)->reg())); | 3918 DCHECK(!trace->mentions_reg(guards->at(j)->reg())); |
3919 } | 3919 } |
3920 } | 3920 } |
3921 #endif | 3921 #endif |
3922 | 3922 |
3923 LimitResult limit_result = LimitVersions(compiler, trace); | 3923 LimitResult limit_result = LimitVersions(compiler, trace); |
3924 if (limit_result == DONE) return; | 3924 if (limit_result == DONE) return; |
3925 ASSERT(limit_result == CONTINUE); | 3925 DCHECK(limit_result == CONTINUE); |
3926 | 3926 |
3927 int new_flush_budget = trace->flush_budget() / choice_count; | 3927 int new_flush_budget = trace->flush_budget() / choice_count; |
3928 if (trace->flush_budget() == 0 && trace->actions() != NULL) { | 3928 if (trace->flush_budget() == 0 && trace->actions() != NULL) { |
3929 trace->Flush(compiler, this); | 3929 trace->Flush(compiler, this); |
3930 return; | 3930 return; |
3931 } | 3931 } |
3932 | 3932 |
3933 RecursionCheck rc(compiler); | 3933 RecursionCheck rc(compiler); |
3934 | 3934 |
3935 Trace* current_trace = trace; | 3935 Trace* current_trace = trace; |
3936 | 3936 |
3937 int text_length = GreedyLoopTextLengthForAlternative(&(alternatives_->at(0))); | 3937 int text_length = GreedyLoopTextLengthForAlternative(&(alternatives_->at(0))); |
3938 bool greedy_loop = false; | 3938 bool greedy_loop = false; |
3939 Label greedy_loop_label; | 3939 Label greedy_loop_label; |
3940 Trace counter_backtrack_trace; | 3940 Trace counter_backtrack_trace; |
3941 counter_backtrack_trace.set_backtrack(&greedy_loop_label); | 3941 counter_backtrack_trace.set_backtrack(&greedy_loop_label); |
3942 if (not_at_start()) counter_backtrack_trace.set_at_start(false); | 3942 if (not_at_start()) counter_backtrack_trace.set_at_start(false); |
3943 | 3943 |
3944 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) { | 3944 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) { |
3945 // Here we have special handling for greedy loops containing only text nodes | 3945 // Here we have special handling for greedy loops containing only text nodes |
3946 // and other simple nodes. These are handled by pushing the current | 3946 // and other simple nodes. These are handled by pushing the current |
3947 // position on the stack and then incrementing the current position each | 3947 // position on the stack and then incrementing the current position each |
3948 // time around the switch. On backtrack we decrement the current position | 3948 // time around the switch. On backtrack we decrement the current position |
3949 // and check it against the pushed value. This avoids pushing backtrack | 3949 // and check it against the pushed value. This avoids pushing backtrack |
3950 // information for each iteration of the loop, which could take up a lot of | 3950 // information for each iteration of the loop, which could take up a lot of |
3951 // space. | 3951 // space. |
3952 greedy_loop = true; | 3952 greedy_loop = true; |
3953 ASSERT(trace->stop_node() == NULL); | 3953 DCHECK(trace->stop_node() == NULL); |
3954 macro_assembler->PushCurrentPosition(); | 3954 macro_assembler->PushCurrentPosition(); |
3955 current_trace = &counter_backtrack_trace; | 3955 current_trace = &counter_backtrack_trace; |
3956 Label greedy_match_failed; | 3956 Label greedy_match_failed; |
3957 Trace greedy_match_trace; | 3957 Trace greedy_match_trace; |
3958 if (not_at_start()) greedy_match_trace.set_at_start(false); | 3958 if (not_at_start()) greedy_match_trace.set_at_start(false); |
3959 greedy_match_trace.set_backtrack(&greedy_match_failed); | 3959 greedy_match_trace.set_backtrack(&greedy_match_failed); |
3960 Label loop_label; | 3960 Label loop_label; |
3961 macro_assembler->Bind(&loop_label); | 3961 macro_assembler->Bind(&loop_label); |
3962 greedy_match_trace.set_stop_node(this); | 3962 greedy_match_trace.set_stop_node(this); |
3963 greedy_match_trace.set_loop_label(&loop_label); | 3963 greedy_match_trace.set_loop_label(&loop_label); |
(...skipping 18 matching lines...) Expand all Loading... |
3982 RegExpNode* eats_anything_node = alt1.node(); | 3982 RegExpNode* eats_anything_node = alt1.node(); |
3983 if (eats_anything_node->GetSuccessorOfOmnivorousTextNode(compiler) == | 3983 if (eats_anything_node->GetSuccessorOfOmnivorousTextNode(compiler) == |
3984 this) { | 3984 this) { |
3985 // At this point we know that we are at a non-greedy loop that will eat | 3985 // At this point we know that we are at a non-greedy loop that will eat |
3986 // any character one at a time. Any non-anchored regexp has such a | 3986 // any character one at a time. Any non-anchored regexp has such a |
3987 // loop prepended to it in order to find where it starts. We look for | 3987 // loop prepended to it in order to find where it starts. We look for |
3988 // a pattern of the form ...abc... where we can look 6 characters ahead | 3988 // a pattern of the form ...abc... where we can look 6 characters ahead |
3989 // and step forwards 3 if the character is not one of abc. Abc need | 3989 // and step forwards 3 if the character is not one of abc. Abc need |
3990 // not be atoms, they can be any reasonably limited character class or | 3990 // not be atoms, they can be any reasonably limited character class or |
3991 // small alternation. | 3991 // small alternation. |
3992 ASSERT(trace->is_trivial()); // This is the case on LoopChoiceNodes. | 3992 DCHECK(trace->is_trivial()); // This is the case on LoopChoiceNodes. |
3993 BoyerMooreLookahead* lookahead = bm_info(not_at_start); | 3993 BoyerMooreLookahead* lookahead = bm_info(not_at_start); |
3994 if (lookahead == NULL) { | 3994 if (lookahead == NULL) { |
3995 eats_at_least = Min(kMaxLookaheadForBoyerMoore, | 3995 eats_at_least = Min(kMaxLookaheadForBoyerMoore, |
3996 EatsAtLeast(kMaxLookaheadForBoyerMoore, | 3996 EatsAtLeast(kMaxLookaheadForBoyerMoore, |
3997 kRecursionBudget, | 3997 kRecursionBudget, |
3998 not_at_start)); | 3998 not_at_start)); |
3999 if (eats_at_least >= 1) { | 3999 if (eats_at_least >= 1) { |
4000 BoyerMooreLookahead* bm = | 4000 BoyerMooreLookahead* bm = |
4001 new(zone()) BoyerMooreLookahead(eats_at_least, | 4001 new(zone()) BoyerMooreLookahead(eats_at_least, |
4002 compiler, | 4002 compiler, |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4167 } | 4167 } |
4168 alternative.node()->Emit(compiler, &out_of_line_trace); | 4168 alternative.node()->Emit(compiler, &out_of_line_trace); |
4169 } | 4169 } |
4170 } | 4170 } |
4171 | 4171 |
4172 | 4172 |
4173 void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) { | 4173 void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
4174 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 4174 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
4175 LimitResult limit_result = LimitVersions(compiler, trace); | 4175 LimitResult limit_result = LimitVersions(compiler, trace); |
4176 if (limit_result == DONE) return; | 4176 if (limit_result == DONE) return; |
4177 ASSERT(limit_result == CONTINUE); | 4177 DCHECK(limit_result == CONTINUE); |
4178 | 4178 |
4179 RecursionCheck rc(compiler); | 4179 RecursionCheck rc(compiler); |
4180 | 4180 |
4181 switch (action_type_) { | 4181 switch (action_type_) { |
4182 case STORE_POSITION: { | 4182 case STORE_POSITION: { |
4183 Trace::DeferredCapture | 4183 Trace::DeferredCapture |
4184 new_capture(data_.u_position_register.reg, | 4184 new_capture(data_.u_position_register.reg, |
4185 data_.u_position_register.is_capture, | 4185 data_.u_position_register.is_capture, |
4186 trace); | 4186 trace); |
4187 Trace new_trace = *trace; | 4187 Trace new_trace = *trace; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4275 int clear_registers_from = data_.u_submatch.clear_register_from; | 4275 int clear_registers_from = data_.u_submatch.clear_register_from; |
4276 Label clear_registers_backtrack; | 4276 Label clear_registers_backtrack; |
4277 Trace new_trace = *trace; | 4277 Trace new_trace = *trace; |
4278 new_trace.set_backtrack(&clear_registers_backtrack); | 4278 new_trace.set_backtrack(&clear_registers_backtrack); |
4279 on_success()->Emit(compiler, &new_trace); | 4279 on_success()->Emit(compiler, &new_trace); |
4280 | 4280 |
4281 assembler->Bind(&clear_registers_backtrack); | 4281 assembler->Bind(&clear_registers_backtrack); |
4282 int clear_registers_to = clear_registers_from + clear_register_count - 1; | 4282 int clear_registers_to = clear_registers_from + clear_register_count - 1; |
4283 assembler->ClearRegisters(clear_registers_from, clear_registers_to); | 4283 assembler->ClearRegisters(clear_registers_from, clear_registers_to); |
4284 | 4284 |
4285 ASSERT(trace->backtrack() == NULL); | 4285 DCHECK(trace->backtrack() == NULL); |
4286 assembler->Backtrack(); | 4286 assembler->Backtrack(); |
4287 return; | 4287 return; |
4288 } | 4288 } |
4289 default: | 4289 default: |
4290 UNREACHABLE(); | 4290 UNREACHABLE(); |
4291 } | 4291 } |
4292 } | 4292 } |
4293 | 4293 |
4294 | 4294 |
4295 void BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) { | 4295 void BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
4296 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 4296 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
4297 if (!trace->is_trivial()) { | 4297 if (!trace->is_trivial()) { |
4298 trace->Flush(compiler, this); | 4298 trace->Flush(compiler, this); |
4299 return; | 4299 return; |
4300 } | 4300 } |
4301 | 4301 |
4302 LimitResult limit_result = LimitVersions(compiler, trace); | 4302 LimitResult limit_result = LimitVersions(compiler, trace); |
4303 if (limit_result == DONE) return; | 4303 if (limit_result == DONE) return; |
4304 ASSERT(limit_result == CONTINUE); | 4304 DCHECK(limit_result == CONTINUE); |
4305 | 4305 |
4306 RecursionCheck rc(compiler); | 4306 RecursionCheck rc(compiler); |
4307 | 4307 |
4308 ASSERT_EQ(start_reg_ + 1, end_reg_); | 4308 DCHECK_EQ(start_reg_ + 1, end_reg_); |
4309 if (compiler->ignore_case()) { | 4309 if (compiler->ignore_case()) { |
4310 assembler->CheckNotBackReferenceIgnoreCase(start_reg_, | 4310 assembler->CheckNotBackReferenceIgnoreCase(start_reg_, |
4311 trace->backtrack()); | 4311 trace->backtrack()); |
4312 } else { | 4312 } else { |
4313 assembler->CheckNotBackReference(start_reg_, trace->backtrack()); | 4313 assembler->CheckNotBackReference(start_reg_, trace->backtrack()); |
4314 } | 4314 } |
4315 on_success()->Emit(compiler, trace); | 4315 on_success()->Emit(compiler, trace); |
4316 } | 4316 } |
4317 | 4317 |
4318 | 4318 |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4679 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler, | 4679 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler, |
4680 RegExpNode* on_success) { | 4680 RegExpNode* on_success) { |
4681 return new(compiler->zone()) TextNode(elements(), on_success); | 4681 return new(compiler->zone()) TextNode(elements(), on_success); |
4682 } | 4682 } |
4683 | 4683 |
4684 | 4684 |
4685 static bool CompareInverseRanges(ZoneList<CharacterRange>* ranges, | 4685 static bool CompareInverseRanges(ZoneList<CharacterRange>* ranges, |
4686 const int* special_class, | 4686 const int* special_class, |
4687 int length) { | 4687 int length) { |
4688 length--; // Remove final 0x10000. | 4688 length--; // Remove final 0x10000. |
4689 ASSERT(special_class[length] == 0x10000); | 4689 DCHECK(special_class[length] == 0x10000); |
4690 ASSERT(ranges->length() != 0); | 4690 DCHECK(ranges->length() != 0); |
4691 ASSERT(length != 0); | 4691 DCHECK(length != 0); |
4692 ASSERT(special_class[0] != 0); | 4692 DCHECK(special_class[0] != 0); |
4693 if (ranges->length() != (length >> 1) + 1) { | 4693 if (ranges->length() != (length >> 1) + 1) { |
4694 return false; | 4694 return false; |
4695 } | 4695 } |
4696 CharacterRange range = ranges->at(0); | 4696 CharacterRange range = ranges->at(0); |
4697 if (range.from() != 0) { | 4697 if (range.from() != 0) { |
4698 return false; | 4698 return false; |
4699 } | 4699 } |
4700 for (int i = 0; i < length; i += 2) { | 4700 for (int i = 0; i < length; i += 2) { |
4701 if (special_class[i] != (range.to() + 1)) { | 4701 if (special_class[i] != (range.to() + 1)) { |
4702 return false; | 4702 return false; |
4703 } | 4703 } |
4704 range = ranges->at((i >> 1) + 1); | 4704 range = ranges->at((i >> 1) + 1); |
4705 if (special_class[i+1] != range.from()) { | 4705 if (special_class[i+1] != range.from()) { |
4706 return false; | 4706 return false; |
4707 } | 4707 } |
4708 } | 4708 } |
4709 if (range.to() != 0xffff) { | 4709 if (range.to() != 0xffff) { |
4710 return false; | 4710 return false; |
4711 } | 4711 } |
4712 return true; | 4712 return true; |
4713 } | 4713 } |
4714 | 4714 |
4715 | 4715 |
4716 static bool CompareRanges(ZoneList<CharacterRange>* ranges, | 4716 static bool CompareRanges(ZoneList<CharacterRange>* ranges, |
4717 const int* special_class, | 4717 const int* special_class, |
4718 int length) { | 4718 int length) { |
4719 length--; // Remove final 0x10000. | 4719 length--; // Remove final 0x10000. |
4720 ASSERT(special_class[length] == 0x10000); | 4720 DCHECK(special_class[length] == 0x10000); |
4721 if (ranges->length() * 2 != length) { | 4721 if (ranges->length() * 2 != length) { |
4722 return false; | 4722 return false; |
4723 } | 4723 } |
4724 for (int i = 0; i < length; i += 2) { | 4724 for (int i = 0; i < length; i += 2) { |
4725 CharacterRange range = ranges->at(i >> 1); | 4725 CharacterRange range = ranges->at(i >> 1); |
4726 if (range.from() != special_class[i] || | 4726 if (range.from() != special_class[i] || |
4727 range.to() != special_class[i + 1] - 1) { | 4727 range.to() != special_class[i + 1] - 1) { |
4728 return false; | 4728 return false; |
4729 } | 4729 } |
4730 } | 4730 } |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4807 | 4807 |
4808 // Scoped object to keep track of how much we unroll quantifier loops in the | 4808 // Scoped object to keep track of how much we unroll quantifier loops in the |
4809 // regexp graph generator. | 4809 // regexp graph generator. |
4810 class RegExpExpansionLimiter { | 4810 class RegExpExpansionLimiter { |
4811 public: | 4811 public: |
4812 static const int kMaxExpansionFactor = 6; | 4812 static const int kMaxExpansionFactor = 6; |
4813 RegExpExpansionLimiter(RegExpCompiler* compiler, int factor) | 4813 RegExpExpansionLimiter(RegExpCompiler* compiler, int factor) |
4814 : compiler_(compiler), | 4814 : compiler_(compiler), |
4815 saved_expansion_factor_(compiler->current_expansion_factor()), | 4815 saved_expansion_factor_(compiler->current_expansion_factor()), |
4816 ok_to_expand_(saved_expansion_factor_ <= kMaxExpansionFactor) { | 4816 ok_to_expand_(saved_expansion_factor_ <= kMaxExpansionFactor) { |
4817 ASSERT(factor > 0); | 4817 DCHECK(factor > 0); |
4818 if (ok_to_expand_) { | 4818 if (ok_to_expand_) { |
4819 if (factor > kMaxExpansionFactor) { | 4819 if (factor > kMaxExpansionFactor) { |
4820 // Avoid integer overflow of the current expansion factor. | 4820 // Avoid integer overflow of the current expansion factor. |
4821 ok_to_expand_ = false; | 4821 ok_to_expand_ = false; |
4822 compiler->set_current_expansion_factor(kMaxExpansionFactor + 1); | 4822 compiler->set_current_expansion_factor(kMaxExpansionFactor + 1); |
4823 } else { | 4823 } else { |
4824 int new_factor = saved_expansion_factor_ * factor; | 4824 int new_factor = saved_expansion_factor_ * factor; |
4825 ok_to_expand_ = (new_factor <= kMaxExpansionFactor); | 4825 ok_to_expand_ = (new_factor <= kMaxExpansionFactor); |
4826 compiler->set_current_expansion_factor(new_factor); | 4826 compiler->set_current_expansion_factor(new_factor); |
4827 } | 4827 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4896 // Unroll the forced matches from 0 to min. This can cause chains of | 4896 // Unroll the forced matches from 0 to min. This can cause chains of |
4897 // TextNodes (which the parser does not generate). These should be | 4897 // TextNodes (which the parser does not generate). These should be |
4898 // combined if it turns out they hinder good code generation. | 4898 // combined if it turns out they hinder good code generation. |
4899 for (int i = 0; i < min; i++) { | 4899 for (int i = 0; i < min; i++) { |
4900 answer = body->ToNode(compiler, answer); | 4900 answer = body->ToNode(compiler, answer); |
4901 } | 4901 } |
4902 return answer; | 4902 return answer; |
4903 } | 4903 } |
4904 } | 4904 } |
4905 if (max <= kMaxUnrolledMaxMatches && min == 0) { | 4905 if (max <= kMaxUnrolledMaxMatches && min == 0) { |
4906 ASSERT(max > 0); // Due to the 'if' above. | 4906 DCHECK(max > 0); // Due to the 'if' above. |
4907 RegExpExpansionLimiter limiter(compiler, max); | 4907 RegExpExpansionLimiter limiter(compiler, max); |
4908 if (limiter.ok_to_expand()) { | 4908 if (limiter.ok_to_expand()) { |
4909 // Unroll the optional matches up to max. | 4909 // Unroll the optional matches up to max. |
4910 RegExpNode* answer = on_success; | 4910 RegExpNode* answer = on_success; |
4911 for (int i = 0; i < max; i++) { | 4911 for (int i = 0; i < max; i++) { |
4912 ChoiceNode* alternation = new(zone) ChoiceNode(2, zone); | 4912 ChoiceNode* alternation = new(zone) ChoiceNode(2, zone); |
4913 if (is_greedy) { | 4913 if (is_greedy) { |
4914 alternation->AddAlternative( | 4914 alternation->AddAlternative( |
4915 GuardedAlternative(body->ToNode(compiler, answer))); | 4915 GuardedAlternative(body->ToNode(compiler, answer))); |
4916 alternation->AddAlternative(GuardedAlternative(on_success)); | 4916 alternation->AddAlternative(GuardedAlternative(on_success)); |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5135 } | 5135 } |
5136 return current; | 5136 return current; |
5137 } | 5137 } |
5138 | 5138 |
5139 | 5139 |
5140 static void AddClass(const int* elmv, | 5140 static void AddClass(const int* elmv, |
5141 int elmc, | 5141 int elmc, |
5142 ZoneList<CharacterRange>* ranges, | 5142 ZoneList<CharacterRange>* ranges, |
5143 Zone* zone) { | 5143 Zone* zone) { |
5144 elmc--; | 5144 elmc--; |
5145 ASSERT(elmv[elmc] == 0x10000); | 5145 DCHECK(elmv[elmc] == 0x10000); |
5146 for (int i = 0; i < elmc; i += 2) { | 5146 for (int i = 0; i < elmc; i += 2) { |
5147 ASSERT(elmv[i] < elmv[i + 1]); | 5147 DCHECK(elmv[i] < elmv[i + 1]); |
5148 ranges->Add(CharacterRange(elmv[i], elmv[i + 1] - 1), zone); | 5148 ranges->Add(CharacterRange(elmv[i], elmv[i + 1] - 1), zone); |
5149 } | 5149 } |
5150 } | 5150 } |
5151 | 5151 |
5152 | 5152 |
5153 static void AddClassNegated(const int *elmv, | 5153 static void AddClassNegated(const int *elmv, |
5154 int elmc, | 5154 int elmc, |
5155 ZoneList<CharacterRange>* ranges, | 5155 ZoneList<CharacterRange>* ranges, |
5156 Zone* zone) { | 5156 Zone* zone) { |
5157 elmc--; | 5157 elmc--; |
5158 ASSERT(elmv[elmc] == 0x10000); | 5158 DCHECK(elmv[elmc] == 0x10000); |
5159 ASSERT(elmv[0] != 0x0000); | 5159 DCHECK(elmv[0] != 0x0000); |
5160 ASSERT(elmv[elmc-1] != String::kMaxUtf16CodeUnit); | 5160 DCHECK(elmv[elmc-1] != String::kMaxUtf16CodeUnit); |
5161 uc16 last = 0x0000; | 5161 uc16 last = 0x0000; |
5162 for (int i = 0; i < elmc; i += 2) { | 5162 for (int i = 0; i < elmc; i += 2) { |
5163 ASSERT(last <= elmv[i] - 1); | 5163 DCHECK(last <= elmv[i] - 1); |
5164 ASSERT(elmv[i] < elmv[i + 1]); | 5164 DCHECK(elmv[i] < elmv[i + 1]); |
5165 ranges->Add(CharacterRange(last, elmv[i] - 1), zone); | 5165 ranges->Add(CharacterRange(last, elmv[i] - 1), zone); |
5166 last = elmv[i + 1]; | 5166 last = elmv[i + 1]; |
5167 } | 5167 } |
5168 ranges->Add(CharacterRange(last, String::kMaxUtf16CodeUnit), zone); | 5168 ranges->Add(CharacterRange(last, String::kMaxUtf16CodeUnit), zone); |
5169 } | 5169 } |
5170 | 5170 |
5171 | 5171 |
5172 void CharacterRange::AddClassEscape(uc16 type, | 5172 void CharacterRange::AddClassEscape(uc16 type, |
5173 ZoneList<CharacterRange>* ranges, | 5173 ZoneList<CharacterRange>* ranges, |
5174 Zone* zone) { | 5174 Zone* zone) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5250 if (*target == NULL) *target = new(zone_) ZoneList<CharacterRange>(2, zone_); | 5250 if (*target == NULL) *target = new(zone_) ZoneList<CharacterRange>(2, zone_); |
5251 (*target)->Add(CharacterRange(entry.from(), entry.to()), zone_); | 5251 (*target)->Add(CharacterRange(entry.from(), entry.to()), zone_); |
5252 } | 5252 } |
5253 | 5253 |
5254 | 5254 |
5255 void CharacterRange::Split(ZoneList<CharacterRange>* base, | 5255 void CharacterRange::Split(ZoneList<CharacterRange>* base, |
5256 Vector<const int> overlay, | 5256 Vector<const int> overlay, |
5257 ZoneList<CharacterRange>** included, | 5257 ZoneList<CharacterRange>** included, |
5258 ZoneList<CharacterRange>** excluded, | 5258 ZoneList<CharacterRange>** excluded, |
5259 Zone* zone) { | 5259 Zone* zone) { |
5260 ASSERT_EQ(NULL, *included); | 5260 DCHECK_EQ(NULL, *included); |
5261 ASSERT_EQ(NULL, *excluded); | 5261 DCHECK_EQ(NULL, *excluded); |
5262 DispatchTable table(zone); | 5262 DispatchTable table(zone); |
5263 for (int i = 0; i < base->length(); i++) | 5263 for (int i = 0; i < base->length(); i++) |
5264 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase, zone); | 5264 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase, zone); |
5265 for (int i = 0; i < overlay.length(); i += 2) { | 5265 for (int i = 0; i < overlay.length(); i += 2) { |
5266 table.AddRange(CharacterRange(overlay[i], overlay[i + 1] - 1), | 5266 table.AddRange(CharacterRange(overlay[i], overlay[i + 1] - 1), |
5267 CharacterRangeSplitter::kInOverlay, zone); | 5267 CharacterRangeSplitter::kInOverlay, zone); |
5268 } | 5268 } |
5269 CharacterRangeSplitter callback(included, excluded, zone); | 5269 CharacterRangeSplitter callback(included, excluded, zone); |
5270 table.ForEach(&callback); | 5270 table.ForEach(&callback); |
5271 } | 5271 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5311 // covered by the range (handling characters that is not in a block | 5311 // covered by the range (handling characters that is not in a block |
5312 // as a "singleton block"). | 5312 // as a "singleton block"). |
5313 unibrow::uchar range[unibrow::Ecma262UnCanonicalize::kMaxWidth]; | 5313 unibrow::uchar range[unibrow::Ecma262UnCanonicalize::kMaxWidth]; |
5314 int pos = bottom; | 5314 int pos = bottom; |
5315 while (pos <= top) { | 5315 while (pos <= top) { |
5316 int length = isolate->jsregexp_canonrange()->get(pos, '\0', range); | 5316 int length = isolate->jsregexp_canonrange()->get(pos, '\0', range); |
5317 uc16 block_end; | 5317 uc16 block_end; |
5318 if (length == 0) { | 5318 if (length == 0) { |
5319 block_end = pos; | 5319 block_end = pos; |
5320 } else { | 5320 } else { |
5321 ASSERT_EQ(1, length); | 5321 DCHECK_EQ(1, length); |
5322 block_end = range[0]; | 5322 block_end = range[0]; |
5323 } | 5323 } |
5324 int end = (block_end > top) ? top : block_end; | 5324 int end = (block_end > top) ? top : block_end; |
5325 length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0', range); | 5325 length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0', range); |
5326 for (int i = 0; i < length; i++) { | 5326 for (int i = 0; i < length; i++) { |
5327 uc32 c = range[i]; | 5327 uc32 c = range[i]; |
5328 uc16 range_from = c - (block_end - pos); | 5328 uc16 range_from = c - (block_end - pos); |
5329 uc16 range_to = c - (block_end - end); | 5329 uc16 range_to = c - (block_end - end); |
5330 if (!(bottom <= range_from && range_to <= top)) { | 5330 if (!(bottom <= range_from && range_to <= top)) { |
5331 ranges->Add(CharacterRange(range_from, range_to), zone); | 5331 ranges->Add(CharacterRange(range_from, range_to), zone); |
5332 } | 5332 } |
5333 } | 5333 } |
5334 pos = end + 1; | 5334 pos = end + 1; |
5335 } | 5335 } |
5336 } | 5336 } |
5337 } | 5337 } |
5338 | 5338 |
5339 | 5339 |
5340 bool CharacterRange::IsCanonical(ZoneList<CharacterRange>* ranges) { | 5340 bool CharacterRange::IsCanonical(ZoneList<CharacterRange>* ranges) { |
5341 ASSERT_NOT_NULL(ranges); | 5341 DCHECK_NOT_NULL(ranges); |
5342 int n = ranges->length(); | 5342 int n = ranges->length(); |
5343 if (n <= 1) return true; | 5343 if (n <= 1) return true; |
5344 int max = ranges->at(0).to(); | 5344 int max = ranges->at(0).to(); |
5345 for (int i = 1; i < n; i++) { | 5345 for (int i = 1; i < n; i++) { |
5346 CharacterRange next_range = ranges->at(i); | 5346 CharacterRange next_range = ranges->at(i); |
5347 if (next_range.from() <= max + 1) return false; | 5347 if (next_range.from() <= max + 1) return false; |
5348 max = next_range.to(); | 5348 max = next_range.to(); |
5349 } | 5349 } |
5350 return true; | 5350 return true; |
5351 } | 5351 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5471 int read = i; // Range to insert. | 5471 int read = i; // Range to insert. |
5472 int num_canonical = i; // Length of canonicalized part of list. | 5472 int num_canonical = i; // Length of canonicalized part of list. |
5473 do { | 5473 do { |
5474 num_canonical = InsertRangeInCanonicalList(character_ranges, | 5474 num_canonical = InsertRangeInCanonicalList(character_ranges, |
5475 num_canonical, | 5475 num_canonical, |
5476 character_ranges->at(read)); | 5476 character_ranges->at(read)); |
5477 read++; | 5477 read++; |
5478 } while (read < n); | 5478 } while (read < n); |
5479 character_ranges->Rewind(num_canonical); | 5479 character_ranges->Rewind(num_canonical); |
5480 | 5480 |
5481 ASSERT(CharacterRange::IsCanonical(character_ranges)); | 5481 DCHECK(CharacterRange::IsCanonical(character_ranges)); |
5482 } | 5482 } |
5483 | 5483 |
5484 | 5484 |
5485 void CharacterRange::Negate(ZoneList<CharacterRange>* ranges, | 5485 void CharacterRange::Negate(ZoneList<CharacterRange>* ranges, |
5486 ZoneList<CharacterRange>* negated_ranges, | 5486 ZoneList<CharacterRange>* negated_ranges, |
5487 Zone* zone) { | 5487 Zone* zone) { |
5488 ASSERT(CharacterRange::IsCanonical(ranges)); | 5488 DCHECK(CharacterRange::IsCanonical(ranges)); |
5489 ASSERT_EQ(0, negated_ranges->length()); | 5489 DCHECK_EQ(0, negated_ranges->length()); |
5490 int range_count = ranges->length(); | 5490 int range_count = ranges->length(); |
5491 uc16 from = 0; | 5491 uc16 from = 0; |
5492 int i = 0; | 5492 int i = 0; |
5493 if (range_count > 0 && ranges->at(0).from() == 0) { | 5493 if (range_count > 0 && ranges->at(0).from() == 0) { |
5494 from = ranges->at(0).to(); | 5494 from = ranges->at(0).to(); |
5495 i = 1; | 5495 i = 1; |
5496 } | 5496 } |
5497 while (i < range_count) { | 5497 while (i < range_count) { |
5498 CharacterRange range = ranges->at(i); | 5498 CharacterRange range = ranges->at(i); |
5499 negated_ranges->Add(CharacterRange(from + 1, range.from() - 1), zone); | 5499 negated_ranges->Add(CharacterRange(from + 1, range.from() - 1), zone); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5555 | 5555 |
5556 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar; | 5556 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar; |
5557 | 5557 |
5558 | 5558 |
5559 void DispatchTable::AddRange(CharacterRange full_range, int value, | 5559 void DispatchTable::AddRange(CharacterRange full_range, int value, |
5560 Zone* zone) { | 5560 Zone* zone) { |
5561 CharacterRange current = full_range; | 5561 CharacterRange current = full_range; |
5562 if (tree()->is_empty()) { | 5562 if (tree()->is_empty()) { |
5563 // If this is the first range we just insert into the table. | 5563 // If this is the first range we just insert into the table. |
5564 ZoneSplayTree<Config>::Locator loc; | 5564 ZoneSplayTree<Config>::Locator loc; |
5565 ASSERT_RESULT(tree()->Insert(current.from(), &loc)); | 5565 DCHECK_RESULT(tree()->Insert(current.from(), &loc)); |
5566 loc.set_value(Entry(current.from(), current.to(), | 5566 loc.set_value(Entry(current.from(), current.to(), |
5567 empty()->Extend(value, zone))); | 5567 empty()->Extend(value, zone))); |
5568 return; | 5568 return; |
5569 } | 5569 } |
5570 // First see if there is a range to the left of this one that | 5570 // First see if there is a range to the left of this one that |
5571 // overlaps. | 5571 // overlaps. |
5572 ZoneSplayTree<Config>::Locator loc; | 5572 ZoneSplayTree<Config>::Locator loc; |
5573 if (tree()->FindGreatestLessThan(current.from(), &loc)) { | 5573 if (tree()->FindGreatestLessThan(current.from(), &loc)) { |
5574 Entry* entry = &loc.value(); | 5574 Entry* entry = &loc.value(); |
5575 // If we've found a range that overlaps with this one, and it | 5575 // If we've found a range that overlaps with this one, and it |
5576 // starts strictly to the left of this one, we have to fix it | 5576 // starts strictly to the left of this one, we have to fix it |
5577 // because the following code only handles ranges that start on | 5577 // because the following code only handles ranges that start on |
5578 // or after the start point of the range we're adding. | 5578 // or after the start point of the range we're adding. |
5579 if (entry->from() < current.from() && entry->to() >= current.from()) { | 5579 if (entry->from() < current.from() && entry->to() >= current.from()) { |
5580 // Snap the overlapping range in half around the start point of | 5580 // Snap the overlapping range in half around the start point of |
5581 // the range we're adding. | 5581 // the range we're adding. |
5582 CharacterRange left(entry->from(), current.from() - 1); | 5582 CharacterRange left(entry->from(), current.from() - 1); |
5583 CharacterRange right(current.from(), entry->to()); | 5583 CharacterRange right(current.from(), entry->to()); |
5584 // The left part of the overlapping range doesn't overlap. | 5584 // The left part of the overlapping range doesn't overlap. |
5585 // Truncate the whole entry to be just the left part. | 5585 // Truncate the whole entry to be just the left part. |
5586 entry->set_to(left.to()); | 5586 entry->set_to(left.to()); |
5587 // The right part is the one that overlaps. We add this part | 5587 // The right part is the one that overlaps. We add this part |
5588 // to the map and let the next step deal with merging it with | 5588 // to the map and let the next step deal with merging it with |
5589 // the range we're adding. | 5589 // the range we're adding. |
5590 ZoneSplayTree<Config>::Locator loc; | 5590 ZoneSplayTree<Config>::Locator loc; |
5591 ASSERT_RESULT(tree()->Insert(right.from(), &loc)); | 5591 DCHECK_RESULT(tree()->Insert(right.from(), &loc)); |
5592 loc.set_value(Entry(right.from(), | 5592 loc.set_value(Entry(right.from(), |
5593 right.to(), | 5593 right.to(), |
5594 entry->out_set())); | 5594 entry->out_set())); |
5595 } | 5595 } |
5596 } | 5596 } |
5597 while (current.is_valid()) { | 5597 while (current.is_valid()) { |
5598 if (tree()->FindLeastGreaterThan(current.from(), &loc) && | 5598 if (tree()->FindLeastGreaterThan(current.from(), &loc) && |
5599 (loc.value().from() <= current.to()) && | 5599 (loc.value().from() <= current.to()) && |
5600 (loc.value().to() >= current.from())) { | 5600 (loc.value().to() >= current.from())) { |
5601 Entry* entry = &loc.value(); | 5601 Entry* entry = &loc.value(); |
5602 // We have overlap. If there is space between the start point of | 5602 // We have overlap. If there is space between the start point of |
5603 // the range we're adding and where the overlapping range starts | 5603 // the range we're adding and where the overlapping range starts |
5604 // then we have to add a range covering just that space. | 5604 // then we have to add a range covering just that space. |
5605 if (current.from() < entry->from()) { | 5605 if (current.from() < entry->from()) { |
5606 ZoneSplayTree<Config>::Locator ins; | 5606 ZoneSplayTree<Config>::Locator ins; |
5607 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); | 5607 DCHECK_RESULT(tree()->Insert(current.from(), &ins)); |
5608 ins.set_value(Entry(current.from(), | 5608 ins.set_value(Entry(current.from(), |
5609 entry->from() - 1, | 5609 entry->from() - 1, |
5610 empty()->Extend(value, zone))); | 5610 empty()->Extend(value, zone))); |
5611 current.set_from(entry->from()); | 5611 current.set_from(entry->from()); |
5612 } | 5612 } |
5613 ASSERT_EQ(current.from(), entry->from()); | 5613 DCHECK_EQ(current.from(), entry->from()); |
5614 // If the overlapping range extends beyond the one we want to add | 5614 // If the overlapping range extends beyond the one we want to add |
5615 // we have to snap the right part off and add it separately. | 5615 // we have to snap the right part off and add it separately. |
5616 if (entry->to() > current.to()) { | 5616 if (entry->to() > current.to()) { |
5617 ZoneSplayTree<Config>::Locator ins; | 5617 ZoneSplayTree<Config>::Locator ins; |
5618 ASSERT_RESULT(tree()->Insert(current.to() + 1, &ins)); | 5618 DCHECK_RESULT(tree()->Insert(current.to() + 1, &ins)); |
5619 ins.set_value(Entry(current.to() + 1, | 5619 ins.set_value(Entry(current.to() + 1, |
5620 entry->to(), | 5620 entry->to(), |
5621 entry->out_set())); | 5621 entry->out_set())); |
5622 entry->set_to(current.to()); | 5622 entry->set_to(current.to()); |
5623 } | 5623 } |
5624 ASSERT(entry->to() <= current.to()); | 5624 DCHECK(entry->to() <= current.to()); |
5625 // The overlapping range is now completely contained by the range | 5625 // The overlapping range is now completely contained by the range |
5626 // we're adding so we can just update it and move the start point | 5626 // we're adding so we can just update it and move the start point |
5627 // of the range we're adding just past it. | 5627 // of the range we're adding just past it. |
5628 entry->AddValue(value, zone); | 5628 entry->AddValue(value, zone); |
5629 // Bail out if the last interval ended at 0xFFFF since otherwise | 5629 // Bail out if the last interval ended at 0xFFFF since otherwise |
5630 // adding 1 will wrap around to 0. | 5630 // adding 1 will wrap around to 0. |
5631 if (entry->to() == String::kMaxUtf16CodeUnit) | 5631 if (entry->to() == String::kMaxUtf16CodeUnit) |
5632 break; | 5632 break; |
5633 ASSERT(entry->to() + 1 > current.from()); | 5633 DCHECK(entry->to() + 1 > current.from()); |
5634 current.set_from(entry->to() + 1); | 5634 current.set_from(entry->to() + 1); |
5635 } else { | 5635 } else { |
5636 // There is no overlap so we can just add the range | 5636 // There is no overlap so we can just add the range |
5637 ZoneSplayTree<Config>::Locator ins; | 5637 ZoneSplayTree<Config>::Locator ins; |
5638 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); | 5638 DCHECK_RESULT(tree()->Insert(current.from(), &ins)); |
5639 ins.set_value(Entry(current.from(), | 5639 ins.set_value(Entry(current.from(), |
5640 current.to(), | 5640 current.to(), |
5641 empty()->Extend(value, zone))); | 5641 empty()->Extend(value, zone))); |
5642 break; | 5642 break; |
5643 } | 5643 } |
5644 } | 5644 } |
5645 } | 5645 } |
5646 | 5646 |
5647 | 5647 |
5648 OutSet* DispatchTable::Get(uc16 value) { | 5648 OutSet* DispatchTable::Get(uc16 value) { |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5821 bm->max_char() == String::kMaxOneByteCharCode, | 5821 bm->max_char() == String::kMaxOneByteCharCode, |
5822 chars); | 5822 chars); |
5823 for (int j = 0; j < length; j++) { | 5823 for (int j = 0; j < length; j++) { |
5824 bm->Set(offset, chars[j]); | 5824 bm->Set(offset, chars[j]); |
5825 } | 5825 } |
5826 } else { | 5826 } else { |
5827 if (character <= max_char) bm->Set(offset, character); | 5827 if (character <= max_char) bm->Set(offset, character); |
5828 } | 5828 } |
5829 } | 5829 } |
5830 } else { | 5830 } else { |
5831 ASSERT_EQ(TextElement::CHAR_CLASS, text.text_type()); | 5831 DCHECK_EQ(TextElement::CHAR_CLASS, text.text_type()); |
5832 RegExpCharacterClass* char_class = text.char_class(); | 5832 RegExpCharacterClass* char_class = text.char_class(); |
5833 ZoneList<CharacterRange>* ranges = char_class->ranges(zone()); | 5833 ZoneList<CharacterRange>* ranges = char_class->ranges(zone()); |
5834 if (char_class->is_negated()) { | 5834 if (char_class->is_negated()) { |
5835 bm->SetAll(offset); | 5835 bm->SetAll(offset); |
5836 } else { | 5836 } else { |
5837 for (int k = 0; k < ranges->length(); k++) { | 5837 for (int k = 0; k < ranges->length(); k++) { |
5838 CharacterRange& range = ranges->at(k); | 5838 CharacterRange& range = ranges->at(k); |
5839 if (range.from() > max_char) continue; | 5839 if (range.from() > max_char) continue; |
5840 int to = Min(max_char, static_cast<int>(range.to())); | 5840 int to = Min(max_char, static_cast<int>(range.to())); |
5841 bm->SetInterval(offset, Interval(range.from(), to)); | 5841 bm->SetInterval(offset, Interval(range.from(), to)); |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6104 } | 6104 } |
6105 | 6105 |
6106 return compiler.Assemble(¯o_assembler, | 6106 return compiler.Assemble(¯o_assembler, |
6107 node, | 6107 node, |
6108 data->capture_count, | 6108 data->capture_count, |
6109 pattern); | 6109 pattern); |
6110 } | 6110 } |
6111 | 6111 |
6112 | 6112 |
6113 }} // namespace v8::internal | 6113 }} // namespace v8::internal |
OLD | NEW |