Support shared user data for scripts (#4710)

The same data is returned for the script and all of its functions,
including those which are created by an eval call.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2021-07-20 10:33:23 +02:00
committed by GitHub
parent 9ff25dbc12
commit 713d90b5a0
20 changed files with 780 additions and 126 deletions
+63 -20
View File
@@ -50,9 +50,6 @@ snapshot_get_global_flags (bool has_regex, /**< regex literal is present */
#if JERRY_ESNEXT
flags |= (has_class ? JERRY_SNAPSHOT_HAS_CLASS_LITERAL : 0);
#endif /* JERRY_ESNEXT */
#if JERRY_BUILTIN_REALMS
flags |= JERRY_SNAPSHOT_HAS_REALM_VALUE;
#endif /* JERRY_BUILTIN_REALMS */
return flags;
} /* snapshot_get_global_flags */
@@ -71,9 +68,6 @@ snapshot_check_global_flags (uint32_t global_flags) /**< global flags */
#if JERRY_ESNEXT
global_flags &= (uint32_t) ~JERRY_SNAPSHOT_HAS_CLASS_LITERAL;
#endif /* JERRY_ESNEXT */
#if JERRY_BUILTIN_REALMS
global_flags |= JERRY_SNAPSHOT_HAS_REALM_VALUE;
#endif /* JERRY_BUILTIN_REALMS */
return global_flags == snapshot_get_global_flags (false, false);
} /* snapshot_check_global_flags */
@@ -395,9 +389,7 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end);
#if JERRY_BUILTIN_REALMS
args_p->realm_value = JMEM_CP_NULL;
#endif /* JERRY_BUILTIN_REALMS */
args_p->script_value = JMEM_CP_NULL;
}
else
{
@@ -407,9 +399,7 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end);
#if JERRY_BUILTIN_REALMS
args_p->realm_value = JMEM_CP_NULL;
#endif /* JERRY_BUILTIN_REALMS */
args_p->script_value = JMEM_CP_NULL;
}
for (uint32_t i = 0; i < const_literal_end; i++)
@@ -569,6 +559,7 @@ static ecma_compiled_code_t *
snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of the
* current primary function */
const uint8_t *literal_base_p, /**< literal start */
cbc_script_t *script_p, /**< script */
bool copy_bytecode) /**< byte code should be copied to memory */
{
ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) base_addr_p;
@@ -598,6 +589,14 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
uint32_t const_literal_end;
uint32_t literal_end;
if (JERRY_UNLIKELY (script_p->refs_and_type >= CBC_SCRIPT_REF_MAX))
{
/* This is probably never happens in practice. */
jerry_fatal (ERR_REF_COUNT_LIMIT);
}
script_p->refs_and_type += CBC_SCRIPT_REF_ONE;
if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
{
uint8_t *byte_p = (uint8_t *) bytecode_p;
@@ -608,9 +607,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
header_size = sizeof (cbc_uint16_arguments_t);
#if JERRY_BUILTIN_REALMS
ECMA_SET_INTERNAL_VALUE_POINTER (args_p->realm_value, ecma_builtin_get_global ());
#endif /* JERRY_BUILTIN_REALMS */
ECMA_SET_INTERNAL_VALUE_POINTER (args_p->script_value, script_p);
}
else
{
@@ -622,9 +619,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
header_size = sizeof (cbc_uint8_arguments_t);
#if JERRY_BUILTIN_REALMS
ECMA_SET_INTERNAL_VALUE_POINTER (args_p->realm_value, ecma_builtin_get_global ());
#endif /* JERRY_BUILTIN_REALMS */
ECMA_SET_INTERNAL_VALUE_POINTER (args_p->script_value, script_p);
}
if (copy_bytecode
@@ -729,6 +724,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
ecma_compiled_code_t *literal_bytecode_p;
literal_bytecode_p = snapshot_load_compiled_code (base_addr_p + literal_offset,
literal_base_p,
script_p,
copy_bytecode);
ECMA_SET_INTERNAL_VALUE_POINTER (literal_start_p[i],
@@ -930,14 +926,18 @@ jerry_value_t
jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
size_t snapshot_size, /**< size of snapshot */
size_t func_index, /**< index of primary function */
uint32_t exec_snapshot_opts) /**< jerry_exec_snapshot_opts_t option bits */
uint32_t exec_snapshot_opts, /**< jerry_exec_snapshot_opts_t option bits */
const jerry_exec_snapshot_option_values_t *option_values_p) /**< additional option values,
* can be NULL if not used */
{
#if JERRY_SNAPSHOT_EXEC
JERRY_ASSERT (snapshot_p != NULL);
uint32_t allowed_opts = (JERRY_SNAPSHOT_EXEC_COPY_DATA
| JERRY_SNAPSHOT_EXEC_ALLOW_STATIC
| JERRY_SNAPSHOT_EXEC_LOAD_AS_FUNCTION);
| JERRY_SNAPSHOT_EXEC_LOAD_AS_FUNCTION
| JERRY_SNAPSHOT_EXEC_HAS_RESOURCE
| JERRY_SNAPSHOT_EXEC_HAS_USER_VALUE);
if ((exec_snapshot_opts & ~(allowed_opts)) != 0)
{
@@ -998,16 +998,58 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
}
else
{
ecma_value_t user_value = ECMA_VALUE_EMPTY;
if ((exec_snapshot_opts & JERRY_SNAPSHOT_EXEC_HAS_USER_VALUE)
&& option_values_p != NULL)
{
user_value = option_values_p->user_value;
}
uint32_t script_size = (user_value != ECMA_VALUE_EMPTY ? sizeof (cbc_script_user_t)
: sizeof (cbc_script_t));
cbc_script_t *script_p = jmem_heap_alloc_block (script_size);
CBC_SCRIPT_SET_TYPE (script_p, user_value, CBC_SCRIPT_REF_ONE);
#if JERRY_BUILTIN_REALMS
script_p->realm_p = (ecma_object_t *) JERRY_CONTEXT (global_object_p);
#endif /* JERRY_BUILTIN_REALMS */
#if JERRY_RESOURCE_NAME
ecma_value_t resource_name = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
if ((exec_snapshot_opts & JERRY_SNAPSHOT_EXEC_HAS_RESOURCE)
&& option_values_p != NULL
&& option_values_p->resource_name_length > 0)
{
resource_name = ecma_find_or_create_literal_string (option_values_p->resource_name_p,
(lit_utf8_size_t) option_values_p->resource_name_length);
}
script_p->resource_name = resource_name;
#endif /* JERRY_RESOURCE_NAME */
const uint8_t *literal_base_p = snapshot_data_p + header_p->lit_table_offset;
bytecode_p = snapshot_load_compiled_code ((const uint8_t *) bytecode_p,
literal_base_p,
script_p,
(exec_snapshot_opts & JERRY_SNAPSHOT_EXEC_COPY_DATA) != 0);
if (bytecode_p == NULL)
{
JERRY_ASSERT (script_p->refs_and_type >= CBC_SCRIPT_REF_ONE);
jmem_heap_free_block (script_p, script_size);
return ecma_raise_type_error (invalid_format_error_p);
}
script_p->refs_and_type -= CBC_SCRIPT_REF_ONE;
if (user_value != ECMA_VALUE_EMPTY)
{
((cbc_script_user_t *) script_p)->user_value = ecma_copy_value_if_not_object (user_value);
}
}
#if JERRY_PARSER_DUMP_BYTE_CODE
@@ -1063,6 +1105,7 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
JERRY_UNUSED (snapshot_size);
JERRY_UNUSED (func_index);
JERRY_UNUSED (exec_snapshot_opts);
JERRY_UNUSED (option_values_p);
return jerry_create_error (JERRY_ERROR_COMMON, (const jerry_char_t *) "Snapshot execution is not supported");
#endif /* JERRY_SNAPSHOT_EXEC */
+1 -2
View File
@@ -45,8 +45,7 @@ typedef enum
{
/* 8 bits are reserved for dynamic features */
JERRY_SNAPSHOT_HAS_REGEX_LITERAL = (1u << 0), /**< byte code has regex literal */
JERRY_SNAPSHOT_HAS_REALM_VALUE = (1u << 1), /**< byte code has realm value */
JERRY_SNAPSHOT_HAS_CLASS_LITERAL = (1u << 2), /**< byte code has class 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;
+34 -2
View File
@@ -393,7 +393,8 @@ jerry_parse (const jerry_char_t *source_p, /**< script source */
uint32_t allowed_parse_options = (JERRY_PARSE_STRICT_MODE
| JERRY_PARSE_MODULE
| JERRY_PARSE_HAS_RESOURCE
| JERRY_PARSE_HAS_START);
| JERRY_PARSE_HAS_START
| JERRY_PARSE_HAS_USER_VALUE);
if (options_p != NULL && (options_p->options & ~allowed_parse_options) != 0)
{
@@ -493,7 +494,8 @@ jerry_parse_function (const jerry_char_t *arg_list_p, /**< script source */
uint32_t allowed_parse_options = (JERRY_PARSE_STRICT_MODE
| JERRY_PARSE_HAS_RESOURCE
| JERRY_PARSE_HAS_START);
| JERRY_PARSE_HAS_START
| JERRY_PARSE_HAS_USER_VALUE);
if (options_p != NULL && (options_p->options & ~allowed_parse_options) != 0)
{
@@ -5381,6 +5383,36 @@ jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */
return ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
} /* jerry_get_resource_name */
/**
* Returns the user value assigned to a script / module / function.
*
* Note:
* This value is usually set by the parser when
* the JERRY_PARSE_HAS_USER_VALUE flag is passed.
*
* @return user value
*/
jerry_value_t
jerry_get_user_value (const jerry_value_t value) /**< jerry api value */
{
const ecma_compiled_code_t *bytecode_p = ecma_bytecode_get_from_value (value);
if (bytecode_p == NULL)
{
return ECMA_VALUE_UNDEFINED;
}
ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value;
cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value);
if (CBC_SCRIPT_GET_TYPE (script_p) == CBC_SCRIPT_GENERIC)
{
return ECMA_VALUE_UNDEFINED;
}
return ecma_copy_value (((cbc_script_user_t *) script_p)->user_value);
} /* jerry_get_user_value */
/**
* Replaces the currently active realm with another realm.
*