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:
@@ -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 */
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user