Index: src/ast/ast.h |
diff --git a/src/ast/ast.h b/src/ast/ast.h |
index b4f2992e047215ac95d2c61b96a98d64afbfb5a1..ea81eba4caf9c1c39abf664890178ae84148ae76 100644 |
--- a/src/ast/ast.h |
+++ b/src/ast/ast.h |
@@ -2874,6 +2874,7 @@ class RegExpVisitor BASE_EMBEDDED { |
class RegExpTree : public ZoneObject { |
public: |
static const int kInfinity = kMaxInt; |
+ static const int kUninitialized = -1; |
virtual ~RegExpTree() {} |
virtual void* Accept(RegExpVisitor* visitor, void* data) = 0; |
virtual RegExpNode* ToNode(RegExpCompiler* compiler, |
@@ -2898,7 +2899,12 @@ class RegExpTree : public ZoneObject { |
class RegExpDisjunction final : public RegExpTree { |
public: |
- explicit RegExpDisjunction(ZoneList<RegExpTree*>* alternatives); |
+ explicit RegExpDisjunction(ZoneList<RegExpTree*>* alternatives) |
+ : alternatives_(alternatives), |
+ min_match_(kUninitialized), |
+ max_match_(kUninitialized) { |
+ DCHECK(alternatives->length() > 1); |
+ } |
void* Accept(RegExpVisitor* visitor, void* data) override; |
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; |
RegExpDisjunction* AsDisjunction() override; |
@@ -2906,10 +2912,18 @@ class RegExpDisjunction final : public RegExpTree { |
bool IsDisjunction() override; |
bool IsAnchoredAtStart() override; |
bool IsAnchoredAtEnd() override; |
- int min_match() override { return min_match_; } |
- int max_match() override { return max_match_; } |
+ int min_match() override { |
+ if (min_match_ == kUninitialized) LazilyComputeMatchLengths(); |
+ return min_match_; |
+ } |
+ int max_match() override { |
+ if (max_match_ == kUninitialized) LazilyComputeMatchLengths(); |
+ return max_match_; |
+ } |
ZoneList<RegExpTree*>* alternatives() { return alternatives_; } |
+ |
private: |
+ void LazilyComputeMatchLengths(); |
bool SortConsecutiveAtoms(RegExpCompiler* compiler); |
void RationalizeConsecutiveAtoms(RegExpCompiler* compiler); |
void FixSingleCharacterDisjunctions(RegExpCompiler* compiler); |
@@ -2921,7 +2935,10 @@ class RegExpDisjunction final : public RegExpTree { |
class RegExpAlternative final : public RegExpTree { |
public: |
- explicit RegExpAlternative(ZoneList<RegExpTree*>* nodes); |
+ explicit RegExpAlternative(ZoneList<RegExpTree*>* nodes) |
+ : nodes_(nodes), min_match_(kUninitialized), max_match_(kUninitialized) { |
+ DCHECK(nodes->length() > 1); |
+ } |
void* Accept(RegExpVisitor* visitor, void* data) override; |
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; |
RegExpAlternative* AsAlternative() override; |
@@ -2929,10 +2946,18 @@ class RegExpAlternative final : public RegExpTree { |
bool IsAlternative() override; |
bool IsAnchoredAtStart() override; |
bool IsAnchoredAtEnd() override; |
- int min_match() override { return min_match_; } |
- int max_match() override { return max_match_; } |
+ int min_match() override { |
+ if (min_match_ == kUninitialized) LazilyComputeMatchLengths(); |
+ return min_match_; |
+ } |
+ int max_match() override { |
+ if (max_match_ == kUninitialized) LazilyComputeMatchLengths(); |
+ return max_match_; |
+ } |
ZoneList<RegExpTree*>* nodes() { return nodes_; } |
+ |
private: |
+ void LazilyComputeMatchLengths(); |
ZoneList<RegExpTree*>* nodes_; |
int min_match_; |
int max_match_; |
@@ -3075,14 +3100,9 @@ class RegExpQuantifier final : public RegExpTree { |
: body_(body), |
min_(min), |
max_(max), |
- min_match_(min * body->min_match()), |
- quantifier_type_(type) { |
- if (max > 0 && body->max_match() > kInfinity / max) { |
- max_match_ = kInfinity; |
- } else { |
- max_match_ = max * body->max_match(); |
- } |
- } |
+ min_match_(kUninitialized), |
+ max_match_(kUninitialized), |
+ quantifier_type_(type) {} |
void* Accept(RegExpVisitor* visitor, void* data) override; |
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; |
static RegExpNode* ToNode(int min, |
@@ -3095,8 +3115,14 @@ class RegExpQuantifier final : public RegExpTree { |
RegExpQuantifier* AsQuantifier() override; |
Interval CaptureRegisters() override; |
bool IsQuantifier() override; |
- int min_match() override { return min_match_; } |
- int max_match() override { return max_match_; } |
+ int min_match() override { |
+ if (min_match_ == kUninitialized) LazilyComputeMatchLengths(); |
+ return min_match_; |
+ } |
+ int max_match() override { |
+ if (max_match_ == kUninitialized) LazilyComputeMatchLengths(); |
+ return max_match_; |
+ } |
int min() { return min_; } |
int max() { return max_; } |
bool is_possessive() { return quantifier_type_ == POSSESSIVE; } |
@@ -3105,6 +3131,7 @@ class RegExpQuantifier final : public RegExpTree { |
RegExpTree* body() { return body_; } |
private: |
+ void LazilyComputeMatchLengths(); |
RegExpTree* body_; |
int min_; |
int max_; |
@@ -3180,24 +3207,21 @@ class RegExpLookaround final : public RegExpTree { |
class RegExpBackReference final : public RegExpTree { |
public: |
explicit RegExpBackReference(RegExpCapture* capture) |
- : capture_(capture) { } |
+ : capture_(capture), max_match_(kUninitialized) {} |
void* Accept(RegExpVisitor* visitor, void* data) override; |
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; |
RegExpBackReference* AsBackReference() override; |
bool IsBackReference() override; |
int min_match() override { return 0; } |
- // The capture may not be completely parsed yet, if the reference occurs |
- // before the capture. In the ordinary case, nothing has been captured yet, |
- // so the back reference must have the length 0. If the back reference is |
- // inside a lookbehind, effectively making it a forward reference, we return |
- // 0 since lookbehinds have a length of 0. |
- int max_match() override { |
- return capture_->body() ? capture_->max_match() : 0; |
- } |
+ int max_match() override; |
int index() { return capture_->index(); } |
RegExpCapture* capture() { return capture_; } |
private: |
+ static const int kRecursionMarker = -2; |
+ STATIC_ASSERT(kRecursionMarker != kUninitialized); |
+ |
RegExpCapture* capture_; |
+ int max_match_; |
}; |