Files
jerryscript/jerry-core/jmem/jmem.h
T
Dániel Bátyai ac1c48eeff Update jerry-port and jerry-ext (#4907)
Notable changes:
  - Updated and the port API interface, new functions have been added
    and some have been changed. The port library is now cleaned up to
    not have any dependency on jerry-core, as it should be. The port library
    is now strictly a collection of functions that implement
    embedding/platform specific behavior.
  - The default port implementation has been split for windows and unix.
    Implemented port functions have been categorized and reorganized,
    and marked with attribute((weak)) for better reusability.
  - External context allocation has been moved to the port API instead
    of a core API callback. The iterface has also been extended with a
    function to free the allocated context. When external context is
    enabled, jerry_init now automatically calls the port implementation
    to allocate the context and jerry_cleanup automatically calls the port
    to free the context.
  - jerry_port_log has been changed to no longer require formatting to
    be implemented by the port. The reason beind this is that it was vague what
    format specifiers were used by the engine, and in what manner. The port
    function now takes a zero-terminated string, and should only implement
    how the string should be logged.
  - Logging and log message formatting is now handled by the core jerry library
    where it can be implemented as necessary. Logging can be done through a new
    core API function, which uses the port to output the final log message.
  - Log level has been moved into jerry-core, and an API function has
    been added to set the log level. It should be the library that
    filters log messages based on the requested log level, instead of
    logging everything and requiring the user to do so.
  - Module resolving logic has been moved into jerry-core. There's no
    reason to have it in the port library and requiring embedders to
    duplicate the code. It also added an unnecessary dependency on
    jerry-core to the port. Platform specific behavior is still used through
    the port API, like resolving module specifiers, and reading source file
    contents. If necessary, the resolving logic can still be overridden as
    previously.
  - The jerry-ext library has also been cleaned up, and many utility
    functions have been added that previously were implemented in
    jerry-main. This allows easier reusability for some common operations,
    like printing unhandled exceptions or providing a repl console.
  - Debugger interaction with logged/printed messages has been fixed, so
    that it's no longer the port implementations responsibility to send
    the output to the debugger, as the port should have no notion of what a
    debugger is.  The printing and logging functions will now pass the
    result message to the debugger, if connected.
  - Cleaned up TZA handling in the date port implementation, and simplified
    the API function prototype.
  - Moved property access helper functions that use ASCII strings as
    keys from jerry-ext to the core API.

JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai@inf.u-szeged.hu
2022-01-20 13:53:47 +01:00

323 lines
11 KiB
C

/* Copyright JS Foundation and other contributors, http://js.foundation
*
* 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 JMEM_H
#define JMEM_H
#include "jrt.h"
/** \addtogroup mem Memory allocation
* @{
*
* \addtogroup heap Heap
* @{
*/
/**
* Logarithm of required alignment for allocated units/blocks
*/
#define JMEM_ALIGNMENT_LOG 3
/**
* Representation of NULL value for compressed pointers
*/
#define JMEM_CP_NULL ((jmem_cpointer_t) 0)
/**
* Required alignment for allocated units/blocks
*/
#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) && JERRY_CPOINTER_32_BIT
#define JMEM_TAG_SHIFT 0
#else /* !JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY || !JERRY_CPOINTER_32_BIT */
#define JMEM_TAG_SHIFT 3
#endif /* JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY && 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
*
* 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
*/
#if 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 */
/**
* Compressed pointer with tag value
*/
typedef uint32_t jmem_cpointer_tag_t;
/**
* Memory usage pressure for reclaiming unused memory.
*
* Each failed allocation will try to reclaim memory with increasing pressure,
* until enough memory is freed to fulfill the allocation request.
*
* If not enough memory is freed and JMEM_PRESSURE_FULL is reached,
* then the engine is shut down with JERRY_FATAL_OUT_OF_MEMORY.
*/
typedef enum
{
JMEM_PRESSURE_NONE, /**< no memory pressure */
JMEM_PRESSURE_LOW, /**< low memory pressure */
JMEM_PRESSURE_HIGH, /**< high memory pressure */
JMEM_PRESSURE_FULL, /**< memory full */
} jmem_pressure_t;
/**
* Node for free chunk list
*/
typedef struct jmem_pools_chunk_t
{
struct jmem_pools_chunk_t *next_p; /**< pointer to next pool chunk */
} jmem_pools_chunk_t;
/**
* Free region node
*/
typedef struct
{
uint32_t next_offset; /**< Offset of next region in list */
uint32_t size; /**< Size of region */
} jmem_heap_free_t;
void jmem_init (void);
void jmem_finalize (void);
void *jmem_heap_alloc_block (const size_t size);
void *jmem_heap_alloc_block_null_on_error (const size_t size);
void *jmem_heap_realloc_block (void *ptr, const size_t old_size, const size_t new_size);
void jmem_heap_free_block (void *ptr, const size_t size);
#if JERRY_MEM_STATS
/**
* Heap memory usage statistics
*/
typedef struct
{
size_t size; /**< heap total size */
size_t allocated_bytes; /**< currently allocated bytes */
size_t peak_allocated_bytes; /**< peak allocated bytes */
size_t waste_bytes; /**< bytes waste due to blocks filled partially */
size_t peak_waste_bytes; /**< peak wasted bytes */
size_t byte_code_bytes; /**< allocated memory for byte code */
size_t peak_byte_code_bytes; /**< peak allocated memory for byte code */
size_t string_bytes; /**< allocated memory for strings */
size_t peak_string_bytes; /**< peak allocated memory for strings */
size_t object_bytes; /**< allocated memory for objects */
size_t peak_object_bytes; /**< peak allocated memory for objects */
size_t property_bytes; /**< allocated memory for properties */
size_t peak_property_bytes; /**< peak allocated memory for properties */
} jmem_heap_stats_t;
void jmem_stats_allocate_byte_code_bytes (size_t property_size);
void jmem_stats_free_byte_code_bytes (size_t property_size);
void jmem_stats_allocate_string_bytes (size_t string_size);
void jmem_stats_free_string_bytes (size_t string_size);
void jmem_stats_allocate_object_bytes (size_t object_size);
void jmem_stats_free_object_bytes (size_t string_size);
void jmem_stats_allocate_property_bytes (size_t property_size);
void jmem_stats_free_property_bytes (size_t property_size);
void jmem_heap_get_stats (jmem_heap_stats_t *);
void jmem_heap_stats_reset_peak (void);
void jmem_heap_stats_print (void);
#endif /* JERRY_MEM_STATS */
jmem_cpointer_t JERRY_ATTR_PURE jmem_compress_pointer (const void *pointer_p);
void *JERRY_ATTR_PURE jmem_decompress_pointer (uintptr_t compressed_pointer);
/**
* Define a local array variable and allocate memory for the array on the heap.
*
* If requested number of elements is zero, assign NULL to the variable.
*
* Warning:
* if there is not enough memory on the heap, shutdown engine with JERRY_FATAL_OUT_OF_MEMORY.
*/
#define JMEM_DEFINE_LOCAL_ARRAY(var_name, number, type) \
{ \
size_t var_name##___size = (size_t) (number) * sizeof (type); \
type *var_name = (type *) (jmem_heap_alloc_block (var_name##___size));
/**
* Free the previously defined local array variable, freeing corresponding block on the heap,
* if it was allocated (i.e. if the array's size was non-zero).
*/
#define JMEM_FINALIZE_LOCAL_ARRAY(var_name) \
if (var_name != NULL) \
{ \
JERRY_ASSERT (var_name##___size != 0); \
\
jmem_heap_free_block (var_name, var_name##___size); \
} \
else \
{ \
JERRY_ASSERT (var_name##___size == 0); \
} \
}
/**
* Get value of pointer from specified non-null compressed pointer value
*/
#define JMEM_CP_GET_NON_NULL_POINTER(type, cp_value) ((type *) (jmem_decompress_pointer (cp_value)))
/**
* Get value of pointer from specified compressed pointer value
*/
#define JMEM_CP_GET_POINTER(type, cp_value) \
(((JERRY_UNLIKELY ((cp_value) == JMEM_CP_NULL)) ? NULL : JMEM_CP_GET_NON_NULL_POINTER (type, cp_value)))
/**
* Set value of non-null compressed pointer so that it will correspond
* 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)
/**
* Set value of compressed pointer so that it will correspond
* to specified non_compressed_pointer
*/
#define JMEM_CP_SET_POINTER(cp_value, non_compressed_pointer) \
do \
{ \
void *ptr_value = (void *) non_compressed_pointer; \
\
if (JERRY_UNLIKELY ((ptr_value) == NULL)) \
{ \
(cp_value) = JMEM_CP_NULL; \
} \
else \
{ \
JMEM_CP_SET_NON_NULL_POINTER (cp_value, ptr_value); \
} \
} 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)))
/**
* Extract tag bits from pointer-tag value
*/
#define JMEM_CP_GET_POINTER_TAG_BITS(cp_value) \
(cp_value & (JMEM_FIRST_TAG_BIT_MASK | JMEM_SECOND_TAG_BIT_MASK | JMEM_THIRD_TAG_BIT_MASK))
/**
* 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
* @{
*/
void *jmem_pools_alloc (size_t size);
void jmem_pools_free (void *chunk_p, size_t size);
void jmem_pools_collect_empty (void);
/**
* @}
* @}
*/
#endif /* !JMEM_H */