@@ -1337,7 +1337,7 @@ RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
13371337 Trace* trace) {
13381338 // If we are generating a fixed length loop then don't stop and don't reuse
13391339 // code.
1340- if (trace->stop_node () != nullptr ) {
1340+ if (trace->fixed_length_loop_state () != nullptr ) {
13411341 return CONTINUE;
13421342 }
13431343
@@ -2692,7 +2692,8 @@ void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
26922692
26932693void LoopChoiceNode::Emit (RegExpCompiler* compiler, Trace* trace) {
26942694 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler ();
2695- if (trace->stop_node () == this ) {
2695+ if (trace->fixed_length_loop_state () != nullptr &&
2696+ trace->fixed_length_loop_state ()->loop_choice_node () == this ) {
26962697 // Back edge of fixed length optimized loop node graph.
26972698 int text_length =
26982699 FixedLengthLoopLengthForAlternative (&(alternatives_->at (0 )));
@@ -2701,10 +2702,10 @@ void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
27012702 // optimization for fixed length loops (see below).
27022703 DCHECK (trace->cp_offset () == text_length);
27032704 macro_assembler->AdvanceCurrentPosition (text_length);
2704- macro_assembler-> GoTo (trace-> loop_label () );
2705+ trace-> fixed_length_loop_state ()-> GoToLoopTopLabel (macro_assembler );
27052706 return ;
27062707 }
2707- DCHECK_NULL (trace->stop_node ());
2708+ DCHECK_NULL (trace->fixed_length_loop_state ());
27082709 if (!trace->is_trivial ()) {
27092710 trace->Flush (compiler, this );
27102711 return ;
@@ -3136,11 +3137,28 @@ void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) {
31363137 * S2--/
31373138 */
31383139
3139- FixedLengthLoopState::FixedLengthLoopState (bool not_at_start) {
3140- counter_backtrack_trace_.set_backtrack (&label_);
3140+ FixedLengthLoopState::FixedLengthLoopState (bool not_at_start,
3141+ ChoiceNode* loop_choice_node)
3142+ : loop_choice_node_(loop_choice_node) {
3143+ counter_backtrack_trace_.set_backtrack (&step_backwards_label_);
31413144 if (not_at_start) counter_backtrack_trace_.set_at_start (Trace::FALSE_VALUE);
31423145}
31433146
3147+ void FixedLengthLoopState::BindStepBackwardsLabel (
3148+ RegExpMacroAssembler* macro_assembler) {
3149+ macro_assembler->Bind (&step_backwards_label_);
3150+ }
3151+
3152+ void FixedLengthLoopState::BindLoopTopLabel (
3153+ RegExpMacroAssembler* macro_assembler) {
3154+ macro_assembler->Bind (&loop_top_label_);
3155+ }
3156+
3157+ void FixedLengthLoopState::GoToLoopTopLabel (
3158+ RegExpMacroAssembler* macro_assembler) {
3159+ macro_assembler->GoTo (&loop_top_label_);
3160+ }
3161+
31443162void ChoiceNode::AssertGuardsMentionRegisters (Trace* trace) {
31453163#ifdef DEBUG
31463164 int choice_count = alternatives_->length ();
@@ -3195,7 +3213,9 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
31953213
31963214 PreloadState preload;
31973215 preload.init ();
3198- FixedLengthLoopState fixed_length_loop_state (not_at_start ());
3216+ // This must be outside the 'if' because the trace we use for what
3217+ // comes after the fixed_length_loop is inside it and needs the lifetime.
3218+ FixedLengthLoopState fixed_length_loop_state (not_at_start (), this );
31993219
32003220 int text_length = FixedLengthLoopLengthForAlternative (&alternatives_->at (0 ));
32013221 AlternativeGenerationList alt_gens (choice_count, zone ());
@@ -3242,32 +3262,32 @@ Trace* ChoiceNode::EmitFixedLengthLoop(
32423262 // decrement the current position and check it against the pushed value.
32433263 // This avoids pushing backtrack information for each iteration of the loop,
32443264 // which could take up a lot of space.
3245- DCHECK (trace->stop_node () == nullptr );
3265+ DCHECK (trace->fixed_length_loop_state () == nullptr );
32463266 macro_assembler->PushCurrentPosition ();
3247- Label fixed_length_match_failed;
3267+ // This is the label for trying to match what comes after the greedy
3268+ // quantifier, either because the body of the quantifier failed, or because
3269+ // we have stepped back to try again with one iteration fewer.
3270+ Label after_body_match_attempt;
32483271 Trace fixed_length_match_trace;
32493272 if (not_at_start ()) fixed_length_match_trace.set_at_start (Trace::FALSE_VALUE);
3250- fixed_length_match_trace.set_backtrack (&fixed_length_match_failed);
3251- Label loop_label;
3252- macro_assembler->Bind (&loop_label);
3253- fixed_length_match_trace.set_stop_node (this );
3254- fixed_length_match_trace.set_loop_label (&loop_label);
3273+ fixed_length_match_trace.set_backtrack (&after_body_match_attempt);
3274+ fixed_length_loop_state->BindLoopTopLabel (macro_assembler);
3275+ fixed_length_match_trace.set_fixed_length_loop_state (fixed_length_loop_state);
32553276 alternatives_->at (0 ).node ()->Emit (compiler, &fixed_length_match_trace);
3256- macro_assembler->Bind (&fixed_length_match_failed);
3257-
3258- Label second_choice; // For use in fixed length matches.
3259- macro_assembler->Bind (&second_choice);
3277+ macro_assembler->Bind (&after_body_match_attempt);
32603278
32613279 Trace* new_trace = fixed_length_loop_state->counter_backtrack_trace ();
32623280
3281+ // In a fixed length loop there is only one other choice, which is what
3282+ // comes after the greedy quantifer. Try to match that now.
32633283 EmitChoices (compiler, alt_gens, 1 , new_trace, preload);
32643284
3265- macro_assembler-> Bind ( fixed_length_loop_state->label () );
3285+ fixed_length_loop_state->BindStepBackwardsLabel (macro_assembler );
32663286 // If we have unwound to the bottom then backtrack.
32673287 macro_assembler->CheckFixedLengthLoop (trace->backtrack ());
32683288 // Otherwise try the second priority at an earlier position.
32693289 macro_assembler->AdvanceCurrentPosition (-text_length);
3270- macro_assembler->GoTo (&second_choice );
3290+ macro_assembler->GoTo (&after_body_match_attempt );
32713291 return new_trace;
32723292}
32733293
0 commit comments