Home | History | Annotate | Download | only in src
      1 // Copyright 2011 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 #include "jsregexp.h"
     38 #include "regexp-macro-assembler.h"
     39 
     40 namespace v8 {
     41 namespace internal {
     42 
     43 
     44 typedef unibrow::Mapping<unibrow::Ecma262Canonicalize> Canonicalize;
     45 
     46 static bool BackRefMatchesNoCase(Canonicalize* interp_canonicalize,
     47                                  int from,
     48                                  int current,
     49                                  int len,
     50                                  Vector<const uc16> subject) {
     51   for (int i = 0; i < len; i++) {
     52     unibrow::uchar old_char = subject[from++];
     53     unibrow::uchar new_char = subject[current++];
     54     if (old_char == new_char) continue;
     55     unibrow::uchar old_string[1] = { old_char };
     56     unibrow::uchar new_string[1] = { new_char };
     57     interp_canonicalize->get(old_char, '\0', old_string);
     58     interp_canonicalize->get(new_char, '\0', new_string);
     59     if (old_string[0] != new_string[0]) {
     60       return false;
     61     }
     62   }
     63   return true;
     64 }
     65 
     66 
     67 static bool BackRefMatchesNoCase(Canonicalize* interp_canonicalize,
     68                                  int from,
     69                                  int current,
     70                                  int len,
     71                                  Vector<const uint8_t> subject) {
     72   for (int i = 0; i < len; i++) {
     73     unsigned int old_char = subject[from++];
     74     unsigned int new_char = subject[current++];
     75     if (old_char == new_char) continue;
     76     // Convert both characters to lower case.
     77     old_char |= 0x20;
     78     new_char |= 0x20;
     79     if (old_char != new_char) return false;
     80     // Not letters in the ASCII range and Latin-1 range.
     81     if (!(old_char - 'a' <= 'z' - 'a') &&
     82         !(old_char - 224 <= 254 - 224 && old_char != 247)) {
     83       return false;
     84     }
     85   }
     86   return true;
     87 }
     88 
     89 
     90 #ifdef DEBUG
     91 static void TraceInterpreter(const byte* code_base,
     92                              const byte* pc,
     93                              int stack_depth,
     94                              int current_position,
     95                              uint32_t current_char,
     96                              int bytecode_length,
     97                              const char* bytecode_name) {
     98   if (FLAG_trace_regexp_bytecodes) {
     99     bool printable = (current_char < 127 && current_char >= 32);
    100     const char* format =
    101         printable ?
    102         "pc = %02x, sp = %d, curpos = %d, curchar = %08x (%c), bc = %s" :
    103         "pc = %02x, sp = %d, curpos = %d, curchar = %08x .%c., bc = %s";
    104     PrintF(format,
    105            pc - code_base,
    106            stack_depth,
    107            current_position,
    108            current_char,
    109            printable ? current_char : '.',
    110            bytecode_name);
    111     for (int i = 0; i < bytecode_length; i++) {
    112       printf(", %02x", pc[i]);
    113     }
    114     printf(" ");
    115     for (int i = 1; i < bytecode_length; i++) {
    116       unsigned char b = pc[i];
    117       if (b < 127 && b >= 32) {
    118         printf("%c", b);
    119       } else {
    120         printf(".");
    121       }
    122     }
    123     printf("\n");
    124   }
    125 }
    126 
    127 
    128 #define BYTECODE(name)                                                      \
    129   case BC_##name:                                                           \
    130     TraceInterpreter(code_base,                                             \
    131                      pc,                                                    \
    132                      static_cast<int>(backtrack_sp - backtrack_stack_base), \
    133                      current,                                               \
    134                      current_char,                                          \
    135                      BC_##name##_LENGTH,                                    \
    136                      #name);
    137 #else
    138 #define BYTECODE(name)                                                      \
    139   case BC_##name:
    140 #endif
    141 
    142 
    143 static int32_t Load32Aligned(const byte* pc) {
    144   ASSERT((reinterpret_cast<intptr_t>(pc) & 3) == 0);
    145   return *reinterpret_cast<const int32_t *>(pc);
    146 }
    147 
    148 
    149 static int32_t Load16Aligned(const byte* pc) {
    150   ASSERT((reinterpret_cast<intptr_t>(pc) & 1) == 0);
    151   return *reinterpret_cast<const uint16_t *>(pc);
    152 }
    153 
    154 
    155 // A simple abstraction over the backtracking stack used by the interpreter.
    156 // This backtracking stack does not grow automatically, but it ensures that the
    157 // the memory held by the stack is released or remembered in a cache if the
    158 // matching terminates.
    159 class BacktrackStack {
    160  public:
    161   explicit BacktrackStack(Isolate* isolate) : isolate_(isolate) {
    162     if (isolate->irregexp_interpreter_backtrack_stack_cache() != NULL) {
    163       // If the cache is not empty reuse the previously allocated stack.
    164       data_ = isolate->irregexp_interpreter_backtrack_stack_cache();
    165       isolate->set_irregexp_interpreter_backtrack_stack_cache(NULL);
    166     } else {
    167       // Cache was empty. Allocate a new backtrack stack.
    168       data_ = NewArray<int>(kBacktrackStackSize);
    169     }
    170   }
    171 
    172   ~BacktrackStack() {
    173     if (isolate_->irregexp_interpreter_backtrack_stack_cache() == NULL) {
    174       // The cache is empty. Keep this backtrack stack around.
    175       isolate_->set_irregexp_interpreter_backtrack_stack_cache(data_);
    176     } else {
    177       // A backtrack stack was already cached, just release this one.
    178       DeleteArray(data_);
    179     }
    180   }
    181 
    182   int* data() const { return data_; }
    183 
    184   int max_size() const { return kBacktrackStackSize; }
    185 
    186  private:
    187   static const int kBacktrackStackSize = 10000;
    188 
    189   int* data_;
    190   Isolate* isolate_;
    191 
    192   DISALLOW_COPY_AND_ASSIGN(BacktrackStack);
    193 };
    194 
    195 
    196 template <typename Char>
    197 static RegExpImpl::IrregexpResult RawMatch(Isolate* isolate,
    198                                            const byte* code_base,
    199                                            Vector<const Char> subject,
    200                                            int* registers,
    201                                            int current,
    202                                            uint32_t current_char) {
    203   const byte* pc = code_base;
    204   // BacktrackStack ensures that the memory allocated for the backtracking stack
    205   // is returned to the system or cached if there is no stack being cached at
    206   // the moment.
    207   BacktrackStack backtrack_stack(isolate);
    208   int* backtrack_stack_base = backtrack_stack.data();
    209   int* backtrack_sp = backtrack_stack_base;
    210   int backtrack_stack_space = backtrack_stack.max_size();
    211 #ifdef DEBUG
    212   if (FLAG_trace_regexp_bytecodes) {
    213     PrintF("\n\nStart bytecode interpreter\n\n");
    214   }
    215 #endif
    216   while (true) {
    217     int32_t insn = Load32Aligned(pc);
    218     switch (insn & BYTECODE_MASK) {
    219       BYTECODE(BREAK)
    220         UNREACHABLE();
    221         return RegExpImpl::RE_FAILURE;
    222       BYTECODE(PUSH_CP)
    223         if (--backtrack_stack_space < 0) {
    224           return RegExpImpl::RE_EXCEPTION;
    225         }
    226         *backtrack_sp++ = current;
    227         pc += BC_PUSH_CP_LENGTH;
    228         break;
    229       BYTECODE(PUSH_BT)
    230         if (--backtrack_stack_space < 0) {
    231           return RegExpImpl::RE_EXCEPTION;
    232         }
    233         *backtrack_sp++ = Load32Aligned(pc + 4);
    234         pc += BC_PUSH_BT_LENGTH;
    235         break;
    236       BYTECODE(PUSH_REGISTER)
    237         if (--backtrack_stack_space < 0) {
    238           return RegExpImpl::RE_EXCEPTION;
    239         }
    240         *backtrack_sp++ = registers[insn >> BYTECODE_SHIFT];
    241         pc += BC_PUSH_REGISTER_LENGTH;
    242         break;
    243       BYTECODE(SET_REGISTER)
    244         registers[insn >> BYTECODE_SHIFT] = Load32Aligned(pc + 4);
    245         pc += BC_SET_REGISTER_LENGTH;
    246         break;
    247       BYTECODE(ADVANCE_REGISTER)
    248         registers[insn >> BYTECODE_SHIFT] += Load32Aligned(pc + 4);
    249         pc += BC_ADVANCE_REGISTER_LENGTH;
    250         break;
    251       BYTECODE(SET_REGISTER_TO_CP)
    252         registers[insn >> BYTECODE_SHIFT] = current + Load32Aligned(pc + 4);
    253         pc += BC_SET_REGISTER_TO_CP_LENGTH;
    254         break;
    255       BYTECODE(SET_CP_TO_REGISTER)
    256         current = registers[insn >> BYTECODE_SHIFT];
    257         pc += BC_SET_CP_TO_REGISTER_LENGTH;
    258         break;
    259       BYTECODE(SET_REGISTER_TO_SP)
    260         registers[insn >> BYTECODE_SHIFT] =
    261             static_cast<int>(backtrack_sp - backtrack_stack_base);
    262         pc += BC_SET_REGISTER_TO_SP_LENGTH;
    263         break;
    264       BYTECODE(SET_SP_TO_REGISTER)
    265         backtrack_sp = backtrack_stack_base + registers[insn >> BYTECODE_SHIFT];
    266         backtrack_stack_space = backtrack_stack.max_size() -
    267             static_cast<int>(backtrack_sp - backtrack_stack_base);
    268         pc += BC_SET_SP_TO_REGISTER_LENGTH;
    269         break;
    270       BYTECODE(POP_CP)
    271         backtrack_stack_space++;
    272         --backtrack_sp;
    273         current = *backtrack_sp;
    274         pc += BC_POP_CP_LENGTH;
    275         break;
    276       BYTECODE(POP_BT)
    277         backtrack_stack_space++;
    278         --backtrack_sp;
    279         pc = code_base + *backtrack_sp;
    280         break;
    281       BYTECODE(POP_REGISTER)
    282         backtrack_stack_space++;
    283         --backtrack_sp;
    284         registers[insn >> BYTECODE_SHIFT] = *backtrack_sp;
    285         pc += BC_POP_REGISTER_LENGTH;
    286         break;
    287       BYTECODE(FAIL)
    288         return RegExpImpl::RE_FAILURE;
    289       BYTECODE(SUCCEED)
    290         return RegExpImpl::RE_SUCCESS;
    291       BYTECODE(ADVANCE_CP)
    292         current += insn >> BYTECODE_SHIFT;
    293         pc += BC_ADVANCE_CP_LENGTH;
    294         break;
    295       BYTECODE(GOTO)
    296         pc = code_base + Load32Aligned(pc + 4);
    297         break;
    298       BYTECODE(ADVANCE_CP_AND_GOTO)
    299         current += insn >> BYTECODE_SHIFT;
    300         pc = code_base + Load32Aligned(pc + 4);
    301         break;
    302       BYTECODE(CHECK_GREEDY)
    303         if (current == backtrack_sp[-1]) {
    304           backtrack_sp--;
    305           backtrack_stack_space++;
    306           pc = code_base + Load32Aligned(pc + 4);
    307         } else {
    308           pc += BC_CHECK_GREEDY_LENGTH;
    309         }
    310         break;
    311       BYTECODE(LOAD_CURRENT_CHAR) {
    312         int pos = current + (insn >> BYTECODE_SHIFT);
    313         if (pos >= subject.length()) {
    314           pc = code_base + Load32Aligned(pc + 4);
    315         } else {
    316           current_char = subject[pos];
    317           pc += BC_LOAD_CURRENT_CHAR_LENGTH;
    318         }
    319         break;
    320       }
    321       BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
    322         int pos = current + (insn >> BYTECODE_SHIFT);
    323         current_char = subject[pos];
    324         pc += BC_LOAD_CURRENT_CHAR_UNCHECKED_LENGTH;
    325         break;
    326       }
    327       BYTECODE(LOAD_2_CURRENT_CHARS) {
    328         int pos = current + (insn >> BYTECODE_SHIFT);
    329         if (pos + 2 > subject.length()) {
    330           pc = code_base + Load32Aligned(pc + 4);
    331         } else {
    332           Char next = subject[pos + 1];
    333           current_char =
    334               (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
    335           pc += BC_LOAD_2_CURRENT_CHARS_LENGTH;
    336         }
    337         break;
    338       }
    339       BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
    340         int pos = current + (insn >> BYTECODE_SHIFT);
    341         Char next = subject[pos + 1];
    342         current_char = (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
    343         pc += BC_LOAD_2_CURRENT_CHARS_UNCHECKED_LENGTH;
    344         break;
    345       }
    346       BYTECODE(LOAD_4_CURRENT_CHARS) {
    347         ASSERT(sizeof(Char) == 1);
    348         int pos = current + (insn >> BYTECODE_SHIFT);
    349         if (pos + 4 > subject.length()) {
    350           pc = code_base + Load32Aligned(pc + 4);
    351         } else {
    352           Char next1 = subject[pos + 1];
    353           Char next2 = subject[pos + 2];
    354           Char next3 = subject[pos + 3];
    355           current_char = (subject[pos] |
    356                           (next1 << 8) |
    357                           (next2 << 16) |
    358                           (next3 << 24));
    359           pc += BC_LOAD_4_CURRENT_CHARS_LENGTH;
    360         }
    361         break;
    362       }
    363       BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
    364         ASSERT(sizeof(Char) == 1);
    365         int pos = current + (insn >> BYTECODE_SHIFT);
    366         Char next1 = subject[pos + 1];
    367         Char next2 = subject[pos + 2];
    368         Char next3 = subject[pos + 3];
    369         current_char = (subject[pos] |
    370                         (next1 << 8) |
    371                         (next2 << 16) |
    372                         (next3 << 24));
    373         pc += BC_LOAD_4_CURRENT_CHARS_UNCHECKED_LENGTH;
    374         break;
    375       }
    376       BYTECODE(CHECK_4_CHARS) {
    377         uint32_t c = Load32Aligned(pc + 4);
    378         if (c == current_char) {
    379           pc = code_base + Load32Aligned(pc + 8);
    380         } else {
    381           pc += BC_CHECK_4_CHARS_LENGTH;
    382         }
    383         break;
    384       }
    385       BYTECODE(CHECK_CHAR) {
    386         uint32_t c = (insn >> BYTECODE_SHIFT);
    387         if (c == current_char) {
    388           pc = code_base + Load32Aligned(pc + 4);
    389         } else {
    390           pc += BC_CHECK_CHAR_LENGTH;
    391         }
    392         break;
    393       }
    394       BYTECODE(CHECK_NOT_4_CHARS) {
    395         uint32_t c = Load32Aligned(pc + 4);
    396         if (c != current_char) {
    397           pc = code_base + Load32Aligned(pc + 8);
    398         } else {
    399           pc += BC_CHECK_NOT_4_CHARS_LENGTH;
    400         }
    401         break;
    402       }
    403       BYTECODE(CHECK_NOT_CHAR) {
    404         uint32_t c = (insn >> BYTECODE_SHIFT);
    405         if (c != current_char) {
    406           pc = code_base + Load32Aligned(pc + 4);
    407         } else {
    408           pc += BC_CHECK_NOT_CHAR_LENGTH;
    409         }
    410         break;
    411       }
    412       BYTECODE(AND_CHECK_4_CHARS) {
    413         uint32_t c = Load32Aligned(pc + 4);
    414         if (c == (current_char & Load32Aligned(pc + 8))) {
    415           pc = code_base + Load32Aligned(pc + 12);
    416         } else {
    417           pc += BC_AND_CHECK_4_CHARS_LENGTH;
    418         }
    419         break;
    420       }
    421       BYTECODE(AND_CHECK_CHAR) {
    422         uint32_t c = (insn >> BYTECODE_SHIFT);
    423         if (c == (current_char & Load32Aligned(pc + 4))) {
    424           pc = code_base + Load32Aligned(pc + 8);
    425         } else {
    426           pc += BC_AND_CHECK_CHAR_LENGTH;
    427         }
    428         break;
    429       }
    430       BYTECODE(AND_CHECK_NOT_4_CHARS) {
    431         uint32_t c = Load32Aligned(pc + 4);
    432         if (c != (current_char & Load32Aligned(pc + 8))) {
    433           pc = code_base + Load32Aligned(pc + 12);
    434         } else {
    435           pc += BC_AND_CHECK_NOT_4_CHARS_LENGTH;
    436         }
    437         break;
    438       }
    439       BYTECODE(AND_CHECK_NOT_CHAR) {
    440         uint32_t c = (insn >> BYTECODE_SHIFT);
    441         if (c != (current_char & Load32Aligned(pc + 4))) {
    442           pc = code_base + Load32Aligned(pc + 8);
    443         } else {
    444           pc += BC_AND_CHECK_NOT_CHAR_LENGTH;
    445         }
    446         break;
    447       }
    448       BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
    449         uint32_t c = (insn >> BYTECODE_SHIFT);
    450         uint32_t minus = Load16Aligned(pc + 4);
    451         uint32_t mask = Load16Aligned(pc + 6);
    452         if (c != ((current_char - minus) & mask)) {
    453           pc = code_base + Load32Aligned(pc + 8);
    454         } else {
    455           pc += BC_MINUS_AND_CHECK_NOT_CHAR_LENGTH;
    456         }
    457         break;
    458       }
    459       BYTECODE(CHECK_CHAR_IN_RANGE) {
    460         uint32_t from = Load16Aligned(pc + 4);
    461         uint32_t to = Load16Aligned(pc + 6);
    462         if (from <= current_char && current_char <= to) {
    463           pc = code_base + Load32Aligned(pc + 8);
    464         } else {
    465           pc += BC_CHECK_CHAR_IN_RANGE_LENGTH;
    466         }
    467         break;
    468       }
    469       BYTECODE(CHECK_CHAR_NOT_IN_RANGE) {
    470         uint32_t from = Load16Aligned(pc + 4);
    471         uint32_t to = Load16Aligned(pc + 6);
    472         if (from > current_char || current_char > to) {
    473           pc = code_base + Load32Aligned(pc + 8);
    474         } else {
    475           pc += BC_CHECK_CHAR_NOT_IN_RANGE_LENGTH;
    476         }
    477         break;
    478       }
    479       BYTECODE(CHECK_BIT_IN_TABLE) {
    480         int mask = RegExpMacroAssembler::kTableMask;
    481         byte b = pc[8 + ((current_char & mask) >> kBitsPerByteLog2)];
    482         int bit = (current_char & (kBitsPerByte - 1));
    483         if ((b & (1 << bit)) != 0) {
    484           pc = code_base + Load32Aligned(pc + 4);
    485         } else {
    486           pc += BC_CHECK_BIT_IN_TABLE_LENGTH;
    487         }
    488         break;
    489       }
    490       BYTECODE(CHECK_LT) {
    491         uint32_t limit = (insn >> BYTECODE_SHIFT);
    492         if (current_char < limit) {
    493           pc = code_base + Load32Aligned(pc + 4);
    494         } else {
    495           pc += BC_CHECK_LT_LENGTH;
    496         }
    497         break;
    498       }
    499       BYTECODE(CHECK_GT) {
    500         uint32_t limit = (insn >> BYTECODE_SHIFT);
    501         if (current_char > limit) {
    502           pc = code_base + Load32Aligned(pc + 4);
    503         } else {
    504           pc += BC_CHECK_GT_LENGTH;
    505         }
    506         break;
    507       }
    508       BYTECODE(CHECK_REGISTER_LT)
    509         if (registers[insn >> BYTECODE_SHIFT] < Load32Aligned(pc + 4)) {
    510           pc = code_base + Load32Aligned(pc + 8);
    511         } else {
    512           pc += BC_CHECK_REGISTER_LT_LENGTH;
    513         }
    514         break;
    515       BYTECODE(CHECK_REGISTER_GE)
    516         if (registers[insn >> BYTECODE_SHIFT] >= Load32Aligned(pc + 4)) {
    517           pc = code_base + Load32Aligned(pc + 8);
    518         } else {
    519           pc += BC_CHECK_REGISTER_GE_LENGTH;
    520         }
    521         break;
    522       BYTECODE(CHECK_REGISTER_EQ_POS)
    523         if (registers[insn >> BYTECODE_SHIFT] == current) {
    524           pc = code_base + Load32Aligned(pc + 4);
    525         } else {
    526           pc += BC_CHECK_REGISTER_EQ_POS_LENGTH;
    527         }
    528         break;
    529       BYTECODE(CHECK_NOT_REGS_EQUAL)
    530         if (registers[insn >> BYTECODE_SHIFT] ==
    531             registers[Load32Aligned(pc + 4)]) {
    532           pc += BC_CHECK_NOT_REGS_EQUAL_LENGTH;
    533         } else {
    534           pc = code_base + Load32Aligned(pc + 8);
    535         }
    536         break;
    537       BYTECODE(CHECK_NOT_BACK_REF) {
    538         int from = registers[insn >> BYTECODE_SHIFT];
    539         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
    540         if (from < 0 || len <= 0) {
    541           pc += BC_CHECK_NOT_BACK_REF_LENGTH;
    542           break;
    543         }
    544         if (current + len > subject.length()) {
    545           pc = code_base + Load32Aligned(pc + 4);
    546           break;
    547         } else {
    548           int i;
    549           for (i = 0; i < len; i++) {
    550             if (subject[from + i] != subject[current + i]) {
    551               pc = code_base + Load32Aligned(pc + 4);
    552               break;
    553             }
    554           }
    555           if (i < len) break;
    556           current += len;
    557         }
    558         pc += BC_CHECK_NOT_BACK_REF_LENGTH;
    559         break;
    560       }
    561       BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
    562         int from = registers[insn >> BYTECODE_SHIFT];
    563         int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
    564         if (from < 0 || len <= 0) {
    565           pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
    566           break;
    567         }
    568         if (current + len > subject.length()) {
    569           pc = code_base + Load32Aligned(pc + 4);
    570           break;
    571         } else {
    572           if (BackRefMatchesNoCase(isolate->interp_canonicalize_mapping(),
    573                                    from, current, len, subject)) {
    574             current += len;
    575             pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
    576           } else {
    577             pc = code_base + Load32Aligned(pc + 4);
    578           }
    579         }
    580         break;
    581       }
    582       BYTECODE(CHECK_AT_START)
    583         if (current == 0) {
    584           pc = code_base + Load32Aligned(pc + 4);
    585         } else {
    586           pc += BC_CHECK_AT_START_LENGTH;
    587         }
    588         break;
    589       BYTECODE(CHECK_NOT_AT_START)
    590         if (current == 0) {
    591           pc += BC_CHECK_NOT_AT_START_LENGTH;
    592         } else {
    593           pc = code_base + Load32Aligned(pc + 4);
    594         }
    595         break;
    596       BYTECODE(SET_CURRENT_POSITION_FROM_END) {
    597         int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
    598         if (subject.length() - current > by) {
    599           current = subject.length() - by;
    600           current_char = subject[current - 1];
    601         }
    602         pc += BC_SET_CURRENT_POSITION_FROM_END_LENGTH;
    603         break;
    604       }
    605       default:
    606         UNREACHABLE();
    607         break;
    608     }
    609   }
    610 }
    611 
    612 
    613 RegExpImpl::IrregexpResult IrregexpInterpreter::Match(
    614     Isolate* isolate,
    615     Handle<ByteArray> code_array,
    616     Handle<String> subject,
    617     int* registers,
    618     int start_position) {
    619   ASSERT(subject->IsFlat());
    620 
    621   DisallowHeapAllocation no_gc;
    622   const byte* code_base = code_array->GetDataStartAddress();
    623   uc16 previous_char = '\n';
    624   String::FlatContent subject_content = subject->GetFlatContent();
    625   if (subject_content.IsAscii()) {
    626     Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
    627     if (start_position != 0) previous_char = subject_vector[start_position - 1];
    628     return RawMatch(isolate,
    629                     code_base,
    630                     subject_vector,
    631                     registers,
    632                     start_position,
    633                     previous_char);
    634   } else {
    635     ASSERT(subject_content.IsTwoByte());
    636     Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
    637     if (start_position != 0) previous_char = subject_vector[start_position - 1];
    638     return RawMatch(isolate,
    639                     code_base,
    640                     subject_vector,
    641                     registers,
    642                     start_position,
    643                     previous_char);
    644   }
    645 }
    646 
    647 } }  // namespace v8::internal
    648