| 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 |