Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: runtime/vm/regexp_interpreter.cc

Issue 1201383002: Port irregexp bytecode compiler and interpreter from V8 r24065. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/regexp_interpreter.h ('k') | runtime/vm/regexp_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, 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,
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
OLDNEW
« no previous file with comments | « runtime/vm/regexp_interpreter.h ('k') | runtime/vm/regexp_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698