Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3139 if (match.is_null()) { | 3139 if (match.is_null()) { |
| 3140 return Failure::Exception(); | 3140 return Failure::Exception(); |
| 3141 } | 3141 } |
| 3142 if (match->IsNull()) { | 3142 if (match->IsNull()) { |
| 3143 return isolate->heap()->null_value(); | 3143 return isolate->heap()->null_value(); |
| 3144 } | 3144 } |
| 3145 int length = subject->length(); | 3145 int length = subject->length(); |
| 3146 | 3146 |
| 3147 ZoneScope zone_space(isolate, DELETE_ON_EXIT); | 3147 ZoneScope zone_space(isolate, DELETE_ON_EXIT); |
| 3148 ZoneList<int> offsets(8); | 3148 ZoneList<int> offsets(8); |
| 3149 int start; | |
| 3150 int end; | |
| 3149 do { | 3151 do { |
| 3150 int start; | |
| 3151 int end; | |
| 3152 { | 3152 { |
| 3153 AssertNoAllocation no_alloc; | 3153 AssertNoAllocation no_alloc; |
| 3154 FixedArray* elements = FixedArray::cast(regexp_info->elements()); | 3154 FixedArray* elements = FixedArray::cast(regexp_info->elements()); |
| 3155 start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value(); | 3155 start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value(); |
| 3156 end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value(); | 3156 end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value(); |
| 3157 } | 3157 } |
| 3158 offsets.Add(start); | 3158 offsets.Add(start); |
| 3159 offsets.Add(end); | 3159 offsets.Add(end); |
| 3160 int index = start < end ? end : end + 1; | 3160 if (start == end) if (++end > length) break; |
| 3161 if (index > length) break; | 3161 match = RegExpImpl::Exec(regexp, subject, end, regexp_info); |
| 3162 match = RegExpImpl::Exec(regexp, subject, index, regexp_info); | |
| 3163 if (match.is_null()) { | 3162 if (match.is_null()) { |
| 3164 return Failure::Exception(); | 3163 return Failure::Exception(); |
| 3165 } | 3164 } |
| 3166 } while (!match->IsNull()); | 3165 } while (!match->IsNull()); |
| 3167 int matches = offsets.length() / 2; | 3166 int matches = offsets.length() / 2; |
| 3168 Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches); | 3167 Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches); |
| 3169 for (int i = 0; i < matches ; i++) { | 3168 Handle<String> substring = isolate->factory()-> |
| 3170 int from = offsets.at(i * 2); | 3169 NewSubString(subject, offsets.at(0), offsets.at(1)); |
| 3171 int to = offsets.at(i * 2 + 1); | 3170 elements->set(0, *substring); |
| 3172 Handle<String> match = isolate->factory()->NewSubString(subject, from, to); | 3171 for (int i = 1, j = 2; i < matches ; i++) { |
| 3173 elements->set(i, *match); | 3172 int from = offsets.at(j++); |
| 3173 int to = offsets.at(j++); | |
|
Lasse Reichstein
2011/06/22 13:05:45
Is this really faster?
Any optimizing compiler wor
sandholm
2011/06/22 14:05:41
Sure. I'll change it back then.
| |
| 3174 Handle<String> substring = isolate->factory()-> | |
| 3175 NewStrictSubString(subject, from, to); | |
| 3176 elements->set(i, *substring); | |
| 3174 } | 3177 } |
| 3175 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements); | 3178 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements); |
| 3176 result->set_length(Smi::FromInt(matches)); | 3179 result->set_length(Smi::FromInt(matches)); |
| 3177 return *result; | 3180 return *result; |
| 3178 } | 3181 } |
| 3179 | 3182 |
| 3180 | 3183 |
| 3181 // Two smis before and after the match, for very long strings. | 3184 // Two smis before and after the match, for very long strings. |
| 3182 const int kMaxBuilderEntriesPerRegExpMatch = 5; | 3185 const int kMaxBuilderEntriesPerRegExpMatch = 5; |
| 3183 | 3186 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3313 ASSERT(subject->IsFlat()); | 3316 ASSERT(subject->IsFlat()); |
| 3314 int match_start = -1; | 3317 int match_start = -1; |
| 3315 int match_end = 0; | 3318 int match_end = 0; |
| 3316 int pos = 0; | 3319 int pos = 0; |
| 3317 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); | 3320 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); |
| 3318 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; | 3321 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; |
| 3319 | 3322 |
| 3320 OffsetsVector registers(required_registers); | 3323 OffsetsVector registers(required_registers); |
| 3321 Vector<int32_t> register_vector(registers.vector(), registers.length()); | 3324 Vector<int32_t> register_vector(registers.vector(), registers.length()); |
| 3322 int subject_length = subject->length(); | 3325 int subject_length = subject->length(); |
| 3326 bool first = true; | |
| 3323 | 3327 |
| 3324 for (;;) { // Break on failure, return on exception. | 3328 for (;;) { // Break on failure, return on exception. |
| 3325 RegExpImpl::IrregexpResult result = | 3329 RegExpImpl::IrregexpResult result = |
| 3326 RegExpImpl::IrregexpExecOnce(regexp, | 3330 RegExpImpl::IrregexpExecOnce(regexp, |
| 3327 subject, | 3331 subject, |
| 3328 pos, | 3332 pos, |
| 3329 register_vector); | 3333 register_vector); |
| 3330 if (result == RegExpImpl::RE_SUCCESS) { | 3334 if (result == RegExpImpl::RE_SUCCESS) { |
| 3331 match_start = register_vector[0]; | 3335 match_start = register_vector[0]; |
| 3332 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); | 3336 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
| 3333 if (match_end < match_start) { | 3337 if (match_end < match_start) { |
| 3334 ReplacementStringBuilder::AddSubjectSlice(builder, | 3338 ReplacementStringBuilder::AddSubjectSlice(builder, |
| 3335 match_end, | 3339 match_end, |
| 3336 match_start); | 3340 match_start); |
| 3337 } | 3341 } |
| 3338 match_end = register_vector[1]; | 3342 match_end = register_vector[1]; |
| 3339 HandleScope loop_scope(isolate); | 3343 HandleScope loop_scope(isolate); |
| 3340 builder->Add(*isolate->factory()->NewSubString(subject, | 3344 if (!first) { |
| 3341 match_start, | 3345 builder->Add(*isolate->factory()->NewStrictSubString(subject, |
| 3342 match_end)); | 3346 match_start, |
| 3347 match_end)); | |
| 3348 } else { | |
| 3349 builder->Add(*isolate->factory()->NewSubString(subject, | |
| 3350 match_start, | |
| 3351 match_end)); | |
| 3352 } | |
| 3343 if (match_start != match_end) { | 3353 if (match_start != match_end) { |
| 3344 pos = match_end; | 3354 pos = match_end; |
| 3345 } else { | 3355 } else { |
| 3346 pos = match_end + 1; | 3356 pos = match_end + 1; |
| 3347 if (pos > subject_length) break; | 3357 if (pos > subject_length) break; |
| 3348 } | 3358 } |
| 3349 } else if (result == RegExpImpl::RE_FAILURE) { | 3359 } else if (result == RegExpImpl::RE_FAILURE) { |
| 3350 break; | 3360 break; |
| 3351 } else { | 3361 } else { |
| 3352 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); | 3362 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); |
| 3353 return result; | 3363 return result; |
| 3354 } | 3364 } |
| 3365 first = false; | |
| 3355 } | 3366 } |
| 3356 | 3367 |
| 3357 if (match_start >= 0) { | 3368 if (match_start >= 0) { |
| 3358 if (match_end < subject_length) { | 3369 if (match_end < subject_length) { |
| 3359 ReplacementStringBuilder::AddSubjectSlice(builder, | 3370 ReplacementStringBuilder::AddSubjectSlice(builder, |
| 3360 match_end, | 3371 match_end, |
| 3361 subject_length); | 3372 subject_length); |
| 3362 } | 3373 } |
| 3363 SetLastMatchInfoNoCaptures(subject, | 3374 SetLastMatchInfoNoCaptures(subject, |
| 3364 last_match_array, | 3375 last_match_array, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3396 | 3407 |
| 3397 // Position to search from. | 3408 // Position to search from. |
| 3398 int pos = 0; | 3409 int pos = 0; |
| 3399 // End of previous match. Differs from pos if match was empty. | 3410 // End of previous match. Differs from pos if match was empty. |
| 3400 int match_end = 0; | 3411 int match_end = 0; |
| 3401 if (result == RegExpImpl::RE_SUCCESS) { | 3412 if (result == RegExpImpl::RE_SUCCESS) { |
| 3402 // Need to keep a copy of the previous match for creating last_match_info | 3413 // Need to keep a copy of the previous match for creating last_match_info |
| 3403 // at the end, so we have two vectors that we swap between. | 3414 // at the end, so we have two vectors that we swap between. |
| 3404 OffsetsVector registers2(required_registers); | 3415 OffsetsVector registers2(required_registers); |
| 3405 Vector<int> prev_register_vector(registers2.vector(), registers2.length()); | 3416 Vector<int> prev_register_vector(registers2.vector(), registers2.length()); |
| 3406 | 3417 bool first = true; |
| 3407 do { | 3418 do { |
| 3408 int match_start = register_vector[0]; | 3419 int match_start = register_vector[0]; |
| 3409 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); | 3420 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
| 3410 if (match_end < match_start) { | 3421 if (match_end < match_start) { |
| 3411 ReplacementStringBuilder::AddSubjectSlice(builder, | 3422 ReplacementStringBuilder::AddSubjectSlice(builder, |
| 3412 match_end, | 3423 match_end, |
| 3413 match_start); | 3424 match_start); |
| 3414 } | 3425 } |
| 3415 match_end = register_vector[1]; | 3426 match_end = register_vector[1]; |
| 3416 | 3427 |
| 3417 { | 3428 { |
| 3418 // Avoid accumulating new handles inside loop. | 3429 // Avoid accumulating new handles inside loop. |
| 3419 HandleScope temp_scope(isolate); | 3430 HandleScope temp_scope(isolate); |
| 3420 // Arguments array to replace function is match, captures, index and | 3431 // Arguments array to replace function is match, captures, index and |
| 3421 // subject, i.e., 3 + capture count in total. | 3432 // subject, i.e., 3 + capture count in total. |
| 3422 Handle<FixedArray> elements = | 3433 Handle<FixedArray> elements = |
| 3423 isolate->factory()->NewFixedArray(3 + capture_count); | 3434 isolate->factory()->NewFixedArray(3 + capture_count); |
| 3424 Handle<String> match = isolate->factory()->NewSubString(subject, | 3435 Handle<String> match; |
| 3425 match_start, | 3436 if (!first) { |
| 3426 match_end); | 3437 match = isolate->factory()->NewStrictSubString(subject, |
| 3438 match_start, | |
| 3439 match_end); | |
| 3440 } else { | |
| 3441 match = isolate->factory()->NewSubString(subject, | |
| 3442 match_start, | |
| 3443 match_end); | |
| 3444 } | |
| 3427 elements->set(0, *match); | 3445 elements->set(0, *match); |
| 3428 for (int i = 1; i <= capture_count; i++) { | 3446 for (int i = 1; i <= capture_count; i++) { |
| 3429 int start = register_vector[i * 2]; | 3447 int start = register_vector[i * 2]; |
| 3430 if (start >= 0) { | 3448 if (start >= 0) { |
| 3431 int end = register_vector[i * 2 + 1]; | 3449 int end = register_vector[i * 2 + 1]; |
| 3432 ASSERT(start <= end); | 3450 ASSERT(start <= end); |
| 3433 Handle<String> substring = isolate->factory()->NewSubString(subject, | 3451 Handle<String> substring; |
| 3434 start, | 3452 if (!first) { |
| 3435 end); | 3453 substring = isolate->factory()->NewStrictSubString(subject, |
| 3454 start, | |
| 3455 end); | |
| 3456 } else { | |
| 3457 substring = isolate->factory()->NewSubString(subject, start, end); | |
| 3458 } | |
| 3436 elements->set(i, *substring); | 3459 elements->set(i, *substring); |
| 3437 } else { | 3460 } else { |
| 3438 ASSERT(register_vector[i * 2 + 1] < 0); | 3461 ASSERT(register_vector[i * 2 + 1] < 0); |
| 3439 elements->set(i, isolate->heap()->undefined_value()); | 3462 elements->set(i, isolate->heap()->undefined_value()); |
| 3440 } | 3463 } |
| 3441 } | 3464 } |
| 3442 elements->set(capture_count + 1, Smi::FromInt(match_start)); | 3465 elements->set(capture_count + 1, Smi::FromInt(match_start)); |
| 3443 elements->set(capture_count + 2, *subject); | 3466 elements->set(capture_count + 2, *subject); |
| 3444 builder->Add(*isolate->factory()->NewJSArrayWithElements(elements)); | 3467 builder->Add(*isolate->factory()->NewJSArrayWithElements(elements)); |
| 3445 } | 3468 } |
| 3446 // Swap register vectors, so the last successful match is in | 3469 // Swap register vectors, so the last successful match is in |
| 3447 // prev_register_vector. | 3470 // prev_register_vector. |
| 3448 Vector<int32_t> tmp = prev_register_vector; | 3471 Vector<int32_t> tmp = prev_register_vector; |
| 3449 prev_register_vector = register_vector; | 3472 prev_register_vector = register_vector; |
| 3450 register_vector = tmp; | 3473 register_vector = tmp; |
| 3451 | 3474 |
| 3452 if (match_end > match_start) { | 3475 if (match_end > match_start) { |
| 3453 pos = match_end; | 3476 pos = match_end; |
| 3454 } else { | 3477 } else { |
| 3455 pos = match_end + 1; | 3478 pos = match_end + 1; |
| 3456 if (pos > subject_length) { | 3479 if (pos > subject_length) { |
| 3457 break; | 3480 break; |
| 3458 } | 3481 } |
| 3459 } | 3482 } |
| 3460 | 3483 |
| 3461 result = RegExpImpl::IrregexpExecOnce(regexp, | 3484 result = RegExpImpl::IrregexpExecOnce(regexp, |
| 3462 subject, | 3485 subject, |
| 3463 pos, | 3486 pos, |
| 3464 register_vector); | 3487 register_vector); |
| 3488 first = false; | |
| 3465 } while (result == RegExpImpl::RE_SUCCESS); | 3489 } while (result == RegExpImpl::RE_SUCCESS); |
| 3466 | 3490 |
| 3467 if (result != RegExpImpl::RE_EXCEPTION) { | 3491 if (result != RegExpImpl::RE_EXCEPTION) { |
| 3468 // Finished matching, with at least one match. | 3492 // Finished matching, with at least one match. |
| 3469 if (match_end < subject_length) { | 3493 if (match_end < subject_length) { |
| 3470 ReplacementStringBuilder::AddSubjectSlice(builder, | 3494 ReplacementStringBuilder::AddSubjectSlice(builder, |
| 3471 match_end, | 3495 match_end, |
| 3472 subject_length); | 3496 subject_length); |
| 3473 } | 3497 } |
| 3474 | 3498 |
| (...skipping 2348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5823 FixedArray::cast(result->elements())->set(0, *subject); | 5847 FixedArray::cast(result->elements())->set(0, *subject); |
| 5824 return *result; | 5848 return *result; |
| 5825 } | 5849 } |
| 5826 | 5850 |
| 5827 Handle<FixedArray> elements(FixedArray::cast(result->elements())); | 5851 Handle<FixedArray> elements(FixedArray::cast(result->elements())); |
| 5828 int part_start = 0; | 5852 int part_start = 0; |
| 5829 for (int i = 0; i < part_count; i++) { | 5853 for (int i = 0; i < part_count; i++) { |
| 5830 HandleScope local_loop_handle; | 5854 HandleScope local_loop_handle; |
| 5831 int part_end = indices.at(i); | 5855 int part_end = indices.at(i); |
| 5832 Handle<String> substring = | 5856 Handle<String> substring = |
| 5833 isolate->factory()->NewSubString(subject, part_start, part_end); | 5857 isolate->factory()->NewStrictSubString(subject, part_start, part_end); |
| 5834 elements->set(i, *substring); | 5858 elements->set(i, *substring); |
| 5835 part_start = part_end + pattern_length; | 5859 part_start = part_end + pattern_length; |
| 5836 } | 5860 } |
| 5837 | 5861 |
| 5838 return *result; | 5862 return *result; |
| 5839 } | 5863 } |
| 5840 | 5864 |
| 5841 | 5865 |
| 5842 // Copies ascii characters to the given fixed array looking up | 5866 // Copies ascii characters to the given fixed array looking up |
| 5843 // one-char strings in the cache. Gives up on the first char that is | 5867 // one-char strings in the cache. Gives up on the first char that is |
| (...skipping 6614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12458 } else { | 12482 } else { |
| 12459 // Handle last resort GC and make sure to allow future allocations | 12483 // Handle last resort GC and make sure to allow future allocations |
| 12460 // to grow the heap without causing GCs (if possible). | 12484 // to grow the heap without causing GCs (if possible). |
| 12461 isolate->counters()->gc_last_resort_from_js()->Increment(); | 12485 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 12462 isolate->heap()->CollectAllGarbage(false); | 12486 isolate->heap()->CollectAllGarbage(false); |
| 12463 } | 12487 } |
| 12464 } | 12488 } |
| 12465 | 12489 |
| 12466 | 12490 |
| 12467 } } // namespace v8::internal | 12491 } } // namespace v8::internal |
| OLD | NEW |