• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 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 // A simple interpreter for the Irregexp byte code.
6 
7 #ifdef V8_INTERPRETED_REGEXP
8 
9 #include "src/regexp/interpreter-irregexp.h"
10 
11 #include "src/ast/ast.h"
12 #include "src/objects-inl.h"
13 #include "src/regexp/bytecodes-irregexp.h"
14 #include "src/regexp/jsregexp.h"
15 #include "src/regexp/regexp-macro-assembler.h"
16 #include "src/unicode.h"
17 #include "src/utils.h"
18 
19 #ifdef V8_I18N_SUPPORT
20 #include "unicode/uchar.h"
21 #endif  // V8_I18N_SUPPORT
22 
23 namespace v8 {
24 namespace internal {
25 
26 typedef unibrow::Mapping<unibrow::Ecma262Canonicalize> Canonicalize;
27 
BackRefMatchesNoCase(Isolate * isolate,int from,int current,int len,Vector<const uc16> subject,bool unicode)28 static bool BackRefMatchesNoCase(Isolate* isolate, int from, int current,
29                                  int len, Vector<const uc16> subject,
30                                  bool unicode) {
31   Address offset_a =
32       reinterpret_cast<Address>(const_cast<uc16*>(&subject.at(from)));
33   Address offset_b =
34       reinterpret_cast<Address>(const_cast<uc16*>(&subject.at(current)));
35   size_t length = len * kUC16Size;
36   return RegExpMacroAssembler::CaseInsensitiveCompareUC16(
37              offset_a, offset_b, length, unicode ? nullptr : isolate) == 1;
38 }
39 
40 
BackRefMatchesNoCase(Isolate * isolate,int from,int current,int len,Vector<const uint8_t> subject,bool unicode)41 static bool BackRefMatchesNoCase(Isolate* isolate, int from, int current,
42                                  int len, Vector<const uint8_t> subject,
43                                  bool unicode) {
44   // For Latin1 characters the unicode flag makes no difference.
45   for (int i = 0; i < len; i++) {
46     unsigned int old_char = subject[from++];
47     unsigned int new_char = subject[current++];
48     if (old_char == new_char) continue;
49     // Convert both characters to lower case.
50     old_char |= 0x20;
51     new_char |= 0x20;
52     if (old_char != new_char) return false;
53     // Not letters in the ASCII range and Latin-1 range.
54     if (!(old_char - 'a' <= 'z' - 'a') &&
55         !(old_char - 224 <= 254 - 224 && old_char != 247)) {
56       return false;
57     }
58   }
59   return true;
60 }
61 
62 
63 #ifdef DEBUG
TraceInterpreter(const byte * code_base,const byte * pc,int stack_depth,int current_position,uint32_t current_char,int bytecode_length,const char * bytecode_name)64 static void TraceInterpreter(const byte* code_base,
65                              const byte* pc,
66                              int stack_depth,
67                              int current_position,
68                              uint32_t current_char,
69                              int bytecode_length,
70                              const char* bytecode_name) {
71   if (FLAG_trace_regexp_bytecodes) {
72     bool printable = (current_char < 127 && current_char >= 32);
73     const char* format =
74         printable ?
75         "pc = %02x, sp = %d, curpos = %d, curchar = %08x (%c), bc = %s" :
76         "pc = %02x, sp = %d, curpos = %d, curchar = %08x .%c., bc = %s";
77     PrintF(format,
78            pc - code_base,
79            stack_depth,
80            current_position,
81            current_char,
82            printable ? current_char : '.',
83            bytecode_name);
84     for (int i = 0; i < bytecode_length; i++) {
85       printf(", %02x", pc[i]);
86     }
87     printf(" ");
88     for (int i = 1; i < bytecode_length; i++) {
89       unsigned char b = pc[i];
90       if (b < 127 && b >= 32) {
91         printf("%c", b);
92       } else {
93         printf(".");
94       }
95     }
96     printf("\n");
97   }
98 }
99 
100 
101 #define BYTECODE(name)                                                      \
102   case BC_##name:                                                           \
103     TraceInterpreter(code_base,                                             \
104                      pc,                                                    \
105                      static_cast<int>(backtrack_sp - backtrack_stack_base), \
106                      current,                                               \
107                      current_char,                                          \
108                      BC_##name##_LENGTH,                                    \
109                      #name);
110 #else
111 #define BYTECODE(name)                                                      \
112   case BC_##name:
113 #endif
114 
115 
Load32Aligned(const byte * pc)116 static int32_t Load32Aligned(const byte* pc) {
117   DCHECK((reinterpret_cast<intptr_t>(pc) & 3) == 0);
118   return *reinterpret_cast<const int32_t *>(pc);
119 }
120 
121 
Load16Aligned(const byte * pc)122 static int32_t Load16Aligned(const byte* pc) {
123   DCHECK((reinterpret_cast<intptr_t>(pc) & 1) == 0);
124   return *reinterpret_cast<const uint16_t *>(pc);
125 }
126 
127 
128 // A simple abstraction over the backtracking stack used by the interpreter.
129 // This backtracking stack does not grow automatically, but it ensures that the
130 // the memory held by the stack is released or remembered in a cache if the
131 // matching terminates.
132 class BacktrackStack {
133  public:
BacktrackStack()134   BacktrackStack() { data_ = NewArray<int>(kBacktrackStackSize); }
135 
~BacktrackStack()136   ~BacktrackStack() {
137     DeleteArray(data_);
138   }
139 
data() const140   int* data() const { return data_; }
141 
max_size() const142   int max_size() const { return kBacktrackStackSize; }
143 
144  private:
145   static const int kBacktrackStackSize = 10000;
146 
147   int* data_;
148 
149   DISALLOW_COPY_AND_ASSIGN(BacktrackStack);
150 };
151 
152 
153 template <typename Char>
RawMatch(Isolate * isolate,const byte * code_base,Vector<const Char> subject,int * registers,int current,uint32_t current_char)154 static RegExpImpl::IrregexpResult RawMatch(Isolate* isolate,
155                                            const byte* code_base,
156                                            Vector<const Char> subject,
157                                            int* registers,
158                                            int current,
159                                            uint32_t current_char) {
160   const byte* pc = code_base;
161   // BacktrackStack ensures that the memory allocated for the backtracking stack
162   // is returned to the system or cached if there is no stack being cached at
163   // the moment.
164   BacktrackStack backtrack_stack;
165   int* backtrack_stack_base = backtrack_stack.data();
166   int* backtrack_sp = backtrack_stack_base;
167   int backtrack_stack_space = backtrack_stack.max_size();
168 #ifdef DEBUG
169   if (FLAG_trace_regexp_bytecodes) {
170     PrintF("\n\nStart bytecode interpreter\n\n");
171   }
172 #endif
173   while (true) {
174     int32_t insn = Load32Aligned(pc);
175     switch (insn & BYTECODE_MASK) {
176       BYTECODE(BREAK)
177         UNREACHABLE();
178         return RegExpImpl::RE_FAILURE;
179       BYTECODE(PUSH_CP)
180         if (--backtrack_stack_space < 0) {
181           return RegExpImpl::RE_EXCEPTION;
182         }
183         *backtrack_sp++ = current;
184         pc += BC_PUSH_CP_LENGTH;
185         break;
186       BYTECODE(PUSH_BT)
187         if (--backtrack_stack_space < 0) {
188           return RegExpImpl::RE_EXCEPTION;
189         }
190         *backtrack_sp++ = Load32Aligned(pc + 4);
191         pc += BC_PUSH_BT_LENGTH;
192         break;
193       BYTECODE(PUSH_REGISTER)
194         if (--backtrack_stack_space < 0) {
195           return RegExpImpl::RE_EXCEPTION;
196         }
197         *backtrack_sp++ = registers[insn >> BYTECODE_SHIFT];
198         pc += BC_PUSH_REGISTER_LENGTH;
199         break;
200       BYTECODE(SET_REGISTER)
201         registers[insn >> BYTECODE_SHIFT] = Load32Aligned(pc + 4);
202         pc += BC_SET_REGISTER_LENGTH;
203         break;
204       BYTECODE(ADVANCE_REGISTER)
205         registers[insn >> BYTECODE_SHIFT] += Load32Aligned(pc + 4);
206         pc += BC_ADVANCE_REGISTER_LENGTH;
207         break;
208       BYTECODE(SET_REGISTER_TO_CP)
209         registers[insn >> BYTECODE_SHIFT] = current + Load32Aligned(pc + 4);
210         pc += BC_SET_REGISTER_TO_CP_LENGTH;
211         break;
212       BYTECODE(SET_CP_TO_REGISTER)
213         current = registers[insn >> BYTECODE_SHIFT];
214         pc += BC_SET_CP_TO_REGISTER_LENGTH;
215         break;
216       BYTECODE(SET_REGISTER_TO_SP)
217         registers[insn >> BYTECODE_SHIFT] =
218             static_cast<int>(backtrack_sp - backtrack_stack_base);
219         pc += BC_SET_REGISTER_TO_SP_LENGTH;
220         break;
221       BYTECODE(SET_SP_TO_REGISTER)
222         backtrack_sp = backtrack_stack_base + registers[insn >> BYTECODE_SHIFT];
223         backtrack_stack_space = backtrack_stack.max_size() -
224             static_cast<int>(backtrack_sp - backtrack_stack_base);
225         pc += BC_SET_SP_TO_REGISTER_LENGTH;
226         break;
227       BYTECODE(POP_CP)
228         backtrack_stack_space++;
229         --backtrack_sp;
230         current = *backtrack_sp;
231         pc += BC_POP_CP_LENGTH;
232         break;
233       BYTECODE(POP_BT)
234         backtrack_stack_space++;
235         --backtrack_sp;
236         pc = code_base + *backtrack_sp;
237         break;
238       BYTECODE(POP_REGISTER)
239         backtrack_stack_space++;
240         --backtrack_sp;
241         registers[insn >> BYTECODE_SHIFT] = *backtrack_sp;
242         pc += BC_POP_REGISTER_LENGTH;
243         break;
244       BYTECODE(FAIL)
245         return RegExpImpl::RE_FAILURE;
246       BYTECODE(SUCCEED)
247         return RegExpImpl::RE_SUCCESS;
248       BYTECODE(ADVANCE_CP)
249         current += insn >> BYTECODE_SHIFT;
250         pc += BC_ADVANCE_CP_LENGTH;
251         break;
252       BYTECODE(GOTO)
253         pc = code_base + Load32Aligned(pc + 4);
254         break;
255       BYTECODE(ADVANCE_CP_AND_GOTO)
256         current += insn >> BYTECODE_SHIFT;
257         pc = code_base + Load32Aligned(pc + 4);
258         break;
259       BYTECODE(CHECK_GREEDY)
260         if (current == backtrack_sp[-1]) {
261           backtrack_sp--;
262           backtrack_stack_space++;
263           pc = code_base + Load32Aligned(pc + 4);
264         } else {
265           pc += BC_CHECK_GREEDY_LENGTH;
266         }
267         break;
268       BYTECODE(LOAD_CURRENT_CHAR) {
269         int pos = current + (insn >> BYTECODE_SHIFT);
270         if (pos >= subject.length() || pos < 0) {
271           pc = code_base + Load32Aligned(pc + 4);
272         } else {
273           current_char = subject[pos];
274           pc += BC_LOAD_CURRENT_CHAR_LENGTH;
275         }
276         break;
277       }
278       BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
279         int pos = current + (insn >> BYTECODE_SHIFT);
280         current_char = subject[pos];
281         pc += BC_LOAD_CURRENT_CHAR_UNCHECKED_LENGTH;
282         break;
283       }
284       BYTECODE(LOAD_2_CURRENT_CHARS) {
285         int pos = current + (insn >> BYTECODE_SHIFT);
286         if (pos + 2 > subject.length() || pos < 0) {
287           pc = code_base + Load32Aligned(pc + 4);
288         } else {
289           Char next = subject[pos + 1];
290           current_char =
291               (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
292           pc += BC_LOAD_2_CURRENT_CHARS_LENGTH;
293         }
294         break;
295       }
296       BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
297         int pos = current + (insn >> BYTECODE_SHIFT);
298         Char next = subject[pos + 1];
299         current_char = (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
300         pc += BC_LOAD_2_CURRENT_CHARS_UNCHECKED_LENGTH;
301         break;
302       }
303       BYTECODE(LOAD_4_CURRENT_CHARS) {
304         DCHECK(sizeof(Char) == 1);
305         int pos = current + (insn >> BYTECODE_SHIFT);
306         if (pos + 4 > subject.length() || pos < 0) {
307           pc = code_base + Load32Aligned(pc + 4);
308         } else {
309           Char next1 = subject[pos + 1];
310           Char next2 = subject[pos + 2];
311           Char next3 = subject[pos + 3];
312           current_char = (subject[pos] |
313                           (next1 << 8) |
314                           (next2 << 16) |
315                           (next3 << 24));
316           pc += BC_LOAD_4_CURRENT_CHARS_LENGTH;
317         }
318         break;
319       }
320       BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
321         DCHECK(sizeof(Char) == 1);
322         int pos = current + (insn >> BYTECODE_SHIFT);
323         Char next1 = subject[pos + 1];
324         Char next2 = subject[pos + 2];
325         Char next3 = subject[pos + 3];
326         current_char = (subject[pos] |
327                         (next1 << 8) |
328                         (next2 << 16) |
329                         (next3 << 24));
330         pc += BC_LOAD_4_CURRENT_CHARS_UNCHECKED_LENGTH;
331         break;
332       }
333       BYTECODE(CHECK_4_CHARS) {
334         uint32_t c = Load32Aligned(pc + 4);
335         if (c == current_char) {
336           pc = code_base + Load32Aligned(pc + 8);
337         } else {
338           pc += BC_CHECK_4_CHARS_LENGTH;
339         }
340         break;
341       }
342       BYTECODE(CHECK_CHAR) {
343         uint32_t c = (insn >> BYTECODE_SHIFT);
344         if (c == current_char) {
345           pc = code_base + Load32Aligned(pc + 4);
346         } else {
347           pc += BC_CHECK_CHAR_LENGTH;
348         }
349         break;
350       }
351       BYTECODE(CHECK_NOT_4_CHARS) {
352         uint32_t c = Load32Aligned(pc + 4);
353         if (c != current_char) {
354           pc = code_base + Load32Aligned(pc + 8);
355         } else {
356           pc += BC_CHECK_NOT_4_CHARS_LENGTH;
357         }
358         break;
359       }
360       BYTECODE(CHECK_NOT_CHAR) {
361         uint32_t c = (insn >> BYTECODE_SHIFT);
362         if (c != current_char) {
363           pc = code_base + Load32Aligned(pc + 4);
364         } else {
365           pc += BC_CHECK_NOT_CHAR_LENGTH;
366         }
367         break;
368       }
369       BYTECODE(AND_CHECK_4_CHARS) {
370         uint32_t c = Load32Aligned(pc + 4);
371         if (c == (current_char & Load32Aligned(pc + 8))) {
372           pc = code_base + Load32Aligned(pc + 12);
373         } else {
374           pc += BC_AND_CHECK_4_CHARS_LENGTH;
375         }
376         break;
377       }
378       BYTECODE(AND_CHECK_CHAR) {
379         uint32_t c = (insn >> BYTECODE_SHIFT);
380         if (c == (current_char & Load32Aligned(pc + 4))) {
381           pc = code_base + Load32Aligned(pc + 8);
382         } else {
383           pc += BC_AND_CHECK_CHAR_LENGTH;
384         }
385         break;
386       }
387       BYTECODE(AND_CHECK_NOT_4_CHARS) {
388         uint32_t c = Load32Aligned(pc + 4);
389         if (c != (current_char & Load32Aligned(pc + 8))) {
390           pc = code_base + Load32Aligned(pc + 12);
391         } else {
392           pc += BC_AND_CHECK_NOT_4_CHARS_LENGTH;
393         }
394         break;
395       }
396       BYTECODE(AND_CHECK_NOT_CHAR) {
397         uint32_t c = (insn >> BYTECODE_SHIFT);
398         if (c != (current_char & Load32Aligned(pc + 4))) {
399           pc = code_base + Load32Aligned(pc + 8);
400         } else {
401           pc += BC_AND_CHECK_NOT_CHAR_LENGTH;
402         }
403         break;
404       }
405       BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
406         uint32_t c = (insn >> BYTECODE_SHIFT);
407         uint32_t minus = Load16Aligned(pc + 4);
408         uint32_t mask = Load16Aligned(pc + 6);
409         if (c != ((current_char - minus) & mask)) {
410           pc = code_base + Load32Aligned(pc + 8);
411         } else {
412           pc += BC_MINUS_AND_CHECK_NOT_CHAR_LENGTH;
413         }
414         break;
415       }
416       BYTECODE(CHECK_CHAR_IN_RANGE) {
417         uint32_t from = Load16Aligned(pc + 4);
418         uint32_t to = Load16Aligned(pc + 6);
419         if (from <= current_char && current_char <= to) {
420           pc = code_base + Load32Aligned(pc + 8);
421         } else {
422           pc += BC_CHECK_CHAR_IN_RANGE_LENGTH;
423         }
424         break;
425       }
426       BYTECODE(CHECK_CHAR_NOT_IN_RANGE) {
427         uint32_t from = Load16Aligned(pc + 4);
428         uint32_t to = Load16Aligned(pc + 6);
429         if (from > current_char || current_char > to) {
430           pc = code_base + Load32Aligned(pc + 8);
431         } else {
432           pc += BC_CHECK_CHAR_NOT_IN_RANGE_LENGTH;
433         }
434         break;
435       }
436       BYTECODE(CHECK_BIT_IN_TABLE) {
437         int mask = RegExpMacroAssembler::kTableMask;
438         byte b = pc[8 + ((current_char & mask) >> kBitsPerByteLog2)];
439         int bit = (current_char & (kBitsPerByte - 1));
440         if ((b & (1 << bit)) != 0) {
441           pc = code_base + Load32Aligned(pc + 4);
442         } else {
443           pc += BC_CHECK_BIT_IN_TABLE_LENGTH;
444         }
445         break;
446       }
447       BYTECODE(CHECK_LT) {
448         uint32_t limit = (insn >> BYTECODE_SHIFT);
449         if (current_char < limit) {
450           pc = code_base + Load32Aligned(pc + 4);
451         } else {
452           pc += BC_CHECK_LT_LENGTH;
453         }
454         break;
455       }
456       BYTECODE(CHECK_GT) {
457         uint32_t limit = (insn >> BYTECODE_SHIFT);
458         if (current_char > limit) {
459           pc = code_base + Load32Aligned(pc + 4);
460         } else {
461           pc += BC_CHECK_GT_LENGTH;
462         }
463         break;
464       }
465       BYTECODE(CHECK_REGISTER_LT)
466         if (registers[insn >> BYTECODE_SHIFT] < Load32Aligned(pc + 4)) {
467           pc = code_base + Load32Aligned(pc + 8);
468         } else {
469           pc += BC_CHECK_REGISTER_LT_LENGTH;
470         }
471         break;
472       BYTECODE(CHECK_REGISTER_GE)
473         if (registers[insn >> BYTECODE_SHIFT] >= Load32Aligned(pc + 4)) {
474           pc = code_base + Load32Aligned(pc + 8);
475         } else {
476           pc += BC_CHECK_REGISTER_GE_LENGTH;
477         }
478         break;
479       BYTECODE(CHECK_REGISTER_EQ_POS)
480         if (registers[insn >> BYTECODE_SHIFT] == current) {
481           pc = code_base + Load32Aligned(pc + 4);
482         } else {
483           pc += BC_CHECK_REGISTER_EQ_POS_LENGTH;
484         }
485         break;
486       BYTECODE(CHECK_NOT_REGS_EQUAL)
487         if (registers[insn >> BYTECODE_SHIFT] ==
488             registers[Load32Aligned(pc + 4)]) {
489           pc += BC_CHECK_NOT_REGS_EQUAL_LENGTH;
490         } else {
491           pc = code_base + Load32Aligned(pc + 8);
492         }
493         break;
494       BYTECODE(CHECK_NOT_BACK_REF) {
495         int from = registers[insn >> BYTECODE_SHIFT];
496         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
497         if (from >= 0 && len > 0) {
498           if (current + len > subject.length() ||
499               CompareChars(&subject[from], &subject[current], len) != 0) {
500             pc = code_base + Load32Aligned(pc + 4);
501             break;
502           }
503           current += len;
504         }
505         pc += BC_CHECK_NOT_BACK_REF_LENGTH;
506         break;
507       }
508       BYTECODE(CHECK_NOT_BACK_REF_BACKWARD) {
509         int from = registers[insn >> BYTECODE_SHIFT];
510         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
511         if (from >= 0 && len > 0) {
512           if (current - len < 0 ||
513               CompareChars(&subject[from], &subject[current - len], len) != 0) {
514             pc = code_base + Load32Aligned(pc + 4);
515             break;
516           }
517           current -= len;
518         }
519         pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
520         break;
521       }
522       BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE)
523       BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
524         bool unicode =
525             (insn & BYTECODE_MASK) == BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE;
526         int from = registers[insn >> BYTECODE_SHIFT];
527         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
528         if (from >= 0 && len > 0) {
529           if (current + len > subject.length() ||
530               !BackRefMatchesNoCase(isolate, from, current, len, subject,
531                                     unicode)) {
532             pc = code_base + Load32Aligned(pc + 4);
533             break;
534           }
535           current += len;
536         }
537         pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
538         break;
539       }
540       BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD)
541       BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) {
542         bool unicode = (insn & BYTECODE_MASK) ==
543                        BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD;
544         int from = registers[insn >> BYTECODE_SHIFT];
545         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
546         if (from >= 0 && len > 0) {
547           if (current - len < 0 ||
548               !BackRefMatchesNoCase(isolate, from, current - len, len, subject,
549                                     unicode)) {
550             pc = code_base + Load32Aligned(pc + 4);
551             break;
552           }
553           current -= len;
554         }
555         pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
556         break;
557       }
558       BYTECODE(CHECK_AT_START)
559         if (current == 0) {
560           pc = code_base + Load32Aligned(pc + 4);
561         } else {
562           pc += BC_CHECK_AT_START_LENGTH;
563         }
564         break;
565       BYTECODE(CHECK_NOT_AT_START)
566         if (current + (insn >> BYTECODE_SHIFT) == 0) {
567           pc += BC_CHECK_NOT_AT_START_LENGTH;
568         } else {
569           pc = code_base + Load32Aligned(pc + 4);
570         }
571         break;
572       BYTECODE(SET_CURRENT_POSITION_FROM_END) {
573         int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
574         if (subject.length() - current > by) {
575           current = subject.length() - by;
576           current_char = subject[current - 1];
577         }
578         pc += BC_SET_CURRENT_POSITION_FROM_END_LENGTH;
579         break;
580       }
581       default:
582         UNREACHABLE();
583         break;
584     }
585   }
586 }
587 
588 
Match(Isolate * isolate,Handle<ByteArray> code_array,Handle<String> subject,int * registers,int start_position)589 RegExpImpl::IrregexpResult IrregexpInterpreter::Match(
590     Isolate* isolate,
591     Handle<ByteArray> code_array,
592     Handle<String> subject,
593     int* registers,
594     int start_position) {
595   DCHECK(subject->IsFlat());
596 
597   DisallowHeapAllocation no_gc;
598   const byte* code_base = code_array->GetDataStartAddress();
599   uc16 previous_char = '\n';
600   String::FlatContent subject_content = subject->GetFlatContent();
601   if (subject_content.IsOneByte()) {
602     Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
603     if (start_position != 0) previous_char = subject_vector[start_position - 1];
604     return RawMatch(isolate,
605                     code_base,
606                     subject_vector,
607                     registers,
608                     start_position,
609                     previous_char);
610   } else {
611     DCHECK(subject_content.IsTwoByte());
612     Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
613     if (start_position != 0) previous_char = subject_vector[start_position - 1];
614     return RawMatch(isolate,
615                     code_base,
616                     subject_vector,
617                     registers,
618                     start_position,
619                     previous_char);
620   }
621 }
622 
623 }  // namespace internal
624 }  // namespace v8
625 
626 #endif  // V8_INTERPRETED_REGEXP
627