Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: src/jsregexp.cc

Issue 430503007: Rename ASSERT* to DCHECK*. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE and fixes Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/jsregexp.h ('k') | src/libplatform/default-platform.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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 &register_array_[current_match_index_ * registers_per_match_]; 742 &register_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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
6104 } 6104 }
6105 6105
6106 return compiler.Assemble(&macro_assembler, 6106 return compiler.Assemble(&macro_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
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | src/libplatform/default-platform.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698