1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 
6 #ifndef V8_REGEXP_JSREGEXP_INL_H_
7 #define V8_REGEXP_JSREGEXP_INL_H_
8 
9 #include "src/allocation.h"
10 #include "src/handles.h"
11 #include "src/heap/heap.h"
12 #include "src/objects.h"
13 #include "src/regexp/jsregexp.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 
~GlobalCache()19 RegExpImpl::GlobalCache::~GlobalCache() {
20   // Deallocate the register array if we allocated it in the constructor
21   // (as opposed to using the existing jsregexp_static_offsets_vector).
22   if (register_array_size_ > Isolate::kJSRegexpStaticOffsetsVectorSize) {
23     DeleteArray(register_array_);
24   }
25 }
26 
27 
FetchNext()28 int32_t* RegExpImpl::GlobalCache::FetchNext() {
29   current_match_index_++;
30   if (current_match_index_ >= num_matches_) {
31     // Current batch of results exhausted.
32     // Fail if last batch was not even fully filled.
33     if (num_matches_ < max_matches_) {
34       num_matches_ = 0;  // Signal failed match.
35       return NULL;
36     }
37 
38     int32_t* last_match =
39         &register_array_[(current_match_index_ - 1) * registers_per_match_];
40     int last_end_index = last_match[1];
41 
42     if (regexp_->TypeTag() == JSRegExp::ATOM) {
43       num_matches_ = RegExpImpl::AtomExecRaw(regexp_,
44                                              subject_,
45                                              last_end_index,
46                                              register_array_,
47                                              register_array_size_);
48     } else {
49       int last_start_index = last_match[0];
50       if (last_start_index == last_end_index) {
51         // Zero-length match. Advance by one code point.
52         last_end_index = AdvanceZeroLength(last_end_index);
53       }
54       if (last_end_index > subject_->length()) {
55         num_matches_ = 0;  // Signal failed match.
56         return NULL;
57       }
58       num_matches_ = RegExpImpl::IrregexpExecRaw(regexp_,
59                                                  subject_,
60                                                  last_end_index,
61                                                  register_array_,
62                                                  register_array_size_);
63     }
64 
65     if (num_matches_ <= 0) return NULL;
66     current_match_index_ = 0;
67     return register_array_;
68   } else {
69     return &register_array_[current_match_index_ * registers_per_match_];
70   }
71 }
72 
73 
LastSuccessfulMatch()74 int32_t* RegExpImpl::GlobalCache::LastSuccessfulMatch() {
75   int index = current_match_index_ * registers_per_match_;
76   if (num_matches_ == 0) {
77     // After a failed match we shift back by one result.
78     index -= registers_per_match_;
79   }
80   return &register_array_[index];
81 }
82 
83 
84 }  // namespace internal
85 }  // namespace v8
86 
87 #endif  // V8_REGEXP_JSREGEXP_INL_H_
88