OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/regexp/jsregexp.h" | 5 #include "src/regexp/jsregexp.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
10 #include "src/compilation-cache.h" | 10 #include "src/compilation-cache.h" |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 // Compilation succeeded so the data is set on the regexp | 187 // Compilation succeeded so the data is set on the regexp |
188 // and we can store it in the cache. | 188 // and we can store it in the cache. |
189 Handle<FixedArray> data(FixedArray::cast(re->data())); | 189 Handle<FixedArray> data(FixedArray::cast(re->data())); |
190 compilation_cache->PutRegExp(pattern, flags, data); | 190 compilation_cache->PutRegExp(pattern, flags, data); |
191 | 191 |
192 return re; | 192 return re; |
193 } | 193 } |
194 | 194 |
195 MaybeHandle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp, | 195 MaybeHandle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp, |
196 Handle<String> subject, int index, | 196 Handle<String> subject, int index, |
197 Handle<JSObject> last_match_info) { | 197 Handle<RegExpMatchInfo> last_match_info) { |
198 switch (regexp->TypeTag()) { | 198 switch (regexp->TypeTag()) { |
199 case JSRegExp::ATOM: | 199 case JSRegExp::ATOM: |
200 return AtomExec(regexp, subject, index, last_match_info); | 200 return AtomExec(regexp, subject, index, last_match_info); |
201 case JSRegExp::IRREGEXP: { | 201 case JSRegExp::IRREGEXP: { |
202 return IrregexpExec(regexp, subject, index, last_match_info); | 202 return IrregexpExec(regexp, subject, index, last_match_info); |
203 } | 203 } |
204 default: | 204 default: |
205 UNREACHABLE(); | 205 UNREACHABLE(); |
206 return MaybeHandle<Object>(); | 206 return MaybeHandle<Object>(); |
207 } | 207 } |
208 } | 208 } |
209 | 209 |
210 | 210 |
211 // RegExp Atom implementation: Simple string search using indexOf. | 211 // RegExp Atom implementation: Simple string search using indexOf. |
212 | 212 |
213 | 213 |
214 void RegExpImpl::AtomCompile(Handle<JSRegExp> re, | 214 void RegExpImpl::AtomCompile(Handle<JSRegExp> re, |
215 Handle<String> pattern, | 215 Handle<String> pattern, |
216 JSRegExp::Flags flags, | 216 JSRegExp::Flags flags, |
217 Handle<String> match_pattern) { | 217 Handle<String> match_pattern) { |
218 re->GetIsolate()->factory()->SetRegExpAtomData(re, | 218 re->GetIsolate()->factory()->SetRegExpAtomData(re, |
219 JSRegExp::ATOM, | 219 JSRegExp::ATOM, |
220 pattern, | 220 pattern, |
221 flags, | 221 flags, |
222 match_pattern); | 222 match_pattern); |
223 } | 223 } |
224 | 224 |
225 | 225 static void SetAtomLastCapture(Handle<RegExpMatchInfo> last_match_info, |
226 static void SetAtomLastCapture(FixedArray* array, | 226 String* subject, int from, int to) { |
227 String* subject, | 227 SealHandleScope shs(last_match_info->GetIsolate()); |
228 int from, | 228 last_match_info->SetNumberOfCaptureRegisters(2); |
229 int to) { | 229 last_match_info->SetLastSubject(subject); |
230 SealHandleScope shs(array->GetIsolate()); | 230 last_match_info->SetLastInput(subject); |
231 RegExpImpl::SetLastCaptureCount(array, 2); | 231 last_match_info->SetCapture(0, from); |
232 RegExpImpl::SetLastSubject(array, subject); | 232 last_match_info->SetCapture(1, to); |
233 RegExpImpl::SetLastInput(array, subject); | |
234 RegExpImpl::SetCapture(array, 0, from); | |
235 RegExpImpl::SetCapture(array, 1, to); | |
236 } | 233 } |
237 | 234 |
238 | 235 |
239 int RegExpImpl::AtomExecRaw(Handle<JSRegExp> regexp, | 236 int RegExpImpl::AtomExecRaw(Handle<JSRegExp> regexp, |
240 Handle<String> subject, | 237 Handle<String> subject, |
241 int index, | 238 int index, |
242 int32_t* output, | 239 int32_t* output, |
243 int output_size) { | 240 int output_size) { |
244 Isolate* isolate = regexp->GetIsolate(); | 241 Isolate* isolate = regexp->GetIsolate(); |
245 | 242 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 output[i] = index; | 279 output[i] = index; |
283 output[i+1] = index + needle_len; | 280 output[i+1] = index + needle_len; |
284 index += needle_len; | 281 index += needle_len; |
285 } | 282 } |
286 } | 283 } |
287 return output_size / 2; | 284 return output_size / 2; |
288 } | 285 } |
289 | 286 |
290 Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re, Handle<String> subject, | 287 Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re, Handle<String> subject, |
291 int index, | 288 int index, |
292 Handle<JSObject> last_match_info) { | 289 Handle<RegExpMatchInfo> last_match_info) { |
293 Isolate* isolate = re->GetIsolate(); | 290 Isolate* isolate = re->GetIsolate(); |
294 | 291 |
295 static const int kNumRegisters = 2; | 292 static const int kNumRegisters = 2; |
296 STATIC_ASSERT(kNumRegisters <= Isolate::kJSRegexpStaticOffsetsVectorSize); | 293 STATIC_ASSERT(kNumRegisters <= Isolate::kJSRegexpStaticOffsetsVectorSize); |
297 int32_t* output_registers = isolate->jsregexp_static_offsets_vector(); | 294 int32_t* output_registers = isolate->jsregexp_static_offsets_vector(); |
298 | 295 |
299 int res = AtomExecRaw(re, subject, index, output_registers, kNumRegisters); | 296 int res = AtomExecRaw(re, subject, index, output_registers, kNumRegisters); |
300 | 297 |
301 if (res == RegExpImpl::RE_FAILURE) return isolate->factory()->null_value(); | 298 if (res == RegExpImpl::RE_FAILURE) return isolate->factory()->null_value(); |
302 | 299 |
303 DCHECK_EQ(res, RegExpImpl::RE_SUCCESS); | 300 DCHECK_EQ(res, RegExpImpl::RE_SUCCESS); |
304 SealHandleScope shs(isolate); | 301 SealHandleScope shs(isolate); |
305 FixedArray* array = FixedArray::cast(last_match_info->elements()); | 302 SetAtomLastCapture(last_match_info, *subject, output_registers[0], |
306 SetAtomLastCapture(array, *subject, output_registers[0], output_registers[1]); | 303 output_registers[1]); |
307 return last_match_info; | 304 return last_match_info; |
308 } | 305 } |
309 | 306 |
310 | 307 |
311 // Irregexp implementation. | 308 // Irregexp implementation. |
312 | 309 |
313 // Ensures that the regexp object contains a compiled version of the | 310 // Ensures that the regexp object contains a compiled version of the |
314 // source for either one-byte or two-byte subject strings. | 311 // source for either one-byte or two-byte subject strings. |
315 // If the compiled version doesn't already exist, it is compiled | 312 // If the compiled version doesn't already exist, it is compiled |
316 // from the source pattern. | 313 // from the source pattern. |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 MemCopy(output, raw_output, number_of_capture_registers * sizeof(int32_t)); | 556 MemCopy(output, raw_output, number_of_capture_registers * sizeof(int32_t)); |
560 } | 557 } |
561 if (result == RE_EXCEPTION) { | 558 if (result == RE_EXCEPTION) { |
562 DCHECK(!isolate->has_pending_exception()); | 559 DCHECK(!isolate->has_pending_exception()); |
563 isolate->StackOverflow(); | 560 isolate->StackOverflow(); |
564 } | 561 } |
565 return result; | 562 return result; |
566 #endif // V8_INTERPRETED_REGEXP | 563 #endif // V8_INTERPRETED_REGEXP |
567 } | 564 } |
568 | 565 |
569 MaybeHandle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp, | 566 MaybeHandle<Object> RegExpImpl::IrregexpExec( |
570 Handle<String> subject, | 567 Handle<JSRegExp> regexp, Handle<String> subject, int previous_index, |
571 int previous_index, | 568 Handle<RegExpMatchInfo> last_match_info) { |
572 Handle<JSObject> last_match_info) { | |
573 Isolate* isolate = regexp->GetIsolate(); | 569 Isolate* isolate = regexp->GetIsolate(); |
574 DCHECK_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); | 570 DCHECK_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); |
575 | 571 |
576 // Prepare space for the return values. | 572 // Prepare space for the return values. |
577 #if defined(V8_INTERPRETED_REGEXP) && defined(DEBUG) | 573 #if defined(V8_INTERPRETED_REGEXP) && defined(DEBUG) |
578 if (FLAG_trace_regexp_bytecodes) { | 574 if (FLAG_trace_regexp_bytecodes) { |
579 String* pattern = regexp->Pattern(); | 575 String* pattern = regexp->Pattern(); |
580 PrintF("\n\nRegexp match: /%s/\n\n", pattern->ToCString().get()); | 576 PrintF("\n\nRegexp match: /%s/\n\n", pattern->ToCString().get()); |
581 PrintF("\n\nSubject string: '%s'\n\n", subject->ToCString().get()); | 577 PrintF("\n\nSubject string: '%s'\n\n", subject->ToCString().get()); |
582 } | 578 } |
(...skipping 23 matching lines...) Expand all Loading... |
606 last_match_info, subject, capture_count, output_registers); | 602 last_match_info, subject, capture_count, output_registers); |
607 } | 603 } |
608 if (res == RE_EXCEPTION) { | 604 if (res == RE_EXCEPTION) { |
609 DCHECK(isolate->has_pending_exception()); | 605 DCHECK(isolate->has_pending_exception()); |
610 return MaybeHandle<Object>(); | 606 return MaybeHandle<Object>(); |
611 } | 607 } |
612 DCHECK(res == RE_FAILURE); | 608 DCHECK(res == RE_FAILURE); |
613 return isolate->factory()->null_value(); | 609 return isolate->factory()->null_value(); |
614 } | 610 } |
615 | 611 |
616 static void EnsureSize(Handle<JSObject> array, uint32_t minimum_size) { | 612 Handle<RegExpMatchInfo> RegExpImpl::SetLastMatchInfo( |
617 if (static_cast<uint32_t>(array->elements()->length()) < minimum_size) { | 613 Handle<RegExpMatchInfo> last_match_info, Handle<String> subject, |
618 array->GetElementsAccessor()->GrowCapacityAndConvert(array, minimum_size); | 614 int capture_count, int32_t* match) { |
| 615 // This is the only place where match infos can grow. If, after executing the |
| 616 // regexp, RegExpExecStub finds that the match info is too small, it restarts |
| 617 // execution in RegExpImpl::Exec, which finally grows the match info right |
| 618 // here. |
| 619 |
| 620 int capture_register_count = (capture_count + 1) * 2; |
| 621 Handle<RegExpMatchInfo> result = |
| 622 RegExpMatchInfo::ReserveCaptures(last_match_info, capture_register_count); |
| 623 result->SetNumberOfCaptureRegisters(capture_register_count); |
| 624 |
| 625 if (*result != *last_match_info) { |
| 626 // The match info has been reallocated, update the corresponding reference |
| 627 // on the native context. |
| 628 Isolate* isolate = last_match_info->GetIsolate(); |
| 629 if (*last_match_info == *isolate->regexp_last_match_info()) { |
| 630 isolate->native_context()->set_regexp_last_match_info(*result); |
| 631 } else if (*last_match_info == *isolate->regexp_internal_match_info()) { |
| 632 isolate->native_context()->set_regexp_internal_match_info(*result); |
| 633 } |
619 } | 634 } |
620 } | |
621 | 635 |
622 Handle<JSObject> RegExpImpl::SetLastMatchInfo(Handle<JSObject> last_match_info, | |
623 Handle<String> subject, | |
624 int capture_count, | |
625 int32_t* match) { | |
626 DCHECK(last_match_info->HasFastObjectElements()); | |
627 int capture_register_count = (capture_count + 1) * 2; | |
628 EnsureSize(last_match_info, capture_register_count + kLastMatchOverhead); | |
629 DisallowHeapAllocation no_allocation; | 636 DisallowHeapAllocation no_allocation; |
630 FixedArray* array = FixedArray::cast(last_match_info->elements()); | |
631 if (match != NULL) { | 637 if (match != NULL) { |
632 for (int i = 0; i < capture_register_count; i += 2) { | 638 for (int i = 0; i < capture_register_count; i += 2) { |
633 SetCapture(array, i, match[i]); | 639 result->SetCapture(i, match[i]); |
634 SetCapture(array, i + 1, match[i + 1]); | 640 result->SetCapture(i + 1, match[i + 1]); |
635 } | 641 } |
636 } | 642 } |
637 SetLastCaptureCount(array, capture_register_count); | 643 result->SetLastSubject(*subject); |
638 SetLastSubject(array, *subject); | 644 result->SetLastInput(*subject); |
639 SetLastInput(array, *subject); | 645 return result; |
640 return last_match_info; | |
641 } | 646 } |
642 | 647 |
643 | 648 |
644 RegExpImpl::GlobalCache::GlobalCache(Handle<JSRegExp> regexp, | 649 RegExpImpl::GlobalCache::GlobalCache(Handle<JSRegExp> regexp, |
645 Handle<String> subject, | 650 Handle<String> subject, |
646 Isolate* isolate) | 651 Isolate* isolate) |
647 : register_array_(NULL), | 652 : register_array_(NULL), |
648 register_array_size_(0), | 653 register_array_size_(0), |
649 regexp_(regexp), | 654 regexp_(regexp), |
650 subject_(subject) { | 655 subject_(subject) { |
(...skipping 6219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6870 | 6875 |
6871 | 6876 |
6872 void RegExpResultsCache::Clear(FixedArray* cache) { | 6877 void RegExpResultsCache::Clear(FixedArray* cache) { |
6873 for (int i = 0; i < kRegExpResultsCacheSize; i++) { | 6878 for (int i = 0; i < kRegExpResultsCacheSize; i++) { |
6874 cache->set(i, Smi::kZero); | 6879 cache->set(i, Smi::kZero); |
6875 } | 6880 } |
6876 } | 6881 } |
6877 | 6882 |
6878 } // namespace internal | 6883 } // namespace internal |
6879 } // namespace v8 | 6884 } // namespace v8 |
OLD | NEW |