v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
regexp-nodes.h
Go to the documentation of this file.
1// Copyright 2019 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_REGEXP_REGEXP_NODES_H_
6#define V8_REGEXP_REGEXP_NODES_H_
7
8#include "src/codegen/label.h"
10#include "src/zone/zone.h"
11
12namespace v8 {
13namespace internal {
14
15class AlternativeGenerationList;
16class BoyerMooreLookahead;
17class GreedyLoopState;
18class NodeVisitor;
19class QuickCheckDetails;
20class RegExpCompiler;
21class SeqRegExpNode;
22class Trace;
23struct PreloadState;
24
25#define FOR_EACH_NODE_TYPE(VISIT) \
26 VISIT(End) \
27 VISIT(Action) \
28 VISIT(Choice) \
29 VISIT(LoopChoice) \
30 VISIT(NegativeLookaroundChoice) \
31 VISIT(BackReference) \
32 VISIT(Assertion) \
33 VISIT(Text)
34
35#define FORWARD_DECLARE(type) class type##Node;
37#undef FORWARD_DECLARE
38
39struct NodeInfo final {
41 : being_analyzed(false),
42 been_analyzed(false),
46 at_end(false),
47 visited(false),
49
50 // Returns true if the interests and assumptions of this node
51 // matches the given one.
52 bool Matches(NodeInfo* that) {
53 return (at_end == that->at_end) &&
54 (follows_word_interest == that->follows_word_interest) &&
55 (follows_newline_interest == that->follows_newline_interest) &&
56 (follows_start_interest == that->follows_start_interest);
57 }
58
59 // Updates the interests of this node given the interests of the
60 // node preceding it.
62 at_end |= that->at_end;
63 follows_word_interest |= that->follows_word_interest;
64 follows_newline_interest |= that->follows_newline_interest;
65 follows_start_interest |= that->follows_start_interest;
66 }
67
72
73 // Sets the interests of this node to include the interests of the
74 // following node.
76 follows_word_interest |= that->follows_word_interest;
77 follows_newline_interest |= that->follows_newline_interest;
78 follows_start_interest |= that->follows_start_interest;
79 }
80
82 being_analyzed = false;
83 been_analyzed = false;
84 }
85
87 bool been_analyzed : 1;
88
89 // These bits are set of this node has to know what the preceding
90 // character was.
94
95 bool at_end : 1;
96 bool visited : 1;
98};
99
100struct EatsAtLeastInfo final {
105 void SetMin(const EatsAtLeastInfo& other) {
106 if (other.eats_at_least_from_possibly_start <
109 other.eats_at_least_from_possibly_start;
110 }
111 if (other.eats_at_least_from_not_start < eats_at_least_from_not_start) {
112 eats_at_least_from_not_start = other.eats_at_least_from_not_start;
113 }
114 }
115
116 bool IsZero() const {
119 }
120
121 // Any successful match starting from the current node will consume at least
122 // this many characters. This does not necessarily mean that there is a
123 // possible match with exactly this many characters, but we generally try to
124 // get this number as high as possible to allow for early exit on failure.
126
127 // Like eats_at_least_from_possibly_start, but with the additional assumption
128 // that start-of-string assertions (^) can't match. This value is greater than
129 // or equal to eats_at_least_from_possibly_start.
131};
132
133class RegExpNode : public ZoneObject {
134 public:
136 : replacement_(nullptr),
137 on_work_list_(false),
138 trace_count_(0),
139 zone_(zone) {
140 bm_info_[0] = bm_info_[1] = nullptr;
141 }
142 virtual ~RegExpNode();
143 virtual void Accept(NodeVisitor* visitor) = 0;
144 // Generates a goto to this node or actually generates the code at this point.
145 virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0;
146 // How many characters must this node consume at a minimum in order to
147 // succeed. The not_at_start argument is used to indicate that we know we are
148 // not at the start of the input. In this case anchored branches will always
149 // fail and can be ignored when determining how many characters are consumed
150 // on success. If this node has not been analyzed yet, EatsAtLeast returns 0.
151 uint32_t EatsAtLeast(bool not_at_start);
152 // Returns how many characters this node must consume in order to succeed,
153 // given that this is a LoopChoiceNode whose counter register is in a
154 // newly-initialized state at the current position in the generated code. For
155 // example, consider /a{6,8}/. Absent any extra information, the
156 // LoopChoiceNode for the repetition must report that it consumes at least
157 // zero characters, because it may have already looped several times. However,
158 // with a newly-initialized counter, it can report that it consumes at least
159 // six characters.
161 // Emits some quick code that checks whether the preloaded characters match.
162 // Falls through on certain failure, jumps to the label on possible success.
163 // If the node cannot make a quick check it does nothing and returns false.
164 bool EmitQuickCheck(RegExpCompiler* compiler, Trace* bounds_check_trace,
165 Trace* trace, bool preload_has_checked_bounds,
166 Label* on_possible_success,
167 QuickCheckDetails* details_return,
168 bool fall_through_on_failure, ChoiceNode* predecessor);
169 // For a given number of characters this returns a mask and a value. The
170 // next n characters are anded with the mask and compared with the value.
171 // A comparison failure indicates the node cannot match the next n characters.
172 // A comparison success indicates the node may match.
174 RegExpCompiler* compiler,
175 int characters_filled_in,
176 bool not_at_start) = 0;
177 // Fills in quick check details for this node, given that this is a
178 // LoopChoiceNode whose counter register is in a newly-initialized state at
179 // the current position in the generated code. For example, consider /a{6,8}/.
180 // Absent any extra information, the LoopChoiceNode for the repetition cannot
181 // generate any useful quick check because a match might be the (empty)
182 // continuation node. However, with a newly-initialized counter, it can
183 // generate a quick check for several 'a' characters at once.
185 RegExpCompiler* compiler,
186 int characters_filled_in,
187 bool not_at_start);
190 // Only returns the successor for a text node of length 1 that matches any
191 // character and that has no guards on it.
193 RegExpCompiler* compiler) {
194 return nullptr;
195 }
196
197 // Collects information on the possible code units (mod 128) that can match if
198 // we look forward. This is used for a Boyer-Moore-like string searching
199 // implementation. TODO(erikcorry): This should share more code with
200 // EatsAtLeast, GetQuickCheckDetails. The budget argument is used to limit
201 // the number of nodes we are willing to look at in order to create this data.
202 static const int kRecursionBudget = 200;
203 bool KeepRecursing(RegExpCompiler* compiler);
204 virtual void FillInBMInfo(Isolate* isolate, int offset, int budget,
205 BoyerMooreLookahead* bm, bool not_at_start) {
206 UNREACHABLE();
207 }
208
209 // If we know that the input is one-byte then there are some nodes that can
210 // never match. This method returns a node that can be substituted for
211 // itself, or nullptr if the node can never match.
212 virtual RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) {
213 return this;
214 }
215 // Helper for FilterOneByte.
217 DCHECK(info()->replacement_calculated);
218 return replacement_;
219 }
223 return replacement; // For convenience.
224 }
225
226 // We want to avoid recalculating the lookahead info, so we store it on the
227 // node. Only info that is for this node is stored. We can tell that the
228 // info is for this node when offset == 0, so the information is calculated
229 // relative to this node.
230 void SaveBMInfo(BoyerMooreLookahead* bm, bool not_at_start, int offset) {
231 if (offset == 0) set_bm_info(not_at_start, bm);
232 }
233
234 Label* label() { return &label_; }
235 // If non-generic code is generated for a node (i.e. the node is not at the
236 // start of the trace) then it cannot be reused. This variable sets a limit
237 // on how often we allow that to happen before we insist on starting a new
238 // trace and generating generic code for a node that can be reused by flushing
239 // the deferred actions in the current trace and generating a goto.
240 static const int kMaxCopiesCodeGenerated = 10;
241
242 bool on_work_list() { return on_work_list_; }
243 void set_on_work_list(bool value) { on_work_list_ = value; }
244
245 NodeInfo* info() { return &info_; }
247 void set_eats_at_least_info(const EatsAtLeastInfo& eats_at_least) {
248 eats_at_least_ = eats_at_least;
249 }
250
251 // TODO(v8:10441): This is a hacky way to avoid exponential code size growth
252 // for very large choice nodes that can be generated by unicode property
253 // escapes. In order to avoid inlining (i.e. trace recursion), we pretend to
254 // have generated the maximum count of code copies already.
255 // We should instead fix this properly, e.g. by using the code size budget
256 // (flush_budget) or by generating property escape matches as calls to a C
257 // function.
259
260 BoyerMooreLookahead* bm_info(bool not_at_start) {
261 return bm_info_[not_at_start ? 1 : 0];
262 }
263
264#define DECLARE_CAST(type) \
265 virtual type##Node* As##type##Node() { return nullptr; }
267#undef DECLARE_CAST
268
269 virtual SeqRegExpNode* AsSeqRegExpNode() { return nullptr; }
270
271 Zone* zone() const { return zone_; }
272
273 protected:
276
278
279 void set_bm_info(bool not_at_start, BoyerMooreLookahead* bm) {
280 bm_info_[not_at_start ? 1 : 0] = bm;
281 }
282
283 private:
284 static const int kFirstCharBudget = 10;
288
289 // Saved values for EatsAtLeast results, to avoid recomputation. Filled in
290 // during analysis (valid if info_.been_analyzed is true).
292
293 // This variable keeps track of how many times code has been generated for
294 // this node (in different traces). We don't keep track of where the
295 // generated code is located unless the code is generated at the start of
296 // a trace, in which case it is generic and can be reused by flushing the
297 // deferred operations in the current trace and generating a goto.
300
302};
303
304class SeqRegExpNode : public RegExpNode {
305 public:
310 RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) override;
311 void FillInBMInfo(Isolate* isolate, int offset, int budget,
312 BoyerMooreLookahead* bm, bool not_at_start) override {
313 on_success_->FillInBMInfo(isolate, offset, budget - 1, bm, not_at_start);
314 if (offset == 0) set_bm_info(not_at_start, bm);
315 }
316 SeqRegExpNode* AsSeqRegExpNode() override { return this; }
317
318 protected:
319 RegExpNode* FilterSuccessor(int depth, RegExpCompiler* compiler);
320
321 private:
323};
324
325class ActionNode : public SeqRegExpNode {
326 public:
338 static ActionNode* SetRegisterForLoop(int reg, int val,
341 static ActionNode* StorePosition(int reg, bool is_capture,
344 static ActionNode* BeginPositiveSubmatch(int stack_pointer_reg,
345 int position_reg, RegExpNode* body,
347 static ActionNode* BeginNegativeSubmatch(int stack_pointer_reg,
348 int position_reg,
350 static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg,
351 int restore_reg,
352 int clear_capture_count,
353 int clear_capture_from,
360 ActionNode* AsActionNode() override { return this; }
361 void Accept(NodeVisitor* visitor) override;
362 void Emit(RegExpCompiler* compiler, Trace* trace) override;
364 RegExpCompiler* compiler, int filled_in,
365 bool not_at_start) override;
366 void FillInBMInfo(Isolate* isolate, int offset, int budget,
367 BoyerMooreLookahead* bm, bool not_at_start) override;
369 // TODO(erikcorry): We should allow some action nodes in greedy loops.
370 int GreedyLoopTextLength() override {
372 }
375 return RegExpFlags{data_.u_modify_flags.flags};
376 }
379 return data_.u_submatch.success_node;
380 }
381
382 protected:
385
386 private:
387 union {
388 struct {
389 int reg;
390 int value;
392 struct {
393 int reg;
395 struct {
396 int reg;
399 struct {
404 ActionNode* success_node; // Only used for positive submatch.
406 struct {
411 struct {
415 struct {
416 int flags;
419
421 friend class DotPrinterImpl;
422 friend Zone;
423};
424
425class TextNode : public SeqRegExpNode {
426 public:
436 // Create TextNode for a single character class for the given ranges.
439 bool read_backward,
441 // Create TextNode for a surrogate pair (i.e. match a sequence of two uc16
442 // code unit ranges).
444 Zone* zone, CharacterRange lead, ZoneList<CharacterRange>* trail_ranges,
447 ZoneList<CharacterRange>* lead_ranges,
448 CharacterRange trail,
449 bool read_backward,
451 TextNode* AsTextNode() override { return this; }
452 void Accept(NodeVisitor* visitor) override;
453 void Emit(RegExpCompiler* compiler, Trace* trace) override;
455 RegExpCompiler* compiler, int characters_filled_in,
456 bool not_at_start) override;
458 bool read_backward() { return read_backward_; }
459 void MakeCaseIndependent(Isolate* isolate, bool is_one_byte,
460 RegExpFlags flags);
461 int GreedyLoopTextLength() override;
463 RegExpCompiler* compiler) override;
464 void FillInBMInfo(Isolate* isolate, int offset, int budget,
465 BoyerMooreLookahead* bm, bool not_at_start) override;
466 void CalculateOffsets();
467 RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) override;
468 int Length();
469
470 private:
472 NON_LATIN1_MATCH, // Check for characters that can never match.
473 SIMPLE_CHARACTER_MATCH, // Case-dependent single character check.
474 NON_LETTER_CHARACTER_MATCH, // Check characters that have no case equivs.
475 CASE_CHARACTER_MATCH, // Case-independent single character check.
476 CHARACTER_CLASS_MATCH // Character class.
477 };
478 void TextEmitPass(RegExpCompiler* compiler, TextEmitPassType pass,
479 bool preloaded, Trace* trace, bool first_element_checked,
480 int* checked_up_to);
483};
484
486 public:
509 AssertionNode* AsAssertionNode() override { return this; }
510 void Accept(NodeVisitor* visitor) override;
511 void Emit(RegExpCompiler* compiler, Trace* trace) override;
513 RegExpCompiler* compiler, int filled_in,
514 bool not_at_start) override;
515 void FillInBMInfo(Isolate* isolate, int offset, int budget,
516 BoyerMooreLookahead* bm, bool not_at_start) override;
518
519 private:
520 friend Zone;
521
522 void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace);
524 void BacktrackIfPrevious(RegExpCompiler* compiler, Trace* trace,
525 IfPrevious backtrack_if_previous);
529};
530
532 public:
533 BackReferenceNode(int start_reg, int end_reg, bool read_backward,
536 start_reg_(start_reg),
537 end_reg_(end_reg),
539 BackReferenceNode* AsBackReferenceNode() override { return this; }
540 void Accept(NodeVisitor* visitor) override;
541 int start_register() { return start_reg_; }
542 int end_register() { return end_reg_; }
543 bool read_backward() { return read_backward_; }
544 void Emit(RegExpCompiler* compiler, Trace* trace) override;
546 RegExpCompiler* compiler, int characters_filled_in,
547 bool not_at_start) override {
548 return;
549 }
550 void FillInBMInfo(Isolate* isolate, int offset, int budget,
551 BoyerMooreLookahead* bm, bool not_at_start) override;
552
553 private:
557};
558
559class EndNode : public RegExpNode {
560 public:
562 EndNode(Action action, Zone* zone) : RegExpNode(zone), action_(action) {}
563 EndNode* AsEndNode() override { return this; }
564 void Accept(NodeVisitor* visitor) override;
565 void Emit(RegExpCompiler* compiler, Trace* trace) override;
567 RegExpCompiler* compiler, int characters_filled_in,
568 bool not_at_start) override {
569 // Returning 0 from EatsAtLeast should ensure we never get here.
570 UNREACHABLE();
571 }
572 void FillInBMInfo(Isolate* isolate, int offset, int budget,
573 BoyerMooreLookahead* bm, bool not_at_start) override {
574 // Returning 0 from EatsAtLeast should ensure we never get here.
575 UNREACHABLE();
576 }
577
578 private:
580};
581
583 public:
584 NegativeSubmatchSuccess(int stack_pointer_reg, int position_reg,
585 int clear_capture_count, int clear_capture_start,
586 Zone* zone)
588 stack_pointer_register_(stack_pointer_reg),
589 current_position_register_(position_reg),
590 clear_capture_count_(clear_capture_count),
591 clear_capture_start_(clear_capture_start) {}
592 void Emit(RegExpCompiler* compiler, Trace* trace) override;
593
594 private:
599};
600
601class Guard : public ZoneObject {
602 public:
603 enum Relation { LT, GEQ };
604 Guard(int reg, Relation op, int value) : reg_(reg), op_(op), value_(value) {}
605 int reg() { return reg_; }
606 Relation op() { return op_; }
607 int value() { return value_; }
608
609 private:
610 int reg_;
613};
614
616 public:
618 : node_(node), guards_(nullptr) {}
619 void AddGuard(Guard* guard, Zone* zone);
620 RegExpNode* node() { return node_; }
621 void set_node(RegExpNode* node) { node_ = node; }
623
624 private:
627};
628
630
631class ChoiceNode : public RegExpNode {
632 public:
633 explicit ChoiceNode(int expected_size, Zone* zone)
634 : RegExpNode(zone),
636 zone->New<ZoneList<GuardedAlternative>>(expected_size, zone)),
637 not_at_start_(false),
638 being_calculated_(false) {}
639 ChoiceNode* AsChoiceNode() override { return this; }
640 void Accept(NodeVisitor* visitor) override;
642 alternatives()->Add(node, zone());
643 }
645 void Emit(RegExpCompiler* compiler, Trace* trace) override;
647 RegExpCompiler* compiler, int characters_filled_in,
648 bool not_at_start) override;
649 void FillInBMInfo(Isolate* isolate, int offset, int budget,
650 BoyerMooreLookahead* bm, bool not_at_start) override;
651
653 bool not_at_start() { return not_at_start_; }
656 virtual bool try_to_emit_quick_check_for_alternative(bool is_first) {
657 return true;
658 }
659 RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) override;
660 virtual bool read_backward() { return false; }
661
662 protected:
665
666 private:
667 template <typename...>
668 friend class Analysis;
669
670 void GenerateGuard(RegExpMacroAssembler* macro_assembler, Guard* guard,
671 Trace* trace);
672 int CalculatePreloadCharacters(RegExpCompiler* compiler, int eats_at_least);
673 void EmitOutOfLineContinuation(RegExpCompiler* compiler, Trace* trace,
674 GuardedAlternative alternative,
675 AlternativeGeneration* alt_gen,
676 int preload_characters,
677 bool next_expects_preload);
678 void SetUpPreLoad(RegExpCompiler* compiler, Trace* current_trace,
679 PreloadState* preloads);
682 Trace* EmitGreedyLoop(RegExpCompiler* compiler, Trace* trace,
684 PreloadState* preloads,
685 GreedyLoopState* greedy_loop_state, int text_length);
686 void EmitChoices(RegExpCompiler* compiler,
687 AlternativeGenerationList* alt_gens, int first_choice,
688 Trace* trace, PreloadState* preloads);
689
690 // If true, this node is never checked at the start of the input.
691 // Allows a new trace to start with at_start() set to false.
694};
695
697 public:
699 GuardedAlternative then_do_this,
700 Zone* zone)
701 : ChoiceNode(2, zone) {
702 AddAlternative(this_must_fail);
703 AddAlternative(then_do_this);
704 }
705 void GetQuickCheckDetails(QuickCheckDetails* details,
706 RegExpCompiler* compiler, int characters_filled_in,
707 bool not_at_start) override;
708 void FillInBMInfo(Isolate* isolate, int offset, int budget,
709 BoyerMooreLookahead* bm, bool not_at_start) override {
710 continue_node()->FillInBMInfo(isolate, offset, budget - 1, bm,
711 not_at_start);
712 if (offset == 0) set_bm_info(not_at_start, bm);
713 }
714 static constexpr int kLookaroundIndex = 0;
715 static constexpr int kContinueIndex = 1;
717 return alternatives()->at(kLookaroundIndex).node();
718 }
720 return alternatives()->at(kContinueIndex).node();
721 }
722 // For a negative lookahead we don't emit the quick check for the
723 // alternative that is expected to fail. This is because quick check code
724 // starts by loading enough characters for the alternative that takes fewest
725 // characters, but on a negative lookahead the negative branch did not take
726 // part in that calculation (EatsAtLeast) so the assumptions don't hold.
727 bool try_to_emit_quick_check_for_alternative(bool is_first) override {
728 return !is_first;
729 }
733 void Accept(NodeVisitor* visitor) override;
734 RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) override;
735};
736
738 public:
739 LoopChoiceNode(bool body_can_be_zero_length, bool read_backward,
740 int min_loop_iterations, Zone* zone)
741 : ChoiceNode(2, zone),
742 loop_node_(nullptr),
743 continue_node_(nullptr),
744 body_can_be_zero_length_(body_can_be_zero_length),
745 read_backward_(read_backward),
746 traversed_loop_initialization_node_(false),
747 min_loop_iterations_(min_loop_iterations) {}
748 void AddLoopAlternative(GuardedAlternative alt);
749 void AddContinueAlternative(GuardedAlternative alt);
750 void Emit(RegExpCompiler* compiler, Trace* trace) override;
751 void GetQuickCheckDetails(QuickCheckDetails* details,
752 RegExpCompiler* compiler, int characters_filled_in,
753 bool not_at_start) override;
754 void GetQuickCheckDetailsFromLoopEntry(QuickCheckDetails* details,
755 RegExpCompiler* compiler,
756 int characters_filled_in,
757 bool not_at_start) override;
758 void FillInBMInfo(Isolate* isolate, int offset, int budget,
759 BoyerMooreLookahead* bm, bool not_at_start) override;
760 EatsAtLeastInfo EatsAtLeastFromLoopEntry() override;
761 RegExpNode* loop_node() { return loop_node_; }
762 RegExpNode* continue_node() { return continue_node_; }
763 bool body_can_be_zero_length() { return body_can_be_zero_length_; }
764 int min_loop_iterations() const { return min_loop_iterations_; }
765 bool read_backward() override { return read_backward_; }
766 LoopChoiceNode* AsLoopChoiceNode() override { return this; }
767 void Accept(NodeVisitor* visitor) override;
768 RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) override;
769
770 private:
771 // AddAlternative is made private for loop nodes because alternatives
772 // should not be added freely, we need to keep track of which node
773 // goes back to the node itself.
777
782
783 // Temporary marker set only while generating quick check details. Represents
784 // whether GetQuickCheckDetails traversed the initialization node for this
785 // loop's counter. If so, we may be able to generate stricter quick checks
786 // because we know the loop node must match at least min_loop_iterations_
787 // times before the continuation node can match.
789
790 // The minimum number of times the loop_node_ must match before the
791 // continue_node_ might be considered. This value can be temporarily decreased
792 // while generating quick check details, to represent the remaining iterations
793 // after the completed portion of the quick check details.
795
798};
799
801 public:
802 virtual ~NodeVisitor() = default;
803#define DECLARE_VISIT(Type) virtual void Visit##Type(Type##Node* that) = 0;
805#undef DECLARE_VISIT
806};
807
808} // namespace internal
809} // namespace v8
810
811#endif // V8_REGEXP_REGEXP_NODES_H_
#define DECLARE_CAST(CamelName)
Definition asm-types.h:111
#define DECLARE_VISIT(type)
#define FORWARD_DECLARE(Name, Argc)
Definition builtins.cc:30
ActionNode * AsActionNode() override
static ActionNode * EmptyMatchCheck(int start_register, int repetition_register, int repetition_limit, RegExpNode *on_success)
static ActionNode * ModifyFlags(RegExpFlags flags, RegExpNode *on_success)
struct v8::internal::ActionNode::@137::@143 u_clear_captures
RegExpFlags flags() const
ActionNode(ActionType action_type, RegExpNode *on_success)
ActionType action_type() const
void Accept(NodeVisitor *visitor) override
static ActionNode * StorePosition(int reg, bool is_capture, RegExpNode *on_success)
int GreedyLoopTextLength() override
ActionNode * success_node() const
static ActionNode * PositiveSubmatchSuccess(int stack_pointer_reg, int restore_reg, int clear_capture_count, int clear_capture_from, RegExpNode *on_success)
union v8::internal::ActionNode::@137 data_
static ActionNode * BeginNegativeSubmatch(int stack_pointer_reg, int position_reg, RegExpNode *on_success)
static ActionNode * SetRegisterForLoop(int reg, int val, RegExpNode *on_success)
struct v8::internal::ActionNode::@137::@140 u_position_register
void FillInBMInfo(Isolate *isolate, int offset, int budget, BoyerMooreLookahead *bm, bool not_at_start) override
struct v8::internal::ActionNode::@137::@144 u_modify_flags
static ActionNode * IncrementRegister(int reg, RegExpNode *on_success)
struct v8::internal::ActionNode::@137::@138 u_store_register
void Emit(RegExpCompiler *compiler, Trace *trace) override
struct v8::internal::ActionNode::@137::@139 u_increment_register
void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int filled_in, bool not_at_start) override
static ActionNode * BeginPositiveSubmatch(int stack_pointer_reg, int position_reg, RegExpNode *body, ActionNode *success_node)
struct v8::internal::ActionNode::@137::@141 u_submatch
struct v8::internal::ActionNode::@137::@142 u_empty_match_check
static ActionNode * ClearCaptures(Interval range, RegExpNode *on_success)
AssertionNode * AsAssertionNode() override
AssertionNode(AssertionType t, RegExpNode *on_success)
AssertionType assertion_type()
void EmitBoundaryCheck(RegExpCompiler *compiler, Trace *trace)
static AssertionNode * AtStart(RegExpNode *on_success)
static AssertionNode * AtBoundary(RegExpNode *on_success)
static AssertionNode * AtEnd(RegExpNode *on_success)
void Accept(NodeVisitor *visitor) override
static AssertionNode * AtNonBoundary(RegExpNode *on_success)
void FillInBMInfo(Isolate *isolate, int offset, int budget, BoyerMooreLookahead *bm, bool not_at_start) override
void BacktrackIfPrevious(RegExpCompiler *compiler, Trace *trace, IfPrevious backtrack_if_previous)
void Emit(RegExpCompiler *compiler, Trace *trace) override
void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int filled_in, bool not_at_start) override
static AssertionNode * AfterNewline(RegExpNode *on_success)
void FillInBMInfo(Isolate *isolate, int offset, int budget, BoyerMooreLookahead *bm, bool not_at_start) override
void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start) override
void Accept(NodeVisitor *visitor) override
void Emit(RegExpCompiler *compiler, Trace *trace) override
BackReferenceNode * AsBackReferenceNode() override
BackReferenceNode(int start_reg, int end_reg, bool read_backward, RegExpNode *on_success)
ChoiceNode(int expected_size, Zone *zone)
int EmitOptimizedUnanchoredSearch(RegExpCompiler *compiler, Trace *trace)
ZoneList< GuardedAlternative > * alternatives_
ChoiceNode * AsChoiceNode() override
void AddAlternative(GuardedAlternative node)
int GreedyLoopTextLengthForAlternative(GuardedAlternative *alternative)
ZoneList< GuardedAlternative > * alternatives()
int CalculatePreloadCharacters(RegExpCompiler *compiler, int eats_at_least)
Trace * EmitGreedyLoop(RegExpCompiler *compiler, Trace *trace, AlternativeGenerationList *alt_gens, PreloadState *preloads, GreedyLoopState *greedy_loop_state, int text_length)
void set_being_calculated(bool b)
void FillInBMInfo(Isolate *isolate, int offset, int budget, BoyerMooreLookahead *bm, bool not_at_start) override
void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start) override
virtual bool read_backward()
virtual bool try_to_emit_quick_check_for_alternative(bool is_first)
void EmitChoices(RegExpCompiler *compiler, AlternativeGenerationList *alt_gens, int first_choice, Trace *trace, PreloadState *preloads)
void Accept(NodeVisitor *visitor) override
RegExpNode * FilterOneByte(int depth, RegExpCompiler *compiler) override
void EmitOutOfLineContinuation(RegExpCompiler *compiler, Trace *trace, GuardedAlternative alternative, AlternativeGeneration *alt_gen, int preload_characters, bool next_expects_preload)
void SetUpPreLoad(RegExpCompiler *compiler, Trace *current_trace, PreloadState *preloads)
void AssertGuardsMentionRegisters(Trace *trace)
void GenerateGuard(RegExpMacroAssembler *macro_assembler, Guard *guard, Trace *trace)
void Emit(RegExpCompiler *compiler, Trace *trace) override
EndNode * AsEndNode() override
void Accept(NodeVisitor *visitor) override
void FillInBMInfo(Isolate *isolate, int offset, int budget, BoyerMooreLookahead *bm, bool not_at_start) override
void Emit(RegExpCompiler *compiler, Trace *trace) override
EndNode(Action action, Zone *zone)
void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start) override
Guard(int reg, Relation op, int value)
void AddGuard(Guard *guard, Zone *zone)
void set_node(RegExpNode *node)
GuardedAlternative(RegExpNode *node)
ZoneList< Guard * > * guards_
ZoneList< Guard * > * guards()
friend class LoopInitializationMarker
LoopChoiceNode * AsLoopChoiceNode() override
LoopChoiceNode(bool body_can_be_zero_length, bool read_backward, int min_loop_iterations, Zone *zone)
void AddAlternative(GuardedAlternative node)
void Accept(NodeVisitor *visitor) override
bool try_to_emit_quick_check_for_alternative(bool is_first) override
void Accept(NodeVisitor *visitor) override
void FillInBMInfo(Isolate *isolate, int offset, int budget, BoyerMooreLookahead *bm, bool not_at_start) override
NegativeLookaroundChoiceNode * AsNegativeLookaroundChoiceNode() override
NegativeLookaroundChoiceNode(GuardedAlternative this_must_fail, GuardedAlternative then_do_this, Zone *zone)
void Emit(RegExpCompiler *compiler, Trace *trace) override
NegativeSubmatchSuccess(int stack_pointer_reg, int position_reg, int clear_capture_count, int clear_capture_start, Zone *zone)
virtual ~NodeVisitor()=default
void set_bm_info(bool not_at_start, BoyerMooreLookahead *bm)
virtual EatsAtLeastInfo EatsAtLeastFromLoopEntry()
virtual void FillInBMInfo(Isolate *isolate, int offset, int budget, BoyerMooreLookahead *bm, bool not_at_start)
virtual RegExpNode * GetSuccessorOfOmnivorousTextNode(RegExpCompiler *compiler)
BoyerMooreLookahead * bm_info(bool not_at_start)
BoyerMooreLookahead * bm_info_[2]
bool KeepRecursing(RegExpCompiler *compiler)
const EatsAtLeastInfo * eats_at_least_info() const
LimitResult LimitVersions(RegExpCompiler *compiler, Trace *trace)
void SaveBMInfo(BoyerMooreLookahead *bm, bool not_at_start, int offset)
uint32_t EatsAtLeast(bool not_at_start)
bool EmitQuickCheck(RegExpCompiler *compiler, Trace *bounds_check_trace, Trace *trace, bool preload_has_checked_bounds, Label *on_possible_success, QuickCheckDetails *details_return, bool fall_through_on_failure, ChoiceNode *predecessor)
void set_eats_at_least_info(const EatsAtLeastInfo &eats_at_least)
virtual SeqRegExpNode * AsSeqRegExpNode()
virtual int GreedyLoopTextLength()
EatsAtLeastInfo eats_at_least_
virtual RegExpNode * FilterOneByte(int depth, RegExpCompiler *compiler)
virtual void GetQuickCheckDetailsFromLoopEntry(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start)
virtual void Emit(RegExpCompiler *compiler, Trace *trace)=0
virtual void Accept(NodeVisitor *visitor)=0
static const int kRecursionBudget
static const int kNodeIsTooComplexForGreedyLoops
virtual void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start)=0
static const int kMaxCopiesCodeGenerated
void set_on_work_list(bool value)
static const int kFirstCharBudget
RegExpNode * set_replacement(RegExpNode *replacement)
RegExpNode * replacement()
RegExpNode * FilterSuccessor(int depth, RegExpCompiler *compiler)
void FillInBMInfo(Isolate *isolate, int offset, int budget, BoyerMooreLookahead *bm, bool not_at_start) override
void set_on_success(RegExpNode *node)
SeqRegExpNode(RegExpNode *on_success)
RegExpNode * FilterOneByte(int depth, RegExpCompiler *compiler) override
SeqRegExpNode * AsSeqRegExpNode() override
static TextElement ClassRanges(RegExpClassRanges *class_ranges)
void Accept(NodeVisitor *visitor) override
static TextNode * CreateForSurrogatePair(Zone *zone, CharacterRange lead, ZoneList< CharacterRange > *trail_ranges, bool read_backward, RegExpNode *on_success)
static TextNode * CreateForCharacterRanges(Zone *zone, ZoneList< CharacterRange > *ranges, bool read_backward, RegExpNode *on_success)
RegExpNode * GetSuccessorOfOmnivorousTextNode(RegExpCompiler *compiler) override
ZoneList< TextElement > * elements()
void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start) override
int GreedyLoopTextLength() override
ZoneList< TextElement > * elms_
TextNode(RegExpClassRanges *that, bool read_backward, RegExpNode *on_success)
RegExpNode * FilterOneByte(int depth, RegExpCompiler *compiler) override
void Emit(RegExpCompiler *compiler, Trace *trace) override
void TextEmitPass(RegExpCompiler *compiler, TextEmitPassType pass, bool preloaded, Trace *trace, bool first_element_checked, int *checked_up_to)
TextNode * AsTextNode() override
void FillInBMInfo(Isolate *isolate, int offset, int budget, BoyerMooreLookahead *bm, bool not_at_start) override
TextNode(ZoneList< TextElement > *elms, bool read_backward, RegExpNode *on_success)
void MakeCaseIndependent(Isolate *isolate, bool is_one_byte, RegExpFlags flags)
T * New(Args &&... args)
Definition zone.h:114
int32_t offset
Node * node
constexpr int kMinInt
Definition globals.h:375
return value
Definition map-inl.h:893
#define FOR_EACH_NODE_TYPE(VISIT)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
void SetMin(const EatsAtLeastInfo &other)
void AddFromFollowing(NodeInfo *that)
void AddFromPreceding(NodeInfo *that)
bool Matches(NodeInfo *that)