/* * 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 address 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 an externref object * bits[1] is 1: the object is an anyref object * bits[2] is 1: the object has extra information * if both bits[0] and bits[1] are 0, then this object header must * be a pointer of a WASMRttType, 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_EXTERNREF_OBJ_FLAG (((uintptr_t)1) << 0) #define WASM_OBJ_ANYREF_OBJ_FLAG (((uintptr_t)1) << 1) #define WASM_OBJ_EXTRA_INFO_FLAG (((uintptr_t)1) << 2) /* Representation of WASM objects */ typedef struct WASMObject { WASMObjectHeader header; } WASMObject, *WASMObjectRef; /* Representation of WASM rtt types */ typedef struct WASMRttType { /* type_flag must be WASM_TYPE_FUNC/STRUCT/ARRAY to denote an object of func, struct or array */ uint32 type_flag; uint32 inherit_depth; WASMType *defined_type; WASMType *root_type; } WASMRttType, *WASMRttTypeRef; /* Representation of WASM externref objects */ typedef struct WASMExternrefObject { /* bits[0] must be 1, denotes an externref object */ WASMObjectHeader header; /* an object of WASMAnyrefObjectRef which encapsulates the external object passed from host, or other internal objects passed to opcode extern.externalize */ WASMObjectRef internal_obj; } WASMExternrefObject, *WASMExternrefObjectRef; /* Representation of WASM anyref objects which encapsulate the external object passed from host */ typedef struct WASMAnyrefObject { /* bits[1] must be 1, denotes an anyref object */ WASMObjectHeader header; const void *host_obj; } WASMAnyrefObject, *WASMAnyrefObjectRef; /** * Representation of WASM i31 objects, the lowest bit is 1: * for a pointer of WASMObjectRef, 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; /* ( << 2) | , * elem_count = length >> 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; } WASMFuncObject, *WASMFuncObjectRef; /* Representation of WASM stringref objects */ typedef struct WASMStringrefObject { WASMObjectHeader header; const void *str_obj; } WASMStringrefObject, *WASMStringrefObjectRef; typedef struct WASMStringviewWTF8Object { WASMObjectHeader header; const void *str_obj; } WASMStringviewWTF8Object, *WASMStringviewWTF8ObjectRef; typedef struct WASMStringviewWTF16Object { WASMObjectHeader header; const void *str_obj; } WASMStringviewWTF16Object, *WASMStringviewWTF16ObjectRef; typedef struct WASMStringviewIterObject { WASMObjectHeader header; const void *str_obj; int32 pos; } WASMStringviewIterObject, *WASMStringviewIterObjectRef; struct WASMExecEnv; inline static WASMObjectHeader wasm_object_header(const WASMObjectRef obj) { return (obj->header & WASM_OBJ_HEADER_MASK); } WASMRttTypeRef wasm_rtt_type_new(WASMType *defined_type, uint32 defined_type_idx, WASMRttType **rtt_types, uint32 rtt_type_count, korp_mutex *rtt_type_lock); inline static WASMType * wasm_rtt_type_get_defined_type(const WASMRttTypeRef rtt_type) { return rtt_type->defined_type; } WASMStructObjectRef wasm_struct_obj_new_internal(void *heap_handle, WASMRttTypeRef rtt_type); WASMStructObjectRef wasm_struct_obj_new(struct WASMExecEnv *exec_env, WASMRttTypeRef rtt_type); void wasm_struct_obj_set_field(WASMStructObjectRef struct_obj, uint32 field_idx, const WASMValue *value); void wasm_struct_obj_get_field(const WASMStructObjectRef struct_obj, uint32 field_idx, bool sign_extend, WASMValue *value); /** * Return the field count of the WASM struct object. * * @param struct_obj the WASM struct object * * @return the field count of the WASM struct object */ uint32 wasm_struct_obj_get_field_count(const WASMStructObjectRef struct_obj); WASMArrayObjectRef wasm_array_obj_new_internal(void *heap_handle, WASMRttTypeRef rtt_type, uint32 length, WASMValue *init_value); WASMArrayObjectRef wasm_array_obj_new(struct WASMExecEnv *exec_env, WASMRttTypeRef rtt_type, uint32 length, WASMValue *init_value); void wasm_array_obj_set_elem(WASMArrayObjectRef array_obj, uint32 elem_idx, const WASMValue *value); void wasm_array_obj_get_elem(const WASMArrayObjectRef array_obj, uint32 elem_idx, bool sign_extend, WASMValue *value); void wasm_array_obj_fill(const WASMArrayObjectRef array_obj, uint32 elem_idx, uint32 len, WASMValue *value); void wasm_array_obj_copy(WASMArrayObjectRef dst_obj, uint32 dst_idx, WASMArrayObjectRef src_obj, uint32 src_idx, uint32 len); /** * 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 */ uint32 wasm_array_obj_length(const WASMArrayObjectRef array_obj); /** * 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 */ void * wasm_array_obj_first_elem_addr(const WASMArrayObjectRef array_obj); /** * 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 */ void * wasm_array_obj_elem_addr(const WASMArrayObjectRef array_obj, uint32 elem_idx); WASMFuncObjectRef wasm_func_obj_new_internal(void *heap_handle, WASMRttTypeRef rtt_type, uint32 func_idx_bound); WASMFuncObjectRef wasm_func_obj_new(struct WASMExecEnv *exec_env, WASMRttTypeRef rtt_type, uint32 func_idx_bound); uint32 wasm_func_obj_get_func_idx_bound(const WASMFuncObjectRef func_obj); WASMFuncType * wasm_func_obj_get_func_type(const WASMFuncObjectRef func_obj); WASMExternrefObjectRef wasm_externref_obj_new(struct WASMExecEnv *exec_env, const void *host_obj); WASMAnyrefObjectRef wasm_anyref_obj_new(struct WASMExecEnv *exec_env, const void *host_obj); /* Implementation of opcode extern.internalize */ WASMObjectRef wasm_externref_obj_to_internal_obj(const WASMExternrefObjectRef externref_obj); /* Implementation of opcode extern.externalize */ WASMExternrefObjectRef wasm_internal_obj_to_externref_obj(struct WASMExecEnv *exec_env, const WASMObjectRef internal_obj); const void * wasm_anyref_obj_get_value(const WASMAnyrefObjectRef anyref_obj); const void * wasm_externref_obj_get_value(const WASMExternrefObjectRef externref_obj); WASMI31ObjectRef wasm_i31_obj_new(uint32 i31_value); uint32 wasm_i31_obj_get_value(WASMI31ObjectRef i31_obj, bool sign_extend); bool wasm_obj_is_i31_obj(WASMObjectRef obj); bool wasm_obj_is_externref_obj(WASMObjectRef obj); bool wasm_obj_is_anyref_obj(WASMObjectRef obj); bool wasm_obj_is_i31_externref_or_anyref_obj(WASMObjectRef obj); bool wasm_obj_is_struct_obj(WASMObjectRef obj); bool wasm_obj_is_array_obj(WASMObjectRef obj); bool wasm_obj_is_func_obj(WASMObjectRef obj); bool wasm_obj_is_internal_obj(WASMObjectRef obj); bool wasm_obj_is_eq_obj(WASMObjectRef obj); inline static bool wasm_obj_is_null_obj(WASMObjectRef obj) { return obj == NULL_REF ? true : false; } inline static bool wasm_obj_is_created_from_heap(WASMObjectRef obj) { if (obj == NULL || (((uintptr_t)obj) & 1)) /* null object or i31 object */ return false; return true; } bool wasm_obj_is_instance_of(WASMObjectRef obj, uint32 type_idx, WASMType **types, uint32 type_count); bool wasm_obj_is_type_of(WASMObjectRef obj, int32 heap_type); 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); #if WASM_ENABLE_STRINGREF != 0 WASMStringrefObjectRef wasm_stringref_obj_new(struct WASMExecEnv *exec_env, const void *str_obj); WASMStringviewWTF8ObjectRef wasm_stringview_wtf8_obj_new(struct WASMExecEnv *exec_env, const void *str_obj); WASMStringviewWTF16ObjectRef wasm_stringview_wtf16_obj_new(struct WASMExecEnv *exec_env, const void *str_obj); WASMStringviewIterObjectRef wasm_stringview_iter_obj_new(struct WASMExecEnv *exec_env, const void *str_obj, int32 pos); const void * wasm_stringref_obj_get_value(WASMStringrefObjectRef stringref_obj); const void * wasm_stringview_wtf8_obj_get_value( WASMStringviewWTF8ObjectRef stringview_wtf8_obj); const void * wasm_stringview_wtf16_obj_get_value( WASMStringviewWTF16ObjectRef stringview_wtf16_obj); const void * wasm_stringview_iter_obj_get_value( WASMStringviewIterObjectRef stringview_iter_obj); int32 wasm_stringview_iter_obj_get_pos( WASMStringviewIterObjectRef stringview_iter_obj); void wasm_stringview_iter_obj_update_pos( WASMStringviewIterObjectRef stringview_iter_obj, int32 pos); bool wasm_obj_is_stringref_obj(WASMObjectRef obj); bool wasm_obj_is_stringview_wtf8_obj(WASMObjectRef obj); bool wasm_obj_is_stringview_wtf16_obj(WASMObjectRef obj); #endif /* end of WASM_ENABLE_STRINGREF != 0 */ #ifdef __cplusplus } /* end of extern "C" */ #endif #endif /* end of _GC_OBJECT_H_ */