• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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