Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1106)

Unified Diff: src/jsregexp.h

Issue 14892: Merge changes from bleeding_edge into experimental toiger branch.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/interpreter-irregexp.cc ('k') | src/jsregexp.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/jsregexp.h
===================================================================
--- src/jsregexp.h (revision 1012)
+++ src/jsregexp.h (working copy)
@@ -439,6 +439,7 @@
explicit TextElement(Type t) : type(t), cp_offset(-1) { }
static TextElement Atom(RegExpAtom* atom);
static TextElement CharClass(RegExpCharacterClass* char_class);
+ int length();
Type type;
union {
RegExpAtom* u_atom;
@@ -459,23 +460,10 @@
NodeInfo()
: being_analyzed(false),
been_analyzed(false),
- being_expanded(false),
- been_expanded(false),
- determine_word(false),
- determine_newline(false),
- determine_start(false),
- does_determine_word(false),
- does_determine_newline(false),
- does_determine_start(false),
follows_word_interest(false),
follows_newline_interest(false),
follows_start_interest(false),
- is_word(UNKNOWN),
- is_newline(UNKNOWN),
at_end(false),
- follows_word(UNKNOWN),
- follows_newline(UNKNOWN),
- follows_start(UNKNOWN),
visited(false) { }
// Returns true if the interests and assumptions of this node
@@ -484,21 +472,9 @@
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) &&
- (follows_word == that->follows_word) &&
- (follows_newline == that->follows_newline) &&
- (follows_start == that->follows_start) &&
- (does_determine_word == that->does_determine_word) &&
- (does_determine_newline == that->does_determine_newline) &&
- (does_determine_start == that->does_determine_start);
+ (follows_start_interest == that->follows_start_interest);
}
- bool HasAssertions() {
- return (follows_word != UNKNOWN) ||
- (follows_newline != UNKNOWN) ||
- (follows_start != UNKNOWN);
- }
-
// Updates the interests of this node given the interests of the
// node preceding it.
void AddFromPreceding(NodeInfo* that) {
@@ -508,26 +484,6 @@
follows_start_interest |= that->follows_start_interest;
}
- void AddAssumptions(NodeInfo* that) {
- if (that->follows_word != UNKNOWN) {
- ASSERT(follows_word == UNKNOWN || follows_word == that->follows_word);
- follows_word = that->follows_word;
- }
- if (that->follows_newline != UNKNOWN) {
- ASSERT(follows_newline == UNKNOWN ||
- follows_newline == that->follows_newline);
- follows_newline = that->follows_newline;
- }
- if (that->follows_start != UNKNOWN) {
- ASSERT(follows_start == UNKNOWN ||
- follows_start == that->follows_start);
- follows_start = that->follows_start;
- }
- does_determine_word = that->does_determine_word;
- does_determine_newline = that->does_determine_newline;
- does_determine_start = that->does_determine_start;
- }
-
bool HasLookbehind() {
return follows_word_interest ||
follows_newline_interest ||
@@ -545,61 +501,22 @@
void ResetCompilationState() {
being_analyzed = false;
been_analyzed = false;
- being_expanded = false;
- been_expanded = false;
}
bool being_analyzed: 1;
bool been_analyzed: 1;
- bool being_expanded: 1;
- bool been_expanded: 1;
- // These bits are set if this node must propagate forward information
- // about the last character it consumed (or, in the case of 'start',
- // if it is at the start of the input).
- bool determine_word: 1;
- bool determine_newline: 1;
- bool determine_start: 1;
-
- bool does_determine_word: 1;
- bool does_determine_newline: 1;
- bool does_determine_start: 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;
- TriBool is_word: 2;
- TriBool is_newline: 2;
-
bool at_end: 1;
-
- // These bits are set if the node can make assumptions about what
- // the previous character was.
- TriBool follows_word: 2;
- TriBool follows_newline: 2;
- TriBool follows_start: 2;
-
bool visited: 1;
};
-class ExpansionGuard {
- public:
- explicit inline ExpansionGuard(NodeInfo* info) : info_(info) {
- ASSERT(!info->being_expanded);
- info->being_expanded = true;
- }
- inline ~ExpansionGuard() {
- info_->being_expanded = false;
- }
- private:
- NodeInfo* info_;
-};
-
-
class SiblingList {
public:
SiblingList() : list_(NULL) { }
@@ -619,24 +536,84 @@
};
+// Details of a quick mask-compare check that can look ahead in the
+// input stream.
+class QuickCheckDetails {
+ public:
+ QuickCheckDetails()
+ : characters_(0),
+ mask_(0),
+ value_(0) { }
+ explicit QuickCheckDetails(int characters)
+ : characters_(characters),
+ mask_(0),
+ value_(0) { }
+ bool Rationalize(bool ascii);
+ // Merge in the information from another branch of an alternation.
+ void Merge(QuickCheckDetails* other, int from_index);
+ // Advance the current position by some amount.
+ void Advance(int by, bool ascii);
+ void Clear();
+ struct Position {
+ Position() : mask(0), value(0), determines_perfectly(false) { }
+ uc16 mask;
+ uc16 value;
+ bool determines_perfectly;
+ };
+ int characters() { return characters_; }
+ void set_characters(int characters) { characters_ = characters; }
+ Position* positions(int index) {
+ ASSERT(index >= 0);
+ ASSERT(index < characters_);
+ return positions_ + index;
+ }
+ uint32_t mask() { return mask_; }
+ uint32_t value() { return value_; }
+
+ private:
+ // How many characters do we have quick check information from. This is
+ // the same for all branches of a choice node.
+ int characters_;
+ Position positions_[4];
+ // These values are the condensate of the above array after Rationalize().
+ uint32_t mask_;
+ uint32_t value_;
+};
+
+
class RegExpNode: public ZoneObject {
public:
RegExpNode() : variants_generated_(0) { }
- virtual ~RegExpNode() { }
+ virtual ~RegExpNode();
virtual void Accept(NodeVisitor* visitor) = 0;
// Generates a goto to this node or actually generates the code at this point.
// Until the implementation is complete we will return true for success and
// false for failure.
virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant) = 0;
+ // How many characters must this node consume at a minimum in order to
+ // succeed.
+ virtual int EatsAtLeast(int recursion_depth) = 0;
+ // 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,
+ GenerationVariant* variant,
+ bool preload_has_checked_bounds,
+ Label* on_possible_success,
+ QuickCheckDetails* details_return,
+ bool fall_through_on_failure);
+ // 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) = 0;
static const int kNodeIsTooComplexForGreedyLoops = -1;
virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
Label* label() { return &label_; }
static const int kMaxVariantsGenerated = 10;
- RegExpNode* EnsureExpanded(NodeInfo* info);
- virtual RegExpNode* ExpandLocal(NodeInfo* info) = 0;
- virtual void ExpandChildren() = 0;
-
// Propagates the given interest information forward. When seeing
// \bfoo for instance, the \b is implemented by propagating forward
// to the 'foo' string that it should only succeed if its first
@@ -720,8 +697,12 @@
RegExpNode* on_success);
virtual void Accept(NodeVisitor* visitor);
virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
- virtual RegExpNode* ExpandLocal(NodeInfo* info);
- virtual void ExpandChildren();
+ virtual int EatsAtLeast(int recursion_depth);
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+ RegExpCompiler* compiler,
+ int filled_in) {
+ return on_success()->GetQuickCheckDetails(details, compiler, filled_in);
+ }
virtual RegExpNode* PropagateForward(NodeInfo* info);
Type type() { return type_; }
// TODO(erikcorry): We should allow some action nodes in greedy loops.
@@ -767,9 +748,11 @@
}
virtual void Accept(NodeVisitor* visitor);
virtual RegExpNode* PropagateForward(NodeInfo* info);
- virtual RegExpNode* ExpandLocal(NodeInfo* info);
- virtual void ExpandChildren();
virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual int EatsAtLeast(int recursion_depth);
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+ RegExpCompiler* compiler,
+ int characters_filled_in);
ZoneList<TextElement>* elements() { return elms_; }
void MakeCaseIndependent();
virtual int GreedyLoopTextLength();
@@ -779,10 +762,21 @@
return result;
}
void CalculateOffsets();
+
private:
- void ExpandAtomChildren(RegExpAtom* that);
- void ExpandCharClassChildren(RegExpCharacterClass* that);
-
+ enum TextEmitPassType {
+ NON_ASCII_MATCH,
+ CHARACTER_MATCH,
+ CASE_CHARACTER_MATCH,
+ CHARACTER_CLASS_MATCH
+ };
+ void TextEmitPass(RegExpCompiler* compiler,
+ TextEmitPassType pass,
+ bool preloaded,
+ GenerationVariant* variant,
+ bool first_element_checked,
+ int* checked_up_to);
+ int Length();
ZoneList<TextElement>* elms_;
};
@@ -799,9 +793,13 @@
int start_register() { return start_reg_; }
int end_register() { return end_reg_; }
virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual int EatsAtLeast(int recursion_depth) { return 0; }
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+ RegExpCompiler* compiler,
+ int characters_filled_in) {
+ return;
+ }
virtual RegExpNode* PropagateForward(NodeInfo* info);
- virtual RegExpNode* ExpandLocal(NodeInfo* info);
- virtual void ExpandChildren();
virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); }
private:
@@ -816,9 +814,14 @@
explicit EndNode(Action action) : action_(action) { }
virtual void Accept(NodeVisitor* visitor);
virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual int EatsAtLeast(int recursion_depth) { return 0; }
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+ RegExpCompiler* compiler,
+ int characters_filled_in) {
+ // Returning 0 from EatsAtLeast should ensure we never get here.
+ UNREACHABLE();
+ }
virtual RegExpNode* PropagateForward(NodeInfo* info);
- virtual RegExpNode* ExpandLocal(NodeInfo* info);
- virtual void ExpandChildren();
virtual EndNode* Clone() { return new EndNode(*this); }
protected:
@@ -875,6 +878,9 @@
};
+class AlternativeGeneration;
+
+
class ChoiceNode: public RegExpNode {
public:
explicit ChoiceNode(int expected_size)
@@ -886,9 +892,12 @@
ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
DispatchTable* GetTable(bool ignore_case);
virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual int EatsAtLeast(int recursion_depth);
+ int EatsAtLeastHelper(int recursion_depth, RegExpNode* ignore_this_node);
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+ RegExpCompiler* compiler,
+ int characters_filled_in);
virtual RegExpNode* PropagateForward(NodeInfo* info);
- virtual RegExpNode* ExpandLocal(NodeInfo* info);
- virtual void ExpandChildren();
virtual ChoiceNode* Clone() { return new ChoiceNode(*this); }
bool being_calculated() { return being_calculated_; }
@@ -900,10 +909,17 @@
private:
friend class DispatchTableConstructor;
- friend class AssertionPropagation;
+ friend class Analysis;
void GenerateGuard(RegExpMacroAssembler* macro_assembler,
Guard *guard,
GenerationVariant* variant);
+ int CalculatePreloadCharacters(RegExpCompiler* compiler);
+ bool EmitOutOfLineContinuation(RegExpCompiler* compiler,
+ GenerationVariant* variant,
+ GuardedAlternative alternative,
+ AlternativeGeneration* alt_gen,
+ int preload_characters,
+ bool next_expects_preload);
DispatchTable* table_;
bool being_calculated_;
};
@@ -911,9 +927,35 @@
class LoopChoiceNode: public ChoiceNode {
public:
- explicit LoopChoiceNode(int expected_size) : ChoiceNode(expected_size) { }
+ explicit LoopChoiceNode(bool body_can_be_zero_length)
+ : ChoiceNode(2),
+ loop_node_(NULL),
+ continue_node_(NULL),
+ body_can_be_zero_length_(body_can_be_zero_length) { }
+ void AddLoopAlternative(GuardedAlternative alt);
+ void AddContinueAlternative(GuardedAlternative alt);
virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual int EatsAtLeast(int recursion_depth); // Returns 0.
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+ RegExpCompiler* compiler,
+ int characters_filled_in);
virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
+ RegExpNode* loop_node() { return loop_node_; }
+ RegExpNode* continue_node() { return continue_node_; }
+ bool body_can_be_zero_length() { return body_can_be_zero_length_; }
+ virtual void Accept(NodeVisitor* visitor);
+
+ 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_;
};
@@ -963,42 +1005,47 @@
: DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { }
};
- explicit GenerationVariant(Label* backtrack)
- : cp_offset_(0),
- actions_(NULL),
- backtrack_(backtrack),
- stop_node_(NULL),
- loop_label_(NULL) { }
GenerationVariant()
: cp_offset_(0),
actions_(NULL),
backtrack_(NULL),
stop_node_(NULL),
- loop_label_(NULL) { }
+ loop_label_(NULL),
+ characters_preloaded_(0) { }
bool Flush(RegExpCompiler* compiler, RegExpNode* successor);
int cp_offset() { return cp_offset_; }
DeferredAction* actions() { return actions_; }
bool is_trivial() {
- return backtrack_ == NULL && actions_ == NULL && cp_offset_ == 0;
+ return backtrack_ == NULL &&
+ actions_ == NULL &&
+ cp_offset_ == 0 &&
+ characters_preloaded_ == 0 &&
+ quick_check_performed_.characters() == 0;
}
Label* backtrack() { return backtrack_; }
Label* loop_label() { return loop_label_; }
RegExpNode* stop_node() { return stop_node_; }
- // These set methods should be used only on new GenerationVariants - the
- // intention is that GenerationVariants are immutable after creation.
+ int characters_preloaded() { return characters_preloaded_; }
+ QuickCheckDetails* quick_check_performed() { return &quick_check_performed_; }
+ bool mentions_reg(int reg);
+ // These set methods and AdvanceVariant should be used only on new
+ // GenerationVariants - the intention is that GenerationVariants are
+ // immutable after creation.
void add_action(DeferredAction* new_action) {
ASSERT(new_action->next_ == NULL);
new_action->next_ = actions_;
actions_ = new_action;
}
- void set_cp_offset(int new_cp_offset) {
- ASSERT(new_cp_offset >= cp_offset_);
- cp_offset_ = new_cp_offset;
- }
void set_backtrack(Label* backtrack) { backtrack_ = backtrack; }
void set_stop_node(RegExpNode* node) { stop_node_ = node; }
void set_loop_label(Label* label) { loop_label_ = label; }
- bool mentions_reg(int reg);
+ void set_characters_preloaded(int cpre) { characters_preloaded_ = cpre; }
+ void set_quick_check_performed(QuickCheckDetails* d) {
+ quick_check_performed_ = *d;
+ }
+ void clear_quick_check_performed() {
+ }
+ void AdvanceVariant(int by, bool ascii);
private:
int FindAffectedRegisters(OutSet* affected_registers);
void PerformDeferredActions(RegExpMacroAssembler* macro,
@@ -1015,7 +1062,11 @@
Label* backtrack_;
RegExpNode* stop_node_;
Label* loop_label_;
+ int characters_preloaded_;
+ QuickCheckDetails quick_check_performed_;
};
+
+
class NodeVisitor {
public:
virtual ~NodeVisitor() { }
@@ -1023,6 +1074,7 @@
virtual void Visit##Type(Type##Node* that) = 0;
FOR_EACH_NODE_TYPE(DECLARE_VISIT)
#undef DECLARE_VISIT
+ virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); }
};
@@ -1070,33 +1122,9 @@
// +-------+ ---> +------------+
// | word? | | check word |
// +-------+ +------------+
-//
-// At a later phase all nodes that determine information for their
-// following nodes are split into several 'sibling' nodes. In this
-// case the first '.' is split into one node that only matches words
-// and one that only matches non-words. The second '.' is also split,
-// into one node that assumes that the previous character was a word
-// character and one that assumes that is was non-word. In this case
-// the result is
-//
-// +------------------+ +------------------+
-// /--> | intersect(., \w) | ---> | intersect(., \W) |
-// | +------------------+ +------------------+
-// | | follows \w |
-// | +------------------+
-// --?
-// | +------------------+ +------------------+
-// \--> | intersect(., \W) | ---> | intersect(., \w) |
-// +------------------+ +------------------+
-// | follows \W |
-// +------------------+
-//
-// This way we don't need to explicitly check the previous character
-// but can always assume that whoever consumed the previous character
-// has propagated the relevant information forward.
-class AssertionPropagation: public NodeVisitor {
+class Analysis: public NodeVisitor {
public:
- explicit AssertionPropagation(bool ignore_case)
+ explicit Analysis(bool ignore_case)
: ignore_case_(ignore_case) { }
void EnsureAnalyzed(RegExpNode* node);
@@ -1104,11 +1132,12 @@
virtual void Visit##Type(Type##Node* that);
FOR_EACH_NODE_TYPE(DECLARE_VISIT)
#undef DECLARE_VISIT
+ virtual void VisitLoopChoice(LoopChoiceNode* that);
private:
bool ignore_case_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(AssertionPropagation);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis);
};
@@ -1116,12 +1145,10 @@
RegExpCompileData()
: tree(NULL),
node(NULL),
- has_lookbehind(false),
simple(true),
capture_count(0) { }
RegExpTree* tree;
RegExpNode* node;
- bool has_lookbehind;
bool simple;
Handle<String> error;
int capture_count;
« no previous file with comments | « src/interpreter-irregexp.cc ('k') | src/jsregexp.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698