From cc74bccd10b9d0718fc21d9d138e6efb8388ccaf Mon Sep 17 00:00:00 2001
From: Robert Fancsik <robert.fancsik@h-lab.eu>
Date: Wed, 5 Jan 2022 16:44:35 +0100
Subject: [PATCH] Rework VM dispatch

Overview:
- `VM_OC_*` opcodes are removed, now the dispatch is based on the `CBC`/`CBC_EXT` opcode
- The common argument decoding is removed, now each opcode resolves it's arguments individually using `VM_DECODE_{EXT}_...` macros. Whenever an argument is decoded the dispatcher continues with the same opcode increased by `VM_OPCODE_DECODED_ARG`.
- E.g.: A opcode with 2 literal arguments dispatches as the following:
  - step_1: `case opcode: goto resolve_first_literal`, opcode increment by `VM_OPCODE_DECODED_ARG`, dispatch again (Hidden by macro)
  - step_2: `case VM_OPCODE_ONE_LITERAL(opcode): goto resolve_second_literal`, opcode increment by `VM_OPCODE_DECODED_ARG`, dispatch again (Hidden by macro)
  - step_3: `case VM_OPCODE_TWO_LITERALS (opcode):` Opcode handler implementation goes here.
  - The opcode handler implementation goes as the following:
```c
  case VM_OPCODE_TWO_LITERALS (opcode):
  {
    VM_DECODE_LITERAL_LITERAL (opcode);

   /* use left and right value as before */
  }
```
- The put result block is optimized, each assignment knows whether an ident or property reference should be resolved
- `free_left_value` and `free_both_values` labels are removed, due to the extra long jumps they caused to execute 1 or 2 simple calls.

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik robert.fancsik@h-lab.eu
---
 docs/05.PORT-API.md                   |    3 +-
 jerry-core/api/jerry-snapshot.c       |   73 +-
 jerry-core/api/jerry-snapshot.h       |   16 +-
 jerry-core/include/jerryscript-port.h |    3 +-
 jerry-core/jrt/jrt-fatals.c           |    5 -
 jerry-core/parser/js/byte-code.c      |    4 +-
 jerry-core/parser/js/byte-code.h      |  935 ++++------
 jerry-core/parser/js/js-parser-expr.c |    4 +-
 jerry-core/vm/opcodes.c               |  226 +--
 jerry-core/vm/opcodes.h               |   32 +-
 jerry-core/vm/vm.c                    | 2317 +++++++++++++++++--------
 jerry-core/vm/vm.h                    |  458 +----
 12 files changed, 2123 insertions(+), 1953 deletions(-)

diff --git a/docs/05.PORT-API.md b/docs/05.PORT-API.md
index 4577f598e2..cf4c525e64 100644
--- a/docs/05.PORT-API.md
+++ b/docs/05.PORT-API.md
@@ -26,8 +26,7 @@ typedef enum
 {
   JERRY_FATAL_OUT_OF_MEMORY = 10,
   JERRY_FATAL_REF_COUNT_LIMIT = 12,
-  JERRY_FATAL_DISABLED_BYTE_CODE = 13,
-  JERRY_FATAL_UNTERMINATED_GC_LOOPS = 14,
+  JERRY_FATAL_UNTERMINATED_GC_LOOPS = 13,
   JERRY_FATAL_FAILED_ASSERTION = 120
 } jerry_fatal_code_t;
 ```
diff --git a/jerry-core/api/jerry-snapshot.c b/jerry-core/api/jerry-snapshot.c
index 55e905a4f3..130f1f20aa 100644
--- a/jerry-core/api/jerry-snapshot.c
+++ b/jerry-core/api/jerry-snapshot.c
@@ -34,46 +34,43 @@
 #if JERRY_SNAPSHOT_SAVE || JERRY_SNAPSHOT_EXEC
 
 /**
- * Get snapshot configuration flags.
+ * Get snapshot feature configuration flags.
  *
- * @return configuration flags
+ * @return feature configuration flags
  */
-static inline uint32_t JERRY_ATTR_ALWAYS_INLINE
-snapshot_get_global_flags (bool has_regex, /**< regex literal is present */
-                           bool has_class) /**< class literal is present */
+static inline jerry_snapshot_feature_flags_t
+snapshot_get_feature_flags (void)
 {
-  JERRY_UNUSED (has_regex);
-  JERRY_UNUSED (has_class);
-
-  uint32_t flags = 0;
+  jerry_snapshot_feature_flags_t flags = JERRY_SNAPSHOT_FEATURE_NONE;
 
 #if JERRY_BUILTIN_REGEXP
-  flags |= (has_regex ? JERRY_SNAPSHOT_HAS_REGEX_LITERAL : 0);
+  flags |= JERRY_SNAPSHOT_FEATURE_REGEXP;
 #endif /* JERRY_BUILTIN_REGEXP */
+#if JERRY_MODULE_SYSTEM
+  flags |= JERRY_SNAPSHOT_FEATURE_MODULE;
+#endif /* JERRY_MODULE_SYSTEM */
+#if JERRY_DEBUGGER
+  flags |= JERRY_SNAPSHOT_FEATURE_DEBUGGER;
+#endif /* JERRY_DEBUGGER */
 #if JERRY_ESNEXT
-  flags |= (has_class ? JERRY_SNAPSHOT_HAS_CLASS_LITERAL : 0);
+  flags |= JERRY_SNAPSHOT_FEATURE_ESNEXT;
 #endif /* JERRY_ESNEXT */
 
   return flags;
-} /* snapshot_get_global_flags */
+} /* snapshot_get_feature_flags */
 
 /**
- * Checks whether the global_flags argument matches to the current feature set.
+ * Validate snapshot header
  *
- * @return true if global_flags accepted, false otherwise
+ * @return true - if the header is valid
+ *         false - otherwise
  */
-static inline bool JERRY_ATTR_ALWAYS_INLINE
-snapshot_check_global_flags (uint32_t global_flags) /**< global flags */
+static bool
+snapshot_validate_header (const jerry_snapshot_header_t *header_p)
 {
-#if JERRY_BUILTIN_REGEXP
-  global_flags &= (uint32_t) ~JERRY_SNAPSHOT_HAS_REGEX_LITERAL;
-#endif /* JERRY_BUILTIN_REGEXP */
-#if JERRY_ESNEXT
-  global_flags &= (uint32_t) ~JERRY_SNAPSHOT_HAS_CLASS_LITERAL;
-#endif /* JERRY_ESNEXT */
-
-  return global_flags == snapshot_get_global_flags (false, false);
-} /* snapshot_check_global_flags */
+  return (header_p->magic == JERRY_SNAPSHOT_MAGIC && header_p->version == JERRY_SNAPSHOT_VERSION
+          && (header_p->feature_flags & snapshot_get_feature_flags ()) == header_p->feature_flags);
+} /* snapshot_validate_header */
 
 #endif /* JERRY_SNAPSHOT_SAVE || JERRY_SNAPSHOT_EXEC */
 
@@ -86,8 +83,6 @@ typedef struct
 {
   size_t snapshot_buffer_write_offset;
   ecma_value_t snapshot_error;
-  bool regex_found;
-  bool class_found;
 } snapshot_globals_t;
 
 /** \addtogroup jerrysnapshot Jerry snapshot operations
@@ -171,11 +166,6 @@ snapshot_add_compiled_code (const ecma_compiled_code_t *compiled_code_p, /**< co
       jerry_throw_sz (JERRY_ERROR_RANGE, ecma_get_error_msg (ECMA_ERR_TAGGED_TEMPLATE_LITERALS));
     return 0;
   }
-
-  if (CBC_FUNCTION_GET_TYPE (compiled_code_p->status_flags) == CBC_FUNCTION_CONSTRUCTOR)
-  {
-    globals_p->class_found = true;
-  }
 #endif /* JERRY_ESNEXT */
 
 #if JERRY_BUILTIN_REGEXP
@@ -216,7 +206,6 @@ snapshot_add_compiled_code (const ecma_compiled_code_t *compiled_code_p, /**< co
       return 0;
     }
 
-    globals_p->regex_found = true;
     globals_p->snapshot_buffer_write_offset = JERRY_ALIGNUP (globals_p->snapshot_buffer_write_offset, JMEM_ALIGNMENT);
 
     /* Regexp character size is stored in refs. */
@@ -788,8 +777,6 @@ jerry_generate_snapshot (jerry_value_t compiled_code, /**< parsed script or func
 
   globals.snapshot_buffer_write_offset = aligned_header_size;
   globals.snapshot_error = ECMA_VALUE_EMPTY;
-  globals.regex_found = false;
-  globals.class_found = false;
 
   if (generate_snapshot_opts & JERRY_SNAPSHOT_SAVE_STATIC)
   {
@@ -808,7 +795,7 @@ jerry_generate_snapshot (jerry_value_t compiled_code, /**< parsed script or func
   jerry_snapshot_header_t header;
   header.magic = JERRY_SNAPSHOT_MAGIC;
   header.version = JERRY_SNAPSHOT_VERSION;
-  header.global_flags = snapshot_get_global_flags (globals.regex_found, globals.class_found);
+  header.feature_flags = (uint32_t) snapshot_get_feature_flags ();
   header.lit_table_offset = (uint32_t) globals.snapshot_buffer_write_offset;
   header.number_of_funcs = 1;
   header.func_offsets[0] = aligned_header_size;
@@ -897,8 +884,7 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
 
   const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) snapshot_data_p;
 
-  if (header_p->magic != JERRY_SNAPSHOT_MAGIC || header_p->version != JERRY_SNAPSHOT_VERSION
-      || !snapshot_check_global_flags (header_p->global_flags))
+  if (!snapshot_validate_header (header_p))
   {
     return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INVALID_SNAPSHOT_VERSION_OR_FEATURES));
   }
@@ -1219,7 +1205,6 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t
 {
 #if JERRY_SNAPSHOT_SAVE
   uint32_t number_of_funcs = 0;
-  uint32_t merged_global_flags = 0;
   size_t functions_size = sizeof (jerry_snapshot_header_t);
 
   if (number_of_snapshots < 2)
@@ -1241,16 +1226,13 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t
 
     const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) inp_buffers_p[i];
 
-    if (header_p->magic != JERRY_SNAPSHOT_MAGIC || header_p->version != JERRY_SNAPSHOT_VERSION
-        || !snapshot_check_global_flags (header_p->global_flags))
+    if (!snapshot_validate_header (header_p))
     {
       *error_p = "invalid snapshot version or unsupported features present";
       ecma_collection_destroy (lit_pool_p);
       return 0;
     }
 
-    merged_global_flags |= header_p->global_flags;
-
     uint32_t start_offset = header_p->func_offsets[0];
     const uint8_t *data_p = (const uint8_t *) inp_buffers_p[i];
     const uint8_t *literal_base_p = data_p + header_p->lit_table_offset;
@@ -1278,7 +1260,7 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t
 
   header_p->magic = JERRY_SNAPSHOT_MAGIC;
   header_p->version = JERRY_SNAPSHOT_VERSION;
-  header_p->global_flags = merged_global_flags;
+  header_p->feature_flags = snapshot_get_feature_flags ();
   header_p->lit_table_offset = (uint32_t) functions_size;
   header_p->number_of_funcs = number_of_funcs;
 
@@ -1555,8 +1537,7 @@ jerry_get_literals_from_snapshot (const uint32_t *snapshot_p, /**< input snapsho
   const uint8_t *snapshot_data_p = (uint8_t *) snapshot_p;
   const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) snapshot_data_p;
 
-  if (snapshot_size <= sizeof (jerry_snapshot_header_t) || header_p->magic != JERRY_SNAPSHOT_MAGIC
-      || header_p->version != JERRY_SNAPSHOT_VERSION || !snapshot_check_global_flags (header_p->global_flags))
+  if (snapshot_size <= sizeof (jerry_snapshot_header_t) || !snapshot_validate_header (header_p))
   {
     /* Invalid snapshot format */
     return 0;
diff --git a/jerry-core/api/jerry-snapshot.h b/jerry-core/api/jerry-snapshot.h
index 94d09178c9..2eab937dc9 100644
--- a/jerry-core/api/jerry-snapshot.h
+++ b/jerry-core/api/jerry-snapshot.h
@@ -27,7 +27,7 @@ typedef struct
    * uint32_t alignment. Otherwise some bytes after the header are wasted. */
   uint32_t magic; /**< four byte magic number */
   uint32_t version; /**< version number */
-  uint32_t global_flags; /**< global configuration and feature flags */
+  uint32_t feature_flags; /**< combination of jerry_snapshot_global_flags_t */
   uint32_t lit_table_offset; /**< byte offset of the literal table */
   uint32_t number_of_funcs; /**< number of primary ECMAScript functions */
   uint32_t func_offsets[1]; /**< function offsets (lowest bit: global(0) or eval(1) context) */
@@ -39,15 +39,15 @@ typedef struct
 #define JERRY_SNAPSHOT_MAGIC (0x5952524Au)
 
 /**
- * Snapshot configuration flags.
+ * Feature flags for snapshot execution.
  */
 typedef enum
 {
-  /* 8 bits are reserved for dynamic features */
-  JERRY_SNAPSHOT_HAS_REGEX_LITERAL = (1u << 0), /**< byte code has regex literal */
-  JERRY_SNAPSHOT_HAS_CLASS_LITERAL = (1u << 1), /**< byte code has class literal */
-  /* 24 bits are reserved for compile time features */
-  JERRY_SNAPSHOT_FOUR_BYTE_CPOINTER = (1u << 8) /**< deprecated, an unused placeholder now */
-} jerry_snapshot_global_flags_t;
+  JERRY_SNAPSHOT_FEATURE_NONE = 0,
+  JERRY_SNAPSHOT_FEATURE_REGEXP = (1u << 0), /**< feature flag for JERRY_BUILTIN_REGEXP */
+  JERRY_SNAPSHOT_FEATURE_MODULE = (1u << 1), /**< feature flag for JERRY_MODULE_SYSTEM */
+  JERRY_SNAPSHOT_FEATURE_DEBUGGER = (1u << 2), /**< feature flag for JERRY_DEBUGGER */
+  JERRY_SNAPSHOT_FEATURE_ESNEXT = (1u << 3), /**< feature flag for JERRY_ESNEXT */
+} jerry_snapshot_feature_flags_t;
 
 #endif /* !JERRY_SNAPSHOT_H */
diff --git a/jerry-core/include/jerryscript-port.h b/jerry-core/include/jerryscript-port.h
index 7317a12b2a..2db89918e0 100644
--- a/jerry-core/include/jerryscript-port.h
+++ b/jerry-core/include/jerryscript-port.h
@@ -44,8 +44,7 @@ typedef enum
 {
   JERRY_FATAL_OUT_OF_MEMORY = 10, /**< Out of memory */
   JERRY_FATAL_REF_COUNT_LIMIT = 12, /**< Reference count limit reached */
-  JERRY_FATAL_DISABLED_BYTE_CODE = 13, /**< Executed disabled instruction */
-  JERRY_FATAL_UNTERMINATED_GC_LOOPS = 14, /**< Garbage collection loop limit reached */
+  JERRY_FATAL_UNTERMINATED_GC_LOOPS = 13, /**< Garbage collection loop limit reached */
   JERRY_FATAL_FAILED_ASSERTION = 120 /**< Assertion failed */
 } jerry_fatal_code_t;
 
diff --git a/jerry-core/jrt/jrt-fatals.c b/jerry-core/jrt/jrt-fatals.c
index c2e09488fa..e7865ff46c 100644
--- a/jerry-core/jrt/jrt-fatals.c
+++ b/jerry-core/jrt/jrt-fatals.c
@@ -47,11 +47,6 @@ jerry_fatal (jerry_fatal_code_t code) /**< status code */
       JERRY_ERROR_MSG ("Error: JERRY_FATAL_UNTERMINATED_GC_LOOPS\n");
       break;
     }
-    case JERRY_FATAL_DISABLED_BYTE_CODE:
-    {
-      JERRY_ERROR_MSG ("Error: JERRY_FATAL_DISABLED_BYTE_CODE\n");
-      break;
-    }
     case JERRY_FATAL_FAILED_ASSERTION:
     {
       JERRY_ERROR_MSG ("Error: JERRY_FATAL_FAILED_ASSERTION\n");
diff --git a/jerry-core/parser/js/byte-code.c b/jerry-core/parser/js/byte-code.c
index 4ba63cd3d1..429ad1cea5 100644
--- a/jerry-core/parser/js/byte-code.c
+++ b/jerry-core/parser/js/byte-code.c
@@ -45,7 +45,7 @@ JERRY_STATIC_ASSERT (CBC_EXT_END == 167, number_of_cbc_ext_opcodes_changed);
 /**
  * Compact bytecode definition
  */
-#define CBC_OPCODE(arg1, arg2, arg3, arg4) ((arg2) | (((arg3) + CBC_STACK_ADJUST_BASE) << CBC_STACK_ADJUST_SHIFT)),
+#define CBC_OPCODE(arg1, arg2, arg3) ((arg2) | (((arg3) + CBC_STACK_ADJUST_BASE) << CBC_STACK_ADJUST_SHIFT)),
 
 /**
  * Flags of the opcodes.
@@ -63,7 +63,7 @@ const uint8_t cbc_ext_flags[] = { CBC_EXT_OPCODE_LIST };
 
 #if JERRY_PARSER_DUMP_BYTE_CODE
 
-#define CBC_OPCODE(arg1, arg2, arg3, arg4) #arg1,
+#define CBC_OPCODE(arg1, arg2, arg3) #arg1,
 
 /**
  * Names of the opcodes.
diff --git a/jerry-core/parser/js/byte-code.h b/jerry-core/parser/js/byte-code.h
index 18d5325e9d..f94a13df41 100644
--- a/jerry-core/parser/js/byte-code.h
+++ b/jerry-core/parser/js/byte-code.h
@@ -86,40 +86,22 @@
                                         == (cbc_ext_flags[PARSER_GET_EXT_OPCODE (op2)] & CBC_ARG_TYPES)) \
                                      : ((cbc_flags[op1] & CBC_ARG_TYPES) == (cbc_flags[op2] & CBC_ARG_TYPES)))
 
-#define CBC_UNARY_OPERATION(name, group)                                                 \
-  CBC_OPCODE (name, CBC_NO_FLAG, 0, (VM_OC_##group) | VM_OC_GET_STACK | VM_OC_PUT_STACK) \
-  CBC_OPCODE (name##_LITERAL, CBC_HAS_LITERAL_ARG, 1, (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_STACK)
-
-#define CBC_BINARY_OPERATION(name, group)                                                       \
-  CBC_OPCODE (name, CBC_NO_FLAG, -1, (VM_OC_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \
-  CBC_OPCODE (name##_RIGHT_LITERAL,                                                             \
-              CBC_HAS_LITERAL_ARG,                                                              \
-              0,                                                                                \
-              (VM_OC_##group) | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK)                      \
-  CBC_OPCODE (name##_TWO_LITERALS,                                                              \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                       \
-              1,                                                                                \
-              (VM_OC_##group) | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK)
-
-#define CBC_UNARY_LVALUE_OPERATION(name, group)                                                            \
-  CBC_OPCODE (name, CBC_NO_FLAG, -2, (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE)   \
-  CBC_OPCODE (name##_PUSH_RESULT,                                                                          \
-              CBC_NO_FLAG,                                                                                 \
-              -1,                                                                                          \
-              (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK)        \
-  CBC_OPCODE (name##_BLOCK,                                                                                \
-              CBC_NO_FLAG,                                                                                 \
-              -2,                                                                                          \
-              (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK)        \
-  CBC_OPCODE (name##_IDENT, CBC_HAS_LITERAL_ARG, 0, (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \
-  CBC_OPCODE (name##_IDENT_PUSH_RESULT,                                                                    \
-              CBC_HAS_LITERAL_ARG,                                                                         \
-              1,                                                                                           \
-              (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_STACK)                     \
-  CBC_OPCODE (name##_IDENT_BLOCK,                                                                          \
-              CBC_HAS_LITERAL_ARG,                                                                         \
-              0,                                                                                           \
-              (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK)
+#define CBC_UNARY_OPERATION(name)   \
+  CBC_OPCODE (name, CBC_NO_FLAG, 0) \
+  CBC_OPCODE (name##_LITERAL, CBC_HAS_LITERAL_ARG, 1)
+
+#define CBC_BINARY_OPERATION(name)                          \
+  CBC_OPCODE (name, CBC_NO_FLAG, -1)                        \
+  CBC_OPCODE (name##_RIGHT_LITERAL, CBC_HAS_LITERAL_ARG, 0) \
+  CBC_OPCODE (name##_TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1)
+
+#define CBC_UNARY_LVALUE_OPERATION(name)                        \
+  CBC_OPCODE (name, CBC_NO_FLAG, -2)                            \
+  CBC_OPCODE (name##_PUSH_RESULT, CBC_NO_FLAG, -1)              \
+  CBC_OPCODE (name##_BLOCK, CBC_NO_FLAG, -2)                    \
+  CBC_OPCODE (name##_IDENT, CBC_HAS_LITERAL_ARG, 0)             \
+  CBC_OPCODE (name##_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 1) \
+  CBC_OPCODE (name##_IDENT_BLOCK, CBC_HAS_LITERAL_ARG, 0)
 
 #define CBC_UNARY_LVALUE_WITH_IDENT 3
 
@@ -166,15 +148,15 @@
  * The offset bytes are encoded in higher to lower order.
  */
 
-#define CBC_FORWARD_BRANCH(name, stack, vm_oc)                                                          \
-  CBC_OPCODE (name, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH)     \
-  CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH) \
-  CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH)
+#define CBC_FORWARD_BRANCH(name, stack)                                     \
+  CBC_OPCODE (name, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack)     \
+  CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack) \
+  CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack)
 
-#define CBC_BACKWARD_BRANCH(name, stack, vm_oc)                                                        \
-  CBC_OPCODE (name, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH)     \
-  CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) \
-  CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH)
+#define CBC_BACKWARD_BRANCH(name, stack)           \
+  CBC_OPCODE (name, CBC_HAS_BRANCH_ARG, stack)     \
+  CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG, stack) \
+  CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG, stack)
 
 #define CBC_BRANCH_OFFSET_LENGTH(opcode) ((opcode) &0x3)
 
@@ -216,542 +198,345 @@
 /**
  * Opcode definitions.
  */
-#define CBC_OPCODE_LIST                                                                                             \
-  /* Branch opcodes first. Some other opcodes are mixed. */                                                         \
-  CBC_OPCODE (CBC_EXT_OPCODE, CBC_NO_FLAG, 0, VM_OC_NONE)                                                           \
-  CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD, 0, VM_OC_JUMP)                                                              \
-  CBC_OPCODE (CBC_POP, CBC_NO_FLAG, -1, VM_OC_POP)                                                                  \
-  CBC_BACKWARD_BRANCH (CBC_JUMP_BACKWARD, 0, VM_OC_JUMP)                                                            \
-  CBC_OPCODE (CBC_POP_BLOCK, CBC_NO_FLAG, -1, VM_OC_POP_BLOCK | VM_OC_PUT_BLOCK)                                    \
-  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_TRUE_FORWARD, -1, VM_OC_BRANCH_IF_TRUE)                                         \
-  CBC_OPCODE (CBC_THROW, CBC_NO_FLAG, -1, VM_OC_THROW | VM_OC_GET_STACK)                                            \
-  CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_TRUE_BACKWARD, -1, VM_OC_BRANCH_IF_TRUE)                                       \
-  CBC_OPCODE (CBC_CONTEXT_END, CBC_NO_FLAG, 0, VM_OC_CONTEXT_END)                                                   \
-  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_FALSE_FORWARD, -1, VM_OC_BRANCH_IF_FALSE)                                       \
-  CBC_OPCODE (CBC_CREATE_OBJECT, CBC_NO_FLAG, 1, VM_OC_PUSH_OBJECT | VM_OC_PUT_STACK)                               \
-  CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_FALSE_BACKWARD, -1, VM_OC_BRANCH_IF_FALSE)                                     \
-  CBC_OPCODE (CBC_SET_PROPERTY,                                                                                     \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              -1,                                                                                                   \
-              VM_OC_SET_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL)                                 \
-  CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD_EXIT_CONTEXT, 0, VM_OC_JUMP_AND_EXIT_CONTEXT)                                \
-  CBC_OPCODE (CBC_CREATE_ARRAY, CBC_NO_FLAG, 1, VM_OC_PUSH_ARRAY | VM_OC_PUT_STACK)                                 \
-  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE, -1, VM_OC_BRANCH_IF_LOGICAL_TRUE)                                 \
-  CBC_OPCODE (CBC_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_APPEND_ARRAY)                                  \
-  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE, -1, VM_OC_BRANCH_IF_LOGICAL_FALSE)                               \
-  CBC_OPCODE (CBC_PUSH_ELISION, CBC_NO_FLAG, 1, VM_OC_PUSH_ELISON | VM_OC_PUT_STACK)                                \
-  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL, -1, VM_OC_BRANCH_IF_STRICT_EQUAL)                                 \
-  CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1, VM_OC_PUSH_NULL | VM_OC_PUT_STACK)                                     \
-  CBC_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION, VM_OC_BLOCK_CREATE_CONTEXT)  \
-                                                                                                                    \
-  /* Basic opcodes. Note: These 4 opcodes must me in this order */                                                  \
-  CBC_OPCODE (CBC_PUSH_LITERAL, CBC_HAS_LITERAL_ARG, 1, VM_OC_PUSH | VM_OC_GET_LITERAL)                             \
-  CBC_OPCODE (CBC_PUSH_TWO_LITERALS,                                                                                \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                           \
-              2,                                                                                                    \
-              VM_OC_PUSH_TWO | VM_OC_GET_LITERAL_LITERAL)                                                           \
-  CBC_OPCODE (CBC_PUSH_THIS_LITERAL, CBC_HAS_LITERAL_ARG, 2, VM_OC_PUSH_TWO | VM_OC_GET_THIS_LITERAL)               \
-  CBC_OPCODE (CBC_PUSH_THREE_LITERALS, CBC_HAS_LITERAL_ARG2, 3, VM_OC_PUSH_THREE | VM_OC_GET_LITERAL_LITERAL)       \
-  CBC_OPCODE (CBC_PUSH_UNDEFINED, CBC_NO_FLAG, 1, VM_OC_PUSH_UNDEFINED | VM_OC_PUT_STACK)                           \
-  CBC_OPCODE (CBC_PUSH_TRUE, CBC_NO_FLAG, 1, VM_OC_PUSH_TRUE | VM_OC_PUT_STACK)                                     \
-  CBC_OPCODE (CBC_PUSH_FALSE, CBC_NO_FLAG, 1, VM_OC_PUSH_FALSE | VM_OC_PUT_STACK)                                   \
-  CBC_OPCODE (CBC_PUSH_THIS, CBC_NO_FLAG, 1, VM_OC_PUSH_THIS | VM_OC_PUT_STACK)                                     \
-  CBC_OPCODE (CBC_PUSH_NUMBER_0, CBC_NO_FLAG, 1, VM_OC_PUSH_0 | VM_OC_PUT_STACK)                                    \
-  CBC_OPCODE (CBC_PUSH_NUMBER_POS_BYTE, CBC_HAS_BYTE_ARG, 1, VM_OC_PUSH_POS_BYTE | VM_OC_PUT_STACK)                 \
-  CBC_OPCODE (CBC_PUSH_NUMBER_NEG_BYTE, CBC_HAS_BYTE_ARG, 1, VM_OC_PUSH_NEG_BYTE | VM_OC_PUT_STACK)                 \
-  CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_0, CBC_HAS_LITERAL_ARG, 2, VM_OC_PUSH_LIT_0 | VM_OC_GET_LITERAL)         \
-  CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE,                                                                \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG,                                                               \
-              2,                                                                                                    \
-              VM_OC_PUSH_LIT_POS_BYTE | VM_OC_GET_LITERAL)                                                          \
-  CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE,                                                                \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG,                                                               \
-              2,                                                                                                    \
-              VM_OC_PUSH_LIT_NEG_BYTE | VM_OC_GET_LITERAL)                                                          \
-  /* Note: These 4 opcodes must me in this order */                                                                 \
-  CBC_OPCODE (CBC_PUSH_PROP, CBC_NO_FLAG, -1, VM_OC_PROP_GET | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK)             \
-  CBC_OPCODE (CBC_PUSH_PROP_LITERAL,                                                                                \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              0,                                                                                                    \
-              VM_OC_PROP_GET | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK)                                           \
-  CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL,                                                                        \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                           \
-              1,                                                                                                    \
-              VM_OC_PROP_GET | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK)                                         \
-  CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL,                                                                           \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              1,                                                                                                    \
-              VM_OC_PROP_GET | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK)                                            \
-  CBC_OPCODE (CBC_PUSH_IDENT_REFERENCE, CBC_HAS_LITERAL_ARG, 3, VM_OC_IDENT_REFERENCE | VM_OC_PUT_STACK)            \
-  /* Note: These 4 opcodes must me in this order */                                                                 \
-  CBC_OPCODE (CBC_PUSH_PROP_REFERENCE, CBC_NO_FLAG, 1, VM_OC_PROP_REFERENCE | VM_OC_PUT_STACK)                      \
-  CBC_OPCODE (CBC_PUSH_PROP_LITERAL_REFERENCE,                                                                      \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              2,                                                                                                    \
-              VM_OC_PROP_REFERENCE | VM_OC_GET_LITERAL | VM_OC_PUT_STACK)                                           \
-  CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE,                                                              \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                           \
-              3,                                                                                                    \
-              VM_OC_PROP_REFERENCE | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK)                                   \
-  CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE,                                                                 \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              3,                                                                                                    \
-              VM_OC_PROP_REFERENCE | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK)                                      \
-  CBC_OPCODE (CBC_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_NEW | VM_OC_PUT_STACK)                                  \
-  CBC_OPCODE (CBC_NEW0, CBC_NO_FLAG, 0, VM_OC_NEW | VM_OC_PUT_STACK)                                                \
-  CBC_OPCODE (CBC_NEW1, CBC_NO_FLAG, -1, VM_OC_NEW | VM_OC_PUT_STACK)                                               \
-  CBC_OPCODE (CBC_EVAL, CBC_NO_FLAG, 0, VM_OC_EVAL)                                                                 \
-  CBC_OPCODE (CBC_CHECK_VAR, CBC_HAS_LITERAL_ARG, 0, VM_OC_CHECK_VAR)                                               \
-  CBC_OPCODE (CBC_CHECK_LET, CBC_HAS_LITERAL_ARG, 0, VM_OC_CHECK_LET)                                               \
-  CBC_OPCODE (CBC_CREATE_VAR, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING)                                         \
-  CBC_OPCODE (CBC_CREATE_LET, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING)                                         \
-  CBC_OPCODE (CBC_CREATE_CONST, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING)                                       \
-  CBC_OPCODE (CBC_CREATE_LOCAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING)                                       \
-  CBC_OPCODE (CBC_INIT_ARG_OR_CATCH, CBC_HAS_LITERAL_ARG, -1, VM_OC_INIT_BINDING)                                   \
-  CBC_OPCODE (CBC_INIT_LET, CBC_HAS_LITERAL_ARG, -1, VM_OC_INIT_BINDING)                                            \
-  CBC_OPCODE (CBC_INIT_CONST, CBC_HAS_LITERAL_ARG, -1, VM_OC_INIT_BINDING)                                          \
-  CBC_OPCODE (CBC_INIT_ARG_OR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, VM_OC_INIT_ARG_OR_FUNC)          \
-  CBC_OPCODE (CBC_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_VAR_EVAL)                                          \
-  CBC_OPCODE (CBC_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, VM_OC_VAR_EVAL)              \
-  CBC_OPCODE (CBC_SET_VAR_FUNC,                                                                                     \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                           \
-              0,                                                                                                    \
-              VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT)                                                   \
-  CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0, VM_OC_SET_BYTECODE_PTR)                                         \
-  CBC_OPCODE (CBC_RETURN, CBC_NO_FLAG, -1, VM_OC_RETURN | VM_OC_GET_STACK)                                          \
-  CBC_OPCODE (CBC_RETURN_FUNCTION_END, CBC_NO_FLAG, 0, VM_OC_RETURN_FUNCTION_END)                                   \
-  CBC_OPCODE (CBC_RETURN_WITH_LITERAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_RETURN | VM_OC_GET_LITERAL)                    \
-  CBC_OPCODE (CBC_SET_LITERAL_PROPERTY,                                                                             \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                           \
-              0,                                                                                                    \
-              VM_OC_SET_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL)                               \
-  CBC_OPCODE (CBC_COPY_TO_GLOBAL,                                                                                   \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                           \
-              0,                                                                                                    \
-              VM_OC_COPY_TO_GLOBAL | VM_OC_GET_LITERAL)                                                             \
-  CBC_OPCODE (CBC_BREAKPOINT_ENABLED, CBC_NO_FLAG, 0, VM_OC_BREAKPOINT_ENABLED)                                     \
-  CBC_OPCODE (CBC_BREAKPOINT_DISABLED, CBC_NO_FLAG, 0, VM_OC_BREAKPOINT_DISABLED)                                   \
-                                                                                                                    \
-  /* Unary opcodes. */                                                                                              \
-  CBC_UNARY_OPERATION (CBC_PLUS, PLUS)                                                                              \
-  CBC_UNARY_OPERATION (CBC_NEGATE, MINUS)                                                                           \
-  CBC_UNARY_OPERATION (CBC_LOGICAL_NOT, NOT)                                                                        \
-  CBC_UNARY_OPERATION (CBC_BIT_NOT, BIT_NOT)                                                                        \
-  CBC_UNARY_OPERATION (CBC_VOID, VOID)                                                                              \
-  CBC_OPCODE (CBC_TYPEOF, CBC_NO_FLAG, 0, VM_OC_TYPEOF | VM_OC_GET_STACK | VM_OC_PUT_STACK)                         \
-  CBC_OPCODE (CBC_TYPEOF_IDENT, CBC_HAS_LITERAL_ARG, 1, VM_OC_TYPEOF_IDENT | VM_OC_PUT_STACK)                       \
-                                                                                                                    \
-  /* Binary opcodes. */                                                                                             \
-  CBC_BINARY_OPERATION (CBC_BIT_OR, BIT_OR)                                                                         \
-  CBC_BINARY_OPERATION (CBC_BIT_XOR, BIT_XOR)                                                                       \
-  CBC_BINARY_OPERATION (CBC_BIT_AND, BIT_AND)                                                                       \
-  CBC_BINARY_OPERATION (CBC_EQUAL, EQUAL)                                                                           \
-  CBC_BINARY_OPERATION (CBC_NOT_EQUAL, NOT_EQUAL)                                                                   \
-  CBC_BINARY_OPERATION (CBC_STRICT_EQUAL, STRICT_EQUAL)                                                             \
-  CBC_BINARY_OPERATION (CBC_STRICT_NOT_EQUAL, STRICT_NOT_EQUAL)                                                     \
-  CBC_BINARY_OPERATION (CBC_LESS, LESS)                                                                             \
-  CBC_BINARY_OPERATION (CBC_GREATER, GREATER)                                                                       \
-  CBC_BINARY_OPERATION (CBC_LESS_EQUAL, LESS_EQUAL)                                                                 \
-  CBC_BINARY_OPERATION (CBC_GREATER_EQUAL, GREATER_EQUAL)                                                           \
-  CBC_BINARY_OPERATION (CBC_IN, IN)                                                                                 \
-  CBC_BINARY_OPERATION (CBC_INSTANCEOF, INSTANCEOF)                                                                 \
-  CBC_BINARY_OPERATION (CBC_LEFT_SHIFT, LEFT_SHIFT)                                                                 \
-  CBC_BINARY_OPERATION (CBC_RIGHT_SHIFT, RIGHT_SHIFT)                                                               \
-  CBC_BINARY_OPERATION (CBC_UNS_RIGHT_SHIFT, UNS_RIGHT_SHIFT)                                                       \
-  CBC_BINARY_OPERATION (CBC_ADD, ADD)                                                                               \
-  CBC_BINARY_OPERATION (CBC_SUBTRACT, SUB)                                                                          \
-  CBC_BINARY_OPERATION (CBC_MULTIPLY, MUL)                                                                          \
-  CBC_BINARY_OPERATION (CBC_DIVIDE, DIV)                                                                            \
-  CBC_BINARY_OPERATION (CBC_MODULO, MOD)                                                                            \
-  CBC_BINARY_OPERATION (CBC_EXPONENTIATION, EXP)                                                                    \
-                                                                                                                    \
-  /* Unary lvalue opcodes. */                                                                                       \
-  CBC_OPCODE (CBC_DELETE_PUSH_RESULT, CBC_NO_FLAG, -1, VM_OC_PROP_DELETE | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \
-  CBC_OPCODE (CBC_DELETE_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 1, VM_OC_DELETE | VM_OC_PUT_STACK)                 \
-  CBC_UNARY_LVALUE_OPERATION (CBC_PRE_INCR, PRE_INCR)                                                               \
-  CBC_UNARY_LVALUE_OPERATION (CBC_PRE_DECR, PRE_DECR)                                                               \
-  CBC_UNARY_LVALUE_OPERATION (CBC_POST_INCR, POST_INCR)                                                             \
-  CBC_UNARY_LVALUE_OPERATION (CBC_POST_DECR, POST_DECR)                                                             \
-                                                                                                                    \
-  /* Call opcodes. */                                                                                               \
-  CBC_OPCODE (CBC_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_CALL)                                                 \
-  CBC_OPCODE (CBC_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_CALL | VM_OC_PUT_STACK)                    \
-  CBC_OPCODE (CBC_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_CALL | VM_OC_PUT_BLOCK)                         \
-  CBC_OPCODE (CBC_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_CALL)                                            \
-  CBC_OPCODE (CBC_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2, VM_OC_CALL | VM_OC_PUT_STACK)              \
-  CBC_OPCODE (CBC_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK)                    \
-  CBC_OPCODE (CBC_CALL0, CBC_NO_FLAG, -1, VM_OC_CALL)                                                               \
-  CBC_OPCODE (CBC_CALL0_PUSH_RESULT, CBC_NO_FLAG, 0, VM_OC_CALL | VM_OC_PUT_STACK)                                  \
-  CBC_OPCODE (CBC_CALL0_BLOCK, CBC_NO_FLAG, -1, VM_OC_CALL | VM_OC_PUT_BLOCK)                                       \
-  CBC_OPCODE (CBC_CALL0_PROP, CBC_NO_FLAG, -3, VM_OC_CALL)                                                          \
-  CBC_OPCODE (CBC_CALL0_PROP_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_STACK)                            \
-  CBC_OPCODE (CBC_CALL0_PROP_BLOCK, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK)                                  \
-  CBC_OPCODE (CBC_CALL1, CBC_NO_FLAG, -2, VM_OC_CALL)                                                               \
-  CBC_OPCODE (CBC_CALL1_PUSH_RESULT, CBC_NO_FLAG, -1, VM_OC_CALL | VM_OC_PUT_STACK)                                 \
-  CBC_OPCODE (CBC_CALL1_BLOCK, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_BLOCK)                                       \
-  CBC_OPCODE (CBC_CALL1_PROP, CBC_NO_FLAG, -4, VM_OC_CALL)                                                          \
-  CBC_OPCODE (CBC_CALL1_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_STACK)                            \
-  CBC_OPCODE (CBC_CALL1_PROP_BLOCK, CBC_NO_FLAG, -4, VM_OC_CALL | VM_OC_PUT_BLOCK)                                  \
-  CBC_OPCODE (CBC_CALL2, CBC_NO_FLAG, -3, VM_OC_CALL)                                                               \
-  CBC_OPCODE (CBC_CALL2_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_STACK)                                 \
-  CBC_OPCODE (CBC_CALL2_BLOCK, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK)                                       \
-  CBC_OPCODE (CBC_CALL2_PROP, CBC_NO_FLAG, -4, VM_OC_CALL)                                                          \
-  CBC_OPCODE (CBC_CALL2_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_STACK)                            \
-  CBC_OPCODE (CBC_CALL2_PROP_BLOCK, CBC_NO_FLAG, -4, VM_OC_CALL | VM_OC_PUT_BLOCK)                                  \
-                                                                                                                    \
-  /* Binary assignment opcodes. */                                                                                  \
-  CBC_OPCODE (CBC_ASSIGN, CBC_NO_FLAG, -3, VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE)                    \
-  CBC_OPCODE (CBC_ASSIGN_PUSH_RESULT,                                                                               \
-              CBC_NO_FLAG,                                                                                          \
-              -2,                                                                                                   \
-              VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK)                               \
-  CBC_OPCODE (CBC_ASSIGN_BLOCK,                                                                                     \
-              CBC_NO_FLAG,                                                                                          \
-              -3,                                                                                                   \
-              VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK)                               \
-  CBC_OPCODE (CBC_ASSIGN_SET_IDENT, CBC_HAS_LITERAL_ARG, -1, VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT)      \
-  CBC_OPCODE (CBC_ASSIGN_SET_IDENT_PUSH_RESULT,                                                                     \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              0,                                                                                                    \
-              VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT | VM_OC_PUT_STACK)                                   \
-  CBC_OPCODE (CBC_ASSIGN_SET_IDENT_BLOCK,                                                                           \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              -1,                                                                                                   \
-              VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK)                                   \
-  CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT,                                                                         \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                           \
-              0,                                                                                                    \
-              VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT)                                                   \
-  CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_PUSH_RESULT,                                                             \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                           \
-              1,                                                                                                    \
-              VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_STACK)                                 \
-  CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_BLOCK,                                                                   \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                           \
-              0,                                                                                                    \
-              VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK)                                 \
-  CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL,                                                                              \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              -2,                                                                                                   \
-              VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE)                                          \
-  CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_PUSH_RESULT,                                                                  \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              -1,                                                                                                   \
-              VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK)                        \
-  CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_BLOCK,                                                                        \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              -2,                                                                                                   \
-              VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK)                        \
-  CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL,                                                                         \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              -1,                                                                                                   \
-              VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE)                                     \
-  CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_PUSH_RESULT,                                                             \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              0,                                                                                                    \
-              VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK)                   \
-  CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_BLOCK,                                                                   \
-              CBC_HAS_LITERAL_ARG,                                                                                  \
-              -1,                                                                                                   \
-              VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK)                   \
-  CBC_OPCODE (CBC_MOV_IDENT, CBC_HAS_LITERAL_ARG, -1, VM_OC_MOV_IDENT | VM_OC_GET_STACK | VM_OC_PUT_IDENT)          \
-  CBC_OPCODE (CBC_ASSIGN_LET_CONST, CBC_HAS_LITERAL_ARG, -1, VM_OC_ASSIGN_LET_CONST | VM_OC_GET_STACK)              \
-  CBC_OPCODE (CBC_ASSIGN_LET_CONST_LITERAL,                                                                         \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                           \
-              0,                                                                                                    \
-              VM_OC_ASSIGN_LET_CONST | VM_OC_GET_LITERAL)                                                           \
-                                                                                                                    \
-  /* Last opcode (not a real opcode). */                                                                            \
-  CBC_OPCODE (CBC_END, CBC_NO_FLAG, 0, VM_OC_NONE)
+#define CBC_OPCODE_LIST                                                                                \
+  /* Branch opcodes first. Some other opcodes are mixed. */                                            \
+  CBC_OPCODE (CBC_EXT_OPCODE, CBC_NO_FLAG, 0)                                                          \
+  CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD, 0)                                                             \
+  CBC_OPCODE (CBC_POP, CBC_NO_FLAG, -1)                                                                \
+  CBC_BACKWARD_BRANCH (CBC_JUMP_BACKWARD, 0)                                                           \
+  CBC_OPCODE (CBC_POP_BLOCK, CBC_NO_FLAG, -1)                                                          \
+  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_TRUE_FORWARD, -1)                                                  \
+  CBC_OPCODE (CBC_THROW, CBC_NO_FLAG, -1)                                                              \
+  CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_TRUE_BACKWARD, -1)                                                \
+  CBC_OPCODE (CBC_CONTEXT_END, CBC_NO_FLAG, 0)                                                         \
+  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_FALSE_FORWARD, -1)                                                 \
+  CBC_OPCODE (CBC_CREATE_OBJECT, CBC_NO_FLAG, 1)                                                       \
+  CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_FALSE_BACKWARD, -1)                                               \
+  CBC_OPCODE (CBC_SET_PROPERTY, CBC_HAS_LITERAL_ARG, -1)                                               \
+  CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD_EXIT_CONTEXT, 0)                                                \
+  CBC_OPCODE (CBC_CREATE_ARRAY, CBC_NO_FLAG, 1)                                                        \
+  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE, -1)                                                  \
+  CBC_OPCODE (CBC_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0)                                         \
+  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE, -1)                                                 \
+  CBC_OPCODE (CBC_PUSH_ELISION, CBC_NO_FLAG, 1)                                                        \
+  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL, -1)                                                  \
+  CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1)                                                           \
+  CBC_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION)                 \
+                                                                                                       \
+  /* Basic opcodes. Note: These 4 opcodes must be in this order */                                     \
+  CBC_OPCODE (CBC_PUSH_LITERAL, CBC_HAS_LITERAL_ARG, 1)                                                \
+  CBC_OPCODE (CBC_PUSH_TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 2)                    \
+  CBC_OPCODE (CBC_PUSH_THIS_LITERAL, CBC_HAS_LITERAL_ARG, 2)                                           \
+  CBC_OPCODE (CBC_PUSH_THREE_LITERALS, CBC_HAS_LITERAL_ARG2, 3)                                        \
+  CBC_OPCODE (CBC_PUSH_UNDEFINED, CBC_NO_FLAG, 1)                                                      \
+  CBC_OPCODE (CBC_PUSH_TRUE, CBC_NO_FLAG, 1)                                                           \
+  CBC_OPCODE (CBC_PUSH_FALSE, CBC_NO_FLAG, 1)                                                          \
+  CBC_OPCODE (CBC_PUSH_THIS, CBC_NO_FLAG, 1)                                                           \
+  CBC_OPCODE (CBC_PUSH_NUMBER_0, CBC_NO_FLAG, 1)                                                       \
+  CBC_OPCODE (CBC_PUSH_NUMBER_POS_BYTE, CBC_HAS_BYTE_ARG, 1)                                           \
+  CBC_OPCODE (CBC_PUSH_NUMBER_NEG_BYTE, CBC_HAS_BYTE_ARG, 1)                                           \
+  CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_0, CBC_HAS_LITERAL_ARG, 2)                                  \
+  CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2)        \
+  CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2)        \
+  /* Note: These 4 opcodes must be in this order */                                                    \
+  CBC_OPCODE (CBC_PUSH_PROP, CBC_NO_FLAG, -1)                                                          \
+  CBC_OPCODE (CBC_PUSH_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 0)                                           \
+  CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1)            \
+  CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL, CBC_HAS_LITERAL_ARG, 1)                                      \
+  CBC_OPCODE (CBC_PUSH_IDENT_REFERENCE, CBC_HAS_LITERAL_ARG, 3)                                        \
+  /* Note: These 4 opcodes must be in this order */                                                    \
+  CBC_OPCODE (CBC_PUSH_PROP_REFERENCE, CBC_NO_FLAG, 1)                                                 \
+  CBC_OPCODE (CBC_PUSH_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 2)                                 \
+  CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 3)  \
+  CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3)                            \
+  CBC_OPCODE (CBC_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0)                                                  \
+  CBC_OPCODE (CBC_NEW0, CBC_NO_FLAG, 0)                                                                \
+  CBC_OPCODE (CBC_NEW1, CBC_NO_FLAG, -1)                                                               \
+  CBC_OPCODE (CBC_EVAL, CBC_NO_FLAG, 0)                                                                \
+  CBC_OPCODE (CBC_CHECK_VAR, CBC_HAS_LITERAL_ARG, 0)                                                   \
+  CBC_OPCODE (CBC_CHECK_LET, CBC_HAS_LITERAL_ARG, 0)                                                   \
+  CBC_OPCODE (CBC_CREATE_VAR, CBC_HAS_LITERAL_ARG, 0)                                                  \
+  CBC_OPCODE (CBC_CREATE_LET, CBC_HAS_LITERAL_ARG, 0)                                                  \
+  CBC_OPCODE (CBC_CREATE_CONST, CBC_HAS_LITERAL_ARG, 0)                                                \
+  CBC_OPCODE (CBC_CREATE_LOCAL, CBC_HAS_LITERAL_ARG, 0)                                                \
+  CBC_OPCODE (CBC_INIT_ARG_OR_CATCH, CBC_HAS_LITERAL_ARG, -1)                                          \
+  CBC_OPCODE (CBC_INIT_LET, CBC_HAS_LITERAL_ARG, -1)                                                   \
+  CBC_OPCODE (CBC_INIT_CONST, CBC_HAS_LITERAL_ARG, -1)                                                 \
+  CBC_OPCODE (CBC_INIT_ARG_OR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                     \
+  CBC_OPCODE (CBC_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0)                                             \
+  CBC_OPCODE (CBC_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                 \
+  CBC_OPCODE (CBC_SET_VAR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                         \
+  CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0)                                                    \
+  CBC_OPCODE (CBC_RETURN, CBC_NO_FLAG, -1)                                                             \
+  CBC_OPCODE (CBC_RETURN_FUNCTION_END, CBC_NO_FLAG, 0)                                                 \
+  CBC_OPCODE (CBC_RETURN_WITH_LITERAL, CBC_HAS_LITERAL_ARG, 0)                                         \
+  CBC_OPCODE (CBC_SET_LITERAL_PROPERTY, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                 \
+  CBC_OPCODE (CBC_COPY_TO_GLOBAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                       \
+  CBC_OPCODE (CBC_BREAKPOINT_ENABLED, CBC_NO_FLAG, 0)                                                  \
+  CBC_OPCODE (CBC_BREAKPOINT_DISABLED, CBC_NO_FLAG, 0)                                                 \
+                                                                                                       \
+  /* Unary opcodes. */                                                                                 \
+  CBC_UNARY_OPERATION (CBC_PLUS)                                                                       \
+  CBC_UNARY_OPERATION (CBC_NEGATE)                                                                     \
+  CBC_UNARY_OPERATION (CBC_LOGICAL_NOT)                                                                \
+  CBC_UNARY_OPERATION (CBC_BIT_NOT)                                                                    \
+  CBC_UNARY_OPERATION (CBC_VOID)                                                                       \
+  CBC_OPCODE (CBC_TYPEOF, CBC_NO_FLAG, 0)                                                              \
+  CBC_OPCODE (CBC_TYPEOF_IDENT, CBC_HAS_LITERAL_ARG, 1)                                                \
+                                                                                                       \
+  /* Binary opcodes. */                                                                                \
+  CBC_BINARY_OPERATION (CBC_BIT_OR)                                                                    \
+  CBC_BINARY_OPERATION (CBC_BIT_XOR)                                                                   \
+  CBC_BINARY_OPERATION (CBC_BIT_AND)                                                                   \
+  CBC_BINARY_OPERATION (CBC_EQUAL)                                                                     \
+  CBC_BINARY_OPERATION (CBC_NOT_EQUAL)                                                                 \
+  CBC_BINARY_OPERATION (CBC_STRICT_EQUAL)                                                              \
+  CBC_BINARY_OPERATION (CBC_STRICT_NOT_EQUAL)                                                          \
+  CBC_BINARY_OPERATION (CBC_LESS)                                                                      \
+  CBC_BINARY_OPERATION (CBC_GREATER)                                                                   \
+  CBC_BINARY_OPERATION (CBC_LESS_EQUAL)                                                                \
+  CBC_BINARY_OPERATION (CBC_GREATER_EQUAL)                                                             \
+  CBC_BINARY_OPERATION (CBC_IN)                                                                        \
+  CBC_BINARY_OPERATION (CBC_INSTANCEOF)                                                                \
+  CBC_BINARY_OPERATION (CBC_LEFT_SHIFT)                                                                \
+  CBC_BINARY_OPERATION (CBC_RIGHT_SHIFT)                                                               \
+  CBC_BINARY_OPERATION (CBC_UNS_RIGHT_SHIFT)                                                           \
+  CBC_BINARY_OPERATION (CBC_ADD)                                                                       \
+  CBC_BINARY_OPERATION (CBC_SUBTRACT)                                                                  \
+  CBC_BINARY_OPERATION (CBC_MULTIPLY)                                                                  \
+  CBC_BINARY_OPERATION (CBC_DIVIDE)                                                                    \
+  CBC_BINARY_OPERATION (CBC_MODULO)                                                                    \
+  CBC_BINARY_OPERATION (CBC_EXPONENTIATION)                                                            \
+                                                                                                       \
+  /* Unary lvalue opcodes. */                                                                          \
+  CBC_OPCODE (CBC_DELETE_PUSH_RESULT, CBC_NO_FLAG, -1)                                                 \
+  CBC_OPCODE (CBC_DELETE_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 1)                                    \
+  CBC_UNARY_LVALUE_OPERATION (CBC_PRE_INCR)                                                            \
+  CBC_UNARY_LVALUE_OPERATION (CBC_PRE_DECR)                                                            \
+  CBC_UNARY_LVALUE_OPERATION (CBC_POST_INCR)                                                           \
+  CBC_UNARY_LVALUE_OPERATION (CBC_POST_DECR)                                                           \
+                                                                                                       \
+  /* Call opcodes. */                                                                                  \
+  CBC_OPCODE (CBC_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1)                                                \
+  CBC_OPCODE (CBC_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0)                                     \
+  CBC_OPCODE (CBC_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1)                                          \
+  CBC_OPCODE (CBC_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3)                                           \
+  CBC_OPCODE (CBC_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2)                               \
+  CBC_OPCODE (CBC_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3)                                     \
+  CBC_OPCODE (CBC_CALL0, CBC_NO_FLAG, -1)                                                              \
+  CBC_OPCODE (CBC_CALL0_PUSH_RESULT, CBC_NO_FLAG, 0)                                                   \
+  CBC_OPCODE (CBC_CALL0_BLOCK, CBC_NO_FLAG, -1)                                                        \
+  CBC_OPCODE (CBC_CALL0_PROP, CBC_NO_FLAG, -3)                                                         \
+  CBC_OPCODE (CBC_CALL0_PROP_PUSH_RESULT, CBC_NO_FLAG, -2)                                             \
+  CBC_OPCODE (CBC_CALL0_PROP_BLOCK, CBC_NO_FLAG, -3)                                                   \
+  CBC_OPCODE (CBC_CALL1, CBC_NO_FLAG, -2)                                                              \
+  CBC_OPCODE (CBC_CALL1_PUSH_RESULT, CBC_NO_FLAG, -1)                                                  \
+  CBC_OPCODE (CBC_CALL1_BLOCK, CBC_NO_FLAG, -2)                                                        \
+  CBC_OPCODE (CBC_CALL1_PROP, CBC_NO_FLAG, -4)                                                         \
+  CBC_OPCODE (CBC_CALL1_PROP_PUSH_RESULT, CBC_NO_FLAG, -3)                                             \
+  CBC_OPCODE (CBC_CALL1_PROP_BLOCK, CBC_NO_FLAG, -4)                                                   \
+  CBC_OPCODE (CBC_CALL2, CBC_NO_FLAG, -3)                                                              \
+  CBC_OPCODE (CBC_CALL2_PUSH_RESULT, CBC_NO_FLAG, -2)                                                  \
+  CBC_OPCODE (CBC_CALL2_BLOCK, CBC_NO_FLAG, -3)                                                        \
+  CBC_OPCODE (CBC_CALL2_PROP, CBC_NO_FLAG, -4)                                                         \
+  CBC_OPCODE (CBC_CALL2_PROP_PUSH_RESULT, CBC_NO_FLAG, -3)                                             \
+  CBC_OPCODE (CBC_CALL2_PROP_BLOCK, CBC_NO_FLAG, -4)                                                   \
+                                                                                                       \
+  /* Binary assignment opcodes. */                                                                     \
+  CBC_OPCODE (CBC_ASSIGN, CBC_NO_FLAG, -3)                                                             \
+  CBC_OPCODE (CBC_ASSIGN_PUSH_RESULT, CBC_NO_FLAG, -2)                                                 \
+  CBC_OPCODE (CBC_ASSIGN_BLOCK, CBC_NO_FLAG, -3)                                                       \
+  CBC_OPCODE (CBC_ASSIGN_SET_IDENT, CBC_HAS_LITERAL_ARG, -1)                                           \
+  CBC_OPCODE (CBC_ASSIGN_SET_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 0)                                \
+  CBC_OPCODE (CBC_ASSIGN_SET_IDENT_BLOCK, CBC_HAS_LITERAL_ARG, -1)                                     \
+  CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)             \
+  CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1) \
+  CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_BLOCK, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)       \
+  CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL, CBC_HAS_LITERAL_ARG, -2)                                        \
+  CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_PUSH_RESULT, CBC_HAS_LITERAL_ARG, -1)                            \
+  CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_BLOCK, CBC_HAS_LITERAL_ARG, -2)                                  \
+  CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL, CBC_HAS_LITERAL_ARG, -1)                                   \
+  CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 0)                        \
+  CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_BLOCK, CBC_HAS_LITERAL_ARG, -1)                             \
+  CBC_OPCODE (CBC_MOV_IDENT, CBC_HAS_LITERAL_ARG, -1)                                                  \
+  CBC_OPCODE (CBC_ASSIGN_LET_CONST, CBC_HAS_LITERAL_ARG, -1)                                           \
+  CBC_OPCODE (CBC_ASSIGN_LET_CONST_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)             \
+                                                                                                       \
+  /* Last opcode (not a real opcode). */                                                               \
+  CBC_OPCODE (CBC_END, CBC_NO_FLAG, 0)
 
 /* All EXT branches are statement block end
  * marks, so they are always forward branches. */
 
-#define CBC_EXT_OPCODE_LIST                                                                                            \
-  /* Branch opcodes first. Some other opcodes are mixed. */                                                            \
-  CBC_OPCODE (CBC_EXT_NOP, CBC_NO_FLAG, 0, VM_OC_NONE)                                                                 \
-  CBC_FORWARD_BRANCH (CBC_EXT_WITH_CREATE_CONTEXT, -1 + PARSER_WITH_CONTEXT_STACK_ALLOCATION, VM_OC_WITH)              \
-  CBC_OPCODE (CBC_EXT_FOR_IN_GET_NEXT, CBC_NO_FLAG, 1, VM_OC_FOR_IN_GET_NEXT | VM_OC_PUT_STACK)                        \
-  CBC_FORWARD_BRANCH (CBC_EXT_FOR_IN_INIT, -1 + PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION, VM_OC_FOR_IN_INIT)             \
-  CBC_OPCODE (CBC_EXT_SET_GETTER,                                                                                      \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL)                                    \
-  CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT, 0, VM_OC_FOR_IN_HAS_NEXT)                                    \
-  CBC_OPCODE (CBC_EXT_FOR_OF_GET_NEXT, CBC_NO_FLAG, 1, VM_OC_FOR_OF_GET_NEXT | VM_OC_PUT_STACK)                        \
-  CBC_FORWARD_BRANCH (CBC_EXT_FOR_OF_INIT, -1 + PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION, VM_OC_FOR_OF_INIT)             \
-  CBC_OPCODE (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION,                                                                      \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              1,                                                                                                       \
-              VM_OC_PUSH_NAMED_FUNC_EXPR | VM_OC_GET_LITERAL_LITERAL)                                                  \
-  CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT, 0, VM_OC_FOR_OF_HAS_NEXT)                                    \
-  CBC_OPCODE (CBC_EXT_CLONE_CONTEXT, CBC_NO_FLAG, 0, VM_OC_CLONE_CONTEXT)                                              \
-  CBC_FORWARD_BRANCH (CBC_EXT_FOR_AWAIT_OF_INIT,                                                                       \
-                      -1 + PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION,                                               \
-                      VM_OC_FOR_AWAIT_OF_INIT)                                                                         \
-  CBC_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT, CBC_NO_FLAG, 0, VM_OC_CLONE_CONTEXT)                                         \
-  CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT, 0, VM_OC_FOR_AWAIT_OF_HAS_NEXT)                        \
-  CBC_OPCODE (CBC_EXT_SET_SETTER,                                                                                      \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL)                                    \
-  CBC_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT, PARSER_TRY_CONTEXT_STACK_ALLOCATION, VM_OC_TRY)                      \
-  CBC_OPCODE (CBC_EXT_TRY_CREATE_ENV, CBC_NO_FLAG, 0, VM_OC_BLOCK_CREATE_CONTEXT)                                      \
-  CBC_FORWARD_BRANCH (CBC_EXT_CATCH, 1, VM_OC_CATCH)                                                                   \
-  CBC_OPCODE (CBC_EXT_RESOLVE_BASE, CBC_NO_FLAG, 0, VM_OC_RESOLVE_BASE_FOR_CALL)                                       \
-  CBC_FORWARD_BRANCH (CBC_EXT_FINALLY, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION, VM_OC_FINALLY)                   \
-  CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP, CBC_NO_FLAG, 0, VM_OC_INITIALIZER_PUSH_PROP)                              \
-  CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, -1, VM_OC_DEFAULT_INITIALIZER)                                      \
-  CBC_OPCODE (CBC_EXT_ERROR, CBC_NO_FLAG, 0, VM_OC_ERROR)                                                              \
-  CBC_FORWARD_BRANCH (CBC_EXT_BRANCH_IF_NULLISH, -1, VM_OC_BRANCH_IF_NULLISH)                                          \
-                                                                                                                       \
-  /* Basic opcodes. */                                                                                                 \
-  CBC_OPCODE (CBC_EXT_POP_REFERENCE, CBC_NO_FLAG, -2, VM_OC_POP_REFERENCE)                                             \
-  CBC_OPCODE (CBC_EXT_CREATE_ARGUMENTS, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_ARGUMENTS)                                \
-  CBC_OPCODE (CBC_EXT_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_EXT_VAR_EVAL)                                     \
-  CBC_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, VM_OC_EXT_VAR_EVAL)         \
-  CBC_OPCODE (CBC_EXT_COPY_FROM_ARG, CBC_HAS_LITERAL_ARG, 0, VM_OC_COPY_FROM_ARG)                                      \
-  CBC_OPCODE (CBC_EXT_PUSH_REST_OBJECT, CBC_NO_FLAG, 1, VM_OC_PUSH_REST_OBJECT)                                        \
-  CBC_OPCODE (CBC_EXT_MODULE_IMPORT, CBC_NO_FLAG, 0, VM_OC_MODULE_IMPORT)                                              \
-  CBC_OPCODE (CBC_EXT_MODULE_IMPORT_META, CBC_NO_FLAG, 1, VM_OC_MODULE_IMPORT_META)                                    \
-  CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1, VM_OC_STRING_CONCAT | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK)   \
-  CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL,                                                                     \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              0,                                                                                                       \
-              VM_OC_STRING_CONCAT | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK)                                         \
-  CBC_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS,                                                                      \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              1,                                                                                                       \
-              VM_OC_STRING_CONCAT | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK)                                       \
-  CBC_OPCODE (CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, CBC_HAS_BYTE_ARG, 1, VM_OC_GET_TEMPLATE_OBJECT | VM_OC_PUT_STACK)   \
-  CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1, VM_OC_THROW_REFERENCE_ERROR)                              \
-  CBC_OPCODE (CBC_EXT_THROW_ASSIGN_CONST_ERROR, CBC_NO_FLAG, 0, VM_OC_THROW_CONST_ERROR)                               \
-  CBC_OPCODE (CBC_EXT_REQUIRE_OBJECT_COERCIBLE, CBC_NO_FLAG, 0, VM_OC_REQUIRE_OBJECT_COERCIBLE)                        \
-  CBC_OPCODE (CBC_EXT_COPY_DATA_PROPERTIES, CBC_NO_FLAG, -1, VM_OC_COPY_DATA_PROPERTIES)                               \
-  CBC_OPCODE (CBC_EXT_SET_FUNCTION_NAME, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FUNCTION_NAME | VM_OC_GET_LITERAL)          \
-  CBC_OPCODE (CBC_EXT_SET_CLASS_NAME, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FUNCTION_NAME)                                 \
-  CBC_OPCODE (CBC_EXT_SET_COMPUTED_FUNCTION_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME)                             \
-  CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME)                               \
-  CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME)                               \
-                                                                                                                       \
-  /* Computed / class property related opcodes. */                                                                     \
-  CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY,                                                                           \
-              CBC_NO_FLAG,                                                                                             \
-              -2,                                                                                                      \
-              VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK)                             \
-  CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL,                                                                   \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              -1,                                                                                                      \
-              VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL)                           \
-  CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER,                                                                             \
-              CBC_NO_FLAG,                                                                                             \
-              -2,                                                                                                      \
-              VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK)                                        \
-  CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER,                                                                             \
-              CBC_NO_FLAG,                                                                                             \
-              -2,                                                                                                      \
-              VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK)                                        \
-  CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY, CBC_HAS_LITERAL_ARG, -1, VM_OC_SET_PROPERTY | VM_OC_GET_STACK_LITERAL)      \
-  CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL,                                                                     \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_SET_PROPERTY | VM_OC_GET_LITERAL_LITERAL)                                                          \
-  CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY,                                                                    \
-              CBC_NO_FLAG,                                                                                             \
-              -2,                                                                                                      \
-              VM_OC_SET_COMPUTED_PROPERTY | VM_OC_GET_STACK_STACK)                                                     \
-  CBC_OPCODE (CBC_EXT_SET_STATIC_GETTER,                                                                               \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_SET_GETTER | VM_OC_GET_LITERAL_LITERAL)                                                            \
-  CBC_OPCODE (CBC_EXT_SET_STATIC_SETTER,                                                                               \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_SET_SETTER | VM_OC_GET_LITERAL_LITERAL)                                                            \
-  CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_GETTER, CBC_NO_FLAG, -2, VM_OC_SET_GETTER | VM_OC_GET_STACK_STACK)           \
-  CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_NO_FLAG, -2, VM_OC_SET_SETTER | VM_OC_GET_STACK_STACK)           \
-  CBC_OPCODE (CBC_EXT_SET__PROTO__, CBC_NO_FLAG, -1, VM_OC_SET__PROTO__ | VM_OC_GET_STACK)                             \
-  CBC_OPCODE (CBC_EXT_PUSH_STATIC_FIELD_FUNC,                                                                          \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              1,                                                                                                       \
-              VM_OC_PUSH_STATIC_FIELD_FUNC | VM_OC_GET_LITERAL)                                                        \
-  CBC_OPCODE (CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC,                                                                 \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              0,                                                                                                       \
-              VM_OC_PUSH_STATIC_FIELD_FUNC | VM_OC_GET_LITERAL)                                                        \
-  CBC_OPCODE (CBC_EXT_ADD_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_ADD_COMPUTED_FIELD | VM_OC_GET_STACK)                 \
-  CBC_OPCODE (CBC_EXT_ADD_STATIC_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_ADD_COMPUTED_FIELD | VM_OC_GET_STACK)          \
-  CBC_OPCODE (CBC_EXT_CLASS_CALL_STATIC_BLOCK,                                                                         \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              0,                                                                                                       \
-              VM_OC_CLASS_CALL_STATIC_BLOCK | VM_OC_GET_LITERAL)                                                       \
-  /* Class private property related opcodes */                                                                         \
-  CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE,                                                             \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              2,                                                                                                       \
-              VM_OC_PRIVATE_PROP_REFERENCE | VM_OC_GET_LITERAL | VM_OC_PUT_STACK)                                      \
-  CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL,                                                                       \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              0,                                                                                                       \
-              VM_OC_PRIVATE_PROP_GET | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK)                                      \
-  CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN,                                                                    \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              0,                                                                                                       \
-              VM_OC_PRIVATE_IN | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK)                                            \
-  CBC_OPCODE (CBC_EXT_PRIVATE_FIELD_ADD, CBC_HAS_LITERAL_ARG, -1, VM_OC_PRIVATE_FIELD_ADD | VM_OC_GET_STACK_LITERAL)   \
-  /* These 8 opcodes must be in this order  */                                                                         \
-  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_FIELD,                                                                           \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              0,                                                                                                       \
-              VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL)                                                      \
-  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_METHOD,                                                                          \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL)                                              \
-  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_GETTER,                                                                          \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL)                                              \
-  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_SETTER,                                                                          \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL)                                              \
-  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD,                                                                    \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              0,                                                                                                       \
-              VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL)                                                      \
-  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD,                                                                   \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL)                                              \
-  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER,                                                                   \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL)                                              \
-  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER,                                                                   \
-              CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2,                                                              \
-              0,                                                                                                       \
-              VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL)                                              \
-  /* Class related opcodes. */                                                                                         \
-  CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1, VM_OC_PUSH_CLASS_ENVIRONMENT)                      \
-  CBC_OPCODE (CBC_EXT_DEFINE_FIELD, CBC_HAS_LITERAL_ARG, -1, VM_OC_DEFINE_FIELD | VM_OC_GET_STACK_LITERAL)             \
-  CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR, CBC_NO_FLAG, 1, VM_OC_PUSH_IMPLICIT_CTOR | VM_OC_PUT_STACK)           \
-  CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE, CBC_NO_FLAG, 1, VM_OC_PUSH_IMPLICIT_CTOR | VM_OC_PUT_STACK)  \
-  CBC_OPCODE (CBC_EXT_INIT_CLASS, CBC_NO_FLAG, 0, VM_OC_INIT_CLASS | VM_OC_PUT_STACK)                                  \
-  CBC_OPCODE (CBC_EXT_FINALIZE_NAMED_CLASS, CBC_HAS_LITERAL_ARG, -2, VM_OC_FINALIZE_CLASS)                             \
-  CBC_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS, CBC_NO_FLAG, -2, VM_OC_FINALIZE_CLASS)                                 \
-  CBC_OPCODE (CBC_EXT_SET_FIELD_INIT, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FIELD_INIT | VM_OC_GET_LITERAL)                \
-  CBC_OPCODE (CBC_EXT_RUN_FIELD_INIT, CBC_NO_FLAG, 0, VM_OC_RUN_FIELD_INIT)                                            \
-  CBC_OPCODE (CBC_EXT_RUN_STATIC_FIELD_INIT, CBC_NO_FLAG, -1, VM_OC_RUN_STATIC_FIELD_INIT)                             \
-  CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC,                                                          \
-              CBC_NO_FLAG,                                                                                             \
-              -1,                                                                                                      \
-              VM_OC_SET_NEXT_COMPUTED_FIELD | VM_OC_PUT_REFERENCE)                                                     \
-  CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_SET_NEXT_COMPUTED_FIELD | VM_OC_PUT_REFERENCE)   \
-  CBC_OPCODE (CBC_EXT_PUSH_SUPER, CBC_NO_FLAG, 1, VM_OC_NONE)                                                          \
-  CBC_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR, CBC_NO_FLAG, 1, VM_OC_PUSH_SUPER_CONSTRUCTOR)                            \
-  CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP, CBC_NO_FLAG, 0, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK)                        \
-  CBC_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE, CBC_NO_FLAG, 2, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK)                   \
-  CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1, VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL)      \
-  CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3, VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \
-  CBC_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE, CBC_NO_FLAG, 1, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK)        \
-  CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE,                                                         \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              2,                                                                                                       \
-              VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL)                                                               \
-  CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT, CBC_NO_FLAG, 0, VM_OC_SET_HOME_OBJECT)                           \
-  CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED, CBC_NO_FLAG, 0, VM_OC_SET_HOME_OBJECT)                  \
-  CBC_OPCODE (CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, 1, VM_OC_OBJECT_LITERAL_HOME_ENV)                    \
-  CBC_OPCODE (CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, -1, VM_OC_OBJECT_LITERAL_HOME_ENV)                    \
-  CBC_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS, CBC_NO_FLAG, 1, VM_OC_RESOLVE_LEXICAL_THIS | VM_OC_PUT_STACK)              \
-  CBC_OPCODE (CBC_EXT_LOCAL_EVAL, CBC_HAS_BYTE_ARG, 0, VM_OC_LOCAL_EVAL)                                               \
-  CBC_OPCODE (CBC_EXT_ASSIGN_SUPER, CBC_NO_FLAG, -3, VM_OC_ASSIGN_SUPER)                                               \
-  CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_ASSIGN_SUPER | VM_OC_PUT_STACK)                 \
-  CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_BLOCK, CBC_NO_FLAG, -3, VM_OC_ASSIGN_SUPER | VM_OC_PUT_BLOCK)                       \
-  CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE, CBC_NO_FLAG, -3, VM_OC_ASSIGN_PRIVATE)                                           \
-  CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_ASSIGN_PRIVATE | VM_OC_PUT_STACK)             \
-  CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_BLOCK, CBC_NO_FLAG, -3, VM_OC_ASSIGN_PRIVATE | VM_OC_PUT_BLOCK)                   \
-  CBC_OPCODE (CBC_EXT_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL)                                    \
-  CBC_OPCODE (CBC_EXT_SUPER_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_SUPER_CALL | VM_OC_PUT_STACK)       \
-  CBC_OPCODE (CBC_EXT_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK)            \
-  CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL)                             \
-  CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_PUSH_RESULT,                                                                   \
-              CBC_HAS_POP_STACK_BYTE_ARG,                                                                              \
-              0,                                                                                                       \
-              VM_OC_SUPER_CALL | VM_OC_PUT_STACK)                                                                      \
-  CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK)     \
-                                                                                                                       \
-  /* Spread / rest operation related opcodes. */                                                                       \
-  CBC_OPCODE (CBC_EXT_SPREAD_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SPREAD_ARGUMENTS)                             \
-  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PUSH_RESULT,                                                                         \
-              CBC_HAS_POP_STACK_BYTE_ARG,                                                                              \
-              0,                                                                                                       \
-              VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK)                                                                \
-  CBC_OPCODE (CBC_EXT_SPREAD_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_BLOCK)     \
-  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_SPREAD_ARGUMENTS)                        \
-  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_PUSH_RESULT,                                                                    \
-              CBC_HAS_POP_STACK_BYTE_ARG,                                                                              \
-              -2,                                                                                                      \
-              VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK)                                                                \
-  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK,                                                                          \
-              CBC_HAS_POP_STACK_BYTE_ARG,                                                                              \
-              -3,                                                                                                      \
-              VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_BLOCK)                                                                \
-  CBC_OPCODE (CBC_EXT_PUSH_SPREAD_ELEMENT, CBC_NO_FLAG, 1, VM_OC_PUSH_SPREAD_ELEMENT)                                  \
-  CBC_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_APPEND_ARRAY)                          \
-  CBC_OPCODE (CBC_EXT_REST_INITIALIZER, CBC_NO_FLAG, 1, VM_OC_REST_INITIALIZER)                                        \
-  CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL,                                                                   \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              1,                                                                                                       \
-              VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_LITERAL)                                                         \
-  CBC_OPCODE (CBC_EXT_SPREAD_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK)             \
-                                                                                                                       \
-  /* Iterator related opcodes. */                                                                                      \
-  CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_CREATE,                                                                         \
-              CBC_NO_FLAG,                                                                                             \
-              PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION,                                                                \
-              VM_OC_ITERATOR_CONTEXT_CREATE)                                                                           \
-  CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_END,                                                                            \
-              CBC_NO_FLAG,                                                                                             \
-              -PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION,                                                               \
-              VM_OC_ITERATOR_CONTEXT_END)                                                                              \
-  CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1, VM_OC_ITERATOR_STEP)                                              \
-                                                                                                                       \
-  /* Object initializer related opcodes. */                                                                            \
-  CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_CREATE,                                                                         \
-              CBC_NO_FLAG,                                                                                             \
-              PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION,                                                                \
-              VM_OC_OBJ_INIT_CONTEXT_CREATE)                                                                           \
-  CBC_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE,                                                                    \
-              CBC_NO_FLAG,                                                                                             \
-              PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION,                                                           \
-              VM_OC_OBJ_INIT_CONTEXT_CREATE)                                                                           \
-  CBC_OPCODE (CBC_EXT_OBJ_INIT_PUSH_REST, CBC_NO_FLAG, 1, VM_OC_OBJ_INIT_PUSH_REST)                                    \
-  CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_END,                                                                            \
-              CBC_NO_FLAG,                                                                                             \
-              -PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION,                                                               \
-              VM_OC_OBJ_INIT_CONTEXT_END)                                                                              \
-  CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME, CBC_NO_FLAG, 0, VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_STACK)            \
-  CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL,                                                                   \
-              CBC_HAS_LITERAL_ARG,                                                                                     \
-              1,                                                                                                       \
-              VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_LITERAL)                                                         \
-                                                                                                                       \
-  /* Executable object related opcodes. */                                                                             \
-  CBC_OPCODE (CBC_EXT_CREATE_GENERATOR, CBC_NO_FLAG, 1, VM_OC_CREATE_GENERATOR)                                        \
-  CBC_OPCODE (CBC_EXT_YIELD, CBC_NO_FLAG, 0, VM_OC_YIELD)                                                              \
-  CBC_OPCODE (CBC_EXT_YIELD_ITERATOR, CBC_NO_FLAG, 0, VM_OC_YIELD)                                                     \
-  CBC_OPCODE (CBC_EXT_ASYNC_YIELD, CBC_NO_FLAG, 0, VM_OC_ASYNC_YIELD)                                                  \
-  CBC_OPCODE (CBC_EXT_ASYNC_YIELD_ITERATOR, CBC_NO_FLAG, 0, VM_OC_ASYNC_YIELD_ITERATOR)                                \
-  CBC_OPCODE (CBC_EXT_AWAIT, CBC_NO_FLAG, 0, VM_OC_AWAIT)                                                              \
-  CBC_OPCODE (CBC_EXT_GENERATOR_AWAIT, CBC_NO_FLAG, 0, VM_OC_GENERATOR_AWAIT)                                          \
-  CBC_OPCODE (CBC_EXT_ASYNC_EXIT, CBC_NO_FLAG, 0, VM_OC_ASYNC_EXIT)                                                    \
-  CBC_OPCODE (CBC_EXT_RETURN, CBC_NO_FLAG, -1, VM_OC_EXT_RETURN | VM_OC_GET_STACK)                                     \
-  CBC_OPCODE (CBC_EXT_RETURN_UNDEFINED, CBC_NO_FLAG, 0, VM_OC_EXT_RETURN)                                              \
-  CBC_OPCODE (CBC_EXT_PUSH_NEW_TARGET, CBC_NO_FLAG, 1, VM_OC_PUSH_NEW_TARGET | VM_OC_PUT_STACK)                        \
-                                                                                                                       \
-  /* Last opcode (not a real opcode). */                                                                               \
-  CBC_OPCODE (CBC_EXT_END, CBC_NO_FLAG, 0, VM_OC_NONE)
+#define CBC_EXT_OPCODE_LIST                                                                                     \
+  /* Branch opcodes first. Some other opcodes are mixed. */                                                     \
+  CBC_OPCODE (CBC_EXT_NOP, CBC_NO_FLAG, 0)                                                                      \
+  CBC_FORWARD_BRANCH (CBC_EXT_WITH_CREATE_CONTEXT, -1 + PARSER_WITH_CONTEXT_STACK_ALLOCATION)                   \
+  CBC_OPCODE (CBC_EXT_FOR_IN_GET_NEXT, CBC_NO_FLAG, 1)                                                          \
+  CBC_FORWARD_BRANCH (CBC_EXT_FOR_IN_INIT, -1 + PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION)                         \
+  CBC_OPCODE (CBC_EXT_POP_REFERENCE, CBC_NO_FLAG, -2)                                                           \
+  CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT, 0)                                                    \
+  CBC_OPCODE (CBC_EXT_FOR_OF_GET_NEXT, CBC_NO_FLAG, 1)                                                          \
+  CBC_FORWARD_BRANCH (CBC_EXT_FOR_OF_INIT, -1 + PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION)                         \
+  CBC_OPCODE (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1)                \
+  CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT, 0)                                                    \
+  CBC_OPCODE (CBC_EXT_CLONE_CONTEXT, CBC_NO_FLAG, 0)                                                            \
+  CBC_FORWARD_BRANCH (CBC_EXT_FOR_AWAIT_OF_INIT, -1 + PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION)             \
+  CBC_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT, CBC_NO_FLAG, 0)                                                       \
+  CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT, 0)                                              \
+  CBC_OPCODE (CBC_EXT_CREATE_ARGUMENTS, CBC_HAS_LITERAL_ARG, 0)                                                 \
+  CBC_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT, PARSER_TRY_CONTEXT_STACK_ALLOCATION)                          \
+  CBC_OPCODE (CBC_EXT_TRY_CREATE_ENV, CBC_NO_FLAG, 0)                                                           \
+  CBC_FORWARD_BRANCH (CBC_EXT_CATCH, 1)                                                                         \
+  CBC_OPCODE (CBC_EXT_RESOLVE_BASE, CBC_NO_FLAG, 0)                                                             \
+  CBC_FORWARD_BRANCH (CBC_EXT_FINALLY, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION)                           \
+  CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP, CBC_NO_FLAG, 0)                                                    \
+  CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, -1)                                                          \
+  CBC_OPCODE (CBC_EXT_ERROR, CBC_NO_FLAG, 0)                                                                    \
+  CBC_FORWARD_BRANCH (CBC_EXT_BRANCH_IF_NULLISH, -1)                                                            \
+                                                                                                                \
+  /* Basic opcodes. */                                                                                          \
+  CBC_OPCODE (CBC_EXT_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0)                                                  \
+  CBC_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                      \
+  CBC_OPCODE (CBC_EXT_COPY_FROM_ARG, CBC_HAS_LITERAL_ARG, 0)                                                    \
+  CBC_OPCODE (CBC_EXT_PUSH_REST_OBJECT, CBC_NO_FLAG, 1)                                                         \
+  CBC_OPCODE (CBC_EXT_MODULE_IMPORT, CBC_NO_FLAG, 0)                                                            \
+  CBC_OPCODE (CBC_EXT_MODULE_IMPORT_META, CBC_NO_FLAG, 1)                                                       \
+  /*Note: These 3 opcodes must be in this order */                                                              \
+  CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1)                                                           \
+  CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL, CBC_HAS_LITERAL_ARG, 0)                                      \
+  CBC_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1)                \
+  CBC_OPCODE (CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, CBC_HAS_BYTE_ARG, 1)                                         \
+  CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1)                                                    \
+  CBC_OPCODE (CBC_EXT_THROW_ASSIGN_CONST_ERROR, CBC_NO_FLAG, 0)                                                 \
+  CBC_OPCODE (CBC_EXT_REQUIRE_OBJECT_COERCIBLE, CBC_NO_FLAG, 0)                                                 \
+  CBC_OPCODE (CBC_EXT_COPY_DATA_PROPERTIES, CBC_NO_FLAG, -1)                                                    \
+  CBC_OPCODE (CBC_EXT_SET_FUNCTION_NAME, CBC_HAS_LITERAL_ARG, 0)                                                \
+  CBC_OPCODE (CBC_EXT_SET_CLASS_NAME, CBC_HAS_LITERAL_ARG, 0)                                                   \
+  CBC_OPCODE (CBC_EXT_SET_COMPUTED_FUNCTION_NAME, CBC_NO_FLAG, 0)                                               \
+  CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME, CBC_NO_FLAG, 0)                                                 \
+  CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME, CBC_NO_FLAG, 0)                                                 \
+                                                                                                                \
+  /* Computed / class property related opcodes. */                                                              \
+  CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY, CBC_NO_FLAG, -2)                                                   \
+  CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG, -1)                                   \
+  CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY, CBC_NO_FLAG, -2)                                            \
+  /* Note: These 8 opcodes must be in this order */                                                             \
+  CBC_OPCODE (CBC_EXT_SET_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                                \
+  CBC_OPCODE (CBC_EXT_SET_STATIC_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                         \
+  CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER, CBC_NO_FLAG, -2)                                                     \
+  CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_GETTER, CBC_NO_FLAG, -2)                                              \
+  CBC_OPCODE (CBC_EXT_SET_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                                \
+  CBC_OPCODE (CBC_EXT_SET_STATIC_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                         \
+  CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER, CBC_NO_FLAG, -2)                                                     \
+  CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_NO_FLAG, -2)                                              \
+  CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY, CBC_HAS_LITERAL_ARG, -1)                                             \
+  CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)               \
+  CBC_OPCODE (CBC_EXT_SET__PROTO__, CBC_NO_FLAG, -1)                                                            \
+  CBC_OPCODE (CBC_EXT_PUSH_STATIC_FIELD_FUNC, CBC_HAS_LITERAL_ARG, 1)                                           \
+  CBC_OPCODE (CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC, CBC_HAS_LITERAL_ARG, 0)                                  \
+  CBC_OPCODE (CBC_EXT_ADD_COMPUTED_FIELD, CBC_NO_FLAG, -1)                                                      \
+  CBC_OPCODE (CBC_EXT_ADD_STATIC_COMPUTED_FIELD, CBC_NO_FLAG, -1)                                               \
+  CBC_OPCODE (CBC_EXT_CLASS_CALL_STATIC_BLOCK, CBC_HAS_LITERAL_ARG, 0)                                          \
+  /* Class private property related opcodes */                                                                  \
+  CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 2)                              \
+  CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 0)                                        \
+  CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN, CBC_HAS_LITERAL_ARG, 0)                                     \
+  CBC_OPCODE (CBC_EXT_PRIVATE_FIELD_ADD, CBC_HAS_LITERAL_ARG, -1)                                               \
+  /* These 8 opcodes must be in this order  */                                                                  \
+  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_FIELD, CBC_HAS_LITERAL_ARG, 0)                                            \
+  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_METHOD, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                    \
+  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                    \
+  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)                    \
+  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD, CBC_HAS_LITERAL_ARG, 0)                                     \
+  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)             \
+  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)             \
+  CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0)             \
+  /* Class related opcodes. */                                                                                  \
+  CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1)                                             \
+  CBC_OPCODE (CBC_EXT_DEFINE_FIELD, CBC_HAS_LITERAL_ARG, -1)                                                    \
+  CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR, CBC_NO_FLAG, 1)                                                \
+  CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE, CBC_NO_FLAG, 1)                                       \
+  CBC_OPCODE (CBC_EXT_INIT_CLASS, CBC_NO_FLAG, 0)                                                               \
+  CBC_OPCODE (CBC_EXT_FINALIZE_NAMED_CLASS, CBC_HAS_LITERAL_ARG, -2)                                            \
+  CBC_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS, CBC_NO_FLAG, -2)                                                \
+  CBC_OPCODE (CBC_EXT_SET_FIELD_INIT, CBC_HAS_LITERAL_ARG, 0)                                                   \
+  CBC_OPCODE (CBC_EXT_RUN_FIELD_INIT, CBC_NO_FLAG, 0)                                                           \
+  CBC_OPCODE (CBC_EXT_RUN_STATIC_FIELD_INIT, CBC_NO_FLAG, -1)                                                   \
+  CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC, CBC_NO_FLAG, -1)                                  \
+  CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD, CBC_NO_FLAG, -1)                                                 \
+  CBC_OPCODE (CBC_EXT_PUSH_SUPER, CBC_NO_FLAG, 1)                                                               \
+  CBC_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR, CBC_NO_FLAG, 1)                                                   \
+  /* Note: These 4 opcodes must be in this order */                                                             \
+  CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP, CBC_NO_FLAG, 0)                                                          \
+  CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1)                                          \
+  CBC_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE, CBC_NO_FLAG, 2)                                                     \
+  CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3)                                     \
+  CBC_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE, CBC_NO_FLAG, 1)                                          \
+  CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE, CBC_HAS_LITERAL_ARG, 2)                          \
+  /* Note: These 2 opcodes must be in this order */                                                             \
+  CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT, CBC_NO_FLAG, 0)                                           \
+  CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED, CBC_NO_FLAG, 0)                                  \
+  CBC_OPCODE (CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, 1)                                            \
+  CBC_OPCODE (CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, -1)                                            \
+  CBC_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS, CBC_NO_FLAG, 1)                                                     \
+  CBC_OPCODE (CBC_EXT_LOCAL_EVAL, CBC_HAS_BYTE_ARG, 0)                                                          \
+  CBC_OPCODE (CBC_EXT_ASSIGN_SUPER, CBC_NO_FLAG, -3)                                                            \
+  CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_PUSH_RESULT, CBC_NO_FLAG, -2)                                                \
+  CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_BLOCK, CBC_NO_FLAG, -3)                                                      \
+  CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE, CBC_NO_FLAG, -3)                                                          \
+  CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_PUSH_RESULT, CBC_NO_FLAG, -2)                                              \
+  CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_BLOCK, CBC_NO_FLAG, -3)                                                    \
+  /* Note: These 6 opcodes must be in this order */                                                             \
+  CBC_OPCODE (CBC_EXT_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1)                                               \
+  CBC_OPCODE (CBC_EXT_SUPER_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0)                                    \
+  CBC_OPCODE (CBC_EXT_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1)                                         \
+  CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1)                                        \
+  CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0)                             \
+  CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1)                                  \
+                                                                                                                \
+  /* Spread / rest operation related opcodes. */                                                                \
+  /* Note: These 9 opcodes must be in this order */                                                             \
+  CBC_OPCODE (CBC_EXT_SPREAD_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1)                                              \
+  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0)                                   \
+  CBC_OPCODE (CBC_EXT_SPREAD_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1)                                        \
+  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3)                                         \
+  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2)                             \
+  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3)                                   \
+  CBC_OPCODE (CBC_EXT_PUSH_SPREAD_ELEMENT, CBC_NO_FLAG, 1)                                                      \
+  CBC_OPCODE (CBC_EXT_SPREAD_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0)                                                \
+  CBC_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0)                                       \
+  CBC_OPCODE (CBC_EXT_REST_INITIALIZER, CBC_NO_FLAG, 1)                                                         \
+  CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1)                                    \
+                                                                                                                \
+  /* Iterator related opcodes. */                                                                               \
+  CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_CREATE, CBC_NO_FLAG, PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION)           \
+  CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_END, CBC_NO_FLAG, -PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION)             \
+  CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1)                                                            \
+                                                                                                                \
+  /* Object initializer related opcodes. */                                                                     \
+  CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_CREATE, CBC_NO_FLAG, PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION)           \
+  CBC_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE, CBC_NO_FLAG, PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION) \
+  CBC_OPCODE (CBC_EXT_OBJ_INIT_PUSH_REST, CBC_NO_FLAG, 1)                                                       \
+  CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_END, CBC_NO_FLAG, -PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION)             \
+  CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME, CBC_NO_FLAG, 0)                                                    \
+  CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL, CBC_HAS_LITERAL_ARG, 1)                                    \
+                                                                                                                \
+  /* Executable object related opcodes. */                                                                      \
+  CBC_OPCODE (CBC_EXT_CREATE_GENERATOR, CBC_NO_FLAG, 1)                                                         \
+  CBC_OPCODE (CBC_EXT_YIELD, CBC_NO_FLAG, 0)                                                                    \
+  CBC_OPCODE (CBC_EXT_YIELD_ITERATOR, CBC_NO_FLAG, 0)                                                           \
+  CBC_OPCODE (CBC_EXT_ASYNC_YIELD, CBC_NO_FLAG, 0)                                                              \
+  CBC_OPCODE (CBC_EXT_ASYNC_YIELD_ITERATOR, CBC_NO_FLAG, 0)                                                     \
+  CBC_OPCODE (CBC_EXT_AWAIT, CBC_NO_FLAG, 0)                                                                    \
+  CBC_OPCODE (CBC_EXT_GENERATOR_AWAIT, CBC_NO_FLAG, 0)                                                          \
+  CBC_OPCODE (CBC_EXT_ASYNC_EXIT, CBC_NO_FLAG, 0)                                                               \
+  CBC_OPCODE (CBC_EXT_RETURN, CBC_NO_FLAG, -1)                                                                  \
+  CBC_OPCODE (CBC_EXT_RETURN_UNDEFINED, CBC_NO_FLAG, 0)                                                         \
+  CBC_OPCODE (CBC_EXT_PUSH_NEW_TARGET, CBC_NO_FLAG, 1)                                                          \
+                                                                                                                \
+  /* Last opcode (not a real opcode). */                                                                        \
+  CBC_OPCODE (CBC_EXT_END, CBC_NO_FLAG, 0)
 
 #define CBC_MAXIMUM_BYTE_VALUE  255
 #define CBC_MAXIMUM_SMALL_VALUE 510
@@ -1018,7 +803,7 @@ typedef struct
 #define CBC_SCRIPT_GET_IMPORT_META(script_p, type) \
   (CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[((type) &CBC_SCRIPT_HAS_USER_VALUE) ? 1 : 0])
 
-#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1,
+#define CBC_OPCODE(arg1, arg2, arg3) arg1,
 
 /**
  * Opcode list.
diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c
index 67b69d2c76..dd76f951a0 100644
--- a/jerry-core/parser/js/js-parser-expr.c
+++ b/jerry-core/parser/js/js-parser-expr.c
@@ -1420,7 +1420,7 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
         uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags);
 
 #if JERRY_ESNEXT
-        if (opcode >= CBC_EXT_SET_COMPUTED_GETTER)
+        if (is_computed)
         {
           literal_index = function_literal_index;
         }
@@ -3487,7 +3487,7 @@ parser_process_binary_assignment_token (parser_context_t *context_p, /**< contex
 
   if (opcode == CBC_ASSIGN_PROP_THIS_LITERAL && (context_p->stack_depth >= context_p->stack_limit))
   {
-    /* Stack limit is increased for VM_OC_ASSIGN_PROP_THIS. Needed by vm.c. */
+    /* Needed by vm.c. */
     JERRY_ASSERT (context_p->stack_depth == context_p->stack_limit);
 
     context_p->stack_limit++;
diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c
index 933a724f0a..93ec7267c8 100644
--- a/jerry-core/vm/opcodes.c
+++ b/jerry-core/vm/opcodes.c
@@ -59,10 +59,10 @@ opfunc_typeof (ecma_value_t left_value) /**< left value */
 /**
  * Update data property for object literals.
  */
-void
-opfunc_set_data_property (ecma_object_t *object_p, /**< object */
-                          ecma_string_t *prop_name_p, /**< data property name */
-                          ecma_value_t value) /**< new value */
+static void
+opfunc_assing_data_property (ecma_object_t *object_p, /**< object */
+                             ecma_string_t *prop_name_p, /**< data property name */
+                             ecma_value_t value) /**< new value */
 {
   JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
 
@@ -96,7 +96,7 @@ opfunc_set_data_property (ecma_object_t *object_p, /**< object */
   }
 
   ecma_named_data_property_assign_value (object_p, prop_value_p, value);
-} /* opfunc_set_data_property */
+} /* opfunc_assing_data_property */
 
 /**
  * Update getter or setter for object literals.
@@ -320,17 +320,15 @@ opfunc_for_in (ecma_value_t iterable_value, /**< ideally an iterable value */
 #if JERRY_ESNEXT
 
 /**
- * 'VM_OC_APPEND_ARRAY' opcode handler specialized for spread objects
+ * 'CBC_EXT_SPREAD_ARRAY_APPEND' opcode handler specialized for spread objects
  *
  * @return ECMA_VALUE_ERROR - if the operation failed
  *         ECMA_VALUE_EMPTY, otherwise
  */
-static ecma_value_t JERRY_ATTR_NOINLINE
+ecma_value_t JERRY_ATTR_NOINLINE
 opfunc_append_to_spread_array (ecma_value_t *stack_top_p, /**< current stack top */
                                uint16_t values_length) /**< number of elements to set */
 {
-  JERRY_ASSERT (!(values_length & OPFUNC_HAS_SPREAD_ELEMENT));
-
   ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]);
   JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY);
 
@@ -501,23 +499,15 @@ opfunc_spread_arguments (ecma_value_t *stack_top_p, /**< pointer to the current
 #endif /* JERRY_ESNEXT */
 
 /**
- * 'VM_OC_APPEND_ARRAY' opcode handler, for setting array object properties
+ * 'CBC_ARRAY_APPEND' opcode handler, for setting array object properties
  *
  * @return ECMA_VALUE_ERROR - if the operation failed
  *         ECMA_VALUE_EMPTY, otherwise
  */
 ecma_value_t JERRY_ATTR_NOINLINE
 opfunc_append_array (ecma_value_t *stack_top_p, /**< current stack top */
-                     uint16_t values_length) /**< number of elements to set
-                                              *   with potential OPFUNC_HAS_SPREAD_ELEMENT flag */
+                     uint16_t values_length) /**< number of elements to set */
 {
-#if JERRY_ESNEXT
-  if (values_length >= OPFUNC_HAS_SPREAD_ELEMENT)
-  {
-    return opfunc_append_to_spread_array (stack_top_p, (uint16_t) (values_length & ~OPFUNC_HAS_SPREAD_ELEMENT));
-  }
-#endif /* JERRY_ESNEXT */
-
   ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]);
   JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY);
 
@@ -1158,8 +1148,8 @@ opfunc_add_computed_field (ecma_value_t class_object, /**< class object */
  * @return - new external function ecma-object
  */
 ecma_value_t
-opfunc_create_implicit_class_constructor (uint8_t opcode, /**< current cbc opcode */
-                                          const ecma_compiled_code_t *bytecode_p) /**< current byte code */
+opfunc_create_implicit_class_constructor (const ecma_compiled_code_t *bytecode_p, /**< current byte code */
+                                          bool is_herigate) /* true -if class heritage is present */
 {
   /* 8. */
   ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value;
@@ -1181,7 +1171,7 @@ opfunc_create_implicit_class_constructor (uint8_t opcode, /**< current cbc opcod
   constructor_object_p->u.constructor_function.flags = 0;
 
   /* 10.a.i */
-  if (opcode == CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE)
+  if (is_herigate)
   {
     constructor_object_p->u.constructor_function.flags |= ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE;
   }
@@ -1574,9 +1564,6 @@ opfunc_collect_private_properties (ecma_value_t constructor, ecma_value_t prop_n
 
   if (opcode == CBC_EXT_COLLECT_PRIVATE_METHOD)
   {
-    prop_name ^= value;
-    value ^= prop_name;
-    prop_name ^= value;
     kind = ECMA_PRIVATE_METHOD;
   }
   else if (opcode == CBC_EXT_COLLECT_PRIVATE_GETTER)
@@ -1977,10 +1964,7 @@ opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
  *         ECMA_VALUE_EMPTY - otherwise
  */
 ecma_value_t
-opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stack top */
-                             vm_frame_ctx_t *frame_ctx_p, /**< frame context */
-                             ecma_value_t prop_name, /**< property name to resolve */
-                             uint8_t opcode) /**< current cbc opcode */
+opfunc_resolve_super (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 {
   ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (frame_ctx_p->lex_env_p);
 
@@ -2001,112 +1985,8 @@ opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stac
     return ECMA_VALUE_ERROR;
   }
 
-  ecma_value_t *stack_top_p = *vm_stack_top_p;
-
-  if (opcode >= CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE)
-  {
-    JERRY_ASSERT (opcode == CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE
-                  || opcode == CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE);
-    *stack_top_p++ = parent;
-    *stack_top_p++ = ecma_copy_value (prop_name);
-    *vm_stack_top_p = stack_top_p;
-
-    return ECMA_VALUE_EMPTY;
-  }
-
-  ecma_object_t *parent_p = ecma_get_object_from_value (parent);
-  ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name);
-
-  if (prop_name_p == NULL)
-  {
-    ecma_deref_object (parent_p);
-    return ECMA_VALUE_ERROR;
-  }
-
-  ecma_value_t result = ecma_op_object_get_with_receiver (parent_p, prop_name_p, frame_ctx_p->this_binding);
-  ecma_deref_ecma_string (prop_name_p);
-  ecma_deref_object (parent_p);
-
-  if (ECMA_IS_VALUE_ERROR (result))
-  {
-    return result;
-  }
-
-  if (opcode == CBC_EXT_SUPER_PROP_LITERAL_REFERENCE || opcode == CBC_EXT_SUPER_PROP_REFERENCE)
-  {
-    *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding);
-    *stack_top_p++ = ECMA_VALUE_UNDEFINED;
-  }
-
-  *stack_top_p++ = result;
-  *vm_stack_top_p = stack_top_p;
-
-  return ECMA_VALUE_EMPTY;
-} /* opfunc_form_super_reference */
-
-/**
- * Assignment operation for SuperRefence base
- *
- * @return ECMA_VALUE_ERROR - if the operation fails
- *         ECMA_VALUE_EMPTY - otherwise
- */
-ecma_value_t
-opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, /**< vm stack top */
-                               vm_frame_ctx_t *frame_ctx_p, /**< frame context */
-                               uint32_t opcode_data) /**< opcode data to store the result */
-{
-  ecma_value_t *stack_top_p = *vm_stack_top_p;
-
-  ecma_value_t base_obj = ecma_op_to_object (stack_top_p[-3]);
-
-  if (ECMA_IS_VALUE_ERROR (base_obj))
-  {
-    return base_obj;
-  }
-
-  ecma_object_t *base_obj_p = ecma_get_object_from_value (base_obj);
-  ecma_string_t *prop_name_p = ecma_op_to_property_key (stack_top_p[-2]);
-
-  if (prop_name_p == NULL)
-  {
-    ecma_deref_object (base_obj_p);
-    return ECMA_VALUE_ERROR;
-  }
-
-  bool is_strict = (frame_ctx_p->status_flags & VM_FRAME_CTX_IS_STRICT) != 0;
-
-  ecma_value_t result =
-    ecma_op_object_put_with_receiver (base_obj_p, prop_name_p, stack_top_p[-1], frame_ctx_p->this_binding, is_strict);
-
-  ecma_deref_ecma_string (prop_name_p);
-  ecma_deref_object (base_obj_p);
-
-  if (ECMA_IS_VALUE_ERROR (result))
-  {
-    return result;
-  }
-
-  for (int32_t i = 1; i <= 3; i++)
-  {
-    ecma_free_value (stack_top_p[-i]);
-  }
-
-  stack_top_p -= 3;
-
-  if (opcode_data & VM_OC_PUT_STACK)
-  {
-    *stack_top_p++ = result;
-  }
-  else if (opcode_data & VM_OC_PUT_BLOCK)
-  {
-    ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0));
-    VM_GET_REGISTERS (frame_ctx_p)[0] = result;
-  }
-
-  *vm_stack_top_p = stack_top_p;
-
-  return result;
-} /* opfunc_assign_super_reference */
+  return parent;
+} /* opfunc_resolve_super */
 
 /**
  * Copy data properties of an object
@@ -2222,7 +2102,7 @@ opfunc_copy_data_properties (ecma_value_t target_object, /**< target object */
       }
     }
 
-    opfunc_set_data_property (target_object_p, property_name_p, result);
+    opfunc_assing_data_property (target_object_p, property_name_p, result);
     ecma_free_value (result);
 
     result = ECMA_VALUE_EMPTY;
@@ -2303,8 +2183,82 @@ opfunc_lexical_scope_has_restricted_binding (vm_frame_ctx_t *frame_ctx_p, /**< f
                                   && !ecma_is_property_configurable (property));
 } /* opfunc_lexical_scope_has_restricted_binding */
 
+/**
+ * Create function name property to the given function object
+ */
+void
+opfunc_set_function_name (ecma_value_t function_object, /**< function object */
+                          ecma_value_t function_name, /**< function name */
+                          char *prefix_p, /**< function name prefix */
+                          lit_utf8_size_t prefix_size) /**< function name prefix's length */
+{
+  ecma_object_t *func_obj_p = ecma_get_object_from_value (function_object);
+
+  if (ecma_find_named_property (func_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_NAME)) != NULL)
+  {
+    return;
+  }
+
+  ecma_property_value_t *value_p;
+  value_p = ecma_create_named_data_property (func_obj_p,
+                                             ecma_get_magic_string (LIT_MAGIC_STRING_NAME),
+                                             ECMA_PROPERTY_FLAG_CONFIGURABLE,
+                                             NULL);
+
+  if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
+  {
+    ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp);
+  }
+
+  value_p->value = ecma_op_function_form_name (ecma_get_prop_name_from_value (function_name), prefix_p, prefix_size);
+} /* opfunc_set_function_name */
+
 #endif /* JERRY_ESNEXT */
 
+/**
+ * Set data property to an object/class
+ *
+ * @return ECMA_VALUE_ERROR - if the operation fails
+ *         ECMA_VALUE_EMPTY - otherwise
+ */
+ecma_value_t
+opfunc_set_data_property (ecma_value_t *stack_top_p, /**< vm stack */
+                          ecma_value_t prop_name, /**< property name to set */
+                          ecma_value_t value, /**< value to set */
+                          bool is_static) /**< true - if set class property
+                                               false - otherwise */
+{
+  ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name);
+
+  if (JERRY_UNLIKELY (prop_name_p == NULL))
+  {
+    return ECMA_VALUE_ERROR;
+  }
+
+  int index = -1;
+
+#if JERRY_ESNEXT
+  if (JERRY_UNLIKELY (is_static))
+  {
+    if (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE))
+    {
+      return ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE);
+    }
+
+    index--;
+  }
+#else /* !JERRY_ESNEXT */
+  JERRY_UNUSED (is_static);
+#endif /* JERRY_ESNEXT */
+
+  ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[index]);
+
+  opfunc_assing_data_property (object_p, prop_name_p, value);
+  ecma_deref_ecma_string (prop_name_p);
+
+  return ECMA_VALUE_EMPTY;
+} /* opfunc_set_data_property */
+
 /**
  * @}
  * @}
diff --git a/jerry-core/vm/opcodes.h b/jerry-core/vm/opcodes.h
index 1657755d1b..415ec748f2 100644
--- a/jerry-core/vm/opcodes.h
+++ b/jerry-core/vm/opcodes.h
@@ -67,11 +67,6 @@ typedef enum
 
 #endif /* JERRY_ESNEXT */
 
-/**
- * The stack contains spread object during the upcoming APPEND_ARRAY operation
- */
-#define OPFUNC_HAS_SPREAD_ELEMENT (1 << 8)
-
 ecma_value_t opfunc_equality (ecma_value_t left_value, ecma_value_t right_value);
 
 ecma_value_t do_number_arithmetic (number_arithmetic_op op, ecma_value_t left_value, ecma_value_t right_value);
@@ -92,8 +87,6 @@ ecma_value_t opfunc_instanceof (ecma_value_t left_value, ecma_value_t right_valu
 
 ecma_value_t opfunc_typeof (ecma_value_t left_value);
 
-void opfunc_set_data_property (ecma_object_t *object_p, ecma_string_t *prop_name_p, ecma_value_t value);
-
 void opfunc_set_accessor (bool is_getter, ecma_value_t object, ecma_string_t *accessor_name_p, ecma_value_t accessor);
 
 ecma_value_t vm_op_delete_prop (ecma_value_t object, ecma_value_t property, bool is_strict);
@@ -102,13 +95,12 @@ ecma_value_t vm_op_delete_var (ecma_value_t name_literal, ecma_object_t *lex_env
 
 ecma_collection_t *opfunc_for_in (ecma_value_t left_value, ecma_value_t *result_obj_p);
 
-#if JERRY_ESNEXT
-ecma_collection_t *opfunc_spread_arguments (ecma_value_t *stack_top_p, uint8_t argument_list_len);
-#endif /* JERRY_ESNEXT */
-
 ecma_value_t opfunc_append_array (ecma_value_t *stack_top_p, uint16_t values_length);
 
 #if JERRY_ESNEXT
+ecma_value_t opfunc_append_to_spread_array (ecma_value_t *stack_top_p, uint16_t values_length);
+
+ecma_collection_t *opfunc_spread_arguments (ecma_value_t *stack_top_p, uint8_t argument_list_len);
 
 vm_executable_object_t *opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p,
                                                          vm_create_executable_object_type_t type);
@@ -128,7 +120,7 @@ ecma_value_t opfunc_init_static_class_fields (ecma_value_t function_object, ecma
 
 ecma_value_t opfunc_add_computed_field (ecma_value_t class_object, ecma_value_t name);
 
-ecma_value_t opfunc_create_implicit_class_constructor (uint8_t opcode, const ecma_compiled_code_t *bytecode_p);
+ecma_value_t opfunc_create_implicit_class_constructor (const ecma_compiled_code_t *bytecode_p, bool is_herigate);
 
 void opfunc_set_home_object (ecma_object_t *func_p, ecma_object_t *parent_env_p);
 
@@ -162,20 +154,22 @@ void opfunc_pop_lexical_environment (vm_frame_ctx_t *frame_ctx_p);
 
 void opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, ecma_value_t **vm_stack_top_p, ecma_value_t class_name);
 
-ecma_value_t opfunc_form_super_reference (ecma_value_t **vm_stack_top_p,
-                                          vm_frame_ctx_t *frame_ctx_p,
-                                          ecma_value_t prop_name,
-                                          uint8_t opcode);
-
-ecma_value_t
-opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, vm_frame_ctx_t *frame_ctx_p, uint32_t opcode_data);
+ecma_value_t opfunc_resolve_super (vm_frame_ctx_t *frame_ctx_p);
 
 ecma_value_t
 opfunc_copy_data_properties (ecma_value_t target_object, ecma_value_t source_object, ecma_value_t filter_array);
 
 ecma_value_t opfunc_lexical_scope_has_restricted_binding (vm_frame_ctx_t *vm_frame_ctx_p, ecma_string_t *name_p);
+
+void opfunc_set_function_name (ecma_value_t function_object,
+                               ecma_value_t function_name,
+                               char *prefix_p,
+                               lit_utf8_size_t prefix_size);
 #endif /* JERRY_ESNEXT */
 
+ecma_value_t
+opfunc_set_data_property (ecma_value_t *stack_top_p, ecma_value_t prop_name, ecma_value_t value, bool is_static);
+
 /**
  * @}
  * @}
diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c
index df7ce69f22..c58d9a5472 100644
--- a/jerry-core/vm/vm.c
+++ b/jerry-core/vm/vm.c
@@ -236,16 +236,6 @@ vm_op_set_value (ecma_value_t base, /**< base object */
   return result;
 } /* vm_op_set_value */
 
-/** Compact bytecode define */
-#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg4,
-
-/**
- * Decode table for both opcodes and extended opcodes.
- */
-static const uint16_t vm_decode_table[] JERRY_ATTR_CONST_DATA = { CBC_OPCODE_LIST CBC_EXT_OPCODE_LIST };
-
-#undef CBC_OPCODE
-
 /**
  * Run global code
  *
@@ -622,13 +612,13 @@ vm_super_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
   else
   {
     frame_ctx_p->byte_code_p = byte_code_p;
-    uint32_t opcode_data = vm_decode_table[(CBC_END + 1) + opcode];
+    vm_put_result_flags_t put_result_flags = (opcode - CBC_EXT_SUPER_CALL) % 3;
 
-    if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
+    if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK)))
     {
       ecma_fast_free_value (completion_value);
     }
-    else if (opcode_data & VM_OC_PUT_STACK)
+    else if (put_result_flags & VM_PUT_RESULT_STACK)
     {
       *frame_ctx_p->stack_top_p++ = completion_value;
     }
@@ -711,13 +701,13 @@ vm_spread_operation (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
   }
   else
   {
-    uint32_t opcode_data = vm_decode_table[(CBC_END + 1) + opcode];
+    vm_put_result_flags_t put_result_flags = (opcode - CBC_EXT_SPREAD_CALL) % 3;
 
-    if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
+    if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK)))
     {
       ecma_fast_free_value (completion_value);
     }
-    else if (opcode_data & VM_OC_PUT_STACK)
+    else if (put_result_flags & VM_PUT_RESULT_STACK)
     {
       *frame_ctx_p->stack_top_p++ = completion_value;
     }
@@ -788,13 +778,13 @@ opfunc_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
   {
     frame_ctx_p->byte_code_p = byte_code_p;
     ecma_free_value (*(--stack_top_p));
-    uint32_t opcode_data = vm_decode_table[opcode];
+    vm_put_result_flags_t put_result_flags = (opcode - CBC_CALL) % 3;
 
-    if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
+    if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK)))
     {
       ecma_fast_free_value (completion_value);
     }
-    else if (opcode_data & VM_OC_PUT_STACK)
+    else if (put_result_flags & VM_PUT_RESULT_STACK)
     {
       *stack_top_p++ = completion_value;
     }
@@ -894,77 +884,546 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
  * When we are able to construct a function with similar speed,
  * we can remove this macro.
  */
-#define READ_LITERAL(literal_index, target_value)                                                 \
-  do                                                                                              \
-  {                                                                                               \
-    if ((literal_index) < ident_end)                                                              \
-    {                                                                                             \
-      if ((literal_index) < register_end)                                                         \
-      {                                                                                           \
-        /* Note: There should be no specialization for arguments. */                              \
-        (target_value) = ecma_fast_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index));     \
-      }                                                                                           \
-      else                                                                                        \
-      {                                                                                           \
-        ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);      \
-                                                                                                  \
-        result = ecma_op_resolve_reference_value (frame_ctx_p->lex_env_p, name_p);                \
-                                                                                                  \
-        if (ECMA_IS_VALUE_ERROR (result))                                                         \
-        {                                                                                         \
-          goto error;                                                                             \
-        }                                                                                         \
-        (target_value) = result;                                                                  \
-      }                                                                                           \
-    }                                                                                             \
-    else if (literal_index < const_literal_end)                                                   \
-    {                                                                                             \
-      (target_value) = ecma_fast_copy_value (literal_start_p[literal_index]);                     \
-    }                                                                                             \
-    else                                                                                          \
-    {                                                                                             \
-      /* Object construction. */                                                                  \
-      (target_value) = vm_construct_literal_object (frame_ctx_p, literal_start_p[literal_index]); \
-    }                                                                                             \
-  } while (0)
+#define READ_LITERAL(literal_index, target_value)                                               \
+  if ((literal_index) < register_end)                                                           \
+  {                                                                                             \
+    /* Note: There should be no specialization for arguments. */                                \
+    (target_value) = ecma_fast_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index));       \
+  }                                                                                             \
+  else if ((literal_index) < ident_end)                                                         \
+  {                                                                                             \
+    ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);        \
+                                                                                                \
+    result = ecma_op_resolve_reference_value (frame_ctx_p->lex_env_p, name_p);                  \
+                                                                                                \
+    if (ECMA_IS_VALUE_ERROR (result))                                                           \
+    {                                                                                           \
+      goto error;                                                                               \
+    }                                                                                           \
+    (target_value) = result;                                                                    \
+  }                                                                                             \
+  else if (literal_index < const_literal_end)                                                   \
+  {                                                                                             \
+    (target_value) = ecma_fast_copy_value (literal_start_p[literal_index]);                     \
+  }                                                                                             \
+  else                                                                                          \
+  {                                                                                             \
+    /* Object construction. */                                                                  \
+    (target_value) = vm_construct_literal_object (frame_ctx_p, literal_start_p[literal_index]); \
+  }
+
+/**
+ * Get the end of the existing topmost context
+ */
+#define VM_LAST_CONTEXT_END() (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth)
 
 /**
- * Store the original value for post increase/decrease operators
+ * VM opcode layout:
  *
- * @param value original value
+ * 0 - 255: CBC opcodes
+ * 256 - 511: decoded CBC opcodes with one literal or branch argument
+ * 511 - 767: decoded CBC opcodes with two literal arguments
+ *
+ * 768 - 1023: CBC_EXTt opcodes
+ * 1024 - 1279: decoded CBC_EXT opcodes with one literal or branch argument
+ * 1280 - 1535: decoded CBC_EXT opcodes with two literal arguments
+ */
+
+/**
+ * Whenver an opcode's argument is decoded in `VM_DECODE_ARGUMENT_OPCODE` block
+ * the opcode is incremented by this offset
+ */
+#define VM_OPCODE_DECODED_ARG 256
+
+/**
+ * Decoded branch CBC opcode
+ */
+#define VM_OPCODE_BRANCH(opcode) (opcode + VM_OPCODE_DECODED_ARG)
+
+/**
+ * Decoded CBC opcode with one literal argument
+ */
+#define VM_OPCODE_ONE_LITERAL(opcode) (opcode + VM_OPCODE_DECODED_ARG)
+
+/**
+ * Decoded CBC opcode with two literal arguments
+ */
+#define VM_OPCODE_TWO_LITERALS(opcode) (VM_OPCODE_ONE_LITERAL (opcode) + VM_OPCODE_DECODED_ARG)
+
+/**
+ * Last VM opcode for CBC opcodes
+ */
+#define VM_OPCODE_LAST VM_OPCODE_TWO_LITERALS (VM_OPCODE_DECODED_ARG)
+
+/**
+ * CBC_EXT opcodes corresponding VM opcode
+ */
+#define VM_EXT_OPCODE(opcode) (VM_OPCODE_LAST + opcode)
+
+/**
+ * Generate VM opcode cases for branch CBC opcodes
+ */
+#define VM_OPCODE_BRANCH_CASE(op) \
+  VM_OPCODE_BRANCH (op) : case VM_OPCODE_BRANCH (op##_2) : case VM_OPCODE_BRANCH (op##_3)
+
+/**
+ * Generate VM opcode cases for CBC opcodes with put result
+ */
+#define VM_OPCODE_PUT_RESULT_CASE(op) \
+op:                                   \
+  case op##_PUSH_RESULT:              \
+  case op##_BLOCK
+
+/**
+ * Generate VM opcode cases for CBC opcodes with put result and one literal argument
+ */
+#define VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE(op) \
+  VM_OPCODE_ONE_LITERAL (op) : case VM_OPCODE_ONE_LITERAL (op##_PUSH_RESULT) : case VM_OPCODE_ONE_LITERAL (op##_BLOCK)
+
+/**
+ * Generate VM opcode cases for arithmetic CBC opcodes
+ */
+#define VM_OPCODE_ARITHMETIC_CASE(op) \
+  VM_OPCODE_ONE_LITERAL (op##_RIGHT_LITERAL) : case VM_OPCODE_TWO_LITERALS (op##_TWO_LITERALS)
+
+/**
+ * Decoded branch CBC_EXT opcode
+ */
+#define VM_EXT_OPCODE_BRANCH(ext_opcode) (VM_EXT_OPCODE (ext_opcode) + VM_OPCODE_DECODED_ARG)
+
+/**
+ * Decoded CBC_EXT opcode with one literal argument
+ */
+#define VM_EXT_OPCODE_ONE_LITERAL(ext_opcode) (VM_EXT_OPCODE (ext_opcode) + VM_OPCODE_DECODED_ARG)
+
+/**
+ * Decoded CBC_EXT opcode with two literal arguments
+ */
+#define VM_EXT_OPCODE_TWO_LITERALS(ext_opcode) (VM_EXT_OPCODE_ONE_LITERAL (ext_opcode) + VM_OPCODE_DECODED_ARG)
+
+/**
+ * Last VM opcode for CBC_EXT opcodes
+ */
+#define VM_EXT_OPCODE_LAST VM_EXT_OPCODE_TWO_LITERALS (VM_OPCODE_DECODED_ARG)
+
+/**
+ * Generate VM opcode cases for branch CBC_EXT opcodes
+ */
+#define VM_EXT_OPCODE_BRANCH_CASE(op) \
+  VM_EXT_OPCODE_BRANCH (op) : case VM_EXT_OPCODE_BRANCH (op##_2) : case VM_EXT_OPCODE_BRANCH (op##_3)
+
+/**
+ * VM opcode case where for argument decoding
+ */
+#define VM_DECODE_ARGUMENT_OPCODE (VM_EXT_OPCODE_LAST + 1)
+
+/**
+ * Open an unreachable block. This can be used to create cases with same ending, however the normal execution never
+ * reaches this block. You can enter this block via goto or you can place the opcode dispather `case VM_OPCODE...:`
+ * label into this block.
  */
-#define POST_INCREASE_DECREASE_PUT_RESULT(value)                                                             \
-  if (opcode_data & VM_OC_PUT_STACK)                                                                         \
-  {                                                                                                          \
-    if (opcode_flags & VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG)                                                  \
-    {                                                                                                        \
-      JERRY_ASSERT (opcode == CBC_POST_INCR_IDENT_PUSH_RESULT || opcode == CBC_POST_DECR_IDENT_PUSH_RESULT); \
-      *stack_top_p++ = (value);                                                                              \
-    }                                                                                                        \
-    else                                                                                                     \
-    {                                                                                                        \
-      /* The parser ensures there is enough space for the                                                    \
-       * extra value on the stack. See js-parser-expr.c. */                                                  \
-      JERRY_ASSERT (opcode == CBC_POST_INCR_PUSH_RESULT || opcode == CBC_POST_DECR_PUSH_RESULT);             \
-      stack_top_p++;                                                                                         \
-      stack_top_p[-1] = stack_top_p[-2];                                                                     \
-      stack_top_p[-2] = stack_top_p[-3];                                                                     \
-      stack_top_p[-3] = (value);                                                                             \
-    }                                                                                                        \
-    opcode_data &= (uint32_t) ~VM_OC_PUT_STACK;                                                              \
-  }                                                                                                          \
-  else                                                                                                       \
-  {                                                                                                          \
-    JERRY_ASSERT (opcode_data &VM_OC_PUT_BLOCK);                                                             \
-    ecma_free_value (VM_GET_REGISTER (frame_ctx_p, 0));                                                      \
-    VM_GET_REGISTERS (frame_ctx_p)[0] = (value);                                                             \
-    opcode_data &= (uint32_t) ~VM_OC_PUT_BLOCK;                                                              \
+#define VM_OPCODE_UNREACHABLE_BLOCK if (0)
+
+/**
+ * Decode CBC opcode with one literal argument.
+ * The decoded literal is placed into `left_value`
+ */
+#define VM_DECODE_LITERAL(op)  \
+  VM_OPCODE_UNREACHABLE_BLOCK  \
+  {                            \
+    case op:                   \
+    {                          \
+      goto decode_one_literal; \
+    }                          \
   }
 
 /**
- * Get the end of the existing topmost context
+ * Decode 2 CBC opcodes with one literal argument
+ * The decoded literal is placed into `left_value`
  */
-#define VM_LAST_CONTEXT_END() (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth)
+#define VM_DECODE_LITERAL_2(op1, op2) \
+  VM_OPCODE_UNREACHABLE_BLOCK         \
+  {                                   \
+    case op1:                         \
+    case op2:                         \
+    {                                 \
+      goto decode_one_literal;        \
+    }                                 \
+  }
+
+/**
+ * Decode CBC opcode with two literal arguments
+ * The first decoded literal is placed into `left_value`
+ * The second decoded literal is placed into `right_value`
+ */
+#define VM_DECODE_LITERAL_LITERAL(op) \
+  VM_OPCODE_UNREACHABLE_BLOCK         \
+  {                                   \
+    case op:                          \
+    {                                 \
+      goto decode_first_literal;      \
+    }                                 \
+    case VM_OPCODE_ONE_LITERAL (op):  \
+    {                                 \
+      goto decode_second_literal;     \
+    }                                 \
+  }
+
+/**
+ * Decode 2 CBC opcodes with two literal arguments
+ * The first decoded literal is placed into `left_value`
+ * The second decoded literal is placed into `right_value`
+ */
+#define VM_DECODE_LITERAL_LITERAL_2(op1, op2) \
+  VM_OPCODE_UNREACHABLE_BLOCK                 \
+  {                                           \
+    case op1:                                 \
+    case op2:                                 \
+    {                                         \
+      goto decode_first_literal;              \
+    }                                         \
+    case VM_OPCODE_ONE_LITERAL (op1):         \
+    case VM_OPCODE_ONE_LITERAL (op2):         \
+    {                                         \
+      goto decode_second_literal;             \
+    }                                         \
+  }
+
+/**
+ * Decode CBC opcode with this argument and one literal argument
+ * The frame context's this_value is placed into `left_value`
+ * The decoded literal is placed into `right_value`
+ */
+#define VM_DECODE_THIS_LITERAL(op) \
+  VM_OPCODE_UNREACHABLE_BLOCK      \
+  {                                \
+    case op:                       \
+    {                              \
+      goto decode_this_literal;    \
+    }                              \
+  }
+
+/**
+ * Decode two CBC opcodes with this argument and one literal argument
+ * The frame context's this_value is placed into `left_value`
+ * The decoded literal is placed into `right_value`
+ */
+#define VM_DECODE_THIS_LITERAL_2(op1, op2) \
+  VM_OPCODE_UNREACHABLE_BLOCK              \
+  {                                        \
+    case op1:                              \
+    case op2:                              \
+    {                                      \
+      goto decode_this_literal;            \
+    }                                      \
+  }
+
+/**
+ * Pop an element from the stack into `target`
+ */
+#define VM_POP_STACK(target)                                                  \
+  JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); \
+  (target) = *(--stack_top_p)
+
+/**
+ * Pop two elements from the stack into `target1` and `target2`
+ */
+#define VM_POP_STACK_STACK(target1, target2) \
+  VM_POP_STACK (target1);                    \
+  VM_POP_STACK (target2)
+
+/**
+ * Decode CBC opcode with pop stack argument
+ * The popped element from the stack is placed into `left_value`
+ */
+#define VM_DECODE_STACK(op)      \
+  VM_OPCODE_UNREACHABLE_BLOCK    \
+  {                              \
+    case op:                     \
+    {                            \
+      VM_POP_STACK (left_value); \
+    }                            \
+  }
+
+/**
+ * Decode 2 CBC opcodes with pop stack argument
+ * The popped element from the stack is placed into `left_value`
+ */
+#define VM_DECODE_STACK_2(op1, op2) \
+  VM_OPCODE_UNREACHABLE_BLOCK       \
+  {                                 \
+    case op1:                       \
+    case op2:                       \
+    {                               \
+      VM_POP_STACK (left_value);    \
+    }                               \
+  }
+
+/**
+ * Decode CBC opcode with pop stack-stack argument
+ * The first popped element from the stack is placed into `right_value`
+ * The second popped element from the stack is placed into `left_value`
+ */
+#define VM_DECODE_STACK_STACK(op)                   \
+  VM_OPCODE_UNREACHABLE_BLOCK                       \
+  {                                                 \
+    case op:                                        \
+    {                                               \
+      VM_POP_STACK_STACK (right_value, left_value); \
+    }                                               \
+  }
+
+/**
+ * Decode 2 CBC opcodes with pop stack-stack argument
+ * The first popped element from the stack is placed into `right_value`
+ * The second popped element from the stack is placed into `left_value`
+ */
+#define VM_DECODE_STACK_STACK_2(op1, op2)           \
+  VM_OPCODE_UNREACHABLE_BLOCK                       \
+  {                                                 \
+    case op1:                                       \
+    case op2:                                       \
+    {                                               \
+      VM_POP_STACK_STACK (right_value, left_value); \
+    }                                               \
+  }
+
+/**
+ * Decode CBC opcode with pop stack and one literal argument
+ * The popped element from the stack is placed into `left_value`
+ * The decoded literal is placed into `right_value`
+ */
+#define VM_DECODE_STACK_LITERAL(op) \
+  VM_OPCODE_UNREACHABLE_BLOCK       \
+  {                                 \
+    case op:                        \
+    {                               \
+      goto decode_stack_literal;    \
+    }                               \
+  }
+
+/**
+ * Decode 2 CBC opcodes with pop stack and one literal argument
+ * The popped element from the stack is placed into `left_value`
+ * The decoded literal is placed into `right_value`
+ */
+#define VM_DECODE_STACK_LITERAL_2(op1, op2) \
+  VM_OPCODE_UNREACHABLE_BLOCK               \
+  {                                         \
+    case op1:                               \
+    case op2:                               \
+    {                                       \
+      goto decode_stack_literal;            \
+    }                                       \
+  }
+
+/**
+ * Decode CBC opcode with forward branch argument
+ * The decoded branch offset is placed into `branch_offset`
+ */
+#define VM_DECODE_FORWARD_BRANCH(op) \
+  VM_OPCODE_UNREACHABLE_BLOCK        \
+  {                                  \
+    case op:                         \
+    {                                \
+      goto decode_forward_branch_1;  \
+    }                                \
+    case op##_2:                     \
+    {                                \
+      goto decode_forward_branch_2;  \
+    }                                \
+    case op##_3:                     \
+    {                                \
+      goto decode_forward_branch_3;  \
+    }                                \
+  }
+
+/**
+ * Decode CBC opcode with backward branch argument
+ * The decoded branch offset is placed into `branch_offset`
+ */
+#define VM_DECODE_BACKWARD_BRANCH(op) \
+  VM_OPCODE_UNREACHABLE_BLOCK         \
+  {                                   \
+    case op:                          \
+    {                                 \
+      goto decode_backward_branch_1;  \
+    }                                 \
+    case op##_2:                      \
+    {                                 \
+      goto decode_backward_branch_2;  \
+    }                                 \
+    case op##_3:                      \
+    {                                 \
+      goto decode_backward_branch_3;  \
+    }                                 \
+  }
+
+/**
+ * Decode arguments of an arithmetic CBC opcode
+ */
+#define VM_DECODE_ARITHMETIC(op)                 \
+  VM_DECODE_STACK_LITERAL (op##_RIGHT_LITERAL);  \
+  VM_DECODE_LITERAL_LITERAL (op##_TWO_LITERALS); \
+  VM_DECODE_STACK_STACK (op)
+
+/**
+ * Decode CBC opcode with put result and one literal argument.
+ * The decoded literal is placed into `left_value`
+ */
+#define VM_DECODE_LITERAL_PUT_RESULT(op) \
+  VM_OPCODE_UNREACHABLE_BLOCK            \
+  {                                      \
+    case op:                             \
+    case op##_PUSH_RESULT:               \
+    case op##_BLOCK:                     \
+    {                                    \
+      goto decode_one_literal;           \
+    }                                    \
+  }
+
+/**
+ * Generate VM opcode cases for CBC_EXT opcodes with put result
+ */
+#define VM_EXT_OPCODE_PUT_RESULT_CASE(op) \
+  VM_EXT_OPCODE (op) : case VM_EXT_OPCODE (op##_PUSH_RESULT) : case VM_EXT_OPCODE (op##_BLOCK)
+
+/**
+ * Generate VM opcode cases for arithmetic CBC_EXT opcodes
+ */
+#define VM_EXT_OPCODE_ARITHMETIC_CASE(op) \
+  VM_EXT_OPCODE_ONE_LITERAL (op##_RIGHT_LITERAL) : case VM_EXT_OPCODE_TWO_LITERALS (op##_TWO_LITERALS)
+
+/**
+ * VM_DECODE_STACK marco for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_STACK(op) VM_DECODE_STACK (VM_EXT_OPCODE (op))
+
+/**
+ * VM_DECODE_STACK_STACK marco for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_STACK_STACK(op) VM_DECODE_STACK_STACK (VM_EXT_OPCODE (op))
+
+/**
+ * VM_DECODE_STACK_LITERAL marco for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_STACK_LITERAL(op) VM_DECODE_STACK_LITERAL (VM_EXT_OPCODE (op))
+
+/**
+ * VM_DECODE_LITERAL marco for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_LITERAL(op) VM_DECODE_LITERAL (VM_EXT_OPCODE (op))
+
+/**
+ * VM_DECODE_LITERAL_LITERAL marco for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_LITERAL_LITERAL(op) VM_DECODE_LITERAL_LITERAL (VM_EXT_OPCODE (op))
+
+/**
+ * VM_DECODE_STACK_2 marco for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_STACK_2(op1, op2) VM_DECODE_STACK_2 (VM_EXT_OPCODE (op1), VM_EXT_OPCODE (op2))
+
+/**
+ * VM_DECODE_STACK_STACK_2 marco for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_STACK_STACK_2(op1, op2) VM_DECODE_STACK_STACK_2 (VM_EXT_OPCODE (op1), VM_EXT_OPCODE (op2))
+
+/**
+ * VM_DECODE_STACK_LITERAL_2 marco for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_STACK_LITERAL_2(op1, op2) VM_DECODE_STACK_LITERAL_2 (VM_EXT_OPCODE (op1), VM_EXT_OPCODE (op2))
+
+/**
+ * VM_DECODE_LITERAL_2 marco for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_LITERAL_2(op1, op2) VM_DECODE_LITERAL_2 (VM_EXT_OPCODE (op1), VM_EXT_OPCODE (op2))
+
+/**
+ * VM_DECODE_LITERAL_LITERAL_2 marco for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_LITERAL_LITERAL_2(op1, op2) VM_DECODE_LITERAL_LITERAL_2 (VM_EXT_OPCODE (op1), VM_EXT_OPCODE (op2))
+
+/**
+ * VM_DECODE_FORWARD_BRANCH macro for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_FORWARD_BRANCH(op) \
+  VM_OPCODE_UNREACHABLE_BLOCK            \
+  {                                      \
+    case VM_EXT_OPCODE (op):             \
+    {                                    \
+      goto decode_forward_branch_1;      \
+    }                                    \
+    case VM_EXT_OPCODE (op##_2):         \
+    {                                    \
+      goto decode_forward_branch_2;      \
+    }                                    \
+    case VM_EXT_OPCODE (op##_3):         \
+    {                                    \
+      goto decode_forward_branch_3;      \
+    }                                    \
+  }
+
+/**
+ * VM_DECODE_BACKWARD_BRANCH macro for CBC_EXT opcodes
+ */
+#define VM_DECODE_EXT_BACKWARD_BRANCH(op) \
+  VM_OPCODE_UNREACHABLE_BLOCK             \
+  {                                       \
+    case VM_EXT_OPCODE (op):              \
+    {                                     \
+      goto decode_backward_branch_1;      \
+    }                                     \
+    case VM_EXT_OPCODE (op##_2):          \
+    {                                     \
+      goto decode_backward_branch_2;      \
+    }                                     \
+    case VM_EXT_OPCODE (op##_3):          \
+    {                                     \
+      goto decode_backward_branch_3;      \
+    }                                     \
+  }
+
+/**
+ * Decode arguments of an arithmetic CBC_EXT opcode
+ */
+#define VM_DECODE_EXT_ARITHMETIC(op)                 \
+  VM_DECODE_EXT_STACK_LITERAL (op##_RIGHT_LITERAL);  \
+  VM_DECODE_EXT_LITERAL_LITERAL (op##_TWO_LITERALS); \
+  VM_DECODE_EXT_STACK_STACK (op)
+
+/**
+ * Put result decode table for pre/post incr/decr opcodes
+ */
+static const uint8_t vm_incr_decr_flags[] = {
+  VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_NONE,
+  VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_STACK,
+  VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_BLOCK,
+  VM_PUT_RESULT_IDENT | VM_PUT_RESULT_NONE,
+  VM_PUT_RESULT_IDENT | VM_PUT_RESULT_STACK,
+  VM_PUT_RESULT_IDENT | VM_PUT_RESULT_BLOCK,
+
+  VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_NONE,
+  VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_STACK,
+  VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_BLOCK,
+  VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_NONE,
+  VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_STACK,
+  VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_BLOCK,
+
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_NONE,
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_STACK,
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_BLOCK,
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_NONE,
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_STACK,
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_BLOCK,
+
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_NONE,
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_STACK,
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_BLOCK,
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_NONE,
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_STACK,
+  VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_BLOCK,
+};
 
 /**
  * Run generic byte code.
@@ -985,11 +1444,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
   uint16_t ident_end;
   uint16_t const_literal_end;
   int32_t branch_offset = 0;
-  uint8_t branch_offset_length = 0;
   ecma_value_t left_value;
   ecma_value_t right_value;
   ecma_value_t result = ECMA_VALUE_EMPTY;
   bool is_strict = ((bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0);
+  uint8_t put_result_flags = VM_PUT_RESULT_NONE;
 
   /* Prepare for byte code execution. */
   if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING))
@@ -1027,92 +1486,51 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
     while (true)
     {
       const uint8_t *byte_code_start_p = byte_code_p;
-      uint8_t opcode = *byte_code_p++;
-      uint32_t opcode_data = opcode;
-
-      if (opcode == CBC_EXT_OPCODE)
-      {
-        opcode = *byte_code_p++;
-        opcode_data = (uint32_t) ((CBC_END + 1) + opcode);
-      }
-
-      opcode_data = vm_decode_table[opcode_data];
+      uint16_t opcode = *byte_code_p++;
 
       left_value = ECMA_VALUE_UNDEFINED;
       right_value = ECMA_VALUE_UNDEFINED;
 
-      uint32_t operands = VM_OC_GET_ARGS_INDEX (opcode_data);
-
-      if (operands >= VM_OC_GET_LITERAL)
+dispatch_opcode:
+      switch (opcode)
       {
-        uint16_t literal_index;
-        READ_LITERAL_INDEX (literal_index);
-        READ_LITERAL (literal_index, left_value);
-
-        if (operands != VM_OC_GET_LITERAL)
+        case VM_DECODE_ARGUMENT_OPCODE:
         {
-          switch (operands)
-          {
-            case VM_OC_GET_LITERAL_LITERAL:
-            {
-              uint16_t second_literal_index;
-              READ_LITERAL_INDEX (second_literal_index);
-              READ_LITERAL (second_literal_index, right_value);
-              break;
-            }
-            case VM_OC_GET_STACK_LITERAL:
-            {
-              JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end);
-              right_value = left_value;
-              left_value = *(--stack_top_p);
-              break;
-            }
-            default:
-            {
-              JERRY_ASSERT (operands == VM_OC_GET_THIS_LITERAL);
+decode_forward_branch_1:
+          branch_offset = *(byte_code_p++);
 
-              right_value = left_value;
-              left_value = ecma_copy_value (frame_ctx_p->this_binding);
-              break;
-            }
+          VM_OPCODE_UNREACHABLE_BLOCK
+          {
+decode_forward_branch_2:
+            branch_offset = byte_code_p[0] << 8 | byte_code_p[1];
+            byte_code_p += 2;
+          }
+          VM_OPCODE_UNREACHABLE_BLOCK
+          {
+decode_forward_branch_3:
+            branch_offset = byte_code_p[0] << 16 | byte_code_p[1] << 8 | byte_code_p[2];
+            byte_code_p += 3;
           }
-        }
-      }
-      else if (operands >= VM_OC_GET_STACK)
-      {
-        JERRY_ASSERT (operands == VM_OC_GET_STACK || operands == VM_OC_GET_STACK_STACK);
-
-        JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end);
-        left_value = *(--stack_top_p);
-
-        if (operands == VM_OC_GET_STACK_STACK)
-        {
-          JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end);
-          right_value = left_value;
-          left_value = *(--stack_top_p);
-        }
-      }
-      else if (operands == VM_OC_GET_BRANCH)
-      {
-        branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (opcode);
-        JERRY_ASSERT (branch_offset_length >= 1 && branch_offset_length <= 3);
 
-        branch_offset = *(byte_code_p++);
+          opcode = (uint16_t) (opcode + VM_OPCODE_DECODED_ARG);
+          goto dispatch_opcode;
 
-        if (JERRY_UNLIKELY (branch_offset_length != 1))
-        {
-          branch_offset <<= 8;
-          branch_offset |= *(byte_code_p++);
+decode_backward_branch_1:
+          branch_offset = -(*byte_code_p++);
 
-          if (JERRY_UNLIKELY (branch_offset_length == 3))
+          VM_OPCODE_UNREACHABLE_BLOCK
           {
-            branch_offset <<= 8;
-            branch_offset |= *(byte_code_p++);
+decode_backward_branch_2:
+            branch_offset = -(byte_code_p[0] << 8 | byte_code_p[1]);
+            byte_code_p += 2;
+          }
+          VM_OPCODE_UNREACHABLE_BLOCK
+          {
+decode_backward_branch_3:
+            branch_offset = -(byte_code_p[0] << 16 | byte_code_p[1] << 8 | byte_code_p[2]);
+            byte_code_p += 3;
           }
-        }
 
-        if (opcode_data & VM_OC_BACKWARD_BRANCH)
-        {
 #if JERRY_VM_HALT
           if (JERRY_CONTEXT (vm_exec_stop_cb) != NULL && --JERRY_CONTEXT (vm_exec_stop_counter) == 0)
           {
@@ -1143,115 +1561,150 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 #endif /* JERRY_VM_HALT */
 
-          branch_offset = -branch_offset;
-        }
-      }
+          opcode = (uint16_t) (opcode + VM_OPCODE_DECODED_ARG);
+          goto dispatch_opcode;
 
-      switch (VM_OC_GROUP_GET_INDEX (opcode_data))
-      {
-        case VM_OC_POP:
+          uint16_t literal_index;
+decode_one_literal:
+          READ_LITERAL_INDEX (literal_index);
+          READ_LITERAL (literal_index, left_value);
+
+          opcode = (uint16_t) (opcode + VM_OPCODE_DECODED_ARG);
+          goto dispatch_opcode;
+
+decode_second_literal:
+          left_value = right_value;
+          right_value = ECMA_VALUE_UNDEFINED;
+
+          VM_OPCODE_UNREACHABLE_BLOCK
+          {
+decode_stack_literal:
+            VM_POP_STACK (left_value);
+          }
+          VM_OPCODE_UNREACHABLE_BLOCK
+          {
+decode_this_literal:
+            left_value = ecma_copy_value (frame_ctx_p->this_binding);
+          }
+
+decode_first_literal:
+          READ_LITERAL_INDEX (literal_index);
+          READ_LITERAL (literal_index, right_value);
+
+          opcode = (uint16_t) (opcode + VM_OPCODE_DECODED_ARG);
+          goto dispatch_opcode;
+        }
+        case CBC_EXT_OPCODE:
+        {
+          opcode = (uint16_t) VM_EXT_OPCODE (*byte_code_p++);
+          goto dispatch_opcode;
+        }
+        case CBC_POP:
         {
           JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end);
           ecma_free_value (*(--stack_top_p));
           continue;
         }
-        case VM_OC_POP_BLOCK:
+        case CBC_POP_BLOCK:
         {
           ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0));
           VM_GET_REGISTERS (frame_ctx_p)[0] = *(--stack_top_p);
           continue;
         }
-        case VM_OC_PUSH:
+        case VM_OPCODE_ONE_LITERAL (CBC_PUSH_LITERAL):
         {
+          VM_DECODE_LITERAL (CBC_PUSH_LITERAL);
+
           *stack_top_p++ = left_value;
           continue;
         }
-        case VM_OC_PUSH_TWO:
+        case VM_OPCODE_ONE_LITERAL (CBC_PUSH_THIS_LITERAL):
+        case VM_OPCODE_TWO_LITERALS (CBC_PUSH_TWO_LITERALS):
         {
+          VM_DECODE_LITERAL_LITERAL (CBC_PUSH_TWO_LITERALS);
+          VM_DECODE_THIS_LITERAL (CBC_PUSH_THIS_LITERAL)
+
           *stack_top_p++ = left_value;
           *stack_top_p++ = right_value;
           continue;
         }
-        case VM_OC_PUSH_THREE:
+        case VM_OPCODE_TWO_LITERALS (CBC_PUSH_THREE_LITERALS):
         {
-          uint16_t literal_index;
-
-          *stack_top_p++ = left_value;
-          left_value = ECMA_VALUE_UNDEFINED;
-
-          READ_LITERAL_INDEX (literal_index);
-          READ_LITERAL (literal_index, left_value);
+          VM_DECODE_LITERAL_LITERAL (CBC_PUSH_THREE_LITERALS);
 
-          *stack_top_p++ = right_value;
           *stack_top_p++ = left_value;
-          continue;
+          opcode = VM_OPCODE_ONE_LITERAL (CBC_PUSH_TWO_LITERALS);
+          goto decode_second_literal;
         }
-        case VM_OC_PUSH_UNDEFINED:
+        case CBC_PUSH_UNDEFINED:
         {
           *stack_top_p++ = ECMA_VALUE_UNDEFINED;
           continue;
         }
-        case VM_OC_PUSH_TRUE:
+        case CBC_PUSH_TRUE:
         {
           *stack_top_p++ = ECMA_VALUE_TRUE;
           continue;
         }
-        case VM_OC_PUSH_FALSE:
+        case CBC_PUSH_FALSE:
         {
           *stack_top_p++ = ECMA_VALUE_FALSE;
           continue;
         }
-        case VM_OC_PUSH_NULL:
+        case CBC_PUSH_NULL:
         {
           *stack_top_p++ = ECMA_VALUE_NULL;
           continue;
         }
-        case VM_OC_PUSH_THIS:
+        case CBC_PUSH_THIS:
         {
           *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding);
           continue;
         }
-        case VM_OC_PUSH_0:
+        case CBC_PUSH_NUMBER_0:
         {
           *stack_top_p++ = ecma_make_integer_value (0);
           continue;
         }
-        case VM_OC_PUSH_POS_BYTE:
+        case CBC_PUSH_NUMBER_POS_BYTE:
         {
           ecma_integer_value_t number = *byte_code_p++;
           *stack_top_p++ = ecma_make_integer_value (number + 1);
           continue;
         }
-        case VM_OC_PUSH_NEG_BYTE:
+        case CBC_PUSH_NUMBER_NEG_BYTE:
         {
           ecma_integer_value_t number = *byte_code_p++;
           *stack_top_p++ = ecma_make_integer_value (-(number + 1));
           continue;
         }
-        case VM_OC_PUSH_LIT_0:
+        case VM_OPCODE_ONE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_0):
         {
+          VM_DECODE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_0);
           stack_top_p[0] = left_value;
           stack_top_p[1] = ecma_make_integer_value (0);
           stack_top_p += 2;
           continue;
         }
-        case VM_OC_PUSH_LIT_POS_BYTE:
+        case VM_OPCODE_ONE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE):
         {
+          VM_DECODE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE);
           ecma_integer_value_t number = *byte_code_p++;
           stack_top_p[0] = left_value;
           stack_top_p[1] = ecma_make_integer_value (number + 1);
           stack_top_p += 2;
           continue;
         }
-        case VM_OC_PUSH_LIT_NEG_BYTE:
+        case VM_OPCODE_ONE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE):
         {
+          VM_DECODE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE);
           ecma_integer_value_t number = *byte_code_p++;
           stack_top_p[0] = left_value;
           stack_top_p[1] = ecma_make_integer_value (-(number + 1));
           stack_top_p += 2;
           continue;
         }
-        case VM_OC_PUSH_OBJECT:
+        case CBC_CREATE_OBJECT:
         {
           ecma_object_t *obj_p =
             ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL);
@@ -1259,8 +1712,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = ecma_make_object_value (obj_p);
           continue;
         }
-        case VM_OC_PUSH_NAMED_FUNC_EXPR:
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION):
         {
+          VM_DECODE_EXT_LITERAL_LITERAL (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION);
+
           ecma_object_t *func_p = ecma_get_object_from_value (left_value);
 
           JERRY_ASSERT (ecma_get_object_type (func_p) == ECMA_OBJECT_TYPE_FUNCTION);
@@ -1281,12 +1736,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = left_value;
           continue;
         }
-        case VM_OC_CREATE_BINDING:
+        case CBC_CREATE_VAR:
+#if JERRY_ESNEXT
+        case CBC_CREATE_LET:
+        case CBC_CREATE_CONST:
+        case CBC_CREATE_LOCAL:
+#endif /* JERRY_ESNEXT */
         {
-#if !JERRY_ESNEXT
-          JERRY_ASSERT (opcode == CBC_CREATE_VAR);
-#endif /* !JERRY_ESNEXT */
-
           uint32_t literal_index;
 
           READ_LITERAL_INDEX (literal_index);
@@ -1321,7 +1777,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
           continue;
         }
-        case VM_OC_VAR_EVAL:
+        case CBC_CREATE_VAR_EVAL:
+        case CBC_CREATE_VAR_FUNC_EVAL:
         {
           uint32_t literal_index;
           ecma_value_t lit_value = ECMA_VALUE_UNDEFINED;
@@ -1413,15 +1870,22 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           continue;
         }
+        case VM_OPCODE_ONE_LITERAL (CBC_SET_VAR_FUNC):
+        {
+          VM_DECODE_LITERAL (CBC_SET_VAR_FUNC);
+          result = left_value;
+          left_value = ECMA_VALUE_UNDEFINED;
+          put_result_flags = VM_PUT_RESULT_NONE;
+          goto dispatch_put_ident;
+        }
 #if JERRY_ESNEXT
-        case VM_OC_EXT_VAR_EVAL:
+        case VM_EXT_OPCODE (CBC_EXT_CREATE_VAR_EVAL):
+        case VM_EXT_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL):
         {
           uint32_t literal_index;
           ecma_value_t lit_value = ECMA_VALUE_UNDEFINED;
 
-          JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE);
-
-          if (opcode == CBC_EXT_CREATE_VAR_FUNC_EVAL)
+          if (opcode == VM_EXT_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL))
           {
             uint32_t value_index;
             READ_LITERAL_INDEX (value_index);
@@ -1486,7 +1950,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           continue;
         }
 #endif /* JERRY_ESNEXT */
-        case VM_OC_CREATE_ARGUMENTS:
+        case VM_EXT_OPCODE (CBC_EXT_CREATE_ARGUMENTS):
         {
           uint32_t literal_index;
           READ_LITERAL_INDEX (literal_index);
@@ -1517,14 +1981,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           continue;
         }
 #if JERRY_SNAPSHOT_EXEC
-        case VM_OC_SET_BYTECODE_PTR:
+        case CBC_SET_BYTECODE_PTR:
         {
           memcpy (&byte_code_p, byte_code_p++, sizeof (uintptr_t));
           frame_ctx_p->byte_code_start_p = byte_code_p;
           continue;
         }
 #endif /* JERRY_SNAPSHOT_EXEC */
-        case VM_OC_INIT_ARG_OR_FUNC:
+        case CBC_INIT_ARG_OR_FUNC:
         {
           uint32_t literal_index, value_index;
           ecma_value_t lit_value;
@@ -1575,7 +2039,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           continue;
         }
 #if JERRY_ESNEXT
-        case VM_OC_CHECK_VAR:
+        case CBC_CHECK_VAR:
         {
           JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags)
                         == CBC_FUNCTION_SCRIPT);
@@ -1599,7 +2063,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
           continue;
         }
-        case VM_OC_CHECK_LET:
+        case CBC_CHECK_LET:
         {
           JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags)
                         == CBC_FUNCTION_SCRIPT);
@@ -1645,8 +2109,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
           continue;
         }
-        case VM_OC_ASSIGN_LET_CONST:
+        case VM_OPCODE_ONE_LITERAL (CBC_ASSIGN_LET_CONST_LITERAL):
         {
+          VM_DECODE_LITERAL (CBC_ASSIGN_LET_CONST_LITERAL);
+          VM_DECODE_STACK (CBC_ASSIGN_LET_CONST);
+
           uint32_t literal_index;
           READ_LITERAL_INDEX (literal_index);
 
@@ -1670,7 +2137,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           continue;
         }
-        case VM_OC_INIT_BINDING:
+        case CBC_INIT_ARG_OR_CATCH:
+        case CBC_INIT_LET:
+        case CBC_INIT_CONST:
         {
           uint32_t literal_index;
 
@@ -1705,13 +2174,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           ecma_deref_if_object (value);
           continue;
         }
-        case VM_OC_THROW_CONST_ERROR:
+        case VM_EXT_OPCODE (CBC_EXT_THROW_ASSIGN_CONST_ERROR):
         {
           result = ecma_raise_type_error (ECMA_ERR_CONSTANT_BINDINGS_CANNOT_BE_REASSIGNED);
           goto error;
         }
-        case VM_OC_COPY_TO_GLOBAL:
+        case VM_OPCODE_ONE_LITERAL (CBC_COPY_TO_GLOBAL):
         {
+          VM_DECODE_LITERAL (CBC_COPY_TO_GLOBAL);
+
           uint32_t literal_index;
           READ_LITERAL_INDEX (literal_index);
 
@@ -1762,9 +2233,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             }
           }
 
-          goto free_left_value;
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_COPY_FROM_ARG:
+        case VM_EXT_OPCODE (CBC_EXT_COPY_FROM_ARG):
         {
           uint32_t literal_index;
           READ_LITERAL_INDEX (literal_index);
@@ -1789,38 +2261,45 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           property_value_p->value = ecma_copy_value_if_not_object (arg_prop_value_p->value);
           continue;
         }
-        case VM_OC_CLONE_CONTEXT:
+        case VM_EXT_OPCODE (CBC_EXT_CLONE_CONTEXT):
+        case VM_EXT_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT):
         {
-          JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE);
-
-          bool copy_values = (byte_code_start_p[1] == CBC_EXT_CLONE_FULL_CONTEXT);
+          bool copy_values = (opcode == VM_EXT_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT));
           frame_ctx_p->lex_env_p = ecma_clone_decl_lexical_environment (frame_ctx_p->lex_env_p, copy_values);
           continue;
         }
-        case VM_OC_SET__PROTO__:
+        case VM_EXT_OPCODE (CBC_EXT_SET__PROTO__):
         {
+          VM_POP_STACK (left_value);
+
           result = ecma_builtin_object_object_set_proto (stack_top_p[-1], left_value);
+
           if (ECMA_IS_VALUE_ERROR (result))
           {
             goto error;
           }
-          goto free_left_value;
+
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_CLASS_CALL_STATIC_BLOCK:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_CLASS_CALL_STATIC_BLOCK):
         {
+          VM_DECODE_EXT_LITERAL (CBC_EXT_CLASS_CALL_STATIC_BLOCK);
+
           result = ecma_op_function_call (ecma_get_object_from_value (left_value), frame_ctx_p->this_binding, NULL, 0);
 
           if (ECMA_IS_VALUE_ERROR (result))
           {
             goto error;
           }
-          goto free_left_value;
+
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_PUSH_STATIC_FIELD_FUNC:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_STATIC_FIELD_FUNC):
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC):
         {
-          JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE
-                        && (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_FIELD_FUNC
-                            || byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC));
+          VM_DECODE_EXT_LITERAL_2 (CBC_EXT_PUSH_STATIC_FIELD_FUNC, CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC);
 
           bool push_computed = (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC);
           ecma_value_t value = stack_top_p[-1];
@@ -1843,27 +2322,23 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           left_value = value;
-          /* FALLTHRU */
-        }
-        case VM_OC_ADD_COMPUTED_FIELD:
-        {
-          JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE
-                        && (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC
-                            || byte_code_start_p[1] == CBC_EXT_ADD_COMPUTED_FIELD
-                            || byte_code_start_p[1] == CBC_EXT_ADD_STATIC_COMPUTED_FIELD));
 
-          int index = (byte_code_start_p[1] == CBC_EXT_ADD_COMPUTED_FIELD) ? -2 : -4;
+          VM_DECODE_EXT_STACK_2 (CBC_EXT_ADD_COMPUTED_FIELD, CBC_EXT_ADD_STATIC_COMPUTED_FIELD);
+
+          int index = (opcode == VM_EXT_OPCODE (CBC_EXT_ADD_COMPUTED_FIELD)) ? -2 : -4;
           result = opfunc_add_computed_field (stack_top_p[index], left_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
           {
             goto error;
           }
-          goto free_left_value;
+
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_COPY_DATA_PROPERTIES:
+        case VM_EXT_OPCODE (CBC_EXT_COPY_DATA_PROPERTIES):
         {
-          left_value = *(--stack_top_p);
+          VM_POP_STACK (left_value);
 
           if (ecma_is_value_undefined (left_value) || ecma_is_value_null (left_value))
           {
@@ -1877,56 +2352,60 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             goto error;
           }
 
-          goto free_left_value;
-        }
-        case VM_OC_SET_COMPUTED_PROPERTY:
-        {
-          /* Swap values. */
-          left_value ^= right_value;
-          right_value ^= left_value;
-          left_value ^= right_value;
-          /* FALLTHRU */
+          ecma_fast_free_value (left_value);
+          continue;
         }
-#endif /* JERRY_ESNEXT */
-        case VM_OC_SET_PROPERTY:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL):
         {
-          JERRY_STATIC_ASSERT (VM_OC_NON_STATIC_FLAG == VM_OC_BACKWARD_BRANCH,
-                               vm_oc_non_static_flag_must_be_equal_to_vm_oc_backward_branch);
+          VM_DECODE_EXT_STACK_LITERAL (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL);
+          VM_DECODE_EXT_STACK_STACK_2 (CBC_EXT_SET_COMPUTED_PROPERTY, CBC_EXT_SET_STATIC_COMPUTED_PROPERTY);
 
-          JERRY_ASSERT ((opcode_data >> VM_OC_NON_STATIC_SHIFT) <= 0x1);
-
-          ecma_string_t *prop_name_p = ecma_op_to_property_key (right_value);
-
-          if (JERRY_UNLIKELY (prop_name_p == NULL))
-          {
-            result = ECMA_VALUE_ERROR;
-            goto error;
-          }
+          result = opfunc_set_data_property (stack_top_p,
+                                             left_value,
+                                             right_value,
+                                             opcode == VM_EXT_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY));
 
-#if JERRY_ESNEXT
-          if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE))
-              && !(opcode_data & VM_OC_NON_STATIC_FLAG))
+          if (ECMA_IS_VALUE_ERROR (result))
           {
-            result = ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE);
             goto error;
           }
 
-          const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2;
-#else /* !JERRY_ESNEXT */
-          const int index = -1;
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
+        }
 #endif /* JERRY_ESNEXT */
+        case VM_OPCODE_ONE_LITERAL (CBC_SET_PROPERTY):
+        case VM_OPCODE_TWO_LITERALS (CBC_SET_LITERAL_PROPERTY):
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SET_STATIC_PROPERTY):
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_SET_STATIC_PROPERTY_LITERAL):
+        {
+          VM_DECODE_STACK_LITERAL_2 (CBC_SET_PROPERTY, VM_EXT_OPCODE (CBC_EXT_SET_STATIC_PROPERTY));
+          VM_DECODE_LITERAL_LITERAL_2 (CBC_SET_LITERAL_PROPERTY, VM_EXT_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL));
 
-          ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[index]);
+          result =
+            opfunc_set_data_property (stack_top_p, right_value, left_value, *byte_code_start_p == CBC_EXT_OPCODE);
 
-          opfunc_set_data_property (object_p, prop_name_p, left_value);
-          ecma_deref_ecma_string (prop_name_p);
+          if (ECMA_IS_VALUE_ERROR (result))
+          {
+            goto error;
+          }
 
-          goto free_both_values;
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_SET_GETTER:
-        case VM_OC_SET_SETTER:
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_SET_GETTER):
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_SET_SETTER):
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_SET_STATIC_GETTER):
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_SET_STATIC_SETTER):
         {
-          JERRY_ASSERT ((opcode_data >> VM_OC_NON_STATIC_SHIFT) <= 0x1);
+          VM_DECODE_EXT_LITERAL_LITERAL_2 (CBC_EXT_SET_GETTER, CBC_EXT_SET_STATIC_GETTER);
+          VM_DECODE_EXT_LITERAL_LITERAL_2 (CBC_EXT_SET_SETTER, CBC_EXT_SET_STATIC_SETTER);
+          VM_DECODE_EXT_STACK_STACK_2 (CBC_EXT_SET_COMPUTED_GETTER, CBC_EXT_SET_STATIC_COMPUTED_GETTER);
+          VM_DECODE_EXT_STACK_STACK_2 (CBC_EXT_SET_COMPUTED_SETTER, CBC_EXT_SET_STATIC_COMPUTED_SETTER);
+
+          JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE);
 
           ecma_string_t *prop_name_p = ecma_op_to_property_key (left_value);
 
@@ -1936,85 +2415,91 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             goto error;
           }
 
+          int index = -1;
 #if JERRY_ESNEXT
-          if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE))
-              && !(opcode_data & VM_OC_NON_STATIC_FLAG))
+          bool is_static = (byte_code_start_p[1] - CBC_EXT_SET_GETTER) & 0x1;
+
+          if (JERRY_UNLIKELY (is_static))
           {
-            result = ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE);
-            goto error;
-          }
+            if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE)))
+            {
+              result = ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE);
+              goto error;
+            }
 
-          const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2;
-#else /* !JERRY_ESNEXT */
-          const int index = -1;
+            index--;
+          }
 #endif /* JERRY_ESNEXT */
 
-          opfunc_set_accessor (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_SET_GETTER,
-                               stack_top_p[index],
-                               prop_name_p,
-                               right_value);
+          opfunc_set_accessor (byte_code_start_p[1] < CBC_EXT_SET_SETTER, stack_top_p[index], prop_name_p, right_value);
 
           ecma_deref_ecma_string (prop_name_p);
 
-          goto free_both_values;
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_PUSH_ARRAY:
+        case CBC_CREATE_ARRAY:
         {
-          /* Note: this operation cannot throw an exception */
           *stack_top_p++ = ecma_make_object_value (ecma_op_new_array_object (0));
           continue;
         }
 #if JERRY_ESNEXT
-        case VM_OC_LOCAL_EVAL:
+        case VM_EXT_OPCODE (CBC_EXT_LOCAL_EVAL):
         {
           ECMA_CLEAR_LOCAL_PARSE_OPTS ();
           uint8_t parse_opts = *byte_code_p++;
           ECMA_SET_LOCAL_PARSE_OPTS (parse_opts);
           continue;
         }
-        case VM_OC_SUPER_CALL:
+        case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_SUPER_CALL):
         {
           uint8_t arguments_list_len = *byte_code_p++;
 
-          if (opcode >= CBC_EXT_SPREAD_SUPER_CALL)
-          {
-            stack_top_p -= arguments_list_len;
-            ecma_collection_t *arguments_p = opfunc_spread_arguments (stack_top_p, arguments_list_len);
-
-            if (JERRY_UNLIKELY (arguments_p == NULL))
-            {
-              result = ECMA_VALUE_ERROR;
-              goto error;
-            }
+          frame_ctx_p->call_operation = VM_EXEC_SUPER_CALL;
+          frame_ctx_p->byte_code_p = byte_code_start_p;
+          frame_ctx_p->stack_top_p = stack_top_p - arguments_list_len;
+          return ECMA_VALUE_UNDEFINED;
+        }
+        case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_SPREAD_SUPER_CALL):
+        {
+          uint8_t arguments_list_len = *byte_code_p++;
+          stack_top_p -= arguments_list_len;
+          ecma_collection_t *arguments_p = opfunc_spread_arguments (stack_top_p, arguments_list_len);
 
-            stack_top_p++;
-            ECMA_SET_INTERNAL_VALUE_POINTER (stack_top_p[-1], arguments_p);
-          }
-          else
+          if (JERRY_UNLIKELY (arguments_p == NULL))
           {
-            stack_top_p -= arguments_list_len;
+            result = ECMA_VALUE_ERROR;
+            goto error;
           }
 
+          stack_top_p++;
+          ECMA_SET_INTERNAL_VALUE_POINTER (stack_top_p[-1], arguments_p);
+
           frame_ctx_p->call_operation = VM_EXEC_SUPER_CALL;
           frame_ctx_p->byte_code_p = byte_code_start_p;
           frame_ctx_p->stack_top_p = stack_top_p;
           return ECMA_VALUE_UNDEFINED;
         }
-        case VM_OC_PUSH_CLASS_ENVIRONMENT:
+        case VM_EXT_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV):
         {
           uint16_t literal_index;
-
           READ_LITERAL_INDEX (literal_index);
+
           opfunc_push_class_environment (frame_ctx_p, &stack_top_p, literal_start_p[literal_index]);
           continue;
         }
-        case VM_OC_PUSH_IMPLICIT_CTOR:
+        case VM_EXT_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR):
+        case VM_EXT_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE):
         {
-          *stack_top_p++ = opfunc_create_implicit_class_constructor (opcode, frame_ctx_p->shared_p->bytecode_header_p);
+          bool is_herigate = opcode == VM_EXT_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE);
+          *stack_top_p++ = opfunc_create_implicit_class_constructor (bytecode_header_p, is_herigate);
           continue;
         }
-        case VM_OC_DEFINE_FIELD:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_DEFINE_FIELD):
         {
+          VM_DECODE_EXT_STACK_LITERAL (CBC_EXT_DEFINE_FIELD);
+
           result = opfunc_define_field (frame_ctx_p->this_binding, right_value, left_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -2022,9 +2507,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             goto error;
           }
 
-          goto free_both_values;
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_ASSIGN_PRIVATE:
+        case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_ASSIGN_PRIVATE):
         {
           result = opfunc_private_set (stack_top_p[-3], stack_top_p[-2], stack_top_p[-1]);
 
@@ -2038,11 +2525,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           ecma_free_value (stack_top_p[-1]);
           stack_top_p -= 3;
 
-          if (opcode_data & VM_OC_PUT_STACK)
+          if (opcode == VM_EXT_OPCODE (CBC_EXT_ASSIGN_PRIVATE_PUSH_RESULT))
           {
             *stack_top_p++ = result;
           }
-          else if (opcode_data & VM_OC_PUT_BLOCK)
+          else if (opcode == VM_EXT_OPCODE (CBC_EXT_ASSIGN_PRIVATE_BLOCK))
           {
             ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0));
             VM_GET_REGISTERS (frame_ctx_p)[0] = result;
@@ -2052,10 +2539,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             ecma_free_value (result);
           }
 
-          goto free_both_values;
+          continue;
         }
-        case VM_OC_PRIVATE_FIELD_ADD:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PRIVATE_FIELD_ADD):
         {
+          VM_DECODE_EXT_STACK_LITERAL (CBC_EXT_PRIVATE_FIELD_ADD);
+
           result = opfunc_private_field_add (frame_ctx_p->this_binding, right_value, left_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -2063,10 +2552,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             goto error;
           }
 
-          goto free_both_values;
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_PRIVATE_PROP_GET:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL):
         {
+          VM_DECODE_EXT_STACK_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL);
+
           result = opfunc_private_get (left_value, right_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -2075,10 +2568,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_PRIVATE_PROP_REFERENCE:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE):
         {
+          VM_DECODE_EXT_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE);
+
           result = opfunc_private_get (stack_top_p[-1], left_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -2090,8 +2588,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = result;
           continue;
         }
-        case VM_OC_PRIVATE_IN:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN):
         {
+          VM_DECODE_EXT_STACK_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN);
+
           result = opfunc_private_in (left_value, right_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -2100,14 +2600,43 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
+        }
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_COLLECT_PRIVATE_FIELD):
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD):
+        {
+          VM_DECODE_EXT_LITERAL_2 (CBC_EXT_COLLECT_PRIVATE_FIELD, CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD);
+
+          JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE);
+          opfunc_collect_private_properties (stack_top_p[-2], left_value, ECMA_VALUE_UNDEFINED, byte_code_start_p[1]);
+          continue;
+        }
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_METHOD):
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD):
+        {
+          VM_DECODE_EXT_LITERAL_LITERAL_2 (CBC_EXT_COLLECT_PRIVATE_METHOD, CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD);
+
+          JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE);
+          opfunc_collect_private_properties (stack_top_p[-2], right_value, left_value, byte_code_start_p[1]);
+          continue;
         }
-        case VM_OC_COLLECT_PRIVATE_PROPERTY:
+
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_GETTER):
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_SETTER):
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER):
+        case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER):
         {
-          opfunc_collect_private_properties (stack_top_p[-2], left_value, right_value, opcode);
+          VM_DECODE_EXT_LITERAL_LITERAL_2 (CBC_EXT_COLLECT_PRIVATE_GETTER, CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER);
+          VM_DECODE_EXT_LITERAL_LITERAL_2 (CBC_EXT_COLLECT_PRIVATE_SETTER, CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER);
+
+          JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE);
+          opfunc_collect_private_properties (stack_top_p[-2], left_value, right_value, byte_code_start_p[1]);
           continue;
         }
-        case VM_OC_INIT_CLASS:
+        case VM_EXT_OPCODE (CBC_EXT_INIT_CLASS):
         {
           result = opfunc_init_class (frame_ctx_p, stack_top_p);
 
@@ -2117,22 +2646,23 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           continue;
         }
-        case VM_OC_FINALIZE_CLASS:
+        case VM_EXT_OPCODE (CBC_EXT_FINALIZE_NAMED_CLASS):
         {
-          JERRY_ASSERT (opcode == CBC_EXT_FINALIZE_NAMED_CLASS || opcode == CBC_EXT_FINALIZE_ANONYMOUS_CLASS);
-
-          if (opcode == CBC_EXT_FINALIZE_NAMED_CLASS)
-          {
-            uint16_t literal_index;
-            READ_LITERAL_INDEX (literal_index);
-            left_value = literal_start_p[literal_index];
-          }
+          uint16_t literal_index;
+          READ_LITERAL_INDEX (literal_index);
 
-          opfunc_finalize_class (frame_ctx_p, &stack_top_p, left_value);
+          opfunc_finalize_class (frame_ctx_p, &stack_top_p, literal_start_p[literal_index]);
+          continue;
+        }
+        case VM_EXT_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS):
+        {
+          opfunc_finalize_class (frame_ctx_p, &stack_top_p, ECMA_VALUE_UNDEFINED);
           continue;
         }
-        case VM_OC_SET_FIELD_INIT:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SET_FIELD_INIT):
         {
+          VM_DECODE_EXT_LITERAL (CBC_EXT_SET_FIELD_INIT);
+
           ecma_string_t *property_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT);
           ecma_object_t *proto_object_p = ecma_get_object_from_value (stack_top_p[-1]);
           ecma_object_t *class_object_p = ecma_get_object_from_value (stack_top_p[-2]);
@@ -2143,6 +2673,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           ecma_property_value_t *property_value_p =
             ecma_create_named_data_property (class_object_p, property_name_p, ECMA_PROPERTY_FIXED, NULL);
           property_value_p->value = left_value;
+          ecma_deref_object (initializer_func_p);
 
           property_name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED);
           ecma_property_t *property_p = ecma_find_named_property (class_object_p, property_name_p);
@@ -2155,10 +2686,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             compact_collection_p = ecma_compact_collection_shrink (compact_collection_p);
             ECMA_SET_INTERNAL_VALUE_POINTER (property_value_p->value, compact_collection_p);
           }
-
-          goto free_left_value;
+          continue;
         }
-        case VM_OC_RUN_FIELD_INIT:
+        case VM_EXT_OPCODE (CBC_EXT_RUN_FIELD_INIT):
         {
           JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC);
           result = opfunc_init_class_fields (frame_ctx_p->shared_p->function_object_p, frame_ctx_p->this_binding);
@@ -2169,7 +2699,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           continue;
         }
-        case VM_OC_RUN_STATIC_FIELD_INIT:
+        case VM_EXT_OPCODE (CBC_EXT_RUN_STATIC_FIELD_INIT):
         {
           left_value = stack_top_p[-2];
           stack_top_p[-2] = stack_top_p[-1];
@@ -2181,9 +2711,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           {
             goto error;
           }
-          goto free_left_value;
+
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_SET_NEXT_COMPUTED_FIELD:
+        case VM_EXT_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC):
+        case VM_EXT_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD):
         {
           ecma_integer_value_t next_index = ecma_get_integer_from_value (stack_top_p[-2]) + 1;
           stack_top_p[-2] = ecma_make_integer_value (next_index);
@@ -2194,7 +2727,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           JERRY_ASSERT ((ecma_value_t) next_index < ECMA_COMPACT_COLLECTION_GET_SIZE (computed_class_fields_p));
           ecma_value_t prop_name = computed_class_fields_p[next_index];
 
-          if (opcode == CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC)
+          if (opcode == VM_EXT_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC))
           {
             ecma_object_t *func_obj_p = ecma_get_object_from_value (stack_top_p[-1]);
 
@@ -2223,7 +2756,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           ecma_free_value (*(--stack_top_p));
           continue;
         }
-        case VM_OC_PUSH_SUPER_CONSTRUCTOR:
+        case VM_EXT_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR):
         {
           result = ecma_op_function_get_super_constructor (vm_get_class_function (frame_ctx_p));
 
@@ -2235,7 +2768,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = result;
           continue;
         }
-        case VM_OC_RESOLVE_LEXICAL_THIS:
+        case VM_EXT_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS):
         {
           result = ecma_op_get_this_binding (frame_ctx_p->lex_env_p);
 
@@ -2247,118 +2780,160 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = result;
           continue;
         }
-        case VM_OC_OBJECT_LITERAL_HOME_ENV:
+        case VM_EXT_OPCODE (CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT):
         {
-          if (opcode == CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT)
-          {
-            ecma_value_t obj_value = stack_top_p[-1];
-            ecma_object_t *obj_env_p = ecma_create_lex_env_class (frame_ctx_p->lex_env_p, 0);
+          ecma_value_t obj_value = stack_top_p[-1];
+          ecma_object_t *obj_env_p = ecma_create_lex_env_class (frame_ctx_p->lex_env_p, 0);
 
-            ECMA_SET_NON_NULL_POINTER (obj_env_p->u1.bound_object_cp, ecma_get_object_from_value (obj_value));
-            stack_top_p[-1] = ecma_make_object_value (obj_env_p);
-            *stack_top_p++ = obj_value;
-          }
-          else
-          {
-            JERRY_ASSERT (opcode == CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT);
-            ecma_deref_object (ecma_get_object_from_value (stack_top_p[-2]));
-            stack_top_p[-2] = stack_top_p[-1];
-            stack_top_p--;
-          }
+          ECMA_SET_NON_NULL_POINTER (obj_env_p->u1.bound_object_cp, ecma_get_object_from_value (obj_value));
+          stack_top_p[-1] = ecma_make_object_value (obj_env_p);
+          *stack_top_p++ = obj_value;
           continue;
         }
-        case VM_OC_SET_HOME_OBJECT:
+        case VM_EXT_OPCODE (CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT):
         {
-          int offset = opcode == CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED ? -1 : 0;
+          ecma_deref_object (ecma_get_object_from_value (stack_top_p[-2]));
+          stack_top_p[-2] = stack_top_p[-1];
+          stack_top_p--;
+          continue;
+        }
+        case VM_EXT_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT):
+        case VM_EXT_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED):
+        {
+          const int index = opcode - VM_EXT_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT);
           opfunc_set_home_object (ecma_get_object_from_value (stack_top_p[-1]),
-                                  ecma_get_object_from_value (stack_top_p[-3 + offset]));
+                                  ecma_get_object_from_value (stack_top_p[-3 - index]));
           continue;
         }
-        case VM_OC_SUPER_REFERENCE:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE):
         {
-          result = opfunc_form_super_reference (&stack_top_p, frame_ctx_p, left_value, opcode);
+          VM_DECODE_EXT_STACK (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE)
+          VM_DECODE_EXT_LITERAL (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE);
+
+          result = opfunc_resolve_super (frame_ctx_p);
 
           if (ECMA_IS_VALUE_ERROR (result))
           {
             goto error;
           }
 
-          goto free_left_value;
+          *stack_top_p++ = result;
+          *stack_top_p++ = left_value;
+          continue;
         }
-        case VM_OC_SET_FUNCTION_NAME:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE):
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_SUPER_PROP_LITERAL):
         {
-          char *prefix_p = NULL;
-          lit_utf8_size_t prefix_size = 0;
+          VM_DECODE_EXT_STACK_2 (CBC_EXT_PUSH_SUPER_PROP, CBC_EXT_SUPER_PROP_REFERENCE)
+          VM_DECODE_EXT_LITERAL_2 (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_EXT_SUPER_PROP_LITERAL_REFERENCE);
 
-          if (opcode != CBC_EXT_SET_FUNCTION_NAME)
+          JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE);
+          result = opfunc_resolve_super (frame_ctx_p);
+
+          if (ECMA_IS_VALUE_ERROR (result))
           {
-            ecma_value_t prop_name_value;
+            goto error;
+          }
 
-            if (opcode == CBC_EXT_SET_CLASS_NAME)
-            {
-              uint16_t literal_index;
-              READ_LITERAL_INDEX (literal_index);
-              prop_name_value = literal_start_p[literal_index];
-            }
-            else
-            {
-              prop_name_value = stack_top_p[-2];
-            }
+          right_value = result;
+          ecma_object_t *parent_p = ecma_get_object_from_value (right_value);
+          ecma_string_t *prop_name_p = ecma_op_to_property_key (left_value);
 
-            ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name_value);
+          if (prop_name_p == NULL)
+          {
+            result = ECMA_VALUE_ERROR;
+            goto error;
+          }
 
-            if (JERRY_UNLIKELY (prop_name_p == NULL))
-            {
-              result = ECMA_VALUE_ERROR;
-              goto error;
-            }
+          result = ecma_op_object_get_with_receiver (parent_p, prop_name_p, frame_ctx_p->this_binding);
+          ecma_deref_ecma_string (prop_name_p);
 
-            left_value = ecma_make_prop_name_value (prop_name_p);
+          if (ECMA_IS_VALUE_ERROR (result))
+          {
+            return result;
+          }
 
-            if (opcode != CBC_EXT_SET_CLASS_NAME)
-            {
-              ecma_ref_ecma_string (prop_name_p);
-              ecma_free_value (stack_top_p[-2]);
-              stack_top_p[-2] = left_value;
-            }
+          if (byte_code_start_p[1] >= CBC_EXT_SUPER_PROP_REFERENCE)
+          {
+            *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding);
+            *stack_top_p++ = ECMA_VALUE_UNDEFINED;
+          }
 
-            if (opcode == CBC_EXT_SET_COMPUTED_GETTER_NAME || opcode == CBC_EXT_SET_COMPUTED_SETTER_NAME)
-            {
-              prefix_p = (opcode == CBC_EXT_SET_COMPUTED_GETTER_NAME) ? "get " : "set ";
-              prefix_size = 4;
-            }
+          *stack_top_p++ = result;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
+        }
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SET_FUNCTION_NAME):
+        {
+          VM_DECODE_EXT_LITERAL (CBC_EXT_SET_FUNCTION_NAME);
+
+          opfunc_set_function_name (stack_top_p[-1], left_value, NULL, 0);
+
+          ecma_fast_free_value (left_value);
+          continue;
+        }
+        case VM_EXT_OPCODE (CBC_EXT_SET_CLASS_NAME):
+        case VM_EXT_OPCODE (CBC_EXT_SET_COMPUTED_FUNCTION_NAME):
+        case VM_EXT_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME):
+        case VM_EXT_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME):
+        {
+          char *prefix_p = NULL;
+          lit_utf8_size_t prefix_size = 0;
+
+          ecma_value_t prop_name_value;
+
+          if (opcode == VM_EXT_OPCODE (CBC_EXT_SET_CLASS_NAME))
+          {
+            uint16_t literal_index;
+            READ_LITERAL_INDEX (literal_index);
+            prop_name_value = literal_start_p[literal_index];
+          }
+          else
+          {
+            prop_name_value = stack_top_p[-2];
           }
 
-          ecma_object_t *func_obj_p = ecma_get_object_from_value (stack_top_p[-1]);
+          ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name_value);
 
-          if (ecma_find_named_property (func_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_NAME)) != NULL)
+          if (JERRY_UNLIKELY (prop_name_p == NULL))
           {
-            ecma_free_value (left_value);
-            continue;
+            result = ECMA_VALUE_ERROR;
+            goto error;
           }
 
-          ecma_property_value_t *value_p;
-          value_p = ecma_create_named_data_property (func_obj_p,
-                                                     ecma_get_magic_string (LIT_MAGIC_STRING_NAME),
-                                                     ECMA_PROPERTY_FLAG_CONFIGURABLE,
-                                                     NULL);
+          left_value = ecma_make_prop_name_value (prop_name_p);
 
-          if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
+          if (opcode != VM_EXT_OPCODE (CBC_EXT_SET_CLASS_NAME))
           {
-            ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp);
+            ecma_ref_ecma_string (prop_name_p);
+            ecma_free_value (stack_top_p[-2]);
+            stack_top_p[-2] = left_value;
           }
 
-          value_p->value =
-            ecma_op_function_form_name (ecma_get_prop_name_from_value (left_value), prefix_p, prefix_size);
-          ecma_free_value (left_value);
+          if (opcode == VM_EXT_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME))
+          {
+            prefix_p = "get ";
+            prefix_size = 4;
+          }
+          else if (opcode == VM_EXT_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME))
+          {
+            prefix_p = "set ";
+            prefix_size = 4;
+          }
+
+          opfunc_set_function_name (stack_top_p[-1], left_value, prefix_p, prefix_size);
+
+          ecma_fast_free_value (left_value);
           continue;
         }
-        case VM_OC_PUSH_SPREAD_ELEMENT:
+        case VM_EXT_OPCODE (CBC_EXT_PUSH_SPREAD_ELEMENT):
         {
           *stack_top_p++ = ECMA_VALUE_SPREAD_ELEMENT;
           continue;
         }
-        case VM_OC_PUSH_REST_OBJECT:
+        case VM_EXT_OPCODE (CBC_EXT_PUSH_REST_OBJECT):
         {
           vm_frame_ctx_shared_t *shared_p = frame_ctx_p->shared_p;
 
@@ -2388,7 +2963,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = result;
           continue;
         }
-        case VM_OC_ITERATOR_CONTEXT_CREATE:
+        case VM_EXT_OPCODE (CBC_EXT_ITERATOR_CONTEXT_CREATE):
         {
           result = ecma_op_get_iterator (stack_top_p[-1], ECMA_VALUE_SYNC_ITERATOR, &left_value);
 
@@ -2408,7 +2983,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
           continue;
         }
-        case VM_OC_ITERATOR_STEP:
+        case VM_EXT_OPCODE (CBC_EXT_ITERATOR_STEP):
         {
           ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
 
@@ -2445,7 +3020,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = value;
           continue;
         }
-        case VM_OC_ITERATOR_CONTEXT_END:
+        case VM_EXT_OPCODE (CBC_EXT_ITERATOR_CONTEXT_END):
         {
           JERRY_ASSERT (VM_LAST_CONTEXT_END () == stack_top_p);
 
@@ -2464,8 +3039,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             vm_stack_context_abort_variable_length (frame_ctx_p, stack_top_p, PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION);
           continue;
         }
-        case VM_OC_DEFAULT_INITIALIZER:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_DEFAULT_INITIALIZER):
         {
+          VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER);
+
           JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end);
 
           if (stack_top_p[-1] != ECMA_VALUE_UNDEFINED)
@@ -2477,7 +3054,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           stack_top_p--;
           continue;
         }
-        case VM_OC_REST_INITIALIZER:
+        case VM_EXT_OPCODE (CBC_EXT_REST_INITIALIZER):
         {
           ecma_object_t *array_p = ecma_op_new_array_object (0);
           JERRY_ASSERT (ecma_op_object_is_fast_array (array_p));
@@ -2522,13 +3099,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = ecma_make_object_value (array_p);
           continue;
         }
-        case VM_OC_OBJ_INIT_CONTEXT_CREATE:
+        case VM_EXT_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_CREATE):
+        case VM_EXT_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE):
         {
           left_value = stack_top_p[-1];
           vm_stack_context_type_t context_type = VM_CONTEXT_OBJ_INIT;
           uint32_t context_stack_allocation = PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION;
 
-          if (opcode == CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE)
+          if (opcode == VM_EXT_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE))
           {
             context_type = VM_CONTEXT_OBJ_INIT_REST;
             context_stack_allocation = PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION;
@@ -2547,7 +3125,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           continue;
         }
-        case VM_OC_OBJ_INIT_CONTEXT_END:
+        case VM_EXT_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_END):
         {
           JERRY_ASSERT (stack_top_p == VM_LAST_CONTEXT_END ());
 
@@ -2561,7 +3139,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p, stack_top_p, context_stack_allocation);
           continue;
         }
-        case VM_OC_OBJ_INIT_PUSH_REST:
+        case VM_EXT_OPCODE (CBC_EXT_OBJ_INIT_PUSH_REST):
         {
           ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
           if (!ecma_op_require_object_coercible (last_context_end_p[-2]))
@@ -2588,8 +3166,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = left_value;
           continue;
         }
-        case VM_OC_INITIALIZER_PUSH_NAME:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL):
         {
+          VM_DECODE_EXT_STACK (CBC_EXT_INITIALIZER_PUSH_NAME);
+          VM_DECODE_EXT_LITERAL (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL);
+
           if (JERRY_UNLIKELY (!ecma_is_value_prop_name (left_value)))
           {
             ecma_string_t *property_key = ecma_op_to_property_key (left_value);
@@ -2610,14 +3191,19 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
           ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p;
           ecma_fast_array_set_property (array_obj_p, ext_array_obj_p->u.array.length, left_value);
+
+          result = left_value;
           /* FALLTHRU */
         }
-        case VM_OC_INITIALIZER_PUSH_PROP:
+        case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL):
+        case VM_EXT_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP):
         {
+          VM_DECODE_EXT_LITERAL (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL);
+
           ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
           ecma_value_t base = last_context_end_p[-2];
 
-          if (opcode == CBC_EXT_INITIALIZER_PUSH_PROP)
+          if (opcode == VM_EXT_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP))
           {
             left_value = *last_context_end_p++;
             while (last_context_end_p < stack_top_p)
@@ -2636,9 +3222,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_left_value;
+
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_SPREAD_ARGUMENTS:
+        case VM_EXT_OPCODE (CBC_EXT_SPREAD_NEW):
+        case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_SPREAD_CALL):
+        case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_SPREAD_CALL_PROP):
         {
           uint8_t arguments_list_len = *byte_code_p++;
           stack_top_p -= arguments_list_len;
@@ -2659,7 +3249,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           frame_ctx_p->stack_top_p = stack_top_p;
           return ECMA_VALUE_UNDEFINED;
         }
-        case VM_OC_CREATE_GENERATOR:
+        case VM_EXT_OPCODE (CBC_EXT_CREATE_GENERATOR):
         {
           frame_ctx_p->call_operation = VM_EXEC_RETURN;
           frame_ctx_p->byte_code_p = byte_code_p;
@@ -2670,14 +3260,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
           return ecma_make_object_value ((ecma_object_t *) executable_object_p);
         }
-        case VM_OC_YIELD:
+        case VM_EXT_OPCODE (CBC_EXT_YIELD):
+        case VM_EXT_OPCODE (CBC_EXT_YIELD_ITERATOR):
         {
           frame_ctx_p->call_operation = VM_EXEC_RETURN;
           frame_ctx_p->byte_code_p = byte_code_p;
           frame_ctx_p->stack_top_p = --stack_top_p;
           return *stack_top_p;
         }
-        case VM_OC_ASYNC_YIELD:
+        case VM_EXT_OPCODE (CBC_EXT_ASYNC_YIELD):
         {
           ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p);
 
@@ -2688,7 +3279,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           frame_ctx_p->stack_top_p = --stack_top_p;
           return ECMA_VALUE_UNDEFINED;
         }
-        case VM_OC_ASYNC_YIELD_ITERATOR:
+        case VM_EXT_OPCODE (CBC_EXT_ASYNC_YIELD_ITERATOR):
         {
           ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p);
 
@@ -2728,7 +3319,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           frame_ctx_p->stack_top_p = stack_top_p;
           return ECMA_VALUE_UNDEFINED;
         }
-        case VM_OC_AWAIT:
+        case VM_EXT_OPCODE (CBC_EXT_AWAIT):
         {
           if (JERRY_UNLIKELY (!(frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_EXECUTABLE)))
           {
@@ -2746,7 +3337,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           /* FALLTHRU */
         }
-        case VM_OC_GENERATOR_AWAIT:
+        case VM_EXT_OPCODE (CBC_EXT_GENERATOR_AWAIT):
         {
           ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p);
 
@@ -2762,8 +3353,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           frame_ctx_p->stack_top_p = stack_top_p;
           return ECMA_VALUE_UNDEFINED;
         }
-        case VM_OC_EXT_RETURN:
+        case VM_EXT_OPCODE (CBC_EXT_RETURN_UNDEFINED):
         {
+          VM_DECODE_EXT_STACK (CBC_EXT_RETURN);
           result = left_value;
           left_value = ECMA_VALUE_UNDEFINED;
 
@@ -2776,7 +3368,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
           goto error;
         }
-        case VM_OC_ASYNC_EXIT:
+        case VM_EXT_OPCODE (CBC_EXT_ASYNC_EXIT):
         {
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
 
@@ -2819,8 +3411,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           frame_ctx_p->call_operation = VM_NO_EXEC_OP;
           return result;
         }
-        case VM_OC_STRING_CONCAT:
+        case VM_EXT_OPCODE_ARITHMETIC_CASE (CBC_EXT_STRING_CONCAT):
         {
+          VM_DECODE_EXT_ARITHMETIC (CBC_EXT_STRING_CONCAT);
+
           ecma_string_t *left_str_p = ecma_op_to_string (left_value);
 
           if (JERRY_UNLIKELY (left_str_p == NULL))
@@ -2841,9 +3435,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           ecma_deref_ecma_string (right_str_p);
 
           *stack_top_p++ = ecma_make_string_value (result_str_p);
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_GET_TEMPLATE_OBJECT:
+        case VM_EXT_OPCODE (CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL):
         {
           uint8_t tagged_idx = *byte_code_p++;
           ecma_collection_t *collection_p = ecma_compiled_code_get_tagged_template_collection (bytecode_header_p);
@@ -2852,7 +3449,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = ecma_copy_value (collection_p->buffer_p[tagged_idx]);
           continue;
         }
-        case VM_OC_PUSH_NEW_TARGET:
+        case VM_EXT_OPCODE (CBC_EXT_PUSH_NEW_TARGET):
         {
           ecma_object_t *new_target_object_p = JERRY_CONTEXT (current_new_target_p);
           if (new_target_object_p == NULL)
@@ -2866,7 +3463,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           continue;
         }
-        case VM_OC_REQUIRE_OBJECT_COERCIBLE:
+        case VM_EXT_OPCODE (CBC_EXT_REQUIRE_OBJECT_COERCIBLE):
         {
           if (!ecma_op_require_object_coercible (stack_top_p[-1]))
           {
@@ -2875,46 +3472,91 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           continue;
         }
-        case VM_OC_ASSIGN_SUPER:
+        case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_ASSIGN_SUPER):
         {
-          result = opfunc_assign_super_reference (&stack_top_p, frame_ctx_p, opcode_data);
+          JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE);
+
+          ecma_value_t base_obj = ecma_op_to_object (stack_top_p[-3]);
+
+          if (ECMA_IS_VALUE_ERROR (base_obj))
+          {
+            return base_obj;
+          }
+
+          ecma_object_t *base_obj_p = ecma_get_object_from_value (base_obj);
+          ecma_string_t *prop_name_p = ecma_op_to_property_key (stack_top_p[-2]);
+
+          if (prop_name_p == NULL)
+          {
+            ecma_deref_object (base_obj_p);
+            result = ECMA_VALUE_ERROR;
+            goto error;
+          }
+
+          result = ecma_op_object_put_with_receiver (base_obj_p,
+                                                     prop_name_p,
+                                                     stack_top_p[-1],
+                                                     frame_ctx_p->this_binding,
+                                                     is_strict);
+
+          ecma_deref_ecma_string (prop_name_p);
+          ecma_deref_object (base_obj_p);
 
           if (ECMA_IS_VALUE_ERROR (result))
           {
             goto error;
           }
+
+          for (int32_t i = 1; i <= 3; i++)
+          {
+            ecma_free_value (stack_top_p[-i]);
+          }
+
+          stack_top_p -= 3;
+
+          if (opcode == VM_EXT_OPCODE (CBC_EXT_ASSIGN_SUPER_PUSH_RESULT))
+          {
+            *stack_top_p++ = result;
+          }
+          else if (opcode == VM_EXT_OPCODE (CBC_EXT_ASSIGN_SUPER_BLOCK))
+          {
+            ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0));
+            VM_GET_REGISTERS (frame_ctx_p)[0] = result;
+          }
+          else
+          {
+            ecma_free_value (result);
+          }
           continue;
         }
-#endif /* JERRY_ESNEXT */
-        case VM_OC_PUSH_ELISON:
-        {
-          *stack_top_p++ = ECMA_VALUE_ARRAY_HOLE;
-          continue;
-        }
-        case VM_OC_APPEND_ARRAY:
+        case VM_EXT_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND):
         {
           uint16_t values_length = *byte_code_p++;
           stack_top_p -= values_length;
 
-#if JERRY_ESNEXT
-          if (*byte_code_start_p == CBC_EXT_OPCODE)
-          {
-            values_length = (uint16_t) (values_length | OPFUNC_HAS_SPREAD_ELEMENT);
-          }
-#endif /* JERRY_ESNEXT */
-          result = opfunc_append_array (stack_top_p, values_length);
+          result = opfunc_append_to_spread_array (stack_top_p, values_length);
 
-#if JERRY_ESNEXT
           if (ECMA_IS_VALUE_ERROR (result))
           {
             goto error;
           }
-#else /* !JERRY_ESNEXT */
-          JERRY_ASSERT (ecma_is_value_empty (result));
+          continue;
+        }
 #endif /* JERRY_ESNEXT */
+        case CBC_PUSH_ELISION:
+        {
+          *stack_top_p++ = ECMA_VALUE_ARRAY_HOLE;
+          continue;
+        }
+        case CBC_ARRAY_APPEND:
+        {
+          uint16_t values_length = *byte_code_p++;
+          stack_top_p -= values_length;
+
+          opfunc_append_array (stack_top_p, values_length);
           continue;
         }
-        case VM_OC_IDENT_REFERENCE:
+        case CBC_PUSH_IDENT_REFERENCE:
         {
           uint16_t literal_index;
 
@@ -2949,8 +3591,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           continue;
         }
-        case VM_OC_PROP_GET:
+        case VM_OPCODE_ONE_LITERAL (CBC_PUSH_PROP_LITERAL):
+        case VM_OPCODE_ONE_LITERAL (CBC_PUSH_PROP_THIS_LITERAL):
+        case VM_OPCODE_TWO_LITERALS (CBC_PUSH_PROP_LITERAL_LITERAL):
         {
+          VM_DECODE_STACK_LITERAL (CBC_PUSH_PROP_LITERAL);
+          VM_DECODE_LITERAL_LITERAL (CBC_PUSH_PROP_LITERAL_LITERAL);
+          VM_DECODE_THIS_LITERAL (CBC_PUSH_PROP_THIS_LITERAL);
+          VM_DECODE_STACK_STACK (CBC_PUSH_PROP);
+
           result = vm_op_get_value (left_value, right_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -2959,79 +3608,78 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_PROP_REFERENCE:
+        case VM_OPCODE_ONE_LITERAL (CBC_PUSH_PROP_LITERAL_REFERENCE):
         {
-          /* Forms with reference requires preserving the base and offset. */
+          VM_DECODE_LITERAL (CBC_PUSH_PROP_LITERAL_REFERENCE)
+          *stack_top_p++ = left_value;
+          goto vm_push_prop_reference;
+        }
+        case VM_OPCODE_TWO_LITERALS (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE):
+        case VM_OPCODE_ONE_LITERAL (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE):
+        {
+          VM_DECODE_LITERAL_LITERAL (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE);
+          VM_DECODE_THIS_LITERAL (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE);
 
-          if (opcode == CBC_PUSH_PROP_REFERENCE)
-          {
-            left_value = stack_top_p[-2];
-            right_value = stack_top_p[-1];
-          }
-          else if (opcode == CBC_PUSH_PROP_LITERAL_REFERENCE)
-          {
-            *stack_top_p++ = left_value;
-            right_value = left_value;
-            left_value = stack_top_p[-2];
-          }
-          else
-          {
-            JERRY_ASSERT (opcode == CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE
-                          || opcode == CBC_PUSH_PROP_THIS_LITERAL_REFERENCE);
-            *stack_top_p++ = left_value;
-            *stack_top_p++ = right_value;
-          }
+          *stack_top_p++ = left_value;
+          *stack_top_p++ = right_value;
           /* FALLTHRU */
         }
-        case VM_OC_PROP_PRE_INCR:
-        case VM_OC_PROP_PRE_DECR:
-        case VM_OC_PROP_POST_INCR:
-        case VM_OC_PROP_POST_DECR:
+        case CBC_PUSH_PROP_REFERENCE:
         {
-          result = vm_op_get_value (left_value, right_value);
+vm_push_prop_reference:
+          result = vm_op_get_value (stack_top_p[-2], stack_top_p[-1]);
 
-          if (opcode < CBC_PRE_INCR)
+          if (ECMA_IS_VALUE_ERROR (result))
           {
             left_value = ECMA_VALUE_UNDEFINED;
             right_value = ECMA_VALUE_UNDEFINED;
-          }
-
-          if (ECMA_IS_VALUE_ERROR (result))
-          {
             goto error;
           }
 
-          if (opcode < CBC_PRE_INCR)
+          *stack_top_p++ = result;
+          continue;
+        }
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_PRE_INCR):
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_PRE_DECR):
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_POST_INCR):
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_POST_DECR):
+        {
+          left_value = vm_op_get_value (stack_top_p[-2], stack_top_p[-1]);
+
+          if (ECMA_IS_VALUE_ERROR (left_value))
           {
-            break;
+            result = left_value;
+            left_value = ECMA_VALUE_UNDEFINED;
+            goto error;
           }
-
-          stack_top_p += 2;
-          left_value = result;
-          right_value = ECMA_VALUE_UNDEFINED;
           /* FALLTHRU */
         }
-        case VM_OC_PRE_INCR:
-        case VM_OC_PRE_DECR:
-        case VM_OC_POST_INCR:
-        case VM_OC_POST_DECR:
+        case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_PRE_INCR_IDENT):
+        case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_PRE_DECR_IDENT):
+        case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_POST_INCR_IDENT):
+        case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_POST_DECR_IDENT):
         {
-          uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_PROP_PRE_INCR;
+          VM_DECODE_LITERAL_PUT_RESULT (CBC_PRE_INCR_IDENT);
+          VM_DECODE_LITERAL_PUT_RESULT (CBC_PRE_DECR_IDENT);
+          VM_DECODE_LITERAL_PUT_RESULT (CBC_POST_INCR_IDENT);
+          VM_DECODE_LITERAL_PUT_RESULT (CBC_POST_DECR_IDENT);
+
+          put_result_flags = vm_incr_decr_flags[*byte_code_start_p - CBC_PRE_INCR];
           ecma_number_t result_number;
 
           byte_code_p = byte_code_start_p + 1;
 
           if (ecma_is_value_integer_number (left_value))
           {
-            result = left_value;
-            left_value = ECMA_VALUE_UNDEFINED;
-
-            ecma_integer_value_t int_value = (ecma_integer_value_t) result;
+            ecma_integer_value_t int_value = (ecma_integer_value_t) left_value;
             ecma_integer_value_t int_increase = 0;
 
-            if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG)
+            if (put_result_flags & VM_PUT_RESULT_DECR)
             {
               if (int_value > ECMA_INTEGER_NUMBER_MIN_SHIFTED)
               {
@@ -3045,22 +3693,21 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
             if (JERRY_LIKELY (int_increase != 0))
             {
+              result = (ecma_value_t) (int_value + int_increase);
+
               /* Postfix operators require the unmodifed number value. */
-              if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG)
+              if (put_result_flags & VM_PUT_RESULT_POST)
               {
-                POST_INCREASE_DECREASE_PUT_RESULT (result);
+                goto post_incr_decr;
               }
 
-              result = (ecma_value_t) (int_value + int_increase);
               break;
             }
-            result_number = (ecma_number_t) ecma_get_integer_from_value (result);
+            result_number = (ecma_number_t) ecma_get_integer_from_value (left_value);
           }
           else if (ecma_is_value_float_number (left_value))
           {
-            result = left_value;
-            left_value = ECMA_VALUE_UNDEFINED;
-            result_number = ecma_get_number_from_value (result);
+            result_number = ecma_get_number_from_value (left_value);
           }
           else
           {
@@ -3072,105 +3719,146 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             }
 
             ecma_free_value (left_value);
-            left_value = ECMA_VALUE_UNDEFINED;
 
 #if JERRY_BUILTIN_BIGINT
             if (JERRY_UNLIKELY (ecma_is_value_bigint (result)))
             {
+              left_value = result;
               ecma_bigint_unary_operation_type operation_type = ECMA_BIGINT_UNARY_INCREASE;
 
-              if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG)
+              if (put_result_flags & VM_PUT_RESULT_DECR)
               {
                 operation_type = ECMA_BIGINT_UNARY_DECREASE;
               }
 
-              /* Postfix operators require the unmodifed number value. */
-              if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG)
-              {
-                POST_INCREASE_DECREASE_PUT_RESULT (result);
+              result = ecma_bigint_unary (left_value, operation_type);
 
-                result = ecma_bigint_unary (result, operation_type);
-              }
-              else
+              if (ECMA_IS_VALUE_ERROR (result))
               {
-                ecma_value_t original_value = result;
-                result = ecma_bigint_unary (original_value, operation_type);
-                ecma_free_value (original_value);
+                goto error;
               }
 
-              if (ECMA_IS_VALUE_ERROR (result))
+              /* Postfix operators require the unmodifed number value. */
+              if (put_result_flags & VM_PUT_RESULT_POST)
               {
-                goto error;
+                goto post_incr_decr;
               }
+
+              ecma_free_value (left_value);
               break;
             }
 #endif /* JERRY_BUILTIN_BIGINT */
 
-            result = ecma_make_number_value (result_number);
+            left_value = ecma_make_number_value (result_number);
           }
 
           ecma_number_t increase = ECMA_NUMBER_ONE;
 
-          if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG)
+          if (put_result_flags & VM_PUT_RESULT_DECR)
           {
             /* For decrement operators */
             increase = ECMA_NUMBER_MINUS_ONE;
           }
 
           /* Postfix operators require the unmodifed number value. */
-          if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG)
+          if (put_result_flags & VM_PUT_RESULT_POST)
           {
-            POST_INCREASE_DECREASE_PUT_RESULT (result);
-
             result = ecma_make_number_value (result_number + increase);
-            break;
+            goto post_incr_decr;
           }
 
-          if (ecma_is_value_integer_number (result))
+          if (ecma_is_value_integer_number (left_value))
           {
             result = ecma_make_number_value (result_number + increase);
           }
           else
           {
-            result = ecma_update_float_number (result, result_number + increase);
+            result = ecma_update_float_number (left_value, result_number + increase);
+          }
+          break;
+
+post_incr_decr:
+          /* left_value holds the old value, result contains the new value */
+          if (put_result_flags & VM_PUT_RESULT_STACK)
+          {
+            if (put_result_flags & VM_PUT_RESULT_IDENT)
+            {
+              JERRY_ASSERT (opcode == VM_OPCODE_ONE_LITERAL (CBC_POST_INCR_IDENT_PUSH_RESULT)
+                            || opcode == VM_OPCODE_ONE_LITERAL (CBC_POST_DECR_IDENT_PUSH_RESULT));
+              *stack_top_p++ = left_value;
+            }
+            else
+            { /* The parser ensures there is enough space for the extra value on the stack. See js-parser-expr.c. */
+              JERRY_ASSERT (opcode == CBC_POST_INCR_PUSH_RESULT || opcode == CBC_POST_DECR_PUSH_RESULT);
+              stack_top_p++;
+              stack_top_p[-1] = stack_top_p[-2];
+              stack_top_p[-2] = stack_top_p[-3];
+              stack_top_p[-3] = left_value;
+            }
+            put_result_flags &= (uint8_t) ~VM_PUT_RESULT_STACK;
+          }
+          else
+          {
+            JERRY_ASSERT (put_result_flags & VM_PUT_RESULT_BLOCK);
+            ecma_free_value (VM_GET_REGISTER (frame_ctx_p, 0));
+            VM_GET_REGISTERS (frame_ctx_p)[0] = left_value;
+            put_result_flags &= (uint8_t) ~VM_PUT_RESULT_BLOCK;
           }
+
           break;
         }
-        case VM_OC_ASSIGN:
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_ASSIGN):
+        {
+          VM_POP_STACK (result);
+          put_result_flags = (uint8_t) (opcode - CBC_ASSIGN);
+          goto dispatch_put_reference;
+        }
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_ASSIGN_SET_IDENT):
         {
+          VM_POP_STACK (result);
+          put_result_flags = (uint8_t) (opcode - CBC_ASSIGN_SET_IDENT);
+          goto dispatch_put_ident;
+        }
+        case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_ASSIGN_LITERAL_SET_IDENT):
+        {
+          VM_DECODE_LITERAL_PUT_RESULT (CBC_ASSIGN_LITERAL_SET_IDENT);
+
           result = left_value;
-          left_value = ECMA_VALUE_UNDEFINED;
-          break;
+          put_result_flags = (uint8_t) (opcode - CBC_ASSIGN_LITERAL_SET_IDENT);
+          goto dispatch_put_ident;
         }
-        case VM_OC_MOV_IDENT:
+        case CBC_MOV_IDENT:
         {
-          uint32_t literal_index;
+          VM_POP_STACK (left_value);
 
+          uint32_t literal_index;
           READ_LITERAL_INDEX (literal_index);
-
           JERRY_ASSERT (literal_index < register_end);
-          JERRY_ASSERT (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)));
 
           ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index));
           VM_GET_REGISTER (frame_ctx_p, literal_index) = left_value;
           continue;
         }
-        case VM_OC_ASSIGN_PROP:
+        case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_ASSIGN_PROP_LITERAL):
         {
+          VM_DECODE_LITERAL_PUT_RESULT (CBC_ASSIGN_PROP_LITERAL);
+
           result = stack_top_p[-1];
           stack_top_p[-1] = left_value;
-          left_value = ECMA_VALUE_UNDEFINED;
-          break;
+          put_result_flags = (uint8_t) (opcode - CBC_ASSIGN_PROP_LITERAL);
+          goto dispatch_put_reference;
         }
-        case VM_OC_ASSIGN_PROP_THIS:
+        case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_ASSIGN_PROP_THIS_LITERAL):
         {
+          VM_DECODE_LITERAL_PUT_RESULT (CBC_ASSIGN_PROP_THIS_LITERAL);
+
           result = stack_top_p[-1];
           stack_top_p[-1] = ecma_copy_value (frame_ctx_p->this_binding);
           *stack_top_p++ = left_value;
-          left_value = ECMA_VALUE_UNDEFINED;
-          break;
+          put_result_flags = (uint8_t) (opcode - CBC_ASSIGN_PROP_THIS_LITERAL);
+          goto dispatch_put_reference;
         }
-        case VM_OC_RETURN_FUNCTION_END:
+        case CBC_RETURN_FUNCTION_END:
         {
           if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) == CBC_FUNCTION_SCRIPT)
           {
@@ -3184,28 +3872,32 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
           goto error;
         }
-        case VM_OC_RETURN:
+        case CBC_RETURN:
         {
-          JERRY_ASSERT (opcode == CBC_RETURN || opcode == CBC_RETURN_WITH_LITERAL);
-
+          VM_POP_STACK (result);
+          goto error;
+        }
+        case VM_OPCODE_ONE_LITERAL (CBC_RETURN_WITH_LITERAL):
+        {
+          VM_DECODE_LITERAL (CBC_RETURN_WITH_LITERAL);
           result = left_value;
           left_value = ECMA_VALUE_UNDEFINED;
           goto error;
         }
-        case VM_OC_THROW:
+        case CBC_THROW:
         {
-          jcontext_raise_exception (left_value);
+          VM_POP_STACK (result);
 
+          jcontext_raise_exception (result);
           result = ECMA_VALUE_ERROR;
-          left_value = ECMA_VALUE_UNDEFINED;
           goto error;
         }
-        case VM_OC_THROW_REFERENCE_ERROR:
+        case VM_EXT_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR):
         {
           result = ecma_raise_reference_error (ECMA_ERR_UNDEFINED_REFERENCE);
           goto error;
         }
-        case VM_OC_EVAL:
+        case CBC_EVAL:
         {
           JERRY_CONTEXT (status_flags) |= ECMA_STATUS_DIRECT_EVAL;
           JERRY_ASSERT ((*byte_code_p >= CBC_CALL && *byte_code_p <= CBC_CALL2_PROP_BLOCK)
@@ -3213,21 +3905,30 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
                             && byte_code_p[1] <= CBC_EXT_SPREAD_CALL_PROP_BLOCK));
           continue;
         }
-        case VM_OC_CALL:
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL):
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL_PROP):
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL0):
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL0_PROP):
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL1):
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL1_PROP):
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL2):
+        case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL2_PROP):
         {
           frame_ctx_p->call_operation = VM_EXEC_CALL;
           frame_ctx_p->byte_code_p = byte_code_start_p;
           frame_ctx_p->stack_top_p = stack_top_p;
           return ECMA_VALUE_UNDEFINED;
         }
-        case VM_OC_NEW:
+        case CBC_NEW:
+        case CBC_NEW0:
+        case CBC_NEW1:
         {
           frame_ctx_p->call_operation = VM_EXEC_CONSTRUCT;
           frame_ctx_p->byte_code_p = byte_code_start_p;
           frame_ctx_p->stack_top_p = stack_top_p;
           return ECMA_VALUE_UNDEFINED;
         }
-        case VM_OC_ERROR:
+        case VM_EXT_OPCODE (CBC_EXT_ERROR):
         {
           JERRY_ASSERT (frame_ctx_p->byte_code_p[1] == CBC_EXT_ERROR);
 #if JERRY_DEBUGGER
@@ -3237,7 +3938,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           result = ECMA_VALUE_ERROR;
           goto error;
         }
-        case VM_OC_RESOLVE_BASE_FOR_CALL:
+        case VM_EXT_OPCODE (CBC_EXT_RESOLVE_BASE):
         {
           ecma_value_t this_value = stack_top_p[-3];
 
@@ -3255,8 +3956,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
           continue;
         }
-        case VM_OC_PROP_DELETE:
+        case CBC_DELETE_PUSH_RESULT:
         {
+          VM_POP_STACK_STACK (right_value, left_value);
+
           result = vm_op_delete_prop (left_value, right_value, is_strict);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -3267,12 +3970,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           JERRY_ASSERT (ecma_is_value_boolean (result));
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_DELETE:
+        case CBC_DELETE_IDENT_PUSH_RESULT:
         {
           uint16_t literal_index;
-
           READ_LITERAL_INDEX (literal_index);
 
           if (literal_index < register_end)
@@ -3293,13 +3998,18 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = result;
           continue;
         }
-        case VM_OC_JUMP:
+        case VM_OPCODE_BRANCH_CASE (CBC_JUMP_FORWARD):
+        case VM_OPCODE_BRANCH_CASE (CBC_JUMP_BACKWARD):
         {
+          VM_DECODE_FORWARD_BRANCH (CBC_JUMP_FORWARD);
+          VM_DECODE_BACKWARD_BRANCH (CBC_JUMP_BACKWARD);
           byte_code_p = byte_code_start_p + branch_offset;
           continue;
         }
-        case VM_OC_BRANCH_IF_STRICT_EQUAL:
+        case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_STRICT_EQUAL):
         {
+          VM_DECODE_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL);
+
           ecma_value_t value = *(--stack_top_p);
 
           JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end);
@@ -3312,37 +4022,68 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           ecma_free_value (value);
           continue;
         }
-        case VM_OC_BRANCH_IF_TRUE:
-        case VM_OC_BRANCH_IF_FALSE:
-        case VM_OC_BRANCH_IF_LOGICAL_TRUE:
-        case VM_OC_BRANCH_IF_LOGICAL_FALSE:
+        case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_TRUE_FORWARD):
+        case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_TRUE_BACKWARD):
         {
-          uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_BRANCH_IF_TRUE;
-          ecma_value_t value = *(--stack_top_p);
+          VM_DECODE_FORWARD_BRANCH (CBC_BRANCH_IF_TRUE_FORWARD);
+          VM_DECODE_BACKWARD_BRANCH (CBC_BRANCH_IF_TRUE_BACKWARD);
 
-          bool boolean_value = ecma_op_to_boolean (value);
+          ecma_value_t value = *(--stack_top_p);
 
-          if (opcode_flags & VM_OC_BRANCH_IF_FALSE_FLAG)
+          if (ecma_op_to_boolean (value))
           {
-            boolean_value = !boolean_value;
+            byte_code_p = byte_code_start_p + branch_offset;
           }
 
-          if (boolean_value)
+          ecma_fast_free_value (value);
+          continue;
+        }
+        case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_FALSE_FORWARD):
+        case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_FALSE_BACKWARD):
+        {
+          VM_DECODE_FORWARD_BRANCH (CBC_BRANCH_IF_FALSE_FORWARD);
+          VM_DECODE_BACKWARD_BRANCH (CBC_BRANCH_IF_FALSE_BACKWARD);
+
+          ecma_value_t value = *(--stack_top_p);
+
+          if (!ecma_op_to_boolean (value))
           {
             byte_code_p = byte_code_start_p + branch_offset;
-            if (opcode_flags & VM_OC_LOGICAL_BRANCH_FLAG)
-            {
-              /* "Push" the value back to the stack. */
-              ++stack_top_p;
-              continue;
-            }
           }
 
           ecma_fast_free_value (value);
           continue;
         }
+        case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_LOGICAL_TRUE):
+        {
+          VM_DECODE_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE);
+
+          if (ecma_op_to_boolean (stack_top_p[-1]))
+          {
+            byte_code_p = byte_code_start_p + branch_offset;
+          }
+          else
+          {
+            ecma_fast_free_value (*(--stack_top_p));
+          }
+          continue;
+        }
+        case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_LOGICAL_FALSE):
+        {
+          VM_DECODE_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE);
+
+          if (ecma_op_to_boolean (stack_top_p[-1]))
+          {
+            ecma_fast_free_value (*(--stack_top_p));
+          }
+          else
+          {
+            byte_code_p = byte_code_start_p + branch_offset;
+          }
+          continue;
+        }
 #if JERRY_ESNEXT
-        case VM_OC_POP_REFERENCE:
+        case VM_EXT_OPCODE (CBC_EXT_POP_REFERENCE):
         {
           ecma_free_value (stack_top_p[-2]);
           ecma_free_value (stack_top_p[-3]);
@@ -3350,8 +4091,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           stack_top_p -= 2;
           continue;
         }
-        case VM_OC_BRANCH_IF_NULLISH:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_BRANCH_IF_NULLISH):
         {
+          VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_BRANCH_IF_NULLISH);
+
           left_value = stack_top_p[-1];
 
           if (!ecma_is_value_null (left_value) && !ecma_is_value_undefined (left_value))
@@ -3363,10 +4106,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           continue;
         }
 #endif /* JERRY_ESNEXT */
-        case VM_OC_PLUS:
-        case VM_OC_MINUS:
+        case VM_OPCODE_ONE_LITERAL (CBC_PLUS_LITERAL):
+        case VM_OPCODE_ONE_LITERAL (CBC_NEGATE_LITERAL):
         {
-          result = opfunc_unary_operation (left_value, VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_PLUS);
+          VM_DECODE_LITERAL_2 (CBC_PLUS_LITERAL, CBC_NEGATE_LITERAL)
+          VM_DECODE_STACK_2 (CBC_PLUS, CBC_NEGATE);
+
+          result = opfunc_unary_operation (left_value, *byte_code_start_p < CBC_NEGATE);
 
           if (ECMA_IS_VALUE_ERROR (result))
           {
@@ -3374,23 +4120,35 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_left_value;
+
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_NOT:
+        case VM_OPCODE_ONE_LITERAL (CBC_LOGICAL_NOT_LITERAL):
         {
+          VM_DECODE_LITERAL (CBC_LOGICAL_NOT_LITERAL);
+          VM_DECODE_STACK (CBC_LOGICAL_NOT);
+
           *stack_top_p++ = ecma_make_boolean_value (!ecma_op_to_boolean (left_value));
           JERRY_ASSERT (ecma_is_value_boolean (stack_top_p[-1]));
-          goto free_left_value;
+
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_BIT_NOT:
+        case VM_OPCODE_ONE_LITERAL (CBC_BIT_NOT_LITERAL):
         {
+          VM_DECODE_LITERAL (CBC_BIT_NOT_LITERAL);
+          VM_DECODE_STACK (CBC_BIT_NOT);
+
           JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1),
                                direct_type_mask_must_fill_all_bits_before_the_value_starts);
 
           if (ecma_is_value_integer_number (left_value))
           {
             *stack_top_p++ = (~ECMA_DIRECT_TYPE_MASK) ^ left_value;
-            goto free_left_value;
+
+            ecma_fast_free_value (left_value);
+            continue;
           }
 
           result = do_number_bitwise_not (left_value);
@@ -3401,17 +4159,23 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_left_value;
+
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_VOID:
+        case VM_OPCODE_ONE_LITERAL (CBC_VOID_LITERAL):
         {
+          VM_DECODE_LITERAL (CBC_VOID_LITERAL);
+          VM_DECODE_STACK (CBC_VOID);
+
           *stack_top_p++ = ECMA_VALUE_UNDEFINED;
-          goto free_left_value;
+
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_TYPEOF_IDENT:
+        case CBC_TYPEOF_IDENT:
         {
           uint16_t literal_index;
-
           READ_LITERAL_INDEX (literal_index);
 
           JERRY_ASSERT (literal_index < ident_end);
@@ -3440,10 +4204,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
             left_value = result;
           }
-          /* FALLTHRU */
-        }
-        case VM_OC_TYPEOF:
-        {
+
+          VM_DECODE_STACK (CBC_TYPEOF);
+
           result = opfunc_typeof (left_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -3452,10 +4215,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_left_value;
+
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_ADD:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_ADD):
         {
+          VM_DECODE_ARITHMETIC (CBC_ADD);
+
           if (ecma_are_values_integer_numbers (left_value, right_value))
           {
             ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value);
@@ -3491,15 +4258,18 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_SUB:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_SUBTRACT):
         {
+          VM_DECODE_ARITHMETIC (CBC_SUBTRACT);
+
           JERRY_STATIC_ASSERT (ECMA_INTEGER_NUMBER_MAX * 2 <= INT32_MAX && ECMA_INTEGER_NUMBER_MIN * 2 >= INT32_MIN,
                                doubled_ecma_numbers_must_fit_into_int32_range);
 
-          JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value));
-
           if (ecma_are_values_integer_numbers (left_value, right_value))
           {
             ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value);
@@ -3535,11 +4305,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_MUL:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_MULTIPLY):
         {
-          JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value));
+          VM_DECODE_ARITHMETIC (CBC_MULTIPLY);
 
           JERRY_STATIC_ASSERT (ECMA_INTEGER_MULTIPLY_MAX * ECMA_INTEGER_MULTIPLY_MAX <= ECMA_INTEGER_NUMBER_MAX
                                  && -(ECMA_INTEGER_MULTIPLY_MAX * ECMA_INTEGER_MULTIPLY_MAX) >= ECMA_INTEGER_NUMBER_MIN,
@@ -3590,11 +4363,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_DIV:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_DIVIDE):
         {
-          JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value));
+          VM_DECODE_ARITHMETIC (CBC_DIVIDE);
 
           result = do_number_arithmetic (NUMBER_ARITHMETIC_DIVISION, left_value, right_value);
 
@@ -3604,11 +4380,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_MOD:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_MODULO):
         {
-          JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value));
+          VM_DECODE_ARITHMETIC (CBC_MODULO);
 
           if (ecma_are_values_integer_numbers (left_value, right_value))
           {
@@ -3635,11 +4414,16 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
 #if JERRY_ESNEXT
-        case VM_OC_EXP:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_EXPONENTIATION):
         {
+          VM_DECODE_ARITHMETIC (CBC_EXPONENTIATION);
+
           result = do_number_arithmetic (NUMBER_ARITHMETIC_EXPONENTIATION, left_value, right_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -3648,11 +4432,16 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
 #endif /* JERRY_ESNEXT */
-        case VM_OC_EQUAL:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_EQUAL):
         {
+          VM_DECODE_ARITHMETIC (CBC_EQUAL);
+
           result = opfunc_equality (left_value, right_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -3661,10 +4450,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_NOT_EQUAL:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_NOT_EQUAL):
         {
+          VM_DECODE_ARITHMETIC (CBC_NOT_EQUAL);
+
           result = opfunc_equality (left_value, right_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -3673,28 +4467,37 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = ecma_invert_boolean_value (result);
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_STRICT_EQUAL:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_STRICT_EQUAL):
         {
-          bool is_equal = ecma_op_strict_equality_compare (left_value, right_value);
+          VM_DECODE_ARITHMETIC (CBC_STRICT_EQUAL);
 
-          result = ecma_make_boolean_value (is_equal);
+          bool is_equal = ecma_op_strict_equality_compare (left_value, right_value);
+          *stack_top_p++ = ecma_make_boolean_value (is_equal);
 
-          *stack_top_p++ = result;
-          goto free_both_values;
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_STRICT_NOT_EQUAL:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_STRICT_NOT_EQUAL):
         {
-          bool is_equal = ecma_op_strict_equality_compare (left_value, right_value);
+          VM_DECODE_ARITHMETIC (CBC_STRICT_NOT_EQUAL);
 
-          result = ecma_make_boolean_value (!is_equal);
+          bool is_equal = ecma_op_strict_equality_compare (left_value, right_value);
+          *stack_top_p++ = ecma_make_boolean_value (!is_equal);
 
-          *stack_top_p++ = result;
-          goto free_both_values;
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_BIT_OR:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_BIT_OR):
         {
+          VM_DECODE_ARITHMETIC (CBC_BIT_OR);
+
           JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1),
                                direct_type_mask_must_fill_all_bits_before_the_value_starts);
 
@@ -3712,10 +4515,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_BIT_XOR:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_BIT_XOR):
         {
+          VM_DECODE_ARITHMETIC (CBC_BIT_XOR);
+
           JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1),
                                direct_type_mask_must_fill_all_bits_before_the_value_starts);
 
@@ -3733,10 +4541,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_BIT_AND:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_BIT_AND):
         {
+          VM_DECODE_ARITHMETIC (CBC_BIT_AND);
+
           JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1),
                                direct_type_mask_must_fill_all_bits_before_the_value_starts);
 
@@ -3754,10 +4567,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_LEFT_SHIFT:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_LEFT_SHIFT):
         {
+          VM_DECODE_ARITHMETIC (CBC_LEFT_SHIFT);
+
           JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1),
                                direct_type_mask_must_fill_all_bits_before_the_value_starts);
 
@@ -3778,10 +4596,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_RIGHT_SHIFT:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_RIGHT_SHIFT):
         {
+          VM_DECODE_ARITHMETIC (CBC_RIGHT_SHIFT);
+
           JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1),
                                direct_type_mask_must_fill_all_bits_before_the_value_starts);
 
@@ -3801,10 +4624,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_UNS_RIGHT_SHIFT:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_UNS_RIGHT_SHIFT):
         {
+          VM_DECODE_ARITHMETIC (CBC_UNS_RIGHT_SHIFT);
+
           JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1),
                                direct_type_mask_must_fill_all_bits_before_the_value_starts);
 
@@ -3824,10 +4652,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_LESS:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_LESS):
         {
+          VM_DECODE_ARITHMETIC (CBC_LESS);
+
           if (ecma_are_values_integer_numbers (left_value, right_value))
           {
             bool is_less = (ecma_integer_value_t) left_value < (ecma_integer_value_t) right_value;
@@ -3837,7 +4670,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             if (*byte_code_p <= CBC_BRANCH_IF_TRUE_BACKWARD_3 && *byte_code_p >= CBC_BRANCH_IF_TRUE_BACKWARD)
             {
               byte_code_start_p = byte_code_p++;
-              branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (*byte_code_start_p);
+              uint8_t branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (*byte_code_start_p);
               JERRY_ASSERT (branch_offset_length >= 1 && branch_offset_length <= 3);
 
               if (is_less)
@@ -3876,7 +4709,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             ecma_number_t right_number = ecma_get_number_from_value (right_value);
 
             *stack_top_p++ = ecma_make_boolean_value (left_number < right_number);
-            goto free_both_values;
+
+            ecma_fast_free_value (right_value);
+            ecma_fast_free_value (left_value);
+            continue;
           }
 
           result = opfunc_relation (left_value, right_value, true, false);
@@ -3887,10 +4723,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_GREATER:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_GREATER):
         {
+          VM_DECODE_ARITHMETIC (CBC_GREATER);
+
           if (ecma_are_values_integer_numbers (left_value, right_value))
           {
             ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value;
@@ -3906,7 +4747,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             ecma_number_t right_number = ecma_get_number_from_value (right_value);
 
             *stack_top_p++ = ecma_make_boolean_value (left_number > right_number);
-            goto free_both_values;
+
+            ecma_fast_free_value (right_value);
+            ecma_fast_free_value (left_value);
+            continue;
           }
 
           result = opfunc_relation (left_value, right_value, false, false);
@@ -3917,10 +4761,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_LESS_EQUAL:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_LESS_EQUAL):
         {
+          VM_DECODE_ARITHMETIC (CBC_LESS_EQUAL);
+
           if (ecma_are_values_integer_numbers (left_value, right_value))
           {
             ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value;
@@ -3936,7 +4785,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             ecma_number_t right_number = ecma_get_number_from_value (right_value);
 
             *stack_top_p++ = ecma_make_boolean_value (left_number <= right_number);
-            goto free_both_values;
+
+            ecma_fast_free_value (right_value);
+            ecma_fast_free_value (left_value);
+            continue;
           }
 
           result = opfunc_relation (left_value, right_value, false, true);
@@ -3947,10 +4799,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_GREATER_EQUAL:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_GREATER_EQUAL):
         {
+          VM_DECODE_ARITHMETIC (CBC_GREATER_EQUAL);
+
           if (ecma_are_values_integer_numbers (left_value, right_value))
           {
             ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value;
@@ -3966,7 +4823,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
             ecma_number_t right_number = ecma_get_number_from_value (right_value);
 
             *stack_top_p++ = ecma_make_boolean_value (left_number >= right_number);
-            goto free_both_values;
+
+            ecma_fast_free_value (right_value);
+            ecma_fast_free_value (left_value);
+            continue;
           }
 
           result = opfunc_relation (left_value, right_value, true, true);
@@ -3977,10 +4837,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_IN:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_IN):
         {
+          VM_DECODE_ARITHMETIC (CBC_IN);
+
           result = opfunc_in (left_value, right_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -3989,10 +4854,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_INSTANCEOF:
+        case VM_OPCODE_ARITHMETIC_CASE (CBC_INSTANCEOF):
         {
+          VM_DECODE_ARITHMETIC (CBC_INSTANCEOF);
+
           result = opfunc_instanceof (left_value, right_value);
 
           if (ECMA_IS_VALUE_ERROR (result))
@@ -4001,17 +4871,23 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
 
           *stack_top_p++ = result;
-          goto free_both_values;
+
+          ecma_fast_free_value (right_value);
+          ecma_fast_free_value (left_value);
+          continue;
         }
-        case VM_OC_BLOCK_CREATE_CONTEXT:
+        case VM_OPCODE_BRANCH_CASE (CBC_BLOCK_CREATE_CONTEXT):
+        case VM_EXT_OPCODE (CBC_EXT_TRY_CREATE_ENV):
         {
+          VM_DECODE_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT);
+
 #if JERRY_ESNEXT
           ecma_value_t *stack_context_top_p;
           stack_context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth;
 
           JERRY_ASSERT (stack_context_top_p == stack_top_p || stack_context_top_p == stack_top_p - 1);
 
-          if (byte_code_start_p[0] != CBC_EXT_OPCODE)
+          if (opcode != VM_EXT_OPCODE (CBC_EXT_TRY_CREATE_ENV))
           {
             branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p);
 
@@ -4028,8 +4904,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           else
           {
-            JERRY_ASSERT (byte_code_start_p[1] == CBC_EXT_TRY_CREATE_ENV);
-
             JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_TRY
                           || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_CATCH
                           || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP
@@ -4052,8 +4926,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 
           continue;
         }
-        case VM_OC_WITH:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_WITH_CREATE_CONTEXT):
         {
+          VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_WITH_CREATE_CONTEXT);
+
           ecma_value_t value = *(--stack_top_p);
           ecma_object_t *object_p;
           ecma_object_t *with_env_p;
@@ -4084,8 +4960,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           frame_ctx_p->lex_env_p = with_env_p;
           continue;
         }
-        case VM_OC_FOR_IN_INIT:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_FOR_IN_INIT):
         {
+          VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_FOR_IN_INIT);
+
           ecma_value_t value = *(--stack_top_p);
 
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
@@ -4127,7 +5005,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
 #endif /* JERRY_ESNEXT */
           continue;
         }
-        case VM_OC_FOR_IN_GET_NEXT:
+        case VM_EXT_OPCODE (CBC_EXT_FOR_IN_GET_NEXT):
         {
           ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth;
 
@@ -4143,8 +5021,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           context_top_p[-3]++;
           continue;
         }
-        case VM_OC_FOR_IN_HAS_NEXT:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT):
         {
+          VM_DECODE_EXT_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT);
+
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
 
           ecma_collection_t *collection_p;
@@ -4192,8 +5072,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           continue;
         }
 #if JERRY_ESNEXT
-        case VM_OC_FOR_OF_INIT:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_FOR_OF_INIT):
         {
+          VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_FOR_OF_INIT);
+
           ecma_value_t value = *(--stack_top_p);
 
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
@@ -4253,7 +5135,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           continue;
         }
-        case VM_OC_FOR_OF_GET_NEXT:
+        case VM_EXT_OPCODE (CBC_EXT_FOR_OF_GET_NEXT):
         {
           ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth;
           JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_OF
@@ -4264,8 +5146,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           context_top_p[-2] = ECMA_VALUE_UNDEFINED;
           continue;
         }
-        case VM_OC_FOR_OF_HAS_NEXT:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT):
         {
+          VM_DECODE_EXT_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT);
+
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
           JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FOR_OF);
           JERRY_ASSERT (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR);
@@ -4303,8 +5187,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           byte_code_p = byte_code_start_p + branch_offset;
           continue;
         }
-        case VM_OC_FOR_AWAIT_OF_INIT:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_FOR_AWAIT_OF_INIT):
         {
+          VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_FOR_AWAIT_OF_INIT);
+
           ecma_value_t value = *(--stack_top_p);
 
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
@@ -4374,8 +5260,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           return result;
         }
-        case VM_OC_FOR_AWAIT_OF_HAS_NEXT:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT):
         {
+          VM_DECODE_EXT_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT);
+
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
           JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FOR_AWAIT_OF);
           JERRY_ASSERT (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR);
@@ -4406,8 +5294,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           return ECMA_VALUE_UNDEFINED;
         }
 #endif /* JERRY_ESNEXT */
-        case VM_OC_TRY:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_TRY_CREATE_CONTEXT):
         {
+          VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT);
+
           /* Try opcode simply creates the try context. */
           branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p);
 
@@ -4419,8 +5309,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_TRY, branch_offset);
           continue;
         }
-        case VM_OC_CATCH:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_CATCH):
         {
+          VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_CATCH);
+
           /* Catches are ignored and turned to jumps. */
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
           JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY);
@@ -4428,8 +5320,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           byte_code_p = byte_code_start_p + branch_offset;
           continue;
         }
-        case VM_OC_FINALLY:
+        case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_FINALLY):
         {
+          VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_FINALLY);
+
           branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p);
 
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
@@ -4452,7 +5346,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           stack_top_p[-2] = (ecma_value_t) branch_offset;
           continue;
         }
-        case VM_OC_CONTEXT_END:
+        case CBC_CONTEXT_END:
         {
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
           JERRY_ASSERT (!(stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR));
@@ -4541,8 +5435,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
           continue;
         }
-        case VM_OC_JUMP_AND_EXIT_CONTEXT:
+        case VM_OPCODE_BRANCH_CASE (CBC_JUMP_FORWARD_EXIT_CONTEXT):
         {
+          VM_DECODE_FORWARD_BRANCH (CBC_JUMP_FORWARD_EXIT_CONTEXT);
+
           JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
           JERRY_ASSERT (!jcontext_has_pending_exception ());
 
@@ -4586,7 +5482,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           continue;
         }
 #if JERRY_MODULE_SYSTEM
-        case VM_OC_MODULE_IMPORT:
+        case VM_EXT_OPCODE (CBC_EXT_MODULE_IMPORT):
         {
           left_value = *(--stack_top_p);
 
@@ -4618,7 +5514,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           *stack_top_p++ = result;
           continue;
         }
-        case VM_OC_MODULE_IMPORT_META:
+        case VM_EXT_OPCODE (CBC_EXT_MODULE_IMPORT_META):
         {
           ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_header_p)->script_value;
           cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value);
@@ -4654,7 +5550,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
         }
 #endif /* JERRY_MODULE_SYSTEM */
 #if JERRY_DEBUGGER
-        case VM_OC_BREAKPOINT_ENABLED:
+        case CBC_BREAKPOINT_ENABLED:
         {
           if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE)
           {
@@ -4675,7 +5571,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           }
           continue;
         }
-        case VM_OC_BREAKPOINT_DISABLED:
+        case CBC_BREAKPOINT_DISABLED:
         {
           if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE)
           {
@@ -4728,21 +5624,19 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           continue;
         }
 #endif /* JERRY_DEBUGGER */
-        case VM_OC_NONE:
         default:
         {
-          JERRY_ASSERT (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_NONE);
-
-          jerry_fatal (JERRY_FATAL_DISABLED_BYTE_CODE);
+          JERRY_UNREACHABLE ();
         }
       }
 
-      JERRY_ASSERT (VM_OC_HAS_PUT_RESULT (opcode_data));
+      JERRY_ASSERT (put_result_flags != VM_PUT_RESULT_NONE);
 
-      if (opcode_data & VM_OC_PUT_IDENT)
+      if (put_result_flags & VM_PUT_RESULT_IDENT)
       {
         uint16_t literal_index;
 
+dispatch_put_ident:
         READ_LITERAL_INDEX (literal_index);
 
         if (literal_index < register_end)
@@ -4750,10 +5644,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index));
           VM_GET_REGISTER (frame_ctx_p, literal_index) = result;
 
-          if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))
+          if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK)))
           {
-            result = ecma_fast_copy_value (result);
+            continue;
           }
+          result = ecma_fast_copy_value (result);
         }
         else
         {
@@ -4766,19 +5661,23 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           {
             ecma_free_value (result);
             result = put_value_result;
+            left_value = ECMA_VALUE_UNDEFINED;
             goto error;
           }
 
-          if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
+          if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK)))
           {
             ecma_fast_free_value (result);
+            continue;
           }
         }
       }
-      else if (opcode_data & VM_OC_PUT_REFERENCE)
+      else if (put_result_flags & VM_PUT_RESULT_REFERENCE)
       {
-        ecma_value_t property = *(--stack_top_p);
-        ecma_value_t base = *(--stack_top_p);
+        ecma_value_t property, base;
+dispatch_put_reference:
+        property = *(--stack_top_p);
+        base = *(--stack_top_p);
 
         if (base == ECMA_VALUE_REGISTER_REF)
         {
@@ -4786,9 +5685,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, property));
           VM_GET_REGISTER (frame_ctx_p, property) = result;
 
-          if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
+          if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK)))
           {
-            goto free_both_values;
+            continue;
           }
           result = ecma_fast_copy_value (result);
         }
@@ -4800,31 +5699,33 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
           {
             ecma_free_value (result);
             result = set_value_result;
+            left_value = ECMA_VALUE_UNDEFINED;
             goto error;
           }
 
-          if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
+          if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK)))
           {
             ecma_fast_free_value (result);
-            goto free_both_values;
+            continue;
           }
         }
       }
+      else if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK)))
+      {
+        ecma_fast_free_value (result);
+        continue;
+      }
 
-      if (opcode_data & VM_OC_PUT_STACK)
+      if (put_result_flags & VM_PUT_RESULT_STACK)
       {
         *stack_top_p++ = result;
       }
-      else if (opcode_data & VM_OC_PUT_BLOCK)
+      else
       {
+        JERRY_ASSERT (put_result_flags & VM_PUT_RESULT_BLOCK);
         ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0));
         VM_GET_REGISTERS (frame_ctx_p)[0] = result;
       }
-
-free_both_values:
-      ecma_fast_free_value (right_value);
-free_left_value:
-      ecma_fast_free_value (left_value);
     }
 
 error:
diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h
index 3cb1bdb931..f0df0253fa 100644
--- a/jerry-core/vm/vm.h
+++ b/jerry-core/vm/vm.h
@@ -29,459 +29,21 @@
  * @{
  */
 
-/**
- * Each CBC opcode is transformed to three vm opcodes:
- *
- *  - first opcode is a "get arguments" opcode which specifies
- *    the type (register, literal, stack, etc.) and number
- *    (from 0 to 2) of input arguments
- *  - second opcode is a "group" opcode which specifies
- *    the actual operation (add, increment, call, etc.)
- *  - third opcode is a "put result" opcode which specifies
- *    the destination where the result is stored (register,
- *    stack, etc.)
- */
-
-/**
- * If VM_OC_GET_ARGS_INDEX(opcode) == VM_OC_GET_BRANCH,
- * this flag signals that the branch is a backward branch.
- */
-#define VM_OC_BACKWARD_BRANCH (1 << 15)
-
-/**
- * Position of "get arguments" opcode.
- */
-#define VM_OC_GET_ARGS_SHIFT 8
-
-/**
- * Mask of "get arguments" opcode.
- */
-#define VM_OC_GET_ARGS_MASK 0x7
-
-/**
- * Generate the binary representation of a "get arguments" opcode.
- */
-#define VM_OC_GET_ARGS_CREATE_INDEX(V) (((V) &VM_OC_GET_ARGS_MASK) << VM_OC_GET_ARGS_SHIFT)
-
-/**
- * Extract the "get arguments" opcode.
- */
-#define VM_OC_GET_ARGS_INDEX(O) ((O) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT))
-
-/**
- * Checks whether the result is stored somewhere.
- */
-#define VM_OC_HAS_GET_ARGS(V) ((V) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT))
-
-/**
- * Argument getters that are part of the opcodes.
- */
-typedef enum
-{
-  VM_OC_GET_NONE = VM_OC_GET_ARGS_CREATE_INDEX (0), /**< do nothing */
-  VM_OC_GET_BRANCH = VM_OC_GET_ARGS_CREATE_INDEX (1), /**< branch argument */
-  VM_OC_GET_STACK = VM_OC_GET_ARGS_CREATE_INDEX (2), /**< pop one element from the stack */
-  VM_OC_GET_STACK_STACK = VM_OC_GET_ARGS_CREATE_INDEX (3), /**< pop two elements from the stack */
-
-  VM_OC_GET_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (4), /**< resolve literal */
-  VM_OC_GET_LITERAL_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (5), /**< resolve two literals */
-  VM_OC_GET_STACK_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (6), /**< pop one element from the stack
-                                                              *   and resolve a literal */
-  VM_OC_GET_THIS_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (7), /**< get this and resolve a literal */
-} vm_oc_get_types;
-
-/**
- * Mask of "group" opcode.
- */
-#define VM_OC_GROUP_MASK 0xff
-
-/**
- * Extract the "group" opcode.
- */
-#define VM_OC_GROUP_GET_INDEX(O) ((O) &VM_OC_GROUP_MASK)
-
-/**
- * Opcodes.
- */
-typedef enum
-{
-  VM_OC_POP, /**< pop from stack */
-  VM_OC_POP_BLOCK, /**< pop block */
-  VM_OC_PUSH, /**< push one literal  */
-  VM_OC_PUSH_TWO, /**< push two literals */
-  VM_OC_PUSH_THREE, /**< push three literals */
-  VM_OC_PUSH_UNDEFINED, /**< push undefined value */
-  VM_OC_PUSH_TRUE, /**< push true value */
-  VM_OC_PUSH_FALSE, /**< push false value */
-  VM_OC_PUSH_NULL, /**< push null value */
-  VM_OC_PUSH_THIS, /**< push this */
-  VM_OC_PUSH_0, /**< push number zero */
-  VM_OC_PUSH_POS_BYTE, /**< push number between 1 and 256 */
-  VM_OC_PUSH_NEG_BYTE, /**< push number between -1 and -256 */
-  VM_OC_PUSH_LIT_0, /**< push literal and number zero */
-  VM_OC_PUSH_LIT_POS_BYTE, /**< push literal and number between 1 and 256 */
-  VM_OC_PUSH_LIT_NEG_BYTE, /**< push literal and number between -1 and -256 */
-  VM_OC_PUSH_OBJECT, /**< push object */
-  VM_OC_PUSH_NAMED_FUNC_EXPR, /**< push named function expression */
-  VM_OC_SET_PROPERTY, /**< set property */
-
-  VM_OC_SET_GETTER, /**< set getter */
-  VM_OC_SET_SETTER, /**< set setter */
-  VM_OC_PUSH_ARRAY, /**< push array */
-  VM_OC_PUSH_ELISON, /**< push elison */
-  VM_OC_APPEND_ARRAY, /**< append array */
-  VM_OC_IDENT_REFERENCE, /**< ident reference */
-  VM_OC_PROP_REFERENCE, /**< prop reference */
-  VM_OC_PROP_GET, /**< prop get */
-
-  /* These eight opcodes must be in this order. */
-  VM_OC_PROP_PRE_INCR, /**< prefix increment of a property */
-  VM_OC_PROP_PRE_DECR, /**< prop prefix decrement of a property */
-  VM_OC_PROP_POST_INCR, /**< prop postfix increment of a property */
-  VM_OC_PROP_POST_DECR, /**< prop postfix decrement of a property */
-  VM_OC_PRE_INCR, /**< prefix increment  */
-  VM_OC_PRE_DECR, /**< prefix decrement */
-  VM_OC_POST_INCR, /**< postfix increment */
-  VM_OC_POST_DECR, /**< postfix decrement */
-
-  VM_OC_PROP_DELETE, /**< delete property */
-  VM_OC_DELETE, /**< delete */
-
-  VM_OC_MOV_IDENT, /**< move identifier register reference */
-  VM_OC_ASSIGN, /**< assign */
-  VM_OC_ASSIGN_PROP, /**< assign property */
-  VM_OC_ASSIGN_PROP_THIS, /**< assign prop this */
-
-  VM_OC_RETURN, /**< return */
-  VM_OC_RETURN_FUNCTION_END, /**< return at the end of a function/script */
-  VM_OC_THROW, /**< throw */
-  VM_OC_THROW_REFERENCE_ERROR, /**< throw reference error */
-
-  VM_OC_EVAL, /**< eval */
-  VM_OC_CALL, /**< call */
-  VM_OC_NEW, /**< new */
-  VM_OC_RESOLVE_BASE_FOR_CALL, /**< resolve base value before call */
-  VM_OC_ERROR, /**< error while the vm_loop is suspended */
-
-  VM_OC_JUMP, /**< jump */
-#if JERRY_ESNEXT
-  VM_OC_BRANCH_IF_NULLISH, /** branch if undefined or null */
-  VM_OC_POP_REFERENCE, /** prop identifier or property reference from the stack */
-#endif /* JERRY_ESNEXT */
-  VM_OC_BRANCH_IF_STRICT_EQUAL, /**< branch if strict equal */
-
-  /* These four opcodes must be in this order. */
-  VM_OC_BRANCH_IF_TRUE, /**< branch if true */
-  VM_OC_BRANCH_IF_FALSE, /**< branch if false */
-  VM_OC_BRANCH_IF_LOGICAL_TRUE, /**< branch if logical true */
-  VM_OC_BRANCH_IF_LOGICAL_FALSE, /**< branch if logical false */
-
-  VM_OC_PLUS, /**< unary plus */
-  VM_OC_MINUS, /**< unary minus */
-  VM_OC_NOT, /**< not */
-  VM_OC_BIT_NOT, /**< bitwise not */
-  VM_OC_VOID, /**< void */
-  VM_OC_TYPEOF_IDENT, /**< typeof identifier */
-  VM_OC_TYPEOF, /**< typeof */
-
-  VM_OC_ADD, /**< binary add */
-  VM_OC_SUB, /**< binary sub */
-  VM_OC_MUL, /**< mul */
-  VM_OC_DIV, /**< div */
-  VM_OC_MOD, /**< mod */
-#if JERRY_ESNEXT
-  VM_OC_EXP, /**< exponentiation */
-#endif /* JERRY_ESNEXT */
-
-  VM_OC_EQUAL, /**< equal */
-  VM_OC_NOT_EQUAL, /**< not equal */
-  VM_OC_STRICT_EQUAL, /**< strict equal */
-  VM_OC_STRICT_NOT_EQUAL, /**< strict not equal */
-  VM_OC_LESS, /**< less */
-  VM_OC_GREATER, /**< greater */
-  VM_OC_LESS_EQUAL, /**< less equal */
-  VM_OC_GREATER_EQUAL, /**< greater equal */
-  VM_OC_IN, /**< in */
-  VM_OC_INSTANCEOF, /**< instanceof */
-
-  VM_OC_BIT_OR, /**< bitwise or */
-  VM_OC_BIT_XOR, /**< bitwise xor */
-  VM_OC_BIT_AND, /**< bitwise and */
-  VM_OC_LEFT_SHIFT, /**< left shift */
-  VM_OC_RIGHT_SHIFT, /**< right shift */
-  VM_OC_UNS_RIGHT_SHIFT, /**< unsigned right shift */
-
-  VM_OC_BLOCK_CREATE_CONTEXT, /**< create lexical environment for blocks enclosed in braces */
-  VM_OC_WITH, /**< with */
-  VM_OC_FOR_IN_INIT, /**< for-in init context */
-  VM_OC_FOR_IN_GET_NEXT, /**< get next */
-  VM_OC_FOR_IN_HAS_NEXT, /**< has next */
-
-  VM_OC_TRY, /**< try */
-  VM_OC_CATCH, /**< catch */
-  VM_OC_FINALLY, /**< finally */
-  VM_OC_CONTEXT_END, /**< context end */
-  VM_OC_JUMP_AND_EXIT_CONTEXT, /**< jump and exit context */
-
-  VM_OC_CREATE_BINDING, /**< create variables */
-  VM_OC_CREATE_ARGUMENTS, /**< create arguments object */
-  VM_OC_SET_BYTECODE_PTR, /**< setting bytecode pointer */
-  VM_OC_VAR_EVAL, /**< variable and function evaluation */
-#if JERRY_ESNEXT
-  VM_OC_EXT_VAR_EVAL, /**< variable and function evaluation for
-                       *   functions with separate argument context */
-#endif /* JERRY_ESNEXT */
-  VM_OC_INIT_ARG_OR_FUNC, /**< create and init a function or argument binding */
-
-#if JERRY_DEBUGGER
-  VM_OC_BREAKPOINT_ENABLED, /**< enabled breakpoint for debugger */
-  VM_OC_BREAKPOINT_DISABLED, /**< disabled breakpoint for debugger */
-#endif /* JERRY_DEBUGGER */
-#if JERRY_ESNEXT
-  VM_OC_CLASS_CALL_STATIC_BLOCK, /**< call the class static block */
-  VM_OC_DEFINE_FIELD, /**< define class field  */
-  VM_OC_PRIVATE_PROP_REFERENCE, /**< reference to class private method */
-  VM_OC_ASSIGN_PRIVATE, /**< assign to private field  */
-  VM_OC_PRIVATE_FIELD_ADD, /**< add private field */
-  VM_OC_PRIVATE_PROP_GET, /**< get private field */
-  VM_OC_PRIVATE_IN, /**< 'in' opcode handler for private identifiers */
-  VM_OC_COLLECT_PRIVATE_PROPERTY, /**< collect private properties */
-  VM_OC_CHECK_VAR, /**< check redeclared vars in the global scope */
-  VM_OC_CHECK_LET, /**< check redeclared lets in the global scope */
-  VM_OC_ASSIGN_LET_CONST, /**< assign values to let/const declarations */
-  VM_OC_INIT_BINDING, /**< create and intialize a binding */
-  VM_OC_THROW_CONST_ERROR, /**< throw invalid assignment to const variable error */
-  VM_OC_COPY_TO_GLOBAL, /**< copy value to global lex env */
-  VM_OC_COPY_FROM_ARG, /**< copy value from arg lex env */
-  VM_OC_CLONE_CONTEXT, /**< clone lexical environment with let/const declarations */
-  VM_OC_COPY_DATA_PROPERTIES, /**< copy data properties of an object */
-  VM_OC_SET_COMPUTED_PROPERTY, /**< set computed property */
-
-  VM_OC_FOR_OF_INIT, /**< for-of init context */
-  VM_OC_FOR_OF_GET_NEXT, /**< for-of get next */
-  VM_OC_FOR_OF_HAS_NEXT, /**< for-of has next */
-  VM_OC_FOR_AWAIT_OF_INIT, /**< for-await-of init context */
-  VM_OC_FOR_AWAIT_OF_HAS_NEXT, /**< for-await-of has next */
-
-  VM_OC_LOCAL_EVAL, /**< eval in local context */
-  VM_OC_SUPER_CALL, /**< call the 'super' constructor */
-  VM_OC_PUSH_CLASS_ENVIRONMENT, /**< push class environment */
-  VM_OC_PUSH_IMPLICIT_CTOR, /**< create implicit class constructor */
-  VM_OC_INIT_CLASS, /**< initialize class */
-  VM_OC_FINALIZE_CLASS, /**< finalize class */
-  VM_OC_SET_FIELD_INIT, /**< store the class field initializer function */
-  VM_OC_SET_STATIC_FIELD_INIT, /**< store the static class field initializer function */
-  VM_OC_RUN_FIELD_INIT, /**< run the class field initializer function */
-  VM_OC_RUN_STATIC_FIELD_INIT, /**< run the static class field initializer function */
-  VM_OC_SET_NEXT_COMPUTED_FIELD, /**< set the next computed field of a class */
-  VM_OC_PUSH_SUPER_CONSTRUCTOR, /**< getSuperConstructor operation */
-  VM_OC_RESOLVE_LEXICAL_THIS, /**< resolve this_binding from from the lexical environment */
-  VM_OC_SUPER_REFERENCE, /**< push super reference */
-  VM_OC_SET_HOME_OBJECT, /**< set the [[HomeObject]] environment in an object literal */
-  VM_OC_OBJECT_LITERAL_HOME_ENV, /**< create/destroy [[HomeObject]] environment of an object literal */
-  VM_OC_SET_FUNCTION_NAME, /**< set function name property */
-
-  VM_OC_PUSH_SPREAD_ELEMENT, /**< push spread element */
-  VM_OC_PUSH_REST_OBJECT, /**< push rest object */
-  VM_OC_ITERATOR_CONTEXT_CREATE, /**< create iterator conext */
-  VM_OC_ITERATOR_CONTEXT_END, /**< finalize iterator cotnext */
-  VM_OC_ITERATOR_STEP, /**< IteratorStep abstract operation */
-  VM_OC_OBJ_INIT_CONTEXT_CREATE, /**< create object initializer context */
-  VM_OC_OBJ_INIT_CONTEXT_END, /**< finalize object initializer context */
-  VM_OC_OBJ_INIT_PUSH_REST, /**< push the object with the rest properties */
-  VM_OC_INITIALIZER_PUSH_NAME, /**< append string to name list array and push the string */
-  VM_OC_DEFAULT_INITIALIZER, /**< default initializer inside a pattern */
-  VM_OC_REST_INITIALIZER, /**< create rest object inside an array pattern */
-  VM_OC_INITIALIZER_PUSH_PROP, /**< push property for object initializer */
-  VM_OC_SPREAD_ARGUMENTS, /**< perform function call/construct with spreaded arguments */
-  VM_OC_CREATE_GENERATOR, /**< create a generator object */
-  VM_OC_YIELD, /**< yield operation */
-  VM_OC_ASYNC_YIELD, /**< async yield operation */
-  VM_OC_ASYNC_YIELD_ITERATOR, /**< async yield iterator operation */
-  VM_OC_AWAIT, /**< await operation */
-  VM_OC_GENERATOR_AWAIT, /**< generator await operation */
-  VM_OC_EXT_RETURN, /**< return which also clears the stack */
-  VM_OC_ASYNC_EXIT, /**< return from async function */
-  VM_OC_STRING_CONCAT, /**< string concatenation */
-  VM_OC_GET_TEMPLATE_OBJECT, /**< GetTemplateObject operation */
-  VM_OC_PUSH_NEW_TARGET, /**< push new.target onto the stack */
-  VM_OC_REQUIRE_OBJECT_COERCIBLE, /**< RequireObjectCoercible opretaion */
-  VM_OC_ASSIGN_SUPER, /**< assign super reference */
-  VM_OC_SET__PROTO__, /**< set prototype when __proto__: form is used */
-  VM_OC_PUSH_STATIC_FIELD_FUNC, /**< push static field initializer function */
-  VM_OC_ADD_COMPUTED_FIELD, /**< add computed field name */
-#endif /* JERRY_ESNEXT */
-#if JERRY_MODULE_SYSTEM
-  VM_OC_MODULE_IMPORT, /**< module dynamic import */
-  VM_OC_MODULE_IMPORT_META, /**< module import.meta */
-#endif /* JERRY_MODULE_SYSTEM */
-
-  VM_OC_NONE, /**< a special opcode for unsupported byte codes */
-} vm_oc_types;
-
-/**
- * Unused opcodes, but required by byte-code types.
- */
-typedef enum
-{
-#if !JERRY_ESNEXT
-  VM_OC_EXP = VM_OC_NONE, /**< exponentiation */
-  VM_OC_BRANCH_IF_NULLISH = VM_OC_NONE, /** branch if undefined or null */
-  VM_OC_POP_REFERENCE = VM_OC_NONE, /** prop identifier or property reference from the stack */
-#endif /* !JERRY_ESNEXT */
-#if !JERRY_DEBUGGER
-  VM_OC_BREAKPOINT_ENABLED = VM_OC_NONE, /**< enabled breakpoint for debugger is unused */
-  VM_OC_BREAKPOINT_DISABLED = VM_OC_NONE, /**< disabled breakpoint for debugger is unused */
-#endif /* !JERRY_DEBUGGER */
-#if !JERRY_ESNEXT
-  VM_OC_CLASS_CALL_STATIC_BLOCK = VM_OC_NONE, /**< call the class static block */
-  VM_OC_DEFINE_FIELD = VM_OC_NONE, /**< define class field */
-  VM_OC_PRIVATE_PROP_REFERENCE = VM_OC_NONE, /* reference to class private method  */
-  VM_OC_ASSIGN_PRIVATE = VM_OC_NONE, /**< assign to private field */
-  VM_OC_PRIVATE_FIELD_ADD = VM_OC_NONE, /**< add private field */
-  VM_OC_PRIVATE_PROP_GET = VM_OC_NONE, /**< get private field */
-  VM_OC_PRIVATE_IN = VM_OC_NONE, /**< 'in' opcode handler for private identifiers */
-  VM_OC_COLLECT_PRIVATE_PROPERTY = VM_OC_NONE, /**< collect private properties */
-  VM_OC_EXT_VAR_EVAL = VM_OC_NONE, /**< variable and function evaluation for
-                                    *   functions with separate argument context */
-  VM_OC_CHECK_VAR = VM_OC_NONE, /**< check redeclared vars in the global scope */
-  VM_OC_CHECK_LET = VM_OC_NONE, /**< check redeclared lets in the global scope */
-  VM_OC_ASSIGN_LET_CONST = VM_OC_NONE, /**< assign values to let/const declarations */
-  VM_OC_INIT_BINDING = VM_OC_NONE, /**< create and intialize a binding */
-  VM_OC_THROW_CONST_ERROR = VM_OC_NONE, /**< throw invalid assignment to const variable error */
-  VM_OC_COPY_TO_GLOBAL = VM_OC_NONE, /**< copy value to global lex env */
-  VM_OC_COPY_FROM_ARG = VM_OC_NONE, /**< copy value from arg lex env */
-  VM_OC_CLONE_CONTEXT = VM_OC_NONE, /**< clone lexical environment with let/const declarations */
-  VM_OC_COPY_DATA_PROPERTIES = VM_OC_NONE, /**< copy data properties of an object */
-  VM_OC_SET_COMPUTED_PROPERTY = VM_OC_NONE, /**< set computed property is unused */
-
-  VM_OC_FOR_OF_INIT = VM_OC_NONE, /**< for-of init context */
-  VM_OC_FOR_OF_GET_NEXT = VM_OC_NONE, /**< for-of get next */
-  VM_OC_FOR_OF_HAS_NEXT = VM_OC_NONE, /**< for-of has next */
-  VM_OC_FOR_AWAIT_OF_INIT = VM_OC_NONE, /**< for-await-of init context */
-  VM_OC_FOR_AWAIT_OF_HAS_NEXT = VM_OC_NONE, /**< for-await-of has next */
-
-  VM_OC_LOCAL_EVAL = VM_OC_NONE, /**< eval in local context */
-  VM_OC_SUPER_CALL = VM_OC_NONE, /**< call the 'super' constructor */
-  VM_OC_PUSH_CLASS_ENVIRONMENT = VM_OC_NONE, /**< push class environment */
-  VM_OC_PUSH_IMPLICIT_CTOR = VM_OC_NONE, /**< create implicit class constructor */
-  VM_OC_INIT_CLASS = VM_OC_NONE, /**< initialize class */
-  VM_OC_FINALIZE_CLASS = VM_OC_NONE, /**< finalize class */
-  VM_OC_SET_FIELD_INIT = VM_OC_NONE, /**< store the class field initializer function */
-  VM_OC_SET_STATIC_FIELD_INIT = VM_OC_NONE, /**< store the static class field initializer function */
-  VM_OC_RUN_FIELD_INIT = VM_OC_NONE, /**< run the class field initializer function */
-  VM_OC_RUN_STATIC_FIELD_INIT = VM_OC_NONE, /**< run the static class field initializer function */
-  VM_OC_SET_NEXT_COMPUTED_FIELD = VM_OC_NONE, /**< set the next computed field of a class */
-  VM_OC_PUSH_SUPER_CONSTRUCTOR = VM_OC_NONE, /**< getSuperConstructor operation */
-  VM_OC_RESOLVE_LEXICAL_THIS = VM_OC_NONE, /**< resolve this_binding from from the lexical environment */
-  VM_OC_SUPER_REFERENCE = VM_OC_NONE, /**< push super reference */
-  VM_OC_SET_HOME_OBJECT = VM_OC_NONE, /**< set the [[HomeObject]] internal property in an object literal */
-  VM_OC_OBJECT_LITERAL_HOME_ENV = VM_OC_NONE, /**< create/destroy [[HomeObject]] environment of an object literal */
-  VM_OC_SET_FUNCTION_NAME = VM_OC_NONE, /**< set function name property */
-
-  VM_OC_PUSH_SPREAD_ELEMENT = VM_OC_NONE, /**< push spread element */
-  VM_OC_PUSH_REST_OBJECT = VM_OC_NONE, /**< push rest object */
-  VM_OC_ITERATOR_CONTEXT_CREATE = VM_OC_NONE, /**< create iterator context */
-  VM_OC_ITERATOR_STEP = VM_OC_NONE, /**< IteratorStep abstract operation */
-  VM_OC_ITERATOR_CONTEXT_END = VM_OC_NONE, /**< finalize iterator cotnext */
-  VM_OC_OBJ_INIT_CONTEXT_CREATE = VM_OC_NONE, /**< create object initializer context */
-  VM_OC_OBJ_INIT_CONTEXT_END = VM_OC_NONE, /**< finalize object initializer context */
-  VM_OC_OBJ_INIT_PUSH_REST = VM_OC_NONE, /**< push the object with the rest properties */
-  VM_OC_INITIALIZER_PUSH_NAME = VM_OC_NONE, /**< append string to name list array and push the string */
-  VM_OC_DEFAULT_INITIALIZER = VM_OC_NONE, /**< default initializer inside a pattern */
-  VM_OC_REST_INITIALIZER = VM_OC_NONE, /**< create rest object inside an array pattern */
-  VM_OC_INITIALIZER_PUSH_PROP = VM_OC_NONE, /**< push property for object initializer */
-  VM_OC_SPREAD_ARGUMENTS = VM_OC_NONE, /**< perform function call/construct with spreaded arguments */
-  VM_OC_CREATE_GENERATOR = VM_OC_NONE, /**< create a generator object */
-  VM_OC_YIELD = VM_OC_NONE, /**< yield operation */
-  VM_OC_ASYNC_YIELD = VM_OC_NONE, /**< async yield operation */
-  VM_OC_ASYNC_YIELD_ITERATOR = VM_OC_NONE, /**< async yield iterator operation */
-  VM_OC_AWAIT = VM_OC_NONE, /**< await operation */
-  VM_OC_GENERATOR_AWAIT = VM_OC_NONE, /**< generator await operation */
-  VM_OC_EXT_RETURN = VM_OC_NONE, /**< return which also clears the stack */
-  VM_OC_ASYNC_EXIT = VM_OC_NONE, /**< return from async function */
-  VM_OC_STRING_CONCAT = VM_OC_NONE, /**< string concatenation */
-  VM_OC_GET_TEMPLATE_OBJECT = VM_OC_NONE, /**< GetTemplateObject operation */
-  VM_OC_PUSH_NEW_TARGET = VM_OC_NONE, /**< push new.target onto the stack */
-  VM_OC_REQUIRE_OBJECT_COERCIBLE = VM_OC_NONE, /**< RequireObjectCoercible opretaion */
-  VM_OC_ASSIGN_SUPER = VM_OC_NONE, /**< assign super reference */
-  VM_OC_SET__PROTO__ = VM_OC_NONE, /**< set prototype when __proto__: form is used */
-  VM_OC_PUSH_STATIC_FIELD_FUNC = VM_OC_NONE, /**< push static field initializer function */
-  VM_OC_ADD_COMPUTED_FIELD = VM_OC_NONE, /**< add computed field name */
-#endif /* !JERRY_ESNEXT */
-#if !JERRY_MODULE_SYSTEM
-  VM_OC_MODULE_IMPORT = VM_OC_NONE, /**< module dynamic import */
-  VM_OC_MODULE_IMPORT_META = VM_OC_NONE, /**< module import.meta */
-#endif /* JERRY_MODULE_SYSTEM */
-
-  VM_OC_UNUSED = VM_OC_NONE /**< placeholder if the list is empty */
-} vm_oc_unused_types;
-
-/**
- * Decrement operator.
- */
-#define VM_OC_DECREMENT_OPERATOR_FLAG 0x1
-
-/**
- * Postfix increment/decrement operator.
- */
-#define VM_OC_POST_INCR_DECR_OPERATOR_FLAG 0x2
-
-/**
- * An named variable is updated by the increment/decrement operator.
- */
-#define VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG 0x4
-
-/**
- * Jump to target offset if input value is logical false.
- */
-#define VM_OC_BRANCH_IF_FALSE_FLAG 0x1
-
-/**
- * Branch optimized for logical and/or opcodes.
- */
-#define VM_OC_LOGICAL_BRANCH_FLAG 0x2
-
-/**
- * Bit index shift for non-static property initializers.
- */
-#define VM_OC_NON_STATIC_SHIFT 15
-
-/**
- * This flag is set for static property initializers.
- */
-#define VM_OC_NON_STATIC_FLAG (0x1 << VM_OC_NON_STATIC_SHIFT)
-
-/**
- * Position of "put result" opcode.
- */
-#define VM_OC_PUT_RESULT_SHIFT 11
-
-/**
- * Mask of "put result" opcode.
- */
-#define VM_OC_PUT_RESULT_MASK 0xf
-
-/**
- * Generate a "put result" opcode flag bit.
- */
-#define VM_OC_PUT_RESULT_CREATE_FLAG(V) (((V) &VM_OC_PUT_RESULT_MASK) << VM_OC_PUT_RESULT_SHIFT)
-
-/**
- * Checks whether the result is stored somewhere.
- */
-#define VM_OC_HAS_PUT_RESULT(V) ((V) & (VM_OC_PUT_RESULT_MASK << VM_OC_PUT_RESULT_SHIFT))
-
 /**
  * Specify where the result is stored
  */
 typedef enum
 {
-  VM_OC_PUT_IDENT = VM_OC_PUT_RESULT_CREATE_FLAG (0x1),
-  VM_OC_PUT_REFERENCE = VM_OC_PUT_RESULT_CREATE_FLAG (0x2),
-  VM_OC_PUT_STACK = VM_OC_PUT_RESULT_CREATE_FLAG (0x4),
-  VM_OC_PUT_BLOCK = VM_OC_PUT_RESULT_CREATE_FLAG (0x8),
-} vm_oc_put_types;
+  /* These 3 flags must be in this order */
+  VM_PUT_RESULT_NONE = 0, /**< result is not needed, can be free */
+  VM_PUT_RESULT_STACK = 1 << 0, /**< result must be placed on to the stack */
+  VM_PUT_RESULT_BLOCK = 1 << 1, /**< result must be placed on to frame's block result */
+
+  VM_PUT_RESULT_IDENT = 1 << 2, /**< assign to ident reference */
+  VM_PUT_RESULT_REFERENCE = 1 << 4, /**< assign to property reference */
+  VM_PUT_RESULT_DECR = 1 << 5, /**< unary -- flag */
+  VM_PUT_RESULT_POST = 1 << 6, /**< post unary lvalue flag */
+} vm_put_result_flags_t;
 
 /**
  * Non-recursive vm_loop: the vm_loop can be suspended