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 "jsregexp.h"
     37 #include "interpreter-irregexp.h"
     38 
     39 namespace v8 {
     40 namespace internal {
     41 
     42 
     43 typedef unibrow::Mapping<unibrow::Ecma262Canonicalize> Canonicalize;
     44 
     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 
     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
     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 
    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 
    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:
    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 
    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 
    175   int* data() const { return data_; }
    176 
    177   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>
    190 static RegExpImpl::IrregexpResult 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 RegExpImpl::RE_FAILURE;
    215       BYTECODE(PUSH_CP)
    216         if (--backtrack_stack_space < 0) {
    217           return RegExpImpl::RE_EXCEPTION;
    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 RegExpImpl::RE_EXCEPTION;
    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 RegExpImpl::RE_EXCEPTION;
    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 RegExpImpl::RE_FAILURE;
    282       BYTECODE(SUCCEED)
    283         return RegExpImpl::RE_SUCCESS;
    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 
    628 RegExpImpl::IrregexpResult IrregexpInterpreter::Match(
    629     Isolate* isolate,
    630     Handle<ByteArray> code_array,
    631     Handle<String> subject,
    632     int* registers,
    633     int start_position) {
    634   ASSERT(subject->IsFlat());
    635 
    636   AssertNoAllocation a;
    637   const byte* code_base = code_array->GetDataStartAddress();
    638   uc16 previous_char = '\n';
    639   String::FlatContent subject_content = subject->GetFlatContent();
    640   if (subject_content.IsAscii()) {
    641     Vector<const char> subject_vector = subject_content.ToAsciiVector();
    642     if (start_position != 0) previous_char = subject_vector[start_position - 1];
    643     return RawMatch(isolate,
    644                     code_base,
    645                     subject_vector,
    646                     registers,
    647                     start_position,
    648                     previous_char);
    649   } else {
    650     ASSERT(subject_content.IsTwoByte());
    651     Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
    652     if (start_position != 0) previous_char = subject_vector[start_position - 1];
    653     return RawMatch(isolate,
    654                     code_base,
    655                     subject_vector,
    656                     registers,
    657                     start_position,
    658                     previous_char);
    659   }
    660 }
    661 
    662 } }  // namespace v8::internal
    663