mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-07 12:16:24 +00:00

Implement the GC (Garbage Collection) feature for interpreter mode, AOT mode and LLVM-JIT mode, and support most features of the latest spec proposal, and also enable the stringref feature. Use `cmake -DWAMR_BUILD_GC=1/0` to enable/disable the feature, and `wamrc --enable-gc` to generate the AOT file with GC supported. And update the AOT file version from 2 to 3 since there are many AOT ABI breaks, including the changes of AOT file format, the changes of AOT module/memory instance layouts, the AOT runtime APIs for the AOT code to invoke and so on.
348 lines
7.7 KiB
C
348 lines
7.7 KiB
C
/*
|
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
*/
|
|
|
|
/**
|
|
* @file ems_gc.h
|
|
* @date Wed Aug 3 10:46:38 2011
|
|
*
|
|
* @brief This file defines GC modules types and interfaces.
|
|
*/
|
|
|
|
#ifndef _EMS_GC_H
|
|
#define _EMS_GC_H
|
|
|
|
#include "bh_platform.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifndef GC_STAT_DATA
|
|
#define GC_STAT_DATA 0
|
|
#endif
|
|
|
|
#ifndef GC_STAT_SHOW
|
|
#define GC_STAT_SHOW 0
|
|
#endif
|
|
|
|
#ifndef GC_IN_EVERY_ALLOCATION
|
|
#define GC_IN_EVERY_ALLOCATION 0
|
|
#endif
|
|
|
|
#ifndef GC_MANUALLY
|
|
#define GC_MANUALLY 0
|
|
#endif
|
|
|
|
#define GC_HEAD_PADDING 4
|
|
|
|
#ifndef NULL_REF
|
|
#define NULL_REF ((gc_object_t)NULL)
|
|
#endif
|
|
|
|
#define GC_SUCCESS (0)
|
|
#define GC_ERROR (-1)
|
|
|
|
#define GC_TRUE (1)
|
|
#define GC_FALSE (0)
|
|
|
|
#define GC_MAX_HEAP_SIZE (256 * BH_KB)
|
|
|
|
typedef void *gc_handle_t;
|
|
typedef void *gc_object_t;
|
|
typedef uint64 gc_uint64;
|
|
typedef int64 gc_int64;
|
|
typedef uint32 gc_uint32;
|
|
typedef int32 gc_int32;
|
|
typedef uint16 gc_uint16;
|
|
typedef int16 gc_int16;
|
|
typedef uint8 gc_uint8;
|
|
typedef int8 gc_int8;
|
|
typedef uint32 gc_size_t;
|
|
|
|
typedef enum {
|
|
GC_STAT_TOTAL = 0,
|
|
GC_STAT_FREE,
|
|
GC_STAT_HIGHMARK,
|
|
GC_STAT_COUNT,
|
|
GC_STAT_TIME,
|
|
GC_STAT_MAX
|
|
} GC_STAT_INDEX;
|
|
|
|
typedef void (*gc_finalizer_t)(void *obj, void *data);
|
|
|
|
#ifndef EXTRA_INFO_NORMAL_NODE_CNT
|
|
#define EXTRA_INFO_NORMAL_NODE_CNT 32
|
|
#endif
|
|
|
|
/* extra information attached to specific object */
|
|
typedef struct extra_info_node {
|
|
gc_object_t obj;
|
|
gc_finalizer_t finalizer;
|
|
void *data;
|
|
} extra_info_node_t;
|
|
|
|
/**
|
|
* GC initialization from a buffer, which is separated into
|
|
* two parts: the beginning of the buffer is used to create
|
|
* the heap structure, and the left is used to create the
|
|
* actual pool data
|
|
*
|
|
* @param buf the buffer to be initialized to a heap
|
|
* @param buf_size the size of buffer
|
|
*
|
|
* @return gc handle if success, NULL otherwise
|
|
*/
|
|
gc_handle_t
|
|
gc_init_with_pool(char *buf, gc_size_t buf_size);
|
|
|
|
/**
|
|
* GC initialization from heap struct buffer and pool buffer
|
|
*
|
|
* @param struct_buf the struct buffer to create the heap structure
|
|
* @param struct_buf_size the size of struct buffer
|
|
* @param pool_buf the pool buffer to create pool data
|
|
* @param pool_buf_size the size of poll buffer
|
|
*
|
|
* @return gc handle if success, NULL otherwise
|
|
*/
|
|
gc_handle_t
|
|
gc_init_with_struct_and_pool(char *struct_buf, gc_size_t struct_buf_size,
|
|
char *pool_buf, gc_size_t pool_buf_size);
|
|
|
|
/**
|
|
* Destroy heap which is initilized from a buffer
|
|
*
|
|
* @param handle handle to heap needed destroy
|
|
*
|
|
* @return GC_SUCCESS if success
|
|
* GC_ERROR for bad parameters or failed system resource freeing.
|
|
*/
|
|
int
|
|
gc_destroy_with_pool(gc_handle_t handle);
|
|
|
|
#if WASM_ENABLE_GC != 0
|
|
/**
|
|
* Enable or disable GC reclaim for a heap
|
|
*
|
|
* @param handle handle of the heap
|
|
* @param exec_env the exec_env of current module instance
|
|
*/
|
|
#if WASM_ENABLE_THREAD_MGR == 0
|
|
void
|
|
gc_enable_gc_reclaim(gc_handle_t handle, void *exec_env);
|
|
#else
|
|
/**
|
|
* Enable or disable GC reclaim for a heap
|
|
*
|
|
* @param handle handle of the heap
|
|
* @param cluster the tread cluster of current module instance
|
|
*/
|
|
void
|
|
gc_enable_gc_reclaim(gc_handle_t handle, void *cluster);
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Return heap struct size
|
|
*/
|
|
uint32
|
|
gc_get_heap_struct_size(void);
|
|
|
|
/**
|
|
* Migrate heap from one pool buf to another pool buf
|
|
*
|
|
* @param handle handle of the new heap
|
|
* @param pool_buf_new the new pool buffer
|
|
* @param pool_buf_size the size of new pool buffer
|
|
*
|
|
* @return GC_SUCCESS if success, GC_ERROR otherwise
|
|
*/
|
|
int
|
|
gc_migrate(gc_handle_t handle, char *pool_buf_new, gc_size_t pool_buf_size);
|
|
|
|
/**
|
|
* Check whether the heap is corrupted
|
|
*
|
|
* @param handle handle of the heap
|
|
*
|
|
* @return true if success, false otherwise
|
|
*/
|
|
bool
|
|
gc_is_heap_corrupted(gc_handle_t handle);
|
|
|
|
/**
|
|
* Get Heap Stats
|
|
*
|
|
* @param stats [out] integer array to save heap stats
|
|
* @param size [in] the size of stats
|
|
* @param mmt [in] type of heap, MMT_SHARED or MMT_INSTANCE
|
|
*/
|
|
void *
|
|
gc_heap_stats(void *heap, uint32 *stats, int size);
|
|
|
|
#if BH_ENABLE_GC_VERIFY == 0
|
|
|
|
gc_object_t
|
|
gc_alloc_vo(void *heap, gc_size_t size);
|
|
|
|
gc_object_t
|
|
gc_realloc_vo(void *heap, void *ptr, gc_size_t size);
|
|
|
|
int
|
|
gc_free_vo(void *heap, gc_object_t obj);
|
|
|
|
#if WASM_ENABLE_GC != 0
|
|
gc_object_t
|
|
gc_alloc_wo(void *heap, gc_size_t size);
|
|
|
|
void
|
|
gc_free_wo(void *vheap, void *ptr);
|
|
#endif
|
|
|
|
#else /* else of BH_ENABLE_GC_VERIFY */
|
|
|
|
gc_object_t
|
|
gc_alloc_vo_internal(void *heap, gc_size_t size, const char *file, int line);
|
|
|
|
gc_object_t
|
|
gc_realloc_vo_internal(void *heap, void *ptr, gc_size_t size, const char *file,
|
|
int line);
|
|
|
|
int
|
|
gc_free_vo_internal(void *heap, gc_object_t obj, const char *file, int line);
|
|
|
|
#if WASM_ENABLE_GC != 0
|
|
gc_object_t
|
|
gc_alloc_wo_internal(void *heap, gc_size_t size, const char *file, int line);
|
|
|
|
void
|
|
gc_free_wo_internal(void *vheap, void *ptr, const char *file, int line);
|
|
#endif
|
|
|
|
/* clang-format off */
|
|
#define gc_alloc_vo(heap, size) \
|
|
gc_alloc_vo_internal(heap, size, __FILE__, __LINE__)
|
|
|
|
#define gc_realloc_vo(heap, ptr, size) \
|
|
gc_realloc_vo_internal(heap, ptr, size, __FILE__, __LINE__)
|
|
|
|
#define gc_free_vo(heap, obj) \
|
|
gc_free_vo_internal(heap, obj, __FILE__, __LINE__)
|
|
|
|
#if WASM_ENABLE_GC != 0
|
|
#define gc_alloc_wo(heap, size) \
|
|
gc_alloc_wo_internal(heap, size, __FILE__, __LINE__)
|
|
|
|
#define gc_free_wo(heap, obj) \
|
|
gc_free_wo_internal(heap, obj, __FILE__, __LINE__)
|
|
#endif
|
|
/* clang-format on */
|
|
|
|
#endif /* end of BH_ENABLE_GC_VERIFY */
|
|
|
|
#if WASM_ENABLE_GC != 0
|
|
/**
|
|
* Add gc object ref to the rootset of a gc heap.
|
|
*
|
|
* @param heap the heap to add the gc object to its rootset
|
|
* @param obj pointer to a valid WASM object managed by the gc heap.
|
|
*
|
|
* @return GC_SUCCESS if success, GC_ERROR otherwise
|
|
*/
|
|
int
|
|
gc_add_root(void *heap, gc_object_t obj);
|
|
|
|
int
|
|
gci_gc_heap(void *heap);
|
|
|
|
extra_info_node_t *
|
|
gc_search_extra_info_node(gc_handle_t handle, gc_object_t obj,
|
|
gc_size_t *p_index);
|
|
|
|
/**
|
|
* Set finalizer to the given object, if another finalizer is set to the same
|
|
* object, the previous one will be cancelled
|
|
*
|
|
* @param handle handle of the heap
|
|
* @param obj object to set finalizer
|
|
* @param cb finalizer function to be called before this object is freed
|
|
* @param data custom data to be passed to finalizer function
|
|
*
|
|
* @return true if success, false otherwise
|
|
*/
|
|
bool
|
|
gc_set_finalizer(gc_handle_t handle, gc_object_t obj, gc_finalizer_t cb,
|
|
void *data);
|
|
|
|
/**
|
|
* Unset finalizer to the given object
|
|
*
|
|
* @param handle handle of the heap
|
|
* @param obj object to unset finalizer
|
|
*/
|
|
void
|
|
gc_unset_finalizer(gc_handle_t handle, gc_object_t obj);
|
|
|
|
#if WASM_ENABLE_THREAD_MGR == 0
|
|
bool
|
|
wasm_runtime_traverse_gc_rootset(void *exec_env, void *heap);
|
|
#else
|
|
bool
|
|
wasm_runtime_traverse_gc_rootset(void *cluster, void *heap);
|
|
#endif
|
|
|
|
bool
|
|
wasm_runtime_get_wasm_object_ref_list(gc_object_t obj, bool *p_is_compact_mode,
|
|
gc_uint32 *p_ref_num,
|
|
gc_uint16 **p_ref_list,
|
|
gc_uint32 *p_ref_start_offset);
|
|
|
|
bool
|
|
wasm_runtime_get_wasm_object_extra_info_flag(gc_object_t obj);
|
|
|
|
void
|
|
wasm_runtime_set_wasm_object_extra_info_flag(gc_object_t obj, bool set);
|
|
|
|
void
|
|
wasm_runtime_gc_prepare();
|
|
|
|
void
|
|
wasm_runtime_gc_finalize();
|
|
#endif /* end of WASM_ENABLE_GC != 0 */
|
|
|
|
#define GC_HEAP_STAT_SIZE (128 / 4)
|
|
|
|
typedef struct {
|
|
int usage;
|
|
int usage_block;
|
|
int vo_usage;
|
|
int wo_usage;
|
|
int free;
|
|
int free_block;
|
|
int vo_free;
|
|
int wo_free;
|
|
int usage_sizes[GC_HEAP_STAT_SIZE];
|
|
int free_sizes[GC_HEAP_STAT_SIZE];
|
|
} gc_stat_t;
|
|
|
|
void
|
|
gc_show_stat(gc_handle_t handle);
|
|
|
|
#if WASM_ENABLE_GC != 0
|
|
void
|
|
gc_show_fragment(gc_handle_t handle);
|
|
|
|
#if WASM_ENABLE_GC_PERF_PROFILING != 0
|
|
void
|
|
gc_dump_perf_profiling(gc_handle_t *handle);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|