wasm-micro-runtime/core/iwasm/common/gc/gc_object.c
Wenyong Huang a6d390740f
Implement GC bytecode validation (#918)
Implement GC bytecode validation in loader stage, except for opcode
let and and func.bind. Pass the related spec cases.

And implement some GC object related APIs.

The source code may be not so elegant, we will optimize it in the future.
2022-02-15 11:24:25 +08:00

200 lines
5.0 KiB
C

/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "gc_object.h"
static uint32
rtt_obj_hash(const void *key)
{
const WASMRttObjectRef rtt_obj = (const WASMRttObjectRef)key;
return (uint32)(((uintptr_t)rtt_obj->defined_type)
^ ((uintptr_t)rtt_obj->parent));
}
static bool
rtt_obj_equal(void *key1, void *key2)
{
const WASMRttObjectRef rtt_obj1 = (const WASMRttObjectRef)key1;
const WASMRttObjectRef rtt_obj2 = (const WASMRttObjectRef)key2;
return (rtt_obj1->defined_type == rtt_obj2->defined_type
&& rtt_obj1->parent == rtt_obj2->parent)
? true
: false;
}
HashMap *
wasm_rttobj_set_create(uint32 size)
{
HashMap *rtt_obj_set = bh_hash_map_create(
size, true, rtt_obj_hash, rtt_obj_equal, NULL, wasm_runtime_free);
return rtt_obj_set;
}
WASMRttObjectRef
wasm_rtt_obj_new(HashMap *rtt_obj_set, WASMRttObject *parent,
WASMType *defined_type, uint32 defined_type_idx)
{
WASMRttObject *rtt_obj, *rtt_obj_ret;
if (!(rtt_obj = wasm_runtime_malloc(sizeof(WASMRttObject))))
return NULL;
rtt_obj->header = WASM_OBJ_RTT_OBJ_FLAG;
rtt_obj->type_flag = defined_type->type_flag;
rtt_obj->n = parent ? parent->n + 1 : 0;
rtt_obj->defined_type_idx = defined_type_idx;
rtt_obj->defined_type = defined_type;
rtt_obj->root = parent ? parent->root : rtt_obj;
rtt_obj->parent = parent;
if ((rtt_obj_ret = bh_hash_map_find(rtt_obj_set, (void *)rtt_obj))) {
wasm_runtime_free(rtt_obj);
return rtt_obj_ret;
}
if (!bh_hash_map_insert(rtt_obj_set, rtt_obj, rtt_obj)) {
wasm_runtime_free(rtt_obj);
return NULL;
}
return rtt_obj;
}
static void *
gc_obj_malloc(void *heap_handle, uint64 size)
{
void *mem;
/* Allocate from global heap for test,
TODO: changed to allocate from heap_handle */
if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
return NULL;
}
memset(mem, 0, (uint32)size);
return mem;
}
WASMStructObjectRef
wasm_struct_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj)
{
WASMStructObjectRef struct_obj;
WASMStructType *struct_type;
bh_assert(rtt_obj->type_flag == WASM_TYPE_STRUCT);
struct_type = (WASMStructType *)rtt_obj->defined_type;
if (!(struct_obj = gc_obj_malloc(heap_handle, struct_type->total_size))) {
return NULL;
}
struct_obj->header = (WASMObjectHeader)rtt_obj;
return struct_obj;
}
void
wasm_struct_obj_set_field(WASMStructObjectRef struct_obj, uint32 field_idx,
WASMValue *value)
{}
WASMValue *
wasm_struct_obj_get_field(const WASMStructObjectRef struct_obj,
uint32 field_idx)
{
return NULL;
}
WASMArrayObjectRef
wasm_array_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj, uint32 length,
WASMValue *init_value)
{
WASMArrayObjectRef array_obj;
WASMArrayType *array_type;
uint64 total_size;
uint32 elem_size, elem_size_log;
bh_assert(rtt_obj->type_flag == WASM_TYPE_ARRAY);
if (length >= (1 << 29))
return NULL;
array_type = (WASMArrayType *)rtt_obj->defined_type;
if (array_type->elem_type == PACKED_TYPE_I8) {
elem_size = 1;
elem_size_log = 0;
}
else if (array_type->elem_type == PACKED_TYPE_I16) {
elem_size = 2;
elem_size_log = 1;
}
else {
elem_size = wasm_value_type_size(array_type->elem_type);
elem_size_log = (elem_size == 4) ? 2 : 3;
}
total_size =
offsetof(WASMArrayObject, elem_data) + (uint64)elem_size * length;
if (!(array_obj = gc_obj_malloc(heap_handle, total_size))) {
return NULL;
}
array_obj->header = (WASMObjectHeader)rtt_obj;
array_obj->length = (length << 2) | elem_size_log;
return array_obj;
}
void
wasm_array_obj_set_elem(WASMArrayObjectRef array_obj, uint32 elem_idx,
WASMValue *value)
{}
WASMValue *
wasm_array_obj_get_elem(WASMArrayObjectRef array_obj, uint32 elem_idx)
{
return NULL;
}
WASMFuncObjectRef
wasm_func_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj, uint32 func_idx)
{
WASMFuncObjectRef func_obj;
WASMFuncType *func_type;
uint64 total_size;
bh_assert(rtt_obj->type_flag == WASM_TYPE_FUNC);
func_type = (WASMFuncType *)rtt_obj->defined_type;
total_size =
offsetof(WASMFuncObject, param_data) + func_type->total_param_size;
if (!(func_obj = gc_obj_malloc(heap_handle, total_size))) {
return NULL;
}
func_obj->header = (WASMObjectHeader)rtt_obj;
func_obj->func_idx = func_idx;
return func_obj;
}
void
wasm_func_obj_set_param(WASMFuncObjectRef func_obj, uint32 param_idx,
WASMValue *value)
{}
WASMValue *
wasm_func_obj_get_param(const WASMFuncObjectRef func_obj, uint32 param_idx)
{
return NULL;
}
bool
wasm_obj_is_subtype_of(WASMObjectRef obj1, WASMObjectRef obj2)
{
return false;
}