@@ -294,30 +294,20 @@ RegExpCompiler::CompilationResult RegExpCompiler::Assemble(
294294 return {code, next_register_};
295295}
296296
297- bool Trace::DeferredAction::Mentions (int that) {
298- if (action_type () == ActionNode::CLEAR_CAPTURES) {
299- Interval range = static_cast <DeferredClearCaptures*>(this )->range ();
300- return range.Contains (that);
301- } else {
302- return reg () == that;
303- }
304- }
305-
306- bool Trace::mentions_reg (int reg) {
307- for (DeferredAction* action = actions_; action != nullptr ;
308- action = action->next ()) {
309- if (action->Mentions (reg)) return true ;
297+ bool Trace::mentions_reg (int reg) const {
298+ for (auto trace : *this ) {
299+ if (trace->has_action () && trace->action ()->Mentions (reg)) return true ;
310300 }
311301 return false ;
312302}
313303
314- bool Trace::GetStoredPosition (int reg, int * cp_offset) {
304+ bool Trace::GetStoredPosition (int reg, int * cp_offset) const {
315305 DCHECK_EQ (0 , *cp_offset);
316- for (DeferredAction* action = actions_; action != nullptr ;
317- action = action-> next ( )) {
318- if (action-> Mentions (reg)) {
319- if (action-> action_type () == ActionNode::STORE_POSITION ) {
320- *cp_offset = static_cast <DeferredCapture*>(action) ->cp_offset ();
306+ for (auto trace : * this ) {
307+ if (trace-> has_action () && trace-> action ()-> Mentions (reg )) {
308+ if (trace-> action_ -> action_type () == ActionNode::CLEAR_POSITION ||
309+ trace-> action_ -> action_type () == ActionNode::RESTORE_POSITION ) {
310+ *cp_offset = trace-> next_ ->cp_offset ();
321311 return true ;
322312 } else {
323313 return false ;
@@ -363,16 +353,13 @@ class DynamicBitSet : public ZoneObject {
363353int Trace::FindAffectedRegisters (DynamicBitSet* affected_registers,
364354 Zone* zone) {
365355 int max_register = RegExpCompiler::kNoRegister ;
366- for (DeferredAction* action = actions_; action != nullptr ;
367- action = action->next ()) {
368- if (action->action_type () == ActionNode::CLEAR_CAPTURES) {
369- Interval range = static_cast <DeferredClearCaptures*>(action)->range ();
370- for (int i = range.from (); i <= range.to (); i++)
356+ for (auto trace : *this ) {
357+ if (ActionNode* action = trace->action_ ) {
358+ int to = action->register_to ();
359+ for (int i = action->register_from (); i <= to; i++) {
371360 affected_registers->Set (i, zone);
372- if (range.to () > max_register) max_register = range.to ();
373- } else {
374- affected_registers->Set (action->reg (), zone);
375- if (action->reg () > max_register) max_register = action->reg ();
361+ }
362+ if (to > max_register) max_register = to;
376363 }
377364 }
378365 return max_register;
@@ -420,15 +407,14 @@ void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
420407 int store_position = kNoStore ;
421408 // This is a little tricky because we are scanning the actions in reverse
422409 // historical order (newest first).
423- for (DeferredAction* action = actions_; action != nullptr ;
424- action = action->next ()) {
410+ for (auto trace : *this ) {
411+ ActionNode* action = trace->action_ ;
412+ if (!action) continue ;
425413 if (action->Mentions (reg)) {
426414 switch (action->action_type ()) {
427415 case ActionNode::SET_REGISTER_FOR_LOOP: {
428- Trace::DeferredSetRegisterForLoop* psr =
429- static_cast <Trace::DeferredSetRegisterForLoop*>(action);
430416 if (!absolute) {
431- value += psr ->value ();
417+ value += action ->value ();
432418 absolute = true ;
433419 }
434420 // SET_REGISTER_FOR_LOOP is only used for newly introduced loop
@@ -449,11 +435,10 @@ void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
449435 DCHECK (!clear);
450436 undo_action = RESTORE;
451437 break ;
452- case ActionNode::STORE_POSITION: {
453- Trace::DeferredCapture* pc =
454- static_cast <Trace::DeferredCapture*>(action);
438+ case ActionNode::CLEAR_POSITION:
439+ case ActionNode::RESTORE_POSITION: {
455440 if (!clear && store_position == kNoStore ) {
456- store_position = pc ->cp_offset ();
441+ store_position = trace-> next () ->cp_offset ();
457442 }
458443
459444 // For captures we know that stores and clears alternate.
@@ -466,7 +451,11 @@ void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
466451 // will set it again or fail.
467452 undo_action = IGNORE;
468453 } else {
469- undo_action = pc->is_capture () ? CLEAR : RESTORE;
454+ if (action->action_type () == ActionNode::CLEAR_POSITION) {
455+ undo_action = CLEAR;
456+ } else {
457+ undo_action = RESTORE;
458+ }
470459 }
471460 DCHECK (!absolute);
472461 DCHECK_EQ (value, 0 );
@@ -527,7 +516,7 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
527516
528517 DCHECK (!is_trivial ());
529518
530- if (actions_ == nullptr && backtrack () == nullptr ) {
519+ if (! has_any_actions () && backtrack () == nullptr ) {
531520 // Here we just have some deferred cp advances to fix and we are back to
532521 // a normal situation. We may also have to forget some information gained
533522 // through a quick check that was already performed.
@@ -638,35 +627,26 @@ void GuardedAlternative::AddGuard(Guard* guard, Zone* zone) {
638627
639628ActionNode* ActionNode::SetRegisterForLoop (int reg, int val,
640629 RegExpNode* on_success) {
641- ActionNode* result =
642- on_success->zone ()->New <ActionNode>(SET_REGISTER_FOR_LOOP, on_success);
643- result->data_ .u_store_register .reg = reg;
644- result->data_ .u_store_register .value = val;
645- return result;
630+ return on_success->zone ()->New <ActionNode>(SET_REGISTER_FOR_LOOP, on_success,
631+ reg, reg, val);
646632}
647633
648634ActionNode* ActionNode::IncrementRegister (int reg, RegExpNode* on_success) {
649- ActionNode* result =
650- on_success->zone ()->New <ActionNode>(INCREMENT_REGISTER, on_success);
651- result->data_ .u_increment_register .reg = reg;
652- return result;
635+ return on_success->zone ()->New <ActionNode>(INCREMENT_REGISTER, on_success,
636+ reg);
653637}
654638
655- ActionNode* ActionNode::StorePosition (int reg, bool is_capture,
656- RegExpNode* on_success) {
657- ActionNode* result =
658- on_success->zone ()->New <ActionNode>(STORE_POSITION, on_success);
659- result->data_ .u_position_register .reg = reg;
660- result->data_ .u_position_register .is_capture = is_capture;
661- return result;
639+ ActionNode* ActionNode::ClearPosition (int reg, RegExpNode* on_success) {
640+ return on_success->zone ()->New <ActionNode>(CLEAR_POSITION, on_success, reg);
641+ }
642+
643+ ActionNode* ActionNode::RestorePosition (int reg, RegExpNode* on_success) {
644+ return on_success->zone ()->New <ActionNode>(RESTORE_POSITION, on_success, reg);
662645}
663646
664647ActionNode* ActionNode::ClearCaptures (Interval range, RegExpNode* on_success) {
665- ActionNode* result =
666- on_success->zone ()->New <ActionNode>(CLEAR_CAPTURES, on_success);
667- result->data_ .u_clear_captures .range_from = range.from ();
668- result->data_ .u_clear_captures .range_to = range.to ();
669- return result;
648+ return on_success->zone ()->New <ActionNode>(CLEAR_CAPTURES, on_success,
649+ range.from (), range.to ());
670650}
671651
672652ActionNode* ActionNode::BeginPositiveSubmatch (int stack_reg, int position_reg,
@@ -2373,7 +2353,7 @@ void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
23732353
23742354namespace {
23752355
2376- bool DeterminedAlready (QuickCheckDetails* quick_check, int offset) {
2356+ bool DeterminedAlready (const QuickCheckDetails* quick_check, int offset) {
23772357 if (quick_check == nullptr ) return false ;
23782358 if (offset >= quick_check->characters ()) return false ;
23792359 return quick_check->positions (offset)->determines_perfectly ;
@@ -2423,7 +2403,7 @@ void TextNode::TextEmitPass(RegExpCompiler* compiler, TextEmitPassType pass,
24232403 Isolate* isolate = assembler->isolate ();
24242404 bool one_byte = compiler->one_byte ();
24252405 Label* backtrack = trace->backtrack ();
2426- QuickCheckDetails* quick_check = trace->quick_check_performed ();
2406+ const QuickCheckDetails* quick_check = trace->quick_check_performed ();
24272407 int element_count = elements ()->length ();
24282408 int backward_offset = read_backward () ? -Length () : 0 ;
24292409 for (int i = preloaded ? 0 : element_count - 1 ; i >= 0 ; i--) {
@@ -3206,7 +3186,7 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
32063186
32073187 // For loop nodes we already flushed (see LoopChoiceNode::Emit), but for
32083188 // other choice nodes we only flush if we are out of code size budget.
3209- if (trace->flush_budget () == 0 && trace->actions () != nullptr ) {
3189+ if (trace->flush_budget () == 0 && trace->has_any_actions () ) {
32103190 trace->Flush (compiler, this );
32113191 return ;
32123192 }
@@ -3239,7 +3219,7 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
32393219 // If there are actions to be flushed we have to limit how many times
32403220 // they are flushed. Take the budget of the parent trace and distribute
32413221 // it fairly amongst the children.
3242- if (new_trace.actions () != nullptr ) {
3222+ if (new_trace.has_any_actions () ) {
32433223 new_trace.set_flush_budget (new_flush_budget);
32443224 }
32453225 bool next_expects_preload =
@@ -3407,7 +3387,7 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
34073387 generate_full_check_inline = true ;
34083388 }
34093389 if (generate_full_check_inline) {
3410- if (new_trace.actions () != nullptr ) {
3390+ if (new_trace.has_any_actions () ) {
34113391 new_trace.set_flush_budget (new_flush_budget);
34123392 }
34133393 for (int j = 0 ; j < guard_count; j++) {
@@ -3468,42 +3448,26 @@ void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
34683448 RecursionCheck rc (compiler);
34693449
34703450 switch (action_type_) {
3471- case STORE_POSITION: {
3472- Trace::DeferredCapture new_capture (data_.u_position_register .reg ,
3473- data_.u_position_register .is_capture ,
3474- trace);
3475- Trace new_trace = *trace;
3476- new_trace.add_action (&new_capture);
3477- on_success ()->Emit (compiler, &new_trace);
3478- break ;
3479- }
3480- case INCREMENT_REGISTER: {
3481- Trace::DeferredIncrementRegister new_increment (
3482- data_.u_increment_register .reg );
3483- Trace new_trace = *trace;
3484- new_trace.add_action (&new_increment);
3485- on_success ()->Emit (compiler, &new_trace);
3486- break ;
3487- }
3488- case SET_REGISTER_FOR_LOOP: {
3489- Trace::DeferredSetRegisterForLoop new_set (data_.u_store_register .reg ,
3490- data_.u_store_register .value );
3491- Trace new_trace = *trace;
3492- new_trace.add_action (&new_set);
3493- on_success ()->Emit (compiler, &new_trace);
3494- break ;
3495- }
3451+ // Start with the actions we know how to defer. These are just recorded in
3452+ // the new trace, no code is emitted right now. (If we backtrack then we
3453+ // don't have to perform and undo these actions.)
3454+ case CLEAR_POSITION:
3455+ case RESTORE_POSITION:
3456+ case INCREMENT_REGISTER:
3457+ case SET_REGISTER_FOR_LOOP:
34963458 case CLEAR_CAPTURES: {
3497- Trace::DeferredClearCaptures new_capture (Interval (
3498- data_.u_clear_captures .range_from , data_.u_clear_captures .range_to ));
34993459 Trace new_trace = *trace;
3500- new_trace.add_action (&new_capture );
3460+ new_trace.add_action (this );
35013461 on_success ()->Emit (compiler, &new_trace);
35023462 break ;
35033463 }
3464+ // We don't yet have the ability to defer these.
35043465 case BEGIN_POSITIVE_SUBMATCH:
35053466 case BEGIN_NEGATIVE_SUBMATCH:
35063467 if (!trace->is_trivial ()) {
3468+ // Complex situation: Flush the trace state to the assembler and
3469+ // generate a generic version of this action. This call will
3470+ // recurse back to the else clause here.
35073471 trace->Flush (compiler, this );
35083472 } else {
35093473 assembler->WriteCurrentPositionToRegister (
0 commit comments