1 // Copyright 2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 // A simple interpreter for the Irregexp byte code.
29
30
31 #include "v8.h"
32 #include "unicode.h"
33 #include "utils.h"
34 #include "ast.h"
35 #include "bytecodes-irregexp.h"
36 #include "interpreter-irregexp.h"
37
38
39 namespace v8 {
40 namespace internal {
41
42
43 typedef unibrow::Mapping<unibrow::Ecma262Canonicalize> Canonicalize;
44
BackRefMatchesNoCase(Canonicalize * interp_canonicalize,int from,int current,int len,Vector<const uc16> subject)45 static bool BackRefMatchesNoCase(Canonicalize* interp_canonicalize,
46 int from,
47 int current,
48 int len,
49 Vector<const uc16> subject) {
50 for (int i = 0; i < len; i++) {
51 unibrow::uchar old_char = subject[from++];
52 unibrow::uchar new_char = subject[current++];
53 if (old_char == new_char) continue;
54 unibrow::uchar old_string[1] = { old_char };
55 unibrow::uchar new_string[1] = { new_char };
56 interp_canonicalize->get(old_char, '\0', old_string);
57 interp_canonicalize->get(new_char, '\0', new_string);
58 if (old_string[0] != new_string[0]) {
59 return false;
60 }
61 }
62 return true;
63 }
64
65
BackRefMatchesNoCase(Canonicalize * interp_canonicalize,int from,int current,int len,Vector<const char> subject)66 static bool BackRefMatchesNoCase(Canonicalize* interp_canonicalize,
67 int from,
68 int current,
69 int len,
70 Vector<const char> subject) {
71 for (int i = 0; i < len; i++) {
72 unsigned int old_char = subject[from++];
73 unsigned int new_char = subject[current++];
74 if (old_char == new_char) continue;
75 if (old_char - 'A' <= 'Z' - 'A') old_char |= 0x20;
76 if (new_char - 'A' <= 'Z' - 'A') new_char |= 0x20;
77 if (old_char != new_char) return false;
78 }
79 return true;
80 }
81
82
83 #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)84 static void TraceInterpreter(const byte* code_base,
85 const byte* pc,
86 int stack_depth,
87 int current_position,
88 uint32_t current_char,
89 int bytecode_length,
90 const char* bytecode_name) {
91 if (FLAG_trace_regexp_bytecodes) {
92 bool printable = (current_char < 127 && current_char >= 32);
93 const char* format =
94 printable ?
95 "pc = %02x, sp = %d, curpos = %d, curchar = %08x (%c), bc = %s" :
96 "pc = %02x, sp = %d, curpos = %d, curchar = %08x .%c., bc = %s";
97 PrintF(format,
98 pc - code_base,
99 stack_depth,
100 current_position,
101 current_char,
102 printable ? current_char : '.',
103 bytecode_name);
104 for (int i = 0; i < bytecode_length; i++) {
105 printf(", %02x", pc[i]);
106 }
107 printf(" ");
108 for (int i = 1; i < bytecode_length; i++) {
109 unsigned char b = pc[i];
110 if (b < 127 && b >= 32) {
111 printf("%c", b);
112 } else {
113 printf(".");
114 }
115 }
116 printf("\n");
117 }
118 }
119
120
121 #define BYTECODE(name) \
122 case BC_##name: \
123 TraceInterpreter(code_base, \
124 pc, \
125 static_cast<int>(backtrack_sp - backtrack_stack_base), \
126 current, \
127 current_char, \
128 BC_##name##_LENGTH, \
129 #name);
130 #else
131 #define BYTECODE(name) \
132 case BC_##name:
133 #endif
134
135
Load32Aligned(const byte * pc)136 static int32_t Load32Aligned(const byte* pc) {
137 ASSERT((reinterpret_cast<intptr_t>(pc) & 3) == 0);
138 return *reinterpret_cast<const int32_t *>(pc);
139 }
140
141
Load16Aligned(const byte * pc)142 static int32_t Load16Aligned(const byte* pc) {
143 ASSERT((reinterpret_cast<intptr_t>(pc) & 1) == 0);
144 return *reinterpret_cast<const uint16_t *>(pc);
145 }
146
147
148 // A simple abstraction over the backtracking stack used by the interpreter.
149 // This backtracking stack does not grow automatically, but it ensures that the
150 // the memory held by the stack is released or remembered in a cache if the
151 // matching terminates.
152 class BacktrackStack {
153 public:
BacktrackStack(Isolate * isolate)154 explicit BacktrackStack(Isolate* isolate) : isolate_(isolate) {
155 if (isolate->irregexp_interpreter_backtrack_stack_cache() != NULL) {
156 // If the cache is not empty reuse the previously allocated stack.
157 data_ = isolate->irregexp_interpreter_backtrack_stack_cache();
158 isolate->set_irregexp_interpreter_backtrack_stack_cache(NULL);
159 } else {
160 // Cache was empty. Allocate a new backtrack stack.
161 data_ = NewArray<int>(kBacktrackStackSize);
162 }
163 }
164
~BacktrackStack()165 ~BacktrackStack() {
166 if (isolate_->irregexp_interpreter_backtrack_stack_cache() == NULL) {
167 // The cache is empty. Keep this backtrack stack around.
168 isolate_->set_irregexp_interpreter_backtrack_stack_cache(data_);
169 } else {
170 // A backtrack stack was already cached, just release this one.
171 DeleteArray(data_);
172 }
173 }
174
data() const175 int* data() const { return data_; }
176
max_size() const177 int max_size() const { return kBacktrackStackSize; }
178
179 private:
180 static const int kBacktrackStackSize = 10000;
181
182 int* data_;
183 Isolate* isolate_;
184
185 DISALLOW_COPY_AND_ASSIGN(BacktrackStack);
186 };
187
188
189 template <typename Char>
RawMatch(Isolate * isolate,const byte * code_base,Vector<const Char> subject,int * registers,int current,uint32_t current_char)190 static bool RawMatch(Isolate* isolate,
191 const byte* code_base,
192 Vector<const Char> subject,
193 int* registers,
194 int current,
195 uint32_t current_char) {
196 const byte* pc = code_base;
197 // BacktrackStack ensures that the memory allocated for the backtracking stack
198 // is returned to the system or cached if there is no stack being cached at
199 // the moment.
200 BacktrackStack backtrack_stack(isolate);
201 int* backtrack_stack_base = backtrack_stack.data();
202 int* backtrack_sp = backtrack_stack_base;
203 int backtrack_stack_space = backtrack_stack.max_size();
204 #ifdef DEBUG
205 if (FLAG_trace_regexp_bytecodes) {
206 PrintF("\n\nStart bytecode interpreter\n\n");
207 }
208 #endif
209 while (true) {
210 int32_t insn = Load32Aligned(pc);
211 switch (insn & BYTECODE_MASK) {
212 BYTECODE(BREAK)
213 UNREACHABLE();
214 return false;
215 BYTECODE(PUSH_CP)
216 if (--backtrack_stack_space < 0) {
217 return false; // No match on backtrack stack overflow.
218 }
219 *backtrack_sp++ = current;
220 pc += BC_PUSH_CP_LENGTH;
221 break;
222 BYTECODE(PUSH_BT)
223 if (--backtrack_stack_space < 0) {
224 return false; // No match on backtrack stack overflow.
225 }
226 *backtrack_sp++ = Load32Aligned(pc + 4);
227 pc += BC_PUSH_BT_LENGTH;
228 break;
229 BYTECODE(PUSH_REGISTER)
230 if (--backtrack_stack_space < 0) {
231 return false; // No match on backtrack stack overflow.
232 }
233 *backtrack_sp++ = registers[insn >> BYTECODE_SHIFT];
234 pc += BC_PUSH_REGISTER_LENGTH;
235 break;
236 BYTECODE(SET_REGISTER)
237 registers[insn >> BYTECODE_SHIFT] = Load32Aligned(pc + 4);
238 pc += BC_SET_REGISTER_LENGTH;
239 break;
240 BYTECODE(ADVANCE_REGISTER)
241 registers[insn >> BYTECODE_SHIFT] += Load32Aligned(pc + 4);
242 pc += BC_ADVANCE_REGISTER_LENGTH;
243 break;
244 BYTECODE(SET_REGISTER_TO_CP)
245 registers[insn >> BYTECODE_SHIFT] = current + Load32Aligned(pc + 4);
246 pc += BC_SET_REGISTER_TO_CP_LENGTH;
247 break;
248 BYTECODE(SET_CP_TO_REGISTER)
249 current = registers[insn >> BYTECODE_SHIFT];
250 pc += BC_SET_CP_TO_REGISTER_LENGTH;
251 break;
252 BYTECODE(SET_REGISTER_TO_SP)
253 registers[insn >> BYTECODE_SHIFT] =
254 static_cast<int>(backtrack_sp - backtrack_stack_base);
255 pc += BC_SET_REGISTER_TO_SP_LENGTH;
256 break;
257 BYTECODE(SET_SP_TO_REGISTER)
258 backtrack_sp = backtrack_stack_base + registers[insn >> BYTECODE_SHIFT];
259 backtrack_stack_space = backtrack_stack.max_size() -
260 static_cast<int>(backtrack_sp - backtrack_stack_base);
261 pc += BC_SET_SP_TO_REGISTER_LENGTH;
262 break;
263 BYTECODE(POP_CP)
264 backtrack_stack_space++;
265 --backtrack_sp;
266 current = *backtrack_sp;
267 pc += BC_POP_CP_LENGTH;
268 break;
269 BYTECODE(POP_BT)
270 backtrack_stack_space++;
271 --backtrack_sp;
272 pc = code_base + *backtrack_sp;
273 break;
274 BYTECODE(POP_REGISTER)
275 backtrack_stack_space++;
276 --backtrack_sp;
277 registers[insn >> BYTECODE_SHIFT] = *backtrack_sp;
278 pc += BC_POP_REGISTER_LENGTH;
279 break;
280 BYTECODE(FAIL)
281 return false;
282 BYTECODE(SUCCEED)
283 return true;
284 BYTECODE(ADVANCE_CP)
285 current += insn >> BYTECODE_SHIFT;
286 pc += BC_ADVANCE_CP_LENGTH;
287 break;
288 BYTECODE(GOTO)
289 pc = code_base + Load32Aligned(pc + 4);
290 break;
291 BYTECODE(ADVANCE_CP_AND_GOTO)
292 current += insn >> BYTECODE_SHIFT;
293 pc = code_base + Load32Aligned(pc + 4);
294 break;
295 BYTECODE(CHECK_GREEDY)
296 if (current == backtrack_sp[-1]) {
297 backtrack_sp--;
298 backtrack_stack_space++;
299 pc = code_base + Load32Aligned(pc + 4);
300 } else {
301 pc += BC_CHECK_GREEDY_LENGTH;
302 }
303 break;
304 BYTECODE(LOAD_CURRENT_CHAR) {
305 int pos = current + (insn >> BYTECODE_SHIFT);
306 if (pos >= subject.length()) {
307 pc = code_base + Load32Aligned(pc + 4);
308 } else {
309 current_char = subject[pos];
310 pc += BC_LOAD_CURRENT_CHAR_LENGTH;
311 }
312 break;
313 }
314 BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
315 int pos = current + (insn >> BYTECODE_SHIFT);
316 current_char = subject[pos];
317 pc += BC_LOAD_CURRENT_CHAR_UNCHECKED_LENGTH;
318 break;
319 }
320 BYTECODE(LOAD_2_CURRENT_CHARS) {
321 int pos = current + (insn >> BYTECODE_SHIFT);
322 if (pos + 2 > subject.length()) {
323 pc = code_base + Load32Aligned(pc + 4);
324 } else {
325 Char next = subject[pos + 1];
326 current_char =
327 (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
328 pc += BC_LOAD_2_CURRENT_CHARS_LENGTH;
329 }
330 break;
331 }
332 BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
333 int pos = current + (insn >> BYTECODE_SHIFT);
334 Char next = subject[pos + 1];
335 current_char = (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
336 pc += BC_LOAD_2_CURRENT_CHARS_UNCHECKED_LENGTH;
337 break;
338 }
339 BYTECODE(LOAD_4_CURRENT_CHARS) {
340 ASSERT(sizeof(Char) == 1);
341 int pos = current + (insn >> BYTECODE_SHIFT);
342 if (pos + 4 > subject.length()) {
343 pc = code_base + Load32Aligned(pc + 4);
344 } else {
345 Char next1 = subject[pos + 1];
346 Char next2 = subject[pos + 2];
347 Char next3 = subject[pos + 3];
348 current_char = (subject[pos] |
349 (next1 << 8) |
350 (next2 << 16) |
351 (next3 << 24));
352 pc += BC_LOAD_4_CURRENT_CHARS_LENGTH;
353 }
354 break;
355 }
356 BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
357 ASSERT(sizeof(Char) == 1);
358 int pos = current + (insn >> BYTECODE_SHIFT);
359 Char next1 = subject[pos + 1];
360 Char next2 = subject[pos + 2];
361 Char next3 = subject[pos + 3];
362 current_char = (subject[pos] |
363 (next1 << 8) |
364 (next2 << 16) |
365 (next3 << 24));
366 pc += BC_LOAD_4_CURRENT_CHARS_UNCHECKED_LENGTH;
367 break;
368 }
369 BYTECODE(CHECK_4_CHARS) {
370 uint32_t c = Load32Aligned(pc + 4);
371 if (c == current_char) {
372 pc = code_base + Load32Aligned(pc + 8);
373 } else {
374 pc += BC_CHECK_4_CHARS_LENGTH;
375 }
376 break;
377 }
378 BYTECODE(CHECK_CHAR) {
379 uint32_t c = (insn >> BYTECODE_SHIFT);
380 if (c == current_char) {
381 pc = code_base + Load32Aligned(pc + 4);
382 } else {
383 pc += BC_CHECK_CHAR_LENGTH;
384 }
385 break;
386 }
387 BYTECODE(CHECK_NOT_4_CHARS) {
388 uint32_t c = Load32Aligned(pc + 4);
389 if (c != current_char) {
390 pc = code_base + Load32Aligned(pc + 8);
391 } else {
392 pc += BC_CHECK_NOT_4_CHARS_LENGTH;
393 }
394 break;
395 }
396 BYTECODE(CHECK_NOT_CHAR) {
397 uint32_t c = (insn >> BYTECODE_SHIFT);
398 if (c != current_char) {
399 pc = code_base + Load32Aligned(pc + 4);
400 } else {
401 pc += BC_CHECK_NOT_CHAR_LENGTH;
402 }
403 break;
404 }
405 BYTECODE(AND_CHECK_4_CHARS) {
406 uint32_t c = Load32Aligned(pc + 4);
407 if (c == (current_char & Load32Aligned(pc + 8))) {
408 pc = code_base + Load32Aligned(pc + 12);
409 } else {
410 pc += BC_AND_CHECK_4_CHARS_LENGTH;
411 }
412 break;
413 }
414 BYTECODE(AND_CHECK_CHAR) {
415 uint32_t c = (insn >> BYTECODE_SHIFT);
416 if (c == (current_char & Load32Aligned(pc + 4))) {
417 pc = code_base + Load32Aligned(pc + 8);
418 } else {
419 pc += BC_AND_CHECK_CHAR_LENGTH;
420 }
421 break;
422 }
423 BYTECODE(AND_CHECK_NOT_4_CHARS) {
424 uint32_t c = Load32Aligned(pc + 4);
425 if (c != (current_char & Load32Aligned(pc + 8))) {
426 pc = code_base + Load32Aligned(pc + 12);
427 } else {
428 pc += BC_AND_CHECK_NOT_4_CHARS_LENGTH;
429 }
430 break;
431 }
432 BYTECODE(AND_CHECK_NOT_CHAR) {
433 uint32_t c = (insn >> BYTECODE_SHIFT);
434 if (c != (current_char & Load32Aligned(pc + 4))) {
435 pc = code_base + Load32Aligned(pc + 8);
436 } else {
437 pc += BC_AND_CHECK_NOT_CHAR_LENGTH;
438 }
439 break;
440 }
441 BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
442 uint32_t c = (insn >> BYTECODE_SHIFT);
443 uint32_t minus = Load16Aligned(pc + 4);
444 uint32_t mask = Load16Aligned(pc + 6);
445 if (c != ((current_char - minus) & mask)) {
446 pc = code_base + Load32Aligned(pc + 8);
447 } else {
448 pc += BC_MINUS_AND_CHECK_NOT_CHAR_LENGTH;
449 }
450 break;
451 }
452 BYTECODE(CHECK_LT) {
453 uint32_t limit = (insn >> BYTECODE_SHIFT);
454 if (current_char < limit) {
455 pc = code_base + Load32Aligned(pc + 4);
456 } else {
457 pc += BC_CHECK_LT_LENGTH;
458 }
459 break;
460 }
461 BYTECODE(CHECK_GT) {
462 uint32_t limit = (insn >> BYTECODE_SHIFT);
463 if (current_char > limit) {
464 pc = code_base + Load32Aligned(pc + 4);
465 } else {
466 pc += BC_CHECK_GT_LENGTH;
467 }
468 break;
469 }
470 BYTECODE(CHECK_REGISTER_LT)
471 if (registers[insn >> BYTECODE_SHIFT] < Load32Aligned(pc + 4)) {
472 pc = code_base + Load32Aligned(pc + 8);
473 } else {
474 pc += BC_CHECK_REGISTER_LT_LENGTH;
475 }
476 break;
477 BYTECODE(CHECK_REGISTER_GE)
478 if (registers[insn >> BYTECODE_SHIFT] >= Load32Aligned(pc + 4)) {
479 pc = code_base + Load32Aligned(pc + 8);
480 } else {
481 pc += BC_CHECK_REGISTER_GE_LENGTH;
482 }
483 break;
484 BYTECODE(CHECK_REGISTER_EQ_POS)
485 if (registers[insn >> BYTECODE_SHIFT] == current) {
486 pc = code_base + Load32Aligned(pc + 4);
487 } else {
488 pc += BC_CHECK_REGISTER_EQ_POS_LENGTH;
489 }
490 break;
491 BYTECODE(LOOKUP_MAP1) {
492 // Look up character in a bitmap. If we find a 0, then jump to the
493 // location at pc + 8. Otherwise fall through!
494 int index = current_char - (insn >> BYTECODE_SHIFT);
495 byte map = code_base[Load32Aligned(pc + 4) + (index >> 3)];
496 map = ((map >> (index & 7)) & 1);
497 if (map == 0) {
498 pc = code_base + Load32Aligned(pc + 8);
499 } else {
500 pc += BC_LOOKUP_MAP1_LENGTH;
501 }
502 break;
503 }
504 BYTECODE(LOOKUP_MAP2) {
505 // Look up character in a half-nibble map. If we find 00, then jump to
506 // the location at pc + 8. If we find 01 then jump to location at
507 // pc + 11, etc.
508 int index = (current_char - (insn >> BYTECODE_SHIFT)) << 1;
509 byte map = code_base[Load32Aligned(pc + 3) + (index >> 3)];
510 map = ((map >> (index & 7)) & 3);
511 if (map < 2) {
512 if (map == 0) {
513 pc = code_base + Load32Aligned(pc + 8);
514 } else {
515 pc = code_base + Load32Aligned(pc + 12);
516 }
517 } else {
518 if (map == 2) {
519 pc = code_base + Load32Aligned(pc + 16);
520 } else {
521 pc = code_base + Load32Aligned(pc + 20);
522 }
523 }
524 break;
525 }
526 BYTECODE(LOOKUP_MAP8) {
527 // Look up character in a byte map. Use the byte as an index into a
528 // table that follows this instruction immediately.
529 int index = current_char - (insn >> BYTECODE_SHIFT);
530 byte map = code_base[Load32Aligned(pc + 4) + index];
531 const byte* new_pc = code_base + Load32Aligned(pc + 8) + (map << 2);
532 pc = code_base + Load32Aligned(new_pc);
533 break;
534 }
535 BYTECODE(LOOKUP_HI_MAP8) {
536 // Look up high byte of this character in a byte map. Use the byte as
537 // an index into a table that follows this instruction immediately.
538 int index = (current_char >> 8) - (insn >> BYTECODE_SHIFT);
539 byte map = code_base[Load32Aligned(pc + 4) + index];
540 const byte* new_pc = code_base + Load32Aligned(pc + 8) + (map << 2);
541 pc = code_base + Load32Aligned(new_pc);
542 break;
543 }
544 BYTECODE(CHECK_NOT_REGS_EQUAL)
545 if (registers[insn >> BYTECODE_SHIFT] ==
546 registers[Load32Aligned(pc + 4)]) {
547 pc += BC_CHECK_NOT_REGS_EQUAL_LENGTH;
548 } else {
549 pc = code_base + Load32Aligned(pc + 8);
550 }
551 break;
552 BYTECODE(CHECK_NOT_BACK_REF) {
553 int from = registers[insn >> BYTECODE_SHIFT];
554 int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
555 if (from < 0 || len <= 0) {
556 pc += BC_CHECK_NOT_BACK_REF_LENGTH;
557 break;
558 }
559 if (current + len > subject.length()) {
560 pc = code_base + Load32Aligned(pc + 4);
561 break;
562 } else {
563 int i;
564 for (i = 0; i < len; i++) {
565 if (subject[from + i] != subject[current + i]) {
566 pc = code_base + Load32Aligned(pc + 4);
567 break;
568 }
569 }
570 if (i < len) break;
571 current += len;
572 }
573 pc += BC_CHECK_NOT_BACK_REF_LENGTH;
574 break;
575 }
576 BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
577 int from = registers[insn >> BYTECODE_SHIFT];
578 int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
579 if (from < 0 || len <= 0) {
580 pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
581 break;
582 }
583 if (current + len > subject.length()) {
584 pc = code_base + Load32Aligned(pc + 4);
585 break;
586 } else {
587 if (BackRefMatchesNoCase(isolate->interp_canonicalize_mapping(),
588 from, current, len, subject)) {
589 current += len;
590 pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
591 } else {
592 pc = code_base + Load32Aligned(pc + 4);
593 }
594 }
595 break;
596 }
597 BYTECODE(CHECK_AT_START)
598 if (current == 0) {
599 pc = code_base + Load32Aligned(pc + 4);
600 } else {
601 pc += BC_CHECK_AT_START_LENGTH;
602 }
603 break;
604 BYTECODE(CHECK_NOT_AT_START)
605 if (current == 0) {
606 pc += BC_CHECK_NOT_AT_START_LENGTH;
607 } else {
608 pc = code_base + Load32Aligned(pc + 4);
609 }
610 break;
611 BYTECODE(SET_CURRENT_POSITION_FROM_END) {
612 int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
613 if (subject.length() - current > by) {
614 current = subject.length() - by;
615 current_char = subject[current - 1];
616 }
617 pc += BC_SET_CURRENT_POSITION_FROM_END_LENGTH;
618 break;
619 }
620 default:
621 UNREACHABLE();
622 break;
623 }
624 }
625 }
626
627
Match(Isolate * isolate,Handle<ByteArray> code_array,Handle<String> subject,int * registers,int start_position)628 bool IrregexpInterpreter::Match(Isolate* isolate,
629 Handle<ByteArray> code_array,
630 Handle<String> subject,
631 int* registers,
632 int start_position) {
633 ASSERT(subject->IsFlat());
634
635 AssertNoAllocation a;
636 const byte* code_base = code_array->GetDataStartAddress();
637 uc16 previous_char = '\n';
638 if (subject->IsAsciiRepresentation()) {
639 Vector<const char> subject_vector = subject->ToAsciiVector();
640 if (start_position != 0) previous_char = subject_vector[start_position - 1];
641 return RawMatch(isolate,
642 code_base,
643 subject_vector,
644 registers,
645 start_position,
646 previous_char);
647 } else {
648 Vector<const uc16> subject_vector = subject->ToUC16Vector();
649 if (start_position != 0) previous_char = subject_vector[start_position - 1];
650 return RawMatch(isolate,
651 code_base,
652 subject_vector,
653 registers,
654 start_position,
655 previous_char);
656 }
657 }
658
659 } } // namespace v8::internal
660