Skip to content

Commit

Permalink
Rework VM dispatch
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Robert Fancsik committed Jan 20, 2022
1 parent 0ef5094 commit cc74bcc
Show file tree
Hide file tree
Showing 12 changed files with 2,123 additions and 1,953 deletions.
3 changes: 1 addition & 2 deletions docs/05.PORT-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;
```
Expand Down
73 changes: 27 additions & 46 deletions jerry-core/api/jerry-snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
16 changes: 8 additions & 8 deletions jerry-core/api/jerry-snapshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) */
Expand All @@ -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 */
3 changes: 1 addition & 2 deletions jerry-core/include/jerryscript-port.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
5 changes: 0 additions & 5 deletions jerry-core/jrt/jrt-fatals.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
4 changes: 2 additions & 2 deletions jerry-core/parser/js/byte-code.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand Down

0 comments on commit cc74bcc

Please sign in to comment.