OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2292 | 2292 |
2293 // If we get here code has been generated for this node too many times or | 2293 // If we get here code has been generated for this node too many times or |
2294 // recursion is too deep. Time to switch to a generic version. The code for | 2294 // recursion is too deep. Time to switch to a generic version. The code for |
2295 // generic versions above can handle deep recursion properly. | 2295 // generic versions above can handle deep recursion properly. |
2296 trace->Flush(compiler, this); | 2296 trace->Flush(compiler, this); |
2297 return DONE; | 2297 return DONE; |
2298 } | 2298 } |
2299 | 2299 |
2300 | 2300 |
2301 int ActionNode::EatsAtLeast(int still_to_find, | 2301 int ActionNode::EatsAtLeast(int still_to_find, |
2302 int recursion_depth, | 2302 int budget, |
2303 bool not_at_start) { | 2303 bool not_at_start) { |
2304 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; | 2304 if (budget <= 0) return 0; |
2305 if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input! | 2305 if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input! |
2306 return on_success()->EatsAtLeast(still_to_find, | 2306 return on_success()->EatsAtLeast(still_to_find, |
2307 recursion_depth + 1, | 2307 budget - 1, |
2308 not_at_start); | 2308 not_at_start); |
2309 } | 2309 } |
2310 | 2310 |
2311 | 2311 |
2312 void ActionNode::FillInBMInfo(int offset, | 2312 void ActionNode::FillInBMInfo(int offset, |
2313 int recursion_depth, | |
2314 int budget, | 2313 int budget, |
2315 BoyerMooreLookahead* bm, | 2314 BoyerMooreLookahead* bm, |
2316 bool not_at_start) { | 2315 bool not_at_start) { |
2317 if (type_ == BEGIN_SUBMATCH) { | 2316 if (type_ == BEGIN_SUBMATCH) { |
2318 bm->SetRest(offset); | 2317 bm->SetRest(offset); |
2319 } else if (type_ != POSITIVE_SUBMATCH_SUCCESS) { | 2318 } else if (type_ != POSITIVE_SUBMATCH_SUCCESS) { |
2320 on_success()->FillInBMInfo( | 2319 on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start); |
2321 offset, recursion_depth + 1, budget - 1, bm, not_at_start); | |
2322 } | 2320 } |
2323 SaveBMInfo(bm, not_at_start, offset); | 2321 SaveBMInfo(bm, not_at_start, offset); |
2324 } | 2322 } |
2325 | 2323 |
2326 | 2324 |
2327 int AssertionNode::EatsAtLeast(int still_to_find, | 2325 int AssertionNode::EatsAtLeast(int still_to_find, |
2328 int recursion_depth, | 2326 int budget, |
2329 bool not_at_start) { | 2327 bool not_at_start) { |
2330 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; | 2328 if (budget <= 0) return 0; |
2331 // If we know we are not at the start and we are asked "how many characters | 2329 // If we know we are not at the start and we are asked "how many characters |
2332 // will you match if you succeed?" then we can answer anything since false | 2330 // will you match if you succeed?" then we can answer anything since false |
2333 // implies false. So lets just return the max answer (still_to_find) since | 2331 // implies false. So lets just return the max answer (still_to_find) since |
2334 // that won't prevent us from preloading a lot of characters for the other | 2332 // that won't prevent us from preloading a lot of characters for the other |
2335 // branches in the node graph. | 2333 // branches in the node graph. |
2336 if (type() == AT_START && not_at_start) return still_to_find; | 2334 if (type() == AT_START && not_at_start) return still_to_find; |
2337 return on_success()->EatsAtLeast(still_to_find, | 2335 return on_success()->EatsAtLeast(still_to_find, |
2338 recursion_depth + 1, | 2336 budget - 1, |
2339 not_at_start); | 2337 not_at_start); |
2340 } | 2338 } |
2341 | 2339 |
2342 | 2340 |
2343 void AssertionNode::FillInBMInfo(int offset, | 2341 void AssertionNode::FillInBMInfo(int offset, |
2344 int recursion_depth, | |
2345 int budget, | 2342 int budget, |
2346 BoyerMooreLookahead* bm, | 2343 BoyerMooreLookahead* bm, |
2347 bool not_at_start) { | 2344 bool not_at_start) { |
2348 // Match the behaviour of EatsAtLeast on this node. | 2345 // Match the behaviour of EatsAtLeast on this node. |
2349 if (type() == AT_START && not_at_start) return; | 2346 if (type() == AT_START && not_at_start) return; |
2350 on_success()->FillInBMInfo( | 2347 on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start); |
2351 offset, recursion_depth + 1, budget - 1, bm, not_at_start); | |
2352 SaveBMInfo(bm, not_at_start, offset); | 2348 SaveBMInfo(bm, not_at_start, offset); |
2353 } | 2349 } |
2354 | 2350 |
2355 | 2351 |
2356 int BackReferenceNode::EatsAtLeast(int still_to_find, | 2352 int BackReferenceNode::EatsAtLeast(int still_to_find, |
2357 int recursion_depth, | 2353 int budget, |
2358 bool not_at_start) { | 2354 bool not_at_start) { |
2359 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; | 2355 if (budget <= 0) return 0; |
2360 return on_success()->EatsAtLeast(still_to_find, | 2356 return on_success()->EatsAtLeast(still_to_find, |
2361 recursion_depth + 1, | 2357 budget - 1, |
2362 not_at_start); | 2358 not_at_start); |
2363 } | 2359 } |
2364 | 2360 |
2365 | 2361 |
2366 int TextNode::EatsAtLeast(int still_to_find, | 2362 int TextNode::EatsAtLeast(int still_to_find, |
2367 int recursion_depth, | 2363 int budget, |
2368 bool not_at_start) { | 2364 bool not_at_start) { |
2369 int answer = Length(); | 2365 int answer = Length(); |
2370 if (answer >= still_to_find) return answer; | 2366 if (answer >= still_to_find) return answer; |
2371 if (recursion_depth > RegExpCompiler::kMaxRecursion) return answer; | 2367 if (budget <= 0) return answer; |
2372 // We are not at start after this node so we set the last argument to 'true'. | 2368 // We are not at start after this node so we set the last argument to 'true'. |
2373 return answer + on_success()->EatsAtLeast(still_to_find - answer, | 2369 return answer + on_success()->EatsAtLeast(still_to_find - answer, |
2374 recursion_depth + 1, | 2370 budget - 1, |
2375 true); | 2371 true); |
2376 } | 2372 } |
2377 | 2373 |
2378 | 2374 |
2379 int NegativeLookaheadChoiceNode::EatsAtLeast(int still_to_find, | 2375 int NegativeLookaheadChoiceNode::EatsAtLeast(int still_to_find, |
2380 int recursion_depth, | 2376 int budget, |
2381 bool not_at_start) { | 2377 bool not_at_start) { |
2382 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; | 2378 if (budget <= 0) return 0; |
2383 // Alternative 0 is the negative lookahead, alternative 1 is what comes | 2379 // Alternative 0 is the negative lookahead, alternative 1 is what comes |
2384 // afterwards. | 2380 // afterwards. |
2385 RegExpNode* node = alternatives_->at(1).node(); | 2381 RegExpNode* node = alternatives_->at(1).node(); |
2386 return node->EatsAtLeast(still_to_find, recursion_depth + 1, not_at_start); | 2382 return node->EatsAtLeast(still_to_find, budget - 1, not_at_start); |
2387 } | 2383 } |
2388 | 2384 |
2389 | 2385 |
2390 void NegativeLookaheadChoiceNode::GetQuickCheckDetails( | 2386 void NegativeLookaheadChoiceNode::GetQuickCheckDetails( |
2391 QuickCheckDetails* details, | 2387 QuickCheckDetails* details, |
2392 RegExpCompiler* compiler, | 2388 RegExpCompiler* compiler, |
2393 int filled_in, | 2389 int filled_in, |
2394 bool not_at_start) { | 2390 bool not_at_start) { |
2395 // Alternative 0 is the negative lookahead, alternative 1 is what comes | 2391 // Alternative 0 is the negative lookahead, alternative 1 is what comes |
2396 // afterwards. | 2392 // afterwards. |
2397 RegExpNode* node = alternatives_->at(1).node(); | 2393 RegExpNode* node = alternatives_->at(1).node(); |
2398 return node->GetQuickCheckDetails(details, compiler, filled_in, not_at_start); | 2394 return node->GetQuickCheckDetails(details, compiler, filled_in, not_at_start); |
2399 } | 2395 } |
2400 | 2396 |
2401 | 2397 |
2402 int ChoiceNode::EatsAtLeastHelper(int still_to_find, | 2398 int ChoiceNode::EatsAtLeastHelper(int still_to_find, |
2403 int recursion_depth, | 2399 int budget, |
2404 RegExpNode* ignore_this_node, | 2400 RegExpNode* ignore_this_node, |
2405 bool not_at_start) { | 2401 bool not_at_start) { |
2406 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; | 2402 if (budget <= 0) return 0; |
2407 int min = 100; | 2403 int min = 100; |
2408 int choice_count = alternatives_->length(); | 2404 int choice_count = alternatives_->length(); |
| 2405 budget = (budget - 1) / choice_count; |
2409 for (int i = 0; i < choice_count; i++) { | 2406 for (int i = 0; i < choice_count; i++) { |
2410 RegExpNode* node = alternatives_->at(i).node(); | 2407 RegExpNode* node = alternatives_->at(i).node(); |
2411 if (node == ignore_this_node) continue; | 2408 if (node == ignore_this_node) continue; |
2412 int node_eats_at_least = node->EatsAtLeast(still_to_find, | 2409 int node_eats_at_least = |
2413 recursion_depth + 1, | 2410 node->EatsAtLeast(still_to_find, budget, not_at_start); |
2414 not_at_start); | |
2415 if (node_eats_at_least < min) min = node_eats_at_least; | 2411 if (node_eats_at_least < min) min = node_eats_at_least; |
| 2412 if (min == 0) return 0; |
2416 } | 2413 } |
2417 return min; | 2414 return min; |
2418 } | 2415 } |
2419 | 2416 |
2420 | 2417 |
2421 int LoopChoiceNode::EatsAtLeast(int still_to_find, | 2418 int LoopChoiceNode::EatsAtLeast(int still_to_find, |
2422 int recursion_depth, | 2419 int budget, |
2423 bool not_at_start) { | 2420 bool not_at_start) { |
2424 return EatsAtLeastHelper(still_to_find, | 2421 return EatsAtLeastHelper(still_to_find, |
2425 recursion_depth, | 2422 budget - 1, |
2426 loop_node_, | 2423 loop_node_, |
2427 not_at_start); | 2424 not_at_start); |
2428 } | 2425 } |
2429 | 2426 |
2430 | 2427 |
2431 int ChoiceNode::EatsAtLeast(int still_to_find, | 2428 int ChoiceNode::EatsAtLeast(int still_to_find, |
2432 int recursion_depth, | 2429 int budget, |
2433 bool not_at_start) { | 2430 bool not_at_start) { |
2434 return EatsAtLeastHelper(still_to_find, | 2431 return EatsAtLeastHelper(still_to_find, |
2435 recursion_depth, | 2432 budget, |
2436 NULL, | 2433 NULL, |
2437 not_at_start); | 2434 not_at_start); |
2438 } | 2435 } |
2439 | 2436 |
2440 | 2437 |
2441 // Takes the left-most 1-bit and smears it out, setting all bits to its right. | 2438 // Takes the left-most 1-bit and smears it out, setting all bits to its right. |
2442 static inline uint32_t SmearBitsRight(uint32_t v) { | 2439 static inline uint32_t SmearBitsRight(uint32_t v) { |
2443 v |= v >> 1; | 2440 v |= v >> 1; |
2444 v |= v >> 2; | 2441 v |= v >> 2; |
2445 v |= v >> 4; | 2442 v |= v >> 4; |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2981 if (body_can_be_zero_length_ || info()->visited) return; | 2978 if (body_can_be_zero_length_ || info()->visited) return; |
2982 VisitMarker marker(info()); | 2979 VisitMarker marker(info()); |
2983 return ChoiceNode::GetQuickCheckDetails(details, | 2980 return ChoiceNode::GetQuickCheckDetails(details, |
2984 compiler, | 2981 compiler, |
2985 characters_filled_in, | 2982 characters_filled_in, |
2986 not_at_start); | 2983 not_at_start); |
2987 } | 2984 } |
2988 | 2985 |
2989 | 2986 |
2990 void LoopChoiceNode::FillInBMInfo(int offset, | 2987 void LoopChoiceNode::FillInBMInfo(int offset, |
2991 int recursion_depth, | |
2992 int budget, | 2988 int budget, |
2993 BoyerMooreLookahead* bm, | 2989 BoyerMooreLookahead* bm, |
2994 bool not_at_start) { | 2990 bool not_at_start) { |
2995 if (body_can_be_zero_length_ || | 2991 if (body_can_be_zero_length_ || budget <= 0) { |
2996 recursion_depth > RegExpCompiler::kMaxRecursion || | |
2997 budget <= 0) { | |
2998 bm->SetRest(offset); | 2992 bm->SetRest(offset); |
2999 SaveBMInfo(bm, not_at_start, offset); | 2993 SaveBMInfo(bm, not_at_start, offset); |
3000 return; | 2994 return; |
3001 } | 2995 } |
3002 ChoiceNode::FillInBMInfo( | 2996 ChoiceNode::FillInBMInfo(offset, budget - 1, bm, not_at_start); |
3003 offset, recursion_depth + 1, budget - 1, bm, not_at_start); | |
3004 SaveBMInfo(bm, not_at_start, offset); | 2997 SaveBMInfo(bm, not_at_start, offset); |
3005 } | 2998 } |
3006 | 2999 |
3007 | 3000 |
3008 void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details, | 3001 void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details, |
3009 RegExpCompiler* compiler, | 3002 RegExpCompiler* compiler, |
3010 int characters_filled_in, | 3003 int characters_filled_in, |
3011 bool not_at_start) { | 3004 bool not_at_start) { |
3012 not_at_start = (not_at_start || not_at_start_); | 3005 not_at_start = (not_at_start || not_at_start_); |
3013 int choice_count = alternatives_->length(); | 3006 int choice_count = alternatives_->length(); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3090 | 3083 |
3091 | 3084 |
3092 // Emit the code to handle \b and \B (word-boundary or non-word-boundary). | 3085 // Emit the code to handle \b and \B (word-boundary or non-word-boundary). |
3093 void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) { | 3086 void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) { |
3094 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 3087 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
3095 Trace::TriBool next_is_word_character = Trace::UNKNOWN; | 3088 Trace::TriBool next_is_word_character = Trace::UNKNOWN; |
3096 bool not_at_start = (trace->at_start() == Trace::FALSE); | 3089 bool not_at_start = (trace->at_start() == Trace::FALSE); |
3097 BoyerMooreLookahead* lookahead = bm_info(not_at_start); | 3090 BoyerMooreLookahead* lookahead = bm_info(not_at_start); |
3098 if (lookahead == NULL) { | 3091 if (lookahead == NULL) { |
3099 int eats_at_least = | 3092 int eats_at_least = |
3100 Min(kMaxLookaheadForBoyerMoore, | 3093 Min(kMaxLookaheadForBoyerMoore, EatsAtLeast(kMaxLookaheadForBoyerMoore, |
3101 EatsAtLeast(kMaxLookaheadForBoyerMoore, 0, not_at_start)); | 3094 kFillInBMBudget, |
| 3095 not_at_start)); |
3102 if (eats_at_least >= 1) { | 3096 if (eats_at_least >= 1) { |
3103 BoyerMooreLookahead* bm = | 3097 BoyerMooreLookahead* bm = |
3104 new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone()); | 3098 new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone()); |
3105 FillInBMInfo(0, 0, kFillInBMBudget, bm, not_at_start); | 3099 FillInBMInfo(0, kFillInBMBudget, bm, not_at_start); |
3106 if (bm->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; | 3100 if (bm->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; |
3107 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE; | 3101 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE; |
3108 } | 3102 } |
3109 } else { | 3103 } else { |
3110 if (lookahead->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; | 3104 if (lookahead->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; |
3111 if (lookahead->at(0)->is_word()) next_is_word_character = Trace::TRUE; | 3105 if (lookahead->at(0)->is_word()) next_is_word_character = Trace::TRUE; |
3112 } | 3106 } |
3113 bool at_boundary = (type_ == AssertionNode::AT_BOUNDARY); | 3107 bool at_boundary = (type_ == AssertionNode::AT_BOUNDARY); |
3114 if (next_is_word_character == Trace::UNKNOWN) { | 3108 if (next_is_word_character == Trace::UNKNOWN) { |
3115 Label before_non_word; | 3109 Label before_non_word; |
(...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4027 // At this point we know that we are at a non-greedy loop that will eat | 4021 // At this point we know that we are at a non-greedy loop that will eat |
4028 // any character one at a time. Any non-anchored regexp has such a | 4022 // any character one at a time. Any non-anchored regexp has such a |
4029 // loop prepended to it in order to find where it starts. We look for | 4023 // loop prepended to it in order to find where it starts. We look for |
4030 // a pattern of the form ...abc... where we can look 6 characters ahead | 4024 // a pattern of the form ...abc... where we can look 6 characters ahead |
4031 // and step forwards 3 if the character is not one of abc. Abc need | 4025 // and step forwards 3 if the character is not one of abc. Abc need |
4032 // not be atoms, they can be any reasonably limited character class or | 4026 // not be atoms, they can be any reasonably limited character class or |
4033 // small alternation. | 4027 // small alternation. |
4034 ASSERT(trace->is_trivial()); // This is the case on LoopChoiceNodes. | 4028 ASSERT(trace->is_trivial()); // This is the case on LoopChoiceNodes. |
4035 BoyerMooreLookahead* lookahead = bm_info(not_at_start); | 4029 BoyerMooreLookahead* lookahead = bm_info(not_at_start); |
4036 if (lookahead == NULL) { | 4030 if (lookahead == NULL) { |
4037 eats_at_least = | 4031 eats_at_least = Min(kMaxLookaheadForBoyerMoore, |
4038 Min(kMaxLookaheadForBoyerMoore, | 4032 EatsAtLeast(kMaxLookaheadForBoyerMoore, |
4039 EatsAtLeast(kMaxLookaheadForBoyerMoore, 0, not_at_start)); | 4033 kFillInBMBudget, |
| 4034 not_at_start)); |
4040 if (eats_at_least >= 1) { | 4035 if (eats_at_least >= 1) { |
4041 BoyerMooreLookahead* bm = | 4036 BoyerMooreLookahead* bm = |
4042 new(zone()) BoyerMooreLookahead(eats_at_least, | 4037 new(zone()) BoyerMooreLookahead(eats_at_least, |
4043 compiler, | 4038 compiler, |
4044 zone()); | 4039 zone()); |
4045 GuardedAlternative alt0 = alternatives_->at(0); | 4040 GuardedAlternative alt0 = alternatives_->at(0); |
4046 alt0.node()->FillInBMInfo(0, 0, kFillInBMBudget, bm, not_at_start); | 4041 alt0.node()->FillInBMInfo(0, kFillInBMBudget, bm, not_at_start); |
4047 skip_was_emitted = bm->EmitSkipInstructions(macro_assembler); | 4042 skip_was_emitted = bm->EmitSkipInstructions(macro_assembler); |
4048 } | 4043 } |
4049 } else { | 4044 } else { |
4050 skip_was_emitted = lookahead->EmitSkipInstructions(macro_assembler); | 4045 skip_was_emitted = lookahead->EmitSkipInstructions(macro_assembler); |
4051 } | 4046 } |
4052 } | 4047 } |
4053 } | 4048 } |
4054 } | 4049 } |
4055 | 4050 |
4056 if (eats_at_least == kEatsAtLeastNotYetInitialized) { | 4051 if (eats_at_least == kEatsAtLeastNotYetInitialized) { |
4057 // Save some time by looking at most one machine word ahead. | 4052 // Save some time by looking at most one machine word ahead. |
4058 eats_at_least = EatsAtLeast(compiler->ascii() ? 4 : 2, 0, not_at_start); | 4053 eats_at_least = |
| 4054 EatsAtLeast(compiler->ascii() ? 4 : 2, kFillInBMBudget, not_at_start); |
4059 } | 4055 } |
4060 int preload_characters = CalculatePreloadCharacters(compiler, eats_at_least); | 4056 int preload_characters = CalculatePreloadCharacters(compiler, eats_at_least); |
4061 | 4057 |
4062 bool preload_is_current = !skip_was_emitted && | 4058 bool preload_is_current = !skip_was_emitted && |
4063 (current_trace->characters_preloaded() == preload_characters); | 4059 (current_trace->characters_preloaded() == preload_characters); |
4064 bool preload_has_checked_bounds = preload_is_current; | 4060 bool preload_has_checked_bounds = preload_is_current; |
4065 | 4061 |
4066 AlternativeGenerationList alt_gens(choice_count, zone()); | 4062 AlternativeGenerationList alt_gens(choice_count, zone()); |
4067 | 4063 |
4068 // For now we just call all choices one after the other. The idea ultimately | 4064 // For now we just call all choices one after the other. The idea ultimately |
(...skipping 1735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5804 EnsureAnalyzed(that->on_success()); | 5800 EnsureAnalyzed(that->on_success()); |
5805 } | 5801 } |
5806 | 5802 |
5807 | 5803 |
5808 void Analysis::VisitAssertion(AssertionNode* that) { | 5804 void Analysis::VisitAssertion(AssertionNode* that) { |
5809 EnsureAnalyzed(that->on_success()); | 5805 EnsureAnalyzed(that->on_success()); |
5810 } | 5806 } |
5811 | 5807 |
5812 | 5808 |
5813 void BackReferenceNode::FillInBMInfo(int offset, | 5809 void BackReferenceNode::FillInBMInfo(int offset, |
5814 int recursion_depth, | |
5815 int budget, | 5810 int budget, |
5816 BoyerMooreLookahead* bm, | 5811 BoyerMooreLookahead* bm, |
5817 bool not_at_start) { | 5812 bool not_at_start) { |
5818 // Working out the set of characters that a backreference can match is too | 5813 // Working out the set of characters that a backreference can match is too |
5819 // hard, so we just say that any character can match. | 5814 // hard, so we just say that any character can match. |
5820 bm->SetRest(offset); | 5815 bm->SetRest(offset); |
5821 SaveBMInfo(bm, not_at_start, offset); | 5816 SaveBMInfo(bm, not_at_start, offset); |
5822 } | 5817 } |
5823 | 5818 |
5824 | 5819 |
5825 STATIC_ASSERT(BoyerMoorePositionInfo::kMapSize == | 5820 STATIC_ASSERT(BoyerMoorePositionInfo::kMapSize == |
5826 RegExpMacroAssembler::kTableSize); | 5821 RegExpMacroAssembler::kTableSize); |
5827 | 5822 |
5828 | 5823 |
5829 void ChoiceNode::FillInBMInfo(int offset, | 5824 void ChoiceNode::FillInBMInfo(int offset, |
5830 int recursion_depth, | |
5831 int budget, | 5825 int budget, |
5832 BoyerMooreLookahead* bm, | 5826 BoyerMooreLookahead* bm, |
5833 bool not_at_start) { | 5827 bool not_at_start) { |
5834 ZoneList<GuardedAlternative>* alts = alternatives(); | 5828 ZoneList<GuardedAlternative>* alts = alternatives(); |
5835 budget = (budget - 1) / alts->length(); | 5829 budget = (budget - 1) / alts->length(); |
5836 for (int i = 0; i < alts->length(); i++) { | 5830 for (int i = 0; i < alts->length(); i++) { |
5837 GuardedAlternative& alt = alts->at(i); | 5831 GuardedAlternative& alt = alts->at(i); |
5838 if (alt.guards() != NULL && alt.guards()->length() != 0) { | 5832 if (alt.guards() != NULL && alt.guards()->length() != 0) { |
5839 bm->SetRest(offset); // Give up trying to fill in info. | 5833 bm->SetRest(offset); // Give up trying to fill in info. |
5840 SaveBMInfo(bm, not_at_start, offset); | 5834 SaveBMInfo(bm, not_at_start, offset); |
5841 return; | 5835 return; |
5842 } | 5836 } |
5843 alt.node()->FillInBMInfo( | 5837 alt.node()->FillInBMInfo(offset, budget, bm, not_at_start); |
5844 offset, recursion_depth + 1, budget, bm, not_at_start); | |
5845 } | 5838 } |
5846 SaveBMInfo(bm, not_at_start, offset); | 5839 SaveBMInfo(bm, not_at_start, offset); |
5847 } | 5840 } |
5848 | 5841 |
5849 | 5842 |
5850 void TextNode::FillInBMInfo(int initial_offset, | 5843 void TextNode::FillInBMInfo(int initial_offset, |
5851 int recursion_depth, | |
5852 int budget, | 5844 int budget, |
5853 BoyerMooreLookahead* bm, | 5845 BoyerMooreLookahead* bm, |
5854 bool not_at_start) { | 5846 bool not_at_start) { |
5855 if (initial_offset >= bm->length()) return; | 5847 if (initial_offset >= bm->length()) return; |
5856 int offset = initial_offset; | 5848 int offset = initial_offset; |
5857 int max_char = bm->max_char(); | 5849 int max_char = bm->max_char(); |
5858 for (int i = 0; i < elements()->length(); i++) { | 5850 for (int i = 0; i < elements()->length(); i++) { |
5859 if (offset >= bm->length()) { | 5851 if (offset >= bm->length()) { |
5860 if (initial_offset == 0) set_bm_info(not_at_start, bm); | 5852 if (initial_offset == 0) set_bm_info(not_at_start, bm); |
5861 return; | 5853 return; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5898 } | 5890 } |
5899 } | 5891 } |
5900 offset++; | 5892 offset++; |
5901 } | 5893 } |
5902 } | 5894 } |
5903 if (offset >= bm->length()) { | 5895 if (offset >= bm->length()) { |
5904 if (initial_offset == 0) set_bm_info(not_at_start, bm); | 5896 if (initial_offset == 0) set_bm_info(not_at_start, bm); |
5905 return; | 5897 return; |
5906 } | 5898 } |
5907 on_success()->FillInBMInfo(offset, | 5899 on_success()->FillInBMInfo(offset, |
5908 recursion_depth + 1, | |
5909 budget - 1, | 5900 budget - 1, |
5910 bm, | 5901 bm, |
5911 true); // Not at start after a text node. | 5902 true); // Not at start after a text node. |
5912 if (initial_offset == 0) set_bm_info(not_at_start, bm); | 5903 if (initial_offset == 0) set_bm_info(not_at_start, bm); |
5913 } | 5904 } |
5914 | 5905 |
5915 | 5906 |
5916 // ------------------------------------------------------------------- | 5907 // ------------------------------------------------------------------- |
5917 // Dispatch table construction | 5908 // Dispatch table construction |
5918 | 5909 |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6150 } | 6141 } |
6151 | 6142 |
6152 return compiler.Assemble(¯o_assembler, | 6143 return compiler.Assemble(¯o_assembler, |
6153 node, | 6144 node, |
6154 data->capture_count, | 6145 data->capture_count, |
6155 pattern); | 6146 pattern); |
6156 } | 6147 } |
6157 | 6148 |
6158 | 6149 |
6159 }} // namespace v8::internal | 6150 }} // namespace v8::internal |
OLD | NEW |