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