summaryrefslogtreecommitdiff
path: root/js/src/new-regexp/regexp-nodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/new-regexp/regexp-nodes.h')
-rw-r--r--js/src/new-regexp/regexp-nodes.h750
1 files changed, 0 insertions, 750 deletions
diff --git a/js/src/new-regexp/regexp-nodes.h b/js/src/new-regexp/regexp-nodes.h
deleted file mode 100644
index 099687c25..000000000
--- a/js/src/new-regexp/regexp-nodes.h
+++ /dev/null
@@ -1,750 +0,0 @@
-// Copyright 2019 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_REGEXP_REGEXP_NODES_H_
-#define V8_REGEXP_REGEXP_NODES_H_
-
-#include "new-regexp/regexp-macro-assembler.h"
-
-namespace v8 {
-namespace internal {
-
-class AlternativeGenerationList;
-class BoyerMooreLookahead;
-class GreedyLoopState;
-class Label;
-class NodeVisitor;
-class QuickCheckDetails;
-class RegExpCompiler;
-class Trace;
-struct PreloadState;
-class ChoiceNode;
-
-#define FOR_EACH_NODE_TYPE(VISIT) \
- VISIT(End) \
- VISIT(Action) \
- VISIT(Choice) \
- VISIT(LoopChoice) \
- VISIT(NegativeLookaroundChoice) \
- VISIT(BackReference) \
- VISIT(Assertion) \
- VISIT(Text)
-
-struct NodeInfo final {
- NodeInfo()
- : being_analyzed(false),
- been_analyzed(false),
- follows_word_interest(false),
- follows_newline_interest(false),
- follows_start_interest(false),
- at_end(false),
- visited(false),
- replacement_calculated(false) {}
-
- // Returns true if the interests and assumptions of this node
- // matches the given one.
- bool Matches(NodeInfo* that) {
- return (at_end == that->at_end) &&
- (follows_word_interest == that->follows_word_interest) &&
- (follows_newline_interest == that->follows_newline_interest) &&
- (follows_start_interest == that->follows_start_interest);
- }
-
- // Updates the interests of this node given the interests of the
- // node preceding it.
- void AddFromPreceding(NodeInfo* that) {
- at_end |= that->at_end;
- follows_word_interest |= that->follows_word_interest;
- follows_newline_interest |= that->follows_newline_interest;
- follows_start_interest |= that->follows_start_interest;
- }
-
- bool HasLookbehind() {
- return follows_word_interest || follows_newline_interest ||
- follows_start_interest;
- }
-
- // Sets the interests of this node to include the interests of the
- // following node.
- void AddFromFollowing(NodeInfo* that) {
- follows_word_interest |= that->follows_word_interest;
- follows_newline_interest |= that->follows_newline_interest;
- follows_start_interest |= that->follows_start_interest;
- }
-
- void ResetCompilationState() {
- being_analyzed = false;
- been_analyzed = false;
- }
-
- bool being_analyzed : 1;
- bool been_analyzed : 1;
-
- // These bits are set of this node has to know what the preceding
- // character was.
- bool follows_word_interest : 1;
- bool follows_newline_interest : 1;
- bool follows_start_interest : 1;
-
- bool at_end : 1;
- bool visited : 1;
- bool replacement_calculated : 1;
-};
-
-struct EatsAtLeastInfo final {
- EatsAtLeastInfo() : EatsAtLeastInfo(0) {}
- explicit EatsAtLeastInfo(uint8_t eats)
- : eats_at_least_from_possibly_start(eats),
- eats_at_least_from_not_start(eats) {}
- void SetMin(const EatsAtLeastInfo& other) {
- if (other.eats_at_least_from_possibly_start <
- eats_at_least_from_possibly_start) {
- eats_at_least_from_possibly_start =
- other.eats_at_least_from_possibly_start;
- }
- if (other.eats_at_least_from_not_start < eats_at_least_from_not_start) {
- eats_at_least_from_not_start = other.eats_at_least_from_not_start;
- }
- }
-
- // Any successful match starting from the current node will consume at least
- // this many characters. This does not necessarily mean that there is a
- // possible match with exactly this many characters, but we generally try to
- // get this number as high as possible to allow for early exit on failure.
- uint8_t eats_at_least_from_possibly_start;
-
- // Like eats_at_least_from_possibly_start, but with the additional assumption
- // that start-of-string assertions (^) can't match. This value is greater than
- // or equal to eats_at_least_from_possibly_start.
- uint8_t eats_at_least_from_not_start;
-};
-
-class RegExpNode : public ZoneObject {
- public:
- explicit RegExpNode(Zone* zone)
- : replacement_(nullptr),
- on_work_list_(false),
- trace_count_(0),
- zone_(zone) {
- bm_info_[0] = bm_info_[1] = nullptr;
- }
- virtual ~RegExpNode();
- virtual void Accept(NodeVisitor* visitor) = 0;
- // Generates a goto to this node or actually generates the code at this point.
- virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0;
- // How many characters must this node consume at a minimum in order to
- // succeed. The not_at_start argument is used to indicate that we know we are
- // not at the start of the input. In this case anchored branches will always
- // fail and can be ignored when determining how many characters are consumed
- // on success. If this node has not been analyzed yet, EatsAtLeast returns 0.
- int EatsAtLeast(bool not_at_start);
- // Returns how many characters this node must consume in order to succeed,
- // given that this is a LoopChoiceNode whose counter register is in a
- // newly-initialized state at the current position in the generated code. For
- // example, consider /a{6,8}/. Absent any extra information, the
- // LoopChoiceNode for the repetition must report that it consumes at least
- // zero characters, because it may have already looped several times. However,
- // with a newly-initialized counter, it can report that it consumes at least
- // six characters.
- virtual EatsAtLeastInfo EatsAtLeastFromLoopEntry();
- // Emits some quick code that checks whether the preloaded characters match.
- // Falls through on certain failure, jumps to the label on possible success.
- // If the node cannot make a quick check it does nothing and returns false.
- 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);
- // For a given number of characters this returns a mask and a value. The
- // next n characters are anded with the mask and compared with the value.
- // A comparison failure indicates the node cannot match the next n characters.
- // A comparison success indicates the node may match.
- virtual void GetQuickCheckDetails(QuickCheckDetails* details,
- RegExpCompiler* compiler,
- int characters_filled_in,
- bool not_at_start) = 0;
- // Fills in quick check details for this node, given that this is a
- // LoopChoiceNode whose counter register is in a newly-initialized state at
- // the current position in the generated code. For example, consider /a{6,8}/.
- // Absent any extra information, the LoopChoiceNode for the repetition cannot
- // generate any useful quick check because a match might be the (empty)
- // continuation node. However, with a newly-initialized counter, it can
- // generate a quick check for several 'a' characters at once.
- virtual void GetQuickCheckDetailsFromLoopEntry(QuickCheckDetails* details,
- RegExpCompiler* compiler,
- int characters_filled_in,
- bool not_at_start);
- static const int kNodeIsTooComplexForGreedyLoops = kMinInt;
- virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
- // Only returns the successor for a text node of length 1 that matches any
- // character and that has no guards on it.
- virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
- RegExpCompiler* compiler) {
- return nullptr;
- }
-
- // Collects information on the possible code units (mod 128) that can match if
- // we look forward. This is used for a Boyer-Moore-like string searching
- // implementation. TODO(erikcorry): This should share more code with
- // EatsAtLeast, GetQuickCheckDetails. The budget argument is used to limit
- // the number of nodes we are willing to look at in order to create this data.
- static const int kRecursionBudget = 200;
- bool KeepRecursing(RegExpCompiler* compiler);
- virtual void FillInBMInfo(Isolate* isolate, int offset, int budget,
- BoyerMooreLookahead* bm, bool not_at_start) {
- UNREACHABLE();
- }
-
- // If we know that the input is one-byte then there are some nodes that can
- // never match. This method returns a node that can be substituted for
- // itself, or nullptr if the node can never match.
- virtual RegExpNode* FilterOneByte(int depth) { return this; }
- // Helper for FilterOneByte.
- RegExpNode* replacement() {
- DCHECK(info()->replacement_calculated);
- return replacement_;
- }
- RegExpNode* set_replacement(RegExpNode* replacement) {
- info()->replacement_calculated = true;
- replacement_ = replacement;
- return replacement; // For convenience.
- }
-
- // We want to avoid recalculating the lookahead info, so we store it on the
- // node. Only info that is for this node is stored. We can tell that the
- // info is for this node when offset == 0, so the information is calculated
- // relative to this node.
- void SaveBMInfo(BoyerMooreLookahead* bm, bool not_at_start, int offset) {
- if (offset == 0) set_bm_info(not_at_start, bm);
- }
-
- Label* label() { return &label_; }
- // If non-generic code is generated for a node (i.e. the node is not at the
- // start of the trace) then it cannot be reused. This variable sets a limit
- // on how often we allow that to happen before we insist on starting a new
- // trace and generating generic code for a node that can be reused by flushing
- // the deferred actions in the current trace and generating a goto.
- static const int kMaxCopiesCodeGenerated = 10;
-
- bool on_work_list() { return on_work_list_; }
- void set_on_work_list(bool value) { on_work_list_ = value; }
-
- NodeInfo* info() { return &info_; }
- const EatsAtLeastInfo* eats_at_least_info() const { return &eats_at_least_; }
- void set_eats_at_least_info(const EatsAtLeastInfo& eats_at_least) {
- eats_at_least_ = eats_at_least;
- }
-
- BoyerMooreLookahead* bm_info(bool not_at_start) {
- return bm_info_[not_at_start ? 1 : 0];
- }
-
- Zone* zone() const { return zone_; }
-
- protected:
- enum LimitResult { DONE, CONTINUE };
- RegExpNode* replacement_;
-
- LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);
-
- void set_bm_info(bool not_at_start, BoyerMooreLookahead* bm) {
- bm_info_[not_at_start ? 1 : 0] = bm;
- }
-
- private:
- static const int kFirstCharBudget = 10;
- Label label_;
- bool on_work_list_;
- NodeInfo info_;
-
- // Saved values for EatsAtLeast results, to avoid recomputation. Filled in
- // during analysis (valid if info_.been_analyzed is true).
- EatsAtLeastInfo eats_at_least_;
-
- // This variable keeps track of how many times code has been generated for
- // this node (in different traces). We don't keep track of where the
- // generated code is located unless the code is generated at the start of
- // a trace, in which case it is generic and can be reused by flushing the
- // deferred operations in the current trace and generating a goto.
- int trace_count_;
- BoyerMooreLookahead* bm_info_[2];
-
- Zone* zone_;
-};
-
-class SeqRegExpNode : public RegExpNode {
- public:
- explicit SeqRegExpNode(RegExpNode* on_success)
- : RegExpNode(on_success->zone()), on_success_(on_success) {}
- RegExpNode* on_success() { return on_success_; }
- void set_on_success(RegExpNode* node) { on_success_ = node; }
- RegExpNode* FilterOneByte(int depth) override;
- void FillInBMInfo(Isolate* isolate, int offset, int budget,
- BoyerMooreLookahead* bm, bool not_at_start) override {
- on_success_->FillInBMInfo(isolate, offset, budget - 1, bm, not_at_start);
- if (offset == 0) set_bm_info(not_at_start, bm);
- }
-
- protected:
- RegExpNode* FilterSuccessor(int depth);
-
- private:
- RegExpNode* on_success_;
-};
-
-class ActionNode : public SeqRegExpNode {
- public:
- enum ActionType {
- SET_REGISTER_FOR_LOOP,
- INCREMENT_REGISTER,
- STORE_POSITION,
- BEGIN_SUBMATCH,
- POSITIVE_SUBMATCH_SUCCESS,
- EMPTY_MATCH_CHECK,
- CLEAR_CAPTURES
- };
- static ActionNode* SetRegisterForLoop(int reg, int val,
- RegExpNode* on_success);
- static ActionNode* IncrementRegister(int reg, RegExpNode* on_success);
- static ActionNode* StorePosition(int reg, bool is_capture,
- RegExpNode* on_success);
- static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success);
- static ActionNode* BeginSubmatch(int stack_pointer_reg, int position_reg,
- RegExpNode* on_success);
- static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg,
- int restore_reg,
- int clear_capture_count,
- int clear_capture_from,
- RegExpNode* on_success);
- static ActionNode* EmptyMatchCheck(int start_register,
- int repetition_register,
- int repetition_limit,
- RegExpNode* on_success);
- void Accept(NodeVisitor* visitor) override;
- void Emit(RegExpCompiler* compiler, Trace* trace) override;
- void GetQuickCheckDetails(QuickCheckDetails* details,
- RegExpCompiler* compiler, int filled_in,
- bool not_at_start) override;
- void FillInBMInfo(Isolate* isolate, int offset, int budget,
- BoyerMooreLookahead* bm, bool not_at_start) override;
- ActionType action_type() { return action_type_; }
- // TODO(erikcorry): We should allow some action nodes in greedy loops.
- int GreedyLoopTextLength() override {
- return kNodeIsTooComplexForGreedyLoops;
- }
-
- private:
- union {
- struct {
- int reg;
- int value;
- } u_store_register;
- struct {
- int reg;
- } u_increment_register;
- struct {
- int reg;
- bool is_capture;
- } u_position_register;
- struct {
- int stack_pointer_register;
- int current_position_register;
- int clear_register_count;
- int clear_register_from;
- } u_submatch;
- struct {
- int start_register;
- int repetition_register;
- int repetition_limit;
- } u_empty_match_check;
- struct {
- int range_from;
- int range_to;
- } u_clear_captures;
- } data_;
- ActionNode(ActionType action_type, RegExpNode* on_success)
- : SeqRegExpNode(on_success), action_type_(action_type) {}
- ActionType action_type_;
- friend class DotPrinterImpl;
-};
-
-class TextNode : public SeqRegExpNode {
- public:
- TextNode(ZoneList<TextElement>* elms, bool read_backward,
- RegExpNode* on_success)
- : SeqRegExpNode(on_success), elms_(elms), read_backward_(read_backward) {}
- TextNode(RegExpCharacterClass* that, bool read_backward,
- RegExpNode* on_success)
- : SeqRegExpNode(on_success),
- elms_(new (zone()) ZoneList<TextElement>(1, zone())),
- read_backward_(read_backward) {
- elms_->Add(TextElement::CharClass(that), zone());
- }
- // Create TextNode for a single character class for the given ranges.
- static TextNode* CreateForCharacterRanges(Zone* zone,
- ZoneList<CharacterRange>* ranges,
- bool read_backward,
- RegExpNode* on_success,
- JSRegExp::Flags flags);
- // Create TextNode for a surrogate pair with a range given for the
- // lead and the trail surrogate each.
- static TextNode* CreateForSurrogatePair(Zone* zone, CharacterRange lead,
- CharacterRange trail,
- bool read_backward,
- RegExpNode* on_success,
- JSRegExp::Flags flags);
- void Accept(NodeVisitor* visitor) override;
- void Emit(RegExpCompiler* compiler, Trace* trace) override;
- void GetQuickCheckDetails(QuickCheckDetails* details,
- RegExpCompiler* compiler, int characters_filled_in,
- bool not_at_start) override;
- ZoneList<TextElement>* elements() { return elms_; }
- bool read_backward() { return read_backward_; }
- void MakeCaseIndependent(Isolate* isolate, bool is_one_byte);
- int GreedyLoopTextLength() override;
- RegExpNode* GetSuccessorOfOmnivorousTextNode(
- RegExpCompiler* compiler) override;
- void FillInBMInfo(Isolate* isolate, int offset, int budget,
- BoyerMooreLookahead* bm, bool not_at_start) override;
- void CalculateOffsets();
- RegExpNode* FilterOneByte(int depth) override;
- int Length();
-
- private:
- enum TextEmitPassType {
- NON_LATIN1_MATCH, // Check for characters that can't match.
- SIMPLE_CHARACTER_MATCH, // Case-dependent single character check.
- NON_LETTER_CHARACTER_MATCH, // Check characters that have no case equivs.
- CASE_CHARACTER_MATCH, // Case-independent single character check.
- CHARACTER_CLASS_MATCH // Character class.
- };
- static bool SkipPass(TextEmitPassType pass, bool ignore_case);
- static const int kFirstRealPass = SIMPLE_CHARACTER_MATCH;
- static const int kLastPass = CHARACTER_CLASS_MATCH;
- void TextEmitPass(RegExpCompiler* compiler, TextEmitPassType pass,
- bool preloaded, Trace* trace, bool first_element_checked,
- int* checked_up_to);
- ZoneList<TextElement>* elms_;
- bool read_backward_;
-};
-
-class AssertionNode : public SeqRegExpNode {
- public:
- enum AssertionType {
- AT_END,
- AT_START,
- AT_BOUNDARY,
- AT_NON_BOUNDARY,
- AFTER_NEWLINE
- };
- static AssertionNode* AtEnd(RegExpNode* on_success) {
- return new (on_success->zone()) AssertionNode(AT_END, on_success);
- }
- static AssertionNode* AtStart(RegExpNode* on_success) {
- return new (on_success->zone()) AssertionNode(AT_START, on_success);
- }
- static AssertionNode* AtBoundary(RegExpNode* on_success) {
- return new (on_success->zone()) AssertionNode(AT_BOUNDARY, on_success);
- }
- static AssertionNode* AtNonBoundary(RegExpNode* on_success) {
- return new (on_success->zone()) AssertionNode(AT_NON_BOUNDARY, on_success);
- }
- static AssertionNode* AfterNewline(RegExpNode* on_success) {
- return new (on_success->zone()) AssertionNode(AFTER_NEWLINE, on_success);
- }
- void Accept(NodeVisitor* visitor) override;
- void Emit(RegExpCompiler* compiler, Trace* trace) override;
- void GetQuickCheckDetails(QuickCheckDetails* details,
- RegExpCompiler* compiler, int filled_in,
- bool not_at_start) override;
- void FillInBMInfo(Isolate* isolate, int offset, int budget,
- BoyerMooreLookahead* bm, bool not_at_start) override;
- AssertionType assertion_type() { return assertion_type_; }
-
- private:
- void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace);
- enum IfPrevious { kIsNonWord, kIsWord };
- void BacktrackIfPrevious(RegExpCompiler* compiler, Trace* trace,
- IfPrevious backtrack_if_previous);
- AssertionNode(AssertionType t, RegExpNode* on_success)
- : SeqRegExpNode(on_success), assertion_type_(t) {}
- AssertionType assertion_type_;
-};
-
-class BackReferenceNode : public SeqRegExpNode {
- public:
- BackReferenceNode(int start_reg, int end_reg, JSRegExp::Flags flags,
- bool read_backward, RegExpNode* on_success)
- : SeqRegExpNode(on_success),
- start_reg_(start_reg),
- end_reg_(end_reg),
- flags_(flags),
- read_backward_(read_backward) {}
- void Accept(NodeVisitor* visitor) override;
- int start_register() { return start_reg_; }
- int end_register() { return end_reg_; }
- bool read_backward() { return read_backward_; }
- void Emit(RegExpCompiler* compiler, Trace* trace) override;
- void GetQuickCheckDetails(QuickCheckDetails* details,
- RegExpCompiler* compiler, int characters_filled_in,
- bool not_at_start) override {
- return;
- }
- void FillInBMInfo(Isolate* isolate, int offset, int budget,
- BoyerMooreLookahead* bm, bool not_at_start) override;
-
- private:
- int start_reg_;
- int end_reg_;
- JSRegExp::Flags flags_;
- bool read_backward_;
-};
-
-class EndNode : public RegExpNode {
- public:
- enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
- EndNode(Action action, Zone* zone) : RegExpNode(zone), action_(action) {}
- void Accept(NodeVisitor* visitor) override;
- void Emit(RegExpCompiler* compiler, Trace* trace) override;
- void GetQuickCheckDetails(QuickCheckDetails* details,
- RegExpCompiler* compiler, int characters_filled_in,
- bool not_at_start) override {
- // Returning 0 from EatsAtLeast should ensure we never get here.
- UNREACHABLE();
- }
- void FillInBMInfo(Isolate* isolate, int offset, int budget,
- BoyerMooreLookahead* bm, bool not_at_start) override {
- // Returning 0 from EatsAtLeast should ensure we never get here.
- UNREACHABLE();
- }
-
- private:
- Action action_;
-};
-
-class NegativeSubmatchSuccess : public EndNode {
- public:
- NegativeSubmatchSuccess(int stack_pointer_reg, int position_reg,
- int clear_capture_count, int clear_capture_start,
- Zone* zone)
- : EndNode(NEGATIVE_SUBMATCH_SUCCESS, zone),
- stack_pointer_register_(stack_pointer_reg),
- current_position_register_(position_reg),
- clear_capture_count_(clear_capture_count),
- clear_capture_start_(clear_capture_start) {}
- void Emit(RegExpCompiler* compiler, Trace* trace) override;
-
- private:
- int stack_pointer_register_;
- int current_position_register_;
- int clear_capture_count_;
- int clear_capture_start_;
-};
-
-class Guard : public ZoneObject {
- public:
- enum Relation { LT, GEQ };
- Guard(int reg, Relation op, int value) : reg_(reg), op_(op), value_(value) {}
- int reg() { return reg_; }
- Relation op() { return op_; }
- int value() { return value_; }
-
- private:
- int reg_;
- Relation op_;
- int value_;
-};
-
-class GuardedAlternative {
- public:
- explicit GuardedAlternative(RegExpNode* node)
- : node_(node), guards_(nullptr) {}
- void AddGuard(Guard* guard, Zone* zone);
- RegExpNode* node() { return node_; }
- void set_node(RegExpNode* node) { node_ = node; }
- ZoneList<Guard*>* guards() { return guards_; }
-
- private:
- RegExpNode* node_;
- ZoneList<Guard*>* guards_;
-};
-
-class AlternativeGeneration;
-
-class ChoiceNode : public RegExpNode {
- public:
- explicit ChoiceNode(int expected_size, Zone* zone)
- : RegExpNode(zone),
- alternatives_(new (zone)
- ZoneList<GuardedAlternative>(expected_size, zone)),
- not_at_start_(false),
- being_calculated_(false) {}
- void Accept(NodeVisitor* visitor) override;
- void AddAlternative(GuardedAlternative node) {
- alternatives()->Add(node, zone());
- }
- ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
- void Emit(RegExpCompiler* compiler, Trace* trace) override;
- void GetQuickCheckDetails(QuickCheckDetails* details,
- RegExpCompiler* compiler, int characters_filled_in,
- bool not_at_start) override;
- void FillInBMInfo(Isolate* isolate, int offset, int budget,
- BoyerMooreLookahead* bm, bool not_at_start) override;
-
- bool being_calculated() { return being_calculated_; }
- bool not_at_start() { return not_at_start_; }
- void set_not_at_start() { not_at_start_ = true; }
- void set_being_calculated(bool b) { being_calculated_ = b; }
- virtual bool try_to_emit_quick_check_for_alternative(bool is_first) {
- return true;
- }
- RegExpNode* FilterOneByte(int depth) override;
- virtual bool read_backward() { return false; }
-
- protected:
- int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative);
- ZoneList<GuardedAlternative>* alternatives_;
-
- private:
- template <typename...>
- friend class Analysis;
-
- void GenerateGuard(RegExpMacroAssembler* macro_assembler, Guard* guard,
- Trace* trace);
- int CalculatePreloadCharacters(RegExpCompiler* compiler, int eats_at_least);
- 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);
- int EmitOptimizedUnanchoredSearch(RegExpCompiler* compiler, Trace* trace);
- Trace* EmitGreedyLoop(RegExpCompiler* compiler, Trace* trace,
- AlternativeGenerationList* alt_gens,
- PreloadState* preloads,
- GreedyLoopState* greedy_loop_state, int text_length);
- void EmitChoices(RegExpCompiler* compiler,
- AlternativeGenerationList* alt_gens, int first_choice,
- Trace* trace, PreloadState* preloads);
-
- // If true, this node is never checked at the start of the input.
- // Allows a new trace to start with at_start() set to false.
- bool not_at_start_;
- bool being_calculated_;
-};
-
-class NegativeLookaroundChoiceNode : public ChoiceNode {
- public:
- explicit NegativeLookaroundChoiceNode(GuardedAlternative this_must_fail,
- GuardedAlternative then_do_this,
- Zone* zone)
- : ChoiceNode(2, zone) {
- AddAlternative(this_must_fail);
- AddAlternative(then_do_this);
- }
- void GetQuickCheckDetails(QuickCheckDetails* details,
- RegExpCompiler* compiler, int characters_filled_in,
- bool not_at_start) override;
- void FillInBMInfo(Isolate* isolate, int offset, int budget,
- BoyerMooreLookahead* bm, bool not_at_start) override {
- continue_node()->FillInBMInfo(isolate, offset, budget - 1, bm,
- not_at_start);
- if (offset == 0) set_bm_info(not_at_start, bm);
- }
- static constexpr int kLookaroundIndex = 0;
- static constexpr int kContinueIndex = 1;
- RegExpNode* lookaround_node() {
- return alternatives()->at(kLookaroundIndex).node();
- }
- RegExpNode* continue_node() {
- return alternatives()->at(kContinueIndex).node();
- }
- // For a negative lookahead we don't emit the quick check for the
- // alternative that is expected to fail. This is because quick check code
- // starts by loading enough characters for the alternative that takes fewest
- // characters, but on a negative lookahead the negative branch did not take
- // part in that calculation (EatsAtLeast) so the assumptions don't hold.
- bool try_to_emit_quick_check_for_alternative(bool is_first) override {
- return !is_first;
- }
- void Accept(NodeVisitor* visitor) override;
- RegExpNode* FilterOneByte(int depth) override;
-};
-
-class LoopChoiceNode : public ChoiceNode {
- public:
- LoopChoiceNode(bool body_can_be_zero_length, bool read_backward,
- int min_loop_iterations, Zone* zone)
- : ChoiceNode(2, zone),
- loop_node_(nullptr),
- continue_node_(nullptr),
- body_can_be_zero_length_(body_can_be_zero_length),
- read_backward_(read_backward),
- traversed_loop_initialization_node_(false),
- min_loop_iterations_(min_loop_iterations) {}
- void AddLoopAlternative(GuardedAlternative alt);
- void AddContinueAlternative(GuardedAlternative alt);
- void Emit(RegExpCompiler* compiler, Trace* trace) override;
- void GetQuickCheckDetails(QuickCheckDetails* details,
- RegExpCompiler* compiler, int characters_filled_in,
- bool not_at_start) override;
- void GetQuickCheckDetailsFromLoopEntry(QuickCheckDetails* details,
- RegExpCompiler* compiler,
- int characters_filled_in,
- bool not_at_start) override;
- void FillInBMInfo(Isolate* isolate, int offset, int budget,
- BoyerMooreLookahead* bm, bool not_at_start) override;
- EatsAtLeastInfo EatsAtLeastFromLoopEntry() override;
- RegExpNode* loop_node() { return loop_node_; }
- RegExpNode* continue_node() { return continue_node_; }
- bool body_can_be_zero_length() { return body_can_be_zero_length_; }
- int min_loop_iterations() const { return min_loop_iterations_; }
- bool read_backward() override { return read_backward_; }
- void Accept(NodeVisitor* visitor) override;
- RegExpNode* FilterOneByte(int depth) override;
-
- private:
- // AddAlternative is made private for loop nodes because alternatives
- // should not be added freely, we need to keep track of which node
- // goes back to the node itself.
- void AddAlternative(GuardedAlternative node) {
- ChoiceNode::AddAlternative(node);
- }
-
- RegExpNode* loop_node_;
- RegExpNode* continue_node_;
- bool body_can_be_zero_length_;
- bool read_backward_;
-
- // Temporary marker set only while generating quick check details. Represents
- // whether GetQuickCheckDetails traversed the initialization node for this
- // loop's counter. If so, we may be able to generate stricter quick checks
- // because we know the loop node must match at least min_loop_iterations_
- // times before the continuation node can match.
- bool traversed_loop_initialization_node_;
-
- // The minimum number of times the loop_node_ must match before the
- // continue_node_ might be considered. This value can be temporarily decreased
- // while generating quick check details, to represent the remaining iterations
- // after the completed portion of the quick check details.
- int min_loop_iterations_;
-
- friend class IterationDecrementer;
- friend class LoopInitializationMarker;
-};
-
-class NodeVisitor {
- public:
- virtual ~NodeVisitor() = default;
-#define DECLARE_VISIT(Type) virtual void Visit##Type(Type##Node* that) = 0;
- FOR_EACH_NODE_TYPE(DECLARE_VISIT)
-#undef DECLARE_VISIT
-};
-
-} // namespace internal
-} // namespace v8
-
-#endif // V8_REGEXP_REGEXP_NODES_H_