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 "src/ast/ast.h" | 7 #include "src/ast/ast.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/compilation-cache.h" | 9 #include "src/compilation-cache.h" |
10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
(...skipping 2309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2320 int answer = Length(); | 2320 int answer = Length(); |
2321 if (answer >= still_to_find) return answer; | 2321 if (answer >= still_to_find) return answer; |
2322 if (budget <= 0) return answer; | 2322 if (budget <= 0) return answer; |
2323 // We are not at start after this node so we set the last argument to 'true'. | 2323 // We are not at start after this node so we set the last argument to 'true'. |
2324 return answer + on_success()->EatsAtLeast(still_to_find - answer, | 2324 return answer + on_success()->EatsAtLeast(still_to_find - answer, |
2325 budget - 1, | 2325 budget - 1, |
2326 true); | 2326 true); |
2327 } | 2327 } |
2328 | 2328 |
2329 | 2329 |
2330 int NegativeLookaheadChoiceNode::EatsAtLeast(int still_to_find, | 2330 int NegativeLookaroundChoiceNode::EatsAtLeast(int still_to_find, int budget, |
2331 int budget, | 2331 bool not_at_start) { |
2332 bool not_at_start) { | |
2333 if (budget <= 0) return 0; | 2332 if (budget <= 0) return 0; |
2334 // Alternative 0 is the negative lookahead, alternative 1 is what comes | 2333 // Alternative 0 is the negative lookahead, alternative 1 is what comes |
2335 // afterwards. | 2334 // afterwards. |
2336 RegExpNode* node = alternatives_->at(1).node(); | 2335 RegExpNode* node = alternatives_->at(1).node(); |
2337 return node->EatsAtLeast(still_to_find, budget - 1, not_at_start); | 2336 return node->EatsAtLeast(still_to_find, budget - 1, not_at_start); |
2338 } | 2337 } |
2339 | 2338 |
2340 | 2339 |
2341 void NegativeLookaheadChoiceNode::GetQuickCheckDetails( | 2340 void NegativeLookaroundChoiceNode::GetQuickCheckDetails( |
2342 QuickCheckDetails* details, | 2341 QuickCheckDetails* details, RegExpCompiler* compiler, int filled_in, |
2343 RegExpCompiler* compiler, | |
2344 int filled_in, | |
2345 bool not_at_start) { | 2342 bool not_at_start) { |
2346 // Alternative 0 is the negative lookahead, alternative 1 is what comes | 2343 // Alternative 0 is the negative lookahead, alternative 1 is what comes |
2347 // afterwards. | 2344 // afterwards. |
2348 RegExpNode* node = alternatives_->at(1).node(); | 2345 RegExpNode* node = alternatives_->at(1).node(); |
2349 return node->GetQuickCheckDetails(details, compiler, filled_in, not_at_start); | 2346 return node->GetQuickCheckDetails(details, compiler, filled_in, not_at_start); |
2350 } | 2347 } |
2351 | 2348 |
2352 | 2349 |
2353 int ChoiceNode::EatsAtLeastHelper(int still_to_find, | 2350 int ChoiceNode::EatsAtLeastHelper(int still_to_find, |
2354 int budget, | 2351 int budget, |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2504 // | 2501 // |
2505 // We iterate along the text object, building up for each character a | 2502 // We iterate along the text object, building up for each character a |
2506 // mask and value that can be used to test for a quick failure to match. | 2503 // mask and value that can be used to test for a quick failure to match. |
2507 // The masks and values for the positions will be combined into a single | 2504 // The masks and values for the positions will be combined into a single |
2508 // machine word for the current character width in order to be used in | 2505 // machine word for the current character width in order to be used in |
2509 // generating a quick check. | 2506 // generating a quick check. |
2510 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details, | 2507 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details, |
2511 RegExpCompiler* compiler, | 2508 RegExpCompiler* compiler, |
2512 int characters_filled_in, | 2509 int characters_filled_in, |
2513 bool not_at_start) { | 2510 bool not_at_start) { |
| 2511 // Do not collect any quick check details if the text node reads backward, |
| 2512 // since it reads in the opposite direction than we use for quick checks. |
| 2513 if (read_backward()) return; |
2514 Isolate* isolate = compiler->macro_assembler()->isolate(); | 2514 Isolate* isolate = compiler->macro_assembler()->isolate(); |
2515 DCHECK(characters_filled_in < details->characters()); | 2515 DCHECK(characters_filled_in < details->characters()); |
2516 int characters = details->characters(); | 2516 int characters = details->characters(); |
2517 int char_mask; | 2517 int char_mask; |
2518 if (compiler->one_byte()) { | 2518 if (compiler->one_byte()) { |
2519 char_mask = String::kMaxOneByteCharCode; | 2519 char_mask = String::kMaxOneByteCharCode; |
2520 } else { | 2520 } else { |
2521 char_mask = String::kMaxUtf16CodeUnit; | 2521 char_mask = String::kMaxUtf16CodeUnit; |
2522 } | 2522 } |
2523 for (int k = 0; k < elements()->length(); k++) { | 2523 for (int k = 0; k < elements()->length(); k++) { |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2665 for (int i = 0; i < characters_; i++) { | 2665 for (int i = 0; i < characters_; i++) { |
2666 positions_[i].mask = 0; | 2666 positions_[i].mask = 0; |
2667 positions_[i].value = 0; | 2667 positions_[i].value = 0; |
2668 positions_[i].determines_perfectly = false; | 2668 positions_[i].determines_perfectly = false; |
2669 } | 2669 } |
2670 characters_ = 0; | 2670 characters_ = 0; |
2671 } | 2671 } |
2672 | 2672 |
2673 | 2673 |
2674 void QuickCheckDetails::Advance(int by, bool one_byte) { | 2674 void QuickCheckDetails::Advance(int by, bool one_byte) { |
2675 if (by >= characters_) { | 2675 if (by >= characters_ || by < 0) { |
| 2676 DCHECK_IMPLIES(by < 0, characters_ == 0); |
2676 Clear(); | 2677 Clear(); |
2677 return; | 2678 return; |
2678 } | 2679 } |
| 2680 DCHECK_LE(characters_ - by, 4); |
| 2681 DCHECK_LE(characters_, 4); |
2679 for (int i = 0; i < characters_ - by; i++) { | 2682 for (int i = 0; i < characters_ - by; i++) { |
2680 positions_[i] = positions_[by + i]; | 2683 positions_[i] = positions_[by + i]; |
2681 } | 2684 } |
2682 for (int i = characters_ - by; i < characters_; i++) { | 2685 for (int i = characters_ - by; i < characters_; i++) { |
2683 positions_[i].mask = 0; | 2686 positions_[i].mask = 0; |
2684 positions_[i].value = 0; | 2687 positions_[i].value = 0; |
2685 positions_[i].determines_perfectly = false; | 2688 positions_[i].determines_perfectly = false; |
2686 } | 2689 } |
2687 characters_ -= by; | 2690 characters_ -= by; |
2688 // We could change mask_ and value_ here but we would never advance unless | 2691 // We could change mask_ and value_ here but we would never advance unless |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2884 if (replacement != NULL) { | 2887 if (replacement != NULL) { |
2885 alternatives_->at(i).set_node(replacement); | 2888 alternatives_->at(i).set_node(replacement); |
2886 new_alternatives->Add(alternatives_->at(i), zone()); | 2889 new_alternatives->Add(alternatives_->at(i), zone()); |
2887 } | 2890 } |
2888 } | 2891 } |
2889 alternatives_ = new_alternatives; | 2892 alternatives_ = new_alternatives; |
2890 return this; | 2893 return this; |
2891 } | 2894 } |
2892 | 2895 |
2893 | 2896 |
2894 RegExpNode* NegativeLookaheadChoiceNode::FilterOneByte(int depth, | 2897 RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(int depth, |
2895 bool ignore_case) { | 2898 bool ignore_case) { |
2896 if (info()->replacement_calculated) return replacement(); | 2899 if (info()->replacement_calculated) return replacement(); |
2897 if (depth < 0) return this; | 2900 if (depth < 0) return this; |
2898 if (info()->visited) return this; | 2901 if (info()->visited) return this; |
2899 VisitMarker marker(info()); | 2902 VisitMarker marker(info()); |
2900 // Alternative 0 is the negative lookahead, alternative 1 is what comes | 2903 // Alternative 0 is the negative lookahead, alternative 1 is what comes |
2901 // afterwards. | 2904 // afterwards. |
2902 RegExpNode* node = alternatives_->at(1).node(); | 2905 RegExpNode* node = alternatives_->at(1).node(); |
2903 RegExpNode* replacement = node->FilterOneByte(depth - 1, ignore_case); | 2906 RegExpNode* replacement = node->FilterOneByte(depth - 1, ignore_case); |
2904 if (replacement == NULL) return set_replacement(NULL); | 2907 if (replacement == NULL) return set_replacement(NULL); |
2905 alternatives_->at(1).set_node(replacement); | 2908 alternatives_->at(1).set_node(replacement); |
(...skipping 2460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5366 // the second alternative is tried, which is exactly the desired result | 5369 // the second alternative is tried, which is exactly the desired result |
5367 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special | 5370 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special |
5368 // ChoiceNode that knows to ignore the first exit when calculating quick | 5371 // ChoiceNode that knows to ignore the first exit when calculating quick |
5369 // checks. | 5372 // checks. |
5370 Zone* zone = compiler->zone(); | 5373 Zone* zone = compiler->zone(); |
5371 | 5374 |
5372 GuardedAlternative body_alt( | 5375 GuardedAlternative body_alt( |
5373 body()->ToNode(compiler, new (zone) NegativeSubmatchSuccess( | 5376 body()->ToNode(compiler, new (zone) NegativeSubmatchSuccess( |
5374 stack_pointer_register, position_register, | 5377 stack_pointer_register, position_register, |
5375 register_count, register_start, zone))); | 5378 register_count, register_start, zone))); |
5376 ChoiceNode* choice_node = | 5379 ChoiceNode* choice_node = new (zone) NegativeLookaroundChoiceNode( |
5377 new(zone) NegativeLookaheadChoiceNode(body_alt, | 5380 body_alt, GuardedAlternative(on_success), zone); |
5378 GuardedAlternative(on_success), | |
5379 zone); | |
5380 result = ActionNode::BeginSubmatch(stack_pointer_register, | 5381 result = ActionNode::BeginSubmatch(stack_pointer_register, |
5381 position_register, choice_node); | 5382 position_register, choice_node); |
5382 } | 5383 } |
5383 compiler->set_read_backward(was_reading_backward); | 5384 compiler->set_read_backward(was_reading_backward); |
5384 return result; | 5385 return result; |
5385 } | 5386 } |
5386 | 5387 |
5387 | 5388 |
5388 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, | 5389 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, |
5389 RegExpNode* on_success) { | 5390 RegExpNode* on_success) { |
(...skipping 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6499 | 6500 |
6500 | 6501 |
6501 void RegExpResultsCache::Clear(FixedArray* cache) { | 6502 void RegExpResultsCache::Clear(FixedArray* cache) { |
6502 for (int i = 0; i < kRegExpResultsCacheSize; i++) { | 6503 for (int i = 0; i < kRegExpResultsCacheSize; i++) { |
6503 cache->set(i, Smi::FromInt(0)); | 6504 cache->set(i, Smi::FromInt(0)); |
6504 } | 6505 } |
6505 } | 6506 } |
6506 | 6507 |
6507 } // namespace internal | 6508 } // namespace internal |
6508 } // namespace v8 | 6509 } // namespace v8 |
OLD | NEW |