OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 int to) { | 271 int to) { |
272 NoHandleAllocation no_handles; | 272 NoHandleAllocation no_handles; |
273 RegExpImpl::SetLastCaptureCount(array, 2); | 273 RegExpImpl::SetLastCaptureCount(array, 2); |
274 RegExpImpl::SetLastSubject(array, subject); | 274 RegExpImpl::SetLastSubject(array, subject); |
275 RegExpImpl::SetLastInput(array, subject); | 275 RegExpImpl::SetLastInput(array, subject); |
276 RegExpImpl::SetCapture(array, 0, from); | 276 RegExpImpl::SetCapture(array, 0, from); |
277 RegExpImpl::SetCapture(array, 1, to); | 277 RegExpImpl::SetCapture(array, 1, to); |
278 } | 278 } |
279 | 279 |
280 | 280 |
281 Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re, | 281 int RegExpImpl::AtomExecRaw(Handle<JSRegExp> regexp, |
282 Handle<String> subject, | 282 Handle<String> subject, |
283 int index, | 283 int index, |
284 Handle<JSArray> last_match_info) { | 284 int32_t* output, |
285 Isolate* isolate = re->GetIsolate(); | 285 int output_size) { |
| 286 Isolate* isolate = regexp->GetIsolate(); |
286 | 287 |
287 ASSERT(0 <= index); | 288 ASSERT(0 <= index); |
288 ASSERT(index <= subject->length()); | 289 ASSERT(index <= subject->length()); |
289 | 290 |
290 if (!subject->IsFlat()) FlattenString(subject); | 291 if (!subject->IsFlat()) FlattenString(subject); |
291 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid | 292 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid |
292 | 293 |
293 String* needle = String::cast(re->DataAt(JSRegExp::kAtomPatternIndex)); | 294 String* needle = String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)); |
294 int needle_len = needle->length(); | 295 int needle_len = needle->length(); |
295 ASSERT(needle->IsFlat()); | 296 ASSERT(needle->IsFlat()); |
| 297 ASSERT_LT(0, needle_len); |
296 | 298 |
297 if (needle_len != 0) { | 299 if (index + needle_len > subject->length()) { |
298 if (index + needle_len > subject->length()) { | 300 return RegExpImpl::RE_FAILURE; |
299 return isolate->factory()->null_value(); | 301 } |
300 } | |
301 | 302 |
| 303 for (int i = 0; i < output_size; i += 2) { |
302 String::FlatContent needle_content = needle->GetFlatContent(); | 304 String::FlatContent needle_content = needle->GetFlatContent(); |
303 String::FlatContent subject_content = subject->GetFlatContent(); | 305 String::FlatContent subject_content = subject->GetFlatContent(); |
304 ASSERT(needle_content.IsFlat()); | 306 ASSERT(needle_content.IsFlat()); |
305 ASSERT(subject_content.IsFlat()); | 307 ASSERT(subject_content.IsFlat()); |
306 // dispatch on type of strings | 308 // dispatch on type of strings |
307 index = (needle_content.IsAscii() | 309 index = (needle_content.IsAscii() |
308 ? (subject_content.IsAscii() | 310 ? (subject_content.IsAscii() |
309 ? SearchString(isolate, | 311 ? SearchString(isolate, |
310 subject_content.ToAsciiVector(), | 312 subject_content.ToAsciiVector(), |
311 needle_content.ToAsciiVector(), | 313 needle_content.ToAsciiVector(), |
312 index) | 314 index) |
313 : SearchString(isolate, | 315 : SearchString(isolate, |
314 subject_content.ToUC16Vector(), | 316 subject_content.ToUC16Vector(), |
315 needle_content.ToAsciiVector(), | 317 needle_content.ToAsciiVector(), |
316 index)) | 318 index)) |
317 : (subject_content.IsAscii() | 319 : (subject_content.IsAscii() |
318 ? SearchString(isolate, | 320 ? SearchString(isolate, |
319 subject_content.ToAsciiVector(), | 321 subject_content.ToAsciiVector(), |
320 needle_content.ToUC16Vector(), | 322 needle_content.ToUC16Vector(), |
321 index) | 323 index) |
322 : SearchString(isolate, | 324 : SearchString(isolate, |
323 subject_content.ToUC16Vector(), | 325 subject_content.ToUC16Vector(), |
324 needle_content.ToUC16Vector(), | 326 needle_content.ToUC16Vector(), |
325 index))); | 327 index))); |
326 if (index == -1) return isolate->factory()->null_value(); | 328 if (index == -1) { |
| 329 return i / 2; // Return number of matches. |
| 330 } else { |
| 331 output[i] = index; |
| 332 output[i+1] = index + needle_len; |
| 333 index += needle_len; |
| 334 } |
327 } | 335 } |
328 ASSERT(last_match_info->HasFastObjectElements()); | 336 return output_size / 2; |
| 337 } |
329 | 338 |
330 { | 339 |
331 NoHandleAllocation no_handles; | 340 Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re, |
332 FixedArray* array = FixedArray::cast(last_match_info->elements()); | 341 Handle<String> subject, |
333 SetAtomLastCapture(array, *subject, index, index + needle_len); | 342 int index, |
334 } | 343 Handle<JSArray> last_match_info) { |
| 344 Isolate* isolate = re->GetIsolate(); |
| 345 |
| 346 static const int kNumRegisters = 2; |
| 347 STATIC_ASSERT(kNumRegisters <= Isolate::kJSRegexpStaticOffsetsVectorSize); |
| 348 int32_t* output_registers = isolate->jsregexp_static_offsets_vector(); |
| 349 |
| 350 int res = AtomExecRaw(re, subject, index, output_registers, kNumRegisters); |
| 351 |
| 352 if (res == RegExpImpl::RE_FAILURE) return isolate->factory()->null_value(); |
| 353 |
| 354 ASSERT_EQ(res, RegExpImpl::RE_SUCCESS); |
| 355 NoHandleAllocation no_handles; |
| 356 FixedArray* array = FixedArray::cast(last_match_info->elements()); |
| 357 SetAtomLastCapture(array, *subject, output_registers[0], output_registers[1]); |
335 return last_match_info; | 358 return last_match_info; |
336 } | 359 } |
337 | 360 |
338 | 361 |
339 // Irregexp implementation. | 362 // Irregexp implementation. |
340 | 363 |
341 // Ensures that the regexp object contains a compiled version of the | 364 // Ensures that the regexp object contains a compiled version of the |
342 // source for either ASCII or non-ASCII strings. | 365 // source for either ASCII or non-ASCII strings. |
343 // If the compiled version doesn't already exist, it is compiled | 366 // If the compiled version doesn't already exist, it is compiled |
344 // from the source pattern. | 367 // from the source pattern. |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 int RegExpImpl::IrregexpPrepare(Handle<JSRegExp> regexp, | 527 int RegExpImpl::IrregexpPrepare(Handle<JSRegExp> regexp, |
505 Handle<String> subject) { | 528 Handle<String> subject) { |
506 if (!subject->IsFlat()) FlattenString(subject); | 529 if (!subject->IsFlat()) FlattenString(subject); |
507 | 530 |
508 // Check the asciiness of the underlying storage. | 531 // Check the asciiness of the underlying storage. |
509 bool is_ascii = subject->IsAsciiRepresentationUnderneath(); | 532 bool is_ascii = subject->IsAsciiRepresentationUnderneath(); |
510 if (!EnsureCompiledIrregexp(regexp, subject, is_ascii)) return -1; | 533 if (!EnsureCompiledIrregexp(regexp, subject, is_ascii)) return -1; |
511 | 534 |
512 #ifdef V8_INTERPRETED_REGEXP | 535 #ifdef V8_INTERPRETED_REGEXP |
513 // Byte-code regexp needs space allocated for all its registers. | 536 // Byte-code regexp needs space allocated for all its registers. |
514 return IrregexpNumberOfRegisters(FixedArray::cast(regexp->data())); | 537 // The result captures are copied to the start of the registers array |
| 538 // if the match succeeds. This way those registers are not clobbered |
| 539 // when we set the last match info from last successful match. |
| 540 return IrregexpNumberOfRegisters(FixedArray::cast(regexp->data())) + |
| 541 (IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())) + 1) * 2; |
515 #else // V8_INTERPRETED_REGEXP | 542 #else // V8_INTERPRETED_REGEXP |
516 // Native regexp only needs room to output captures. Registers are handled | 543 // Native regexp only needs room to output captures. Registers are handled |
517 // internally. | 544 // internally. |
518 return (IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())) + 1) * 2; | 545 return (IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())) + 1) * 2; |
519 #endif // V8_INTERPRETED_REGEXP | 546 #endif // V8_INTERPRETED_REGEXP |
520 } | 547 } |
521 | 548 |
522 | 549 |
523 int RegExpImpl::GlobalOffsetsVectorSize(Handle<JSRegExp> regexp, | 550 int RegExpImpl::GlobalOffsetsVectorSize(Handle<JSRegExp> regexp, |
524 int registers_per_match, | 551 int registers_per_match, |
525 int* max_matches) { | 552 int* max_matches) { |
526 #ifdef V8_INTERPRETED_REGEXP | 553 #ifdef V8_INTERPRETED_REGEXP |
527 // Global loop in interpreted regexp is not implemented. Therefore we choose | 554 // Global loop in interpreted regexp is not implemented. Therefore we choose |
528 // the size of the offsets vector so that it can only store one match. | 555 // the size of the offsets vector so that it can only store one match. |
529 *max_matches = 1; | 556 *max_matches = 1; |
530 return registers_per_match; | 557 return registers_per_match; |
531 #else // V8_INTERPRETED_REGEXP | 558 #else // V8_INTERPRETED_REGEXP |
532 int size = Max(registers_per_match, OffsetsVector::kStaticOffsetsVectorSize); | 559 int size = |
| 560 Max(registers_per_match, Isolate::kJSRegexpStaticOffsetsVectorSize); |
533 *max_matches = size / registers_per_match; | 561 *max_matches = size / registers_per_match; |
534 return size; | 562 return size; |
535 #endif // V8_INTERPRETED_REGEXP | 563 #endif // V8_INTERPRETED_REGEXP |
536 } | 564 } |
537 | 565 |
538 | 566 |
539 int RegExpImpl::IrregexpExecRaw( | 567 int RegExpImpl::IrregexpExecRaw(Handle<JSRegExp> regexp, |
540 Handle<JSRegExp> regexp, | 568 Handle<String> subject, |
541 Handle<String> subject, | 569 int index, |
542 int index, | 570 int32_t* output, |
543 Vector<int> output) { | 571 int output_size) { |
544 Isolate* isolate = regexp->GetIsolate(); | 572 Isolate* isolate = regexp->GetIsolate(); |
545 | 573 |
546 Handle<FixedArray> irregexp(FixedArray::cast(regexp->data()), isolate); | 574 Handle<FixedArray> irregexp(FixedArray::cast(regexp->data()), isolate); |
547 | 575 |
548 ASSERT(index >= 0); | 576 ASSERT(index >= 0); |
549 ASSERT(index <= subject->length()); | 577 ASSERT(index <= subject->length()); |
550 ASSERT(subject->IsFlat()); | 578 ASSERT(subject->IsFlat()); |
551 | 579 |
552 bool is_ascii = subject->IsAsciiRepresentationUnderneath(); | 580 bool is_ascii = subject->IsAsciiRepresentationUnderneath(); |
553 | 581 |
554 #ifndef V8_INTERPRETED_REGEXP | 582 #ifndef V8_INTERPRETED_REGEXP |
555 ASSERT(output.length() >= (IrregexpNumberOfCaptures(*irregexp) + 1) * 2); | 583 ASSERT(output_size >= (IrregexpNumberOfCaptures(*irregexp) + 1) * 2); |
556 do { | 584 do { |
557 EnsureCompiledIrregexp(regexp, subject, is_ascii); | 585 EnsureCompiledIrregexp(regexp, subject, is_ascii); |
558 Handle<Code> code(IrregexpNativeCode(*irregexp, is_ascii), isolate); | 586 Handle<Code> code(IrregexpNativeCode(*irregexp, is_ascii), isolate); |
| 587 // The stack is used to allocate registers for the compiled regexp code. |
| 588 // This means that in case of failure, the output registers array is left |
| 589 // untouched and contains the capture results from the previous successful |
| 590 // match. We can use that to set the last match info lazily. |
559 NativeRegExpMacroAssembler::Result res = | 591 NativeRegExpMacroAssembler::Result res = |
560 NativeRegExpMacroAssembler::Match(code, | 592 NativeRegExpMacroAssembler::Match(code, |
561 subject, | 593 subject, |
562 output.start(), | 594 output, |
563 output.length(), | 595 output_size, |
564 index, | 596 index, |
565 isolate); | 597 isolate); |
566 if (res != NativeRegExpMacroAssembler::RETRY) { | 598 if (res != NativeRegExpMacroAssembler::RETRY) { |
567 ASSERT(res != NativeRegExpMacroAssembler::EXCEPTION || | 599 ASSERT(res != NativeRegExpMacroAssembler::EXCEPTION || |
568 isolate->has_pending_exception()); | 600 isolate->has_pending_exception()); |
569 STATIC_ASSERT( | 601 STATIC_ASSERT( |
570 static_cast<int>(NativeRegExpMacroAssembler::SUCCESS) == RE_SUCCESS); | 602 static_cast<int>(NativeRegExpMacroAssembler::SUCCESS) == RE_SUCCESS); |
571 STATIC_ASSERT( | 603 STATIC_ASSERT( |
572 static_cast<int>(NativeRegExpMacroAssembler::FAILURE) == RE_FAILURE); | 604 static_cast<int>(NativeRegExpMacroAssembler::FAILURE) == RE_FAILURE); |
573 STATIC_ASSERT(static_cast<int>(NativeRegExpMacroAssembler::EXCEPTION) | 605 STATIC_ASSERT(static_cast<int>(NativeRegExpMacroAssembler::EXCEPTION) |
574 == RE_EXCEPTION); | 606 == RE_EXCEPTION); |
575 return static_cast<IrregexpResult>(res); | 607 return static_cast<IrregexpResult>(res); |
576 } | 608 } |
577 // If result is RETRY, the string has changed representation, and we | 609 // If result is RETRY, the string has changed representation, and we |
578 // must restart from scratch. | 610 // must restart from scratch. |
579 // In this case, it means we must make sure we are prepared to handle | 611 // In this case, it means we must make sure we are prepared to handle |
580 // the, potentially, different subject (the string can switch between | 612 // the, potentially, different subject (the string can switch between |
581 // being internal and external, and even between being ASCII and UC16, | 613 // being internal and external, and even between being ASCII and UC16, |
582 // but the characters are always the same). | 614 // but the characters are always the same). |
583 IrregexpPrepare(regexp, subject); | 615 IrregexpPrepare(regexp, subject); |
584 is_ascii = subject->IsAsciiRepresentationUnderneath(); | 616 is_ascii = subject->IsAsciiRepresentationUnderneath(); |
585 } while (true); | 617 } while (true); |
586 UNREACHABLE(); | 618 UNREACHABLE(); |
587 return RE_EXCEPTION; | 619 return RE_EXCEPTION; |
588 #else // V8_INTERPRETED_REGEXP | 620 #else // V8_INTERPRETED_REGEXP |
589 | 621 |
590 ASSERT(output.length() >= IrregexpNumberOfRegisters(*irregexp)); | 622 ASSERT(output_size >= IrregexpNumberOfRegisters(*irregexp)); |
591 // We must have done EnsureCompiledIrregexp, so we can get the number of | 623 // We must have done EnsureCompiledIrregexp, so we can get the number of |
592 // registers. | 624 // registers. |
593 int* register_vector = output.start(); | |
594 int number_of_capture_registers = | 625 int number_of_capture_registers = |
595 (IrregexpNumberOfCaptures(*irregexp) + 1) * 2; | 626 (IrregexpNumberOfCaptures(*irregexp) + 1) * 2; |
| 627 int32_t* raw_output = &output[number_of_capture_registers]; |
| 628 // We do not touch the actual capture result registers until we know there |
| 629 // has been a match so that we can use those capture results to set the |
| 630 // last match info. |
596 for (int i = number_of_capture_registers - 1; i >= 0; i--) { | 631 for (int i = number_of_capture_registers - 1; i >= 0; i--) { |
597 register_vector[i] = -1; | 632 raw_output[i] = -1; |
598 } | 633 } |
599 Handle<ByteArray> byte_codes(IrregexpByteCode(*irregexp, is_ascii), isolate); | 634 Handle<ByteArray> byte_codes(IrregexpByteCode(*irregexp, is_ascii), isolate); |
600 | 635 |
601 IrregexpResult result = IrregexpInterpreter::Match(isolate, | 636 IrregexpResult result = IrregexpInterpreter::Match(isolate, |
602 byte_codes, | 637 byte_codes, |
603 subject, | 638 subject, |
604 register_vector, | 639 raw_output, |
605 index); | 640 index); |
| 641 if (result == RE_SUCCESS) { |
| 642 // Copy capture results to the start of the registers array. |
| 643 memcpy(output, raw_output, number_of_capture_registers * sizeof(int32_t)); |
| 644 } |
606 if (result == RE_EXCEPTION) { | 645 if (result == RE_EXCEPTION) { |
607 ASSERT(!isolate->has_pending_exception()); | 646 ASSERT(!isolate->has_pending_exception()); |
608 isolate->StackOverflow(); | 647 isolate->StackOverflow(); |
609 } | 648 } |
610 return result; | 649 return result; |
611 #endif // V8_INTERPRETED_REGEXP | 650 #endif // V8_INTERPRETED_REGEXP |
612 } | 651 } |
613 | 652 |
614 | 653 |
615 Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp, | 654 Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp, |
616 Handle<String> subject, | 655 Handle<String> subject, |
617 int previous_index, | 656 int previous_index, |
618 Handle<JSArray> last_match_info) { | 657 Handle<JSArray> last_match_info) { |
619 Isolate* isolate = jsregexp->GetIsolate(); | 658 Isolate* isolate = regexp->GetIsolate(); |
620 ASSERT_EQ(jsregexp->TypeTag(), JSRegExp::IRREGEXP); | 659 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); |
621 | 660 |
622 // Prepare space for the return values. | 661 // Prepare space for the return values. |
623 #ifdef V8_INTERPRETED_REGEXP | 662 #if defined(V8_INTERPRETED_REGEXP) && defined(DEBUG) |
624 #ifdef DEBUG | |
625 if (FLAG_trace_regexp_bytecodes) { | 663 if (FLAG_trace_regexp_bytecodes) { |
626 String* pattern = jsregexp->Pattern(); | 664 String* pattern = regexp->Pattern(); |
627 PrintF("\n\nRegexp match: /%s/\n\n", *(pattern->ToCString())); | 665 PrintF("\n\nRegexp match: /%s/\n\n", *(pattern->ToCString())); |
628 PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString())); | 666 PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString())); |
629 } | 667 } |
630 #endif | 668 #endif |
631 #endif | 669 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); |
632 int required_registers = RegExpImpl::IrregexpPrepare(jsregexp, subject); | |
633 if (required_registers < 0) { | 670 if (required_registers < 0) { |
634 // Compiling failed with an exception. | 671 // Compiling failed with an exception. |
635 ASSERT(isolate->has_pending_exception()); | 672 ASSERT(isolate->has_pending_exception()); |
636 return Handle<Object>::null(); | 673 return Handle<Object>::null(); |
637 } | 674 } |
638 | 675 |
639 OffsetsVector registers(required_registers, isolate); | 676 int32_t* output_registers; |
| 677 if (required_registers > Isolate::kJSRegexpStaticOffsetsVectorSize) { |
| 678 output_registers = NewArray<int32_t>(required_registers); |
| 679 } else { |
| 680 output_registers = isolate->jsregexp_static_offsets_vector(); |
| 681 } |
640 | 682 |
641 int res = RegExpImpl::IrregexpExecRaw(jsregexp, subject, previous_index, | 683 int res = RegExpImpl::IrregexpExecRaw( |
642 Vector<int>(registers.vector(), | 684 regexp, subject, previous_index, output_registers, required_registers); |
643 registers.length())); | |
644 if (res == RE_SUCCESS) { | 685 if (res == RE_SUCCESS) { |
645 int capture_register_count = | 686 int capture_count = |
646 (IrregexpNumberOfCaptures(FixedArray::cast(jsregexp->data())) + 1) * 2; | 687 IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())); |
647 last_match_info->EnsureSize(capture_register_count + kLastMatchOverhead); | 688 return SetLastMatchInfo( |
648 AssertNoAllocation no_gc; | 689 last_match_info, subject, capture_count, output_registers); |
649 int* register_vector = registers.vector(); | |
650 FixedArray* array = FixedArray::cast(last_match_info->elements()); | |
651 for (int i = 0; i < capture_register_count; i += 2) { | |
652 SetCapture(array, i, register_vector[i]); | |
653 SetCapture(array, i + 1, register_vector[i + 1]); | |
654 } | |
655 SetLastCaptureCount(array, capture_register_count); | |
656 SetLastSubject(array, *subject); | |
657 SetLastInput(array, *subject); | |
658 return last_match_info; | |
659 } | 690 } |
660 if (res == RE_EXCEPTION) { | 691 if (res == RE_EXCEPTION) { |
661 ASSERT(isolate->has_pending_exception()); | 692 ASSERT(isolate->has_pending_exception()); |
662 return Handle<Object>::null(); | 693 return Handle<Object>::null(); |
663 } | 694 } |
664 ASSERT(res == RE_FAILURE); | 695 ASSERT(res == RE_FAILURE); |
665 return isolate->factory()->null_value(); | 696 return isolate->factory()->null_value(); |
666 } | 697 } |
667 | 698 |
668 | 699 |
| 700 Handle<JSArray> RegExpImpl::SetLastMatchInfo(Handle<JSArray> last_match_info, |
| 701 Handle<String> subject, |
| 702 int capture_count, |
| 703 int32_t* match) { |
| 704 int capture_register_count = (capture_count + 1) * 2; |
| 705 last_match_info->EnsureSize(capture_register_count + kLastMatchOverhead); |
| 706 AssertNoAllocation no_gc; |
| 707 FixedArray* array = FixedArray::cast(last_match_info->elements()); |
| 708 if (match != NULL) { |
| 709 for (int i = 0; i < capture_register_count; i += 2) { |
| 710 SetCapture(array, i, match[i]); |
| 711 SetCapture(array, i + 1, match[i + 1]); |
| 712 } |
| 713 } |
| 714 SetLastCaptureCount(array, capture_register_count); |
| 715 SetLastSubject(array, *subject); |
| 716 SetLastInput(array, *subject); |
| 717 return last_match_info; |
| 718 } |
| 719 |
| 720 |
| 721 int RegExpImpl::global_cache_num_matches_ = 0; |
| 722 int RegExpImpl::global_cache_max_matches_ = 0; |
| 723 int RegExpImpl::global_cache_current_match_index_ = 0; |
| 724 int RegExpImpl::global_cache_registers_per_match_ = 0; |
| 725 JSRegExp::Type RegExpImpl::global_cache_current_type_ = JSRegExp::ATOM; |
| 726 int32_t* RegExpImpl::global_cache_register_array_ = NULL; |
| 727 int RegExpImpl::global_cache_register_array_size_ = 0; |
| 728 |
| 729 |
| 730 int RegExpImpl::GlobalCacheInitialize(Handle<JSRegExp> regexp, |
| 731 Handle<String> subject, |
| 732 bool is_global, |
| 733 Isolate* isolate) { |
| 734 int num_registers = 0; |
| 735 #ifdef V8_INTERPRETED_REGEXP |
| 736 bool interpreted = true; |
| 737 #else |
| 738 bool interpreted = false; |
| 739 #endif // V8_INTERPRETED_REGEXP |
| 740 |
| 741 global_cache_current_type_ = regexp->TypeTag(); |
| 742 if (global_cache_current_type_ == JSRegExp::ATOM) { |
| 743 static const int kAtomRegistersPerMatch = 2; |
| 744 global_cache_registers_per_match_ = kAtomRegistersPerMatch; |
| 745 // There is no distinction between interpreted and native for atom regexps. |
| 746 interpreted = false; |
| 747 } else { |
| 748 global_cache_registers_per_match_ = |
| 749 RegExpImpl::IrregexpPrepare(regexp, subject); |
| 750 if (global_cache_registers_per_match_ < 0) return RE_EXCEPTION; |
| 751 } |
| 752 |
| 753 if (is_global && !interpreted) { |
| 754 num_registers = Max(global_cache_registers_per_match_, |
| 755 Isolate::kJSRegexpStaticOffsetsVectorSize); |
| 756 global_cache_max_matches_ = |
| 757 num_registers / global_cache_registers_per_match_; |
| 758 } else { |
| 759 // Global loop in interpreted regexp is not implemented. We choose |
| 760 // the size of the offsets vector so that it can only store one match. |
| 761 num_registers = global_cache_registers_per_match_; |
| 762 global_cache_max_matches_ = 1; |
| 763 } |
| 764 |
| 765 if (global_cache_register_array_size_ > |
| 766 Isolate::kJSRegexpStaticOffsetsVectorSize) { |
| 767 DeleteArray(global_cache_register_array_); |
| 768 } |
| 769 |
| 770 if (num_registers > Isolate::kJSRegexpStaticOffsetsVectorSize) { |
| 771 global_cache_register_array_ = NewArray<int32_t>(num_registers); |
| 772 } else { |
| 773 global_cache_register_array_ = isolate->jsregexp_static_offsets_vector(); |
| 774 } |
| 775 |
| 776 global_cache_register_array_size_ = num_registers; |
| 777 |
| 778 // Set state so that fetching the results the first time triggers a call |
| 779 // to the compiled regexp. |
| 780 global_cache_current_match_index_ = global_cache_max_matches_; |
| 781 global_cache_num_matches_ = global_cache_max_matches_; |
| 782 int32_t* last_match = |
| 783 &global_cache_register_array_[global_cache_register_array_size_ - |
| 784 global_cache_registers_per_match_]; |
| 785 last_match[0] = -1; |
| 786 last_match[1] = 0; |
| 787 return RE_SUCCESS; |
| 788 } |
| 789 |
| 790 |
669 // ------------------------------------------------------------------- | 791 // ------------------------------------------------------------------- |
670 // Implementation of the Irregexp regular expression engine. | 792 // Implementation of the Irregexp regular expression engine. |
671 // | 793 // |
672 // The Irregexp regular expression engine is intended to be a complete | 794 // The Irregexp regular expression engine is intended to be a complete |
673 // implementation of ECMAScript regular expressions. It generates either | 795 // implementation of ECMAScript regular expressions. It generates either |
674 // bytecodes or native code. | 796 // bytecodes or native code. |
675 | 797 |
676 // The Irregexp regexp engine is structured in three steps. | 798 // The Irregexp regexp engine is structured in three steps. |
677 // 1) The parser generates an abstract syntax tree. See ast.cc. | 799 // 1) The parser generates an abstract syntax tree. See ast.cc. |
678 // 2) From the AST a node network is created. The nodes are all | 800 // 2) From the AST a node network is created. The nodes are all |
(...skipping 5324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6003 } | 6125 } |
6004 | 6126 |
6005 return compiler.Assemble(¯o_assembler, | 6127 return compiler.Assemble(¯o_assembler, |
6006 node, | 6128 node, |
6007 data->capture_count, | 6129 data->capture_count, |
6008 pattern); | 6130 pattern); |
6009 } | 6131 } |
6010 | 6132 |
6011 | 6133 |
6012 }} // namespace v8::internal | 6134 }} // namespace v8::internal |
OLD | NEW |