Support stringref proposal (#2651)

This PR implements the WebAssembly stringref proposal:
  https://github.com/WebAssembly/stringref

It adds cmake variable `WAMR_BUILD_STRINGREF` to build the feature,
which will enable GC automatically.

The stringref contains two parts:
- `part 1`: add new ref types in WasmGC, add opcode processing in loader and interpreter
- `part 2`: add a library for string representation/encoding/decoding and so on

To reduce the code size introduced to WAMR, this PR only includes `part 1`,
`part 2` can be provided by embedder, they may use their own implementation,
e.g., Wasmnizer-ts uses JSString from QuickJS to implement stringref:
https://github.com/intel/Wasmnizer-ts/blob/main/runtime-library/stringref/stringref_qjs.c

We will submit another PR of `part 2` and make it as a sample rather than WAMR core part.

Signed-off-by: Su Yihan <yihan.su@intel.com>
Co-authored-by: Xu Jun <jun1.xu@intel.com>
This commit is contained in:
Su Yihan 2023-10-23 12:45:37 +08:00 committed by GitHub
parent 06d46b0fb6
commit 2f45f12cd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 2647 additions and 16 deletions

View File

@ -335,6 +335,14 @@ if (WAMR_BUILD_GC_BINARYEN EQUAL 1)
add_definitions (-DWASM_ENABLE_GC_BINARYEN=1)
message (" GC binaryen compatible mode on")
endif ()
if (WAMR_BUILD_STRINGREF EQUAL 1)
message (" Stringref enabled")
if (NOT DEFINED WAMR_STRINGREF_IMPL_SOURCE)
message (" Using WAMR builtin implementation for stringref")
else ()
message (" Using custom implementation for stringref")
endif()
endif ()
if (WAMR_BUILD_PERF_PROFILING EQUAL 1 OR
WAMR_BUILD_DUMP_CALL_STACK EQUAL 1 OR
WAMR_BUILD_GC EQUAL 1 OR WAMR_BUILD_GC_BINARYEN EQUAL 1)

View File

@ -78,6 +78,10 @@ if (WAMR_BUILD_AOT EQUAL 1)
include (${IWASM_DIR}/aot/iwasm_aot.cmake)
endif ()
if (WAMR_BUILD_STRINGREF EQUAL 1)
set (WAMR_BUILD_GC 1)
endif ()
if (WAMR_BUILD_GC_BINARYEN EQUAL 1)
set (WAMR_BUILD_GC 1)
endif ()

View File

@ -467,6 +467,10 @@
#define WASM_ENABLE_GC_BINARYEN 0
#endif
#ifndef WASM_ENABLE_STRINGREF
#define WASM_ENABLE_STRINGREF 0
#endif
#ifndef GC_REFTYPE_MAP_SIZE_DEFAULT
#define GC_REFTYPE_MAP_SIZE_DEFAULT 64
#endif

View File

@ -19,14 +19,25 @@ wasm_ref_type_normalize(wasm_ref_type_t *ref_type)
int32 heap_type = ref_type->heap_type;
if (!((value_type >= VALUE_TYPE_I16 && value_type <= VALUE_TYPE_I32)
|| (value_type >= VALUE_TYPE_NULLREF
|| (
#if WASM_ENABLE_STRINGREF != 0
value_type >= VALUE_TYPE_STRINGVIEWITER
#else
value_type >= VALUE_TYPE_NULLREF
#endif
&& value_type <= VALUE_TYPE_FUNCREF))) {
return false;
}
if (value_type == VALUE_TYPE_HT_NULLABLE_REF
|| value_type == VALUE_TYPE_HT_NON_NULLABLE_REF) {
if (heap_type < 0
&& (heap_type < HEAP_TYPE_NONE || heap_type > HEAP_TYPE_FUNC)) {
#if WASM_ENABLE_STRINGREF != 0
&& (heap_type < HEAP_TYPE_STRINGVIEWITER
|| heap_type > HEAP_TYPE_FUNC)
#else
&& (heap_type < HEAP_TYPE_NONE || heap_type > HEAP_TYPE_FUNC)
#endif
) {
return false;
}
}
@ -35,9 +46,20 @@ wasm_ref_type_normalize(wasm_ref_type_t *ref_type)
ref_type->nullable = false;
}
else {
if (heap_type >= HEAP_TYPE_NONE && heap_type <= HEAP_TYPE_FUNC) {
if (
#if WASM_ENABLE_STRINGREF != 0
heap_type >= HEAP_TYPE_STRINGVIEWITER && heap_type <= HEAP_TYPE_FUNC
#else
heap_type >= HEAP_TYPE_NONE && heap_type <= HEAP_TYPE_FUNC
#endif
) {
ref_type->value_type =
#if WASM_ENABLE_STRINGREF != 0
(uint8)(REF_TYPE_STRINGVIEWITER + heap_type
- HEAP_TYPE_STRINGVIEWITER);
#else
(uint8)(REF_TYPE_NULLREF + heap_type - HEAP_TYPE_NONE);
#endif
ref_type->nullable = false;
ref_type->heap_type = 0;
}

View File

@ -12,6 +12,9 @@
#if WASM_ENABLE_AOT != 0
#include "../aot/aot_runtime.h"
#endif
#if WASM_ENABLE_STRINGREF != 0
#include "string_object.h"
#endif
WASMRttTypeRef
wasm_rtt_type_new(WASMType *defined_type, uint32 defined_type_idx,
@ -653,6 +656,14 @@ wasm_obj_is_type_of(WASMObjectRef obj, int32 heap_type)
return wasm_obj_is_struct_obj(obj);
case HEAP_TYPE_ARRAY:
return wasm_obj_is_array_obj(obj);
#if WASM_ENABLE_STRINGREF != 0
case HEAP_TYPE_STRINGREF:
return wasm_obj_is_stringref_obj(obj);
case HEAP_TYPE_STRINGVIEWWTF8:
return wasm_obj_is_stringview_wtf8_obj(obj);
case HEAP_TYPE_STRINGVIEWWTF16:
return wasm_obj_is_stringview_wtf16_obj(obj);
#endif
case HEAP_TYPE_NONE:
case HEAP_TYPE_NOFUNC:
case HEAP_TYPE_NOEXTERN:
@ -698,6 +709,18 @@ wasm_object_get_ref_list(WASMObjectRef obj, bool *p_is_compact_mode,
*p_ref_list = NULL;
return true;
}
#if WASM_ENABLE_STRINGREF != 0
else if (rtt_type->type_flag == WASM_TYPE_STRINGREF
|| rtt_type->type_flag == WASM_TYPE_STRINGVIEWWTF8
|| rtt_type->type_flag == WASM_TYPE_STRINGVIEWWTF16
|| rtt_type->type_flag == WASM_TYPE_STRINGVIEWITER) {
/* stringref/stringview_wtf8/stringview_wtf16/stringview_iter object */
*p_is_compact_mode = false;
*p_ref_num = 0;
*p_ref_list = NULL;
return true;
}
#endif /* end of WASM_ENABLE_STRINGREF != 0 */
else if (rtt_type->defined_type->type_flag == WASM_TYPE_FUNC) {
/* function object */
*p_is_compact_mode = false;
@ -750,3 +773,270 @@ wasm_obj_unset_gc_finalizer(wasm_exec_env_t exec_env, void *obj)
void *heap_handle = get_gc_heap_handle(exec_env);
mem_allocator_unset_gc_finalizer(heap_handle, obj);
}
#if WASM_ENABLE_STRINGREF != 0
WASMRttTypeRef
wasm_stringref_rtt_type_new(uint16 type_flag, WASMRttType **rtt_types,
korp_mutex *rtt_type_lock)
{
WASMRttType *rtt_type;
uint32 index;
bh_assert(type_flag >= WASM_TYPE_STRINGREF
&& type_flag <= WASM_TYPE_STRINGVIEWITER);
index = type_flag - WASM_TYPE_STRINGREF;
os_mutex_lock(rtt_type_lock);
if (rtt_types[index]) {
os_mutex_unlock(rtt_type_lock);
return rtt_types[index];
}
if ((rtt_type = wasm_runtime_malloc(sizeof(WASMRttType)))) {
memset(rtt_type, 0, sizeof(WASMRttType));
rtt_type->type_flag = type_flag;
rtt_types[index] = rtt_type;
}
os_mutex_unlock(rtt_type_lock);
return rtt_type;
}
static void
wasm_stringref_obj_finalizer(WASMStringrefObjectRef stringref_obj, void *data)
{
wasm_string_destroy(
(WASMString)wasm_stringref_obj_get_value(stringref_obj));
}
static void
wasm_stringview_wtf8_obj_finalizer(WASMStringviewWTF8ObjectRef stringref_obj,
void *data)
{
wasm_string_destroy(
(WASMString)wasm_stringview_wtf8_obj_get_value(stringref_obj));
}
static void
wasm_stringview_wtf16_obj_finalizer(WASMStringviewWTF16ObjectRef stringref_obj,
void *data)
{
wasm_string_destroy(
(WASMString)wasm_stringview_wtf16_obj_get_value(stringref_obj));
}
static void
wasm_stringview_iter_obj_finalizer(WASMStringviewIterObjectRef stringref_obj,
void *data)
{
wasm_string_destroy(
(WASMString)wasm_stringview_iter_obj_get_value(stringref_obj));
}
static WASMObjectRef
stringref_obj_new(WASMExecEnv *exec_env, uint32 type, const void *str_obj,
int32 pos)
{
WASMObjectRef stringref_obj = NULL;
void *heap_handle = get_gc_heap_handle(exec_env);
WASMModuleInstanceCommon *module_inst =
wasm_runtime_get_module_inst(exec_env);
WASMRttTypeRef rtt_type = NULL;
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
WASMModule *module = ((WASMModuleInstance *)module_inst)->module;
rtt_type = wasm_stringref_rtt_type_new(type, module->stringref_rtts,
&module->rtt_type_lock);
}
#endif
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
AOTModule *module =
(AOTModule *)((AOTModuleInstance *)module_inst)->module;
/* TODO: implement stringref for AoT */
/*
rtt_type = aot_stringref_rtt_type_new(WASM_TYPE_STRINGREF,
module->stringref_rtts,
&module->rtt_type_lock);
*/
}
#endif
if (!rtt_type) {
return NULL;
}
if (type == WASM_TYPE_STRINGREF) {
if (!(stringref_obj =
gc_obj_malloc(heap_handle, sizeof(WASMStringrefObject)))) {
return NULL;
}
((WASMStringrefObjectRef)stringref_obj)->header =
(WASMObjectHeader)rtt_type;
((WASMStringrefObjectRef)stringref_obj)->str_obj = str_obj;
wasm_obj_set_gc_finalizer(
exec_env, (wasm_obj_t)stringref_obj,
(wasm_obj_finalizer_t)wasm_stringref_obj_finalizer, NULL);
}
else if (type == WASM_TYPE_STRINGVIEWWTF8) {
if (!(stringref_obj = gc_obj_malloc(
heap_handle, sizeof(WASMStringviewWTF8Object)))) {
return NULL;
}
((WASMStringviewWTF8ObjectRef)stringref_obj)->header =
(WASMObjectHeader)rtt_type;
((WASMStringviewWTF8ObjectRef)stringref_obj)->str_obj = str_obj;
wasm_obj_set_gc_finalizer(
exec_env, (wasm_obj_t)stringref_obj,
(wasm_obj_finalizer_t)wasm_stringview_wtf8_obj_finalizer, NULL);
}
else if (type == WASM_TYPE_STRINGVIEWWTF16) {
if (!(stringref_obj = gc_obj_malloc(
heap_handle, sizeof(WASMStringviewWTF16Object)))) {
return NULL;
}
((WASMStringviewWTF16ObjectRef)stringref_obj)->header =
(WASMObjectHeader)rtt_type;
((WASMStringviewWTF16ObjectRef)stringref_obj)->str_obj = str_obj;
wasm_obj_set_gc_finalizer(
exec_env, (wasm_obj_t)stringref_obj,
(wasm_obj_finalizer_t)wasm_stringview_wtf16_obj_finalizer, NULL);
}
else if (type == WASM_TYPE_STRINGVIEWITER) {
if (!(stringref_obj = gc_obj_malloc(
heap_handle, sizeof(WASMStringviewIterObject)))) {
return NULL;
}
((WASMStringviewIterObjectRef)stringref_obj)->header =
(WASMObjectHeader)rtt_type;
((WASMStringviewIterObjectRef)stringref_obj)->str_obj = str_obj;
((WASMStringviewIterObjectRef)stringref_obj)->pos = pos;
wasm_obj_set_gc_finalizer(
exec_env, (wasm_obj_t)stringref_obj,
(wasm_obj_finalizer_t)wasm_stringview_iter_obj_finalizer, NULL);
}
return stringref_obj;
}
WASMStringrefObjectRef
wasm_stringref_obj_new(WASMExecEnv *exec_env, const void *str_obj)
{
WASMStringrefObjectRef stringref_obj;
stringref_obj = (WASMStringrefObjectRef)stringref_obj_new(
exec_env, WASM_TYPE_STRINGREF, str_obj, 0);
return stringref_obj;
}
WASMStringviewWTF8ObjectRef
wasm_stringview_wtf8_obj_new(WASMExecEnv *exec_env, const void *str_obj)
{
WASMStringviewWTF8ObjectRef stringview_wtf8_obj;
stringview_wtf8_obj = (WASMStringviewWTF8ObjectRef)stringref_obj_new(
exec_env, WASM_TYPE_STRINGVIEWWTF8, str_obj, 0);
return stringview_wtf8_obj;
}
WASMStringviewWTF16ObjectRef
wasm_stringview_wtf16_obj_new(WASMExecEnv *exec_env, const void *str_obj)
{
WASMStringviewWTF16ObjectRef stringview_wtf16_obj;
stringview_wtf16_obj = (WASMStringviewWTF16ObjectRef)stringref_obj_new(
exec_env, WASM_TYPE_STRINGVIEWWTF16, str_obj, 0);
return stringview_wtf16_obj;
}
WASMStringviewIterObjectRef
wasm_stringview_iter_obj_new(WASMExecEnv *exec_env, const void *str_obj,
int32 pos)
{
WASMStringviewIterObjectRef stringview_iter_obj;
stringview_iter_obj = (WASMStringviewIterObjectRef)stringref_obj_new(
exec_env, WASM_TYPE_STRINGVIEWITER, str_obj, pos);
return stringview_iter_obj;
}
const void *
wasm_stringref_obj_get_value(WASMStringrefObjectRef stringref_obj)
{
return stringref_obj->str_obj;
}
const void *
wasm_stringview_wtf8_obj_get_value(
WASMStringviewWTF8ObjectRef stringview_wtf8_obj)
{
return stringview_wtf8_obj->str_obj;
}
const void *
wasm_stringview_wtf16_obj_get_value(
WASMStringviewWTF16ObjectRef stringview_wtf16_obj)
{
return stringview_wtf16_obj->str_obj;
}
const void *
wasm_stringview_iter_obj_get_value(
WASMStringviewIterObjectRef stringview_iter_obj)
{
return stringview_iter_obj->str_obj;
}
int32
wasm_stringview_iter_obj_get_pos(
WASMStringviewIterObjectRef stringview_iter_obj)
{
return stringview_iter_obj->pos;
}
void
wasm_stringview_iter_obj_update_pos(
WASMStringviewIterObjectRef stringview_iter_obj, int32 pos)
{
stringview_iter_obj->pos = pos;
}
#define WASM_OBJ_IS_STRINGREF_IMPL(flag) \
WASMRttTypeRef rtt_type; \
\
bh_assert(obj); \
\
if (wasm_obj_is_i31_externref_or_anyref_obj(obj)) \
return false; \
\
rtt_type = (WASMRttTypeRef)wasm_object_header(obj); \
return rtt_type->type_flag == flag ? true : false
bool
wasm_obj_is_stringref_obj(WASMObjectRef obj)
{
WASM_OBJ_IS_STRINGREF_IMPL(WASM_TYPE_STRINGREF);
}
bool
wasm_obj_is_stringview_wtf8_obj(WASMObjectRef obj)
{
WASM_OBJ_IS_STRINGREF_IMPL(WASM_TYPE_STRINGVIEWWTF8);
}
bool
wasm_obj_is_stringview_wtf16_obj(WASMObjectRef obj)
{
WASM_OBJ_IS_STRINGREF_IMPL(WASM_TYPE_STRINGVIEWWTF16);
}
#undef WASM_OBJ_IS_STRINGREF_IMPL
#endif /* end of WASM_ENABLE_STRINGREF != 0 */

View File

@ -102,6 +102,28 @@ typedef struct WASMFuncObject {
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
@ -284,6 +306,54 @@ 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

View File

@ -616,7 +616,12 @@ wasm_reftype_size(uint8 type)
return 4;
else if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)
return 8;
#if WASM_ENABLE_STRINGREF != 0
else if (type >= (uint8)REF_TYPE_STRINGVIEWITER
&& type <= (uint8)REF_TYPE_FUNCREF)
#else
else if (type >= (uint8)REF_TYPE_NULLREF && type <= (uint8)REF_TYPE_FUNCREF)
#endif
return sizeof(uintptr_t);
else if (type == PACKED_TYPE_I8)
return 1;
@ -745,13 +750,26 @@ wasm_is_reftype_supers_of_extern(uint8 type)
return (type == REF_TYPE_EXTERNREF) ? true : false;
}
#if WASM_ENABLE_STRINGREF != 0
inline static bool
wasm_is_reftype_supers_of_string(uint8 type)
{
return (type == REF_TYPE_STRINGREF || type == REF_TYPE_ANYREF) ? true
: false;
}
#endif
inline static bool
wasm_is_reftype_supers_of_none(uint8 type, const WASMRefType *ref_type,
const WASMTypePtr *types, uint32 type_count)
{
if (type == REF_TYPE_NULLREF || type == REF_TYPE_I31REF
|| type == REF_TYPE_STRUCTREF || type == REF_TYPE_ARRAYREF
|| wasm_is_reftype_supers_of_eq(type))
|| wasm_is_reftype_supers_of_eq(type)
#if WASM_ENABLE_STRINGREF != 0
|| type == REF_TYPE_STRINGREF
#endif
)
return true;
if (type == REF_TYPE_HT_NULLABLE && ref_type != NULL
@ -875,6 +893,20 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
else if (type1 == REF_TYPE_NULLEXTERNREF) {
return wasm_is_reftype_supers_of_noextern(type2);
}
#if WASM_ENABLE_STRINGREF != 0
else if (type1 == REF_TYPE_STRINGREF) {
return wasm_is_reftype_supers_of_string(type2);
}
else if (type1 == REF_TYPE_STRINGVIEWWTF8) {
return type2 == REF_TYPE_STRINGVIEWWTF8 ? true : false;
}
else if (type1 == REF_TYPE_STRINGVIEWWTF16) {
return type2 == REF_TYPE_STRINGVIEWWTF16 ? true : false;
}
else if (type1 == REF_TYPE_STRINGVIEWITER) {
return type2 == REF_TYPE_STRINGVIEWITER ? true : false;
}
#endif
else if (type1 == REF_TYPE_HT_NULLABLE) {
if (wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)) {
/* reftype1 is (ref null $t) */
@ -895,6 +927,23 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
else if (types[ref_type1->ref_ht_typeidx.type_idx]->type_flag
== WASM_TYPE_FUNC)
return wasm_is_reftype_supers_of_func(type2);
#if WASM_ENABLE_STRINGREF != 0
else if (types[ref_type1->ref_ht_typeidx.type_idx]->type_flag
== WASM_TYPE_STRINGREF)
return wasm_is_reftype_supers_of_string(type2);
else if (types[ref_type1->ref_ht_typeidx.type_idx]->type_flag
== WASM_TYPE_STRINGVIEWWTF8) {
return type2 == REF_TYPE_STRINGVIEWWTF8 ? true : false;
}
else if (types[ref_type1->ref_ht_typeidx.type_idx]->type_flag
== WASM_TYPE_STRINGVIEWWTF16) {
return type2 == REF_TYPE_STRINGVIEWWTF16 ? true : false;
}
else if (types[ref_type1->ref_ht_typeidx.type_idx]->type_flag
== WASM_TYPE_STRINGVIEWITER) {
return type2 == REF_TYPE_STRINGVIEWITER ? true : false;
}
#endif
else
return false;
}
@ -1019,6 +1068,20 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
/* (ref func) <: [funcref] */
return wasm_is_reftype_supers_of_func(type2);
}
#if WASM_ENABLE_STRINGREF != 0
else if (heap_type == HEAP_TYPE_STRINGREF) {
return wasm_is_reftype_supers_of_string(type2);
}
else if (heap_type == HEAP_TYPE_STRINGVIEWWTF8) {
return type2 == REF_TYPE_STRINGVIEWWTF8 ? true : false;
}
else if (heap_type == HEAP_TYPE_STRINGVIEWWTF16) {
return type2 == REF_TYPE_STRINGVIEWWTF16 ? true : false;
}
else if (heap_type == HEAP_TYPE_STRINGVIEWITER) {
return type2 == REF_TYPE_STRINGVIEWITER ? true : false;
}
#endif
else if (heap_type == HEAP_TYPE_NONE) {
/* (ref none) */
/* TODO */

View File

@ -120,7 +120,13 @@ wasm_type_is_subtype_of(const WASMType *type1, const WASMType *type2,
inline static bool
wasm_is_type_reftype(uint8 type)
{
return (type >= (uint8)REF_TYPE_NULLREF && type <= (uint8)REF_TYPE_FUNCREF)
return (
#if WASM_ENABLE_STRINGREF != 0
type >= (uint8)REF_TYPE_STRINGVIEWITER
#else
type >= (uint8)REF_TYPE_NULLREF
#endif
&& type <= (uint8)REF_TYPE_FUNCREF)
? true
: false;
}
@ -244,8 +250,14 @@ wasm_is_refheaptype_common(const RefHeapType_Common *ref_heap_type)
{
return ((ref_heap_type->heap_type >= (int32)HEAP_TYPE_EQ
&& ref_heap_type->heap_type <= (int32)HEAP_TYPE_FUNC)
#if WASM_ENABLE_STRINGREF != 0
|| (ref_heap_type->heap_type >= (int32)HEAP_TYPE_STRINGVIEWITER
&& ref_heap_type->heap_type <= (int32)HEAP_TYPE_I31)
#else
|| (ref_heap_type->heap_type >= (int32)HEAP_TYPE_NONE
&& ref_heap_type->heap_type <= (int32)HEAP_TYPE_I31))
&& ref_heap_type->heap_type <= (int32)HEAP_TYPE_I31)
#endif
)
? true
: false;
}
@ -285,6 +297,17 @@ wasm_is_refheaptype_array(const RefHeapType_Common *ref_heap_type)
return ref_heap_type->heap_type == (int32)HEAP_TYPE_ARRAY ? true : false;
}
#if WASM_ENABLE_STRINGREF != 0
inline static bool
wasm_is_refheaptype_stringrefs(const RefHeapType_Common *ref_heap_type)
{
return ref_heap_type->heap_type <= (int32)HEAP_TYPE_STRINGREF
&& ref_heap_type->heap_type >= HEAP_TYPE_STRINGVIEWITER
? true
: false;
}
#endif
/* Whether two ref heap types are equal */
bool
wasm_refheaptype_equal(const RefHeapType_Common *ref_heap_type1,

View File

@ -11,7 +11,22 @@ endif ()
include_directories (${IWASM_GC_DIR})
file (GLOB_RECURSE source_all ${IWASM_GC_DIR}/*.c)
file (GLOB source_all ${IWASM_GC_DIR}/*.c)
set (IWASM_GC_SOURCE ${source_all})
if (WAMR_BUILD_STRINGREF EQUAL 1)
set (IWASM_STRINGREF_DIR ${CMAKE_CURRENT_LIST_DIR}/stringref)
add_definitions (-DWASM_ENABLE_STRINGREF=1)
include_directories (${IWASM_STRINGREF_DIR})
if (NOT DEFINED WAMR_STRINGREF_IMPL_SOURCE)
message(FATAL_ERROR "stringref feature enabled, but WAMR_STRINGREF_IMPL_SOURCE not set" )
else ()
set (IWASM_STRINGREF_SOURCE ${WAMR_STRINGREF_IMPL_SOURCE})
endif ()
set (IWASM_GC_SOURCE ${IWASM_GC_SOURCE} ${IWASM_STRINGREF_SOURCE})
endif ()

View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _STRING_OBJECT_H_
#define _STRING_OBJECT_H_
#include "wasm.h"
typedef enum EncodingFlag {
UTF8,
WTF8,
WTF16,
LOSSY_UTF8,
} EncodingFlag;
typedef enum StringViewType {
STRING_VIEW_WTF8,
STRING_VIEW_WTF16,
STRING_VIEW_ITER,
} StringViewType;
typedef enum ErrorCode {
Insufficient_Space = -3,
Encode_Fail = -2,
Isolated_Surrogate = -1,
} ErrorCode;
/******************* gc finalizer *****************/
void
wasm_string_destroy(WASMString str_obj);
/******************* opcode functions *****************/
/* string.const */
WASMString
wasm_string_new_const(const char *str);
/* string.new_xx8/new_wtf16 */
/* string.new_xx8_array */
/* string.new_wtf16_array */
WASMString
wasm_string_new_with_encoding(void *addr, uint32 count, EncodingFlag flag);
/* string.measure */
int32
wasm_string_measure(WASMString str_obj, EncodingFlag flag);
/* stringview_wtf16.length */
int32
wasm_string_wtf16_get_length(WASMString str_obj);
/* string.encode_xx8 */
/* string.encode_wtf16 */
/* stringview_wtf8.encode_xx */
/* stringview_wtf16.encode */
/* string.encode_xx8_array */
/* string.encode_wtf16_array */
int32
wasm_string_encode(WASMString str_obj, uint32 pos, uint32 count, void *addr,
uint32 *next_pos, EncodingFlag flag);
/* string.concat */
WASMString
wasm_string_concat(WASMString str_obj1, WASMString str_obj2);
/* string.eq */
int32
wasm_string_eq(WASMString str_obj1, WASMString str_obj2);
/* string.is_usv_sequence */
int32
wasm_string_is_usv_sequence(WASMString str_obj);
/* string.as_wtf8 */
/* string.as_wtf16 */
/* string.as_iter */
WASMString
wasm_string_create_view(WASMString str_obj, StringViewType type);
/* stringview_wtf8.advance */
/* stringview_iter.advance */
int32
wasm_string_advance(WASMString str_obj, uint32 pos, uint32 count,
uint32 *target_pos);
/* stringview_wtf8.slice */
/* stringview_wtf16.slice */
/* stringview_iter.slice */
WASMString
wasm_string_slice(WASMString str_obj, uint32 start, uint32 end,
StringViewType type);
/* stringview_wtf16.get_codeunit */
int16
wasm_string_get_wtf16_codeunit(WASMString str_obj, int32 pos);
/* stringview_iter.next */
uint32
wasm_string_next_codepoint(WASMString str_obj, uint32 pos);
/* stringview_iter.rewind */
uint32
wasm_string_rewind(WASMString str_obj, uint32 pos, uint32 count,
uint32 *target_pos);
/******************* application functions *****************/
void
wasm_string_dump(WASMString str_obj);
#endif /* end of _STRING_OBJECT_H_ */

View File

@ -15,6 +15,9 @@
#endif
#if WASM_ENABLE_GC != 0
#include "gc/gc_object.h"
#if WASM_ENABLE_STRINGREF != 0
#include "string_object.h"
#endif
#endif
static void
@ -718,6 +721,18 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
}
else if (wasm_obj_is_func_obj(gc_obj))
os_printf("ref.func");
#if WASM_ENABLE_STRINGREF != 0
else if (wasm_obj_is_stringref_obj(gc_obj)
|| wasm_obj_is_stringview_wtf8_obj(gc_obj)) {
wasm_string_dump(
(WASMString)wasm_stringref_obj_get_value(gc_obj));
}
else if (wasm_obj_is_stringview_wtf16_obj(gc_obj)) {
wasm_string_dump(
(WASMString)wasm_stringview_wtf16_obj_get_value(
gc_obj));
}
#endif
else if (wasm_obj_is_externref_obj(gc_obj)) {
WASMObjectRef obj = wasm_externref_obj_to_internal_obj(
(WASMExternrefObjectRef)gc_obj);

View File

@ -96,7 +96,11 @@ compare_type_with_signautre(uint8 type, const char signature)
#if WASM_ENABLE_REF_TYPES != 0
if ('r' == signature
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_STRINGREF != 0
&& (type >= REF_TYPE_STRINGVIEWITER && type <= REF_TYPE_FUNCREF)
#else
&& (type >= REF_TYPE_NULLREF && type <= REF_TYPE_FUNCREF)
#endif
#else
&& type == VALUE_TYPE_EXTERNREF
#endif

View File

@ -3569,6 +3569,12 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
{
bh_memcpy_s(argv_dst, sizeof(uintptr_t), argv_src,
sizeof(uintptr_t));
@ -3632,6 +3638,12 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
{
bh_memcpy_s(argv_ret, sizeof(uintptr_t), argv1,
sizeof(uintptr_t));
@ -3734,6 +3746,12 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
@ -3892,6 +3910,12 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
@ -4111,6 +4135,12 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
@ -4257,6 +4287,12 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
@ -4357,6 +4393,12 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
@ -4616,6 +4658,12 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *(uint64 *)argv_src;
@ -4719,6 +4767,12 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
PUT_I64_TO_ADDR(argv_ret,
invokeNative_Int64(func_ptr, argv1, n_stacks));

View File

@ -34,6 +34,10 @@ typedef enum wasm_value_type_enum {
VALUE_TYPE_STRUCTREF = 0x67,
VALUE_TYPE_ARRAYREF = 0x66,
VALUE_TYPE_NULLREF = 0x65,
VALUE_TYPE_STRINGREF = 0X64,
VALUE_TYPE_STRINGVIEWWTF8 = 0x63,
VALUE_TYPE_STRINGVIEWWTF16 = 0x62,
VALUE_TYPE_STRINGVIEWITER = 0x61
} wasm_value_type_enum;
typedef int32_t wasm_heap_type_t;
@ -133,6 +137,7 @@ typedef struct WASMAnyrefObject *wasm_anyref_obj_t;
typedef struct WASMStructObject *wasm_struct_obj_t;
typedef struct WASMArrayObject *wasm_array_obj_t;
typedef struct WASMFuncObject *wasm_func_obj_t;
typedef struct WASMStringrefObject *wasm_stringref_obj_t;
typedef uintptr_t wasm_i31_obj_t;
typedef void (*wasm_obj_finalizer_t)(const wasm_obj_t obj, void *data);

View File

@ -44,6 +44,10 @@ extern "C" {
#define REF_TYPE_STRUCTREF 0x67
#define REF_TYPE_ARRAYREF 0x66
#define REF_TYPE_NULLREF 0x65
#define REF_TYPE_STRINGREF VALUE_TYPE_STRINGREF
#define REF_TYPE_STRINGVIEWWTF8 VALUE_TYPE_STRINGVIEWWTF8
#define REF_TYPE_STRINGVIEWWTF16 VALUE_TYPE_STRINGVIEWWTF16
#define REF_TYPE_STRINGVIEWITER VALUE_TYPE_STRINGVIEWITER
/* Heap Types */
#define HEAP_TYPE_FUNC (-0x10)
@ -56,6 +60,10 @@ extern "C" {
#define HEAP_TYPE_STRUCT (-0x19)
#define HEAP_TYPE_ARRAY (-0x1A)
#define HEAP_TYPE_NONE (-0x1B)
#define HEAP_TYPE_STRINGREF (-0x1C)
#define HEAP_TYPE_STRINGVIEWWTF8 (-0x1D)
#define HEAP_TYPE_STRINGVIEWWTF16 (-0x1E)
#define HEAP_TYPE_STRINGVIEWITER (-0x1F)
/* Defined Types */
#define DEFINED_TYPE_FUNC 0x60
@ -71,7 +79,7 @@ extern "C" {
* Used by loader to represent any type of i32/i64/f32/f64/v128
* and ref types, including funcref, externref, anyref, eqref,
* (ref null $ht), (ref $ht), i31ref, structref, arrayref,
* nullfuncref, nullexternref and nullref
* nullfuncref, nullexternref, nullref and stringref
*/
#define VALUE_TYPE_ANY 0x42
/**
@ -132,6 +140,9 @@ typedef void *table_elem_type_t;
#if WASM_ENABLE_BULK_MEMORY != 0
#define SECTION_TYPE_DATACOUNT 12
#endif
#if WASM_ENABLE_STRINGREF != 0
#define SECTION_TYPE_STRINGREF 14
#endif
#define SUB_SECTION_TYPE_MODULE 0
#define SUB_SECTION_TYPE_FUNC 1
@ -156,6 +167,13 @@ typedef void *table_elem_type_t;
#define WASM_TYPE_STRUCT 1
#define WASM_TYPE_ARRAY 2
#if WASM_ENABLE_STRINGREF != 0
#define WASM_TYPE_STRINGREF 3
#define WASM_TYPE_STRINGVIEWWTF8 4
#define WASM_TYPE_STRINGVIEWWTF16 5
#define WASM_TYPE_STRINGVIEWITER 6
#endif
typedef struct WASMModule WASMModule;
typedef struct WASMFunction WASMFunction;
typedef struct WASMGlobal WASMGlobal;
@ -353,6 +371,36 @@ typedef struct WASMArrayType {
described with one byte */
WASMRefType *elem_ref_type;
} WASMArrayType;
#if WASM_ENABLE_STRINGREF != 0
/* stringref representation, we define it as a void * pointer here, the
* stringref implementation can use any structure */
/*
WasmGC heap
+-----------------------+
| |
| stringref |
| +----------+ | external string representation
| | host_ptr |--------o------+----->+------------+
| +----------+ | | | |
| | | +------------+
| stringview_wtf8/16 | |
| +----------+ | |
| | host_ptr |--------o------+
| +----------+ | |
| | |
| stringview_iter | |
| +----------+ | |
| | host_ptr |--------o------+
| +----------+ |
| | pos | |
| +----------+ |
| |
+-----------------------+
*/
typedef void *WASMString;
#endif /* end of WASM_ENABLE_STRINGREF != 0 */
#endif /* end of WASM_ENABLE_GC != 0 */
typedef struct WASMTable {
@ -680,6 +728,12 @@ struct WASMModule {
#if WASM_ENABLE_BULK_MEMORY != 0
/* data count read from datacount section */
uint32 data_seg_count1;
#endif
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_STRINGREF != 0
uint32 stringref_count;
char **string_consts;
#endif
#endif
uint32 import_function_count;
@ -760,6 +814,15 @@ struct WASMModule {
HashMap *ref_type_set;
struct WASMRttType **rtt_types;
korp_mutex rtt_type_lock;
#if WASM_ENABLE_STRINGREF != 0
/* special rtts for stringref types
- stringref
- stringview_wtf8
- stringview_wtf16
- stringview_iter
*/
struct WASMRttType *stringref_rtts[4];
#endif
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_DEBUG_AOT != 0
@ -970,7 +1033,12 @@ wasm_value_type_size_ex(uint8 value_type, bool gc_enabled)
else if (value_type == VALUE_TYPE_V128)
return sizeof(int64) * 2;
#endif
else if (value_type >= (uint8)REF_TYPE_NULLREF /* 0x65 */
else if (
#if WASM_ENABLE_STRINGREF != 0
value_type >= (uint8)REF_TYPE_STRINGVIEWITER /* 0x61 */
#else
value_type >= (uint8)REF_TYPE_NULLREF /* 0x65 */
#endif
&& value_type <= (uint8)REF_TYPE_FUNCREF /* 0x70 */ && gc_enabled)
return sizeof(uintptr_t);
else if (value_type == VALUE_TYPE_FUNCREF

View File

@ -13,6 +13,9 @@
#if WASM_ENABLE_GC != 0
#include "../common/gc/gc_object.h"
#include "mem_alloc.h"
#if WASM_ENABLE_STRINGREF != 0
#include "string_object.h"
#endif
#endif
#if WASM_ENABLE_SHARED_MEMORY != 0
#include "../common/wasm_shared_memory.h"
@ -1391,6 +1394,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMFuncObjectRef func_obj;
WASMI31ObjectRef i31_obj;
WASMExternrefObjectRef externref_obj;
#if WASM_ENABLE_STRINGREF != 0
WASMString str_obj = NULL;
WASMStringrefObjectRef stringref_obj;
WASMStringviewWTF8ObjectRef stringview_wtf8_obj;
WASMStringviewWTF16ObjectRef stringview_wtf16_obj;
WASMStringviewIterObjectRef stringview_iter_obj;
#endif
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
@ -2672,6 +2682,727 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP_END();
}
#if WASM_ENABLE_STRINGREF != 0
case WASM_OP_STRING_NEW_UTF8:
case WASM_OP_STRING_NEW_WTF16:
case WASM_OP_STRING_NEW_LOSSY_UTF8:
case WASM_OP_STRING_NEW_WTF8:
{
uint32 mem_idx, addr, bytes_length, offset = 0;
EncodingFlag flag = WTF8;
read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
bytes_length = POP_I32();
addr = POP_I32();
CHECK_MEMORY_OVERFLOW(bytes_length);
if (opcode == WASM_OP_STRING_NEW_WTF16) {
flag = WTF16;
}
else if (opcode == WASM_OP_STRING_NEW_UTF8) {
flag = UTF8;
}
else if (opcode == WASM_OP_STRING_NEW_LOSSY_UTF8) {
flag = LOSSY_UTF8;
}
else if (opcode == WASM_OP_STRING_NEW_WTF8) {
flag = WTF8;
}
str_obj = wasm_string_new_with_encoding(
maddr, bytes_length, flag);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
(void)mem_idx;
HANDLE_OP_END();
}
case WASM_OP_STRING_CONST:
{
WASMModule *wasm_module = module->module;
uint32 contents;
read_leb_uint32(frame_ip, frame_ip_end, contents);
str_obj = wasm_string_new_const(
wasm_module->string_consts[contents]);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_MEASURE_UTF8:
case WASM_OP_STRING_MEASURE_WTF8:
case WASM_OP_STRING_MEASURE_WTF16:
{
int32 target_bytes_length;
EncodingFlag flag = WTF8;
stringref_obj = POP_REF();
if (opcode == WASM_OP_STRING_MEASURE_WTF16) {
flag = WTF16;
}
else if (opcode == WASM_OP_STRING_MEASURE_UTF8) {
flag = UTF8;
}
else if (opcode == WASM_OP_STRING_MEASURE_WTF8) {
flag = LOSSY_UTF8;
}
target_bytes_length = wasm_string_measure(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj),
flag);
PUSH_I32(target_bytes_length);
HANDLE_OP_END();
}
case WASM_OP_STRING_ENCODE_UTF8:
case WASM_OP_STRING_ENCODE_WTF16:
case WASM_OP_STRING_ENCODE_LOSSY_UTF8:
case WASM_OP_STRING_ENCODE_WTF8:
{
uint32 mem_idx, addr;
int32 target_bytes_length;
WASMMemoryInstance *memory_inst;
EncodingFlag flag = WTF8;
read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
addr = POP_I32();
stringref_obj = POP_REF();
str_obj = (WASMString)wasm_stringref_obj_get_value(
stringref_obj);
memory_inst = module->memories[mem_idx];
maddr = memory_inst->memory_data + addr;
if (opcode == WASM_OP_STRING_ENCODE_WTF16) {
flag = WTF16;
count = wasm_string_measure(str_obj, flag);
target_bytes_length = wasm_string_encode(
str_obj, 0, count, maddr, NULL, flag);
}
else {
if (opcode == WASM_OP_STRING_ENCODE_UTF8) {
flag = UTF8;
}
else if (opcode
== WASM_OP_STRING_ENCODE_LOSSY_UTF8) {
flag = LOSSY_UTF8;
}
else if (opcode == WASM_OP_STRING_ENCODE_WTF8) {
flag = WTF8;
}
count = wasm_string_measure(str_obj, flag);
target_bytes_length = wasm_string_encode(
str_obj, 0, count, maddr, NULL, flag);
if (target_bytes_length == -1) {
wasm_set_exception(
module, "isolated surrogate is seen");
goto got_exception;
}
}
if (target_bytes_length < 0) {
wasm_set_exception(module,
"stringref encode failed");
goto got_exception;
}
PUSH_I32(target_bytes_length);
HANDLE_OP_END();
}
case WASM_OP_STRING_CONCAT:
{
WASMStringrefObjectRef stringref_obj1, stringref_obj2;
stringref_obj2 = POP_REF();
stringref_obj1 = POP_REF();
str_obj = wasm_string_concat(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj1),
(WASMString)wasm_stringref_obj_get_value(
stringref_obj2));
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_EQ:
{
WASMStringrefObjectRef stringref_obj1, stringref_obj2;
int32 is_eq;
stringref_obj2 = POP_REF();
stringref_obj1 = POP_REF();
is_eq = wasm_string_eq(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj1),
(WASMString)wasm_stringref_obj_get_value(
stringref_obj2));
PUSH_I32(is_eq);
HANDLE_OP_END();
}
case WASM_OP_STRING_IS_USV_SEQUENCE:
{
int32 is_usv_sequence;
stringref_obj = POP_REF();
is_usv_sequence = wasm_string_is_usv_sequence(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj));
PUSH_I32(is_usv_sequence);
HANDLE_OP_END();
}
case WASM_OP_STRING_AS_WTF8:
{
stringref_obj = POP_REF();
str_obj = wasm_string_create_view(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj),
STRING_VIEW_WTF8);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringview_wtf8_obj =
wasm_stringview_wtf8_obj_new(exec_env, str_obj);
if (!stringview_wtf8_obj) {
wasm_set_exception(module,
"create stringview wtf8 failed");
goto got_exception;
}
PUSH_REF(stringview_wtf8_obj);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF8_ADVANCE:
{
uint32 next_pos, bytes, pos;
bytes = POP_I32();
pos = POP_I32();
stringview_wtf8_obj = POP_REF();
next_pos = wasm_string_advance(
(WASMString)wasm_stringview_wtf8_obj_get_value(
stringview_wtf8_obj),
pos, bytes, NULL);
PUSH_I32(next_pos);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF8_ENCODE_UTF8:
case WASM_OP_STRINGVIEW_WTF8_ENCODE_LOSSY_UTF8:
case WASM_OP_STRINGVIEW_WTF8_ENCODE_WTF8:
{
uint32 mem_idx, addr, pos, bytes, next_pos;
int32 bytes_written;
WASMMemoryInstance *memory_inst;
EncodingFlag flag = WTF8;
if (opcode == WASM_OP_STRINGVIEW_WTF8_ENCODE_UTF8) {
flag = UTF8;
}
else if (opcode
== WASM_OP_STRINGVIEW_WTF8_ENCODE_LOSSY_UTF8) {
flag = LOSSY_UTF8;
}
else if (opcode
== WASM_OP_STRINGVIEW_WTF8_ENCODE_WTF8) {
flag = WTF8;
}
read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
bytes = POP_I32();
pos = POP_I32();
addr = POP_I32();
stringview_wtf8_obj = POP_REF();
memory_inst = module->memories[mem_idx];
maddr = memory_inst->memory_data + addr;
bytes_written = wasm_string_encode(
(WASMString)wasm_stringview_wtf8_obj_get_value(
stringview_wtf8_obj),
pos, bytes, maddr, &next_pos, flag);
if (bytes_written < 0) {
if (bytes_written == Isolated_Surrogate) {
wasm_set_exception(
module, "isolated surrogate is seen");
}
else {
wasm_set_exception(module, "encode failed");
}
goto got_exception;
}
PUSH_I32(next_pos);
PUSH_I32(bytes_written);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF8_SLICE:
{
uint32 start, end;
end = POP_I32();
start = POP_I32();
stringview_wtf8_obj = POP_REF();
str_obj = wasm_string_slice(
(WASMString)wasm_stringview_wtf8_obj_get_value(
stringview_wtf8_obj),
start, end, STRING_VIEW_WTF8);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_AS_WTF16:
{
stringref_obj = POP_REF();
str_obj = wasm_string_create_view(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj),
STRING_VIEW_WTF16);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringview_wtf16_obj =
wasm_stringview_wtf16_obj_new(exec_env, str_obj);
if (!stringview_wtf16_obj) {
wasm_set_exception(
module, "create stringview wtf16 failed");
goto got_exception;
}
PUSH_REF(stringview_wtf16_obj);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF16_LENGTH:
{
int32 code_units_length;
stringview_wtf16_obj = POP_REF();
code_units_length = wasm_string_wtf16_get_length(
(WASMString)wasm_stringview_wtf16_obj_get_value(
stringview_wtf16_obj));
PUSH_I32(code_units_length);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF16_GET_CODEUNIT:
{
int32 pos;
uint32 code_unit;
pos = POP_I32();
stringview_wtf16_obj = POP_REF();
code_unit = (uint32)wasm_string_get_wtf16_codeunit(
(WASMString)wasm_stringview_wtf16_obj_get_value(
stringview_wtf16_obj),
pos);
PUSH_I32(code_unit);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF16_ENCODE:
{
uint32 mem_idx, addr, pos, len, offset = 0;
int32 written_code_units = 0;
read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
len = POP_I32();
pos = POP_I32();
addr = POP_I32();
stringview_wtf16_obj = POP_REF();
CHECK_MEMORY_OVERFLOW(len * sizeof(uint16));
/* check 2-byte alignment */
if (((uintptr_t)maddr & (((uintptr_t)1 << 2) - 1))
!= 0) {
wasm_set_exception(module,
"unaligned memory access");
goto got_exception;
}
written_code_units = wasm_string_encode(
(WASMString)wasm_stringview_wtf16_obj_get_value(
stringview_wtf16_obj),
pos, len, maddr, NULL, WTF16);
if (written_code_units < 0) {
wasm_set_exception(module, "encode failed");
goto got_exception;
}
PUSH_I32(written_code_units);
(void)mem_idx;
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF16_SLICE:
{
uint32 start, end;
end = POP_I32();
start = POP_I32();
stringview_wtf16_obj = POP_REF();
str_obj = wasm_string_slice(
(WASMString)wasm_stringview_wtf16_obj_get_value(
stringview_wtf16_obj),
start, end, STRING_VIEW_WTF16);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_AS_ITER:
{
stringref_obj = POP_REF();
str_obj = wasm_string_create_view(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj),
STRING_VIEW_ITER);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringview_iter_obj =
wasm_stringview_iter_obj_new(exec_env, str_obj, 0);
if (!stringview_iter_obj) {
wasm_set_exception(module,
"create stringview iter failed");
goto got_exception;
}
PUSH_REF(stringview_iter_obj);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_ITER_NEXT:
{
uint32 code_point;
stringview_iter_obj = POP_REF();
code_point = wasm_string_next_codepoint(
(WASMString)wasm_stringview_iter_obj_get_value(
stringview_iter_obj),
wasm_stringview_iter_obj_get_pos(
stringview_iter_obj));
PUSH_I32(code_point);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_ITER_ADVANCE:
case WASM_OP_STRINGVIEW_ITER_REWIND:
{
uint32 code_points_count, code_points_consumed = 0,
cur_pos, next_pos = 0;
code_points_count = POP_I32();
stringview_iter_obj = POP_REF();
str_obj =
(WASMString)wasm_stringview_iter_obj_get_value(
stringview_iter_obj);
cur_pos = wasm_stringview_iter_obj_get_pos(
stringview_iter_obj);
if (opcode == WASM_OP_STRINGVIEW_ITER_ADVANCE) {
next_pos = wasm_string_advance(
str_obj, cur_pos, code_points_count,
&code_points_consumed);
}
else if (opcode == WASM_OP_STRINGVIEW_ITER_REWIND) {
next_pos = wasm_string_rewind(
str_obj, cur_pos, code_points_count,
&code_points_consumed);
}
wasm_stringview_iter_obj_update_pos(stringview_iter_obj,
next_pos);
PUSH_I32(code_points_consumed);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_ITER_SLICE:
{
uint32 code_points_count, cur_pos;
code_points_count = POP_I32();
stringview_iter_obj = POP_REF();
cur_pos = wasm_stringview_iter_obj_get_pos(
stringview_iter_obj);
str_obj = wasm_string_slice(
(WASMString)wasm_stringview_iter_obj_get_value(
stringview_iter_obj),
cur_pos, code_points_count, STRING_VIEW_ITER);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_NEW_UTF8_ARRAY:
case WASM_OP_STRING_NEW_WTF16_ARRAY:
case WASM_OP_STRING_NEW_LOSSY_UTF8_ARRAY:
case WASM_OP_STRING_NEW_WTF8_ARRAY:
{
uint32 start, end, array_len;
EncodingFlag flag = WTF8;
WASMArrayType *array_type;
void *arr_start_addr;
end = POP_I32();
start = POP_I32();
array_obj = POP_REF();
array_type = (WASMArrayType *)wasm_obj_get_defined_type(
(WASMObjectRef)array_obj);
arr_start_addr =
wasm_array_obj_elem_addr(array_obj, start);
array_len = wasm_array_obj_length(array_obj);
if (start > end || end > array_len) {
wasm_set_exception(module,
"array index out of bounds");
goto got_exception;
}
if (opcode == WASM_OP_STRING_NEW_WTF16_ARRAY) {
if (array_type->elem_type != VALUE_TYPE_I16) {
wasm_set_exception(module,
"array type mismatch");
goto got_exception;
}
flag = WTF16;
}
else {
if (array_type->elem_type != VALUE_TYPE_I8) {
wasm_set_exception(module,
"array type mismatch");
goto got_exception;
}
if (opcode == WASM_OP_STRING_NEW_UTF8_ARRAY) {
flag = UTF8;
}
else if (opcode == WASM_OP_STRING_NEW_WTF8_ARRAY) {
flag = WTF8;
}
else if (opcode
== WASM_OP_STRING_NEW_LOSSY_UTF8_ARRAY) {
flag = LOSSY_UTF8;
}
}
str_obj = wasm_string_new_with_encoding(
arr_start_addr, (end - start), flag);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_ENCODE_UTF8_ARRAY:
case WASM_OP_STRING_ENCODE_WTF16_ARRAY:
case WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY:
case WASM_OP_STRING_ENCODE_WTF8_ARRAY:
{
uint32 start, array_len;
int32 bytes_written;
EncodingFlag flag = WTF8;
WASMArrayType *array_type;
void *arr_start_addr;
start = POP_I32();
array_obj = POP_REF();
stringref_obj = POP_REF();
str_obj = (WASMString)wasm_stringref_obj_get_value(
stringref_obj);
array_type = (WASMArrayType *)wasm_obj_get_defined_type(
(WASMObjectRef)array_obj);
arr_start_addr =
wasm_array_obj_elem_addr(array_obj, start);
array_len = wasm_array_obj_length(array_obj);
if (start > array_len) {
wasm_set_exception(module,
"array index out of bounds");
goto got_exception;
}
if (opcode == WASM_OP_STRING_ENCODE_WTF16_ARRAY) {
if (array_type->elem_type != VALUE_TYPE_I16) {
wasm_set_exception(module,
"array type mismatch");
goto got_exception;
}
flag = WTF16;
}
else {
if (array_type->elem_type != VALUE_TYPE_I8) {
wasm_set_exception(module,
"array type mismatch");
goto got_exception;
}
if (opcode == WASM_OP_STRING_ENCODE_UTF8_ARRAY) {
flag = UTF8;
}
else if (opcode
== WASM_OP_STRING_ENCODE_WTF8_ARRAY) {
flag = WTF8;
}
else if (
opcode
== WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY) {
flag = LOSSY_UTF8;
}
}
bytes_written =
wasm_string_encode(str_obj, start, array_len,
arr_start_addr, NULL, flag);
if (bytes_written < 0) {
if (bytes_written == Isolated_Surrogate) {
wasm_set_exception(
module, "isolated surrogate is seen");
}
else if (bytes_written == Insufficient_Space) {
wasm_set_exception(
module, "array space is insufficient");
}
else {
wasm_set_exception(module, "encode failed");
}
goto got_exception;
}
PUSH_I32(bytes_written);
HANDLE_OP_END();
}
#endif /* end of WASM_ENABLE_STRINGREF != 0 */
default:
{
wasm_set_exception(module, "unsupported opcode");

View File

@ -13,6 +13,9 @@
#if WASM_ENABLE_GC != 0
#include "../common/gc/gc_object.h"
#include "mem_alloc.h"
#if WASM_ENABLE_STRINGREF != 0
#include "string_object.h"
#endif
#endif
#if WASM_ENABLE_SHARED_MEMORY != 0
#include "../common/wasm_shared_memory.h"
@ -1477,6 +1480,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMI31ObjectRef i31_obj;
WASMExternrefObjectRef externref_obj;
uint32 type_idx;
#if WASM_ENABLE_STRINGREF != 0
WASMString str_obj;
WASMStringrefObjectRef stringref_obj;
WASMStringviewWTF8ObjectRef stringview_wtf8_obj;
WASMStringviewWTF16ObjectRef stringview_wtf16_obj;
WASMStringviewIterObjectRef stringview_iter_obj;
#endif
#endif
#if WASM_ENABLE_LABELS_AS_VALUES != 0
@ -2608,6 +2618,722 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP_END();
}
#if WASM_ENABLE_STRINGREF != 0
case WASM_OP_STRING_NEW_UTF8:
case WASM_OP_STRING_NEW_WTF16:
case WASM_OP_STRING_NEW_LOSSY_UTF8:
case WASM_OP_STRING_NEW_WTF8:
{
uint32 mem_idx, addr, bytes_length, offset = 0;
EncodingFlag flag = WTF8;
mem_idx = (uint32)read_uint32(frame_ip);
bytes_length = POP_I32();
addr = POP_I32();
CHECK_MEMORY_OVERFLOW(bytes_length);
if (opcode == WASM_OP_STRING_NEW_WTF16) {
flag = WTF16;
}
else if (opcode == WASM_OP_STRING_NEW_UTF8) {
flag = UTF8;
}
else if (opcode == WASM_OP_STRING_NEW_LOSSY_UTF8) {
flag = LOSSY_UTF8;
}
else if (opcode == WASM_OP_STRING_NEW_WTF8) {
flag = WTF8;
}
str_obj = wasm_string_new_with_encoding(
maddr, bytes_length, flag);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
(void)mem_idx;
HANDLE_OP_END();
}
case WASM_OP_STRING_CONST:
{
WASMModule *wasm_module = module->module;
uint32 contents;
contents = (uint32)read_uint32(frame_ip);
str_obj = wasm_string_new_const(
wasm_module->string_consts[contents]);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!str_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_MEASURE_UTF8:
case WASM_OP_STRING_MEASURE_WTF8:
case WASM_OP_STRING_MEASURE_WTF16:
{
int32 target_bytes_length;
EncodingFlag flag = WTF8;
stringref_obj = POP_REF();
if (opcode == WASM_OP_STRING_MEASURE_WTF16) {
flag = WTF16;
}
else if (opcode == WASM_OP_STRING_MEASURE_UTF8) {
flag = UTF8;
}
else if (opcode == WASM_OP_STRING_MEASURE_WTF8) {
flag = LOSSY_UTF8;
}
target_bytes_length = wasm_string_measure(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj),
flag);
PUSH_I32(target_bytes_length);
HANDLE_OP_END();
}
case WASM_OP_STRING_ENCODE_UTF8:
case WASM_OP_STRING_ENCODE_WTF16:
case WASM_OP_STRING_ENCODE_LOSSY_UTF8:
case WASM_OP_STRING_ENCODE_WTF8:
{
uint32 mem_idx, addr;
int32 target_bytes_length;
WASMMemoryInstance *memory_inst;
EncodingFlag flag = WTF8;
mem_idx = (uint32)read_uint32(frame_ip);
addr = POP_I32();
stringref_obj = POP_REF();
str_obj = (WASMString)wasm_stringref_obj_get_value(
stringref_obj);
memory_inst = module->memories[mem_idx];
maddr = memory_inst->memory_data + addr;
if (opcode == WASM_OP_STRING_ENCODE_WTF16) {
flag = WTF16;
count = wasm_string_measure(str_obj, flag);
target_bytes_length = wasm_string_encode(
str_obj, 0, count, maddr, NULL, flag);
}
else {
if (opcode == WASM_OP_STRING_ENCODE_UTF8) {
flag = UTF8;
}
else if (opcode
== WASM_OP_STRING_ENCODE_LOSSY_UTF8) {
flag = LOSSY_UTF8;
}
else if (opcode == WASM_OP_STRING_ENCODE_WTF8) {
flag = WTF8;
}
count = wasm_string_measure(str_obj, flag);
target_bytes_length = wasm_string_encode(
str_obj, 0, count, maddr, NULL, flag);
if (target_bytes_length == -1) {
wasm_set_exception(
module, "isolated surrogate is seen");
goto got_exception;
}
}
if (target_bytes_length < 0) {
wasm_set_exception(module,
"stringref encode failed");
goto got_exception;
}
PUSH_I32(target_bytes_length);
HANDLE_OP_END();
}
case WASM_OP_STRING_CONCAT:
{
WASMStringrefObjectRef stringref_obj1, stringref_obj2;
stringref_obj2 = POP_REF();
stringref_obj1 = POP_REF();
str_obj = wasm_string_concat(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj1),
(WASMString)wasm_stringref_obj_get_value(
stringref_obj2));
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_EQ:
{
WASMStringrefObjectRef stringref_obj1, stringref_obj2;
int32 is_eq;
stringref_obj2 = POP_REF();
stringref_obj1 = POP_REF();
is_eq = wasm_string_eq(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj1),
(WASMString)wasm_stringref_obj_get_value(
stringref_obj2));
PUSH_I32(is_eq);
HANDLE_OP_END();
}
case WASM_OP_STRING_IS_USV_SEQUENCE:
{
int32 is_usv_sequence;
stringref_obj = POP_REF();
is_usv_sequence = wasm_string_is_usv_sequence(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj));
PUSH_I32(is_usv_sequence);
HANDLE_OP_END();
}
case WASM_OP_STRING_AS_WTF8:
{
stringref_obj = POP_REF();
str_obj = wasm_string_create_view(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj),
STRING_VIEW_WTF8);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringview_wtf8_obj =
wasm_stringview_wtf8_obj_new(exec_env, str_obj);
if (!stringview_wtf8_obj) {
wasm_set_exception(module,
"create stringview wtf8 failed");
goto got_exception;
}
PUSH_REF(stringview_wtf8_obj);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF8_ADVANCE:
{
uint32 next_pos, bytes, pos;
bytes = POP_I32();
pos = POP_I32();
stringview_wtf8_obj = POP_REF();
next_pos = wasm_string_advance(
(WASMString)wasm_stringview_wtf8_obj_get_value(
stringview_wtf8_obj),
pos, bytes, NULL);
PUSH_I32(next_pos);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF8_ENCODE_UTF8:
case WASM_OP_STRINGVIEW_WTF8_ENCODE_LOSSY_UTF8:
case WASM_OP_STRINGVIEW_WTF8_ENCODE_WTF8:
{
uint32 mem_idx, addr, pos, bytes, next_pos;
int32 bytes_written;
WASMMemoryInstance *memory_inst;
EncodingFlag flag = WTF8;
if (opcode == WASM_OP_STRINGVIEW_WTF8_ENCODE_UTF8) {
flag = UTF8;
}
else if (opcode
== WASM_OP_STRINGVIEW_WTF8_ENCODE_LOSSY_UTF8) {
flag = LOSSY_UTF8;
}
else if (opcode
== WASM_OP_STRINGVIEW_WTF8_ENCODE_WTF8) {
flag = WTF8;
}
mem_idx = (uint32)read_uint32(frame_ip);
bytes = POP_I32();
pos = POP_I32();
addr = POP_I32();
stringview_wtf8_obj = POP_REF();
memory_inst = module->memories[mem_idx];
maddr = memory_inst->memory_data + addr;
bytes_written = wasm_string_encode(
(WASMString)wasm_stringview_wtf8_obj_get_value(
stringview_wtf8_obj),
pos, bytes, maddr, &next_pos, flag);
if (bytes_written < 0) {
if (bytes_written == Isolated_Surrogate) {
wasm_set_exception(
module, "isolated surrogate is seen");
}
else {
wasm_set_exception(module, "encode failed");
}
goto got_exception;
}
PUSH_I32(next_pos);
PUSH_I32(bytes_written);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF8_SLICE:
{
uint32 start, end;
end = POP_I32();
start = POP_I32();
stringview_wtf8_obj = POP_REF();
str_obj = wasm_string_slice(
(WASMString)wasm_stringview_wtf8_obj_get_value(
stringview_wtf8_obj),
start, end, STRING_VIEW_WTF8);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_AS_WTF16:
{
stringref_obj = POP_REF();
str_obj = wasm_string_create_view(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj),
STRING_VIEW_WTF16);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringview_wtf16_obj =
wasm_stringview_wtf16_obj_new(exec_env, str_obj);
if (!stringview_wtf16_obj) {
wasm_set_exception(
module, "create stringview wtf16 failed");
goto got_exception;
}
PUSH_REF(stringview_wtf16_obj);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF16_LENGTH:
{
int32 code_units_length;
stringview_wtf16_obj = POP_REF();
code_units_length = wasm_string_wtf16_get_length(
(WASMString)wasm_stringview_wtf16_obj_get_value(
stringview_wtf16_obj));
PUSH_I32(code_units_length);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF16_GET_CODEUNIT:
{
int32 pos;
uint32 code_unit;
pos = POP_I32();
stringview_wtf16_obj = POP_REF();
code_unit = (uint32)wasm_string_get_wtf16_codeunit(
(WASMString)wasm_stringview_wtf16_obj_get_value(
stringview_wtf16_obj),
pos);
PUSH_I32(code_unit);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF16_ENCODE:
{
uint32 mem_idx, addr, pos, len, offset = 0;
int32 written_code_units = 0;
mem_idx = (uint32)read_uint32(frame_ip);
len = POP_I32();
pos = POP_I32();
addr = POP_I32();
stringview_wtf16_obj = POP_REF();
CHECK_MEMORY_OVERFLOW(len * sizeof(uint16));
/* check 2-byte alignment */
if (((uintptr_t)maddr & (((uintptr_t)1 << 2) - 1))
!= 0) {
wasm_set_exception(module,
"unaligned memory access");
goto got_exception;
}
written_code_units = wasm_string_encode(
(WASMString)wasm_stringview_wtf16_obj_get_value(
stringview_wtf16_obj),
pos, len, maddr, NULL, WTF16);
PUSH_I32(written_code_units);
(void)mem_idx;
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_WTF16_SLICE:
{
uint32 start, end;
end = POP_I32();
start = POP_I32();
stringview_wtf16_obj = POP_REF();
str_obj = wasm_string_slice(
(WASMString)wasm_stringview_wtf16_obj_get_value(
stringview_wtf16_obj),
start, end, STRING_VIEW_WTF16);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_AS_ITER:
{
stringref_obj = POP_REF();
str_obj = wasm_string_create_view(
(WASMString)wasm_stringref_obj_get_value(
stringref_obj),
STRING_VIEW_ITER);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringview_iter_obj =
wasm_stringview_iter_obj_new(exec_env, str_obj, 0);
if (!stringview_iter_obj) {
wasm_set_exception(module,
"create stringview iter failed");
goto got_exception;
}
PUSH_REF(stringview_iter_obj);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_ITER_NEXT:
{
uint32 code_point;
stringview_iter_obj = POP_REF();
code_point = wasm_string_next_codepoint(
(WASMString)wasm_stringview_iter_obj_get_value(
stringview_iter_obj),
wasm_stringview_iter_obj_get_pos(
stringview_iter_obj));
PUSH_I32(code_point);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_ITER_ADVANCE:
case WASM_OP_STRINGVIEW_ITER_REWIND:
{
uint32 code_points_count, code_points_consumed = 0,
cur_pos, next_pos = 0;
code_points_count = POP_I32();
stringview_iter_obj = POP_REF();
str_obj =
(WASMString)wasm_stringview_iter_obj_get_value(
stringview_iter_obj);
cur_pos = wasm_stringview_iter_obj_get_pos(
stringview_iter_obj);
if (opcode == WASM_OP_STRINGVIEW_ITER_ADVANCE) {
next_pos = wasm_string_advance(
str_obj, cur_pos, code_points_count,
&code_points_consumed);
}
else if (opcode == WASM_OP_STRINGVIEW_ITER_REWIND) {
next_pos = wasm_string_rewind(
str_obj, cur_pos, code_points_count,
&code_points_consumed);
}
wasm_stringview_iter_obj_update_pos(stringview_iter_obj,
next_pos);
PUSH_I32(code_points_consumed);
HANDLE_OP_END();
}
case WASM_OP_STRINGVIEW_ITER_SLICE:
{
uint32 code_points_count, cur_pos;
code_points_count = POP_I32();
stringview_iter_obj = POP_REF();
cur_pos = wasm_stringview_iter_obj_get_pos(
stringview_iter_obj);
str_obj = wasm_string_slice(
(WASMString)wasm_stringview_iter_obj_get_value(
stringview_iter_obj),
cur_pos, code_points_count, STRING_VIEW_ITER);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_NEW_UTF8_ARRAY:
case WASM_OP_STRING_NEW_WTF16_ARRAY:
case WASM_OP_STRING_NEW_LOSSY_UTF8_ARRAY:
case WASM_OP_STRING_NEW_WTF8_ARRAY:
{
uint32 start, end, array_len;
EncodingFlag flag = WTF8;
WASMArrayType *array_type;
void *arr_start_addr;
end = POP_I32();
start = POP_I32();
array_obj = POP_REF();
array_type = (WASMArrayType *)wasm_obj_get_defined_type(
(WASMObjectRef)array_obj);
arr_start_addr =
wasm_array_obj_elem_addr(array_obj, start);
array_len = wasm_array_obj_length(array_obj);
if (start > end || end > array_len) {
wasm_set_exception(module,
"array index out of bounds");
goto got_exception;
}
if (opcode == WASM_OP_STRING_NEW_WTF16_ARRAY) {
if (array_type->elem_type != VALUE_TYPE_I16) {
wasm_set_exception(module,
"array type mismatch");
goto got_exception;
}
flag = WTF16;
}
else {
if (array_type->elem_type != VALUE_TYPE_I8) {
wasm_set_exception(module,
"array type mismatch");
goto got_exception;
}
if (opcode == WASM_OP_STRING_NEW_UTF8_ARRAY) {
flag = UTF8;
}
else if (opcode == WASM_OP_STRING_NEW_WTF8_ARRAY) {
flag = WTF8;
}
else if (opcode
== WASM_OP_STRING_NEW_LOSSY_UTF8_ARRAY) {
flag = LOSSY_UTF8;
}
}
str_obj = wasm_string_new_with_encoding(
arr_start_addr, (end - start), flag);
if (!str_obj) {
wasm_set_exception(module,
"create string object failed");
goto got_exception;
}
SYNC_ALL_TO_FRAME();
stringref_obj =
wasm_stringref_obj_new(exec_env, str_obj);
if (!stringref_obj) {
wasm_set_exception(module,
"create stringref failed");
goto got_exception;
}
PUSH_REF(stringref_obj);
HANDLE_OP_END();
}
case WASM_OP_STRING_ENCODE_UTF8_ARRAY:
case WASM_OP_STRING_ENCODE_WTF16_ARRAY:
case WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY:
case WASM_OP_STRING_ENCODE_WTF8_ARRAY:
{
uint32 start, array_len;
int32 bytes_written;
EncodingFlag flag = WTF8;
WASMArrayType *array_type;
void *arr_start_addr;
start = POP_I32();
array_obj = POP_REF();
stringref_obj = POP_REF();
str_obj = (WASMString)wasm_stringref_obj_get_value(
stringref_obj);
array_type = (WASMArrayType *)wasm_obj_get_defined_type(
(WASMObjectRef)array_obj);
arr_start_addr =
wasm_array_obj_elem_addr(array_obj, start);
array_len = wasm_array_obj_length(array_obj);
if (start > array_len) {
wasm_set_exception(module,
"array index out of bounds");
goto got_exception;
}
if (opcode == WASM_OP_STRING_ENCODE_WTF16_ARRAY) {
if (array_type->elem_type != VALUE_TYPE_I16) {
wasm_set_exception(module,
"array type mismatch");
goto got_exception;
}
flag = WTF16;
}
else {
if (array_type->elem_type != VALUE_TYPE_I8) {
wasm_set_exception(module,
"array type mismatch");
goto got_exception;
}
if (opcode == WASM_OP_STRING_ENCODE_UTF8_ARRAY) {
flag = UTF8;
}
else if (opcode
== WASM_OP_STRING_ENCODE_WTF8_ARRAY) {
flag = WTF8;
}
else if (
opcode
== WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY) {
flag = LOSSY_UTF8;
}
}
bytes_written = wasm_string_encode(
str_obj, 0, array_len, arr_start_addr, NULL, flag);
if (bytes_written < 0) {
if (bytes_written == Isolated_Surrogate) {
wasm_set_exception(
module, "isolated surrogate is seen");
}
else if (bytes_written == Insufficient_Space) {
wasm_set_exception(
module, "array space is insufficient");
}
else {
wasm_set_exception(module, "encode failed");
}
goto got_exception;
}
PUSH_I32(bytes_written);
HANDLE_OP_END();
}
#endif /* end of WASM_ENABLE_STRINGREF != 0 */
default:
{
wasm_set_exception(module, "unsupported opcode");

View File

@ -925,6 +925,14 @@ resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
error_buf, error_buf_size))
return false;
*p_need_ref_type_map = true;
#if WASM_ENABLE_STRINGREF != 0
/* covert (ref string) to stringref */
if (wasm_is_refheaptype_stringrefs(&ref_type->ref_ht_common)) {
ref_type->ref_type =
(uint8)((int32)0x80 + ref_type->ref_ht_common.heap_type);
*p_need_ref_type_map = false;
}
#endif
}
else {
/* type which can be represented by one byte */
@ -3702,6 +3710,60 @@ fail:
return false;
}
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_STRINGREF != 0
static bool
load_stringref_section(const uint8 *buf, const uint8 *buf_end,
WASMModule *module, bool is_load_from_file_buf,
char *error_buf, uint32 error_buf_size)
{
const uint8 *p = buf, *p_end = buf_end;
int32 deferred_count, immediate_count, string_length, i;
uint64 total_size;
read_leb_uint32(p, p_end, deferred_count);
read_leb_uint32(p, p_end, immediate_count);
/* proposal set deferred_count for future extension */
if (deferred_count != 0) {
goto fail;
}
if (immediate_count > 0) {
total_size = sizeof(char *) * (uint64)immediate_count;
if (!(module->string_consts =
loader_malloc(total_size, error_buf, error_buf_size))) {
goto fail;
}
module->stringref_count = immediate_count;
for (i = 0; i < immediate_count; i++) {
read_leb_uint32(p, p_end, string_length);
CHECK_BUF(p, p_end, string_length);
if (!(module->string_consts[i] = const_str_list_insert(
p, string_length, module, is_load_from_file_buf,
error_buf, error_buf_size))) {
goto fail;
}
p += string_length;
}
}
if (p != p_end) {
set_error_buf(error_buf, error_buf_size, "section size mismatch");
goto fail;
}
LOG_VERBOSE("Load stringref section success.\n");
return true;
fail:
return false;
}
#endif /* end of WASM_ENABLE_STRINGREF != 0 */
#endif /* end of WASM_ENABLE_GC != 0 */
#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
static bool
handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
@ -4469,6 +4531,16 @@ load_from_sections(WASMModule *module, WASMSection *sections,
error_buf_size))
return false;
break;
#endif
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_STRINGREF != 0
case SECTION_TYPE_STRINGREF:
if (!load_stringref_section(buf, buf_end, module,
is_load_from_file_buf, error_buf,
error_buf_size))
return false;
break;
#endif
#endif
default:
set_error_buf(error_buf, error_buf_size, "invalid section id");
@ -4927,6 +4999,11 @@ static uint8 section_ids[] = {
SECTION_TYPE_FUNC,
SECTION_TYPE_TABLE,
SECTION_TYPE_MEMORY,
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_STRINGREF != 0
SECTION_TYPE_STRINGREF,
#endif
#endif
SECTION_TYPE_GLOBAL,
SECTION_TYPE_EXPORT,
SECTION_TYPE_START,
@ -5374,6 +5451,14 @@ wasm_loader_unload(WASMModule *module)
}
}
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_STRINGREF != 0
if (module->string_consts) {
wasm_runtime_free(module->string_consts);
}
#endif
#endif
#if WASM_ENABLE_FAST_INTERP == 0
if (module->br_table_cache_list) {
BrTableCache *node = bh_list_first_elem(module->br_table_cache_list);
@ -5451,6 +5536,12 @@ wasm_loader_unload(WASMModule *module)
}
wasm_runtime_free(module->rtt_types);
}
#if WASM_ENABLE_STRINGREF != 0
for (i = 0; i < WASM_TYPE_STRINGVIEWITER - WASM_TYPE_STRINGREF + 1; i++) {
if (module->stringref_rtts[i])
wasm_runtime_free(module->stringref_rtts[i]);
}
#endif
#endif
wasm_runtime_free(module);
@ -5954,6 +6045,61 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
case WASM_OP_EXTERN_EXTERNALIZE:
break;
#if WASM_ENABLE_STRINGREF != 0
case WASM_OP_STRING_NEW_UTF8:
case WASM_OP_STRING_NEW_WTF16:
case WASM_OP_STRING_NEW_LOSSY_UTF8:
case WASM_OP_STRING_NEW_WTF8:
skip_leb_uint32(p, p_end); /* memory index 0x00 */
break;
case WASM_OP_STRING_CONST:
skip_leb_int32(p, p_end); /* contents */
break;
case WASM_OP_STRING_MEASURE_UTF8:
case WASM_OP_STRING_MEASURE_WTF8:
case WASM_OP_STRING_MEASURE_WTF16:
break;
case WASM_OP_STRING_ENCODE_UTF8:
case WASM_OP_STRING_ENCODE_WTF16:
case WASM_OP_STRING_ENCODE_LOSSY_UTF8:
case WASM_OP_STRING_ENCODE_WTF8:
skip_leb_uint32(p, p_end); /* memory index 0x00 */
break;
case WASM_OP_STRING_CONCAT:
case WASM_OP_STRING_EQ:
case WASM_OP_STRING_IS_USV_SEQUENCE:
case WASM_OP_STRING_AS_WTF8:
case WASM_OP_STRINGVIEW_WTF8_ADVANCE:
break;
case WASM_OP_STRINGVIEW_WTF8_ENCODE_UTF8:
case WASM_OP_STRINGVIEW_WTF8_ENCODE_LOSSY_UTF8:
case WASM_OP_STRINGVIEW_WTF8_ENCODE_WTF8:
skip_leb_uint32(p, p_end); /* memory index 0x00 */
break;
case WASM_OP_STRINGVIEW_WTF8_SLICE:
case WASM_OP_STRING_AS_WTF16:
case WASM_OP_STRINGVIEW_WTF16_LENGTH:
case WASM_OP_STRINGVIEW_WTF16_GET_CODEUNIT:
break;
case WASM_OP_STRINGVIEW_WTF16_ENCODE:
skip_leb_uint32(p, p_end); /* memory index 0x00 */
break;
case WASM_OP_STRINGVIEW_WTF16_SLICE:
case WASM_OP_STRING_AS_ITER:
case WASM_OP_STRINGVIEW_ITER_NEXT:
case WASM_OP_STRINGVIEW_ITER_ADVANCE:
case WASM_OP_STRINGVIEW_ITER_REWIND:
case WASM_OP_STRINGVIEW_ITER_SLICE:
case WASM_OP_STRING_NEW_UTF8_ARRAY:
case WASM_OP_STRING_NEW_WTF16_ARRAY:
case WASM_OP_STRING_NEW_LOSSY_UTF8_ARRAY:
case WASM_OP_STRING_NEW_WTF8_ARRAY:
case WASM_OP_STRING_ENCODE_UTF8_ARRAY:
case WASM_OP_STRING_ENCODE_WTF16_ARRAY:
case WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY:
case WASM_OP_STRING_ENCODE_WTF8_ARRAY:
break;
#endif /* end of WASM_ENABLE_STRINGREF != 0 */
default:
return false;
}
@ -8042,6 +8188,7 @@ fail:
#define POP_V128() TEMPLATE_POP(V128)
#define POP_FUNCREF() TEMPLATE_POP(FUNCREF)
#define POP_EXTERNREF() TEMPLATE_POP(EXTERNREF)
#define POP_STRINGREF() TEMPLATE_POP(STRINGREF)
#if WASM_ENABLE_FAST_INTERP != 0
@ -8277,7 +8424,7 @@ fail:
wasm_reftype_struct_size(_ref_type)); \
} \
} while (0)
#endif
#endif /* end of WASM_ENABLE_GC == 0 */
#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() \
do { \
@ -11756,7 +11903,12 @@ re_scan:
}
else {
if (heap_type > HEAP_TYPE_FUNC
|| heap_type < HEAP_TYPE_NONE) {
#if WASM_ENABLE_STRINGREF != 0
|| heap_type < HEAP_TYPE_STRINGVIEWITER
#else
|| heap_type < HEAP_TYPE_NONE
#endif
) {
set_error_buf(error_buf, error_buf_size,
"unknown type");
goto fail;
@ -11774,11 +11926,16 @@ re_scan:
bool nullable =
(opcode1 == WASM_OP_REF_CAST_NULLABLE) ? true
: false;
if (heap_type >= 0 || !nullable) {
wasm_set_refheaptype_typeidx(
&wasm_ref_type.ref_ht_typeidx, nullable,
heap_type);
PUSH_REF(wasm_ref_type.ref_type);
}
else {
PUSH_REF((uint8)((int32)0x80 + heap_type));
}
}
break;
}
@ -11998,6 +12155,215 @@ re_scan:
break;
}
#if WASM_ENABLE_STRINGREF != 0
case WASM_OP_STRING_NEW_UTF8:
case WASM_OP_STRING_NEW_WTF16:
case WASM_OP_STRING_NEW_LOSSY_UTF8:
case WASM_OP_STRING_NEW_WTF8:
{
uint32 memidx;
read_leb_uint32(p, p_end, memidx);
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, (uint32)memidx);
#endif
POP_I32();
POP_I32();
PUSH_REF(REF_TYPE_STRINGREF);
(void)memidx;
break;
}
case WASM_OP_STRING_CONST:
{
uint32 contents;
read_leb_uint32(p, p_end, contents);
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, (uint32)contents);
#endif
PUSH_REF(REF_TYPE_STRINGREF);
(void)contents;
break;
}
case WASM_OP_STRING_MEASURE_UTF8:
case WASM_OP_STRING_MEASURE_WTF8:
case WASM_OP_STRING_MEASURE_WTF16:
{
POP_STRINGREF();
PUSH_I32();
break;
}
case WASM_OP_STRING_ENCODE_UTF8:
case WASM_OP_STRING_ENCODE_WTF16:
case WASM_OP_STRING_ENCODE_LOSSY_UTF8:
case WASM_OP_STRING_ENCODE_WTF8:
{
uint32 memidx;
read_leb_uint32(p, p_end, memidx);
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, (uint32)memidx);
#endif
POP_I32();
POP_STRINGREF();
PUSH_I32();
(void)memidx;
break;
}
case WASM_OP_STRING_CONCAT:
{
POP_STRINGREF();
POP_STRINGREF();
PUSH_REF(REF_TYPE_STRINGREF);
break;
}
case WASM_OP_STRING_EQ:
{
POP_STRINGREF();
POP_STRINGREF();
PUSH_I32();
break;
}
case WASM_OP_STRING_IS_USV_SEQUENCE:
{
POP_STRINGREF();
PUSH_I32();
break;
}
case WASM_OP_STRING_AS_WTF8:
{
POP_STRINGREF();
PUSH_REF(REF_TYPE_STRINGVIEWWTF8);
break;
}
case WASM_OP_STRINGVIEW_WTF8_ADVANCE:
{
POP_I32();
POP_I32();
POP_REF(REF_TYPE_STRINGVIEWWTF8);
PUSH_I32();
break;
}
case WASM_OP_STRINGVIEW_WTF8_ENCODE_UTF8:
case WASM_OP_STRINGVIEW_WTF8_ENCODE_LOSSY_UTF8:
case WASM_OP_STRINGVIEW_WTF8_ENCODE_WTF8:
{
uint32 memidx;
read_leb_uint32(p, p_end, memidx);
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, (uint32)memidx);
#endif
POP_I32();
POP_I32();
POP_I32();
POP_REF(REF_TYPE_STRINGVIEWWTF8);
PUSH_I32();
PUSH_I32();
(void)memidx;
break;
}
case WASM_OP_STRINGVIEW_WTF8_SLICE:
{
POP_I32();
POP_I32();
POP_REF(REF_TYPE_STRINGVIEWWTF8);
PUSH_REF(REF_TYPE_STRINGREF);
break;
}
case WASM_OP_STRING_AS_WTF16:
{
POP_STRINGREF();
PUSH_REF(REF_TYPE_STRINGVIEWWTF16);
break;
}
case WASM_OP_STRINGVIEW_WTF16_LENGTH:
{
POP_REF(REF_TYPE_STRINGVIEWWTF16);
PUSH_I32();
break;
}
case WASM_OP_STRINGVIEW_WTF16_GET_CODEUNIT:
{
POP_I32();
POP_REF(REF_TYPE_STRINGVIEWWTF16);
PUSH_I32();
break;
}
case WASM_OP_STRINGVIEW_WTF16_ENCODE:
{
uint32 memidx;
read_leb_uint32(p, p_end, memidx);
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, (uint32)memidx);
#endif
POP_I32();
POP_I32();
POP_I32();
POP_REF(REF_TYPE_STRINGVIEWWTF16);
PUSH_I32();
(void)memidx;
break;
}
case WASM_OP_STRINGVIEW_WTF16_SLICE:
{
POP_I32();
POP_I32();
POP_REF(REF_TYPE_STRINGVIEWWTF16);
PUSH_REF(REF_TYPE_STRINGREF);
break;
}
case WASM_OP_STRING_AS_ITER:
{
POP_STRINGREF();
PUSH_REF(REF_TYPE_STRINGVIEWITER);
break;
}
case WASM_OP_STRINGVIEW_ITER_NEXT:
{
POP_REF(REF_TYPE_STRINGVIEWITER);
PUSH_I32();
break;
}
case WASM_OP_STRINGVIEW_ITER_ADVANCE:
case WASM_OP_STRINGVIEW_ITER_REWIND:
{
POP_I32();
POP_REF(REF_TYPE_STRINGVIEWITER);
PUSH_I32();
break;
}
case WASM_OP_STRINGVIEW_ITER_SLICE:
{
POP_I32();
POP_REF(REF_TYPE_STRINGVIEWITER);
PUSH_REF(REF_TYPE_STRINGREF);
break;
}
case WASM_OP_STRING_NEW_UTF8_ARRAY:
case WASM_OP_STRING_NEW_WTF16_ARRAY:
case WASM_OP_STRING_NEW_LOSSY_UTF8_ARRAY:
case WASM_OP_STRING_NEW_WTF8_ARRAY:
{
POP_I32();
POP_I32();
POP_REF(REF_TYPE_ARRAYREF);
PUSH_REF(REF_TYPE_STRINGREF);
break;
}
case WASM_OP_STRING_ENCODE_UTF8_ARRAY:
case WASM_OP_STRING_ENCODE_WTF16_ARRAY:
case WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY:
case WASM_OP_STRING_ENCODE_WTF8_ARRAY:
{
POP_I32();
POP_REF(REF_TYPE_ARRAYREF);
POP_STRINGREF();
PUSH_I32();
break;
}
#endif /* end of WASM_ENABLE_STRINGREF != 0 */
default:
set_error_buf_v(error_buf, error_buf_size,
"%s %02x %02x", "unsupported opcode",

View File

@ -337,6 +337,56 @@ typedef enum WASMGCEXTOpcode {
WASM_OP_EXTERN_INTERNALIZE = 0x70, /* extern.internalize */
WASM_OP_EXTERN_EXTERNALIZE = 0x71, /* extern.externalize */
WASM_OP_STRING_NEW_UTF8 = 0x80, /* string.new_utf8 */
WASM_OP_STRING_NEW_WTF16 = 0x81, /* string.new_wtf16 */
WASM_OP_STRING_CONST = 0x82, /* string.const */
WASM_OP_STRING_MEASURE_UTF8 = 0x83, /* string.measure_utf8 */
WASM_OP_STRING_MEASURE_WTF8 = 0x84, /* string.measure_wtf8 */
WASM_OP_STRING_MEASURE_WTF16 = 0x85, /* string.measure_wtf16 */
WASM_OP_STRING_ENCODE_UTF8 = 0x86, /* string.encode_utf8 */
WASM_OP_STRING_ENCODE_WTF16 = 0x87, /* string.encode_wtf16 */
WASM_OP_STRING_CONCAT = 0x88, /* string.concat */
WASM_OP_STRING_EQ = 0x89, /* string.eq */
WASM_OP_STRING_IS_USV_SEQUENCE = 0x8a, /* string.is_usv_sequence */
WASM_OP_STRING_NEW_LOSSY_UTF8 = 0x8b, /* string.new_lossy_utf8 */
WASM_OP_STRING_NEW_WTF8 = 0x8c, /* string.new_wtf8 */
WASM_OP_STRING_ENCODE_LOSSY_UTF8 = 0x8d, /* string.encode_lossy_utf8 */
WASM_OP_STRING_ENCODE_WTF8 = 0x8e, /* string.encode_wtf8 */
WASM_OP_STRING_AS_WTF8 = 0x90, /* string.as_wtf8 */
WASM_OP_STRINGVIEW_WTF8_ADVANCE = 0x91, /* stringview_wtf8.advance */
WASM_OP_STRINGVIEW_WTF8_ENCODE_UTF8 =
0x92, /* stringview_wtf8.encode_utf8 */
WASM_OP_STRINGVIEW_WTF8_SLICE = 0x93, /* stringview_wtf8.slice */
WASM_OP_STRINGVIEW_WTF8_ENCODE_LOSSY_UTF8 =
0x94, /* stringview_wtf8.encode_lossy_utf8 */
WASM_OP_STRINGVIEW_WTF8_ENCODE_WTF8 =
0x95, /* stringview_wtf8.encode_wtf8 */
WASM_OP_STRING_AS_WTF16 = 0x98, /* string.as_wtf16 */
WASM_OP_STRINGVIEW_WTF16_LENGTH = 0x99, /* stringview_wtf16.length */
WASM_OP_STRINGVIEW_WTF16_GET_CODEUNIT =
0x9a, /* stringview_wtf16.get_codeunit */
WASM_OP_STRINGVIEW_WTF16_ENCODE = 0x9b, /* stringview_wtf16.encode */
WASM_OP_STRINGVIEW_WTF16_SLICE = 0x9c, /* stringview_wtf16.slice */
WASM_OP_STRING_AS_ITER = 0xa0, /* string.as_iter */
WASM_OP_STRINGVIEW_ITER_NEXT = 0xa1, /* stringview_iter.next */
WASM_OP_STRINGVIEW_ITER_ADVANCE = 0xa2, /* stringview_iter.advance */
WASM_OP_STRINGVIEW_ITER_REWIND = 0xa3, /* stringview_iter.rewind */
WASM_OP_STRINGVIEW_ITER_SLICE = 0xa4, /* stringview_iter.slice */
WASM_OP_STRING_NEW_UTF8_ARRAY = 0xb0, /* string.new_utf8_array */
WASM_OP_STRING_NEW_WTF16_ARRAY = 0xb1, /* string.new_wtf16_array */
WASM_OP_STRING_ENCODE_UTF8_ARRAY = 0xb2, /* string.encode_utf8_array */
WASM_OP_STRING_ENCODE_WTF16_ARRAY = 0xb3, /* string.encode_wtf16_array */
WASM_OP_STRING_NEW_LOSSY_UTF8_ARRAY =
0xb4, /* string.new_lossy_utf8_array */
WASM_OP_STRING_NEW_WTF8_ARRAY = 0xb5, /* string.new_wtf8_array */
WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY =
0xb6, /* string.encode_lossy_utf8_array */
WASM_OP_STRING_ENCODE_WTF8_ARRAY = 0xb7, /* string.encode_wtf8_array */
} WASMGCEXTOpcode;
typedef enum WASMMiscEXTOpcode {