OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 #include "macro-assembler-ia32.h" | 48 #include "macro-assembler-ia32.h" |
49 #include "regexp-macro-assembler-ia32.h" | 49 #include "regexp-macro-assembler-ia32.h" |
50 #endif | 50 #endif |
51 | 51 |
52 #include "interpreter-irregexp.h" | 52 #include "interpreter-irregexp.h" |
53 | 53 |
54 | 54 |
55 namespace v8 { namespace internal { | 55 namespace v8 { namespace internal { |
56 | 56 |
57 | 57 |
58 String* RegExpImpl::last_ascii_string_ = NULL; | |
59 String* RegExpImpl::two_byte_cached_string_ = NULL; | |
60 | |
61 | |
62 void RegExpImpl::NewSpaceCollectionPrologue() { | |
63 // The two byte string is always in the old space. The Ascii string may be | |
64 // in either place. If it is in the old space we don't need to do anything. | |
65 if (Heap::InNewSpace(last_ascii_string_)) { | |
66 // Invalidate the cache. | |
67 last_ascii_string_ = NULL; | |
68 two_byte_cached_string_ = NULL; | |
69 } | |
70 } | |
71 | |
72 | |
73 void RegExpImpl::OldSpaceCollectionPrologue() { | |
74 last_ascii_string_ = NULL; | |
75 two_byte_cached_string_ = NULL; | |
76 } | |
77 | |
78 | |
79 Handle<Object> RegExpImpl::CreateRegExpLiteral(Handle<JSFunction> constructor, | 58 Handle<Object> RegExpImpl::CreateRegExpLiteral(Handle<JSFunction> constructor, |
80 Handle<String> pattern, | 59 Handle<String> pattern, |
81 Handle<String> flags, | 60 Handle<String> flags, |
82 bool* has_pending_exception) { | 61 bool* has_pending_exception) { |
83 // Ensure that the constructor function has been loaded. | 62 // Ensure that the constructor function has been loaded. |
84 if (!constructor->IsLoaded()) { | 63 if (!constructor->IsLoaded()) { |
85 LoadLazy(constructor, has_pending_exception); | 64 LoadLazy(constructor, has_pending_exception); |
86 if (*has_pending_exception) return Handle<Object>(); | 65 if (*has_pending_exception) return Handle<Object>(); |
87 } | 66 } |
88 // Call the construct code with 2 arguments. | 67 // Call the construct code with 2 arguments. |
89 Object** argv[2] = { Handle<Object>::cast(pattern).location(), | 68 Object** argv[2] = { Handle<Object>::cast(pattern).location(), |
90 Handle<Object>::cast(flags).location() }; | 69 Handle<Object>::cast(flags).location() }; |
91 return Execution::New(constructor, 2, argv, has_pending_exception); | 70 return Execution::New(constructor, 2, argv, has_pending_exception); |
92 } | 71 } |
93 | 72 |
94 | 73 |
95 // Converts a source string to a 16 bit flat string or a SlicedString containing | |
96 // a 16 bit flat string). | |
97 Handle<String> RegExpImpl::CachedStringToTwoByte(Handle<String> subject) { | |
98 if (*subject == last_ascii_string_) { | |
99 ASSERT(two_byte_cached_string_ != NULL); | |
100 return Handle<String>(String::cast(two_byte_cached_string_)); | |
101 } | |
102 Handle<String> two_byte_string = StringToTwoByte(subject); | |
103 last_ascii_string_ = *subject; | |
104 two_byte_cached_string_ = *two_byte_string; | |
105 return two_byte_string; | |
106 } | |
107 | |
108 | |
109 // Converts a source string to a 16 bit flat string or a SlicedString containing | |
110 // a 16 bit flat string). | |
111 Handle<String> RegExpImpl::StringToTwoByte(Handle<String> pattern) { | |
112 StringShape shape(*pattern); | |
113 if (!pattern->IsFlat(shape)) { | |
114 FlattenString(pattern); | |
115 shape = StringShape(*pattern); | |
116 } | |
117 Handle<String> flat_string(shape.IsCons() ? | |
118 String::cast(ConsString::cast(*pattern)->first()) : | |
119 *pattern); | |
120 ASSERT(flat_string->IsString()); | |
121 StringShape flat_shape(*flat_string); | |
122 ASSERT(!flat_shape.IsCons()); | |
123 ASSERT(flat_shape.IsSequential() || | |
124 flat_shape.IsSliced() || | |
125 flat_shape.IsExternal()); | |
126 if (!flat_shape.IsAsciiRepresentation()) { | |
127 return flat_string; | |
128 } | |
129 | |
130 int len = flat_string->length(flat_shape); | |
131 Handle<String> two_byte_string = | |
132 Factory::NewRawTwoByteString(len, TENURED); | |
133 uc16* dest = SeqTwoByteString::cast(*two_byte_string)->GetChars(); | |
134 String::WriteToFlat(*flat_string, flat_shape, dest, 0, len); | |
135 return two_byte_string; | |
136 } | |
137 | |
138 | |
139 static JSRegExp::Flags RegExpFlagsFromString(Handle<String> str) { | 74 static JSRegExp::Flags RegExpFlagsFromString(Handle<String> str) { |
140 int flags = JSRegExp::NONE; | 75 int flags = JSRegExp::NONE; |
141 StringShape shape(*str); | 76 for (int i = 0; i < str->length(); i++) { |
142 for (int i = 0; i < str->length(shape); i++) { | 77 switch (str->Get(i)) { |
143 switch (str->Get(shape, i)) { | |
144 case 'i': | 78 case 'i': |
145 flags |= JSRegExp::IGNORE_CASE; | 79 flags |= JSRegExp::IGNORE_CASE; |
146 break; | 80 break; |
147 case 'g': | 81 case 'g': |
148 flags |= JSRegExp::GLOBAL; | 82 flags |= JSRegExp::GLOBAL; |
149 break; | 83 break; |
150 case 'm': | 84 case 'm': |
151 flags |= JSRegExp::MULTILINE; | 85 flags |= JSRegExp::MULTILINE; |
152 break; | 86 break; |
153 } | 87 } |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 } | 348 } |
415 return true; | 349 return true; |
416 } | 350 } |
417 | 351 |
418 // Compile the RegExp. | 352 // Compile the RegExp. |
419 ZoneScope zone_scope(DELETE_ON_EXIT); | 353 ZoneScope zone_scope(DELETE_ON_EXIT); |
420 | 354 |
421 JSRegExp::Flags flags = re->GetFlags(); | 355 JSRegExp::Flags flags = re->GetFlags(); |
422 | 356 |
423 Handle<String> pattern(re->Pattern()); | 357 Handle<String> pattern(re->Pattern()); |
424 if (!pattern->IsFlat(StringShape(*pattern))) { | 358 if (!pattern->IsFlat()) { |
425 FlattenString(pattern); | 359 FlattenString(pattern); |
426 } | 360 } |
427 | 361 |
428 RegExpCompileData compile_data; | 362 RegExpCompileData compile_data; |
429 FlatStringReader reader(pattern); | 363 FlatStringReader reader(pattern); |
430 if (!ParseRegExp(&reader, flags.is_multiline(), &compile_data)) { | 364 if (!ParseRegExp(&reader, flags.is_multiline(), &compile_data)) { |
431 // Throw an exception if we fail to parse the pattern. | 365 // Throw an exception if we fail to parse the pattern. |
432 // THIS SHOULD NOT HAPPEN. We already parsed it successfully once. | 366 // THIS SHOULD NOT HAPPEN. We already parsed it successfully once. |
433 ThrowRegExpException(re, | 367 ThrowRegExpException(re, |
434 pattern, | 368 pattern, |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 int previous_index = index; | 479 int previous_index = index; |
546 | 480 |
547 #ifdef DEBUG | 481 #ifdef DEBUG |
548 if (FLAG_trace_regexp_bytecodes) { | 482 if (FLAG_trace_regexp_bytecodes) { |
549 String* pattern = regexp->Pattern(); | 483 String* pattern = regexp->Pattern(); |
550 PrintF("\n\nRegexp match: /%s/\n\n", *(pattern->ToCString())); | 484 PrintF("\n\nRegexp match: /%s/\n\n", *(pattern->ToCString())); |
551 PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString())); | 485 PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString())); |
552 } | 486 } |
553 #endif | 487 #endif |
554 | 488 |
555 if (!subject->IsFlat(StringShape(*subject))) { | 489 if (!subject->IsFlat()) { |
556 FlattenString(subject); | 490 FlattenString(subject); |
557 } | 491 } |
558 | 492 |
559 last_match_info->EnsureSize(number_of_capture_registers + kLastMatchOverhead); | 493 last_match_info->EnsureSize(number_of_capture_registers + kLastMatchOverhead); |
560 | 494 |
561 return IrregexpExecOnce(re_data, | 495 return IrregexpExecOnce(re_data, |
562 number_of_capture_registers, | 496 number_of_capture_registers, |
563 last_match_info, | 497 last_match_info, |
564 subject, | 498 subject, |
565 previous_index, | 499 previous_index, |
(...skipping 17 matching lines...) Expand all Loading... |
583 int number_of_capture_registers = | 517 int number_of_capture_registers = |
584 (IrregexpNumberOfCaptures(*irregexp) + 1) * 2; | 518 (IrregexpNumberOfCaptures(*irregexp) + 1) * 2; |
585 OffsetsVector offsets(number_of_capture_registers); | 519 OffsetsVector offsets(number_of_capture_registers); |
586 | 520 |
587 int previous_index = 0; | 521 int previous_index = 0; |
588 | 522 |
589 Handle<JSArray> result = Factory::NewJSArray(0); | 523 Handle<JSArray> result = Factory::NewJSArray(0); |
590 int result_length = 0; | 524 int result_length = 0; |
591 Handle<Object> matches; | 525 Handle<Object> matches; |
592 | 526 |
593 if (!subject->IsFlat(StringShape(*subject))) { | 527 if (!subject->IsFlat()) { |
594 FlattenString(subject); | 528 FlattenString(subject); |
595 } | 529 } |
596 | 530 |
597 last_match_info->EnsureSize(number_of_capture_registers + kLastMatchOverhead); | 531 last_match_info->EnsureSize(number_of_capture_registers + kLastMatchOverhead); |
598 | 532 |
599 while (true) { | 533 while (true) { |
600 if (previous_index > subject->length() || previous_index < 0) { | 534 if (previous_index > subject->length() || previous_index < 0) { |
601 // Per ECMA-262 15.10.6.2, if the previous index is greater than the | 535 // Per ECMA-262 15.10.6.2, if the previous index is greater than the |
602 // string length, there is no match. | 536 // string length, there is no match. |
603 return result; | 537 return result; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 } | 586 } |
653 | 587 |
654 | 588 |
655 Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> regexp, | 589 Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> regexp, |
656 int number_of_capture_registers, | 590 int number_of_capture_registers, |
657 Handle<JSArray> last_match_info, | 591 Handle<JSArray> last_match_info, |
658 Handle<String> subject, | 592 Handle<String> subject, |
659 int previous_index, | 593 int previous_index, |
660 int* offsets_vector, | 594 int* offsets_vector, |
661 int offsets_vector_length) { | 595 int offsets_vector_length) { |
662 StringShape shape(*subject); | 596 ASSERT(subject->IsFlat()); |
663 ASSERT(subject->IsFlat(shape)); | 597 bool is_ascii = StringShape(*subject).IsAsciiRepresentation(); |
664 bool is_ascii = shape.IsAsciiRepresentation(); | |
665 bool rc; | 598 bool rc; |
666 | 599 |
667 Handle<String> original_subject = subject; | 600 Handle<String> original_subject = subject; |
668 if (UseNativeRegexp()) { | 601 if (UseNativeRegexp()) { |
669 #ifdef ARM | 602 #ifdef ARM |
670 UNREACHABLE(); | 603 UNREACHABLE(); |
671 #else | 604 #else |
672 Handle<Code> code(RegExpImpl::IrregexpNativeCode(*regexp, is_ascii)); | 605 Handle<Code> code(RegExpImpl::IrregexpNativeCode(*regexp, is_ascii)); |
673 RegExpMacroAssemblerIA32::Result res = | 606 RegExpMacroAssemblerIA32::Result res = |
674 RegExpMacroAssemblerIA32::Match(code, | 607 RegExpMacroAssemblerIA32::Match(code, |
(...skipping 4011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4686 EmbeddedVector<byte, 1024> codes; | 4619 EmbeddedVector<byte, 1024> codes; |
4687 RegExpMacroAssemblerIrregexp macro_assembler(codes); | 4620 RegExpMacroAssemblerIrregexp macro_assembler(codes); |
4688 return compiler.Assemble(¯o_assembler, | 4621 return compiler.Assemble(¯o_assembler, |
4689 node, | 4622 node, |
4690 data->capture_count, | 4623 data->capture_count, |
4691 pattern); | 4624 pattern); |
4692 } | 4625 } |
4693 | 4626 |
4694 | 4627 |
4695 }} // namespace v8::internal | 4628 }} // namespace v8::internal |
OLD | NEW |