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