Skip to content

Add 32 bit compressed pointer support. #1271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 1, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions docs/04.INTERNALS.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,11 @@ Compressed pointers were introduced to save heap space.

![Compressed Pointer](img/ecma_compressed.png)

These pointers are 8 byte aligned 16 bit long pointers which can address 512 Kb of memory which is also the maximum size of the JerryScript heap.

ECMA data elements are allocated in pools (pools are allocated on heap)
Chunk size of the pool is 8 bytes (reduces fragmentation).
These pointers are 8 byte aligned 16 bit long pointers which can address 512 Kb of
memory which is also the maximum size of the JerryScript heap. To support even more
memory the size of compressed pointers can be extended to 32 bit to cover the entire
address space of a 32 bit system by passing "--cpointer_32_bit on" to the build
system. These "uncompressed pointers" increases the memory consumption by around 20%.

### Number

Expand Down
7 changes: 7 additions & 0 deletions jerry-core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ set(FEATURE_PROFILE "full" CACHE STRING "Profile types: full, minimal")
set(FEATURE_ERROR_MESSAGES OFF CACHE BOOL "Enable error messages?")
set(FEATURE_VALGRIND OFF CACHE BOOL "Enable Valgrind support?")
set(FEATURE_VALGRIND_FREYA OFF CACHE BOOL "Enable Valgrind-Freya support?")
set(FEATURE_CPOINTER_32_BIT OFF CACHE BOOL "Enable 32 bit compressed pointers?")
set(FEATURE_MEM_STRESS_TEST OFF CACHE BOOL "Enable mem-stress test?")
set(FEATURE_MEM_STATS OFF CACHE BOOL "Enable memory statistics?")
set(FEATURE_PARSER_DUMP OFF CACHE BOOL "Enable parser byte-code dumps?")
Expand All @@ -35,6 +36,7 @@ message(STATUS "FEATURE_PROFILE " ${FEATURE_PROFILE})
message(STATUS "FEATURE_ERROR_MESSAGES " ${FEATURE_ERROR_MESSAGES})
message(STATUS "FEATURE_VALGRIND " ${FEATURE_VALGRIND})
message(STATUS "FEATURE_VALGRIND_FREYA " ${FEATURE_VALGRIND_FREYA})
message(STATUS "FEATURE_CPOINTER_32_BIT " ${FEATURE_CPOINTER_32_BIT})
message(STATUS "FEATURE_MEM_STRESS_TEST " ${FEATURE_MEM_STRESS_TEST})
message(STATUS "FEATURE_MEM_STATS " ${FEATURE_MEM_STATS})
message(STATUS "FEATURE_PARSER_DUMP " ${FEATURE_PARSER_DUMP})
Expand Down Expand Up @@ -182,6 +184,11 @@ if(FEATURE_VALGRIND_FREYA)
set(INCLUDE_CORE ${INCLUDE_CORE} ${INCLUDE_THIRD_PARTY_VALGRIND})
endif()

# Enable 32 bit cpointers
if(FEATURE_CPOINTER_32_BIT)
set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_CPOINTER_32_BIT)
endif()

# Memory management stress-test mode
if(FEATURE_MEM_STRESS_TEST)
set(DEFINES_JERRY ${DEFINES_JERRY} JMEM_GC_BEFORE_EACH_ALLOC)
Expand Down
14 changes: 0 additions & 14 deletions jerry-core/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@
*/
#ifndef CONFIG_MEM_HEAP_AREA_SIZE
# define CONFIG_MEM_HEAP_AREA_SIZE (512 * 1024)
#elif CONFIG_MEM_HEAP_AREA_SIZE > (512 * 1024)
# error "Currently, maximum 512 kilobytes heap size is supported"
#endif /* !CONFIG_MEM_HEAP_AREA_SIZE */

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this may be a bad idea, I think it would be better to add && !JERRY_CPOINTER_32_BIT to the condition instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another assertion is added instead of it.

/**
Expand All @@ -53,18 +51,6 @@
*/
#define CONFIG_MEM_HEAP_DESIRED_LIMIT (JERRY_MIN (CONFIG_MEM_HEAP_AREA_SIZE / 32, CONFIG_MEM_HEAP_MAX_LIMIT))

/**
* Log2 of maximum possible offset in the heap
*
* The option affects size of compressed pointer that in turn
* affects size of ECMA Object Model's data types.
*
* In any case size of any of the types should not exceed CONFIG_MEM_POOL_CHUNK_SIZE.
*
* On the other hand, value 2 ^ CONFIG_MEM_HEAP_OFFSET_LOG should not be less than CONFIG_MEM_HEAP_AREA_SIZE.
*/
#define CONFIG_MEM_HEAP_OFFSET_LOG (19)

/**
* Number of lower bits in key of literal hash table.
*/
Expand Down
24 changes: 6 additions & 18 deletions jerry-core/ecma/base/ecma-alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,9 @@ JERRY_STATIC_ASSERT (sizeof (ecma_property_value_t) == sizeof (ecma_value_t),
size_of_ecma_property_value_t_must_be_equal_to_size_of_ecma_value_t);
JERRY_STATIC_ASSERT (((sizeof (ecma_property_value_t) - 1) & sizeof (ecma_property_value_t)) == 0,
size_of_ecma_property_value_t_must_be_power_of_2);
JERRY_STATIC_ASSERT (sizeof (ecma_property_pair_t) == sizeof (uint64_t) * 2,
size_of_ecma_property_pair_t_must_be_equal_to_16_bytes);

JERRY_STATIC_ASSERT (sizeof (ecma_object_t) <= sizeof (uint64_t),
size_of_ecma_object_t_must_be_less_than_or_equal_to_8_bytes);
JERRY_STATIC_ASSERT (sizeof (ecma_extended_object_t) <= sizeof (uint64_t) * 2,
size_of_ecma_extended_object_t_must_be_less_than_or_equal_to_16_bytes);

JERRY_STATIC_ASSERT (sizeof (ecma_collection_header_t) == sizeof (uint64_t),
size_of_ecma_collection_header_t_must_be_less_than_or_equal_to_8_bytes);
JERRY_STATIC_ASSERT (sizeof (ecma_collection_chunk_t) == sizeof (uint64_t),
size_of_ecma_collection_chunk_t_must_be_less_than_or_equal_to_8_bytes);
JERRY_STATIC_ASSERT (sizeof (ecma_string_t) == sizeof (uint64_t),
size_of_ecma_string_t_must_be_less_than_or_equal_to_8_bytes);
JERRY_STATIC_ASSERT (sizeof (ecma_getter_setter_pointers_t) <= sizeof (uint64_t),
size_of_ecma_getter_setter_pointers_t_must_be_less_than_or_equal_to_8_bytes);

/** \addtogroup ecma ECMA
* @{
Expand All @@ -67,20 +54,21 @@ JERRY_STATIC_ASSERT (sizeof (ecma_getter_setter_pointers_t) <= sizeof (uint64_t)
#define ALLOC(ecma_type) ecma_ ## ecma_type ## _t * \
ecma_alloc_ ## ecma_type (void) \
{ \
ecma_ ## ecma_type ## _t *p ## ecma_type = (ecma_ ## ecma_type ## _t *) jmem_pools_alloc (); \
ecma_ ## ecma_type ## _t *ecma_type ## _p; \
ecma_type ## _p = (ecma_ ## ecma_type ## _t *) jmem_pools_alloc (sizeof (ecma_ ## ecma_type ## _t)); \
\
JERRY_ASSERT (p ## ecma_type != NULL); \
JERRY_ASSERT (ecma_type ## _p != NULL); \
\
return p ## ecma_type; \
return ecma_type ## _p; \
}

/**
* Deallocation routine template
*/
#define DEALLOC(ecma_type) void \
ecma_dealloc_ ## ecma_type (ecma_ ## ecma_type ## _t *p ## ecma_type) \
ecma_dealloc_ ## ecma_type (ecma_ ## ecma_type ## _t *ecma_type ## _p) \
{ \
jmem_pools_free ((uint8_t *) p ## ecma_type); \
jmem_pools_free ((uint8_t *) ecma_type ## _p, sizeof (ecma_ ## ecma_type ## _t)); \
}

/**
Expand Down
11 changes: 11 additions & 0 deletions jerry-core/ecma/base/ecma-globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,16 @@ typedef struct
*/
typedef struct
{
#ifdef JERRY_CPOINTER_32_BIT
jmem_cpointer_t next_property_cp; /**< next cpointer */
#endif /* JERRY_CPOINTER_32_BIT */
ecma_property_t types[ECMA_PROPERTY_PAIR_ITEM_COUNT]; /**< two property type slot. The first represent
* the type of this property (e.g. property pair) */
#ifdef JERRY_CPOINTER_32_BIT
uint16_t padding; /**< an unused value */
#else /* !JERRY_CPOINTER_32_BIT */
jmem_cpointer_t next_property_cp; /**< next cpointer */
#endif /* JERRY_CPOINTER_32_BIT */
} ecma_property_header_t;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain this change? Why did you move the next cpointer on 32 bit?

Copy link
Member Author

@zherczeg zherczeg Aug 31, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because ECMA_PROPERTY_VALUE_PTR expects that the type fields are packed in a 4 byte word, which is followed by maximum of four value words. For 16 bit cpointers the next pointer can be squeezed in the last two bytes of the first word. This is not possible with 32 bit cpointers, where that 16 bit is unused.


/**
Expand All @@ -381,7 +388,11 @@ typedef struct
typedef union
{
ecma_value_t value; /**< value of a property */
#ifdef JERRY_CPOINTER_32_BIT
jmem_cpointer_t getter_setter_pair_cp; /**< cpointer to getter setter pair */
#else /* !JERRY_CPOINTER_32_BIT */
ecma_getter_setter_pointers_t getter_setter_pair; /**< getter setter pair */
#endif /* JERRY_CPOINTER_32_BIT */
} ecma_property_value_t;

/**
Expand Down
5 changes: 2 additions & 3 deletions jerry-core/ecma/base/ecma-helpers-value.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ JERRY_STATIC_ASSERT ((ECMA_VALUE_FULL_MASK + 1) == (1 << ECMA_VALUE_SHIFT),
JERRY_STATIC_ASSERT (ECMA_VALUE_SHIFT <= JMEM_ALIGNMENT_LOG,
ecma_value_shift_must_be_less_than_or_equal_than_mem_alignment_log);

JERRY_STATIC_ASSERT ((sizeof (ecma_value_t) * JERRY_BITSINBYTE)
>= (sizeof (jmem_cpointer_t) * JERRY_BITSINBYTE + ECMA_VALUE_SHIFT),
ecma_value_must_be_large_enough_to_store_compressed_pointers);
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);

#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY

Expand Down
60 changes: 45 additions & 15 deletions jerry-core/ecma/base/ecma-helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,16 @@ ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */
ecma_ref_ecma_string (name_p);

ecma_property_value_t value;
#ifdef JERRY_CPOINTER_32_BIT
ecma_getter_setter_pointers_t *getter_setter_pair_p;
getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t));
ECMA_SET_POINTER (getter_setter_pair_p->getter_p, get_p);
ECMA_SET_POINTER (getter_setter_pair_p->setter_p, set_p);
ECMA_SET_POINTER (value.getter_setter_pair_cp, getter_setter_pair_p);
#else /* !JERRY_CPOINTER_32_BIT */
ECMA_SET_POINTER (value.getter_setter_pair.getter_p, get_p);
ECMA_SET_POINTER (value.getter_setter_pair.setter_p, set_p);
#endif /* JERRY_CPOINTER_32_BIT */

return ecma_create_property (object_p, name_p, type_and_flags, value);
} /* ecma_create_named_accessor_property */
Expand Down Expand Up @@ -763,20 +771,6 @@ ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property
return property_p;
} /* ecma_get_named_data_property */

/**
* Free the named data property and values it references.
*/
static void
ecma_free_named_data_property (ecma_object_t *object_p, /**< object the property belongs to */
ecma_property_t *property_p) /**< the property */
{
JERRY_ASSERT (object_p != NULL);
JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);

ecma_value_t v = ecma_get_named_data_property_value (property_p);
ecma_free_value_if_not_object (v);
} /* ecma_free_named_data_property */

/**
* Free the internal property and values it references.
*/
Expand Down Expand Up @@ -873,7 +867,8 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to
{
case ECMA_PROPERTY_TYPE_NAMEDDATA:
{
ecma_free_named_data_property (object_p, property_p);
ecma_free_value_if_not_object (ecma_get_named_data_property_value (property_p));

if (ecma_is_property_lcached (property_p))
{
ecma_lcache_invalidate (object_p, name_p, property_p);
Expand All @@ -882,6 +877,13 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to
}
case ECMA_PROPERTY_TYPE_NAMEDACCESSOR:
{
#ifdef JERRY_CPOINTER_32_BIT
ecma_getter_setter_pointers_t *getter_setter_pair_p;
getter_setter_pair_p = ECMA_GET_POINTER (ecma_getter_setter_pointers_t,
ECMA_PROPERTY_VALUE_PTR (property_p)->getter_setter_pair_cp);
jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t));
#endif /* JERRY_CPOINTER_32_BIT */

if (ecma_is_property_lcached (property_p))
{
ecma_lcache_invalidate (object_p, name_p, property_p);
Expand Down Expand Up @@ -1083,7 +1085,14 @@ ecma_get_named_accessor_property_getter (const ecma_property_t *prop_p) /**< nam
{
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);

#ifdef JERRY_CPOINTER_32_BIT
ecma_getter_setter_pointers_t *getter_setter_pair_p;
getter_setter_pair_p = ECMA_GET_POINTER (ecma_getter_setter_pointers_t,
ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair_cp);
return ECMA_GET_POINTER (ecma_object_t, getter_setter_pair_p->getter_p);
#else /* !JERRY_CPOINTER_32_BIT */
return ECMA_GET_POINTER (ecma_object_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.getter_p);
#endif /* JERRY_CPOINTER_32_BIT */
} /* ecma_get_named_accessor_property_getter */

/**
Expand All @@ -1096,7 +1105,14 @@ ecma_get_named_accessor_property_setter (const ecma_property_t *prop_p) /**< nam
{
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);

#ifdef JERRY_CPOINTER_32_BIT
ecma_getter_setter_pointers_t *getter_setter_pair_p;
getter_setter_pair_p = ECMA_GET_POINTER (ecma_getter_setter_pointers_t,
ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair_cp);
return ECMA_GET_POINTER (ecma_object_t, getter_setter_pair_p->setter_p);
#else /* !JERRY_CPOINTER_32_BIT */
return ECMA_GET_POINTER (ecma_object_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.setter_p);
#endif /* JERRY_CPOINTER_32_BIT */
} /* ecma_get_named_accessor_property_setter */

/**
Expand All @@ -1110,7 +1126,14 @@ ecma_set_named_accessor_property_getter (ecma_object_t *object_p, /**< the prope
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
ecma_assert_object_contains_the_property (object_p, prop_p);

#ifdef JERRY_CPOINTER_32_BIT
ecma_getter_setter_pointers_t *getter_setter_pair_p;
getter_setter_pair_p = ECMA_GET_POINTER (ecma_getter_setter_pointers_t,
ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair_cp);
ECMA_SET_POINTER (getter_setter_pair_p->getter_p, getter_p);
#else /* !JERRY_CPOINTER_32_BIT */
ECMA_SET_POINTER (ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.getter_p, getter_p);
#endif /* JERRY_CPOINTER_32_BIT */
} /* ecma_set_named_accessor_property_getter */

/**
Expand All @@ -1124,7 +1147,14 @@ ecma_set_named_accessor_property_setter (ecma_object_t *object_p, /**< the prope
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
ecma_assert_object_contains_the_property (object_p, prop_p);

#ifdef JERRY_CPOINTER_32_BIT
ecma_getter_setter_pointers_t *getter_setter_pair_p;
getter_setter_pair_p = ECMA_GET_POINTER (ecma_getter_setter_pointers_t,
ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair_cp);
ECMA_SET_POINTER (getter_setter_pair_p->setter_p, setter_p);
#else /* !JERRY_CPOINTER_32_BIT */
ECMA_SET_POINTER (ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.setter_p, setter_p);
#endif /* JERRY_CPOINTER_32_BIT */
} /* ecma_set_named_accessor_property_setter */

/**
Expand Down
13 changes: 6 additions & 7 deletions jerry-core/ecma/base/ecma-literal-storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@
* @{
*/

JERRY_STATIC_ASSERT (sizeof (ecma_lit_storage_item_t) <= sizeof (uint64_t),
size_of_ecma_lit_storage_item_t_must_be_less_than_or_equal_to_8_bytes);

/**
* Free string list
*/
Expand All @@ -50,7 +47,7 @@ ecma_free_string_list (ecma_lit_storage_item_t *string_list_p) /**< string list

ecma_lit_storage_item_t *prev_item = string_list_p;
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
jmem_pools_free (prev_item);
jmem_pools_free (prev_item, sizeof (ecma_lit_storage_item_t));
}
} /* ecma_free_string_list */

Expand Down Expand Up @@ -115,7 +112,8 @@ ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string
return result;
}

ecma_lit_storage_item_t *new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc ();
ecma_lit_storage_item_t *new_item_p;
new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t));

new_item_p->values[0] = result;
for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
Expand Down Expand Up @@ -182,7 +180,7 @@ ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be
number_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, number_list_p->next_cp);
}

ecma_string_t *string_p = (ecma_string_t *) jmem_pools_alloc ();
ecma_string_t *string_p = (ecma_string_t *) jmem_pools_alloc (sizeof (ecma_string_t));
string_p->refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_LITERAL_NUMBER;
string_p->u.lit_number = num;

Expand All @@ -195,7 +193,8 @@ ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be
return result;
}

ecma_lit_storage_item_t *new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc ();
ecma_lit_storage_item_t *new_item_p;
new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t));

new_item_p->values[0] = result;
for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
Expand Down
5 changes: 4 additions & 1 deletion jerry-core/jcontext/jcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ typedef struct
ecma_object_t *ecma_gc_objects_lists[ECMA_GC_COLOR__COUNT]; /**< List of marked (visited during
* current GC session) and umarked objects */
jmem_heap_free_t *jmem_heap_list_skip_p; /**< This is used to speed up deallocation. */
jmem_pools_chunk_t *jmem_free_chunk_p; /**< list of free pool chunks */
jmem_pools_chunk_t *jmem_free_8_byte_chunk_p; /**< list of free eight byte pool chunks */
#ifdef JERRY_CPOINTER_32_BIT
jmem_pools_chunk_t *jmem_free_16_byte_chunk_p; /**< list of free sixteen byte pool chunks */
#endif /* JERRY_CPOINTER_32_BIT */
jmem_free_unused_memory_callback_t jmem_free_unused_memory_callback; /**< Callback for freeing up memory. */
const lit_utf8_byte_t **lit_magic_string_ex_array; /**< array of external magic strings */
const lit_utf8_size_t *lit_magic_string_ex_sizes; /**< external magic string lengths */
Expand Down
Loading