100
113
// This ensures that the regexp is compiled for the subject, and that
101
114
// the subject is flat.
102
115
// Returns the number of integer spaces required by IrregexpExecOnce
103
// as its "registers" argument. If the regexp cannot be compiled,
116
// as its "registers" argument. If the regexp cannot be compiled,
104
117
// an exception is set as pending, and this function returns negative.
105
118
static int IrregexpPrepare(Handle<JSRegExp> regexp,
106
119
Handle<String> subject);
108
// Execute a regular expression once on the subject, starting from
109
// character "index".
110
// If successful, returns RE_SUCCESS and set the capture positions
111
// in the first registers.
121
// Execute a regular expression on the subject, starting from index.
122
// If matching succeeds, return the number of matches. This can be larger
123
// than one in the case of global regular expressions.
124
// The captures and subcaptures are stored into the registers vector.
112
125
// If matching fails, returns RE_FAILURE.
113
126
// If execution fails, sets a pending exception and returns RE_EXCEPTION.
114
static IrregexpResult IrregexpExecOnce(Handle<JSRegExp> regexp,
115
Handle<String> subject,
117
Vector<int> registers);
127
static int IrregexpExecRaw(Handle<JSRegExp> regexp,
128
Handle<String> subject,
119
133
// Execute an Irregexp bytecode pattern.
120
134
// On a successful match, the result is a JSArray containing
121
// captured positions. On a failure, the result is the null value.
135
// captured positions. On a failure, the result is the null value.
122
136
// Returns an empty handle in case of an exception.
123
137
static Handle<Object> IrregexpExec(Handle<JSRegExp> regexp,
124
138
Handle<String> subject,
126
140
Handle<JSArray> lastMatchInfo);
142
// Set last match info. If match is NULL, then setting captures is omitted.
143
static Handle<JSArray> SetLastMatchInfo(Handle<JSArray> last_match_info,
144
Handle<String> subject,
151
GlobalCache(Handle<JSRegExp> regexp,
152
Handle<String> subject,
158
// Fetch the next entry in the cache for global regexp match results.
159
// This does not set the last match info. Upon failure, NULL is returned.
160
// The cause can be checked with Result(). The previous
161
// result is still in available in memory when a failure happens.
162
int32_t* FetchNext();
164
int32_t* LastSuccessfulMatch();
166
inline bool HasException() { return num_matches_ < 0; }
171
int current_match_index_;
172
int registers_per_match_;
173
// Pointer to the last set of captures.
174
int32_t* register_array_;
175
int register_array_size_;
176
Handle<JSRegExp> regexp_;
177
Handle<String> subject_;
128
181
// Array index in the lastMatchInfo array.
129
182
static const int kLastCaptureCount = 0;
130
183
static const int kLastSubject = 1;
184
237
static const int kRegWxpCompiledLimit = 1 * MB;
187
static String* last_ascii_string_;
188
static String* two_byte_cached_string_;
190
static bool CompileIrregexp(Handle<JSRegExp> re, bool is_ascii);
191
static inline bool EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii);
194
// Set the subject cache. The previous string buffer is not deleted, so the
195
// caller should ensure that it doesn't leak.
196
static void SetSubjectCache(String* subject,
199
int character_position,
202
// A one element cache of the last utf8_subject string and its length. The
203
// subject JS String object is cached in the heap. We also cache a
204
// translation between position and utf8 position.
205
static char* utf8_subject_cache_;
206
static int utf8_length_cache_;
207
static int utf8_position_;
208
static int character_position_;
240
static bool CompileIrregexp(
241
Handle<JSRegExp> re, Handle<String> sample_subject, bool is_ascii);
242
static inline bool EnsureCompiledIrregexp(
243
Handle<JSRegExp> re, Handle<String> sample_subject, bool is_ascii);
222
// Represents the relation of two sets.
223
// Sets can be either disjoint, partially or fully overlapping, or equal.
224
class SetRelation BASE_EMBEDDED {
226
// Relation is represented by a bit saying whether there are elements in
227
// one set that is not in the other, and a bit saying that there are elements
228
// that are in both sets.
230
// Location of an element. Corresponds to the internal areas of
233
kInFirst = 1 << kInsideFirst,
234
kInSecond = 1 << kInsideSecond,
235
kInBoth = 1 << kInsideBoth
237
SetRelation() : bits_(0) {}
239
// Add the existence of objects in a particular
240
void SetElementsInFirstSet() { bits_ |= kInFirst; }
241
void SetElementsInSecondSet() { bits_ |= kInSecond; }
242
void SetElementsInBothSets() { bits_ |= kInBoth; }
243
// Check the currently known relation of the sets (common functions only,
244
// for other combinations, use value() to get the bits and check them
246
// Sets are completely disjoint.
247
bool Disjoint() { return (bits_ & kInBoth) == 0; }
249
bool Equals() { return (bits_ & (kInFirst | kInSecond)) == 0; }
250
// First set contains second.
251
bool Contains() { return (bits_ & kInSecond) == 0; }
252
// Second set contains first.
253
bool ContainedIn() { return (bits_ & kInFirst) == 0; }
254
bool NonTrivialIntersection() {
255
return (bits_ == (kInFirst | kInSecond | kInBoth));
257
int value() { return bits_; }
257
// Represents code units in the range from from_ to to_, both ends are
264
259
class CharacterRange {
266
261
CharacterRange() : from_(0), to_(0) { }
267
262
// For compatibility with the CHECK_OK macro
268
263
CharacterRange(void* null) { ASSERT_EQ(NULL, null); } //NOLINT
269
264
CharacterRange(uc16 from, uc16 to) : from_(from), to_(to) { }
270
static void AddClassEscape(uc16 type, ZoneList<CharacterRange>* ranges);
271
static Vector<const uc16> GetWordBounds();
265
static void AddClassEscape(uc16 type, ZoneList<CharacterRange>* ranges,
267
static Vector<const int> GetWordBounds();
272
268
static inline CharacterRange Singleton(uc16 value) {
273
269
return CharacterRange(value, value);
287
283
bool is_valid() { return from_ <= to_; }
288
284
bool IsEverything(uc16 max) { return from_ == 0 && to_ >= max; }
289
285
bool IsSingleton() { return (from_ == to_); }
290
void AddCaseEquivalents(ZoneList<CharacterRange>* ranges, bool is_ascii);
286
void AddCaseEquivalents(ZoneList<CharacterRange>* ranges, bool is_ascii,
291
288
static void Split(ZoneList<CharacterRange>* base,
292
Vector<const uc16> overlay,
289
Vector<const int> overlay,
293
290
ZoneList<CharacterRange>** included,
294
ZoneList<CharacterRange>** excluded);
291
ZoneList<CharacterRange>** excluded,
295
293
// Whether a range list is in canonical form: Ranges ordered by from value,
296
294
// and ranges non-overlapping and non-adjacent.
297
295
static bool IsCanonical(ZoneList<CharacterRange>* ranges);
300
298
// adjacent ranges are merged. The resulting list may be shorter than the
301
299
// original, but cannot be longer.
302
300
static void Canonicalize(ZoneList<CharacterRange>* ranges);
303
// Check how the set of characters defined by a CharacterRange list relates
304
// to the set of word characters. List must be in canonical form.
305
static SetRelation WordCharacterRelation(ZoneList<CharacterRange>* ranges);
306
// Takes two character range lists (representing character sets) in canonical
307
// form and merges them.
308
// The characters that are only covered by the first set are added to
309
// first_set_only_out. the characters that are only in the second set are
310
// added to second_set_only_out, and the characters that are in both are
311
// added to both_sets_out.
312
// The pointers to first_set_only_out, second_set_only_out and both_sets_out
313
// should be to empty lists, but they need not be distinct, and may be NULL.
314
// If NULL, the characters are dropped, and if two arguments are the same
315
// pointer, the result is the union of the two sets that would be created
316
// if the pointers had been distinct.
317
// This way, the Merge function can compute all the usual set operations:
318
// union (all three out-sets are equal), intersection (only both_sets_out is
319
// non-NULL), and set difference (only first_set is non-NULL).
320
static void Merge(ZoneList<CharacterRange>* first_set,
321
ZoneList<CharacterRange>* second_set,
322
ZoneList<CharacterRange>* first_set_only_out,
323
ZoneList<CharacterRange>* second_set_only_out,
324
ZoneList<CharacterRange>* both_sets_out);
325
301
// Negate the contents of a character range in canonical form.
326
302
static void Negate(ZoneList<CharacterRange>* src,
327
ZoneList<CharacterRange>* dst);
303
ZoneList<CharacterRange>* dst,
328
305
static const int kStartMarker = (1 << 24);
329
306
static const int kPayloadMask = (1 << 24) - 1;
632
604
bool not_at_start) = 0;
633
605
static const int kNodeIsTooComplexForGreedyLoops = -1;
634
606
virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
607
// Only returns the successor for a text node of length 1 that matches any
608
// character and that has no guards on it.
609
virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
610
RegExpCompiler* compiler) {
614
// Collects information on the possible code units (mod 128) that can match if
615
// we look forward. This is used for a Boyer-Moore-like string searching
616
// implementation. TODO(erikcorry): This should share more code with
617
// EatsAtLeast, GetQuickCheckDetails. The budget argument is used to limit
618
// the number of nodes we are willing to look at in order to create this data.
619
static const int kFillInBMBudget = 200;
620
virtual void FillInBMInfo(int offset,
623
BoyerMooreLookahead* bm,
628
// If we know that the input is ASCII then there are some nodes that can
629
// never match. This method returns a node that can be substituted for
630
// itself, or NULL if the node can never match.
631
virtual RegExpNode* FilterASCII(int depth) { return this; }
632
// Helper for FilterASCII.
633
RegExpNode* replacement() {
634
ASSERT(info()->replacement_calculated);
637
RegExpNode* set_replacement(RegExpNode* replacement) {
638
info()->replacement_calculated = true;
639
replacement_ = replacement;
640
return replacement; // For convenience.
643
// We want to avoid recalculating the lookahead info, so we store it on the
644
// node. Only info that is for this node is stored. We can tell that the
645
// info is for this node when offset == 0, so the information is calculated
646
// relative to this node.
647
void SaveBMInfo(BoyerMooreLookahead* bm, bool not_at_start, int offset) {
648
if (offset == 0) set_bm_info(not_at_start, bm);
635
651
Label* label() { return &label_; }
636
// If non-generic code is generated for a node (ie the node is not at the
652
// If non-generic code is generated for a node (i.e. the node is not at the
637
653
// start of the trace) then it cannot be reused. This variable sets a limit
638
654
// on how often we allow that to happen before we insist on starting a new
639
655
// trace and generating generic code for a node that can be reused by flushing
643
659
NodeInfo* info() { return &info_; }
645
void AddSibling(RegExpNode* node) { siblings_.Add(node); }
647
// Static version of EnsureSibling that expresses the fact that the
648
// result has the same type as the input.
650
static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) {
651
return static_cast<C*>(node->EnsureSibling(info, cloned));
654
SiblingList* siblings() { return &siblings_; }
655
void set_siblings(SiblingList* other) { siblings_ = *other; }
657
// Return the set of possible next characters recognized by the regexp
658
// (or a safe subset, potentially the set of all characters).
659
ZoneList<CharacterRange>* FirstCharacterSet();
661
// Compute (if possible within the budget of traversed nodes) the
662
// possible first characters of the input matched by this node and
663
// its continuation. Returns the remaining budget after the computation.
664
// If the budget is spent, the result is negative, and the cached
665
// first_character_set_ value isn't set.
666
virtual int ComputeFirstCharacterSet(int budget);
668
// Get and set the cached first character set value.
669
ZoneList<CharacterRange>* first_character_set() {
670
return first_character_set_;
672
void set_first_character_set(ZoneList<CharacterRange>* character_set) {
673
first_character_set_ = character_set;
661
BoyerMooreLookahead* bm_info(bool not_at_start) {
662
return bm_info_[not_at_start ? 1 : 0];
665
Zone* zone() const { return zone_; }
677
668
enum LimitResult { DONE, CONTINUE };
678
static const int kComputeFirstCharacterSetFail = -1;
669
RegExpNode* replacement_;
680
671
LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);
682
// Returns a sibling of this node whose interests and assumptions
683
// match the ones in the given node info. If no sibling exists NULL
685
RegExpNode* TryGetSibling(NodeInfo* info);
687
// Returns a sibling of this node whose interests match the ones in
688
// the given node info. The info must not contain any assertions.
689
// If no node exists a new one will be created by cloning the current
690
// node. The result will always be an instance of the same concrete
691
// class as this node.
692
RegExpNode* EnsureSibling(NodeInfo* info, bool* cloned);
694
// Returns a clone of this node initialized using the copy constructor
695
// of its concrete class. Note that the node may have to be pre-
696
// processed before it is on a usable state.
697
virtual RegExpNode* Clone() = 0;
673
void set_bm_info(bool not_at_start, BoyerMooreLookahead* bm) {
674
bm_info_[not_at_start ? 1 : 0] = bm;
700
678
static const int kFirstCharBudget = 10;
703
SiblingList siblings_;
704
ZoneList<CharacterRange>* first_character_set_;
705
681
// This variable keeps track of how many times code has been generated for
706
682
// this node (in different traces). We don't keep track of where the
707
683
// generated code is located unless the code is generated at the start of
708
684
// a trace, in which case it is generic and can be reused by flushing the
709
685
// deferred operations in the current trace and generating a goto.
710
686
int trace_count_;
687
BoyerMooreLookahead* bm_info_[2];
741
720
class SeqRegExpNode: public RegExpNode {
743
722
explicit SeqRegExpNode(RegExpNode* on_success)
744
: on_success_(on_success) { }
723
: RegExpNode(on_success->zone()), on_success_(on_success) { }
745
724
RegExpNode* on_success() { return on_success_; }
746
725
void set_on_success(RegExpNode* node) { on_success_ = node; }
726
virtual RegExpNode* FilterASCII(int depth);
727
virtual void FillInBMInfo(int offset,
730
BoyerMooreLookahead* bm,
732
on_success_->FillInBMInfo(
733
offset, recursion_depth + 1, budget - 1, bm, not_at_start);
734
if (offset == 0) set_bm_info(not_at_start, bm);
738
RegExpNode* FilterSuccessor(int depth);
748
741
RegExpNode* on_success_;
898
// Types not directly expressible in regexp syntax.
899
// Used for modifying a boundary node if its following character is
900
// known to be word and/or non-word.
901
AFTER_NONWORD_CHARACTER,
904
897
static AssertionNode* AtEnd(RegExpNode* on_success) {
905
return new AssertionNode(AT_END, on_success);
898
return new(on_success->zone()) AssertionNode(AT_END, on_success);
907
900
static AssertionNode* AtStart(RegExpNode* on_success) {
908
return new AssertionNode(AT_START, on_success);
901
return new(on_success->zone()) AssertionNode(AT_START, on_success);
910
903
static AssertionNode* AtBoundary(RegExpNode* on_success) {
911
return new AssertionNode(AT_BOUNDARY, on_success);
904
return new(on_success->zone()) AssertionNode(AT_BOUNDARY, on_success);
913
906
static AssertionNode* AtNonBoundary(RegExpNode* on_success) {
914
return new AssertionNode(AT_NON_BOUNDARY, on_success);
907
return new(on_success->zone()) AssertionNode(AT_NON_BOUNDARY, on_success);
916
909
static AssertionNode* AfterNewline(RegExpNode* on_success) {
917
return new AssertionNode(AFTER_NEWLINE, on_success);
910
return new(on_success->zone()) AssertionNode(AFTER_NEWLINE, on_success);
919
912
virtual void Accept(NodeVisitor* visitor);
920
913
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
925
918
RegExpCompiler* compiler,
927
920
bool not_at_start);
928
virtual int ComputeFirstCharacterSet(int budget);
929
virtual AssertionNode* Clone() { return new AssertionNode(*this); }
921
virtual void FillInBMInfo(int offset,
924
BoyerMooreLookahead* bm,
930
926
AssertionNodeType type() { return type_; }
931
927
void set_type(AssertionNodeType type) { type_ = type; }
930
void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace);
931
enum IfPrevious { kIsNonWord, kIsWord };
932
void BacktrackIfPrevious(RegExpCompiler* compiler,
934
IfPrevious backtrack_if_previous);
934
935
AssertionNode(AssertionNodeType t, RegExpNode* on_success)
935
936
: SeqRegExpNode(on_success), type_(t) { }
936
937
AssertionNodeType type_;
1048
1062
class ChoiceNode: public RegExpNode {
1050
explicit ChoiceNode(int expected_size)
1051
: alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
1064
explicit ChoiceNode(int expected_size, Zone* zone)
1066
alternatives_(new(zone)
1067
ZoneList<GuardedAlternative>(expected_size, zone)),
1053
1069
not_at_start_(false),
1054
1070
being_calculated_(false) { }
1055
1071
virtual void Accept(NodeVisitor* visitor);
1056
void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); }
1072
void AddAlternative(GuardedAlternative node) {
1073
alternatives()->Add(node, zone());
1057
1075
ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
1058
1076
DispatchTable* GetTable(bool ignore_case);
1059
1077
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
1116
1140
RegExpCompiler* compiler,
1117
1141
int characters_filled_in,
1118
1142
bool not_at_start);
1143
virtual void FillInBMInfo(int offset,
1144
int recursion_depth,
1146
BoyerMooreLookahead* bm,
1147
bool not_at_start) {
1148
alternatives_->at(1).node()->FillInBMInfo(
1149
offset, recursion_depth + 1, budget - 1, bm, not_at_start);
1150
if (offset == 0) set_bm_info(not_at_start, bm);
1119
1152
// For a negative lookahead we don't emit the quick check for the
1120
1153
// alternative that is expected to fail. This is because quick check code
1121
1154
// starts by loading enough characters for the alternative that takes fewest
1122
1155
// characters, but on a negative lookahead the negative branch did not take
1123
1156
// part in that calculation (EatsAtLeast) so the assumptions don't hold.
1124
1157
virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; }
1125
virtual int ComputeFirstCharacterSet(int budget);
1158
virtual RegExpNode* FilterASCII(int depth);
1129
1162
class LoopChoiceNode: public ChoiceNode {
1131
explicit LoopChoiceNode(bool body_can_be_zero_length)
1164
explicit LoopChoiceNode(bool body_can_be_zero_length, Zone* zone)
1165
: ChoiceNode(2, zone),
1133
1166
loop_node_(NULL),
1134
1167
continue_node_(NULL),
1135
1168
body_can_be_zero_length_(body_can_be_zero_length) { }
1204
// Improve the speed that we scan for an initial point where a non-anchored
1205
// regexp can match by using a Boyer-Moore-like table. This is done by
1206
// identifying non-greedy non-capturing loops in the nodes that eat any
1207
// character one at a time. For example in the middle of the regexp
1208
// /foo[\s\S]*?bar/ we find such a loop. There is also such a loop implicitly
1209
// inserted at the start of any non-anchored regexp.
1211
// When we have found such a loop we look ahead in the nodes to find the set of
1212
// characters that can come at given distances. For example for the regexp
1213
// /.?foo/ we know that there are at least 3 characters ahead of us, and the
1214
// sets of characters that can occur are [any, [f, o], [o]]. We find a range in
1215
// the lookahead info where the set of characters is reasonably constrained. In
1216
// our example this is from index 1 to 2 (0 is not constrained). We can now
1217
// look 3 characters ahead and if we don't find one of [f, o] (the union of
1218
// [f, o] and [o]) then we can skip forwards by the range size (in this case 2).
1220
// For Unicode input strings we do the same, but modulo 128.
1222
// We also look at the first string fed to the regexp and use that to get a hint
1223
// of the character frequencies in the inputs. This affects the assessment of
1224
// whether the set of characters is 'reasonably constrained'.
1226
// We also have another lookahead mechanism (called quick check in the code),
1227
// which uses a wide load of multiple characters followed by a mask and compare
1228
// to determine whether a match is possible at this point.
1229
enum ContainedInLattice {
1233
kLatticeUnknown = 3 // Can also mean both in and out.
1237
inline ContainedInLattice Combine(ContainedInLattice a, ContainedInLattice b) {
1238
return static_cast<ContainedInLattice>(a | b);
1242
ContainedInLattice AddRange(ContainedInLattice a,
1245
Interval new_range);
1248
class BoyerMoorePositionInfo : public ZoneObject {
1250
explicit BoyerMoorePositionInfo(Zone* zone)
1251
: map_(new(zone) ZoneList<bool>(kMapSize, zone)),
1256
surrogate_(kNotYet) {
1257
for (int i = 0; i < kMapSize; i++) {
1258
map_->Add(false, zone);
1262
bool& at(int i) { return map_->at(i); }
1264
static const int kMapSize = 128;
1265
static const int kMask = kMapSize - 1;
1267
int map_count() const { return map_count_; }
1269
void Set(int character);
1270
void SetInterval(const Interval& interval);
1272
bool is_non_word() { return w_ == kLatticeOut; }
1273
bool is_word() { return w_ == kLatticeIn; }
1276
ZoneList<bool>* map_;
1277
int map_count_; // Number of set bits in the map.
1278
ContainedInLattice w_; // The \w character class.
1279
ContainedInLattice s_; // The \s character class.
1280
ContainedInLattice d_; // The \d character class.
1281
ContainedInLattice surrogate_; // Surrogate UTF-16 code units.
1285
class BoyerMooreLookahead : public ZoneObject {
1287
BoyerMooreLookahead(int length, RegExpCompiler* compiler, Zone* zone);
1289
int length() { return length_; }
1290
int max_char() { return max_char_; }
1291
RegExpCompiler* compiler() { return compiler_; }
1293
int Count(int map_number) {
1294
return bitmaps_->at(map_number)->map_count();
1297
BoyerMoorePositionInfo* at(int i) { return bitmaps_->at(i); }
1299
void Set(int map_number, int character) {
1300
if (character > max_char_) return;
1301
BoyerMoorePositionInfo* info = bitmaps_->at(map_number);
1302
info->Set(character);
1305
void SetInterval(int map_number, const Interval& interval) {
1306
if (interval.from() > max_char_) return;
1307
BoyerMoorePositionInfo* info = bitmaps_->at(map_number);
1308
if (interval.to() > max_char_) {
1309
info->SetInterval(Interval(interval.from(), max_char_));
1311
info->SetInterval(interval);
1315
void SetAll(int map_number) {
1316
bitmaps_->at(map_number)->SetAll();
1319
void SetRest(int from_map) {
1320
for (int i = from_map; i < length_; i++) SetAll(i);
1322
bool EmitSkipInstructions(RegExpMacroAssembler* masm);
1325
// This is the value obtained by EatsAtLeast. If we do not have at least this
1326
// many characters left in the sample string then the match is bound to fail.
1327
// Therefore it is OK to read a character this far ahead of the current match
1330
RegExpCompiler* compiler_;
1331
// 0x7f for ASCII, 0xffff for UTF-16.
1333
ZoneList<BoyerMoorePositionInfo*>* bitmaps_;
1335
int GetSkipTable(int min_lookahead,
1337
Handle<ByteArray> boolean_skip_table);
1338
bool FindWorthwhileInterval(int* from, int* to);
1339
int FindBestInterval(
1340
int max_number_of_chars, int old_biggest_points, int* from, int* to);
1167
1344
// There are many ways to generate code for a node. This class encapsulates
1168
1345
// the current way we should be generating. In other words it encapsulates
1169
1346
// the current state of the code generator. The effect of this is that we
1309
1486
void AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler);
1312
int FindAffectedRegisters(OutSet* affected_registers);
1489
int FindAffectedRegisters(OutSet* affected_registers, Zone* zone);
1313
1490
void PerformDeferredActions(RegExpMacroAssembler* macro,
1315
OutSet& affected_registers,
1316
OutSet* registers_to_pop,
1317
OutSet* registers_to_clear);
1492
OutSet& affected_registers,
1493
OutSet* registers_to_pop,
1494
OutSet* registers_to_clear,
1318
1496
void RestoreAffectedRegisters(RegExpMacroAssembler* macro,
1319
1497
int max_register,
1320
1498
OutSet& registers_to_pop,
1454
1635
static CompilationResult Compile(RegExpCompileData* input,
1455
1636
bool ignore_case,
1456
1638
bool multiline,
1457
1639
Handle<String> pattern,
1640
Handle<String> sample_subject,
1641
bool is_ascii, Zone* zone);
1460
1643
static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
1464
class OffsetsVector {
1466
explicit inline OffsetsVector(int num_registers)
1467
: offsets_vector_length_(num_registers) {
1468
if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize) {
1469
vector_ = NewArray<int>(offsets_vector_length_);
1471
vector_ = Isolate::Current()->jsregexp_static_offsets_vector();
1474
inline ~OffsetsVector() {
1475
if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize) {
1476
DeleteArray(vector_);
1480
inline int* vector() { return vector_; }
1481
inline int length() { return offsets_vector_length_; }
1483
static const int kStaticOffsetsVectorSize = 50;
1486
static Address static_offsets_vector_address(Isolate* isolate) {
1487
return reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector());
1491
int offsets_vector_length_;
1493
friend class ExternalReference;
1497
1647
} } // namespace v8::internal
1499
1649
#endif // V8_JSREGEXP_H_