diff --git a/src/globals.h b/src/globals.h index bd0e1d6ef..bcc9fa1e4 100644 --- a/src/globals.h +++ b/src/globals.h @@ -164,57 +164,4 @@ extern void __noreturn jerry_exit (jerry_status_t code); #define JERRY_MIN(v1, v2) ((v1 < v2) ? v1 : v2) #define JERRY_MAX(v1, v2) ((v1 < v2) ? v2 : v1) -/** - * Bit-fields - */ -inline uint32_t jerry_extract_bit_field (uint32_t value, uint32_t lsb, - uint32_t width); -inline uint32_t jerry_set_bit_field_value (uint32_t value, uint32_t bit_field_value, - uint32_t lsb, uint32_t width); - -/** - * Extract a bit-field from the integer. - * - * @return bit-field's value - */ -inline uint32_t -jerry_extract_bit_field (uint32_t - container, /**< container to extract bit-field from */ - uint32_t lsb, /**< least significant bit of the value - * to be extracted */ - uint32_t width) /**< width of the bit-field to be extracted */ -{ - JERRY_ASSERT (lsb < JERRY_BITSINBYTE * sizeof (uint32_t)); - JERRY_ASSERT ((lsb + width) <= JERRY_BITSINBYTE * sizeof (uint32_t)); - - uint32_t shifted_value = container >> lsb; - uint32_t bit_field_mask = (1u << width) - 1; - - return (shifted_value & bit_field_mask); -} /* jerry_extract_bit_field */ - -/** - * Extract a bit-field from the integer. - * - * @return bit-field's value - */ -inline uint32_t -jerry_set_bit_field_value (uint32_t - container, /**< container to insert bit-field to */ - uint32_t new_bit_field_value, /**< value of bit-field to insert */ - uint32_t lsb, /**< least significant bit of the value - * to be extracted */ - uint32_t width) /**< width of the bit-field to be extracted */ -{ - JERRY_ASSERT (lsb < JERRY_BITSINBYTE * sizeof (uint32_t)); - JERRY_ASSERT ((lsb + width) <= JERRY_BITSINBYTE * sizeof (uint32_t)); - JERRY_ASSERT (new_bit_field_value <= (1u << width)); - - uint32_t bit_field_mask = (1u << width) - 1; - uint32_t shifted_bit_field_mask = bit_field_mask << lsb; - uint32_t shifted_new_bit_field_value = new_bit_field_value << lsb; - - return (container & ~shifted_bit_field_mask) | shifted_new_bit_field_value; -} /* jerry_set_bit_field_value */ - #endif /* !JERRY_GLOBALS_H */ diff --git a/src/libecmaobjects/ecma-alloc.c b/src/libecmaobjects/ecma-alloc.c index 35d4f9e4b..92b17d8ca 100644 --- a/src/libecmaobjects/ecma-alloc.c +++ b/src/libecmaobjects/ecma-alloc.c @@ -19,16 +19,17 @@ #include "ecma-gc.h" #include "mem-poolman.h" -JERRY_STATIC_ASSERT(sizeof (ecma_value_t) <= sizeof (uint16_t)); -JERRY_STATIC_ASSERT(sizeof (ecma_property_t) <= sizeof (uint64_t)); +JERRY_STATIC_ASSERT (sizeof (ecma_value_t) <= sizeof (uint16_t)); +JERRY_STATIC_ASSERT (sizeof (ecma_property_t) <= sizeof (uint64_t)); -FIXME(Pack ecma_object_t) -JERRY_STATIC_ASSERT(sizeof (ecma_object_t) <= 2 * sizeof (uint64_t)); +JERRY_STATIC_ASSERT (sizeof (ecma_object_t) <= sizeof (uint64_t)); +JERRY_STATIC_ASSERT (ECMA_OBJECT_OBJ_TYPE_SIZE <= sizeof (uint64_t) * JERRY_BITSINBYTE); +JERRY_STATIC_ASSERT (ECMA_OBJECT_LEX_ENV_TYPE_SIZE <= sizeof (uint64_t) * JERRY_BITSINBYTE); -JERRY_STATIC_ASSERT(sizeof (ecma_collection_header_t) == sizeof (uint64_t)); -JERRY_STATIC_ASSERT(sizeof (ecma_collection_chunk_t) == sizeof (uint64_t)); -JERRY_STATIC_ASSERT(sizeof (ecma_string_t) == sizeof (uint64_t)); -JERRY_STATIC_ASSERT(sizeof (ecma_completion_value_t) == sizeof (uint32_t)); +JERRY_STATIC_ASSERT (sizeof (ecma_collection_header_t) == sizeof (uint64_t)); +JERRY_STATIC_ASSERT (sizeof (ecma_collection_chunk_t) == sizeof (uint64_t)); +JERRY_STATIC_ASSERT (sizeof (ecma_string_t) == sizeof (uint64_t)); +JERRY_STATIC_ASSERT (sizeof (ecma_completion_value_t) == sizeof (uint32_t)); /** \addtogroup ecma ---TODO--- * @{ diff --git a/src/libecmaobjects/ecma-gc.c b/src/libecmaobjects/ecma-gc.c index 859e1e71e..9dacba0da 100644 --- a/src/libecmaobjects/ecma-gc.c +++ b/src/libecmaobjects/ecma-gc.c @@ -30,6 +30,7 @@ #include "ecma-helpers.h" #include "globals.h" #include "jerry-libc.h" +#include "jrt-bit-fields.h" /** * Global lists of objects sorted by generation identifier. @@ -47,7 +48,9 @@ ecma_gc_get_object_refs (ecma_object_t *object_p) /**< object */ { JERRY_ASSERT (object_p != NULL); - return object_p->gc_info.refs; + return (uint32_t) jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_GC_REFS_POS, + ECMA_OBJECT_GC_REFS_WIDTH); } /* ecma_gc_get_object_refs */ /** @@ -59,9 +62,10 @@ ecma_gc_set_object_refs (ecma_object_t *object_p, /**< object */ { JERRY_ASSERT (object_p != NULL); - object_p->gc_info.refs = refs & ((1u << CONFIG_ECMA_REFERENCE_COUNTER_WIDTH) - 1); - - JERRY_ASSERT (object_p->gc_info.refs == refs); + object_p->container = jrt_set_bit_field_value (object_p->container, + refs, + ECMA_OBJECT_GC_REFS_POS, + ECMA_OBJECT_GC_REFS_WIDTH); } /* ecma_gc_set_object_refs */ /** @@ -72,7 +76,13 @@ ecma_gc_get_object_generation (ecma_object_t *object_p) /**< object */ { JERRY_ASSERT (object_p != NULL); - return object_p->gc_info.generation; + ecma_gc_gen_t ret = (ecma_gc_gen_t) jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_GC_GENERATION_POS, + ECMA_OBJECT_GC_GENERATION_WIDTH); + + JERRY_ASSERT (ret < ECMA_GC_GEN_COUNT); + + return ret; } /* ecma_gc_get_object_generation */ /** @@ -85,7 +95,10 @@ ecma_gc_set_object_generation (ecma_object_t *object_p, /**< object */ JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (generation < ECMA_GC_GEN_COUNT); - object_p->gc_info.generation = generation; + object_p->container = jrt_set_bit_field_value (object_p->container, + generation, + ECMA_OBJECT_GC_GENERATION_POS, + ECMA_OBJECT_GC_GENERATION_WIDTH); } /* ecma_gc_set_object_generation */ /** @@ -96,7 +109,12 @@ ecma_gc_get_object_next (ecma_object_t *object_p) /**< object */ { JERRY_ASSERT (object_p != NULL); - return ECMA_GET_POINTER (object_p->gc_info.next_cp); + JERRY_ASSERT (sizeof (uintptr_t) * JERRY_BITSINBYTE >= ECMA_OBJECT_PROPERTIES_CP_WIDTH); + uintptr_t next_cp = (uintptr_t) jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_GC_NEXT_CP_POS, + ECMA_OBJECT_GC_NEXT_CP_WIDTH); + + return ECMA_GET_POINTER (next_cp); } /* ecma_gc_get_object_next */ /** @@ -108,7 +126,14 @@ ecma_gc_set_object_next (ecma_object_t *object_p, /**< object */ { JERRY_ASSERT (object_p != NULL); - ECMA_SET_POINTER (object_p->gc_info.next_cp, next_object_p); + uintptr_t next_cp; + ECMA_SET_POINTER (next_cp, next_object_p); + + JERRY_ASSERT (sizeof (uintptr_t) * JERRY_BITSINBYTE >= ECMA_OBJECT_PROPERTIES_CP_WIDTH); + object_p->container = jrt_set_bit_field_value (object_p->container, + next_cp, + ECMA_OBJECT_GC_NEXT_CP_POS, + ECMA_OBJECT_GC_NEXT_CP_WIDTH); } /* ecma_gc_set_object_next */ /** @@ -119,7 +144,9 @@ ecma_gc_is_object_visited (ecma_object_t *object_p) /**< object */ { JERRY_ASSERT (object_p != NULL); - return object_p->gc_info.visited; + return jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_GC_VISITED_POS, + ECMA_OBJECT_GC_VISITED_WIDTH); } /* ecma_gc_is_object_visited */ /** @@ -131,7 +158,10 @@ ecma_gc_set_object_visited (ecma_object_t *object_p, /**< object */ { JERRY_ASSERT (object_p != NULL); - object_p->gc_info.visited = is_visited; + object_p->container = jrt_set_bit_field_value (object_p->container, + is_visited, + ECMA_OBJECT_GC_VISITED_POS, + ECMA_OBJECT_GC_VISITED_WIDTH); } /* ecma_gc_set_object_visited */ /** @@ -142,7 +172,9 @@ ecma_gc_is_object_may_ref_younger_objects (ecma_object_t *object_p) /**< object { JERRY_ASSERT (object_p != NULL); - return object_p->gc_info.may_ref_younger_objects; + return jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_GC_REFS_POS, + ECMA_OBJECT_GC_REFS_WIDTH); } /* ecma_gc_is_object_may_ref_younger_objects */ /** @@ -154,7 +186,10 @@ ecma_gc_set_object_may_ref_younger_objects (ecma_object_t *object_p, /**< object { JERRY_ASSERT (object_p != NULL); - object_p->gc_info.may_ref_younger_objects = is_may_ref_younger_objects; + object_p->container = jrt_set_bit_field_value (object_p->container, + is_may_ref_younger_objects, + ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS, + ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH); } /* ecma_gc_set_object_may_ref_younger_objects */ /** @@ -362,9 +397,9 @@ ecma_gc_mark (ecma_object_t *object_p, /**< start object */ } case ECMA_INTERNAL_PROPERTY_PROTOTYPE: /* the property's value is located in ecma_object_t - (see above in the routine) */ + (see above in the routine) */ case ECMA_INTERNAL_PROPERTY_EXTENSIBLE: /* the property's value is located in ecma_object_t - (see above in the routine) */ + (see above in the routine) */ { JERRY_UNREACHABLE(); } diff --git a/src/libecmaobjects/ecma-globals.h b/src/libecmaobjects/ecma-globals.h index 418b44ffd..cd0414e24 100644 --- a/src/libecmaobjects/ecma-globals.h +++ b/src/libecmaobjects/ecma-globals.h @@ -282,39 +282,6 @@ typedef struct ecma_property_t } u; } ecma_property_t; -/** - * Description of GC's information layout - */ -typedef struct -{ - /** - * Reference counter of the object. - * - * Number of references to the object from stack variables. - */ - unsigned int refs : CONFIG_ECMA_REFERENCE_COUNTER_WIDTH; - - /** - * Identifier of GC generation. - */ - unsigned int generation : 2; - - /** - * Compressed pointer to next object in the global list of objects with same generation. - */ - unsigned int next_cp : ECMA_POINTER_FIELD_WIDTH; - - /** - * Marker that is set if the object was visited during graph traverse. - */ - unsigned int visited : 1; - - /** - * Flag indicating that the object may reference objects of younger generations in its properties. - */ - unsigned int may_ref_younger_objects : 1; -} __packed ecma_gc_info_t; - /** * Types of lexical environments */ @@ -363,57 +330,116 @@ typedef enum * Description of ECMA-object or lexical environment * (depending on is_lexical_environment). */ -typedef struct ecma_object_t +typedef struct { - /** Compressed pointer to property list */ - unsigned int properties_cp : ECMA_POINTER_FIELD_WIDTH; +/* Common part for objects and lexical environments */ - /** Flag indicating whether it is a general object (false) - or a lexical environment (true) */ - unsigned int is_lexical_environment : 1; +/** + * Compressed pointer to property list + */ +#define ECMA_OBJECT_PROPERTIES_CP_POS (0) +#define ECMA_OBJECT_PROPERTIES_CP_WIDTH (ECMA_POINTER_FIELD_WIDTH) - /** - * Attributes of either general object or lexical environment - * (depending on is_lexical_environment) - */ - union - { - /** - * A general object's attributes (if !is_lexical_environment) - */ - struct - { - /** Attribute 'Extensible' */ - unsigned int extensible : 1; +/** + * Flag indicating whether it is a general object (false) + * or a lexical environment (true) + */ +#define ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_POS (ECMA_OBJECT_PROPERTIES_CP_POS + \ + ECMA_OBJECT_PROPERTIES_CP_WIDTH) +#define ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_WIDTH (1) - /** Implementation internal object type (ecma_object_type_t) */ - unsigned int type : 3; +/** + * Reference counter of the object, i.e. number of references + * to the object from stack variables. + */ +#define ECMA_OBJECT_GC_REFS_POS (ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_POS + \ + ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_WIDTH) +#define ECMA_OBJECT_GC_REFS_WIDTH (CONFIG_ECMA_REFERENCE_COUNTER_WIDTH) - /** Compressed pointer to prototype object (ecma_object_t) */ - unsigned int prototype_object_cp : ECMA_POINTER_FIELD_WIDTH; - } __packed object; +/** + * Identifier of GC generation. + */ +#define ECMA_OBJECT_GC_GENERATION_POS (ECMA_OBJECT_GC_REFS_POS + \ + ECMA_OBJECT_GC_REFS_WIDTH) +#define ECMA_OBJECT_GC_GENERATION_WIDTH (2) - /** - * A lexical environment's attribute (if is_lexical_environment) - */ - struct - { - /** - * Type of lexical environment (ecma_lexical_environment_type_t). - */ - unsigned int type : 1; +/** + * Compressed pointer to next object in the global list of objects with same generation. + */ +#define ECMA_OBJECT_GC_NEXT_CP_POS (ECMA_OBJECT_GC_GENERATION_POS + \ + ECMA_OBJECT_GC_GENERATION_WIDTH) +#define ECMA_OBJECT_GC_NEXT_CP_WIDTH (ECMA_POINTER_FIELD_WIDTH) - /** Compressed pointer to outer lexical environment */ - unsigned int outer_reference_cp : ECMA_POINTER_FIELD_WIDTH; - } __packed lexical_environment; +/** + * Marker that is set if the object was visited during graph traverse. + */ +#define ECMA_OBJECT_GC_VISITED_POS (ECMA_OBJECT_GC_NEXT_CP_POS + \ + ECMA_OBJECT_GC_NEXT_CP_WIDTH) +#define ECMA_OBJECT_GC_VISITED_WIDTH (1) - } __packed u; +/** + * Flag indicating that the object may reference objects of younger generations in its properties. + */ +#define ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS (ECMA_OBJECT_GC_VISITED_POS + \ + ECMA_OBJECT_GC_VISITED_WIDTH) +#define ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH (1) - /** GC's information */ - ecma_gc_info_t gc_info; - FIXME(Remove aligned attribute after packing the struct) -} __packed __attribute__ ((aligned (16))) ecma_object_t; +/* Objects' only part */ + +/** + * Attribute 'Extensible' + */ +#define ECMA_OBJECT_OBJ_EXTENSIBLE_POS (ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS + \ + ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH) +#define ECMA_OBJECT_OBJ_EXTENSIBLE_WIDTH (1) + +/** + * Implementation internal object type (ecma_object_type_t) + */ +#define ECMA_OBJECT_OBJ_TYPE_POS (ECMA_OBJECT_OBJ_EXTENSIBLE_POS + \ + ECMA_OBJECT_OBJ_EXTENSIBLE_WIDTH) +#define ECMA_OBJECT_OBJ_TYPE_WIDTH (3) + +/** + * Compressed pointer to prototype object (ecma_object_t) + */ +#define ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_POS (ECMA_OBJECT_OBJ_TYPE_POS + \ + ECMA_OBJECT_OBJ_TYPE_WIDTH) +#define ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_WIDTH (ECMA_POINTER_FIELD_WIDTH) + +/** + * Size of structure for objects + */ +#define ECMA_OBJECT_OBJ_TYPE_SIZE (ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_POS + \ + ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_WIDTH) + + +/* Lexical environments' only part */ + +/** + * Type of lexical environment (ecma_lexical_environment_type_t). + */ +#define ECMA_OBJECT_LEX_ENV_TYPE_POS (ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS + \ + ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH) +#define ECMA_OBJECT_LEX_ENV_TYPE_WIDTH (1) + +/** + * Compressed pointer to outer lexical environment + */ +#define ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_POS (ECMA_OBJECT_LEX_ENV_TYPE_POS + \ + ECMA_OBJECT_LEX_ENV_TYPE_WIDTH) +#define ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_WIDTH (ECMA_POINTER_FIELD_WIDTH) + +/** + * Size of structure for lexical environments + */ +#define ECMA_OBJECT_LEX_ENV_TYPE_SIZE (ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_POS + \ + ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_WIDTH) + + uint64_t container; /**< container for fields described above */ +} ecma_object_t; + /** * Description of ECMA property descriptor diff --git a/src/libecmaobjects/ecma-helpers.c b/src/libecmaobjects/ecma-helpers.c index a19311cfb..611893742 100644 --- a/src/libecmaobjects/ecma-helpers.c +++ b/src/libecmaobjects/ecma-helpers.c @@ -24,6 +24,7 @@ #include "ecma-gc.h" #include "ecma-globals.h" #include "ecma-helpers.h" +#include "jrt-bit-fields.h" /** * Create an object with specified prototype object @@ -42,12 +43,30 @@ ecma_create_object (ecma_object_t *prototype_object_p, /**< pointer to prototybe ecma_object_t *object_p = ecma_alloc_object (); ecma_init_gc_info (object_p); - object_p->properties_cp = ECMA_NULL_POINTER; - object_p->is_lexical_environment = false; + object_p->container = jrt_set_bit_field_value (object_p->container, + ECMA_NULL_POINTER, + ECMA_OBJECT_PROPERTIES_CP_POS, + ECMA_OBJECT_PROPERTIES_CP_WIDTH); + object_p->container = jrt_set_bit_field_value (object_p->container, + false, + ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_POS, + ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_WIDTH); + object_p->container = jrt_set_bit_field_value (object_p->container, + is_extensible, + ECMA_OBJECT_OBJ_EXTENSIBLE_POS, + ECMA_OBJECT_OBJ_EXTENSIBLE_WIDTH); + object_p->container = jrt_set_bit_field_value (object_p->container, + type, + ECMA_OBJECT_OBJ_TYPE_POS, + ECMA_OBJECT_OBJ_TYPE_WIDTH); - object_p->u.object.extensible = is_extensible; - ECMA_SET_POINTER(object_p->u.object.prototype_object_cp, prototype_object_p); - object_p->u.object.type = type; + uint64_t prototype_object_cp; + ECMA_SET_POINTER (prototype_object_cp, prototype_object_p); + + object_p->container = jrt_set_bit_field_value (object_p->container, + prototype_object_cp, + ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_POS, + ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_WIDTH); return object_p; } /* ecma_create_object */ @@ -68,12 +87,26 @@ ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p) /**< outer ecma_object_t *new_lexical_environment_p = ecma_alloc_object (); ecma_init_gc_info (new_lexical_environment_p); - new_lexical_environment_p->is_lexical_environment = true; - new_lexical_environment_p->u.lexical_environment.type = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE; + new_lexical_environment_p->container = jrt_set_bit_field_value (new_lexical_environment_p->container, + ECMA_NULL_POINTER, + ECMA_OBJECT_PROPERTIES_CP_POS, + ECMA_OBJECT_PROPERTIES_CP_WIDTH); + new_lexical_environment_p->container = jrt_set_bit_field_value (new_lexical_environment_p->container, + true, + ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_POS, + ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_WIDTH); - new_lexical_environment_p->properties_cp = ECMA_NULL_POINTER; + new_lexical_environment_p->container = jrt_set_bit_field_value (new_lexical_environment_p->container, + ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE, + ECMA_OBJECT_LEX_ENV_TYPE_POS, + ECMA_OBJECT_LEX_ENV_TYPE_WIDTH); - ECMA_SET_POINTER(new_lexical_environment_p->u.lexical_environment.outer_reference_cp, outer_lexical_environment_p); + uint64_t outer_reference_cp; + ECMA_SET_POINTER (outer_reference_cp, outer_lexical_environment_p); + new_lexical_environment_p->container = jrt_set_bit_field_value (new_lexical_environment_p->container, + outer_reference_cp, + ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_POS, + ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_WIDTH); return new_lexical_environment_p; } /* ecma_create_decl_lex_env */ @@ -99,12 +132,26 @@ ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< out ecma_object_t *new_lexical_environment_p = ecma_alloc_object (); ecma_init_gc_info (new_lexical_environment_p); - new_lexical_environment_p->is_lexical_environment = true; - new_lexical_environment_p->u.lexical_environment.type = ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND; + new_lexical_environment_p->container = jrt_set_bit_field_value (new_lexical_environment_p->container, + ECMA_NULL_POINTER, + ECMA_OBJECT_PROPERTIES_CP_POS, + ECMA_OBJECT_PROPERTIES_CP_WIDTH); + new_lexical_environment_p->container = jrt_set_bit_field_value (new_lexical_environment_p->container, + true, + ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_POS, + ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_WIDTH); - new_lexical_environment_p->properties_cp = ECMA_NULL_POINTER; + new_lexical_environment_p->container = jrt_set_bit_field_value (new_lexical_environment_p->container, + ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND, + ECMA_OBJECT_LEX_ENV_TYPE_POS, + ECMA_OBJECT_LEX_ENV_TYPE_WIDTH); - ECMA_SET_POINTER(new_lexical_environment_p->u.lexical_environment.outer_reference_cp, outer_lexical_environment_p); + uint64_t outer_reference_cp; + ECMA_SET_POINTER (outer_reference_cp, outer_lexical_environment_p); + new_lexical_environment_p->container = jrt_set_bit_field_value (new_lexical_environment_p->container, + outer_reference_cp, + ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_POS, + ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_WIDTH); ecma_property_t *provide_this_prop_p = ecma_create_internal_property (new_lexical_environment_p, ECMA_INTERNAL_PROPERTY_PROVIDE_THIS); @@ -127,7 +174,9 @@ ecma_is_lexical_environment (ecma_object_t *object_p) /**< object or lexical env { JERRY_ASSERT (object_p != NULL); - return object_p->is_lexical_environment; + return jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_POS, + ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_WIDTH); } /* ecma_is_lexical_environment */ /** @@ -139,7 +188,9 @@ ecma_get_object_extensible (ecma_object_t *object_p) /**< object */ JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); - return object_p->u.object.extensible; + return jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_OBJ_EXTENSIBLE_POS, + ECMA_OBJECT_OBJ_EXTENSIBLE_WIDTH); } /* ecma_get_object_extensible */ /** @@ -152,7 +203,10 @@ ecma_set_object_extensible (ecma_object_t *object_p, /**< object */ JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); - object_p->u.object.extensible = is_extensible; + object_p->container = jrt_set_bit_field_value (object_p->container, + is_extensible, + ECMA_OBJECT_OBJ_EXTENSIBLE_POS, + ECMA_OBJECT_OBJ_EXTENSIBLE_WIDTH); } /* ecma_set_object_extensible */ /** @@ -164,7 +218,9 @@ ecma_get_object_type (ecma_object_t *object_p) /**< object */ JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); - return object_p->u.object.type; + return jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_OBJ_TYPE_POS, + ECMA_OBJECT_OBJ_TYPE_WIDTH); } /* ecma_get_object_type */ /** @@ -177,7 +233,10 @@ ecma_set_object_type (ecma_object_t *object_p, /**< object */ JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); - object_p->u.object.type = type; + object_p->container = jrt_set_bit_field_value (object_p->container, + type, + ECMA_OBJECT_OBJ_TYPE_POS, + ECMA_OBJECT_OBJ_TYPE_WIDTH); } /* ecma_set_object_type */ /** @@ -189,7 +248,11 @@ ecma_get_object_prototype (ecma_object_t *object_p) /**< object */ JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); - return (ecma_object_t*) ECMA_GET_POINTER (object_p->u.object.prototype_object_cp); + JERRY_ASSERT (sizeof (uintptr_t) * JERRY_BITSINBYTE >= ECMA_OBJECT_PROPERTIES_CP_WIDTH); + uintptr_t prototype_object_cp = (uintptr_t) jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_POS, + ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_WIDTH); + return ECMA_GET_POINTER (prototype_object_cp); } /* ecma_get_object_prototype */ /** @@ -201,7 +264,9 @@ ecma_get_lex_env_type (ecma_object_t *object_p) /**< lexical environment */ JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (ecma_is_lexical_environment (object_p)); - return (ecma_lexical_environment_type_t) object_p->u.lexical_environment.type; + return jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_LEX_ENV_TYPE_POS, + ECMA_OBJECT_LEX_ENV_TYPE_WIDTH); } /* ecma_get_lex_env_type */ /** @@ -213,7 +278,11 @@ ecma_get_lex_env_outer_reference (ecma_object_t *object_p) /**< lexical environm JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (ecma_is_lexical_environment (object_p)); - return (ecma_object_t*) ECMA_GET_POINTER (object_p->u.lexical_environment.outer_reference_cp); + JERRY_ASSERT (sizeof (uintptr_t) * JERRY_BITSINBYTE >= ECMA_OBJECT_PROPERTIES_CP_WIDTH); + uintptr_t outer_reference_cp = (uintptr_t) jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_POS, + ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_WIDTH); + return ECMA_GET_POINTER (outer_reference_cp); } /* ecma_get_lex_env_outer_reference */ /** @@ -224,9 +293,31 @@ ecma_get_property_list (ecma_object_t *object_p) /**< object or lexical environm { JERRY_ASSERT (object_p != NULL); - return (ecma_property_t*) ECMA_GET_POINTER (object_p->properties_cp); + JERRY_ASSERT (sizeof (uintptr_t) * JERRY_BITSINBYTE >= ECMA_OBJECT_PROPERTIES_CP_WIDTH); + uintptr_t properties_cp = (uintptr_t) jrt_extract_bit_field (object_p->container, + ECMA_OBJECT_PROPERTIES_CP_POS, + ECMA_OBJECT_PROPERTIES_CP_WIDTH); + return ECMA_GET_POINTER (properties_cp); } /* ecma_get_property_list */ +/** + * Set object's/lexical environment's property list. + */ +static void +ecma_set_property_list (ecma_object_t *object_p, /**< object or lexical environment */ + ecma_property_t *property_list_p) /**< properties' list */ +{ + JERRY_ASSERT (object_p != NULL); + + uint64_t properties_cp; + ECMA_SET_POINTER (properties_cp, property_list_p); + + object_p->container = jrt_set_bit_field_value (object_p->container, + properties_cp, + ECMA_OBJECT_PROPERTIES_CP_POS, + ECMA_OBJECT_PROPERTIES_CP_WIDTH); +} /* ecma_set_property_list */ + /** * Create internal property in an object and link it into * the object's properties' linked-list (at start of the list). @@ -241,9 +332,9 @@ ecma_create_internal_property (ecma_object_t *object_p, /**< the object */ new_property_p->type = ECMA_PROPERTY_INTERNAL; - ecma_property_t *list_head_p = ECMA_GET_POINTER(object_p->properties_cp); + ecma_property_t *list_head_p = ecma_get_property_list (object_p); ECMA_SET_POINTER(new_property_p->next_property_p, list_head_p); - ECMA_SET_NON_NULL_POINTER(object_p->properties_cp, new_property_p); + ecma_set_property_list (object_p, new_property_p); new_property_p->u.internal_property.type = property_id; new_property_p->u.internal_property.value = ECMA_NULL_POINTER; @@ -329,10 +420,10 @@ ecma_create_named_data_property (ecma_object_t *obj_p, /**< object */ prop_p->u.named_data_property.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - ecma_property_t *list_head_p = ECMA_GET_POINTER(obj_p->properties_cp); + ecma_property_t *list_head_p = ecma_get_property_list (obj_p); ECMA_SET_POINTER(prop_p->next_property_p, list_head_p); - ECMA_SET_NON_NULL_POINTER(obj_p->properties_cp, prop_p); + ecma_set_property_list (obj_p, prop_p); return prop_p; } /* ecma_create_named_data_property */ @@ -368,9 +459,9 @@ ecma_create_named_accessor_property (ecma_object_t *obj_p, /**< object */ prop_p->u.named_accessor_property.enumerable = enumerable; prop_p->u.named_accessor_property.configurable = configurable; - ecma_property_t *list_head_p = ECMA_GET_POINTER(obj_p->properties_cp); + ecma_property_t *list_head_p = ecma_get_property_list (obj_p); ECMA_SET_POINTER(prop_p->next_property_p, list_head_p); - ECMA_SET_NON_NULL_POINTER(obj_p->properties_cp, prop_p); + ecma_set_property_list (obj_p, prop_p); return prop_p; } /* ecma_create_named_accessor_property */ @@ -577,7 +668,7 @@ void ecma_delete_property (ecma_object_t *obj_p, /**< object */ ecma_property_t *prop_p) /**< property */ { - for (ecma_property_t *cur_prop_p = ECMA_GET_POINTER(obj_p->properties_cp), *prev_prop_p = NULL, *next_prop_p; + for (ecma_property_t *cur_prop_p = ecma_get_property_list (obj_p), *prev_prop_p = NULL, *next_prop_p; cur_prop_p != NULL; prev_prop_p = cur_prop_p, cur_prop_p = next_prop_p) { @@ -589,7 +680,7 @@ ecma_delete_property (ecma_object_t *obj_p, /**< object */ if (prev_prop_p == NULL) { - ECMA_SET_POINTER(obj_p->properties_cp, next_prop_p); + ecma_set_property_list (obj_p, next_prop_p); } else { diff --git a/src/libecmaoperations/ecma-lex-env.c b/src/libecmaoperations/ecma-lex-env.c index a2abc89e1..2452249ad 100644 --- a/src/libecmaoperations/ecma-lex-env.c +++ b/src/libecmaoperations/ecma-lex-env.c @@ -517,7 +517,7 @@ ecma_is_lexical_environment_global (ecma_object_t *lex_env_p) /**< lexical envir JERRY_ASSERT(lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); - ecma_lexical_environment_type_t type = lex_env_p->u.lexical_environment.type; + ecma_lexical_environment_type_t type = ecma_get_lex_env_type (lex_env_p); bool ret_value = false; diff --git a/src/libruntime/jrt-bit-fields.c b/src/libruntime/jrt-bit-fields.c new file mode 100644 index 000000000..0f0870db8 --- /dev/null +++ b/src/libruntime/jrt-bit-fields.c @@ -0,0 +1,60 @@ +/* Copyright 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "globals.h" +#include "jrt-bit-fields.h" + +/** + * Extract a bit-field from the integer. + * + * @return bit-field's value + */ +extern uint64_t +jrt_extract_bit_field (uint64_t container, /**< container to extract bit-field from */ + uint32_t lsb, /**< least significant bit of the value + * to be extracted */ + uint32_t width) /**< width of the bit-field to be extracted */ +{ + JERRY_ASSERT (lsb < JERRY_BITSINBYTE * sizeof (uint64_t)); + JERRY_ASSERT ((lsb + width) <= JERRY_BITSINBYTE * sizeof (uint64_t)); + + uint64_t shifted_value = container >> lsb; + uint64_t bit_field_mask = (1ull << width) - 1; + + return (shifted_value & bit_field_mask); +} /* jrt_extract_bit_field */ + +/** + * Extract a bit-field from the integer. + * + * @return bit-field's value + */ +extern uint64_t +jrt_set_bit_field_value (uint64_t container, /**< container to insert bit-field to */ + uint64_t new_bit_field_value, /**< value of bit-field to insert */ + uint32_t lsb, /**< least significant bit of the value + * to be extracted */ + uint32_t width) /**< width of the bit-field to be extracted */ +{ + JERRY_ASSERT (lsb < JERRY_BITSINBYTE * sizeof (uint64_t)); + JERRY_ASSERT ((lsb + width) <= JERRY_BITSINBYTE * sizeof (uint64_t)); + JERRY_ASSERT (new_bit_field_value <= (1ull << width)); + + uint64_t bit_field_mask = (1ull << width) - 1; + uint64_t shifted_bit_field_mask = bit_field_mask << lsb; + uint64_t shifted_new_bit_field_value = new_bit_field_value << lsb; + + return (container & ~shifted_bit_field_mask) | shifted_new_bit_field_value; +} /* jrt_set_bit_field_value */ diff --git a/src/libruntime/jrt-bit-fields.h b/src/libruntime/jrt-bit-fields.h new file mode 100644 index 000000000..34112409b --- /dev/null +++ b/src/libruntime/jrt-bit-fields.h @@ -0,0 +1,24 @@ +/* Copyright 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRY_BIT_FIELDS_H +#define JERRY_BIT_FIELDS_H + +extern uint64_t jrt_extract_bit_field (uint64_t value, uint32_t lsb, + uint32_t width); +extern uint64_t jrt_set_bit_field_value (uint64_t value, uint64_t bit_field_value, + uint32_t lsb, uint32_t width); + +#endif /* !JERRY_BIT_FIELDS_H */