From 34edf53753b11abcf77242054b88c30714f0d689 Mon Sep 17 00:00:00 2001 From: Hyukwoo Park Date: Mon, 2 Mar 2020 23:59:55 +0900 Subject: [PATCH] Add new type which represents pointer with tag value (#3591) jmem_cpointer_tag_t is newly added to represent pointer along with tag value. This new type is first applied to scope_cp to mark initailized function properties (length, name) later JerryScript-DCO-1.0-Signed-off-by: HyukWoo Park hyukwoo.park@samsung.com --- jerry-core/api/jerry.c | 4 +- jerry-core/ecma/base/ecma-gc.c | 4 +- jerry-core/ecma/base/ecma-globals.h | 20 ++--- jerry-core/ecma/base/ecma-helpers-value.c | 3 + jerry-core/ecma/base/ecma-helpers.h | 33 +++++++++ .../ecma/operations/ecma-function-object.c | 8 +- jerry-core/jmem/jmem.h | 74 +++++++++++++++++++ jerry-core/vm/vm.c | 13 ++-- 8 files changed, 135 insertions(+), 24 deletions(-) diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index 9214c0181..8e8694e0f 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -583,8 +583,8 @@ jerry_run (const jerry_value_t func_val) /**< function to run */ ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; - ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_func_p->u.function.scope_cp); + ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, + ext_func_p->u.function.scope_cp); if (scope_p != ecma_get_global_environment ()) { diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 5d1d3fcb2..259df53fc 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -651,8 +651,8 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ if (!ecma_get_object_is_builtin (object_p)) { ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; - ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_func_p->u.function.scope_cp)); + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, + ext_func_p->u.function.scope_cp)); #if ENABLED (JERRY_ES2015) const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code (ext_func_p); diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 581856563..4def4805c 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -36,6 +36,15 @@ */ #define ECMA_NULL_POINTER JMEM_CP_NULL +#if defined (JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY) + +/** + * JMEM_ALIGNMENT_LOG aligned pointers can be stored directly in ecma_value_t + */ +#define ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + +#endif /* JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY */ + /** * @} */ @@ -127,15 +136,6 @@ typedef uint32_t ecma_value_t; */ typedef int32_t ecma_integer_value_t; -#if UINTPTR_MAX <= UINT32_MAX - -/** - * JMEM_ALIGNMENT_LOG aligned pointers can be stored directly in ecma_value_t - */ -#define ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY - -#endif /* UINTPTR_MAX <= UINT32_MAX */ - /** * Mask for ecma types in ecma_value_t */ @@ -848,7 +848,7 @@ typedef struct */ struct { - ecma_value_t scope_cp; /**< function scope */ + jmem_cpointer_tag_t scope_cp; /**< function scope */ ecma_value_t bytecode_cp; /**< function byte code */ } function; diff --git a/jerry-core/ecma/base/ecma-helpers-value.c b/jerry-core/ecma/base/ecma-helpers-value.c index 38b9c284f..0ef1731b5 100644 --- a/jerry-core/ecma/base/ecma-helpers-value.c +++ b/jerry-core/ecma/base/ecma-helpers-value.c @@ -35,6 +35,9 @@ JERRY_STATIC_ASSERT (ECMA_VALUE_SHIFT <= JMEM_ALIGNMENT_LOG, JERRY_STATIC_ASSERT (sizeof (jmem_cpointer_t) <= sizeof (ecma_value_t), size_of_jmem_cpointer_t_must_be_less_or_equal_to_the_size_of_ecma_value_t); +JERRY_STATIC_ASSERT (sizeof (jmem_cpointer_t) <= sizeof (jmem_cpointer_tag_t), + size_of_jmem_cpointer_t_must_be_less_or_equal_to_the_size_of_jmem_cpointer_tag_t); + #ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY JERRY_STATIC_ASSERT (sizeof (uintptr_t) <= sizeof (ecma_value_t), diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index c704ed1f2..c4e35fdd5 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -32,6 +32,12 @@ */ #define ECMA_GET_NON_NULL_POINTER(type, field) JMEM_CP_GET_NON_NULL_POINTER (type, field) +/** + * Extract value of pointer from specified pointer-tag value + */ +#define ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG(type, field) \ + JMEM_CP_GET_NON_NULL_POINTER_FROM_POINTER_TAG (type, field) + /** * Get value of pointer from specified compressed pointer. */ @@ -44,12 +50,39 @@ #define ECMA_SET_NON_NULL_POINTER(field, non_compressed_pointer) JMEM_CP_SET_NON_NULL_POINTER (field, \ non_compressed_pointer) +/** + * Set value of pointer-tag value so that it will correspond + * to specified non_compressed_pointer along with tag + */ +#define ECMA_SET_NON_NULL_POINTER_TAG(field, non_compressed_pointer, tag) \ + JMEM_CP_SET_NON_NULL_POINTER_TAG (field, non_compressed_pointer, tag) + /** * Set value of compressed pointer so that it will correspond * to specified non_compressed_pointer. */ #define ECMA_SET_POINTER(field, non_compressed_pointer) JMEM_CP_SET_POINTER (field, non_compressed_pointer) +/** + * Get value of each tag bit from specified pointer-tag value + */ +#define ECMA_GET_FIRST_BIT_FROM_POINTER_TAG(field) \ + JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (field) /**< get first tag bit from jmem_cpointer_tag_t **/ +#define ECMA_GET_SECOND_BIT_FROM_POINTER_TAG(field) \ + JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (field) /**< get second tag bit from jmem_cpointer_tag_t **/ +#define ECMA_GET_THIRD_BIT_FROM_POINTER_TAG(field) \ + JMEM_CP_GET_THIRD_BIT_FROM_POINTER_TAG (field) /**< get third tag bit from jmem_cpointer_tag_t **/ + +/** + * Set value of each tag bit to specified pointer-tag value + */ +#define ECMA_SET_FIRST_BIT_TO_POINTER_TAG(field) \ + JMEM_CP_SET_FIRST_BIT_TO_POINTER_TAG (field) /**< set first tag bit to jmem_cpointer_tag_t **/ +#define ECMA_SET_SECOND_BIT_TO_POINTER_TAG(field) \ + JMEM_CP_SET_SECOND_BIT_TO_POINTER_TAG (field) /**< set second tag bit to jmem_cpointer_tag_t **/ +#define ECMA_SET_THIRD_BIT_TO_POINTER_TAG(field) \ + JMEM_CP_SET_THIRD_BIT_TO_POINTER_TAG (field) /**< set third tag bit to jmem_cpointer_tag_t **/ + /** * Status flags for ecma_string_get_chars function */ diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index fd913ca44..e5699b5c3 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -335,7 +335,7 @@ ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */ ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p; /* 9. */ - ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.scope_cp, scope_p); + ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, scope_p, 0); /* 10., 11., 12. */ @@ -423,7 +423,7 @@ ecma_op_create_arrow_function_object (ecma_object_t *scope_p, /**< function's sc ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_p; - ECMA_SET_INTERNAL_VALUE_POINTER (arrow_func_p->header.u.function.scope_cp, scope_p); + ECMA_SET_NON_NULL_POINTER_TAG (arrow_func_p->header.u.function.scope_cp, scope_p, 0); #if ENABLED (JERRY_SNAPSHOT_EXEC) if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) @@ -993,8 +993,8 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ /* Entering Function Code (ECMA-262 v5, 10.4.3) */ ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; - ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_func_p->u.function.scope_cp); + ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, + ext_func_p->u.function.scope_cp); /* 8. */ ecma_value_t this_binding = this_arg_value; diff --git a/jerry-core/jmem/jmem.h b/jerry-core/jmem/jmem.h index 18ad2f383..a89f705df 100644 --- a/jerry-core/jmem/jmem.h +++ b/jerry-core/jmem/jmem.h @@ -40,6 +40,37 @@ */ #define JMEM_ALIGNMENT (1u << JMEM_ALIGNMENT_LOG) +/** + * Pointer value can be directly stored without compression + */ +#if UINTPTR_MAX <= UINT32_MAX +#define JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY +#endif /* UINTPTR_MAX <= UINT32_MAX */ + +/** + * Mask for tag part in jmem_cpointer_tag_t + */ +#define JMEM_TAG_MASK 0x7u + +/** + * Shift for tag part in jmem_cpointer_tag_t + */ +#if defined (JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY) && ENABLED (JERRY_CPOINTER_32_BIT) +#define JMEM_TAG_SHIFT 0 +#else /* !JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY || !ENABLED (JERRY_CPOINTER_32_BIT) */ +#define JMEM_TAG_SHIFT 3 +#endif /* JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY && ENABLED (JERRY_CPOINTER_32_BIT) */ + +/** + * Bit mask for tag part in jmem_cpointer_tag_t + */ +enum +{ + JMEM_FIRST_TAG_BIT_MASK = (1u << 0), /**< first tag bit mask **/ + JMEM_SECOND_TAG_BIT_MASK = (1u << 1), /**< second tag bit mask **/ + JMEM_THIRD_TAG_BIT_MASK = (1u << 2), /**< third tag bit mask **/ +}; + /** * Compressed pointer representations * @@ -69,6 +100,11 @@ typedef uint32_t jmem_cpointer_t; typedef uint16_t jmem_cpointer_t; #endif /* ENABLED (JERRY_CPOINTER_32_BIT) */ +/** + * Compressed pointer with tag value + */ +typedef uint32_t jmem_cpointer_tag_t; + /** * Memory usage pressure for reclaiming unused memory. * @@ -223,6 +259,44 @@ void * JERRY_ATTR_PURE jmem_decompress_pointer (uintptr_t compressed_pointer); } \ } while (false); +/** + * Set value of pointer-tag value so that it will correspond + * to specified non_compressed_pointer along with tag + */ +#define JMEM_CP_SET_NON_NULL_POINTER_TAG(cp_value, pointer, tag) \ + do \ + { \ + JERRY_ASSERT ((uintptr_t) tag < (uintptr_t) (JMEM_ALIGNMENT)); \ + jmem_cpointer_tag_t compressed_ptr = jmem_compress_pointer (pointer); \ + (cp_value) = (jmem_cpointer_tag_t) ((compressed_ptr << JMEM_TAG_SHIFT) | tag); \ + } while (false); + +/** + * Extract value of pointer from specified pointer-tag value + */ +#define JMEM_CP_GET_NON_NULL_POINTER_FROM_POINTER_TAG(type, cp_value) \ + ((type *) (jmem_decompress_pointer ((cp_value & ~JMEM_TAG_MASK) >> JMEM_TAG_SHIFT))) + +/** + * Get value of each tag from specified pointer-tag value + */ +#define JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG(cp_value) \ + (cp_value & JMEM_FIRST_TAG_BIT_MASK) /**< get first tag bit **/ +#define JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG(cp_value) \ + (cp_value & JMEM_SECOND_TAG_BIT_MASK) /**< get second tag bit **/ +#define JMEM_CP_GET_THIRD_BIT_FROM_POINTER_TAG(cp_value) \ + (cp_value & JMEM_THIRD_TAG_BIT_MASK) /**< get third tag bit **/ + +/** + * Set value of each tag to specified pointer-tag value + */ +#define JMEM_CP_SET_FIRST_BIT_TO_POINTER_TAG(cp_value) \ + (cp_value) = (cp_value | JMEM_FIRST_TAG_BIT_MASK) /**< set first tag bit **/ +#define JMEM_CP_SET_SECOND_BIT_TO_POINTER_TAG(cp_value) \ + (cp_value) = (cp_value | JMEM_SECOND_TAG_BIT_MASK) /**< set second tag bit **/ +#define JMEM_CP_SET_THIRD_BIT_TO_POINTER_TAG(cp_value) \ + (cp_value) = (cp_value | JMEM_THIRD_TAG_BIT_MASK) /**< set third tag bit **/ + /** * @} * \addtogroup poolman Memory pool manager diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index b627bcfd1..8cd13f18d 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -1224,14 +1224,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p; - JERRY_ASSERT (frame_ctx_p->lex_env_p == ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_func_p->u.function.scope_cp)); + JERRY_ASSERT (frame_ctx_p->lex_env_p == + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp)); ecma_object_t *name_lex_env = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p); ecma_op_create_immutable_binding (name_lex_env, ecma_get_string_from_value (right_value), left_value); - ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.scope_cp, name_lex_env); + ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, name_lex_env, 0); ecma_free_value (right_value); ecma_deref_object (name_lex_env); @@ -1814,9 +1814,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_p); ECMA_SET_INTERNAL_VALUE_POINTER (current_ext_func_obj_p->u.function.bytecode_cp, bytecode_p); - ECMA_SET_INTERNAL_VALUE_POINTER (current_ext_func_obj_p->u.function.scope_cp, - ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_object_t, - new_ext_func_obj_p->u.function.scope_cp)); + + ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, + new_ext_func_obj_p->u.function.scope_cp); + ECMA_SET_NON_NULL_POINTER_TAG (current_ext_func_obj_p->u.function.scope_cp, scope_p, 0); ecma_deref_object (new_constructor_obj_p); continue; }