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

Side by Side Diff: src/jsregexp.cc

Issue 21504: Remove JSCRE (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 10 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
« LICENSE ('K') | « src/jsregexp.h ('k') | src/objects.h » ('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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 44
45 #ifdef ARM 45 #ifdef ARM
46 #include "regexp-macro-assembler-arm.h" 46 #include "regexp-macro-assembler-arm.h"
47 #else // IA32 47 #else // IA32
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 // Including pcre.h undefines DEBUG to avoid getting debug output from
55 // the JSCRE implementation. Make sure to redefine it in debug mode
56 // after having included the header file.
57 #ifdef DEBUG
58 #include "third_party/jscre/pcre.h"
59 #define DEBUG
60 #else
61 #include "third_party/jscre/pcre.h"
62 #endif
63
64 54
65 namespace v8 { namespace internal { 55 namespace v8 { namespace internal {
66 56
67 57
68 static Failure* malloc_failure;
69
70 static void* JSREMalloc(size_t size) {
71 Object* obj = Heap::AllocateByteArray(size);
72
73 // If allocation failed, return a NULL pointer to JSRE, and jsRegExpCompile
74 // will return NULL to the caller, performs GC there.
75 // Also pass failure information to the caller.
76 if (obj->IsFailure()) {
77 malloc_failure = Failure::cast(obj);
78 return NULL;
79 }
80
81 // Note: object is unrooted, the caller of jsRegExpCompile must
82 // create a handle for the return value before doing heap allocation.
83 return reinterpret_cast<void*>(ByteArray::cast(obj)->GetDataStartAddress());
84 }
85
86
87 static void JSREFree(void* p) {
88 USE(p); // Do nothing, memory is garbage collected.
89 }
90
91
92 String* RegExpImpl::last_ascii_string_ = NULL; 58 String* RegExpImpl::last_ascii_string_ = NULL;
93 String* RegExpImpl::two_byte_cached_string_ = NULL; 59 String* RegExpImpl::two_byte_cached_string_ = NULL;
94 60
95 61
96 void RegExpImpl::NewSpaceCollectionPrologue() { 62 void RegExpImpl::NewSpaceCollectionPrologue() {
97 // The two byte string is always in the old space. The Ascii string may be 63 // The two byte string is always in the old space. The Ascii string may be
98 // in either place. If it is in the old space we don't need to do anything. 64 // in either place. If it is in the old space we don't need to do anything.
99 if (Heap::InNewSpace(last_ascii_string_)) { 65 if (Heap::InNewSpace(last_ascii_string_)) {
100 // Invalidate the cache. 66 // Invalidate the cache.
101 last_ascii_string_ = NULL; 67 last_ascii_string_ = NULL;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 if (parse_result.simple && !flags.is_ignore_case()) { 231 if (parse_result.simple && !flags.is_ignore_case()) {
266 // Parse-tree is a single atom that is equal to the pattern. 232 // Parse-tree is a single atom that is equal to the pattern.
267 result = AtomCompile(re, pattern, flags, pattern); 233 result = AtomCompile(re, pattern, flags, pattern);
268 } else if (parse_result.tree->IsAtom() && 234 } else if (parse_result.tree->IsAtom() &&
269 !flags.is_ignore_case() && 235 !flags.is_ignore_case() &&
270 parse_result.capture_count == 0) { 236 parse_result.capture_count == 0) {
271 RegExpAtom* atom = parse_result.tree->AsAtom(); 237 RegExpAtom* atom = parse_result.tree->AsAtom();
272 Vector<const uc16> atom_pattern = atom->data(); 238 Vector<const uc16> atom_pattern = atom->data();
273 Handle<String> atom_string = Factory::NewStringFromTwoByte(atom_pattern); 239 Handle<String> atom_string = Factory::NewStringFromTwoByte(atom_pattern);
274 result = AtomCompile(re, pattern, flags, atom_string); 240 result = AtomCompile(re, pattern, flags, atom_string);
275 } else if (FLAG_irregexp) { 241 } else {
276 result = IrregexpPrepare(re, pattern, flags); 242 result = IrregexpPrepare(re, pattern, flags);
277 } else {
278 result = JscrePrepare(re, pattern, flags);
279 } 243 }
280 Object* data = re->data(); 244 Object* data = re->data();
281 if (data->IsFixedArray()) { 245 if (data->IsFixedArray()) {
282 // If compilation succeeded then the data is set on the regexp 246 // If compilation succeeded then the data is set on the regexp
283 // and we can store it in the cache. 247 // and we can store it in the cache.
284 Handle<FixedArray> data(FixedArray::cast(re->data())); 248 Handle<FixedArray> data(FixedArray::cast(re->data()));
285 CompilationCache::PutRegExp(pattern, flags, data); 249 CompilationCache::PutRegExp(pattern, flags, data);
286 } 250 }
287 } 251 }
288 252
289 return result; 253 return result;
290 } 254 }
291 255
292 256
293 Handle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp, 257 Handle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp,
294 Handle<String> subject, 258 Handle<String> subject,
295 Handle<Object> index) { 259 Handle<Object> index) {
296 switch (regexp->TypeTag()) { 260 switch (regexp->TypeTag()) {
297 case JSRegExp::ATOM: 261 case JSRegExp::ATOM:
298 return AtomExec(regexp, subject, index); 262 return AtomExec(regexp, subject, index);
299 case JSRegExp::IRREGEXP: { 263 case JSRegExp::IRREGEXP: {
300 Handle<Object> result = IrregexpExec(regexp, subject, index); 264 Handle<Object> result = IrregexpExec(regexp, subject, index);
301 ASSERT(!result.is_null() || Top::has_pending_exception()); 265 ASSERT(!result.is_null() || Top::has_pending_exception());
302 return result; 266 return result;
303 } 267 }
304 case JSRegExp::JSCRE:
305 return JscreExec(regexp, subject, index);
306 default: 268 default:
307 UNREACHABLE(); 269 UNREACHABLE();
308 return Handle<Object>::null(); 270 return Handle<Object>::null();
309 } 271 }
310 } 272 }
311 273
312 274
313 Handle<Object> RegExpImpl::ExecGlobal(Handle<JSRegExp> regexp, 275 Handle<Object> RegExpImpl::ExecGlobal(Handle<JSRegExp> regexp,
314 Handle<String> subject) { 276 Handle<String> subject) {
315 switch (regexp->TypeTag()) { 277 switch (regexp->TypeTag()) {
316 case JSRegExp::ATOM: 278 case JSRegExp::ATOM:
317 return AtomExecGlobal(regexp, subject); 279 return AtomExecGlobal(regexp, subject);
318 case JSRegExp::IRREGEXP: { 280 case JSRegExp::IRREGEXP: {
319 Handle<Object> result = IrregexpExecGlobal(regexp, subject); 281 Handle<Object> result = IrregexpExecGlobal(regexp, subject);
320 ASSERT(!result.is_null() || Top::has_pending_exception()); 282 ASSERT(!result.is_null() || Top::has_pending_exception());
321 return result; 283 return result;
322 } 284 }
323 case JSRegExp::JSCRE:
324 return JscreExecGlobal(regexp, subject);
325 default: 285 default:
326 UNREACHABLE(); 286 UNREACHABLE();
327 return Handle<Object>::null(); 287 return Handle<Object>::null();
328 } 288 }
329 } 289 }
330 290
331 291
332 // RegExp Atom implementation: Simple string search using indexOf. 292 // RegExp Atom implementation: Simple string search using indexOf.
333 293
334 294
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 Handle<JSArray> pair = Factory::NewJSArrayWithElements(array); 344 Handle<JSArray> pair = Factory::NewJSArrayWithElements(array);
385 SetElement(result, match_count, pair); 345 SetElement(result, match_count, pair);
386 match_count++; 346 match_count++;
387 index = end; 347 index = end;
388 if (needle_length == 0) index++; 348 if (needle_length == 0) index++;
389 } 349 }
390 return result; 350 return result;
391 } 351 }
392 352
393 353
394 // JSCRE implementation.
395
396
397 int RegExpImpl::JscreNumberOfCaptures(Handle<JSRegExp> re) {
398 FixedArray* value = FixedArray::cast(re->DataAt(JSRegExp::kJscreDataIndex));
399 return Smi::cast(value->get(kJscreNumberOfCapturesIndex))->value();
400 }
401
402
403 ByteArray* RegExpImpl::JscreInternal(Handle<JSRegExp> re) {
404 FixedArray* value = FixedArray::cast(re->DataAt(JSRegExp::kJscreDataIndex));
405 return ByteArray::cast(value->get(kJscreInternalIndex));
406 }
407
408
409 Handle<Object>RegExpImpl::JscrePrepare(Handle<JSRegExp> re,
410 Handle<String> pattern,
411 JSRegExp::Flags flags) {
412 Handle<Object> value(Heap::undefined_value());
413 Factory::SetRegExpData(re, JSRegExp::JSCRE, pattern, flags, value);
414 return re;
415 }
416
417
418 static inline Object* JscreDoCompile(String* pattern,
419 JSRegExp::Flags flags,
420 unsigned* number_of_captures,
421 const char** error_message,
422 v8::jscre::JscreRegExp** code) {
423 v8::jscre::JSRegExpIgnoreCaseOption case_option = flags.is_ignore_case()
424 ? v8::jscre::JSRegExpIgnoreCase
425 : v8::jscre::JSRegExpDoNotIgnoreCase;
426 v8::jscre::JSRegExpMultilineOption multiline_option = flags.is_multiline()
427 ? v8::jscre::JSRegExpMultiline
428 : v8::jscre::JSRegExpSingleLine;
429 *error_message = NULL;
430 malloc_failure = Failure::Exception();
431 *code = v8::jscre::jsRegExpCompile(pattern->GetTwoByteData(),
432 pattern->length(),
433 case_option,
434 multiline_option,
435 number_of_captures,
436 error_message,
437 &JSREMalloc,
438 &JSREFree);
439 if (*code == NULL && (malloc_failure->IsRetryAfterGC() ||
440 malloc_failure->IsOutOfMemoryFailure())) {
441 return malloc_failure;
442 } else {
443 // It doesn't matter which object we return here, we just need to return
444 // a non-failure to indicate to the GC-retry code that there was no
445 // allocation failure.
446 return pattern;
447 }
448 }
449
450
451 static void JscreCompileWithRetryAfterGC(Handle<String> pattern,
452 JSRegExp::Flags flags,
453 unsigned* number_of_captures,
454 const char** error_message,
455 v8::jscre::JscreRegExp** code) {
456 CALL_HEAP_FUNCTION_VOID(JscreDoCompile(*pattern,
457 flags,
458 number_of_captures,
459 error_message,
460 code));
461 }
462
463
464 Handle<Object> RegExpImpl::JscreCompile(Handle<JSRegExp> re) {
465 ASSERT_EQ(re->TypeTag(), JSRegExp::JSCRE);
466 ASSERT(re->DataAt(JSRegExp::kJscreDataIndex)->IsUndefined());
467
468 Handle<String> pattern(re->Pattern());
469 JSRegExp::Flags flags = re->GetFlags();
470
471 Handle<String> two_byte_pattern = StringToTwoByte(pattern);
472
473 unsigned number_of_captures;
474 const char* error_message = NULL;
475
476 v8::jscre::JscreRegExp* code = NULL;
477 FlattenString(pattern);
478
479 JscreCompileWithRetryAfterGC(two_byte_pattern,
480 flags,
481 &number_of_captures,
482 &error_message,
483 &code);
484
485 if (code == NULL) {
486 // Throw an exception.
487 Handle<JSArray> array = Factory::NewJSArray(2);
488 SetElement(array, 0, pattern);
489 const char* message =
490 (error_message == NULL) ? "Unknown regexp error" : error_message;
491 SetElement(array, 1, Factory::NewStringFromUtf8(CStrVector(message)));
492 Handle<Object> regexp_err =
493 Factory::NewSyntaxError("malformed_regexp", array);
494 Top::Throw(*regexp_err);
495 return Handle<Object>();
496 }
497
498 // Convert the return address to a ByteArray pointer.
499 Handle<ByteArray> internal(
500 ByteArray::FromDataStartAddress(reinterpret_cast<Address>(code)));
501
502 Handle<FixedArray> value = Factory::NewFixedArray(kJscreDataLength);
503 value->set(kJscreNumberOfCapturesIndex, Smi::FromInt(number_of_captures));
504 value->set(kJscreInternalIndex, *internal);
505 Factory::SetRegExpData(re, JSRegExp::JSCRE, pattern, flags, value);
506
507 return re;
508 }
509
510
511 Handle<Object> RegExpImpl::JscreExec(Handle<JSRegExp> regexp,
512 Handle<String> subject,
513 Handle<Object> index) {
514 ASSERT_EQ(regexp->TypeTag(), JSRegExp::JSCRE);
515 if (regexp->DataAt(JSRegExp::kJscreDataIndex)->IsUndefined()) {
516 Handle<Object> compile_result = JscreCompile(regexp);
517 if (compile_result.is_null()) return compile_result;
518 }
519 ASSERT(regexp->DataAt(JSRegExp::kJscreDataIndex)->IsFixedArray());
520
521 int num_captures = JscreNumberOfCaptures(regexp);
522
523 OffsetsVector offsets((num_captures + 1) * 3);
524
525 int previous_index = static_cast<int>(DoubleToInteger(index->Number()));
526
527 Handle<String> subject16 = CachedStringToTwoByte(subject);
528
529 return JscreExecOnce(regexp,
530 num_captures,
531 subject,
532 previous_index,
533 subject16->GetTwoByteData(),
534 offsets.vector(),
535 offsets.length());
536 }
537
538
539 Handle<Object> RegExpImpl::JscreExecOnce(Handle<JSRegExp> regexp,
540 int num_captures,
541 Handle<String> subject,
542 int previous_index,
543 const uc16* two_byte_subject,
544 int* offsets_vector,
545 int offsets_vector_length) {
546 int rc;
547 {
548 AssertNoAllocation a;
549 ByteArray* internal = JscreInternal(regexp);
550 const v8::jscre::JscreRegExp* js_regexp =
551 reinterpret_cast<v8::jscre::JscreRegExp*>(
552 internal->GetDataStartAddress());
553
554 rc = v8::jscre::jsRegExpExecute(js_regexp,
555 two_byte_subject,
556 subject->length(),
557 previous_index,
558 offsets_vector,
559 offsets_vector_length);
560 }
561
562 // The KJS JavaScript engine returns null (ie, a failed match) when
563 // JSRE's internal match limit is exceeded. We duplicate that behavior here.
564 if (rc == v8::jscre::JSRegExpErrorNoMatch
565 || rc == v8::jscre::JSRegExpErrorHitLimit) {
566 return Factory::null_value();
567 }
568
569 // Other JSRE errors:
570 if (rc < 0) {
571 // Throw an exception.
572 Handle<Object> code(Smi::FromInt(rc));
573 Handle<Object> args[2] = { Factory::LookupAsciiSymbol("jsre_exec"), code };
574 Handle<Object> regexp_err(
575 Factory::NewTypeError("jsre_error", HandleVector(args, 2)));
576 return Handle<Object>(Top::Throw(*regexp_err));
577 }
578
579 Handle<FixedArray> array = Factory::NewFixedArray(2 * (num_captures+1));
580 // The captures come in (start, end+1) pairs.
581 for (int i = 0; i < 2 * (num_captures+1); i += 2) {
582 array->set(i, Smi::FromInt(offsets_vector[i]));
583 array->set(i+1, Smi::FromInt(offsets_vector[i+1]));
584 }
585 return Factory::NewJSArrayWithElements(array);
586 }
587
588
589 Handle<Object> RegExpImpl::JscreExecGlobal(Handle<JSRegExp> regexp,
590 Handle<String> subject) {
591 ASSERT_EQ(regexp->TypeTag(), JSRegExp::JSCRE);
592 if (regexp->DataAt(JSRegExp::kJscreDataIndex)->IsUndefined()) {
593 Handle<Object> compile_result = JscreCompile(regexp);
594 if (compile_result.is_null()) return compile_result;
595 }
596 ASSERT(regexp->DataAt(JSRegExp::kJscreDataIndex)->IsFixedArray());
597
598 // Prepare space for the return values.
599 int num_captures = JscreNumberOfCaptures(regexp);
600
601 OffsetsVector offsets((num_captures + 1) * 3);
602
603 int previous_index = 0;
604
605 Handle<JSArray> result = Factory::NewJSArray(0);
606 int i = 0;
607 Handle<Object> matches;
608
609 Handle<String> subject16 = CachedStringToTwoByte(subject);
610
611 do {
612 if (previous_index > subject->length() || previous_index < 0) {
613 // Per ECMA-262 15.10.6.2, if the previous index is greater than the
614 // string length, there is no match.
615 matches = Factory::null_value();
616 } else {
617 matches = JscreExecOnce(regexp,
618 num_captures,
619 subject,
620 previous_index,
621 subject16->GetTwoByteData(),
622 offsets.vector(),
623 offsets.length());
624
625 if (matches->IsJSArray()) {
626 SetElement(result, i, matches);
627 i++;
628 previous_index = offsets.vector()[1];
629 if (offsets.vector()[0] == offsets.vector()[1]) {
630 previous_index++;
631 }
632 }
633 }
634 } while (matches->IsJSArray());
635
636 // If we exited the loop with an exception, throw it.
637 if (matches->IsNull()) {
638 // Exited loop normally.
639 return result;
640 } else {
641 // Exited loop with the exception in matches.
642 return matches;
643 }
644 }
645
646
647 // Irregexp implementation. 354 // Irregexp implementation.
648 355
649 356
650 // Retrieves a compiled version of the regexp for either ASCII or non-ASCII 357 // Retrieves a compiled version of the regexp for either ASCII or non-ASCII
651 // strings. If the compiled version doesn't already exist, it is compiled 358 // strings. If the compiled version doesn't already exist, it is compiled
652 // from the source pattern. 359 // from the source pattern.
653 // Irregexp is not feature complete yet. If there is something in the 360 // Irregexp is not feature complete yet. If there is something in the
654 // regexp that the compiler cannot currently handle, an empty 361 // regexp that the compiler cannot currently handle, an empty
655 // handle is returned, but no exception is thrown. 362 // handle is returned, but no exception is thrown.
656 static Handle<FixedArray> GetCompiledIrregexp(Handle<JSRegExp> re, 363 static Handle<FixedArray> GetCompiledIrregexp(Handle<JSRegExp> re,
(...skipping 1406 matching lines...) Expand 10 before | Expand all | Expand 10 after
2063 return DONE; 1770 return DONE;
2064 } 1771 }
2065 // Generate generic version of the node and bind the label for later use. 1772 // Generate generic version of the node and bind the label for later use.
2066 macro_assembler->Bind(&label_); 1773 macro_assembler->Bind(&label_);
2067 return CONTINUE; 1774 return CONTINUE;
2068 } 1775 }
2069 1776
2070 // We are being asked to make a non-generic version. Keep track of how many 1777 // We are being asked to make a non-generic version. Keep track of how many
2071 // non-generic versions we generate so as not to overdo it. 1778 // non-generic versions we generate so as not to overdo it.
2072 trace_count_++; 1779 trace_count_++;
2073 if (FLAG_irregexp_optimization && 1780 if (FLAG_regexp_optimization &&
2074 trace_count_ < kMaxCopiesCodeGenerated && 1781 trace_count_ < kMaxCopiesCodeGenerated &&
2075 compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) { 1782 compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) {
2076 return CONTINUE; 1783 return CONTINUE;
2077 } 1784 }
2078 1785
2079 // If we get here code has been generated for this node too many times or 1786 // If we get here code has been generated for this node too many times or
2080 // recursion is too deep. Time to switch to a generic version. The code for 1787 // recursion is too deep. Time to switch to a generic version. The code for
2081 // generic versions above can handle deep recursion properly. 1788 // generic versions above can handle deep recursion properly.
2082 trace->Flush(compiler, this); 1789 trace->Flush(compiler, this);
2083 return DONE; 1790 return DONE;
(...skipping 1146 matching lines...) Expand 10 before | Expand all | Expand 10 after
3230 new_trace.set_characters_preloaded(preload_is_current ? 2937 new_trace.set_characters_preloaded(preload_is_current ?
3231 preload_characters : 2938 preload_characters :
3232 0); 2939 0);
3233 if (preload_has_checked_bounds) { 2940 if (preload_has_checked_bounds) {
3234 new_trace.set_bound_checked_up_to(preload_characters); 2941 new_trace.set_bound_checked_up_to(preload_characters);
3235 } 2942 }
3236 new_trace.quick_check_performed()->Clear(); 2943 new_trace.quick_check_performed()->Clear();
3237 if (not_at_start_) new_trace.set_at_start(Trace::FALSE); 2944 if (not_at_start_) new_trace.set_at_start(Trace::FALSE);
3238 alt_gen->expects_preload = preload_is_current; 2945 alt_gen->expects_preload = preload_is_current;
3239 bool generate_full_check_inline = false; 2946 bool generate_full_check_inline = false;
3240 if (FLAG_irregexp_optimization && 2947 if (FLAG_regexp_optimization &&
3241 try_to_emit_quick_check_for_alternative(i) && 2948 try_to_emit_quick_check_for_alternative(i) &&
3242 alternative.node()->EmitQuickCheck(compiler, 2949 alternative.node()->EmitQuickCheck(compiler,
3243 &new_trace, 2950 &new_trace,
3244 preload_has_checked_bounds, 2951 preload_has_checked_bounds,
3245 &alt_gen->possible_success, 2952 &alt_gen->possible_success,
3246 &alt_gen->quick_check_details, 2953 &alt_gen->quick_check_details,
3247 i < choice_count - 1)) { 2954 i < choice_count - 1)) {
3248 // Quick check was generated for this choice. 2955 // Quick check was generated for this choice.
3249 preload_is_current = true; 2956 preload_is_current = true;
3250 preload_has_checked_bounds = true; 2957 preload_has_checked_bounds = true;
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after
4031 // this case. 3738 // this case.
4032 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,} 3739 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,}
4033 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3} 3740 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3}
4034 if (max == 0) return on_success; // This can happen due to recursion. 3741 if (max == 0) return on_success; // This can happen due to recursion.
4035 bool body_can_be_empty = (body->min_match() == 0); 3742 bool body_can_be_empty = (body->min_match() == 0);
4036 int body_start_reg = RegExpCompiler::kNoRegister; 3743 int body_start_reg = RegExpCompiler::kNoRegister;
4037 Interval capture_registers = body->CaptureRegisters(); 3744 Interval capture_registers = body->CaptureRegisters();
4038 bool needs_capture_clearing = !capture_registers.is_empty(); 3745 bool needs_capture_clearing = !capture_registers.is_empty();
4039 if (body_can_be_empty) { 3746 if (body_can_be_empty) {
4040 body_start_reg = compiler->AllocateRegister(); 3747 body_start_reg = compiler->AllocateRegister();
4041 } else if (FLAG_irregexp_optimization && !needs_capture_clearing) { 3748 } else if (FLAG_regexp_optimization && !needs_capture_clearing) {
4042 // Only unroll if there are no captures and the body can't be 3749 // Only unroll if there are no captures and the body can't be
4043 // empty. 3750 // empty.
4044 if (min > 0 && min <= kMaxUnrolledMinMatches) { 3751 if (min > 0 && min <= kMaxUnrolledMinMatches) {
4045 int new_max = (max == kInfinity) ? max : max - min; 3752 int new_max = (max == kInfinity) ? max : max - min;
4046 // Recurse once to get the loop or optional matches after the fixed ones. 3753 // Recurse once to get the loop or optional matches after the fixed ones.
4047 RegExpNode* answer = ToNode( 3754 RegExpNode* answer = ToNode(
4048 0, new_max, is_greedy, body, compiler, on_success, true); 3755 0, new_max, is_greedy, body, compiler, on_success, true);
4049 // Unroll the forced matches from 0 to min. This can cause chains of 3756 // Unroll the forced matches from 0 to min. This can cause chains of
4050 // TextNodes (which the parser does not generate). These should be 3757 // TextNodes (which the parser does not generate). These should be
4051 // combined if it turns out they hinder good code generation. 3758 // combined if it turns out they hinder good code generation.
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after
4923 } else { 4630 } else {
4924 node = loop_node; 4631 node = loop_node;
4925 } 4632 }
4926 } 4633 }
4927 data->node = node; 4634 data->node = node;
4928 Analysis analysis(ignore_case); 4635 Analysis analysis(ignore_case);
4929 analysis.EnsureAnalyzed(node); 4636 analysis.EnsureAnalyzed(node);
4930 4637
4931 NodeInfo info = *node->info(); 4638 NodeInfo info = *node->info();
4932 4639
4933 if (FLAG_irregexp_native) { 4640 if (FLAG_regexp_native) {
4934 #ifdef ARM 4641 #ifdef ARM
4935 // Unimplemented, fall-through to bytecode implementation. 4642 // Unimplemented, fall-through to bytecode implementation.
4936 #else // IA32 4643 #else // IA32
4937 RegExpMacroAssemblerIA32::Mode mode; 4644 RegExpMacroAssemblerIA32::Mode mode;
4938 if (is_ascii) { 4645 if (is_ascii) {
4939 mode = RegExpMacroAssemblerIA32::ASCII; 4646 mode = RegExpMacroAssemblerIA32::ASCII;
4940 } else { 4647 } else {
4941 mode = RegExpMacroAssemblerIA32::UC16; 4648 mode = RegExpMacroAssemblerIA32::UC16;
4942 } 4649 }
4943 RegExpMacroAssemblerIA32 macro_assembler(mode, 4650 RegExpMacroAssemblerIA32 macro_assembler(mode,
4944 (data->capture_count + 1) * 2); 4651 (data->capture_count + 1) * 2);
4945 return compiler.Assemble(&macro_assembler, 4652 return compiler.Assemble(&macro_assembler,
4946 node, 4653 node,
4947 data->capture_count, 4654 data->capture_count,
4948 pattern); 4655 pattern);
4949 #endif 4656 #endif
4950 } 4657 }
4951 EmbeddedVector<byte, 1024> codes; 4658 EmbeddedVector<byte, 1024> codes;
4952 RegExpMacroAssemblerIrregexp macro_assembler(codes); 4659 RegExpMacroAssemblerIrregexp macro_assembler(codes);
4953 return compiler.Assemble(&macro_assembler, 4660 return compiler.Assemble(&macro_assembler,
4954 node, 4661 node,
4955 data->capture_count, 4662 data->capture_count,
4956 pattern); 4663 pattern);
4957 } 4664 }
4958 4665
4959 4666
4960 }} // namespace v8::internal 4667 }} // namespace v8::internal
OLDNEW
« LICENSE ('K') | « src/jsregexp.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698