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_INTL_SUPPORT
20 #include "unicode/uchar.h"
21 #endif  // V8_INTL_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_EQ(0, reinterpret_cast<intptr_t>(pc) & 3);
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_EQ(0, reinterpret_cast<intptr_t>(pc) & 1);
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       BYTECODE(PUSH_CP)
179         if (--backtrack_stack_space < 0) {
180           return RegExpImpl::RE_EXCEPTION;
181         }
182         *backtrack_sp++ = current;
183         pc += BC_PUSH_CP_LENGTH;
184         break;
185       BYTECODE(PUSH_BT)
186         if (--backtrack_stack_space < 0) {
187           return RegExpImpl::RE_EXCEPTION;
188         }
189         *backtrack_sp++ = Load32Aligned(pc + 4);
190         pc += BC_PUSH_BT_LENGTH;
191         break;
192       BYTECODE(PUSH_REGISTER)
193         if (--backtrack_stack_space < 0) {
194           return RegExpImpl::RE_EXCEPTION;
195         }
196         *backtrack_sp++ = registers[insn >> BYTECODE_SHIFT];
197         pc += BC_PUSH_REGISTER_LENGTH;
198         break;
199       BYTECODE(SET_REGISTER)
200         registers[insn >> BYTECODE_SHIFT] = Load32Aligned(pc + 4);
201         pc += BC_SET_REGISTER_LENGTH;
202         break;
203       BYTECODE(ADVANCE_REGISTER)
204         registers[insn >> BYTECODE_SHIFT] += Load32Aligned(pc + 4);
205         pc += BC_ADVANCE_REGISTER_LENGTH;
206         break;
207       BYTECODE(SET_REGISTER_TO_CP)
208         registers[insn >> BYTECODE_SHIFT] = current + Load32Aligned(pc + 4);
209         pc += BC_SET_REGISTER_TO_CP_LENGTH;
210         break;
211       BYTECODE(SET_CP_TO_REGISTER)
212         current = registers[insn >> BYTECODE_SHIFT];
213         pc += BC_SET_CP_TO_REGISTER_LENGTH;
214         break;
215       BYTECODE(SET_REGISTER_TO_SP)
216         registers[insn >> BYTECODE_SHIFT] =
217             static_cast<int>(backtrack_sp - backtrack_stack_base);
218         pc += BC_SET_REGISTER_TO_SP_LENGTH;
219         break;
220       BYTECODE(SET_SP_TO_REGISTER)
221         backtrack_sp = backtrack_stack_base + registers[insn >> BYTECODE_SHIFT];
222         backtrack_stack_space = backtrack_stack.max_size() -
223             static_cast<int>(backtrack_sp - backtrack_stack_base);
224         pc += BC_SET_SP_TO_REGISTER_LENGTH;
225         break;
226       BYTECODE(POP_CP)
227         backtrack_stack_space++;
228         --backtrack_sp;
229         current = *backtrack_sp;
230         pc += BC_POP_CP_LENGTH;
231         break;
232       BYTECODE(POP_BT)
233         backtrack_stack_space++;
234         --backtrack_sp;
235         pc = code_base + *backtrack_sp;
236         break;
237       BYTECODE(POP_REGISTER)
238         backtrack_stack_space++;
239         --backtrack_sp;
240         registers[insn >> BYTECODE_SHIFT] = *backtrack_sp;
241         pc += BC_POP_REGISTER_LENGTH;
242         break;
243       BYTECODE(FAIL)
244         return RegExpImpl::RE_FAILURE;
245       BYTECODE(SUCCEED)
246         return RegExpImpl::RE_SUCCESS;
247       BYTECODE(ADVANCE_CP)
248         current += insn >> BYTECODE_SHIFT;
249         pc += BC_ADVANCE_CP_LENGTH;
250         break;
251       BYTECODE(GOTO)
252         pc = code_base + Load32Aligned(pc + 4);
253         break;
254       BYTECODE(ADVANCE_CP_AND_GOTO)
255         current += insn >> BYTECODE_SHIFT;
256         pc = code_base + Load32Aligned(pc + 4);
257         break;
258       BYTECODE(CHECK_GREEDY)
259         if (current == backtrack_sp[-1]) {
260           backtrack_sp--;
261           backtrack_stack_space++;
262           pc = code_base + Load32Aligned(pc + 4);
263         } else {
264           pc += BC_CHECK_GREEDY_LENGTH;
265         }
266         break;
267       BYTECODE(LOAD_CURRENT_CHAR) {
268         int pos = current + (insn >> BYTECODE_SHIFT);
269         if (pos >= subject.length() || pos < 0) {
270           pc = code_base + Load32Aligned(pc + 4);
271         } else {
272           current_char = subject[pos];
273           pc += BC_LOAD_CURRENT_CHAR_LENGTH;
274         }
275         break;
276       }
277       BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
278         int pos = current + (insn >> BYTECODE_SHIFT);
279         current_char = subject[pos];
280         pc += BC_LOAD_CURRENT_CHAR_UNCHECKED_LENGTH;
281         break;
282       }
283       BYTECODE(LOAD_2_CURRENT_CHARS) {
284         int pos = current + (insn >> BYTECODE_SHIFT);
285         if (pos + 2 > subject.length() || pos < 0) {
286           pc = code_base + Load32Aligned(pc + 4);
287         } else {
288           Char next = subject[pos + 1];
289           current_char =
290               (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
291           pc += BC_LOAD_2_CURRENT_CHARS_LENGTH;
292         }
293         break;
294       }
295       BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
296         int pos = current + (insn >> BYTECODE_SHIFT);
297         Char next = subject[pos + 1];
298         current_char = (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
299         pc += BC_LOAD_2_CURRENT_CHARS_UNCHECKED_LENGTH;
300         break;
301       }
302       BYTECODE(LOAD_4_CURRENT_CHARS) {
303         DCHECK_EQ(1, sizeof(Char));
304         int pos = current + (insn >> BYTECODE_SHIFT);
305         if (pos + 4 > subject.length() || pos < 0) {
306           pc = code_base + Load32Aligned(pc + 4);
307         } else {
308           Char next1 = subject[pos + 1];
309           Char next2 = subject[pos + 2];
310           Char next3 = subject[pos + 3];
311           current_char = (subject[pos] |
312                           (next1 << 8) |
313                           (next2 << 16) |
314                           (next3 << 24));
315           pc += BC_LOAD_4_CURRENT_CHARS_LENGTH;
316         }
317         break;
318       }
319       BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
320         DCHECK_EQ(1, sizeof(Char));
321         int pos = current + (insn >> BYTECODE_SHIFT);
322         Char next1 = subject[pos + 1];
323         Char next2 = subject[pos + 2];
324         Char next3 = subject[pos + 3];
325         current_char = (subject[pos] |
326                         (next1 << 8) |
327                         (next2 << 16) |
328                         (next3 << 24));
329         pc += BC_LOAD_4_CURRENT_CHARS_UNCHECKED_LENGTH;
330         break;
331       }
332       BYTECODE(CHECK_4_CHARS) {
333         uint32_t c = Load32Aligned(pc + 4);
334         if (c == current_char) {
335           pc = code_base + Load32Aligned(pc + 8);
336         } else {
337           pc += BC_CHECK_4_CHARS_LENGTH;
338         }
339         break;
340       }
341       BYTECODE(CHECK_CHAR) {
342         uint32_t c = (insn >> BYTECODE_SHIFT);
343         if (c == current_char) {
344           pc = code_base + Load32Aligned(pc + 4);
345         } else {
346           pc += BC_CHECK_CHAR_LENGTH;
347         }
348         break;
349       }
350       BYTECODE(CHECK_NOT_4_CHARS) {
351         uint32_t c = Load32Aligned(pc + 4);
352         if (c != current_char) {
353           pc = code_base + Load32Aligned(pc + 8);
354         } else {
355           pc += BC_CHECK_NOT_4_CHARS_LENGTH;
356         }
357         break;
358       }
359       BYTECODE(CHECK_NOT_CHAR) {
360         uint32_t c = (insn >> BYTECODE_SHIFT);
361         if (c != current_char) {
362           pc = code_base + Load32Aligned(pc + 4);
363         } else {
364           pc += BC_CHECK_NOT_CHAR_LENGTH;
365         }
366         break;
367       }
368       BYTECODE(AND_CHECK_4_CHARS) {
369         uint32_t c = Load32Aligned(pc + 4);
370         if (c == (current_char & Load32Aligned(pc + 8))) {
371           pc = code_base + Load32Aligned(pc + 12);
372         } else {
373           pc += BC_AND_CHECK_4_CHARS_LENGTH;
374         }
375         break;
376       }
377       BYTECODE(AND_CHECK_CHAR) {
378         uint32_t c = (insn >> BYTECODE_SHIFT);
379         if (c == (current_char & Load32Aligned(pc + 4))) {
380           pc = code_base + Load32Aligned(pc + 8);
381         } else {
382           pc += BC_AND_CHECK_CHAR_LENGTH;
383         }
384         break;
385       }
386       BYTECODE(AND_CHECK_NOT_4_CHARS) {
387         uint32_t c = Load32Aligned(pc + 4);
388         if (c != (current_char & Load32Aligned(pc + 8))) {
389           pc = code_base + Load32Aligned(pc + 12);
390         } else {
391           pc += BC_AND_CHECK_NOT_4_CHARS_LENGTH;
392         }
393         break;
394       }
395       BYTECODE(AND_CHECK_NOT_CHAR) {
396         uint32_t c = (insn >> BYTECODE_SHIFT);
397         if (c != (current_char & Load32Aligned(pc + 4))) {
398           pc = code_base + Load32Aligned(pc + 8);
399         } else {
400           pc += BC_AND_CHECK_NOT_CHAR_LENGTH;
401         }
402         break;
403       }
404       BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
405         uint32_t c = (insn >> BYTECODE_SHIFT);
406         uint32_t minus = Load16Aligned(pc + 4);
407         uint32_t mask = Load16Aligned(pc + 6);
408         if (c != ((current_char - minus) & mask)) {
409           pc = code_base + Load32Aligned(pc + 8);
410         } else {
411           pc += BC_MINUS_AND_CHECK_NOT_CHAR_LENGTH;
412         }
413         break;
414       }
415       BYTECODE(CHECK_CHAR_IN_RANGE) {
416         uint32_t from = Load16Aligned(pc + 4);
417         uint32_t to = Load16Aligned(pc + 6);
418         if (from <= current_char && current_char <= to) {
419           pc = code_base + Load32Aligned(pc + 8);
420         } else {
421           pc += BC_CHECK_CHAR_IN_RANGE_LENGTH;
422         }
423         break;
424       }
425       BYTECODE(CHECK_CHAR_NOT_IN_RANGE) {
426         uint32_t from = Load16Aligned(pc + 4);
427         uint32_t to = Load16Aligned(pc + 6);
428         if (from > current_char || current_char > to) {
429           pc = code_base + Load32Aligned(pc + 8);
430         } else {
431           pc += BC_CHECK_CHAR_NOT_IN_RANGE_LENGTH;
432         }
433         break;
434       }
435       BYTECODE(CHECK_BIT_IN_TABLE) {
436         int mask = RegExpMacroAssembler::kTableMask;
437         byte b = pc[8 + ((current_char & mask) >> kBitsPerByteLog2)];
438         int bit = (current_char & (kBitsPerByte - 1));
439         if ((b & (1 << bit)) != 0) {
440           pc = code_base + Load32Aligned(pc + 4);
441         } else {
442           pc += BC_CHECK_BIT_IN_TABLE_LENGTH;
443         }
444         break;
445       }
446       BYTECODE(CHECK_LT) {
447         uint32_t limit = (insn >> BYTECODE_SHIFT);
448         if (current_char < limit) {
449           pc = code_base + Load32Aligned(pc + 4);
450         } else {
451           pc += BC_CHECK_LT_LENGTH;
452         }
453         break;
454       }
455       BYTECODE(CHECK_GT) {
456         uint32_t limit = (insn >> BYTECODE_SHIFT);
457         if (current_char > limit) {
458           pc = code_base + Load32Aligned(pc + 4);
459         } else {
460           pc += BC_CHECK_GT_LENGTH;
461         }
462         break;
463       }
464       BYTECODE(CHECK_REGISTER_LT)
465         if (registers[insn >> BYTECODE_SHIFT] < Load32Aligned(pc + 4)) {
466           pc = code_base + Load32Aligned(pc + 8);
467         } else {
468           pc += BC_CHECK_REGISTER_LT_LENGTH;
469         }
470         break;
471       BYTECODE(CHECK_REGISTER_GE)
472         if (registers[insn >> BYTECODE_SHIFT] >= Load32Aligned(pc + 4)) {
473           pc = code_base + Load32Aligned(pc + 8);
474         } else {
475           pc += BC_CHECK_REGISTER_GE_LENGTH;
476         }
477         break;
478       BYTECODE(CHECK_REGISTER_EQ_POS)
479         if (registers[insn >> BYTECODE_SHIFT] == current) {
480           pc = code_base + Load32Aligned(pc + 4);
481         } else {
482           pc += BC_CHECK_REGISTER_EQ_POS_LENGTH;
483         }
484         break;
485       BYTECODE(CHECK_NOT_REGS_EQUAL)
486         if (registers[insn >> BYTECODE_SHIFT] ==
487             registers[Load32Aligned(pc + 4)]) {
488           pc += BC_CHECK_NOT_REGS_EQUAL_LENGTH;
489         } else {
490           pc = code_base + Load32Aligned(pc + 8);
491         }
492         break;
493       BYTECODE(CHECK_NOT_BACK_REF) {
494         int from = registers[insn >> BYTECODE_SHIFT];
495         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
496         if (from >= 0 && len > 0) {
497           if (current + len > subject.length() ||
498               CompareChars(&subject[from], &subject[current], len) != 0) {
499             pc = code_base + Load32Aligned(pc + 4);
500             break;
501           }
502           current += len;
503         }
504         pc += BC_CHECK_NOT_BACK_REF_LENGTH;
505         break;
506       }
507       BYTECODE(CHECK_NOT_BACK_REF_BACKWARD) {
508         int from = registers[insn >> BYTECODE_SHIFT];
509         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
510         if (from >= 0 && len > 0) {
511           if (current - len < 0 ||
512               CompareChars(&subject[from], &subject[current - len], len) != 0) {
513             pc = code_base + Load32Aligned(pc + 4);
514             break;
515           }
516           current -= len;
517         }
518         pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
519         break;
520       }
521       BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE)
522       V8_FALLTHROUGH;
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       V8_FALLTHROUGH;
542       BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) {
543         bool unicode = (insn & BYTECODE_MASK) ==
544                        BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD;
545         int from = registers[insn >> BYTECODE_SHIFT];
546         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
547         if (from >= 0 && len > 0) {
548           if (current - len < 0 ||
549               !BackRefMatchesNoCase(isolate, from, current - len, len, subject,
550                                     unicode)) {
551             pc = code_base + Load32Aligned(pc + 4);
552             break;
553           }
554           current -= len;
555         }
556         pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
557         break;
558       }
559       BYTECODE(CHECK_AT_START)
560         if (current == 0) {
561           pc = code_base + Load32Aligned(pc + 4);
562         } else {
563           pc += BC_CHECK_AT_START_LENGTH;
564         }
565         break;
566       BYTECODE(CHECK_NOT_AT_START)
567         if (current + (insn >> BYTECODE_SHIFT) == 0) {
568           pc += BC_CHECK_NOT_AT_START_LENGTH;
569         } else {
570           pc = code_base + Load32Aligned(pc + 4);
571         }
572         break;
573       BYTECODE(SET_CURRENT_POSITION_FROM_END) {
574         int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
575         if (subject.length() - current > by) {
576           current = subject.length() - by;
577           current_char = subject[current - 1];
578         }
579         pc += BC_SET_CURRENT_POSITION_FROM_END_LENGTH;
580         break;
581       }
582       default:
583         UNREACHABLE();
584         break;
585     }
586   }
587 }
588 
589 
Match(Isolate * isolate,Handle<ByteArray> code_array,Handle<String> subject,int * registers,int start_position)590 RegExpImpl::IrregexpResult IrregexpInterpreter::Match(
591     Isolate* isolate,
592     Handle<ByteArray> code_array,
593     Handle<String> subject,
594     int* registers,
595     int start_position) {
596   DCHECK(subject->IsFlat());
597 
598   DisallowHeapAllocation no_gc;
599   const byte* code_base = code_array->GetDataStartAddress();
600   uc16 previous_char = '\n';
601   String::FlatContent subject_content = subject->GetFlatContent();
602   if (subject_content.IsOneByte()) {
603     Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
604     if (start_position != 0) previous_char = subject_vector[start_position - 1];
605     return RawMatch(isolate,
606                     code_base,
607                     subject_vector,
608                     registers,
609                     start_position,
610                     previous_char);
611   } else {
612     DCHECK(subject_content.IsTwoByte());
613     Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
614     if (start_position != 0) previous_char = subject_vector[start_position - 1];
615     return RawMatch(isolate,
616                     code_base,
617                     subject_vector,
618                     registers,
619                     start_position,
620                     previous_char);
621   }
622 }
623 
624 }  // namespace internal
625 }  // namespace v8
626 
627 #endif  // V8_INTERPRETED_REGEXP
628