mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-15 08:48:33 +00:00
405 lines
10 KiB
C
405 lines
10 KiB
C
/*
|
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
*/
|
|
|
|
#ifndef _GC_OBJECT_H_
|
|
#define _GC_OBJECT_H_
|
|
|
|
#include "gc_type.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* Object header of a WASM object, as the adddress of allocated memory
|
|
* must be 8-byte aligned, the lowest 3 bits are zero, we use them to
|
|
* mark the object:
|
|
* bits[0] is 1: the object is weak referenced
|
|
* bits[1] is 1: it is an rtt object
|
|
* bits[2] is 1: it is an externref object
|
|
* if both bits[1] and bits[2] are 0, then this object header must
|
|
* be a pointer of a WASMRttObject, denotes that the object is a
|
|
* struct object, or an array object, or a function object
|
|
*/
|
|
typedef uintptr_t WASMObjectHeader;
|
|
|
|
#define WASM_OBJ_HEADER_MASK (~((uintptr_t)7))
|
|
|
|
#define WASM_OBJ_WEAK_REF_FLAG (((uintptr_t)1) << 0)
|
|
|
|
#define WASM_OBJ_RTT_OBJ_FLAG (((uintptr_t)1) << 1)
|
|
|
|
#define WASM_OBJ_EXTERNREF_OBJ_FLAG (((uintptr_t)1) << 2)
|
|
|
|
/* Representation of WASM objects */
|
|
typedef struct WASMObject {
|
|
WASMObjectHeader header;
|
|
} WASMObject, *WASMObjectRef;
|
|
|
|
/* Representation of WASM rtt objects */
|
|
typedef struct WASMRttObject {
|
|
/* bits[1] must be 1, denotes an rtt object */
|
|
WASMObjectHeader header;
|
|
/* type_flag must be WASM_TYPE_FUNC/STRUCT/ARRAY to
|
|
denote an object of func, struct or array */
|
|
uint16 type_flag;
|
|
/* The inheritance depth */
|
|
uint16 n;
|
|
uint32 defined_type_idx;
|
|
WASMType *defined_type;
|
|
/* The root of the super rtt objects, whose parent is NULL */
|
|
struct WASMRttObject *root;
|
|
struct WASMRttObject *parent;
|
|
} WASMRttObject, *WASMRttObjectRef;
|
|
|
|
/* Representation of WASM externref objects */
|
|
typedef struct WASMExternrefObject {
|
|
/* bits[2] must be 1, denotes an externref object */
|
|
WASMObjectHeader header;
|
|
/* The foreign object passed from host */
|
|
void *foreign_obj;
|
|
} WASMExternrefObject, *WASMExternrefObjectRef;
|
|
|
|
/**
|
|
* Representation of WASM i31 objects, the lowest bit is 1:
|
|
* for a pointer of WASMObject, if the lowest bit is 1, then it is an
|
|
* i31 object and bits[1..31] stores the actual i31 value, otherwise
|
|
* it is a normal object of rtt/externref/struct/array/func */
|
|
typedef uintptr_t WASMI31ObjectRef;
|
|
|
|
/* Representation of WASM struct objects */
|
|
typedef struct WASMStructObject {
|
|
/* Must be pointer of WASMRttObject of struct type */
|
|
WASMObjectHeader header;
|
|
uint8 field_data[1];
|
|
} WASMStructObject, *WASMStructObjectRef;
|
|
|
|
/* Representation of WASM array objects */
|
|
typedef struct WASMArrayObject {
|
|
/* Must be pointer of WASMRttObject of array type */
|
|
WASMObjectHeader header;
|
|
/* (<array length> << 2) | <array element size>,
|
|
* elem_count = lenght >> 2
|
|
* elem_size = 2 ^ (length & 0x3)
|
|
*/
|
|
uint32 length;
|
|
uint8 elem_data[1];
|
|
} WASMArrayObject, *WASMArrayObjectRef;
|
|
|
|
#define WASM_ARRAY_LENGTH_SHIFT 2
|
|
#define WASM_ARRAY_ELEM_SIZE_MASK 3
|
|
|
|
/* Representation of WASM function objects */
|
|
typedef struct WASMFuncObject {
|
|
/* must be pointer of WASMRttObject of func type */
|
|
WASMObjectHeader header;
|
|
uint32 func_idx_bound;
|
|
uint32 param_count_bound;
|
|
WASMValue params_bound[1];
|
|
} WASMFuncObject, *WASMFuncObjectRef;
|
|
|
|
inline static WASMObjectHeader
|
|
wasm_object_header(const WASMObjectRef obj)
|
|
{
|
|
return (obj->header & WASM_OBJ_HEADER_MASK);
|
|
}
|
|
|
|
HashMap *
|
|
wasm_rttobj_set_create(uint32 size);
|
|
|
|
WASMRttObjectRef
|
|
wasm_rtt_obj_new(HashMap *rtt_obj_set, WASMRttObject *parent,
|
|
WASMType *defined_type, uint32 defined_type_idx);
|
|
|
|
inline static WASMRttObjectRef
|
|
wasm_rtt_obj_get_parent(const WASMRttObjectRef rtt_obj)
|
|
{
|
|
return rtt_obj->parent;
|
|
}
|
|
|
|
inline static WASMType *
|
|
wasm_rtt_obj_get_defined_type(const WASMRttObjectRef rtt_obj)
|
|
{
|
|
return rtt_obj->defined_type;
|
|
}
|
|
|
|
inline static uint32
|
|
wasm_rtt_obj_get_defined_type_idx(const WASMRttObjectRef rtt_obj)
|
|
{
|
|
return rtt_obj->defined_type_idx;
|
|
}
|
|
|
|
inline static uint32
|
|
wasm_rtt_obj_get_inherit_depth(const WASMRttObjectRef rtt_obj)
|
|
{
|
|
return rtt_obj->n;
|
|
}
|
|
|
|
inline static bool
|
|
wasm_rtt_obj_is_subtype_of(const WASMRttObjectRef rtt_obj1,
|
|
const WASMRttObjectRef rtt_obj2)
|
|
{
|
|
return (rtt_obj1->root == rtt_obj2->root && rtt_obj1->n >= rtt_obj2->n)
|
|
? true
|
|
: false;
|
|
}
|
|
|
|
WASMStructObjectRef
|
|
wasm_struct_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj);
|
|
|
|
void
|
|
wasm_struct_obj_set_field(WASMStructObjectRef struct_obj, uint32 field_idx,
|
|
WASMValue *value);
|
|
|
|
void
|
|
wasm_struct_obj_get_field(const WASMStructObjectRef struct_obj,
|
|
uint32 field_idx, bool sign_extend, WASMValue *value);
|
|
|
|
WASMArrayObjectRef
|
|
wasm_array_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj, uint32 length,
|
|
WASMValue *init_value);
|
|
|
|
void
|
|
wasm_array_obj_set_elem(WASMArrayObjectRef array_obj, uint32 elem_idx,
|
|
WASMValue *value);
|
|
|
|
void
|
|
wasm_array_obj_get_elem(WASMArrayObjectRef array_obj, uint32 elem_idx,
|
|
bool sign_extend, WASMValue *value);
|
|
|
|
/**
|
|
* Return the logarithm of the size of array element.
|
|
*
|
|
* @param array the WASM array object
|
|
*
|
|
* @return log(size of the array element)
|
|
*/
|
|
inline static uint32
|
|
wasm_array_obj_elem_size_log(const WASMArrayObjectRef array_obj)
|
|
{
|
|
return (array_obj->length & WASM_ARRAY_ELEM_SIZE_MASK);
|
|
}
|
|
|
|
/**
|
|
* Return the length of the array.
|
|
*
|
|
* @param array_obj the WASM array object
|
|
*
|
|
* @return the length of the array
|
|
*/
|
|
inline static uint32
|
|
wasm_array_obj_length(const WASMArrayObjectRef array_obj)
|
|
{
|
|
return array_obj->length >> WASM_ARRAY_LENGTH_SHIFT;
|
|
}
|
|
|
|
/**
|
|
* Return the address of the first element of an array object.
|
|
*
|
|
* @param array_obj the WASM array object
|
|
*
|
|
* @return the address of the first element of the array object
|
|
*/
|
|
inline static void *
|
|
wasm_array_obj_first_elem_addr(const WASMArrayObjectRef array_obj)
|
|
{
|
|
return array_obj->elem_data;
|
|
}
|
|
|
|
/**
|
|
* Return the address of the i-th element of an array object.
|
|
*
|
|
* @param array_obj the WASM array object
|
|
* @param index the index of the element
|
|
*
|
|
* @return the address of the i-th element of the array object
|
|
*/
|
|
inline static void *
|
|
wasm_array_obj_elem_addr(const WASMArrayObjectRef array_obj, uint32 elem_idx)
|
|
{
|
|
return array_obj->elem_data
|
|
+ (elem_idx << wasm_array_obj_elem_size_log(array_obj));
|
|
}
|
|
|
|
WASMFuncObjectRef
|
|
wasm_func_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj,
|
|
uint32 func_idx_bound, uint32 param_count_bound);
|
|
|
|
void
|
|
wasm_func_obj_set_param_bound(WASMFuncObjectRef func_obj, uint32 param_idx,
|
|
WASMValue *value);
|
|
|
|
WASMValue *
|
|
wasm_func_obj_get_param_bound(const WASMFuncObjectRef func_obj,
|
|
uint32 param_idx);
|
|
|
|
inline static uint32
|
|
wasm_func_obj_get_func_idx_bound(const WASMFuncObjectRef func_obj)
|
|
{
|
|
return func_obj->func_idx_bound;
|
|
}
|
|
|
|
inline static uint32
|
|
wasm_func_obj_get_param_count_bound(const WASMFuncObjectRef func_obj)
|
|
{
|
|
return func_obj->param_count_bound;
|
|
}
|
|
|
|
inline static WASMFuncType *
|
|
wasm_func_obj_get_func_type(const WASMFuncObjectRef func_obj)
|
|
{
|
|
WASMRttObjectRef rtt_obj =
|
|
(WASMRttObjectRef)wasm_object_header((WASMObjectRef)func_obj);
|
|
bh_assert(rtt_obj->type_flag == WASM_TYPE_FUNC);
|
|
return (WASMFuncType *)rtt_obj->defined_type;
|
|
}
|
|
|
|
WASMExternrefObjectRef
|
|
wasm_externref_obj_new(void *heap_handle, void *foreign_obj);
|
|
|
|
inline static void *
|
|
wasm_externref_obj_get_value(const WASMExternrefObjectRef externref_obj)
|
|
{
|
|
return externref_obj->foreign_obj;
|
|
}
|
|
|
|
inline static WASMI31ObjectRef
|
|
wasm_i31_obj_new(uint32 i31_value)
|
|
{
|
|
return (WASMI31ObjectRef)((i31_value << 1) | 1);
|
|
}
|
|
|
|
inline static uint32
|
|
wasm_i31_obj_get_value(WASMI31ObjectRef i31_obj, bool sign_extend)
|
|
{
|
|
uint32 i31_value = (uint32)(((uintptr_t)i31_obj) >> 1);
|
|
if (sign_extend && (i31_value & 0x40000000)) /* bit 30 is 1 */
|
|
/* set bit 31 to 1 */
|
|
i31_value |= 0x80000000;
|
|
return i31_value;
|
|
}
|
|
|
|
inline static bool
|
|
wasm_obj_is_i31_obj(WASMObjectRef obj)
|
|
{
|
|
bh_assert(obj);
|
|
return (((uintptr_t)obj) & 1) ? true : false;
|
|
}
|
|
|
|
inline static bool
|
|
wasm_obj_is_rtt_obj(WASMObjectRef obj)
|
|
{
|
|
bh_assert(obj);
|
|
return (!wasm_obj_is_i31_obj(obj) && (obj->header & WASM_OBJ_RTT_OBJ_FLAG))
|
|
? true
|
|
: false;
|
|
}
|
|
|
|
inline static bool
|
|
wasm_obj_is_externref_obj(WASMObjectRef obj)
|
|
{
|
|
bh_assert(obj);
|
|
return (!wasm_obj_is_i31_obj(obj)
|
|
&& (obj->header & WASM_OBJ_EXTERNREF_OBJ_FLAG))
|
|
? true
|
|
: false;
|
|
}
|
|
|
|
inline static bool
|
|
wasm_obj_is_i31_rtt_or_externref_obj(WASMObjectRef obj)
|
|
{
|
|
bh_assert(obj);
|
|
return (wasm_obj_is_i31_obj(obj)
|
|
|| (obj->header
|
|
& (WASM_OBJ_RTT_OBJ_FLAG | WASM_OBJ_EXTERNREF_OBJ_FLAG)))
|
|
? true
|
|
: false;
|
|
}
|
|
|
|
inline static bool
|
|
wasm_obj_is_struct_obj(WASMObjectRef obj)
|
|
{
|
|
WASMRttObjectRef rtt_obj;
|
|
|
|
bh_assert(obj);
|
|
|
|
if (wasm_obj_is_i31_rtt_or_externref_obj(obj))
|
|
return false;
|
|
|
|
rtt_obj = (WASMRttObjectRef)wasm_object_header(obj);
|
|
return rtt_obj->type_flag == WASM_TYPE_STRUCT ? true : false;
|
|
}
|
|
|
|
inline static bool
|
|
wasm_obj_is_array_obj(WASMObjectRef obj)
|
|
{
|
|
WASMRttObjectRef rtt_obj;
|
|
|
|
bh_assert(obj);
|
|
|
|
if (wasm_obj_is_i31_rtt_or_externref_obj(obj))
|
|
return false;
|
|
|
|
rtt_obj = (WASMRttObjectRef)wasm_object_header(obj);
|
|
return rtt_obj->type_flag == WASM_TYPE_ARRAY ? true : false;
|
|
}
|
|
|
|
inline static bool
|
|
wasm_obj_is_func_obj(WASMObjectRef obj)
|
|
{
|
|
WASMRttObjectRef rtt_obj;
|
|
|
|
bh_assert(obj);
|
|
|
|
if (wasm_obj_is_i31_rtt_or_externref_obj(obj))
|
|
return false;
|
|
|
|
rtt_obj = (WASMRttObjectRef)wasm_object_header(obj);
|
|
return rtt_obj->type_flag == WASM_TYPE_FUNC ? true : false;
|
|
}
|
|
|
|
inline static bool
|
|
wasm_obj_is_data_obj(WASMObjectRef obj)
|
|
{
|
|
WASMRttObjectRef rtt_obj;
|
|
|
|
bh_assert(obj);
|
|
|
|
if (wasm_obj_is_i31_rtt_or_externref_obj(obj))
|
|
return false;
|
|
|
|
rtt_obj = (WASMRttObjectRef)wasm_object_header(obj);
|
|
return (rtt_obj->type_flag == WASM_TYPE_ARRAY
|
|
|| rtt_obj->type_flag == WASM_TYPE_STRUCT)
|
|
? true
|
|
: false;
|
|
}
|
|
|
|
inline static bool
|
|
wasm_obj_is_null_obj(WASMObjectRef obj)
|
|
{
|
|
return obj == NULL ? true : false;
|
|
}
|
|
|
|
bool
|
|
wasm_obj_is_created_from_heap(WASMObjectRef obj);
|
|
|
|
bool
|
|
wasm_obj_is_instance_of(WASMObjectRef obj, WASMRttObjectRef rtt_obj);
|
|
|
|
bool
|
|
wasm_obj_equal(WASMObjectRef obj1, WASMObjectRef obj2);
|
|
|
|
bool
|
|
wasm_object_get_ref_list(WASMObjectRef obj, bool *p_is_compact_mode,
|
|
uint32 *p_ref_num, uint16 **p_ref_list,
|
|
uint32 *p_ref_start_offset);
|
|
|
|
#ifdef __cplusplus
|
|
} /* end of extern "C" */
|
|
#endif
|
|
|
|
#endif /* end of _GC_OBJECT_H_ */
|