blob: 1cc5c5a1d65cb11f466055ac50e3bff59fe0810d [file] [log] [blame]
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001// Copyright 2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// A simple interpreter for the Irregexp byte code.
29
30
31#include "v8.h"
32#include "unicode.h"
33#include "utils.h"
34#include "ast.h"
35#include "bytecodes-irregexp.h"
36#include "interpreter-irregexp.h"
37
38
39namespace v8 { namespace internal {
40
41
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000042static unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize;
ager@chromium.orga74f0da2008-12-03 16:05:52 +000043
44
45static bool BackRefMatchesNoCase(int from,
46 int current,
47 int len,
48 Vector<const uc16> subject) {
49 for (int i = 0; i < len; i++) {
50 unibrow::uchar old_char = subject[from++];
51 unibrow::uchar new_char = subject[current++];
52 if (old_char == new_char) continue;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000053 interp_canonicalize.get(old_char, '\0', &old_char);
54 interp_canonicalize.get(new_char, '\0', &new_char);
ager@chromium.orga74f0da2008-12-03 16:05:52 +000055 if (old_char != new_char) {
56 return false;
57 }
58 }
59 return true;
60}
61
62
ager@chromium.org8bb60582008-12-11 12:02:20 +000063static bool BackRefMatchesNoCase(int from,
64 int current,
65 int len,
66 Vector<const char> subject) {
67 for (int i = 0; i < len; i++) {
68 unsigned int old_char = subject[from++];
69 unsigned int new_char = subject[current++];
70 if (old_char == new_char) continue;
71 if (old_char - 'A' <= 'Z' - 'A') old_char |= 0x20;
72 if (new_char - 'A' <= 'Z' - 'A') new_char |= 0x20;
73 if (old_char != new_char) return false;
74 }
75 return true;
76}
77
78
ager@chromium.orga74f0da2008-12-03 16:05:52 +000079#ifdef DEBUG
80static void TraceInterpreter(const byte* code_base,
81 const byte* pc,
82 int stack_depth,
83 int current_position,
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000084 uint32_t current_char,
ager@chromium.orga74f0da2008-12-03 16:05:52 +000085 int bytecode_length,
86 const char* bytecode_name) {
87 if (FLAG_trace_regexp_bytecodes) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000088 bool printable = (current_char < 127 && current_char >= 32);
89 const char* format =
90 printable ?
91 "pc = %02x, sp = %d, curpos = %d, curchar = %08x (%c), bc = %s" :
92 "pc = %02x, sp = %d, curpos = %d, curchar = %08x .%c., bc = %s";
93 PrintF(format,
ager@chromium.orga74f0da2008-12-03 16:05:52 +000094 pc - code_base,
95 stack_depth,
96 current_position,
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000097 current_char,
98 printable ? current_char : '.',
ager@chromium.orga74f0da2008-12-03 16:05:52 +000099 bytecode_name);
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000100 for (int i = 0; i < bytecode_length; i++) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000101 printf(", %02x", pc[i]);
102 }
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000103 printf(" ");
104 for (int i = 1; i < bytecode_length; i++) {
105 unsigned char b = pc[i];
106 if (b < 127 && b >= 32) {
107 printf("%c", b);
108 } else {
109 printf(".");
110 }
111 }
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000112 printf("\n");
113 }
114}
115
116
117#define BYTECODE(name) \
118 case BC_##name: \
119 TraceInterpreter(code_base, \
120 pc, \
121 backtrack_sp - backtrack_stack, \
122 current, \
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000123 current_char, \
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000124 BC_##name##_LENGTH, \
125 #name);
126#else
127#define BYTECODE(name) \
128 case BC_##name:
129#endif
130
131
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000132static int32_t Load32Aligned(const byte* pc) {
133 ASSERT((reinterpret_cast<int>(pc) & 3) == 0);
134 return *reinterpret_cast<const int32_t *>(pc);
135}
136
137
138static int32_t Load16Aligned(const byte* pc) {
139 ASSERT((reinterpret_cast<int>(pc) & 1) == 0);
140 return *reinterpret_cast<const uint16_t *>(pc);
141}
142
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000143
ager@chromium.org8bb60582008-12-11 12:02:20 +0000144template <typename Char>
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000145static bool RawMatch(const byte* code_base,
ager@chromium.org8bb60582008-12-11 12:02:20 +0000146 Vector<const Char> subject,
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000147 int* registers,
148 int current,
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000149 uint32_t current_char) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000150 const byte* pc = code_base;
151 static const int kBacktrackStackSize = 10000;
152 int backtrack_stack[kBacktrackStackSize];
153 int backtrack_stack_space = kBacktrackStackSize;
154 int* backtrack_sp = backtrack_stack;
155#ifdef DEBUG
156 if (FLAG_trace_regexp_bytecodes) {
157 PrintF("\n\nStart bytecode interpreter\n\n");
158 }
159#endif
160 while (true) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000161 int32_t insn = Load32Aligned(pc);
162 switch (insn & BYTECODE_MASK) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000163 BYTECODE(BREAK)
164 UNREACHABLE();
165 return false;
166 BYTECODE(PUSH_CP)
167 if (--backtrack_stack_space < 0) {
168 return false; // No match on backtrack stack overflow.
169 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000170 *backtrack_sp++ = current;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000171 pc += BC_PUSH_CP_LENGTH;
172 break;
173 BYTECODE(PUSH_BT)
174 if (--backtrack_stack_space < 0) {
175 return false; // No match on backtrack stack overflow.
176 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000177 *backtrack_sp++ = Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000178 pc += BC_PUSH_BT_LENGTH;
179 break;
180 BYTECODE(PUSH_REGISTER)
181 if (--backtrack_stack_space < 0) {
182 return false; // No match on backtrack stack overflow.
183 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000184 *backtrack_sp++ = registers[insn >> BYTECODE_SHIFT];
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000185 pc += BC_PUSH_REGISTER_LENGTH;
186 break;
187 BYTECODE(SET_REGISTER)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000188 registers[insn >> BYTECODE_SHIFT] = Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000189 pc += BC_SET_REGISTER_LENGTH;
190 break;
191 BYTECODE(ADVANCE_REGISTER)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000192 registers[insn >> BYTECODE_SHIFT] += Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000193 pc += BC_ADVANCE_REGISTER_LENGTH;
194 break;
195 BYTECODE(SET_REGISTER_TO_CP)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000196 registers[insn >> BYTECODE_SHIFT] = current + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000197 pc += BC_SET_REGISTER_TO_CP_LENGTH;
198 break;
199 BYTECODE(SET_CP_TO_REGISTER)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000200 current = registers[insn >> BYTECODE_SHIFT];
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000201 pc += BC_SET_CP_TO_REGISTER_LENGTH;
202 break;
203 BYTECODE(SET_REGISTER_TO_SP)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000204 registers[insn >> BYTECODE_SHIFT] = backtrack_sp - backtrack_stack;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000205 pc += BC_SET_REGISTER_TO_SP_LENGTH;
206 break;
207 BYTECODE(SET_SP_TO_REGISTER)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000208 backtrack_sp = backtrack_stack + registers[insn >> BYTECODE_SHIFT];
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000209 backtrack_stack_space = kBacktrackStackSize -
210 (backtrack_sp - backtrack_stack);
211 pc += BC_SET_SP_TO_REGISTER_LENGTH;
212 break;
213 BYTECODE(POP_CP)
214 backtrack_stack_space++;
215 --backtrack_sp;
216 current = *backtrack_sp;
217 pc += BC_POP_CP_LENGTH;
218 break;
219 BYTECODE(POP_BT)
220 backtrack_stack_space++;
221 --backtrack_sp;
222 pc = code_base + *backtrack_sp;
223 break;
224 BYTECODE(POP_REGISTER)
225 backtrack_stack_space++;
226 --backtrack_sp;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000227 registers[insn >> BYTECODE_SHIFT] = *backtrack_sp;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000228 pc += BC_POP_REGISTER_LENGTH;
229 break;
230 BYTECODE(FAIL)
231 return false;
232 BYTECODE(SUCCEED)
233 return true;
234 BYTECODE(ADVANCE_CP)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000235 current += insn >> BYTECODE_SHIFT;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000236 pc += BC_ADVANCE_CP_LENGTH;
237 break;
238 BYTECODE(GOTO)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000239 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000240 break;
ager@chromium.org381abbb2009-02-25 13:23:22 +0000241 BYTECODE(ADVANCE_CP_AND_GOTO)
242 current += insn >> BYTECODE_SHIFT;
243 pc = code_base + Load32Aligned(pc + 4);
244 break;
ager@chromium.org8bb60582008-12-11 12:02:20 +0000245 BYTECODE(CHECK_GREEDY)
246 if (current == backtrack_sp[-1]) {
247 backtrack_sp--;
248 backtrack_stack_space++;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000249 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.org8bb60582008-12-11 12:02:20 +0000250 } else {
251 pc += BC_CHECK_GREEDY_LENGTH;
252 }
253 break;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000254 BYTECODE(LOAD_CURRENT_CHAR) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000255 int pos = current + (insn >> BYTECODE_SHIFT);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000256 if (pos >= subject.length()) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000257 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000258 } else {
259 current_char = subject[pos];
260 pc += BC_LOAD_CURRENT_CHAR_LENGTH;
261 }
262 break;
263 }
ager@chromium.org8bb60582008-12-11 12:02:20 +0000264 BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000265 int pos = current + (insn >> BYTECODE_SHIFT);
ager@chromium.org8bb60582008-12-11 12:02:20 +0000266 current_char = subject[pos];
267 pc += BC_LOAD_CURRENT_CHAR_UNCHECKED_LENGTH;
268 break;
269 }
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000270 BYTECODE(LOAD_2_CURRENT_CHARS) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000271 int pos = current + (insn >> BYTECODE_SHIFT);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000272 if (pos + 2 > subject.length()) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000273 pc = code_base + Load32Aligned(pc + 4);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000274 } else {
275 Char next = subject[pos + 1];
276 current_char =
277 (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
278 pc += BC_LOAD_2_CURRENT_CHARS_LENGTH;
279 }
280 break;
281 }
282 BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000283 int pos = current + (insn >> BYTECODE_SHIFT);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000284 Char next = subject[pos + 1];
285 current_char = (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
286 pc += BC_LOAD_2_CURRENT_CHARS_UNCHECKED_LENGTH;
287 break;
288 }
289 BYTECODE(LOAD_4_CURRENT_CHARS) {
290 ASSERT(sizeof(Char) == 1);
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000291 int pos = current + (insn >> BYTECODE_SHIFT);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000292 if (pos + 4 > subject.length()) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000293 pc = code_base + Load32Aligned(pc + 4);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000294 } else {
295 Char next1 = subject[pos + 1];
296 Char next2 = subject[pos + 2];
297 Char next3 = subject[pos + 3];
298 current_char = (subject[pos] |
299 (next1 << 8) |
300 (next2 << 16) |
301 (next3 << 24));
302 pc += BC_LOAD_4_CURRENT_CHARS_LENGTH;
303 }
304 break;
305 }
306 BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
307 ASSERT(sizeof(Char) == 1);
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000308 int pos = current + (insn >> BYTECODE_SHIFT);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000309 Char next1 = subject[pos + 1];
310 Char next2 = subject[pos + 2];
311 Char next3 = subject[pos + 3];
312 current_char = (subject[pos] |
313 (next1 << 8) |
314 (next2 << 16) |
315 (next3 << 24));
316 pc += BC_LOAD_4_CURRENT_CHARS_UNCHECKED_LENGTH;
317 break;
318 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000319 BYTECODE(CHECK_4_CHARS) {
320 uint32_t c = Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000321 if (c == current_char) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000322 pc = code_base + Load32Aligned(pc + 8);
323 } else {
324 pc += BC_CHECK_4_CHARS_LENGTH;
325 }
326 break;
327 }
328 BYTECODE(CHECK_CHAR) {
329 uint32_t c = (insn >> BYTECODE_SHIFT);
330 if (c == current_char) {
331 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000332 } else {
333 pc += BC_CHECK_CHAR_LENGTH;
334 }
335 break;
336 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000337 BYTECODE(CHECK_NOT_4_CHARS) {
338 uint32_t c = Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000339 if (c != current_char) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000340 pc = code_base + Load32Aligned(pc + 8);
341 } else {
342 pc += BC_CHECK_NOT_4_CHARS_LENGTH;
343 }
344 break;
345 }
346 BYTECODE(CHECK_NOT_CHAR) {
347 uint32_t c = (insn >> BYTECODE_SHIFT);
348 if (c != current_char) {
349 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000350 } else {
351 pc += BC_CHECK_NOT_CHAR_LENGTH;
352 }
353 break;
354 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000355 BYTECODE(AND_CHECK_4_CHARS) {
356 uint32_t c = Load32Aligned(pc + 4);
357 if (c == (current_char & Load32Aligned(pc + 8))) {
358 pc = code_base + Load32Aligned(pc + 12);
359 } else {
360 pc += BC_AND_CHECK_4_CHARS_LENGTH;
361 }
362 break;
363 }
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000364 BYTECODE(AND_CHECK_CHAR) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000365 uint32_t c = (insn >> BYTECODE_SHIFT);
366 if (c == (current_char & Load32Aligned(pc + 4))) {
367 pc = code_base + Load32Aligned(pc + 8);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000368 } else {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000369 pc += BC_AND_CHECK_CHAR_LENGTH;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000370 }
371 break;
372 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000373 BYTECODE(AND_CHECK_NOT_4_CHARS) {
374 uint32_t c = Load32Aligned(pc + 4);
375 if (c != (current_char & Load32Aligned(pc + 8))) {
376 pc = code_base + Load32Aligned(pc + 12);
377 } else {
378 pc += BC_AND_CHECK_NOT_4_CHARS_LENGTH;
379 }
380 break;
381 }
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000382 BYTECODE(AND_CHECK_NOT_CHAR) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000383 uint32_t c = (insn >> BYTECODE_SHIFT);
384 if (c != (current_char & Load32Aligned(pc + 4))) {
385 pc = code_base + Load32Aligned(pc + 8);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000386 } else {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000387 pc += BC_AND_CHECK_NOT_CHAR_LENGTH;
388 }
389 break;
390 }
391 BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000392 uint32_t c = (insn >> BYTECODE_SHIFT);
393 uint32_t minus = Load16Aligned(pc + 4);
394 uint32_t mask = Load16Aligned(pc + 6);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000395 if (c != ((current_char - minus) & mask)) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000396 pc = code_base + Load32Aligned(pc + 8);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000397 } else {
398 pc += BC_MINUS_AND_CHECK_NOT_CHAR_LENGTH;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000399 }
400 break;
401 }
402 BYTECODE(CHECK_LT) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000403 uint32_t limit = (insn >> BYTECODE_SHIFT);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000404 if (current_char < limit) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000405 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000406 } else {
407 pc += BC_CHECK_LT_LENGTH;
408 }
409 break;
410 }
411 BYTECODE(CHECK_GT) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000412 uint32_t limit = (insn >> BYTECODE_SHIFT);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000413 if (current_char > limit) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000414 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000415 } else {
416 pc += BC_CHECK_GT_LENGTH;
417 }
418 break;
419 }
420 BYTECODE(CHECK_REGISTER_LT)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000421 if (registers[insn >> BYTECODE_SHIFT] < Load32Aligned(pc + 4)) {
422 pc = code_base + Load32Aligned(pc + 8);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000423 } else {
424 pc += BC_CHECK_REGISTER_LT_LENGTH;
425 }
426 break;
427 BYTECODE(CHECK_REGISTER_GE)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000428 if (registers[insn >> BYTECODE_SHIFT] >= Load32Aligned(pc + 4)) {
429 pc = code_base + Load32Aligned(pc + 8);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000430 } else {
431 pc += BC_CHECK_REGISTER_GE_LENGTH;
432 }
433 break;
ager@chromium.org32912102009-01-16 10:38:43 +0000434 BYTECODE(CHECK_REGISTER_EQ_POS)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000435 if (registers[insn >> BYTECODE_SHIFT] == current) {
436 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.org32912102009-01-16 10:38:43 +0000437 } else {
438 pc += BC_CHECK_REGISTER_EQ_POS_LENGTH;
439 }
440 break;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000441 BYTECODE(LOOKUP_MAP1) {
442 // Look up character in a bitmap. If we find a 0, then jump to the
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000443 // location at pc + 8. Otherwise fall through!
444 int index = current_char - (insn >> BYTECODE_SHIFT);
445 byte map = code_base[Load32Aligned(pc + 4) + (index >> 3)];
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000446 map = ((map >> (index & 7)) & 1);
447 if (map == 0) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000448 pc = code_base + Load32Aligned(pc + 8);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000449 } else {
450 pc += BC_LOOKUP_MAP1_LENGTH;
451 }
452 break;
453 }
454 BYTECODE(LOOKUP_MAP2) {
455 // Look up character in a half-nibble map. If we find 00, then jump to
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000456 // the location at pc + 8. If we find 01 then jump to location at
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000457 // pc + 11, etc.
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000458 int index = (current_char - (insn >> BYTECODE_SHIFT)) << 1;
459 byte map = code_base[Load32Aligned(pc + 3) + (index >> 3)];
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000460 map = ((map >> (index & 7)) & 3);
461 if (map < 2) {
462 if (map == 0) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000463 pc = code_base + Load32Aligned(pc + 8);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000464 } else {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000465 pc = code_base + Load32Aligned(pc + 12);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000466 }
467 } else {
468 if (map == 2) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000469 pc = code_base + Load32Aligned(pc + 16);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000470 } else {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000471 pc = code_base + Load32Aligned(pc + 20);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000472 }
473 }
474 break;
475 }
476 BYTECODE(LOOKUP_MAP8) {
477 // Look up character in a byte map. Use the byte as an index into a
478 // table that follows this instruction immediately.
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000479 int index = current_char - (insn >> BYTECODE_SHIFT);
480 byte map = code_base[Load32Aligned(pc + 4) + index];
481 const byte* new_pc = code_base + Load32Aligned(pc + 8) + (map << 2);
482 pc = code_base + Load32Aligned(new_pc);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000483 break;
484 }
485 BYTECODE(LOOKUP_HI_MAP8) {
486 // Look up high byte of this character in a byte map. Use the byte as
487 // an index into a table that follows this instruction immediately.
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000488 int index = (current_char >> 8) - (insn >> BYTECODE_SHIFT);
489 byte map = code_base[Load32Aligned(pc + 4) + index];
490 const byte* new_pc = code_base + Load32Aligned(pc + 8) + (map << 2);
491 pc = code_base + Load32Aligned(new_pc);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000492 break;
493 }
494 BYTECODE(CHECK_NOT_REGS_EQUAL)
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000495 if (registers[insn >> BYTECODE_SHIFT] ==
496 registers[Load32Aligned(pc + 4)]) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000497 pc += BC_CHECK_NOT_REGS_EQUAL_LENGTH;
498 } else {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000499 pc = code_base + Load32Aligned(pc + 8);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000500 }
501 break;
502 BYTECODE(CHECK_NOT_BACK_REF) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000503 int from = registers[insn >> BYTECODE_SHIFT];
504 int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000505 if (from < 0 || len <= 0) {
506 pc += BC_CHECK_NOT_BACK_REF_LENGTH;
507 break;
508 }
509 if (current + len > subject.length()) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000510 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000511 break;
512 } else {
513 int i;
514 for (i = 0; i < len; i++) {
515 if (subject[from + i] != subject[current + i]) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000516 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000517 break;
518 }
519 }
520 if (i < len) break;
521 current += len;
522 }
523 pc += BC_CHECK_NOT_BACK_REF_LENGTH;
524 break;
525 }
526 BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000527 int from = registers[insn >> BYTECODE_SHIFT];
528 int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000529 if (from < 0 || len <= 0) {
530 pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
531 break;
532 }
533 if (current + len > subject.length()) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000534 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000535 break;
536 } else {
537 if (BackRefMatchesNoCase(from, current, len, subject)) {
ager@chromium.org8bb60582008-12-11 12:02:20 +0000538 current += len;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000539 pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
540 } else {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000541 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000542 }
543 }
544 break;
545 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000546 BYTECODE(CHECK_AT_START)
547 if (current == 0) {
548 pc = code_base + Load32Aligned(pc + 4);
549 } else {
550 pc += BC_CHECK_AT_START_LENGTH;
551 }
552 break;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000553 BYTECODE(CHECK_NOT_AT_START)
554 if (current == 0) {
555 pc += BC_CHECK_NOT_AT_START_LENGTH;
556 } else {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000557 pc = code_base + Load32Aligned(pc + 4);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000558 }
559 break;
560 default:
561 UNREACHABLE();
562 break;
563 }
564 }
565}
566
567
568bool IrregexpInterpreter::Match(Handle<ByteArray> code_array,
ager@chromium.org8bb60582008-12-11 12:02:20 +0000569 Handle<String> subject,
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000570 int* registers,
571 int start_position) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000572 ASSERT(subject->IsFlat());
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000573
574 AssertNoAllocation a;
575 const byte* code_base = code_array->GetDataStartAddress();
576 uc16 previous_char = '\n';
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000577 if (StringShape(*subject).IsAsciiRepresentation()) {
ager@chromium.org8bb60582008-12-11 12:02:20 +0000578 Vector<const char> subject_vector = subject->ToAsciiVector();
579 if (start_position != 0) previous_char = subject_vector[start_position - 1];
580 return RawMatch(code_base,
581 subject_vector,
582 registers,
583 start_position,
584 previous_char);
585 } else {
586 Vector<const uc16> subject_vector = subject->ToUC16Vector();
587 if (start_position != 0) previous_char = subject_vector[start_position - 1];
588 return RawMatch(code_base,
589 subject_vector,
590 registers,
591 start_position,
592 previous_char);
593 }
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000594}
595
596} } // namespace v8::internal