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