~yolanda.robla/ubuntu/trusty/nodejs/add_distribution

« back to all changes in this revision

Viewing changes to deps/v8/src/jsregexp.h

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2013-08-14 00:16:46 UTC
  • mfrom: (7.1.40 sid)
  • Revision ID: package-import@ubuntu.com-20130814001646-bzlysfh8sd6mukbo
Tags: 0.10.15~dfsg1-4
* Update 2005 patch, adding a handful of tests that can fail on
  slow platforms.
* Add 1004 patch to fix test failures when writing NaN to buffer
  on mipsel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2006-2008 the V8 project authors. All rights reserved.
 
1
// Copyright 2012 the V8 project authors. All rights reserved.
2
2
// Redistribution and use in source and binary forms, with or without
3
3
// modification, are permitted provided that the following conditions are
4
4
// met:
29
29
#define V8_JSREGEXP_H_
30
30
 
31
31
#include "allocation.h"
 
32
#include "assembler.h"
32
33
#include "zone-inl.h"
33
34
 
34
35
namespace v8 {
35
36
namespace internal {
36
37
 
37
 
 
 
38
class NodeVisitor;
 
39
class RegExpCompiler;
38
40
class RegExpMacroAssembler;
39
 
 
 
41
class RegExpNode;
 
42
class RegExpTree;
 
43
class BoyerMooreLookahead;
40
44
 
41
45
class RegExpImpl {
42
46
 public:
67
71
  // Returns false if compilation fails.
68
72
  static Handle<Object> Compile(Handle<JSRegExp> re,
69
73
                                Handle<String> pattern,
70
 
                                Handle<String> flags);
 
74
                                Handle<String> flags,
 
75
                                Zone* zone);
71
76
 
72
77
  // See ECMA-262 section 15.10.6.2.
73
78
  // This function calls the garbage collector if necessary.
88
93
                          JSRegExp::Flags flags,
89
94
                          Handle<String> match_pattern);
90
95
 
 
96
 
 
97
  static int AtomExecRaw(Handle<JSRegExp> regexp,
 
98
                         Handle<String> subject,
 
99
                         int index,
 
100
                         int32_t* output,
 
101
                         int output_size);
 
102
 
 
103
 
91
104
  static Handle<Object> AtomExec(Handle<JSRegExp> regexp,
92
105
                                 Handle<String> subject,
93
106
                                 int index,
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);
107
120
 
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,
116
 
                                         int index,
117
 
                                         Vector<int> registers);
 
127
  static int IrregexpExecRaw(Handle<JSRegExp> regexp,
 
128
                             Handle<String> subject,
 
129
                             int index,
 
130
                             int32_t* output,
 
131
                             int output_size);
118
132
 
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,
125
139
                                     int index,
126
140
                                     Handle<JSArray> lastMatchInfo);
127
141
 
 
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,
 
145
                                          int capture_count,
 
146
                                          int32_t* match);
 
147
 
 
148
 
 
149
  class GlobalCache {
 
150
   public:
 
151
    GlobalCache(Handle<JSRegExp> regexp,
 
152
                Handle<String> subject,
 
153
                bool is_global,
 
154
                Isolate* isolate);
 
155
 
 
156
    ~GlobalCache();
 
157
 
 
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();
 
163
 
 
164
    int32_t* LastSuccessfulMatch();
 
165
 
 
166
    inline bool HasException() { return num_matches_ < 0; }
 
167
 
 
168
   private:
 
169
    int num_matches_;
 
170
    int max_matches_;
 
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_;
 
178
  };
 
179
 
 
180
 
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;
185
238
 
186
239
 private:
187
 
  static String* last_ascii_string_;
188
 
  static String* two_byte_cached_string_;
189
 
 
190
 
  static bool CompileIrregexp(Handle<JSRegExp> re, bool is_ascii);
191
 
  static inline bool EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii);
192
 
 
193
 
 
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,
197
 
                              char* utf8_subject,
198
 
                              int uft8_length,
199
 
                              int character_position,
200
 
                              int utf8_position);
201
 
 
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);
209
244
};
210
245
 
211
246
 
219
254
};
220
255
 
221
256
 
222
 
// Represents the relation of two sets.
223
 
// Sets can be either disjoint, partially or fully overlapping, or equal.
224
 
class SetRelation BASE_EMBEDDED {
225
 
 public:
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.
229
 
 
230
 
  // Location of an element. Corresponds to the internal areas of
231
 
  // a Venn diagram.
232
 
  enum {
233
 
    kInFirst = 1 << kInsideFirst,
234
 
    kInSecond = 1 << kInsideSecond,
235
 
    kInBoth = 1 << kInsideBoth
236
 
  };
237
 
  SetRelation() : bits_(0) {}
238
 
  ~SetRelation() {}
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
245
 
  // manually).
246
 
  // Sets are completely disjoint.
247
 
  bool Disjoint() { return (bits_ & kInBoth) == 0; }
248
 
  // Sets are equal.
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));
256
 
  }
257
 
  int value() { return bits_; }
258
 
 
259
 
 private:
260
 
  int bits_;
261
 
};
262
 
 
263
 
 
 
257
// Represents code units in the range from from_ to to_, both ends are
 
258
// inclusive.
264
259
class CharacterRange {
265
260
 public:
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,
 
266
                             Zone* zone);
 
267
  static Vector<const int> GetWordBounds();
272
268
  static inline CharacterRange Singleton(uc16 value) {
273
269
    return CharacterRange(value, value);
274
270
  }
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,
 
287
                          Zone* zone);
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,
 
292
                    Zone* zone);
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,
 
304
                     Zone* zone);
328
305
  static const int kStartMarker = (1 << 24);
329
306
  static const int kPayloadMask = (1 << 24) - 1;
330
307
 
339
316
class OutSet: public ZoneObject {
340
317
 public:
341
318
  OutSet() : first_(0), remaining_(NULL), successors_(NULL) { }
342
 
  OutSet* Extend(unsigned value);
 
319
  OutSet* Extend(unsigned value, Zone* zone);
343
320
  bool Get(unsigned value);
344
321
  static const unsigned kFirstLimit = 32;
345
322
 
347
324
  // Destructively set a value in this set.  In most cases you want
348
325
  // to use Extend instead to ensure that only one instance exists
349
326
  // that contains the same values.
350
 
  void Set(unsigned value);
 
327
  void Set(unsigned value, Zone* zone);
351
328
 
352
329
  // The successors are a list of sets that contain the same values
353
330
  // as this set and the one more value that is not present in this
354
331
  // set.
355
 
  ZoneList<OutSet*>* successors() { return successors_; }
 
332
  ZoneList<OutSet*>* successors(Zone* zone) { return successors_; }
356
333
 
357
334
  OutSet(uint32_t first, ZoneList<unsigned>* remaining)
358
335
      : first_(first), remaining_(remaining), successors_(NULL) { }
367
344
// Used for mapping character ranges to choices.
368
345
class DispatchTable : public ZoneObject {
369
346
 public:
 
347
  explicit DispatchTable(Zone* zone) : tree_(zone) { }
 
348
 
370
349
  class Entry {
371
350
   public:
372
351
    Entry() : from_(0), to_(0), out_set_(NULL) { }
375
354
    uc16 from() { return from_; }
376
355
    uc16 to() { return to_; }
377
356
    void set_to(uc16 value) { to_ = value; }
378
 
    void AddValue(int value) { out_set_ = out_set_->Extend(value); }
 
357
    void AddValue(int value, Zone* zone) {
 
358
      out_set_ = out_set_->Extend(value, zone);
 
359
    }
379
360
    OutSet* out_set() { return out_set_; }
380
361
   private:
381
362
    uc16 from_;
388
369
    typedef uc16 Key;
389
370
    typedef Entry Value;
390
371
    static const uc16 kNoKey;
391
 
    static const Entry kNoValue;
 
372
    static const Entry NoValue() { return Value(); }
392
373
    static inline int Compare(uc16 a, uc16 b) {
393
374
      if (a == b)
394
375
        return 0;
399
380
    }
400
381
  };
401
382
 
402
 
  void AddRange(CharacterRange range, int value);
 
383
  void AddRange(CharacterRange range, int value, Zone* zone);
403
384
  OutSet* Get(uc16 value);
404
385
  void Dump();
405
386
 
406
387
  template <typename Callback>
407
 
  void ForEach(Callback* callback) { return tree()->ForEach(callback); }
 
388
  void ForEach(Callback* callback) {
 
389
    return tree()->ForEach(callback);
 
390
  }
408
391
 
409
392
 private:
410
393
  // There can't be a static empty set since it allocates its
472
455
        follows_newline_interest(false),
473
456
        follows_start_interest(false),
474
457
        at_end(false),
475
 
        visited(false) { }
 
458
        visited(false),
 
459
        replacement_calculated(false) { }
476
460
 
477
461
  // Returns true if the interests and assumptions of this node
478
462
  // matches the given one.
522
506
 
523
507
  bool at_end: 1;
524
508
  bool visited: 1;
525
 
};
526
 
 
527
 
 
528
 
class SiblingList {
529
 
 public:
530
 
  SiblingList() : list_(NULL) { }
531
 
  int length() {
532
 
    return list_ == NULL ? 0 : list_->length();
533
 
  }
534
 
  void Ensure(RegExpNode* parent) {
535
 
    if (list_ == NULL) {
536
 
      list_ = new ZoneList<RegExpNode*>(2);
537
 
      list_->Add(parent);
538
 
    }
539
 
  }
540
 
  void Add(RegExpNode* node) { list_->Add(node); }
541
 
  RegExpNode* Get(int index) { return list_->at(index); }
542
 
 private:
543
 
  ZoneList<RegExpNode*>* list_;
 
509
  bool replacement_calculated: 1;
544
510
};
545
511
 
546
512
 
596
562
};
597
563
 
598
564
 
 
565
extern int kUninitializedRegExpNodePlaceHolder;
 
566
 
 
567
 
599
568
class RegExpNode: public ZoneObject {
600
569
 public:
601
 
  RegExpNode() : first_character_set_(NULL), trace_count_(0) { }
 
570
  explicit RegExpNode(Zone* zone)
 
571
  : replacement_(NULL), trace_count_(0), zone_(zone) {
 
572
    bm_info_[0] = bm_info_[1] = NULL;
 
573
  }
602
574
  virtual ~RegExpNode();
603
575
  virtual void Accept(NodeVisitor* visitor) = 0;
604
576
  // Generates a goto to this node or actually generates the code at this point.
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) {
 
611
    return NULL;
 
612
  }
 
613
 
 
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,
 
621
                            int recursion_depth,
 
622
                            int budget,
 
623
                            BoyerMooreLookahead* bm,
 
624
                            bool not_at_start) {
 
625
    UNREACHABLE();
 
626
  }
 
627
 
 
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);
 
635
    return replacement_;
 
636
  }
 
637
  RegExpNode* set_replacement(RegExpNode* replacement) {
 
638
    info()->replacement_calculated = true;
 
639
    replacement_ =  replacement;
 
640
    return replacement;  // For convenience.
 
641
  }
 
642
 
 
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);
 
649
  }
 
650
 
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
642
658
 
643
659
  NodeInfo* info() { return &info_; }
644
660
 
645
 
  void AddSibling(RegExpNode* node) { siblings_.Add(node); }
646
 
 
647
 
  // Static version of EnsureSibling that expresses the fact that the
648
 
  // result has the same type as the input.
649
 
  template <class C>
650
 
  static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) {
651
 
    return static_cast<C*>(node->EnsureSibling(info, cloned));
652
 
  }
653
 
 
654
 
  SiblingList* siblings() { return &siblings_; }
655
 
  void set_siblings(SiblingList* other) { siblings_ = *other; }
656
 
 
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();
660
 
 
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);
667
 
 
668
 
  // Get and set the cached first character set value.
669
 
  ZoneList<CharacterRange>* first_character_set() {
670
 
    return first_character_set_;
671
 
  }
672
 
  void set_first_character_set(ZoneList<CharacterRange>* character_set) {
673
 
    first_character_set_ = character_set;
674
 
  }
 
661
  BoyerMooreLookahead* bm_info(bool not_at_start) {
 
662
    return bm_info_[not_at_start ? 1 : 0];
 
663
  }
 
664
 
 
665
  Zone* zone() const { return zone_; }
675
666
 
676
667
 protected:
677
668
  enum LimitResult { DONE, CONTINUE };
678
 
  static const int kComputeFirstCharacterSetFail = -1;
 
669
  RegExpNode* replacement_;
679
670
 
680
671
  LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);
681
672
 
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
684
 
  // is returned.
685
 
  RegExpNode* TryGetSibling(NodeInfo* info);
686
 
 
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);
693
 
 
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;
 
675
  }
698
676
 
699
677
 private:
700
678
  static const int kFirstCharBudget = 10;
701
679
  Label label_;
702
680
  NodeInfo info_;
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];
 
688
 
 
689
  Zone* zone_;
711
690
};
712
691
 
713
692
 
728
707
    return (from_ <= value) && (value <= to_);
729
708
  }
730
709
  bool is_empty() { return from_ == kNone; }
731
 
  int from() { return from_; }
732
 
  int to() { return to_; }
 
710
  int from() const { return from_; }
 
711
  int to() const { return to_; }
733
712
  static Interval Empty() { return Interval(); }
734
713
  static const int kNone = -1;
735
714
 private:
741
720
class SeqRegExpNode: public RegExpNode {
742
721
 public:
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,
 
728
                            int recursion_depth,
 
729
                            int budget,
 
730
                            BoyerMooreLookahead* bm,
 
731
                            bool not_at_start) {
 
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);
 
735
  }
 
736
 
 
737
 protected:
 
738
  RegExpNode* FilterSuccessor(int depth);
 
739
 
747
740
 private:
748
741
  RegExpNode* on_success_;
749
742
};
790
783
    return on_success()->GetQuickCheckDetails(
791
784
        details, compiler, filled_in, not_at_start);
792
785
  }
 
786
  virtual void FillInBMInfo(int offset,
 
787
                            int recursion_depth,
 
788
                            int budget,
 
789
                            BoyerMooreLookahead* bm,
 
790
                            bool not_at_start);
793
791
  Type type() { return type_; }
794
792
  // TODO(erikcorry): We should allow some action nodes in greedy loops.
795
793
  virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
796
 
  virtual ActionNode* Clone() { return new ActionNode(*this); }
797
 
  virtual int ComputeFirstCharacterSet(int budget);
798
794
 
799
795
 private:
800
796
  union {
842
838
  TextNode(RegExpCharacterClass* that,
843
839
           RegExpNode* on_success)
844
840
      : SeqRegExpNode(on_success),
845
 
        elms_(new ZoneList<TextElement>(1)) {
846
 
    elms_->Add(TextElement::CharClass(that));
 
841
        elms_(new(zone()) ZoneList<TextElement>(1, zone())) {
 
842
    elms_->Add(TextElement::CharClass(that), zone());
847
843
  }
848
844
  virtual void Accept(NodeVisitor* visitor);
849
845
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
857
853
  ZoneList<TextElement>* elements() { return elms_; }
858
854
  void MakeCaseIndependent(bool is_ascii);
859
855
  virtual int GreedyLoopTextLength();
860
 
  virtual TextNode* Clone() {
861
 
    TextNode* result = new TextNode(*this);
862
 
    result->CalculateOffsets();
863
 
    return result;
864
 
  }
 
856
  virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
 
857
      RegExpCompiler* compiler);
 
858
  virtual void FillInBMInfo(int offset,
 
859
                            int recursion_depth,
 
860
                            int budget,
 
861
                            BoyerMooreLookahead* bm,
 
862
                            bool not_at_start);
865
863
  void CalculateOffsets();
866
 
  virtual int ComputeFirstCharacterSet(int budget);
 
864
  virtual RegExpNode* FilterASCII(int depth);
867
865
 
868
866
 private:
869
867
  enum TextEmitPassType {
894
892
    AT_START,
895
893
    AT_BOUNDARY,
896
894
    AT_NON_BOUNDARY,
897
 
    AFTER_NEWLINE,
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,
902
 
    AFTER_WORD_CHARACTER
 
895
    AFTER_NEWLINE
903
896
  };
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);
906
899
  }
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);
909
902
  }
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);
912
905
  }
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);
915
908
  }
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);
918
911
  }
919
912
  virtual void Accept(NodeVisitor* visitor);
920
913
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
925
918
                                    RegExpCompiler* compiler,
926
919
                                    int filled_in,
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,
 
922
                            int recursion_depth,
 
923
                            int budget,
 
924
                            BoyerMooreLookahead* bm,
 
925
                            bool not_at_start);
930
926
  AssertionNodeType type() { return type_; }
931
927
  void set_type(AssertionNodeType type) { type_ = type; }
932
928
 
933
929
 private:
 
930
  void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace);
 
931
  enum IfPrevious { kIsNonWord, kIsWord };
 
932
  void BacktrackIfPrevious(RegExpCompiler* compiler,
 
933
                           Trace* trace,
 
934
                           IfPrevious backtrack_if_previous);
934
935
  AssertionNode(AssertionNodeType t, RegExpNode* on_success)
935
936
      : SeqRegExpNode(on_success), type_(t) { }
936
937
  AssertionNodeType type_;
958
959
                                    bool not_at_start) {
959
960
    return;
960
961
  }
961
 
  virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); }
962
 
  virtual int ComputeFirstCharacterSet(int budget);
 
962
  virtual void FillInBMInfo(int offset,
 
963
                            int recursion_depth,
 
964
                            int budget,
 
965
                            BoyerMooreLookahead* bm,
 
966
                            bool not_at_start);
963
967
 
964
968
 private:
965
969
  int start_reg_;
970
974
class EndNode: public RegExpNode {
971
975
 public:
972
976
  enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
973
 
  explicit EndNode(Action action) : action_(action) { }
 
977
  explicit EndNode(Action action, Zone* zone)
 
978
      : RegExpNode(zone), action_(action) { }
974
979
  virtual void Accept(NodeVisitor* visitor);
975
980
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
976
981
  virtual int EatsAtLeast(int still_to_find,
983
988
    // Returning 0 from EatsAtLeast should ensure we never get here.
984
989
    UNREACHABLE();
985
990
  }
986
 
  virtual EndNode* Clone() { return new EndNode(*this); }
 
991
  virtual void FillInBMInfo(int offset,
 
992
                            int recursion_depth,
 
993
                            int budget,
 
994
                            BoyerMooreLookahead* bm,
 
995
                            bool not_at_start) {
 
996
    // Returning 0 from EatsAtLeast should ensure we never get here.
 
997
    UNREACHABLE();
 
998
  }
 
999
 
987
1000
 private:
988
1001
  Action action_;
989
1002
};
994
1007
  NegativeSubmatchSuccess(int stack_pointer_reg,
995
1008
                          int position_reg,
996
1009
                          int clear_capture_count,
997
 
                          int clear_capture_start)
998
 
      : EndNode(NEGATIVE_SUBMATCH_SUCCESS),
 
1010
                          int clear_capture_start,
 
1011
                          Zone* zone)
 
1012
      : EndNode(NEGATIVE_SUBMATCH_SUCCESS, zone),
999
1013
        stack_pointer_register_(stack_pointer_reg),
1000
1014
        current_position_register_(position_reg),
1001
1015
        clear_capture_count_(clear_capture_count),
1031
1045
class GuardedAlternative {
1032
1046
 public:
1033
1047
  explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) { }
1034
 
  void AddGuard(Guard* guard);
 
1048
  void AddGuard(Guard* guard, Zone* zone);
1035
1049
  RegExpNode* node() { return node_; }
1036
1050
  void set_node(RegExpNode* node) { node_ = node; }
1037
1051
  ZoneList<Guard*>* guards() { return guards_; }
1047
1061
 
1048
1062
class ChoiceNode: public RegExpNode {
1049
1063
 public:
1050
 
  explicit ChoiceNode(int expected_size)
1051
 
      : alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
 
1064
  explicit ChoiceNode(int expected_size, Zone* zone)
 
1065
      : RegExpNode(zone),
 
1066
        alternatives_(new(zone)
 
1067
                      ZoneList<GuardedAlternative>(expected_size, zone)),
1052
1068
        table_(NULL),
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());
 
1074
  }
1057
1075
  ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
1058
1076
  DispatchTable* GetTable(bool ignore_case);
1059
1077
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
1068
1086
                                    RegExpCompiler* compiler,
1069
1087
                                    int characters_filled_in,
1070
1088
                                    bool not_at_start);
1071
 
  virtual ChoiceNode* Clone() { return new ChoiceNode(*this); }
 
1089
  virtual void FillInBMInfo(int offset,
 
1090
                            int recursion_depth,
 
1091
                            int budget,
 
1092
                            BoyerMooreLookahead* bm,
 
1093
                            bool not_at_start);
1072
1094
 
1073
1095
  bool being_calculated() { return being_calculated_; }
1074
1096
  bool not_at_start() { return not_at_start_; }
1075
1097
  void set_not_at_start() { not_at_start_ = true; }
1076
1098
  void set_being_calculated(bool b) { being_calculated_ = b; }
1077
1099
  virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; }
 
1100
  virtual RegExpNode* FilterASCII(int depth);
1078
1101
 
1079
1102
 protected:
1080
1103
  int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative);
1086
1109
  void GenerateGuard(RegExpMacroAssembler* macro_assembler,
1087
1110
                     Guard* guard,
1088
1111
                     Trace* trace);
1089
 
  int CalculatePreloadCharacters(RegExpCompiler* compiler, bool not_at_start);
 
1112
  int CalculatePreloadCharacters(RegExpCompiler* compiler, int eats_at_least);
1090
1113
  void EmitOutOfLineContinuation(RegExpCompiler* compiler,
1091
1114
                                 Trace* trace,
1092
1115
                                 GuardedAlternative alternative,
1104
1127
class NegativeLookaheadChoiceNode: public ChoiceNode {
1105
1128
 public:
1106
1129
  explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail,
1107
 
                                       GuardedAlternative then_do_this)
1108
 
      : ChoiceNode(2) {
 
1130
                                       GuardedAlternative then_do_this,
 
1131
                                       Zone* zone)
 
1132
      : ChoiceNode(2, zone) {
1109
1133
    AddAlternative(this_must_fail);
1110
1134
    AddAlternative(then_do_this);
1111
1135
  }
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,
 
1145
                            int budget,
 
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);
 
1151
  }
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);
1126
1159
};
1127
1160
 
1128
1161
 
1129
1162
class LoopChoiceNode: public ChoiceNode {
1130
1163
 public:
1131
 
  explicit LoopChoiceNode(bool body_can_be_zero_length)
1132
 
      : ChoiceNode(2),
 
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) { }
1143
1176
                                    RegExpCompiler* compiler,
1144
1177
                                    int characters_filled_in,
1145
1178
                                    bool not_at_start);
1146
 
  virtual int ComputeFirstCharacterSet(int budget);
1147
 
  virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
 
1179
  virtual void FillInBMInfo(int offset,
 
1180
                            int recursion_depth,
 
1181
                            int budget,
 
1182
                            BoyerMooreLookahead* bm,
 
1183
                            bool not_at_start);
1148
1184
  RegExpNode* loop_node() { return loop_node_; }
1149
1185
  RegExpNode* continue_node() { return continue_node_; }
1150
1186
  bool body_can_be_zero_length() { return body_can_be_zero_length_; }
1151
1187
  virtual void Accept(NodeVisitor* visitor);
 
1188
  virtual RegExpNode* FilterASCII(int depth);
1152
1189
 
1153
1190
 private:
1154
1191
  // AddAlternative is made private for loop nodes because alternatives
1164
1201
};
1165
1202
 
1166
1203
 
 
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.
 
1210
//
 
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).
 
1219
//
 
1220
// For Unicode input strings we do the same, but modulo 128.
 
1221
//
 
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'.
 
1225
//
 
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 {
 
1230
  kNotYet = 0,
 
1231
  kLatticeIn = 1,
 
1232
  kLatticeOut = 2,
 
1233
  kLatticeUnknown = 3  // Can also mean both in and out.
 
1234
};
 
1235
 
 
1236
 
 
1237
inline ContainedInLattice Combine(ContainedInLattice a, ContainedInLattice b) {
 
1238
  return static_cast<ContainedInLattice>(a | b);
 
1239
}
 
1240
 
 
1241
 
 
1242
ContainedInLattice AddRange(ContainedInLattice a,
 
1243
                            const int* ranges,
 
1244
                            int ranges_size,
 
1245
                            Interval new_range);
 
1246
 
 
1247
 
 
1248
class BoyerMoorePositionInfo : public ZoneObject {
 
1249
 public:
 
1250
  explicit BoyerMoorePositionInfo(Zone* zone)
 
1251
      : map_(new(zone) ZoneList<bool>(kMapSize, zone)),
 
1252
        map_count_(0),
 
1253
        w_(kNotYet),
 
1254
        s_(kNotYet),
 
1255
        d_(kNotYet),
 
1256
        surrogate_(kNotYet) {
 
1257
     for (int i = 0; i < kMapSize; i++) {
 
1258
       map_->Add(false, zone);
 
1259
     }
 
1260
  }
 
1261
 
 
1262
  bool& at(int i) { return map_->at(i); }
 
1263
 
 
1264
  static const int kMapSize = 128;
 
1265
  static const int kMask = kMapSize - 1;
 
1266
 
 
1267
  int map_count() const { return map_count_; }
 
1268
 
 
1269
  void Set(int character);
 
1270
  void SetInterval(const Interval& interval);
 
1271
  void SetAll();
 
1272
  bool is_non_word() { return w_ == kLatticeOut; }
 
1273
  bool is_word() { return w_ == kLatticeIn; }
 
1274
 
 
1275
 private:
 
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.
 
1282
};
 
1283
 
 
1284
 
 
1285
class BoyerMooreLookahead : public ZoneObject {
 
1286
 public:
 
1287
  BoyerMooreLookahead(int length, RegExpCompiler* compiler, Zone* zone);
 
1288
 
 
1289
  int length() { return length_; }
 
1290
  int max_char() { return max_char_; }
 
1291
  RegExpCompiler* compiler() { return compiler_; }
 
1292
 
 
1293
  int Count(int map_number) {
 
1294
    return bitmaps_->at(map_number)->map_count();
 
1295
  }
 
1296
 
 
1297
  BoyerMoorePositionInfo* at(int i) { return bitmaps_->at(i); }
 
1298
 
 
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);
 
1303
  }
 
1304
 
 
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_));
 
1310
    } else {
 
1311
      info->SetInterval(interval);
 
1312
    }
 
1313
  }
 
1314
 
 
1315
  void SetAll(int map_number) {
 
1316
    bitmaps_->at(map_number)->SetAll();
 
1317
  }
 
1318
 
 
1319
  void SetRest(int from_map) {
 
1320
    for (int i = from_map; i < length_; i++) SetAll(i);
 
1321
  }
 
1322
  bool EmitSkipInstructions(RegExpMacroAssembler* masm);
 
1323
 
 
1324
 private:
 
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
 
1328
  // point.
 
1329
  int length_;
 
1330
  RegExpCompiler* compiler_;
 
1331
  // 0x7f for ASCII, 0xffff for UTF-16.
 
1332
  int max_char_;
 
1333
  ZoneList<BoyerMoorePositionInfo*>* bitmaps_;
 
1334
 
 
1335
  int GetSkipTable(int min_lookahead,
 
1336
                   int max_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);
 
1341
};
 
1342
 
 
1343
 
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);
1310
1487
 
1311
1488
 private:
1312
 
  int FindAffectedRegisters(OutSet* affected_registers);
 
1489
  int FindAffectedRegisters(OutSet* affected_registers, Zone* zone);
1313
1490
  void PerformDeferredActions(RegExpMacroAssembler* macro,
1314
 
                               int max_register,
1315
 
                               OutSet& affected_registers,
1316
 
                               OutSet* registers_to_pop,
1317
 
                               OutSet* registers_to_clear);
 
1491
                              int max_register,
 
1492
                              OutSet& affected_registers,
 
1493
                              OutSet* registers_to_pop,
 
1494
                              OutSet* registers_to_clear,
 
1495
                              Zone* zone);
1318
1496
  void RestoreAffectedRegisters(RegExpMacroAssembler* macro,
1319
1497
                                int max_register,
1320
1498
                                OutSet& registers_to_pop,
1347
1525
// dispatch table of a choice node.
1348
1526
class DispatchTableConstructor: public NodeVisitor {
1349
1527
 public:
1350
 
  DispatchTableConstructor(DispatchTable* table, bool ignore_case)
 
1528
  DispatchTableConstructor(DispatchTable* table, bool ignore_case,
 
1529
                           Zone* zone)
1351
1530
      : table_(table),
1352
1531
        choice_index_(-1),
1353
 
        ignore_case_(ignore_case) { }
 
1532
        ignore_case_(ignore_case),
 
1533
        zone_(zone) { }
1354
1534
 
1355
1535
  void BuildTable(ChoiceNode* node);
1356
1536
 
1357
1537
  void AddRange(CharacterRange range) {
1358
 
    table()->AddRange(range, choice_index_);
 
1538
    table()->AddRange(range, choice_index_, zone_);
1359
1539
  }
1360
1540
 
1361
1541
  void AddInverse(ZoneList<CharacterRange>* ranges);
1372
1552
  DispatchTable* table_;
1373
1553
  int choice_index_;
1374
1554
  bool ignore_case_;
 
1555
  Zone* zone_;
1375
1556
};
1376
1557
 
1377
1558
 
1453
1634
 
1454
1635
  static CompilationResult Compile(RegExpCompileData* input,
1455
1636
                                   bool ignore_case,
 
1637
                                   bool global,
1456
1638
                                   bool multiline,
1457
1639
                                   Handle<String> pattern,
1458
 
                                   bool is_ascii);
 
1640
                                   Handle<String> sample_subject,
 
1641
                                   bool is_ascii, Zone* zone);
1459
1642
 
1460
1643
  static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
1461
1644
};
1462
1645
 
1463
1646
 
1464
 
class OffsetsVector {
1465
 
 public:
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_);
1470
 
    } else {
1471
 
      vector_ = Isolate::Current()->jsregexp_static_offsets_vector();
1472
 
    }
1473
 
  }
1474
 
  inline ~OffsetsVector() {
1475
 
    if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize) {
1476
 
      DeleteArray(vector_);
1477
 
      vector_ = NULL;
1478
 
    }
1479
 
  }
1480
 
  inline int* vector() { return vector_; }
1481
 
  inline int length() { return offsets_vector_length_; }
1482
 
 
1483
 
  static const int kStaticOffsetsVectorSize = 50;
1484
 
 
1485
 
 private:
1486
 
  static Address static_offsets_vector_address(Isolate* isolate) {
1487
 
    return reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector());
1488
 
  }
1489
 
 
1490
 
  int* vector_;
1491
 
  int offsets_vector_length_;
1492
 
 
1493
 
  friend class ExternalReference;
1494
 
};
1495
 
 
1496
 
 
1497
1647
} }  // namespace v8::internal
1498
1648
 
1499
1649
#endif  // V8_JSREGEXP_H_