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