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