Add 32 bit compressed pointer support.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2016-09-01 01:44:08 -07:00
parent 9ca78d380f
commit da47dedaed
19 changed files with 271 additions and 173 deletions
+46 -4
View File
@@ -27,6 +27,14 @@
#define JMEM_ALLOCATOR_INTERNAL
#include "jmem-allocator-internal.h"
#ifdef JERRY_CPOINTER_32_BIT
/* This check will go away when we will support 64 bit compressed pointers. */
JERRY_STATIC_ASSERT (sizeof (uintptr_t) <= sizeof (jmem_cpointer_t),
size_of_uintpt_t_must_be_equal_to_jmem_cpointer_t);
#endif
/**
* Initialize memory allocators.
*/
@@ -59,12 +67,29 @@ jmem_finalize ()
*
* @return packed pointer
*/
uintptr_t
inline jmem_cpointer_t __attr_always_inline___
jmem_compress_pointer (const void *pointer_p) /**< pointer to compress */
{
JERRY_ASSERT (pointer_p != NULL);
JERRY_ASSERT (jmem_is_heap_pointer (pointer_p));
return jmem_heap_compress_pointer (pointer_p);
uintptr_t uint_ptr = (uintptr_t) pointer_p;
JERRY_ASSERT (uint_ptr % JMEM_ALIGNMENT == 0);
#ifdef JERRY_CPOINTER_32_BIT
JERRY_ASSERT (((jmem_cpointer_t) uint_ptr) == uint_ptr);
#else /* !JERRY_CPOINTER_32_BIT */
const uintptr_t heap_start = (uintptr_t) &JERRY_HEAP_CONTEXT (first);
uint_ptr -= heap_start;
uint_ptr >>= JMEM_ALIGNMENT_LOG;
JERRY_ASSERT (uint_ptr <= UINT16_MAX);
JERRY_ASSERT (uint_ptr != JMEM_CP_NULL);
#endif /* JERRY_CPOINTER_32_BIT */
return (jmem_cpointer_t) uint_ptr;
} /* jmem_compress_pointer */
/**
@@ -72,10 +97,27 @@ jmem_compress_pointer (const void *pointer_p) /**< pointer to compress */
*
* @return unpacked pointer
*/
void *
inline void * __attr_always_inline___
jmem_decompress_pointer (uintptr_t compressed_pointer) /**< pointer to decompress */
{
return jmem_heap_decompress_pointer (compressed_pointer);
JERRY_ASSERT (compressed_pointer != JMEM_CP_NULL);
uintptr_t uint_ptr = compressed_pointer;
JERRY_ASSERT (((jmem_cpointer_t) uint_ptr) == uint_ptr);
#ifdef JERRY_CPOINTER_32_BIT
JERRY_ASSERT (uint_ptr % JMEM_ALIGNMENT == 0);
#else /* !JERRY_CPOINTER_32_BIT */
const uintptr_t heap_start = (uintptr_t) &JERRY_HEAP_CONTEXT (first);
uint_ptr <<= JMEM_ALIGNMENT_LOG;
uint_ptr += heap_start;
JERRY_ASSERT (jmem_is_heap_pointer ((void *) uint_ptr));
#endif /* JERRY_CPOINTER_32_BIT */
return (void *) uint_ptr;
} /* jmem_decompress_pointer */
/**
+35 -12
View File
@@ -28,10 +28,43 @@
* @{
*/
/**
* Compressed pointer representations
*
* 16 bit representation:
* The jmem_cpointer_t is defined as uint16_t
* and it can contain any sixteen bit value.
*
* 32 bit representation:
* The jmem_cpointer_t is defined as uint32_t.
* The lower JMEM_ALIGNMENT_LOG bits must be zero.
* The other bits can have any value.
*
* The 16 bit representation always encodes an offset from
* a heap base. The 32 bit representation currently encodes
* raw 32 bit JMEM_ALIGNMENT aligned pointers on 32 bit systems.
* This can be extended to encode a 32 bit offset from a heap
* base on 64 bit systems in the future. There are no plans
* to support more than 4G address space for JerryScript.
*/
/**
* Compressed pointer
*/
#ifdef JERRY_CPOINTER_32_BIT
typedef uint32_t jmem_cpointer_t;
#else /* !JERRY_CPOINTER_32_BIT */
typedef uint16_t jmem_cpointer_t;
#endif /* JERRY_CPOINTER_32_BIT */
/**
* Width of compressed memory pointer
*/
#ifdef JERRY_CPOINTER_32_BIT
#define JMEM_CP_WIDTH 32
#else /* !JERRY_CPOINTER_32_BIT */
#define JMEM_CP_WIDTH 16
#endif /* JERRY_CPOINTER_32_BIT */
/**
* Representation of NULL value for compressed pointers
@@ -43,16 +76,6 @@ typedef uint16_t jmem_cpointer_t;
*/
#define JMEM_ALIGNMENT (1u << JMEM_ALIGNMENT_LOG)
/**
* Width of compressed memory pointer
*/
#define JMEM_CP_WIDTH (JMEM_HEAP_OFFSET_LOG - JMEM_ALIGNMENT_LOG)
/**
* Compressed pointer value mask
*/
#define JMEM_CP_MASK ((1ull << JMEM_CP_WIDTH) - 1)
/**
* Severity of a 'try give memory back' request
*
@@ -107,7 +130,7 @@ typedef void (*jmem_free_unused_memory_callback_t) (jmem_free_unused_memory_seve
* to specified non_compressed_pointer
*/
#define JMEM_CP_SET_NON_NULL_POINTER(cp_value, non_compressed_pointer) \
(cp_value) = (jmem_compress_pointer (non_compressed_pointer) & JMEM_CP_MASK)
(cp_value) = jmem_compress_pointer (non_compressed_pointer)
/**
* Set value of compressed pointer so that it will correspond
@@ -131,7 +154,7 @@ typedef void (*jmem_free_unused_memory_callback_t) (jmem_free_unused_memory_seve
extern void jmem_init (void);
extern void jmem_finalize (void);
extern uintptr_t jmem_compress_pointer (const void *);
extern jmem_cpointer_t jmem_compress_pointer (const void *);
extern void *jmem_decompress_pointer (uintptr_t);
extern void jmem_register_free_unused_memory_callback (jmem_free_unused_memory_callback_t);
-10
View File
@@ -18,21 +18,11 @@
#include "config.h"
/**
* Log2 of maximum possible offset in the heap
*/
#define JMEM_HEAP_OFFSET_LOG (CONFIG_MEM_HEAP_OFFSET_LOG)
/**
* Size of heap
*/
#define JMEM_HEAP_SIZE ((size_t) (CONFIG_MEM_HEAP_AREA_SIZE))
/**
* Size of pool chunk
*/
#define JMEM_POOL_CHUNK_SIZE ((size_t) (CONFIG_MEM_POOL_CHUNK_SIZE))
/**
* Logarithm of required alignment for allocated units/blocks
*/
+4 -48
View File
@@ -145,8 +145,10 @@ static void jmem_heap_stat_free_iter ();
void
jmem_heap_init (void)
{
JERRY_STATIC_ASSERT ((1u << JMEM_HEAP_OFFSET_LOG) >= JMEM_HEAP_SIZE,
two_pow_mem_heap_offset_should_not_be_less_than_mem_heap_size);
#ifndef JERRY_CPOINTER_32_BIT
JERRY_STATIC_ASSERT (((UINT16_MAX + 1) << JMEM_ALIGNMENT_LOG) >= JMEM_HEAP_SIZE,
maximum_heap_size_for_16_bit_compressed_pointers_is_512K);
#endif /* !JERRY_CPOINTER_32_BIT */
JERRY_ASSERT ((uintptr_t) JERRY_HEAP_CONTEXT (area) % JMEM_ALIGNMENT == 0);
@@ -521,52 +523,6 @@ jmem_heap_free_block (void *ptr, /**< pointer to beginning of data space of the
JMEM_HEAP_STAT_FREE (size);
} /* jmem_heap_free_block */
/**
* Compress pointer
*
* @return packed heap pointer
*/
uintptr_t __attr_pure___ __attribute__((hot))
jmem_heap_compress_pointer (const void *pointer_p) /**< pointer to compress */
{
JERRY_ASSERT (pointer_p != NULL);
JERRY_ASSERT (jmem_is_heap_pointer (pointer_p));
uintptr_t int_ptr = (uintptr_t) pointer_p;
const uintptr_t heap_start = (uintptr_t) &JERRY_HEAP_CONTEXT (first);
JERRY_ASSERT (int_ptr % JMEM_ALIGNMENT == 0);
int_ptr -= heap_start;
int_ptr >>= JMEM_ALIGNMENT_LOG;
JERRY_ASSERT ((int_ptr & ~((1u << JMEM_HEAP_OFFSET_LOG) - 1)) == 0);
JERRY_ASSERT (int_ptr != JMEM_CP_NULL);
return int_ptr;
} /* jmem_heap_compress_pointer */
/**
* Decompress pointer
*
* @return unpacked heap pointer
*/
void * __attr_pure___ __attribute__((hot))
jmem_heap_decompress_pointer (uintptr_t compressed_pointer) /**< pointer to decompress */
{
JERRY_ASSERT (compressed_pointer != JMEM_CP_NULL);
uintptr_t int_ptr = compressed_pointer;
const uintptr_t heap_start = (uintptr_t) &JERRY_HEAP_CONTEXT (first);
int_ptr <<= JMEM_ALIGNMENT_LOG;
int_ptr += heap_start;
JERRY_ASSERT (jmem_is_heap_pointer ((void *) int_ptr));
return (void *) int_ptr;
} /* jmem_heap_decompress_pointer */
#ifndef JERRY_NDEBUG
/**
* Check whether the pointer points to the heap
-2
View File
@@ -34,8 +34,6 @@ extern void jmem_heap_finalize (void);
extern void *jmem_heap_alloc_block (const size_t);
extern void *jmem_heap_alloc_block_null_on_error (const size_t);
extern void jmem_heap_free_block (void *, const size_t);
extern uintptr_t jmem_heap_compress_pointer (const void *);
extern void *jmem_heap_decompress_pointer (uintptr_t);
extern bool jmem_is_heap_pointer (const void *);
#ifdef JMEM_STATS
+88 -26
View File
@@ -77,9 +77,6 @@ static void jmem_pools_stat_dealloc (void);
# define VALGRIND_FREYA_FREELIKE_SPACE(p)
#endif /* JERRY_VALGRIND_FREYA */
JERRY_STATIC_ASSERT (sizeof (jmem_pools_chunk_t) <= JMEM_POOL_CHUNK_SIZE,
size_of_mem_pools_chunk_t_must_be_less_than_or_equal_to_MEM_POOL_CHUNK_SIZE);
/**
* Finalize pool manager
*/
@@ -88,7 +85,10 @@ jmem_pools_finalize (void)
{
jmem_pools_collect_empty ();
JERRY_ASSERT (JERRY_CONTEXT (jmem_free_chunk_p) == NULL);
JERRY_ASSERT (JERRY_CONTEXT (jmem_free_8_byte_chunk_p) == NULL);
#ifdef JERRY_CPOINTER_32_BIT
JERRY_ASSERT (JERRY_CONTEXT (jmem_free_16_byte_chunk_p) == NULL);
#endif /* JERRY_CPOINTER_32_BIT */
} /* jmem_pools_finalize */
/**
@@ -98,49 +98,94 @@ jmem_pools_finalize (void)
* or NULL - if not enough memory.
*/
inline void * __attribute__((hot)) __attr_always_inline___
jmem_pools_alloc (void)
jmem_pools_alloc (size_t size) /**< size of the chunk */
{
#ifdef JMEM_GC_BEFORE_EACH_ALLOC
jmem_run_free_unused_memory_callbacks (JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH);
#endif /* JMEM_GC_BEFORE_EACH_ALLOC */
if (JERRY_CONTEXT (jmem_free_chunk_p) != NULL)
if (size <= 8)
{
const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_chunk_p);
if (JERRY_CONTEXT (jmem_free_8_byte_chunk_p) != NULL)
{
const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p);
JMEM_POOLS_STAT_REUSE ();
VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_p->next_p;
VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
return (void *) chunk_p;
}
else
{
JMEM_POOLS_STAT_NEW_ALLOC ();
return (void *) jmem_heap_alloc_block (8);
}
}
#ifdef JERRY_CPOINTER_32_BIT
JERRY_ASSERT (size <= 16);
if (JERRY_CONTEXT (jmem_free_16_byte_chunk_p) != NULL)
{
const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p);
JMEM_POOLS_STAT_REUSE ();
VALGRIND_DEFINED_SPACE (chunk_p, JMEM_POOL_CHUNK_SIZE);
VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
JERRY_CONTEXT (jmem_free_chunk_p) = chunk_p->next_p;
JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_p->next_p;
VALGRIND_UNDEFINED_SPACE (chunk_p, JMEM_POOL_CHUNK_SIZE);
VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
return (void *) chunk_p;
}
else
{
JMEM_POOLS_STAT_NEW_ALLOC ();
return (void *) jmem_heap_alloc_block (JMEM_POOL_CHUNK_SIZE);
return (void *) jmem_heap_alloc_block (16);
}
#else /* !JERRY_CPOINTER_32_BIT */
JERRY_UNREACHABLE ();
return NULL;
#endif
} /* jmem_pools_alloc */
/**
* Free the chunk
*/
void __attribute__((hot))
jmem_pools_free (void *chunk_p) /**< pointer to the chunk */
inline void __attribute__((hot)) __attr_always_inline___
jmem_pools_free (void *chunk_p, /**< pointer to the chunk */
size_t size) /**< size of the chunk */
{
JERRY_ASSERT (chunk_p != NULL);
jmem_pools_chunk_t *const chunk_to_free_p = (jmem_pools_chunk_t *) chunk_p;
VALGRIND_DEFINED_SPACE (chunk_to_free_p, JMEM_POOL_CHUNK_SIZE);
VALGRIND_DEFINED_SPACE (chunk_to_free_p, size);
chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_chunk_p);
JERRY_CONTEXT (jmem_free_chunk_p) = chunk_to_free_p;
if (size <= 8)
{
chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p);
JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_to_free_p;
}
else
{
#ifdef JERRY_CPOINTER_32_BIT
JERRY_ASSERT (size <= 16);
VALGRIND_NOACCESS_SPACE (chunk_to_free_p, JMEM_POOL_CHUNK_SIZE);
chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p);
JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_to_free_p;
#else /* !JERRY_CPOINTER_32_BIT */
JERRY_UNREACHABLE ();
#endif /* JERRY_CPOINTER_32_BIT */
}
VALGRIND_NOACCESS_SPACE (chunk_to_free_p, size);
JMEM_POOLS_STAT_FREE_POOL ();
} /* jmem_pools_free */
@@ -151,16 +196,35 @@ jmem_pools_free (void *chunk_p) /**< pointer to the chunk */
void
jmem_pools_collect_empty ()
{
while (JERRY_CONTEXT (jmem_free_chunk_p))
{
VALGRIND_DEFINED_SPACE (JERRY_CONTEXT (jmem_free_chunk_p), sizeof (jmem_pools_chunk_t));
jmem_pools_chunk_t *const next_p = JERRY_CONTEXT (jmem_free_chunk_p)->next_p;
VALGRIND_NOACCESS_SPACE (JERRY_CONTEXT (jmem_free_chunk_p), sizeof (jmem_pools_chunk_t));
jmem_pools_chunk_t *chunk_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p);
JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = NULL;
jmem_heap_free_block (JERRY_CONTEXT (jmem_free_chunk_p), JMEM_POOL_CHUNK_SIZE);
while (chunk_p)
{
VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
jmem_pools_chunk_t *const next_p = chunk_p->next_p;
VALGRIND_NOACCESS_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
jmem_heap_free_block (chunk_p, 8);
JMEM_POOLS_STAT_DEALLOC ();
JERRY_CONTEXT (jmem_free_chunk_p) = next_p;
chunk_p = next_p;
}
#ifdef JERRY_CPOINTER_32_BIT
chunk_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p);
JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = NULL;
while (chunk_p)
{
VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
jmem_pools_chunk_t *const next_p = chunk_p->next_p;
VALGRIND_NOACCESS_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
jmem_heap_free_block (chunk_p, 16);
JMEM_POOLS_STAT_DEALLOC ();
chunk_p = next_p;
}
#endif /* JERRY_CPOINTER_32_BIT */
} /* jmem_pools_collect_empty */
#ifdef JMEM_STATS
@@ -193,12 +257,10 @@ jmem_pools_stats_print (void)
jmem_pools_stats_t *pools_stats = &JERRY_CONTEXT (jmem_pools_stats);
JERRY_DEBUG_MSG ("Pools stats:\n"
" Chunk size: %zu\n"
" Pool chunks: %zu\n"
" Peak pool chunks: %zu\n"
" Free chunks: %zu\n"
" Pool reuse ratio: %zu.%04zu\n",
JMEM_POOL_CHUNK_SIZE,
pools_stats->pools_count,
pools_stats->peak_pools_count,
pools_stats->free_chunks,
+2 -2
View File
@@ -30,8 +30,8 @@
*/
extern void jmem_pools_finalize (void);
extern void *jmem_pools_alloc (void);
extern void jmem_pools_free (void *);
extern void *jmem_pools_alloc (size_t);
extern void jmem_pools_free (void *, size_t);
extern void jmem_pools_collect_empty (void);
#ifdef JMEM_STATS