Commit 9b5141ca authored by Iain Ireland's avatar Iain Ireland Committed by Commit Bot

[regexp] Cache min/max-match for RegExpCapture/Group

Unlike the other RegExpTree types, RegExpCapture and RegExpGroup don't
cache their min/maxMatch value. Instead, they compute it by recursing
on the min/maxMatch of the body node. In pathological cases, with
sufficiently small stacks, this can cause stack overflow. (In
SpiderMonkey's case, it was a worker on 32-bit x86.)

It's easy enough to just precompute the value when the body is set.

R=jgruber@chromium.org

Bug: v8:10303
Change-Id: I4ba3d301d9a4a3f3c0cb94966148b747a4092d26
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2090192
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66673}
parent 73da478c
...@@ -463,7 +463,11 @@ class RegExpQuantifier final : public RegExpTree { ...@@ -463,7 +463,11 @@ class RegExpQuantifier final : public RegExpTree {
class RegExpCapture final : public RegExpTree { class RegExpCapture final : public RegExpTree {
public: public:
explicit RegExpCapture(int index) explicit RegExpCapture(int index)
: body_(nullptr), index_(index), name_(nullptr) {} : body_(nullptr),
index_(index),
min_match_(0),
max_match_(0),
name_(nullptr) {}
void* Accept(RegExpVisitor* visitor, void* data) override; void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override; RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
static RegExpNode* ToNode(RegExpTree* body, int index, static RegExpNode* ToNode(RegExpTree* body, int index,
...@@ -473,10 +477,14 @@ class RegExpCapture final : public RegExpTree { ...@@ -473,10 +477,14 @@ class RegExpCapture final : public RegExpTree {
bool IsAnchoredAtEnd() override; bool IsAnchoredAtEnd() override;
Interval CaptureRegisters() override; Interval CaptureRegisters() override;
bool IsCapture() override; bool IsCapture() override;
int min_match() override { return body_->min_match(); } int min_match() override { return min_match_; }
int max_match() override { return body_->max_match(); } int max_match() override { return max_match_; }
RegExpTree* body() { return body_; } RegExpTree* body() { return body_; }
void set_body(RegExpTree* body) { body_ = body; } void set_body(RegExpTree* body) {
body_ = body;
min_match_ = body->min_match();
max_match_ = body->max_match();
}
int index() const { return index_; } int index() const { return index_; }
const ZoneVector<uc16>* name() const { return name_; } const ZoneVector<uc16>* name() const { return name_; }
void set_name(const ZoneVector<uc16>* name) { name_ = name; } void set_name(const ZoneVector<uc16>* name) { name_ = name; }
...@@ -486,12 +494,17 @@ class RegExpCapture final : public RegExpTree { ...@@ -486,12 +494,17 @@ class RegExpCapture final : public RegExpTree {
private: private:
RegExpTree* body_; RegExpTree* body_;
int index_; int index_;
int min_match_;
int max_match_;
const ZoneVector<uc16>* name_; const ZoneVector<uc16>* name_;
}; };
class RegExpGroup final : public RegExpTree { class RegExpGroup final : public RegExpTree {
public: public:
explicit RegExpGroup(RegExpTree* body) : body_(body) {} explicit RegExpGroup(RegExpTree* body)
: body_(body),
min_match_(body->min_match()),
max_match_(body->max_match()) {}
void* Accept(RegExpVisitor* visitor, void* data) override; void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* ToNode(RegExpCompiler* compiler,
RegExpNode* on_success) override { RegExpNode* on_success) override {
...@@ -501,13 +514,15 @@ class RegExpGroup final : public RegExpTree { ...@@ -501,13 +514,15 @@ class RegExpGroup final : public RegExpTree {
bool IsAnchoredAtStart() override { return body_->IsAnchoredAtStart(); } bool IsAnchoredAtStart() override { return body_->IsAnchoredAtStart(); }
bool IsAnchoredAtEnd() override { return body_->IsAnchoredAtEnd(); } bool IsAnchoredAtEnd() override { return body_->IsAnchoredAtEnd(); }
bool IsGroup() override; bool IsGroup() override;
int min_match() override { return body_->min_match(); } int min_match() override { return min_match_; }
int max_match() override { return body_->max_match(); } int max_match() override { return max_match_; }
Interval CaptureRegisters() override { return body_->CaptureRegisters(); } Interval CaptureRegisters() override { return body_->CaptureRegisters(); }
RegExpTree* body() { return body_; } RegExpTree* body() { return body_; }
private: private:
RegExpTree* body_; RegExpTree* body_;
int min_match_;
int max_match_;
}; };
class RegExpLookaround final : public RegExpTree { class RegExpLookaround final : public RegExpTree {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment