• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecma-globals.h"
17 #include "ecma-regexp-object.h"
18 #include "lit-strings.h"
19 #include "re-bytecode.h"
20 
21 #if ENABLED (JERRY_BUILTIN_REGEXP)
22 
23 /** \addtogroup parser Parser
24  * @{
25  *
26  * \addtogroup regexparser Regular expression
27  * @{
28  *
29  * \addtogroup regexparser_bytecode Bytecode
30  * @{
31  */
32 
33 void
re_initialize_regexp_bytecode(re_compiler_ctx_t * re_ctx_p)34 re_initialize_regexp_bytecode (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */
35 {
36   const size_t initial_size = sizeof (re_compiled_code_t);
37   re_ctx_p->bytecode_start_p = jmem_heap_alloc_block (initial_size);
38   re_ctx_p->bytecode_size = initial_size;
39 } /* re_initialize_regexp_bytecode */
40 
41 inline uint32_t JERRY_ATTR_ALWAYS_INLINE
re_bytecode_size(re_compiler_ctx_t * re_ctx_p)42 re_bytecode_size (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */
43 {
44   return (uint32_t) re_ctx_p->bytecode_size;
45 } /* re_bytecode_size */
46 
47 /**
48  * Append a new bytecode to the and of the bytecode container
49  */
50 static uint8_t *
re_bytecode_reserve(re_compiler_ctx_t * re_ctx_p,const size_t size)51 re_bytecode_reserve (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
52                      const size_t size) /**< size */
53 {
54   const size_t old_size = re_ctx_p->bytecode_size;
55   const size_t new_size = old_size + size;
56   re_ctx_p->bytecode_start_p = jmem_heap_realloc_block (re_ctx_p->bytecode_start_p, old_size, new_size);
57   re_ctx_p->bytecode_size = new_size;
58   return re_ctx_p->bytecode_start_p + old_size;
59 } /* re_bytecode_reserve */
60 
61 /**
62  * Insert a new bytecode to the bytecode container
63  */
64 static uint8_t *
re_bytecode_insert(re_compiler_ctx_t * re_ctx_p,const size_t offset,const size_t size)65 re_bytecode_insert (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
66                     const size_t offset, /**< distance from the start of the container */
67                     const size_t size) /**< size */
68 {
69   const size_t tail_size = re_ctx_p->bytecode_size - offset;
70   re_bytecode_reserve (re_ctx_p, size);
71 
72   uint8_t *dest_p = re_ctx_p->bytecode_start_p + offset;
73   memmove (dest_p + size, dest_p, tail_size);
74 
75   return dest_p;
76 } /* re_bytecode_insert */
77 
78 /**
79  * Append a byte
80  */
81 void
re_append_byte(re_compiler_ctx_t * re_ctx_p,const uint8_t byte)82 re_append_byte (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
83                 const uint8_t byte) /**< byte value */
84 {
85   uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, sizeof (uint8_t));
86   *dest_p = byte;
87 } /* re_append_byte */
88 
89 /**
90  * Insert a byte value
91  */
92 void
re_insert_byte(re_compiler_ctx_t * re_ctx_p,const uint32_t offset,const uint8_t byte)93 re_insert_byte (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
94                 const uint32_t offset, /**< distance from the start of the container */
95                 const uint8_t byte) /**< byte value */
96 {
97   uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, sizeof (uint8_t));
98   *dest_p = byte;
99 } /* re_insert_byte */
100 
101 /**
102  * Get a single byte and icnrease bytecode position.
103  */
104 inline uint8_t JERRY_ATTR_ALWAYS_INLINE
re_get_byte(const uint8_t ** bc_p)105 re_get_byte (const uint8_t **bc_p) /**< pointer to bytecode start */
106 {
107   return *((*bc_p)++);
108 } /* re_get_byte */
109 
110 /**
111  * Append a RegExp opcode
112  */
113 inline void JERRY_ATTR_ALWAYS_INLINE
re_append_opcode(re_compiler_ctx_t * re_ctx_p,const re_opcode_t opcode)114 re_append_opcode (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
115                   const re_opcode_t opcode) /**< input opcode */
116 {
117   re_append_byte (re_ctx_p, (uint8_t) opcode);
118 } /* re_append_opcode */
119 
120 /**
121  * Insert a RegExp opcode
122  */
123 inline void JERRY_ATTR_ALWAYS_INLINE
re_insert_opcode(re_compiler_ctx_t * re_ctx_p,const uint32_t offset,const re_opcode_t opcode)124 re_insert_opcode (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
125                   const uint32_t offset, /**< distance from the start of the container */
126                   const re_opcode_t opcode) /**< input opcode */
127 {
128   re_insert_byte (re_ctx_p, offset, (uint8_t) opcode);
129 } /* re_insert_opcode */
130 
131 /**
132  * Get a RegExp opcode and increase the bytecode position
133  *
134  * @return current RegExp opcode
135  */
136 inline re_opcode_t JERRY_ATTR_ALWAYS_INLINE
re_get_opcode(const uint8_t ** bc_p)137 re_get_opcode (const uint8_t **bc_p) /**< pointer to bytecode start */
138 {
139   return (re_opcode_t) re_get_byte (bc_p);
140 } /* re_get_opcode */
141 
142 /**
143  * Encode 2 byte unsigned integer into the bytecode
144  */
145 static void
re_encode_u16(uint8_t * dest_p,const uint16_t value)146 re_encode_u16 (uint8_t *dest_p, /**< destination */
147                const uint16_t value) /**< value */
148 {
149   *dest_p++ = (uint8_t) ((value >> 8) & 0xFF);
150   *dest_p = (uint8_t) (value & 0xFF);
151 } /* re_encode_u16 */
152 
153 /**
154  * Encode 4 byte unsigned integer into the bytecode
155  */
156 static void
re_encode_u32(uint8_t * dest_p,const uint32_t value)157 re_encode_u32 (uint8_t *dest_p, /**< destination */
158               const uint32_t value) /**< value */
159 {
160   *dest_p++ = (uint8_t) ((value >> 24) & 0xFF);
161   *dest_p++ = (uint8_t) ((value >> 16) & 0xFF);
162   *dest_p++ = (uint8_t) ((value >> 8) & 0xFF);
163   *dest_p = (uint8_t) (value & 0xFF);
164 } /* re_encode_u32 */
165 
166 /**
167  * Decode 2 byte unsigned integer from bytecode
168  *
169  * @return uint16_t value
170  */
171 static uint16_t
re_decode_u16(const uint8_t * src_p)172 re_decode_u16 (const uint8_t *src_p) /**< source */
173 {
174   uint16_t value = (uint16_t) (((uint16_t) *src_p++) << 8);
175   value = (uint16_t) (value + *src_p++);
176   return value;
177 } /* re_decode_u16 */
178 
179 /**
180  * Decode 4 byte unsigned integer from bytecode
181  *
182  * @return uint32_t value
183  */
184 static uint32_t JERRY_ATTR_NOINLINE
re_decode_u32(const uint8_t * src_p)185 re_decode_u32 (const uint8_t *src_p) /**< source */
186 {
187   uint32_t value = (uint32_t) (((uint32_t) *src_p++) << 24);
188   value += (uint32_t) (((uint32_t) *src_p++) << 16);
189   value += (uint32_t) (((uint32_t) *src_p++) << 8);
190   value += (uint32_t) (*src_p++);
191   return value;
192 } /* re_decode_u32 */
193 
194 /**
195  * Get the encoded size of an uint32_t value.
196  *
197  * @return encoded value size
198  */
199 inline static size_t JERRY_ATTR_ALWAYS_INLINE
re_get_encoded_value_size(uint32_t value)200 re_get_encoded_value_size (uint32_t value) /**< value */
201 {
202   if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX))
203   {
204     return 1;
205   }
206 
207   return 5;
208 } /* re_get_encoded_value_size */
209 
210 /*
211  * Encode a value to the specified position in the bytecode.
212  */
213 static void
re_encode_value(uint8_t * dest_p,const uint32_t value)214 re_encode_value (uint8_t *dest_p, /**< position in bytecode */
215                  const uint32_t value) /**< value */
216 {
217   if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX))
218   {
219     *dest_p = (uint8_t) value;
220     return;
221   }
222 
223   *dest_p++ = (uint8_t) (RE_VALUE_4BYTE_MARKER);
224   re_encode_u32 (dest_p, value);
225 } /* re_encode_value */
226 
227 /**
228  * Append a value to the end of the bytecode.
229  */
230 void
re_append_value(re_compiler_ctx_t * re_ctx_p,const uint32_t value)231 re_append_value (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
232                  const uint32_t value) /**< value */
233 {
234   const size_t size = re_get_encoded_value_size (value);
235   uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, size);
236   re_encode_value (dest_p, value);
237 } /* re_append_value */
238 
239 /**
240  * Insert a value into the bytecode at a specific offset.
241  */
242 void
re_insert_value(re_compiler_ctx_t * re_ctx_p,const uint32_t offset,const uint32_t value)243 re_insert_value (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
244                  const uint32_t offset, /**< bytecode offset */
245                  const uint32_t value) /**< value */
246 {
247   const size_t size = re_get_encoded_value_size (value);
248   uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, size);
249   re_encode_value (dest_p, value);
250 } /* re_insert_value */
251 
252 /**
253  * Read an encoded value from the bytecode.
254  *
255  * @return decoded value
256  */
257 uint32_t JERRY_ATTR_ALWAYS_INLINE
re_get_value(const uint8_t ** bc_p)258 re_get_value (const uint8_t **bc_p) /** refence to bytecode pointer */
259 {
260   uint32_t value = *(*bc_p)++;
261   if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX))
262   {
263     return value;
264   }
265 
266   value = re_decode_u32 (*bc_p);
267   *bc_p += sizeof (uint32_t);
268   return value;
269 } /* re_get_value */
270 
271 /**
272  * Append a character to the RegExp bytecode
273  */
274 void
re_append_char(re_compiler_ctx_t * re_ctx_p,const lit_code_point_t cp)275 re_append_char (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
276                 const lit_code_point_t cp) /**< code point */
277 {
278 #if ENABLED (JERRY_ES2015)
279   const size_t size = (re_ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t);
280 #else /* !ENABLED (JERRY_ES2015) */
281   JERRY_UNUSED (re_ctx_p);
282   const size_t size = sizeof (ecma_char_t);
283 #endif /* !ENABLED (JERRY_ES2015) */
284 
285   uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, size);
286 
287 #if ENABLED (JERRY_ES2015)
288   if (re_ctx_p->flags & RE_FLAG_UNICODE)
289   {
290     re_encode_u32 (dest_p, cp);
291     return;
292   }
293 #endif /* ENABLED (JERRY_ES2015) */
294 
295   JERRY_ASSERT (cp <= LIT_UTF16_CODE_UNIT_MAX);
296   re_encode_u16 (dest_p, (ecma_char_t) cp);
297 } /* re_append_char */
298 
299 /**
300  * Append a character to the RegExp bytecode
301  */
302 void
re_insert_char(re_compiler_ctx_t * re_ctx_p,const uint32_t offset,const lit_code_point_t cp)303 re_insert_char (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
304                 const uint32_t offset, /**< bytecode offset */
305                 const lit_code_point_t cp) /**< code point*/
306 {
307 #if ENABLED (JERRY_ES2015)
308   const size_t size = (re_ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t);
309 #else /* !ENABLED (JERRY_ES2015) */
310   JERRY_UNUSED (re_ctx_p);
311   const size_t size = sizeof (ecma_char_t);
312 #endif /* !ENABLED (JERRY_ES2015) */
313 
314   uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, size);
315 
316 #if ENABLED (JERRY_ES2015)
317   if (re_ctx_p->flags & RE_FLAG_UNICODE)
318   {
319     re_encode_u32 (dest_p, cp);
320     return;
321   }
322 #endif /* ENABLED (JERRY_ES2015) */
323 
324   JERRY_ASSERT (cp <= LIT_UTF16_CODE_UNIT_MAX);
325   re_encode_u16 (dest_p, (ecma_char_t) cp);
326 } /* re_insert_char */
327 
328 /**
329  * Decode a character from the bytecode.
330  *
331  * @return decoded character
332  */
333 inline lit_code_point_t JERRY_ATTR_ALWAYS_INLINE
re_get_char(const uint8_t ** bc_p,bool unicode)334 re_get_char (const uint8_t **bc_p, /**< reference to bytecode pointer */
335              bool unicode) /**< full unicode mode */
336 {
337   lit_code_point_t cp;
338 
339 #if !ENABLED (JERRY_ES2015)
340   JERRY_UNUSED (unicode);
341 #else /* ENABLED (JERRY_ES2015) */
342   if (unicode)
343   {
344     cp = re_decode_u32 (*bc_p);
345     *bc_p += sizeof (lit_code_point_t);
346   }
347   else
348 #endif /* ENABLED (JERRY_ES2015) */
349   {
350     cp = re_decode_u16 (*bc_p);
351     *bc_p += sizeof (ecma_char_t);
352   }
353 
354   return cp;
355 } /* re_get_char */
356 
357 #if ENABLED (JERRY_REGEXP_DUMP_BYTE_CODE)
358 static uint32_t
re_get_bytecode_offset(const uint8_t * start_p,const uint8_t * current_p)359 re_get_bytecode_offset (const uint8_t *start_p, /**< bytecode start pointer */
360                         const uint8_t *current_p) /**< current bytecode pointer */
361 {
362   return (uint32_t) ((uintptr_t) current_p - (uintptr_t) start_p);
363 } /* re_get_bytecode_offset */
364 
365 /**
366  * RegExp bytecode dumper
367  */
368 void
re_dump_bytecode(re_compiler_ctx_t * re_ctx_p)369 re_dump_bytecode (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */
370 {
371   static const char escape_chars[] = {'d', 'D', 'w', 'W', 's', 'S'};
372 
373   re_compiled_code_t *compiled_code_p = (re_compiled_code_t *) re_ctx_p->bytecode_start_p;
374   JERRY_DEBUG_MSG ("Flags: 0x%x ", compiled_code_p->header.status_flags);
375   JERRY_DEBUG_MSG ("Capturing groups: %d ", compiled_code_p->captures_count);
376   JERRY_DEBUG_MSG ("Non-capturing groups: %d\n", compiled_code_p->non_captures_count);
377 
378   const uint8_t *bytecode_start_p = (const uint8_t *) (compiled_code_p + 1);
379   const uint8_t *bytecode_p = bytecode_start_p;
380 
381   while (true)
382   {
383     JERRY_DEBUG_MSG ("[%3u] ", (uint32_t) ((uintptr_t) bytecode_p - (uintptr_t) bytecode_start_p));
384     re_opcode_t op = *bytecode_p++;
385     switch (op)
386     {
387       case RE_OP_ALTERNATIVE_START:
388       {
389         JERRY_DEBUG_MSG ("ALTERNATIVE_START ");
390         const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
391         JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
392         break;
393       }
394       case RE_OP_ALTERNATIVE_NEXT:
395       {
396         JERRY_DEBUG_MSG ("ALTERNATIVE_NEXT ");
397         const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
398         JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
399         break;
400       }
401       case RE_OP_NO_ALTERNATIVE:
402       {
403         JERRY_DEBUG_MSG ("NO_ALTERNATIVES\n");
404         break;
405       }
406       case RE_OP_CAPTURING_GROUP_START:
407       {
408         JERRY_DEBUG_MSG ("CAPTURING_GROUP_START ");
409         JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
410         JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p));
411 
412         const uint32_t qmin = re_get_value (&bytecode_p);
413         JERRY_DEBUG_MSG ("qmin: %u", qmin);
414         if (qmin == 0)
415         {
416           const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
417           JERRY_DEBUG_MSG (", tail offset: [%3u]\n", offset);
418         }
419         else
420         {
421           JERRY_DEBUG_MSG ("\n");
422         }
423 
424         break;
425       }
426       case RE_OP_NON_CAPTURING_GROUP_START:
427       {
428         JERRY_DEBUG_MSG ("NON_CAPTURING_GROUP_START ");
429         JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
430         JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p));
431         JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p));
432 
433         const uint32_t qmin = re_get_value (&bytecode_p);
434         JERRY_DEBUG_MSG ("qmin: %u", qmin);
435         if (qmin == 0)
436         {
437           const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
438           JERRY_DEBUG_MSG (", tail offset: [%3u]\n", offset);
439         }
440         else
441         {
442           JERRY_DEBUG_MSG ("\n");
443         }
444 
445         break;
446       }
447       case RE_OP_GREEDY_CAPTURING_GROUP_END:
448       {
449         JERRY_DEBUG_MSG ("GREEDY_CAPTURING_GROUP_END ");
450         JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
451         JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
452         JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
453         break;
454       }
455       case RE_OP_LAZY_CAPTURING_GROUP_END:
456       {
457         JERRY_DEBUG_MSG ("LAZY_CAPTURING_GROUP_END ");
458         JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
459         JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
460         JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
461         break;
462       }
463       case RE_OP_GREEDY_NON_CAPTURING_GROUP_END:
464       {
465         JERRY_DEBUG_MSG ("GREEDY_NON_CAPTURING_GROUP_END ");
466         JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
467         JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
468         JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
469         break;
470       }
471       case RE_OP_LAZY_NON_CAPTURING_GROUP_END:
472       {
473         JERRY_DEBUG_MSG ("LAZY_NON_CAPTURING_GROUP_END ");
474         JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
475         JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
476         JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
477         break;
478       }
479       case RE_OP_GREEDY_ITERATOR:
480       {
481         JERRY_DEBUG_MSG ("GREEDY_ITERATOR ");
482         JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
483         JERRY_DEBUG_MSG ("qmax: %u, ", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
484         const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
485         JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
486         break;
487       }
488       case RE_OP_LAZY_ITERATOR:
489       {
490         JERRY_DEBUG_MSG ("LAZY_ITERATOR ");
491         JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
492         JERRY_DEBUG_MSG ("qmax: %u, ", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
493         const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
494         JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
495         break;
496       }
497       case RE_OP_ITERATOR_END:
498       {
499         JERRY_DEBUG_MSG ("ITERATOR_END\n");
500         break;
501       }
502       case RE_OP_BACKREFERENCE:
503       {
504         JERRY_DEBUG_MSG ("BACKREFERENCE ");
505         JERRY_DEBUG_MSG ("idx: %d\n", re_get_value (&bytecode_p));
506         break;
507       }
508       case RE_OP_ASSERT_LINE_START:
509       {
510         JERRY_DEBUG_MSG ("ASSERT_LINE_START\n");
511         break;
512       }
513       case RE_OP_ASSERT_LINE_END:
514       {
515         JERRY_DEBUG_MSG ("ASSERT_LINE_END\n");
516         break;
517       }
518       case RE_OP_ASSERT_LOOKAHEAD_POS:
519       {
520         JERRY_DEBUG_MSG ("ASSERT_LOOKAHEAD_POS ");
521         JERRY_DEBUG_MSG ("qmin: %u, ", *bytecode_p++);
522         JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p));
523         JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p));
524         const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
525         JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
526         break;
527       }
528       case RE_OP_ASSERT_LOOKAHEAD_NEG:
529       {
530         JERRY_DEBUG_MSG ("ASSERT_LOOKAHEAD_NEG ");
531         JERRY_DEBUG_MSG ("qmin: %u, ", *bytecode_p++);
532         JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p));
533         JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p));
534         const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
535         JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
536         break;
537       }
538       case RE_OP_ASSERT_END:
539       {
540         JERRY_DEBUG_MSG ("ASSERT_END\n");
541         break;
542       }
543       case RE_OP_ASSERT_WORD_BOUNDARY:
544       {
545         JERRY_DEBUG_MSG ("ASSERT_WORD_BOUNDARY\n");
546         break;
547       }
548       case RE_OP_ASSERT_NOT_WORD_BOUNDARY:
549       {
550         JERRY_DEBUG_MSG ("ASSERT_NOT_WORD_BOUNDARY\n");
551         break;
552       }
553       case RE_OP_CLASS_ESCAPE:
554       {
555         ecma_class_escape_t escape = (ecma_class_escape_t) *bytecode_p++;
556         JERRY_DEBUG_MSG ("CLASS_ESCAPE \\%c\n", escape_chars[escape]);
557         break;
558       }
559       case RE_OP_CHAR_CLASS:
560       {
561         JERRY_DEBUG_MSG ("CHAR_CLASS ");
562         uint8_t flags = *bytecode_p++;
563         uint32_t char_count = (flags & RE_CLASS_HAS_CHARS) ? re_get_value (&bytecode_p) : 0;
564         uint32_t range_count = (flags & RE_CLASS_HAS_RANGES) ? re_get_value (&bytecode_p) : 0;
565 
566         if (flags & RE_CLASS_INVERT)
567         {
568           JERRY_DEBUG_MSG ("inverted ");
569         }
570 
571         JERRY_DEBUG_MSG ("escapes: ");
572         uint8_t escape_count = flags & RE_CLASS_ESCAPE_COUNT_MASK;
573         while (escape_count--)
574         {
575           JERRY_DEBUG_MSG ("\\%c, ", escape_chars[*bytecode_p++]);
576         }
577 
578         JERRY_DEBUG_MSG ("chars: ");
579         while (char_count--)
580         {
581           JERRY_DEBUG_MSG ("\\u%04x, ", re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE));
582         }
583 
584         JERRY_DEBUG_MSG ("ranges: ");
585         while (range_count--)
586         {
587           const lit_code_point_t begin = re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE);
588           const lit_code_point_t end = re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE);
589           JERRY_DEBUG_MSG ("\\u%04x-\\u%04x, ", begin, end);
590         }
591 
592         JERRY_DEBUG_MSG ("\n");
593         break;
594       }
595 #if ENABLED (JERRY_ES2015)
596       case RE_OP_UNICODE_PERIOD:
597       {
598         JERRY_DEBUG_MSG ("UNICODE_PERIOD\n");
599         break;
600       }
601 #endif /* ENABLED (JERRY_ES2015) */
602       case RE_OP_PERIOD:
603       {
604         JERRY_DEBUG_MSG ("PERIOD\n");
605         break;
606       }
607       case RE_OP_CHAR:
608       {
609         JERRY_DEBUG_MSG ("CHAR \\u%04x\n", re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE));
610         break;
611       }
612       case RE_OP_BYTE:
613       {
614         const uint8_t ch = *bytecode_p++;
615         JERRY_DEBUG_MSG ("BYTE \\u%04x '%c'\n", ch, (char) ch);
616         break;
617       }
618       case RE_OP_EOF:
619       {
620         JERRY_DEBUG_MSG ("EOF\n");
621         return;
622       }
623       default:
624       {
625         JERRY_DEBUG_MSG ("UNKNOWN(%d)\n", (uint32_t) op);
626         break;
627       }
628     }
629   }
630 } /* re_dump_bytecode */
631 #endif /* ENABLED (JERRY_REGEXP_DUMP_BYTE_CODE) */
632 
633 /**
634  * @}
635  * @}
636  * @}
637  */
638 
639 #endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
640