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

Unified Diff: src/jsregexp.h

Issue 18091: Noone really liked the name "GenerationVariant" so here it gets renamed... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 11 months 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 | « no previous file | 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 1074)
+++ src/jsregexp.h (working copy)
@@ -349,7 +349,7 @@
uint32_t first_;
ZoneList<unsigned>* remaining_;
ZoneList<OutSet*>* successors_;
- friend class GenerationVariant;
+ friend class Trace;
};
@@ -449,7 +449,7 @@
};
-class GenerationVariant;
+class Trace;
struct NodeInfo {
@@ -583,13 +583,13 @@
class RegExpNode: public ZoneObject {
public:
- RegExpNode() : variants_generated_(0) { }
+ RegExpNode() : trace_count_(0) { }
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;
+ virtual bool Emit(RegExpCompiler* compiler, Trace* trace) = 0;
// How many characters must this node consume at a minimum in order to
// succeed.
virtual int EatsAtLeast(int recursion_depth) = 0;
@@ -597,7 +597,7 @@
// 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,
+ Trace* trace,
bool preload_has_checked_bounds,
Label* on_possible_success,
QuickCheckDetails* details_return,
@@ -612,7 +612,12 @@
static const int kNodeIsTooComplexForGreedyLoops = -1;
virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
Label* label() { return &label_; }
- static const int kMaxVariantsGenerated = 10;
+ // If non-generic code is generated for a node (ie 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;
// Propagates the given interest information forward. When seeing
// \bfoo for instance, the \b is implemented by propagating forward
@@ -636,8 +641,7 @@
protected:
enum LimitResult { DONE, FAIL, CONTINUE };
- LimitResult LimitVersions(RegExpCompiler* compiler,
- GenerationVariant* variant);
+ LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);
// Returns a sibling of this node whose interests and assumptions
// match the ones in the given node info. If no sibling exists NULL
@@ -660,7 +664,12 @@
Label label_;
NodeInfo info_;
SiblingList siblings_;
- int variants_generated_;
+ // 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_;
};
@@ -728,7 +737,7 @@
int repetition_limit,
RegExpNode* on_success);
virtual void Accept(NodeVisitor* visitor);
- virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int recursion_depth);
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
@@ -789,7 +798,7 @@
}
virtual void Accept(NodeVisitor* visitor);
virtual RegExpNode* PropagateForward(NodeInfo* info);
- virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int recursion_depth);
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
@@ -814,7 +823,7 @@
void TextEmitPass(RegExpCompiler* compiler,
TextEmitPassType pass,
bool preloaded,
- GenerationVariant* variant,
+ Trace* trace,
bool first_element_checked,
int* checked_up_to);
int Length();
@@ -833,7 +842,7 @@
virtual void Accept(NodeVisitor* visitor);
int start_register() { return start_reg_; }
int end_register() { return end_reg_; }
- virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int recursion_depth) { return 0; }
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
@@ -854,7 +863,7 @@
enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
explicit EndNode(Action action) : action_(action) { }
virtual void Accept(NodeVisitor* visitor);
- virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int recursion_depth) { return 0; }
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
@@ -866,7 +875,7 @@
virtual EndNode* Clone() { return new EndNode(*this); }
protected:
- void EmitInfoChecks(RegExpMacroAssembler* macro, GenerationVariant* variant);
+ void EmitInfoChecks(RegExpMacroAssembler* macro, Trace* trace);
private:
Action action_;
@@ -879,7 +888,7 @@
: EndNode(NEGATIVE_SUBMATCH_SUCCESS),
stack_pointer_register_(stack_pointer_reg),
current_position_register_(position_reg) { }
- virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
private:
int stack_pointer_register_;
@@ -932,7 +941,7 @@
void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); }
ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
DispatchTable* GetTable(bool ignore_case);
- virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+ virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int recursion_depth);
int EatsAtLeastHelper(int recursion_depth, RegExpNode* ignore_this_node);
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
@@ -953,10 +962,10 @@
friend class Analysis;
void GenerateGuard(RegExpMacroAssembler* macro_assembler,
Guard *guard,
- GenerationVariant* variant);
+ Trace* trace);
int CalculatePreloadCharacters(RegExpCompiler* compiler);
bool EmitOutOfLineContinuation(RegExpCompiler* compiler,
- GenerationVariant* variant,
+ Trace* trace,
GuardedAlternative alternative,
AlternativeGeneration* alt_gen,
int preload_characters,
@@ -975,7 +984,7 @@
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 bool Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int recursion_depth); // Returns 0.
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
@@ -1002,8 +1011,16 @@
// There are many ways to generate code for a node. This class encapsulates
// the current way we should be generating. In other words it encapsulates
-// the current state of the code generator.
-class GenerationVariant {
+// the current state of the code generator. The effect of this is that we
+// generate code for paths that the matcher can take through the regular
+// expression. A given node in the regexp can be code-generated several times
+// as it can be part of several traces. For example for the regexp:
+// /foo(bar|ip)baz/ the code to match baz will be generated twice, once as part
+// of the foo-bar-baz trace and once as part of the foo-ip-baz trace. The code
+// to match foo is generated only once (the traces have a common prefix). The
+// code to store the capture is deferred and generated (twice) after the places
+// where baz has been matched.
+class Trace {
public:
class DeferredAction {
public:
@@ -1017,14 +1034,14 @@
ActionNode::Type type_;
int reg_;
DeferredAction* next_;
- friend class GenerationVariant;
+ friend class Trace;
};
class DeferredCapture: public DeferredAction {
public:
- DeferredCapture(int reg, GenerationVariant* variant)
+ DeferredCapture(int reg, Trace* trace)
: DeferredAction(ActionNode::STORE_POSITION, reg),
- cp_offset_(variant->cp_offset()) { }
+ cp_offset_(trace->cp_offset()) { }
int cp_offset() { return cp_offset_; }
private:
int cp_offset_;
@@ -1057,7 +1074,7 @@
: DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { }
};
- GenerationVariant()
+ Trace()
: cp_offset_(0),
actions_(NULL),
backtrack_(NULL),
@@ -1065,9 +1082,22 @@
loop_label_(NULL),
characters_preloaded_(0),
bound_checked_up_to_(0) { }
+ // End the trace. This involves flushing the deferred actions in the trace and
+ // pushing a backtrack location onto the backtrack stack. Once this is done we
+ // can start a new trace or go to one that has already been generated.
bool Flush(RegExpCompiler* compiler, RegExpNode* successor);
int cp_offset() { return cp_offset_; }
DeferredAction* actions() { return actions_; }
+ // A trivial trace is one that has no deferred actions or other state that
+ // affects the assumptions used when generating code. There is no recorded
+ // backtrack location in a trivial trace, so with a trivial trace we will
+ // generate code that, on a failure to match, gets the backtrack location
+ // from the backtrack stack rather than using a direct jump instruction. We
+ // always start code generation with a trivial trace and non-trivial traces
+ // are created as we emit code for nodes or add to the list of deferred
+ // actions in the trace. The location of the code generated for a node using
+ // a trivial trace is recorded in a label in the node so that gotos can be
+ // generated to that code.
bool is_trivial() {
return backtrack_ == NULL &&
actions_ == NULL &&
@@ -1087,9 +1117,8 @@
// register and stores the offset in the out-parameter. Otherwise
// returns false.
bool GetStoredPosition(int reg, int* cp_offset);
- // These set methods and AdvanceVariant should be used only on new
- // GenerationVariants - the intention is that GenerationVariants are
- // immutable after creation.
+ // These set methods and AdvanceCurrentPositionInTrace should be used only on
+ // new traces - the intention is that traces are immutable after creation.
void add_action(DeferredAction* new_action) {
ASSERT(new_action->next_ == NULL);
new_action->next_ = actions_;
@@ -1105,7 +1134,7 @@
}
void clear_quick_check_performed() {
}
- void AdvanceVariant(int by, bool ascii);
+ void AdvanceCurrentPositionInTrace(int by, bool ascii);
private:
int FindAffectedRegisters(OutSet* affected_registers);
void PerformDeferredActions(RegExpMacroAssembler* macro,
« no previous file with comments | « no previous file | src/jsregexp.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698