Sfoglia il codice sorgente

Enable stringref aot (#2816)

Xu Jun 2 anni fa
parent
commit
77d27c9ff6

+ 79 - 0
core/iwasm/aot/aot_loader.c

@@ -871,6 +871,59 @@ fail:
 #endif /* WASM_ENABLE_CUSTOM_NAME_SECTION != 0 */
 }
 
+#if WASM_ENABLE_STRINGREF != 0
+static bool
+load_string_literal_section(const uint8 *buf, const uint8 *buf_end,
+                            AOTModule *module, bool is_load_from_file_buf,
+                            char *error_buf, uint32 error_buf_size)
+{
+    const uint8 *p = buf, *p_end = buf_end;
+    uint32 reserved = 0, string_count = 0, i;
+    uint64 size;
+
+    read_uint32(p, p_end, reserved);
+    if (reserved != 0) {
+        set_error_buf(error_buf, error_buf_size,
+                      "invalid reserved slot in string literal count");
+        goto fail;
+    }
+
+    read_uint32(p, p_end, string_count);
+    if (string_count == 0) {
+        set_error_buf(error_buf, error_buf_size,
+                      "invalid string literal count");
+        goto fail;
+    }
+    module->string_literal_count = string_count;
+
+    size = (uint64)sizeof(char *) * string_count;
+    if (!(module->string_literal_ptrs =
+              loader_malloc(size, error_buf, error_buf_size))) {
+        goto fail;
+    }
+
+    size = (uint64)sizeof(uint32) * string_count;
+    if (!(module->string_literal_lengths =
+              loader_malloc(size, error_buf, error_buf_size))) {
+        goto fail;
+    }
+
+    for (i = 0; i < string_count; i++) {
+        read_uint32(p, p_end, module->string_literal_lengths[i]);
+    }
+
+    for (i = 0; i < string_count; i++) {
+        module->string_literal_ptrs[i] = p;
+        p += module->string_literal_lengths[i];
+    }
+
+    return true;
+
+fail:
+    return false;
+}
+#endif /* end of WASM_ENABLE_STRINGREF != 0 */
+
 static bool
 load_custom_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
                     bool is_load_from_file_buf, char *error_buf,
@@ -894,6 +947,14 @@ load_custom_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
                                    error_buf, error_buf_size))
                 goto fail;
             break;
+#if WASM_ENABLE_STRINGREF != 0
+        case AOT_CUSTOM_SECTION_STRING_LITERAL:
+            if (!load_string_literal_section(buf, buf_end, module,
+                                             is_load_from_file_buf, error_buf,
+                                             error_buf_size))
+                goto fail;
+            break;
+#endif
 #if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
         case AOT_CUSTOM_SECTION_RAW:
         {
@@ -3894,6 +3955,24 @@ aot_unload(AOTModule *module)
         }
         wasm_runtime_free(module->rtt_types);
     }
+#if WASM_ENABLE_STRINGREF != 0
+    {
+        uint32 i;
+        for (i = 0; i < WASM_TYPE_STRINGVIEWITER - WASM_TYPE_STRINGREF + 1;
+             i++) {
+            if (module->stringref_rtts[i])
+                wasm_runtime_free(module->stringref_rtts[i]);
+        }
+
+        if (module->string_literal_lengths) {
+            wasm_runtime_free(module->string_literal_lengths);
+        }
+
+        if (module->string_literal_ptrs) {
+            wasm_runtime_free(module->string_literal_ptrs);
+        }
+    }
+#endif
 #endif
 
     wasm_runtime_free(module);

+ 31 - 0
core/iwasm/aot/aot_reloc.h

@@ -9,6 +9,10 @@
 #include "aot_runtime.h"
 #include "aot_intrinsic.h"
 
+#if WASM_ENABLE_STRINGREF != 0
+#include "string_object.h"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -145,6 +149,32 @@ typedef struct {
 #define REG_GC_SYM()
 #endif
 
+#if WASM_ENABLE_STRINGREF != 0
+#define REG_STRINGREF_SYM()                 \
+    REG_SYM(wasm_stringref_obj_new),        \
+    REG_SYM(wasm_stringview_wtf8_obj_new),  \
+    REG_SYM(wasm_stringview_wtf16_obj_new), \
+    REG_SYM(wasm_stringview_iter_obj_new),  \
+    REG_SYM(wasm_string_destroy),           \
+    REG_SYM(wasm_string_new_const),         \
+    REG_SYM(wasm_string_new_with_encoding), \
+    REG_SYM(wasm_string_measure),           \
+    REG_SYM(wasm_string_wtf16_get_length),  \
+    REG_SYM(wasm_string_encode),            \
+    REG_SYM(wasm_string_concat),            \
+    REG_SYM(wasm_string_eq),                \
+    REG_SYM(wasm_string_is_usv_sequence),   \
+    REG_SYM(wasm_string_create_view),       \
+    REG_SYM(wasm_string_advance),           \
+    REG_SYM(wasm_string_slice),             \
+    REG_SYM(wasm_string_get_wtf16_codeunit),\
+    REG_SYM(wasm_string_next_codepoint),    \
+    REG_SYM(wasm_string_rewind),            \
+    REG_SYM(wasm_string_dump),
+#else
+#define REG_STRINGREF_SYM()
+#endif
+
 #define REG_COMMON_SYMBOLS                \
     REG_SYM(aot_set_exception_with_id),   \
     REG_SYM(aot_invoke_native),           \
@@ -176,6 +206,7 @@ typedef struct {
     REG_INTRINSIC_SYM()                   \
     REG_LLVM_PGO_SYM()                    \
     REG_GC_SYM()                          \
+    REG_STRINGREF_SYM()                   \
 
 #define CHECK_RELOC_OFFSET(data_size) do {              \
     if (!check_reloc_offset(target_section_size,        \

+ 13 - 0
core/iwasm/aot/aot_runtime.h

@@ -52,6 +52,7 @@ typedef enum AOTCustomSectionType {
     AOT_CUSTOM_SECTION_NATIVE_SYMBOL = 1,
     AOT_CUSTOM_SECTION_ACCESS_CONTROL = 2,
     AOT_CUSTOM_SECTION_NAME = 3,
+    AOT_CUSTOM_SECTION_STRING_LITERAL = 4,
 } AOTCustomSectionType;
 
 typedef struct AOTObjectDataSection {
@@ -268,6 +269,18 @@ typedef struct AOTModule {
     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];
+    uint32 string_literal_count;
+    uint32 *string_literal_lengths;
+    const uint8 **string_literal_ptrs;
+#endif
 #endif
 
 #if WASM_ENABLE_DEBUG_AOT != 0

+ 22 - 5
core/iwasm/common/gc/gc_common.c

@@ -738,28 +738,45 @@ wasm_runtime_call_func_ref(WASMExecEnv *exec_env,
                            const WASMFuncObjectRef func_obj, uint32 argc,
                            uint32 argv[])
 {
-    WASMFunctionInstance *func_inst = NULL;
+    WASMFunctionInstanceCommon *func_inst = NULL;
     uint32 func_idx = wasm_func_obj_get_func_idx_bound(func_obj);
+#if WASM_ENABLE_AOT != 0
+    AOTFunctionInstance aot_func_inst = { 0 };
+#endif
 
 #if WASM_ENABLE_INTERP != 0
     if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) {
+        WASMFunctionInstance *wasm_func_inst;
         WASMModuleInstance *module_inst =
             (WASMModuleInstance *)exec_env->module_inst;
 
         bh_assert(func_idx < module_inst->module->import_function_count
                                  + module_inst->module->function_count);
-        func_inst = module_inst->e->functions + func_idx;
+        wasm_func_inst = module_inst->e->functions + func_idx;
+        func_inst = (WASMFunctionInstanceCommon *)wasm_func_inst;
     }
 #endif
 #if WASM_ENABLE_AOT != 0
     if (exec_env->module_inst->module_type == Wasm_Module_AoT) {
+        uint32 func_type_idx;
         AOTModuleInstance *module_inst =
             (AOTModuleInstance *)exec_env->module_inst;
+        AOTModule *module = (AOTModule *)module_inst->module;
         (void)module_inst;
 
-        bh_assert(func_idx < module_inst->module->import_function_count
-                                 + module_inst->module->function_count);
-        /* TODO: Implement call func ref for aot mode */
+        bh_assert(func_idx < module->import_func_count + module->func_count);
+
+        aot_func_inst.func_name = "";
+        aot_func_inst.func_index = func_idx;
+        aot_func_inst.is_import_func = false;
+        func_type_idx =
+            module->func_type_indexes[func_idx - module->import_func_count];
+        aot_func_inst.u.func.func_type =
+            (AOTFuncType *)module->types[func_type_idx];
+        aot_func_inst.u.func.func_ptr =
+            module->func_ptrs[func_idx - module->import_func_count];
+
+        func_inst = (WASMFunctionInstanceCommon *)(&aot_func_inst);
     }
 #endif
 

+ 2 - 6
core/iwasm/common/gc/gc_object.c

@@ -850,12 +850,8 @@ stringref_obj_new(WASMExecEnv *exec_env, uint32 type, const void *str_obj,
     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);
-        */
+        rtt_type = wasm_stringref_rtt_type_new(type, module->stringref_rtts,
+                                               &module->rtt_type_lock);
     }
 #endif
 

+ 5 - 1
core/iwasm/common/gc/iwasm_gc.cmake

@@ -25,7 +25,11 @@ if (WAMR_BUILD_STRINGREF EQUAL 1)
   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})
+    if (${WAMR_STRINGREF_IMPL_SOURCE} STREQUAL "STUB")
+      set (IWASM_STRINGREF_SOURCE ${IWASM_STRINGREF_DIR}/stringref_stub.c)
+    else()
+      set (IWASM_STRINGREF_SOURCE ${WAMR_STRINGREF_IMPL_SOURCE})
+    endif()
   endif ()
 
   set (IWASM_GC_SOURCE ${IWASM_GC_SOURCE} ${IWASM_STRINGREF_SOURCE})

+ 1 - 1
core/iwasm/common/gc/stringref/string_object.h

@@ -39,7 +39,7 @@ wasm_string_destroy(WASMString str_obj);
 
 /* string.const */
 WASMString
-wasm_string_new_const(const char *str);
+wasm_string_new_const(const char *content, uint32 length);
 
 /* string.new_xx8/new_wtf16 */
 /* string.new_xx8_array */

+ 136 - 0
core/iwasm/common/gc/stringref/stringref_stub.c

@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2023 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/* This file is the stub for stringref implementation, only used for wamrc
+ * compiler. The runtime embedder SHOULD NOT use this file */
+
+#include "string_object.h"
+
+/******************* gc finalizer *****************/
+void
+wasm_string_destroy(WASMString str_obj)
+{}
+
+/******************* opcode functions *****************/
+
+/* string.const */
+WASMString
+wasm_string_new_const(const char *str, uint32 length)
+{
+    return NULL;
+}
+
+/* string.new_xx8 */
+/* string.new_wtf16 */
+/* string.new_xx8_array */
+/* string.new_wtf16_array */
+WASMString
+wasm_string_new_with_encoding(void *addr, uint32 count, EncodingFlag flag)
+{
+    return NULL;
+}
+
+/* string.measure */
+/* stringview_wtf16.length */
+int32
+wasm_string_measure(WASMString str_obj, EncodingFlag flag)
+{
+    return 0;
+}
+
+/* stringview_wtf16.length */
+int32
+wasm_string_wtf16_get_length(WASMString str_obj)
+{
+    return 0;
+}
+
+/* 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)
+{
+    return 0;
+}
+
+/* string.concat */
+WASMString
+wasm_string_concat(WASMString str_obj1, WASMString str_obj2)
+{
+    return NULL;
+}
+
+/* string.eq */
+int32
+wasm_string_eq(WASMString str_obj1, WASMString str_obj2)
+{
+    return 0;
+}
+
+/* string.is_usv_sequence */
+int32
+wasm_string_is_usv_sequence(WASMString str_obj)
+{
+    return 0;
+}
+
+/* string.as_wtf8 */
+/* string.as_wtf16 */
+/* string.as_iter */
+WASMString
+wasm_string_create_view(WASMString str_obj, StringViewType type)
+{
+    return NULL;
+}
+
+/* stringview_wtf8.advance */
+/* stringview_iter.advance */
+int32
+wasm_string_advance(WASMString str_obj, uint32 pos, uint32 count,
+                    uint32 *consumed)
+{
+    return 0;
+}
+
+/* stringview_wtf8.slice */
+/* stringview_wtf16.slice */
+/* stringview_iter.slice */
+WASMString
+wasm_string_slice(WASMString str_obj, uint32 start, uint32 end,
+                  StringViewType type)
+{
+    return NULL;
+}
+
+/* stringview_wtf16.get_codeunit */
+int16
+wasm_string_get_wtf16_codeunit(WASMString str_obj, int32 pos)
+{
+    return 0;
+}
+
+/* stringview_iter.next */
+uint32
+wasm_string_next_codepoint(WASMString str_obj, uint32 pos)
+{
+    return 0;
+}
+
+/* stringview_iter.rewind */
+uint32
+wasm_string_rewind(WASMString str_obj, uint32 pos, uint32 count,
+                   uint32 *consumed)
+{
+    return 0;
+}
+
+void
+wasm_string_dump(WASMString str_obj)
+{}

+ 5 - 0
core/iwasm/common/wasm_runtime_common.c

@@ -2504,6 +2504,11 @@ static const char *exception_msgs[] = {
     "create externref object failed", /* EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ */
     "cast failure",                   /* EXCE_CAST_FAILURE */
     "array index out of bounds",      /* EXCE_ARRAY_IDX_OOB */
+    /* stringref related exceptions */
+    "create string object failed",    /* EXCE_FAILED_TO_CREATE_STRING */
+    "create stringref failed",        /* EXCE_FAILED_TO_CREATE_STRINGREF */
+    "create stringview failed",       /* EXCE_FAILED_TO_CREATE_STRINGVIEW */
+    "encode failed",                  /* EXCE_FAILED_TO_ENCODE_STRING */
     "",                               /* EXCE_ALREADY_THROWN */
 };
 /* clang-format on */

+ 6 - 0
core/iwasm/compilation/aot.c

@@ -704,6 +704,12 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
     comp_data->free_func_index = module->free_function;
     comp_data->retain_func_index = module->retain_function;
 
+#if WASM_ENABLE_STRINGREF != 0
+    comp_data->string_literal_count = module->string_literal_count;
+    comp_data->string_literal_ptrs_wp = module->string_literal_ptrs;
+    comp_data->string_literal_lengths_wp = module->string_literal_lengths;
+#endif
+
     comp_data->wasm_module = module;
 
     return comp_data;

+ 6 - 0
core/iwasm/compilation/aot.h

@@ -322,6 +322,12 @@ typedef struct AOTCompData {
     uint32 aux_stack_bottom;
     uint32 aux_stack_size;
 
+#if WASM_ENABLE_STRINGREF != 0
+    uint32 string_literal_count;
+    uint32 *string_literal_lengths_wp;
+    const uint8 **string_literal_ptrs_wp;
+#endif
+
     WASMModule *wasm_module;
 #if WASM_ENABLE_DEBUG_AOT != 0
     dwarf_extractor_handle_t extractor;

+ 274 - 0
core/iwasm/compilation/aot_compiler.c

@@ -37,6 +37,11 @@
 #include "debug/dwarf_extractor.h"
 #endif
 
+#if WASM_ENABLE_STRINGREF != 0
+#include "string_object.h"
+#include "aot_emit_stringref.h"
+#endif
+
 #define CHECK_BUF(buf, buf_end, length)                             \
     do {                                                            \
         if (buf + length > buf_end) {                               \
@@ -396,6 +401,12 @@ aot_gen_commit_values(AOTCompFrame *frame)
                 case REF_TYPE_I31REF:
                 case REF_TYPE_STRUCTREF:
                 case REF_TYPE_ARRAYREF:
+#if WASM_ENABLE_STRINGREF != 0
+                case REF_TYPE_STRINGREF:
+                case REF_TYPE_STRINGVIEWWTF8:
+                case REF_TYPE_STRINGVIEWWTF16:
+                case REF_TYPE_STRINGVIEWITER:
+#endif
                 case VALUE_TYPE_GC_REF:
                     if (comp_ctx->pointer_size == sizeof(uint64)) {
                         bh_assert(p->ref == (p + 1)->ref);
@@ -772,6 +783,12 @@ init_comp_frame(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             case REF_TYPE_I31REF:
             case REF_TYPE_STRUCTREF:
             case REF_TYPE_ARRAYREF:
+#if WASM_ENABLE_STRINGREF != 0
+            case REF_TYPE_STRINGREF:
+            case REF_TYPE_STRINGVIEWWTF8:
+            case REF_TYPE_STRINGVIEWWTF16:
+            case REF_TYPE_STRINGVIEWITER:
+#endif
                 bh_assert(comp_ctx->enable_gc);
                 set_local_gc_ref(comp_ctx->aot_frame, n, local_value,
                                  VALUE_TYPE_GC_REF);
@@ -846,6 +863,12 @@ init_comp_frame(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             case REF_TYPE_I31REF:
             case REF_TYPE_STRUCTREF:
             case REF_TYPE_ARRAYREF:
+#if WASM_ENABLE_STRINGREF != 0
+            case REF_TYPE_STRINGREF:
+            case REF_TYPE_STRINGVIEWWTF8:
+            case REF_TYPE_STRINGVIEWWTF16:
+            case REF_TYPE_STRINGVIEWITER:
+#endif
                 bh_assert(comp_ctx->enable_gc);
                 set_local_gc_ref(comp_ctx->aot_frame, n, GC_REF_NULL,
                                  VALUE_TYPE_GC_REF);
@@ -1548,6 +1571,257 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
                             return false;
                         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:
+                    {
+                        EncodingFlag flag = WTF8;
+
+                        read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
+                        bh_assert(mem_idx == 0);
+
+                        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;
+                        }
+
+                        if (!aot_compile_op_string_new(comp_ctx, func_ctx, flag,
+                                                       frame_ip_org))
+                            return false;
+                        break;
+                    }
+                    case WASM_OP_STRING_CONST:
+                    {
+                        uint32 contents;
+                        read_leb_uint32(frame_ip, frame_ip_end, contents);
+
+                        if (!aot_compile_op_string_const(
+                                comp_ctx, func_ctx, contents, frame_ip_org))
+                            return false;
+                        break;
+                    }
+                    case WASM_OP_STRING_MEASURE_UTF8:
+                    case WASM_OP_STRING_MEASURE_WTF8:
+                    case WASM_OP_STRING_MEASURE_WTF16:
+                    {
+                        EncodingFlag flag = WTF8;
+
+                        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;
+                        }
+
+                        if (!aot_compile_op_string_measure(comp_ctx, func_ctx,
+                                                           flag))
+                            return false;
+                        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:
+                    {
+                        EncodingFlag flag = WTF8;
+
+                        read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
+                        bh_assert(mem_idx == 0);
+
+                        if (opcode == WASM_OP_STRING_ENCODE_WTF16) {
+                            flag = WTF16;
+                        }
+                        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;
+                        }
+
+                        if (!aot_compile_op_string_encode(comp_ctx, func_ctx,
+                                                          mem_idx, flag))
+                            return false;
+                        break;
+                    }
+                    case WASM_OP_STRING_CONCAT:
+                        if (!aot_compile_op_string_concat(comp_ctx, func_ctx,
+                                                          frame_ip_org))
+                            return false;
+                        break;
+                    case WASM_OP_STRING_EQ:
+                        if (!aot_compile_op_string_eq(comp_ctx, func_ctx))
+                            return false;
+                        break;
+                    case WASM_OP_STRING_IS_USV_SEQUENCE:
+                        if (!aot_compile_op_string_is_usv_sequence(comp_ctx,
+                                                                   func_ctx))
+                            return false;
+                        break;
+                    case WASM_OP_STRING_AS_WTF8:
+                        if (!aot_compile_op_string_as_wtf8(comp_ctx, func_ctx,
+                                                           frame_ip_org))
+                            return false;
+                        break;
+                    case WASM_OP_STRINGVIEW_WTF8_ADVANCE:
+                        if (!aot_compile_op_stringview_wtf8_advance(comp_ctx,
+                                                                    func_ctx))
+                            return false;
+                        break;
+                    case WASM_OP_STRINGVIEW_WTF8_ENCODE_UTF8:
+                    case WASM_OP_STRINGVIEW_WTF8_ENCODE_LOSSY_UTF8:
+                    case WASM_OP_STRINGVIEW_WTF8_ENCODE_WTF8:
+                    {
+                        EncodingFlag flag = WTF8;
+
+                        read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
+                        bh_assert(mem_idx == 0);
+
+                        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;
+                        }
+
+                        if (!aot_compile_op_stringview_wtf8_encode(
+                                comp_ctx, func_ctx, mem_idx, flag))
+                            return false;
+                        break;
+                    }
+                    case WASM_OP_STRINGVIEW_WTF8_SLICE:
+                        if (!aot_compile_op_stringview_wtf8_slice(
+                                comp_ctx, func_ctx, frame_ip_org))
+                            return false;
+                        break;
+                    case WASM_OP_STRING_AS_WTF16:
+                        if (!aot_compile_op_string_as_wtf16(comp_ctx, func_ctx,
+                                                            frame_ip_org))
+                            return false;
+                        break;
+                    case WASM_OP_STRINGVIEW_WTF16_LENGTH:
+                        if (!aot_compile_op_stringview_wtf16_length(comp_ctx,
+                                                                    func_ctx))
+                            return false;
+                        break;
+                    case WASM_OP_STRINGVIEW_WTF16_GET_CODEUNIT:
+                        if (!aot_compile_op_stringview_wtf16_get_codeunit(
+                                comp_ctx, func_ctx))
+                            return false;
+                        break;
+                    case WASM_OP_STRINGVIEW_WTF16_ENCODE:
+                    {
+                        read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
+                        bh_assert(mem_idx == 0);
+
+                        if (!aot_compile_op_stringview_wtf16_encode(
+                                comp_ctx, func_ctx, mem_idx))
+                            return false;
+                        break;
+                    }
+                    case WASM_OP_STRINGVIEW_WTF16_SLICE:
+                        if (!aot_compile_op_stringview_wtf16_slice(
+                                comp_ctx, func_ctx, frame_ip_org))
+                            return false;
+                        break;
+                    case WASM_OP_STRING_AS_ITER:
+                        if (!aot_compile_op_string_as_iter(comp_ctx, func_ctx,
+                                                           frame_ip_org))
+                            return false;
+                        break;
+                    case WASM_OP_STRINGVIEW_ITER_NEXT:
+                        if (!aot_compile_op_stringview_iter_next(comp_ctx,
+                                                                 func_ctx))
+                            return false;
+                        break;
+                    case WASM_OP_STRINGVIEW_ITER_ADVANCE:
+                        if (!aot_compile_op_stringview_iter_advance(comp_ctx,
+                                                                    func_ctx))
+                            return false;
+                        break;
+                    case WASM_OP_STRINGVIEW_ITER_REWIND:
+                        if (!aot_compile_op_stringview_iter_rewind(comp_ctx,
+                                                                   func_ctx))
+                            return false;
+                        break;
+                    case WASM_OP_STRINGVIEW_ITER_SLICE:
+                        if (!aot_compile_op_stringview_iter_slice(
+                                comp_ctx, func_ctx, frame_ip_org))
+                            return false;
+                        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:
+                    {
+                        EncodingFlag flag = WTF8;
+
+                        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;
+                        }
+
+                        if (!aot_compile_op_string_new_array(
+                                comp_ctx, func_ctx, flag, frame_ip_org))
+                            return false;
+
+                        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:
+                    {
+                        EncodingFlag flag = WTF8;
+
+                        if (opcode == WASM_OP_STRING_ENCODE_WTF16) {
+                            flag = WTF16;
+                        }
+                        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;
+                        }
+
+                        if (!aot_compile_op_string_encode_array(comp_ctx,
+                                                                func_ctx, flag))
+                            return false;
+                        break;
+                    }
+#endif /* end of WASM_ENABLE_STRINGREF != 0 */
+
                     default:
                         aot_set_last_error("unsupported opcode");
                         return false;

+ 7 - 1
core/iwasm/compilation/aot_compiler.h

@@ -88,7 +88,13 @@ typedef enum FloatArithmetic {
 static inline bool
 aot_is_type_gc_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;
 }

+ 93 - 2
core/iwasm/compilation/aot_emit_aot_file.c

@@ -1059,6 +1059,10 @@ get_native_symbol_list_size(AOTCompContext *comp_ctx)
 static uint32
 get_name_section_size(AOTCompData *comp_data);
 
+static uint32
+get_string_literal_section_size(AOTCompContext *comp_ctx,
+                                AOTCompData *comp_data);
+
 static uint32
 get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data);
 
@@ -1068,6 +1072,9 @@ get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
 {
     uint32 size = 0;
     uint32 size_custom_section = 0;
+#if WASM_ENABLE_STRINGREF != 0
+    uint32 size_string_literal_section = 0;
+#endif
 
     /* aot file header */
     size += get_file_header_size();
@@ -1131,6 +1138,18 @@ get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
         size += size_custom_section;
     }
 
+#if WASM_ENABLE_STRINGREF != 0
+    /* string literal section */
+    size_string_literal_section =
+        get_string_literal_section_size(comp_ctx, comp_data);
+    if (size_string_literal_section > 0) {
+        size = align_uint(size, 4);
+        /* section id + section size + sub section id */
+        size += (uint32)sizeof(uint32) * 3;
+        size += size_string_literal_section;
+    }
+#endif
+
     return size;
 }
 
@@ -1465,6 +1484,30 @@ fail:
     return 0;
 }
 
+#if WASM_ENABLE_STRINGREF != 0
+static uint32
+get_string_literal_section_size(AOTCompContext *comp_ctx,
+                                AOTCompData *comp_data)
+{
+    uint32 i;
+    uint32 size = 0;
+    uint32 string_count = comp_data->string_literal_count;
+
+    if (string_count == 0) {
+        return 0;
+    }
+
+    /* reserved slot + string count + string_lengths */
+    size += sizeof(uint32) * (2 + string_count);
+
+    for (i = 0; i < string_count; i++) {
+        size += comp_data->string_literal_lengths_wp[i];
+    }
+
+    return size;
+}
+#endif /* end of WASM_ENABLE_STRINGREF != 0 */
+
 static uint32
 get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
 {
@@ -2403,6 +2446,50 @@ aot_emit_name_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     return true;
 }
 
+#if WASM_ENABLE_STRINGREF != 0
+static bool
+aot_emit_string_literal_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+                                AOTCompData *comp_data,
+                                AOTCompContext *comp_ctx)
+{
+    uint32 string_count = comp_data->string_literal_count;
+
+    if (string_count > 0) {
+        uint32 offset = *p_offset;
+        uint32 i;
+
+        *p_offset = offset = align_uint(offset, 4);
+
+        EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
+        /* sub section id + string literal section size */
+        EMIT_U32(sizeof(uint32) * 1
+                 + get_string_literal_section_size(comp_ctx, comp_data));
+        EMIT_U32(AOT_CUSTOM_SECTION_STRING_LITERAL);
+
+        /* reserved */
+        EMIT_U32(0);
+
+        /* string literal count */
+        EMIT_U32(string_count);
+
+        for (i = 0; i < string_count; i++) {
+            EMIT_U32(comp_data->string_literal_lengths_wp[i]);
+        }
+
+        for (i = 0; i < string_count; i++) {
+            uint32 string_length = comp_data->string_literal_lengths_wp[i];
+            bh_memcpy_s((uint8 *)(buf + offset), (uint32)(buf_end - buf),
+                        comp_data->string_literal_ptrs_wp[i], string_length);
+            offset += string_length;
+        }
+
+        *p_offset = offset;
+    }
+
+    return true;
+}
+#endif /* end of WASM_ENABLE_STRINGREF != 0 */
+
 static bool
 aot_emit_custom_sections(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
                          AOTCompData *comp_data, AOTCompContext *comp_ctx)
@@ -3949,8 +4036,12 @@ aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
                                         comp_data, obj_data)
         || !aot_emit_native_symbol(buf, buf_end, &offset, comp_ctx)
         || !aot_emit_name_section(buf, buf_end, &offset, comp_data, comp_ctx)
-        || !aot_emit_custom_sections(buf, buf_end, &offset, comp_data,
-                                     comp_ctx))
+        || !aot_emit_custom_sections(buf, buf_end, &offset, comp_data, comp_ctx)
+#if WASM_ENABLE_STRINGREF != 0
+        || !aot_emit_string_literal_section(buf, buf_end, &offset, comp_data,
+                                            comp_ctx)
+#endif
+    )
         goto fail2;
 
 #if 0

+ 6 - 0
core/iwasm/compilation/aot_emit_function.c

@@ -592,6 +592,12 @@ commit_params_to_frame_of_import_func(AOTCompContext *comp_ctx,
             case REF_TYPE_STRUCTREF:
             case REF_TYPE_ARRAYREF:
             case VALUE_TYPE_GC_REF:
+#if WASM_ENABLE_STRINGREF != 0
+            case REF_TYPE_STRINGREF:
+            case REF_TYPE_STRINGVIEWWTF8:
+            case REF_TYPE_STRINGVIEWWTF16:
+            case REF_TYPE_STRINGVIEWITER:
+#endif
                 if (!aot_frame_store_value(
                         comp_ctx, param_values[i], VALUE_TYPE_GC_REF,
                         func_ctx->cur_frame,

+ 2 - 2
core/iwasm/compilation/aot_emit_gc.c

@@ -791,7 +791,7 @@ aot_array_obj_elem_size_log(AOTCompContext *comp_ctx, uint8 array_elem_type)
 }
 
 /* array_obj->elem_data + (elem_idx << elem_size_log) */
-static bool
+bool
 aot_array_obj_elem_addr(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                         LLVMValueRef array_obj, LLVMValueRef elem_idx,
                         LLVMValueRef *p_elem_data, uint8 array_elem_type)
@@ -1064,7 +1064,7 @@ fail:
 }
 
 /* array_obj->length >> WASM_ARRAY_LENGTH_SHIFT */
-static bool
+bool
 aot_array_obj_length(AOTCompContext *comp_ctx, LLVMValueRef array_obj,
                      LLVMValueRef *p_array_len)
 {

+ 9 - 0
core/iwasm/compilation/aot_emit_gc.h

@@ -62,6 +62,15 @@ aot_compile_op_array_new_data(AOTCompContext *comp_ctx,
                               uint32 data_seg_index,
                               const uint8 *frame_ip_array_new_data);
 
+bool
+aot_array_obj_length(AOTCompContext *comp_ctx, LLVMValueRef array_obj,
+                     LLVMValueRef *p_array_len);
+
+bool
+aot_array_obj_elem_addr(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                        LLVMValueRef array_obj, LLVMValueRef elem_idx,
+                        LLVMValueRef *p_elem_data, uint8 array_elem_type);
+
 bool
 aot_compile_op_array_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                          uint32 type_index, bool sign);

+ 7 - 4
core/iwasm/compilation/aot_emit_memory.c

@@ -338,7 +338,7 @@ fail:
         }                                                               \
     } while (0)
 
-#if WASM_ENABLE_SHARED_MEMORY != 0
+#if WASM_ENABLE_SHARED_MEMORY != 0 || WASM_ENABLE_STRINGREF != 0
 bool
 check_memory_alignment(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                        LLVMValueRef addr, uint32 align)
@@ -376,7 +376,9 @@ check_memory_alignment(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 fail:
     return false;
 }
+#endif /* WASM_ENABLE_SHARED_MEMORY != 0 || WASM_ENABLE_STRINGREF != 0 */
 
+#if WASM_ENABLE_SHARED_MEMORY != 0
 #define BUILD_ATOMIC_LOAD(align, data_type)                                \
     do {                                                                   \
         if (!(check_memory_alignment(comp_ctx, func_ctx, maddr, align))) { \
@@ -874,9 +876,8 @@ fail:
     return false;
 }
 
-#if WASM_ENABLE_BULK_MEMORY != 0
-
-static LLVMValueRef
+#if WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_STRINGREF != 0
+LLVMValueRef
 check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                            LLVMValueRef offset, LLVMValueRef bytes)
 {
@@ -971,7 +972,9 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 fail:
     return NULL;
 }
+#endif /* end of WASM_ENABLE_BULK_MEMORY != 0 or WASM_ENABLE_STRINGREF != 0 */
 
+#if WASM_ENABLE_BULK_MEMORY != 0
 bool
 aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                            uint32 seg_index)

+ 8 - 0
core/iwasm/compilation/aot_emit_memory.h

@@ -61,6 +61,14 @@ aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
 bool
 aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
 
+bool
+check_memory_alignment(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                       LLVMValueRef addr, uint32 align);
+
+LLVMValueRef
+check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                           LLVMValueRef offset, LLVMValueRef bytes);
+
 #if WASM_ENABLE_BULK_MEMORY != 0
 bool
 aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,

+ 1461 - 0
core/iwasm/compilation/aot_emit_stringref.c

@@ -0,0 +1,1461 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#if WASM_ENABLE_STRINGREF != 0
+
+#include "aot_emit_stringref.h"
+#include "aot_emit_exception.h"
+#include "aot_emit_memory.h"
+#include "aot_emit_gc.h"
+#include "aot.h"
+#include "aot_compiler.h"
+#include "aot_emit_memory.h"
+#include "gc_object.h"
+#include "string_object.h"
+
+#define BUILD_ISNULL(ptr, res, name)                                  \
+    do {                                                              \
+        if (!(res = LLVMBuildIsNull(comp_ctx->builder, ptr, name))) { \
+            aot_set_last_error("llvm build isnull failed.");          \
+            goto fail;                                                \
+        }                                                             \
+    } while (0)
+
+#define BUILD_ISNOTNULL(ptr, res, name)                                  \
+    do {                                                                 \
+        if (!(res = LLVMBuildIsNotNull(comp_ctx->builder, ptr, name))) { \
+            aot_set_last_error("llvm build isnotnull failed.");          \
+            goto fail;                                                   \
+        }                                                                \
+    } while (0)
+
+#define ADD_BASIC_BLOCK(block, name)                                          \
+    do {                                                                      \
+        if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context,        \
+                                                    func_ctx->func, name))) { \
+            aot_set_last_error("llvm add basic block failed.");               \
+            goto fail;                                                        \
+        }                                                                     \
+    } while (0)
+
+#define CURR_BLOCK() LLVMGetInsertBlock(comp_ctx->builder)
+
+#define MOVE_BLOCK_AFTER(llvm_block, llvm_block_after) \
+    LLVMMoveBasicBlockAfter(llvm_block, llvm_block_after)
+
+#define MOVE_BLOCK_AFTER_CURR(llvm_block) \
+    LLVMMoveBasicBlockAfter(llvm_block, CURR_BLOCK())
+
+#define DEFINE_STRINGREF_CHECK_VAR()                                   \
+    LLVMBasicBlockRef check_string_obj_succ, check_stringref_obj_succ; \
+    LLVMValueRef cmp
+
+#define CHECK_STRING_OBJ(str_obj)                                        \
+    do {                                                                 \
+        ADD_BASIC_BLOCK(check_string_obj_succ, "check string obj succ"); \
+        MOVE_BLOCK_AFTER_CURR(check_string_obj_succ);                    \
+                                                                         \
+        BUILD_ISNULL(str_obj, cmp, "cmp_string_obj");                    \
+        if (!aot_emit_exception(comp_ctx, func_ctx,                      \
+                                EXCE_FAILED_TO_CREATE_STRING, true, cmp, \
+                                check_string_obj_succ))                  \
+            goto fail;                                                   \
+    } while (0)
+
+#define CHECK_STRINGREF_INTERNAL(stringref_obj, exce_id, name)                \
+    do {                                                                      \
+        ADD_BASIC_BLOCK(check_stringref_obj_succ, "check " name " obj succ"); \
+        MOVE_BLOCK_AFTER(check_stringref_obj_succ, check_string_obj_succ);    \
+                                                                              \
+        BUILD_ISNULL(stringref_obj, cmp, "cmp_" name "_obj");                 \
+        if (!aot_emit_exception(comp_ctx, func_ctx, exce_id, true, cmp,       \
+                                check_stringref_obj_succ))                    \
+            goto fail;                                                        \
+    } while (0)
+
+#define CHECK_STRINGREF_OBJ(stringref_obj)                                   \
+    CHECK_STRINGREF_INTERNAL(stringref_obj, EXCE_FAILED_TO_CREATE_STRINGREF, \
+                             "stringref")
+
+#define CHECK_STRINGVIEW_OBJ(stringview_obj)                                   \
+    CHECK_STRINGREF_INTERNAL(stringview_obj, EXCE_FAILED_TO_CREATE_STRINGVIEW, \
+                             "stringview")
+
+#define CHECK_STRING_ENCODE(value)                                             \
+    do {                                                                       \
+        ADD_BASIC_BLOCK(check_string_encode_succ, "check string encode succ"); \
+        MOVE_BLOCK_AFTER_CURR(check_string_encode_succ);                       \
+                                                                               \
+        if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, value,        \
+                                  I32_ZERO, "cmp_string_encode"))) {           \
+            aot_set_last_error("llvm build icmp failed.");                     \
+            goto fail;                                                         \
+        }                                                                      \
+                                                                               \
+        if (!aot_emit_exception(comp_ctx, func_ctx,                            \
+                                EXCE_FAILED_TO_ENCODE_STRING, true, cmp,       \
+                                check_string_encode_succ))                     \
+            goto fail;                                                         \
+    } while (0)
+
+static bool
+aot_call_wasm_stringref_obj_new(AOTCompContext *comp_ctx,
+                                AOTFuncContext *func_ctx, LLVMValueRef str_obj,
+                                uint32 stringref_type, uint32 pos,
+                                LLVMValueRef *stringref_obj)
+{
+    LLVMValueRef param_values[3], func, value, res;
+    LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
+    uint32 argc = 2;
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = INT8_PTR_TYPE;
+    param_types[2] = I32_TYPE;
+    ret_type = INT8_PTR_TYPE;
+
+    if (stringref_type == WASM_TYPE_STRINGREF) {
+        GET_AOT_FUNCTION(wasm_stringref_obj_new, argc);
+    }
+    else if (stringref_type == WASM_TYPE_STRINGVIEWWTF8) {
+        GET_AOT_FUNCTION(wasm_stringview_wtf8_obj_new, argc);
+    }
+    else if (stringref_type == WASM_TYPE_STRINGVIEWWTF16) {
+        GET_AOT_FUNCTION(wasm_stringview_wtf16_obj_new, argc);
+    }
+    else {
+        argc = 3;
+        GET_AOT_FUNCTION(wasm_stringview_iter_obj_new, argc);
+    }
+
+    param_values[0] = func_ctx->exec_env;
+    param_values[1] = str_obj;
+    if (stringref_type == WASM_TYPE_STRINGVIEWITER) {
+        param_values[2] = I32_CONST(pos);
+    }
+
+    if (!(res = LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values,
+                               argc, "create_stringref"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    *stringref_obj = res;
+
+    return true;
+fail:
+    return false;
+}
+
+static LLVMValueRef
+aot_stringref_obj_get_value(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                            LLVMValueRef stringref_obj)
+{
+    LLVMValueRef str_obj_ptr, str_obj, host_ptr_offset;
+
+    /* header */
+    host_ptr_offset = I32_CONST(comp_ctx->pointer_size);
+
+    if (!(stringref_obj =
+              LLVMBuildBitCast(comp_ctx->builder, stringref_obj, INT8_PTR_TYPE,
+                               "stringref_obj_i8p"))) {
+        aot_set_last_error("llvm build bitcast failed.");
+        goto fail;
+    }
+
+    if (!(str_obj_ptr =
+              LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, stringref_obj,
+                                    &host_ptr_offset, 1, "str_obj_i8p"))) {
+        aot_set_last_error("llvm build gep failed.");
+        goto fail;
+    }
+
+    if (!(str_obj_ptr = LLVMBuildBitCast(comp_ctx->builder, str_obj_ptr,
+                                         GC_REF_PTR_TYPE, "str_obj_gcref_p"))) {
+        aot_set_last_error("llvm build bitcast failed.");
+        goto fail;
+    }
+
+    if (!(str_obj = LLVMBuildLoad2(comp_ctx->builder, GC_REF_TYPE, str_obj_ptr,
+                                   "str_obj"))) {
+        aot_set_last_error("llvm build load failed.");
+        goto fail;
+    }
+
+    LLVMSetAlignment(str_obj, 4);
+
+    return str_obj;
+
+fail:
+    return NULL;
+}
+
+static LLVMValueRef
+get_stringview_iter_pos_addr(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                             LLVMValueRef stringview_iter_obj)
+{
+    LLVMValueRef iter_pos_ptr, host_ptr_offset;
+
+    /* header + str_obj */
+    host_ptr_offset = I32_CONST(comp_ctx->pointer_size * 2);
+
+    if (!(stringview_iter_obj =
+              LLVMBuildBitCast(comp_ctx->builder, stringview_iter_obj,
+                               INT8_PTR_TYPE, "stringview_iter_obj_i8p"))) {
+        aot_set_last_error("llvm build bitcast failed.");
+        goto fail;
+    }
+
+    if (!(iter_pos_ptr = LLVMBuildInBoundsGEP2(
+              comp_ctx->builder, INT8_TYPE, stringview_iter_obj,
+              &host_ptr_offset, 1, "iter_pos_i8p"))) {
+        aot_set_last_error("llvm build gep failed.");
+        goto fail;
+    }
+
+    if (!(iter_pos_ptr = LLVMBuildBitCast(comp_ctx->builder, iter_pos_ptr,
+                                          INT32_PTR_TYPE, "iter_pos_i32p"))) {
+        aot_set_last_error("llvm build bitcast failed.");
+        goto fail;
+    }
+
+    return iter_pos_ptr;
+
+fail:
+    return NULL;
+}
+
+static LLVMValueRef
+aot_call_wasm_string_measure(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                             LLVMValueRef stringref_obj, uint32 encoding)
+{
+    LLVMValueRef param_values[3], func, value, str_obj;
+    LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
+
+    if (!(str_obj =
+              aot_stringref_obj_get_value(comp_ctx, func_ctx, stringref_obj))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_measure, 2);
+
+    /* Call function wasm_string_measure() */
+    param_values[0] = str_obj;
+    param_values[1] = I32_CONST(encoding);
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 2, "string_measure"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    return value;
+fail:
+    return NULL;
+}
+
+static LLVMValueRef
+aot_call_wasm_string_create_view(AOTCompContext *comp_ctx,
+                                 AOTFuncContext *func_ctx,
+                                 LLVMValueRef stringref_obj, uint32 encoding)
+{
+    LLVMValueRef param_values[3], func, value, str_obj;
+    LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
+
+    if (!(str_obj =
+              aot_stringref_obj_get_value(comp_ctx, func_ctx, stringref_obj))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    ret_type = INT8_PTR_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_create_view, 2);
+
+    /* Call function wasm_string_create_view() */
+    param_values[0] = str_obj;
+    param_values[1] = I32_CONST(encoding);
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 2, "string_create_view"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    return value;
+fail:
+    return NULL;
+}
+
+static LLVMValueRef
+aot_call_wasm_string_advance(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                             LLVMValueRef stringref_obj, LLVMValueRef bytes,
+                             LLVMValueRef pos)
+{
+    LLVMValueRef param_values[4], func, value, str_obj;
+    LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type;
+
+    if (!(str_obj =
+              aot_stringref_obj_get_value(comp_ctx, func_ctx, stringref_obj))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = INT32_PTR_TYPE;
+    ret_type = INT8_PTR_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_advance, 4);
+
+    /* Call function wasm_string_advance() */
+    param_values[0] = str_obj;
+    param_values[1] = pos;
+    param_values[2] = bytes;
+    param_values[3] = I8_PTR_NULL;
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 4, "string_advance"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    return value;
+fail:
+    return NULL;
+}
+
+static LLVMValueRef
+aot_call_wasm_string_slice(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                           LLVMValueRef stringref_obj, LLVMValueRef start,
+                           LLVMValueRef end, StringViewType stringview_type)
+{
+    LLVMValueRef param_values[4], func, value, str_obj;
+    LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type;
+
+    if (!(str_obj =
+              aot_stringref_obj_get_value(comp_ctx, func_ctx, stringref_obj))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = I32_TYPE;
+    ret_type = INT8_PTR_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_slice, 4);
+
+    /* Call function wasm_string_slice() */
+    param_values[0] = str_obj;
+    param_values[1] = start;
+    param_values[2] = end;
+    param_values[3] = I32_CONST(stringview_type);
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 4, "string_slice"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    return value;
+fail:
+    return NULL;
+}
+
+bool
+aot_compile_op_string_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                          uint32 encoding, const uint8 *frame_ip_stringref_new)
+{
+    LLVMValueRef maddr, byte_length, offset, str_obj, stringref_obj;
+    LLVMValueRef param_values[5], func, value;
+    LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
+    DEFINE_STRINGREF_CHECK_VAR();
+
+    if (!aot_gen_commit_values(comp_ctx->aot_frame))
+        return false;
+
+    if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
+                              frame_ip_stringref_new))
+        return false;
+
+    POP_I32(byte_length);
+    POP_I32(offset);
+
+    if (!(maddr = check_bulk_memory_overflow(comp_ctx, func_ctx, offset,
+                                             byte_length)))
+        goto fail;
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    ret_type = INT8_PTR_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_new_with_encoding, 3);
+
+    /* Call function wasm_struct_obj_new() */
+    param_values[0] = maddr;
+    param_values[1] = byte_length;
+    param_values[2] = I32_CONST(encoding);
+
+    if (!(str_obj = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                   param_values, 3, "wasm_string_new"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+    CHECK_STRING_OBJ(str_obj);
+
+    if (!aot_call_wasm_stringref_obj_new(comp_ctx, func_ctx, str_obj,
+                                         WASM_TYPE_STRINGREF, 0,
+                                         &stringref_obj)) {
+        goto fail;
+    }
+    CHECK_STRINGREF_OBJ(stringref_obj);
+
+    PUSH_GC_REF(stringref_obj);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                            uint32 contents, const uint8 *frame_ip_string_const)
+{
+    LLVMValueRef param_values[2], func, value, str_obj, stringref_obj;
+    LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+    DEFINE_STRINGREF_CHECK_VAR();
+
+    if (!aot_gen_commit_values(comp_ctx->aot_frame))
+        return false;
+
+    if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
+                              frame_ip_string_const))
+        return false;
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    ret_type = INT8_PTR_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_new_const, 2);
+
+    bh_assert(contents < comp_ctx->comp_data->string_literal_count);
+    param_values[0] = LLVMConstIntToPtr(
+        I64_CONST((unsigned long long)(uintptr_t)
+                      comp_ctx->comp_data->string_literal_ptrs_wp[contents]),
+        INT8_PTR_TYPE);
+    param_values[1] =
+        I32_CONST(comp_ctx->comp_data->string_literal_lengths_wp[contents]);
+
+    if (!(str_obj = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                   param_values, 2, "create_stringref"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+    CHECK_STRING_OBJ(str_obj);
+
+    if (!aot_call_wasm_stringref_obj_new(comp_ctx, func_ctx, str_obj,
+                                         WASM_TYPE_STRINGREF, 0,
+                                         &stringref_obj)) {
+        goto fail;
+    }
+    CHECK_STRINGREF_OBJ(stringref_obj);
+
+    PUSH_GC_REF(stringref_obj);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_measure(AOTCompContext *comp_ctx,
+                              AOTFuncContext *func_ctx, uint32 encoding)
+{
+    LLVMValueRef stringref_obj, value;
+
+    POP_GC_REF(stringref_obj);
+
+    if (!(value = aot_call_wasm_string_measure(comp_ctx, func_ctx,
+                                               stringref_obj, encoding))) {
+        goto fail;
+    }
+
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_encode(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                             uint32 mem_idx, uint32 encoding)
+{
+    LLVMValueRef param_values[6], func, value, offset, length, maddr, str_obj,
+        stringref_obj;
+    LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
+    LLVMBasicBlockRef check_string_encode_succ;
+    LLVMValueRef cmp;
+
+    POP_I32(offset);
+    POP_GC_REF(stringref_obj);
+
+    if (!(str_obj =
+              aot_stringref_obj_get_value(comp_ctx, func_ctx, stringref_obj))) {
+        goto fail;
+    }
+
+    if (!(length = aot_call_wasm_string_measure(comp_ctx, func_ctx,
+                                                stringref_obj, encoding))) {
+        goto fail;
+    }
+
+    if (!(maddr =
+              check_bulk_memory_overflow(comp_ctx, func_ctx, offset, length)))
+        goto fail;
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = INT8_PTR_TYPE;
+    param_types[4] = INT8_PTR_TYPE;
+    param_types[5] = I32_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_encode, 6);
+
+    /* Call function wasm_string_measure() */
+    param_values[0] = str_obj;
+    param_values[1] = I32_ZERO;
+    param_values[2] = length;
+    param_values[3] = maddr;
+    param_values[4] = I8_PTR_NULL;
+    param_values[5] = I32_CONST(encoding);
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 6, "string_encode"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    CHECK_STRING_ENCODE(value);
+
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_concat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                             const uint8 *frame_ip_string_concat)
+{
+    LLVMValueRef param_values[2], func, value, str_obj_lhs, str_obj_rhs,
+        stringref_obj_lhs, stringref_obj_rhs, stringref_obj_new;
+    LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+    DEFINE_STRINGREF_CHECK_VAR();
+
+    if (!aot_gen_commit_values(comp_ctx->aot_frame))
+        return false;
+
+    if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
+                              frame_ip_string_concat))
+        return false;
+
+    POP_GC_REF(stringref_obj_rhs);
+    POP_GC_REF(stringref_obj_lhs);
+
+    if (!(str_obj_lhs = aot_stringref_obj_get_value(comp_ctx, func_ctx,
+                                                    stringref_obj_lhs))) {
+        goto fail;
+    }
+
+    if (!(str_obj_rhs = aot_stringref_obj_get_value(comp_ctx, func_ctx,
+                                                    stringref_obj_rhs))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = INT8_PTR_TYPE;
+    ret_type = INT8_PTR_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_concat, 2);
+
+    /* Call function wasm_string_concat() */
+    param_values[0] = str_obj_lhs;
+    param_values[1] = str_obj_rhs;
+
+    if (!(str_obj_lhs = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                       param_values, 2, "string_concat"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+    CHECK_STRING_OBJ(str_obj_lhs);
+
+    if (!aot_call_wasm_stringref_obj_new(comp_ctx, func_ctx, str_obj_lhs,
+                                         WASM_TYPE_STRINGREF, 0,
+                                         &stringref_obj_new)) {
+        goto fail;
+    }
+    CHECK_STRINGREF_OBJ(stringref_obj_new);
+
+    PUSH_GC_REF(stringref_obj_new);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_eq(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+    LLVMValueRef param_values[2], func, value, str_obj_lhs, str_obj_rhs,
+        stringref_obj_lhs, stringref_obj_rhs;
+    LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+
+    POP_GC_REF(stringref_obj_lhs);
+    POP_GC_REF(stringref_obj_rhs);
+
+    if (!(str_obj_lhs = aot_stringref_obj_get_value(comp_ctx, func_ctx,
+                                                    stringref_obj_lhs))) {
+        goto fail;
+    }
+
+    if (!(str_obj_rhs = aot_stringref_obj_get_value(comp_ctx, func_ctx,
+                                                    stringref_obj_rhs))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = INT8_PTR_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_eq, 2);
+
+    /* Call function wasm_string_eq() */
+    param_values[0] = str_obj_lhs;
+    param_values[1] = str_obj_rhs;
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 2, "string_eq"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_is_usv_sequence(AOTCompContext *comp_ctx,
+                                      AOTFuncContext *func_ctx)
+{
+    LLVMValueRef param_values[1], func, value, str_obj, stringref_obj;
+    LLVMTypeRef param_types[1], ret_type, func_type, func_ptr_type;
+
+    POP_GC_REF(stringref_obj);
+
+    if (!(str_obj =
+              aot_stringref_obj_get_value(comp_ctx, func_ctx, stringref_obj))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_is_usv_sequence, 1);
+
+    /* Call function wasm_string_is_usv_sequence() */
+    param_values[0] = str_obj;
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 1, "string_is_usv_sequence"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_as_wtf8(AOTCompContext *comp_ctx,
+                              AOTFuncContext *func_ctx,
+                              const uint8 *frame_ip_string_as_wtf8)
+{
+    LLVMValueRef str_obj, stringref_obj, stringview_wtf8_obj;
+    DEFINE_STRINGREF_CHECK_VAR();
+
+    if (!aot_gen_commit_values(comp_ctx->aot_frame))
+        return false;
+
+    if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
+                              frame_ip_string_as_wtf8))
+        return false;
+
+    POP_GC_REF(stringref_obj);
+
+    if (!(str_obj = aot_call_wasm_string_create_view(
+              comp_ctx, func_ctx, stringref_obj, STRING_VIEW_WTF8))) {
+        goto fail;
+    }
+    CHECK_STRING_OBJ(str_obj);
+
+    if (!aot_call_wasm_stringref_obj_new(comp_ctx, func_ctx, str_obj,
+                                         WASM_TYPE_STRINGVIEWWTF8, 0,
+                                         &stringview_wtf8_obj)) {
+        goto fail;
+    }
+    CHECK_STRINGVIEW_OBJ(stringref_obj);
+
+    PUSH_GC_REF(stringview_wtf8_obj);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_stringview_wtf8_advance(AOTCompContext *comp_ctx,
+                                       AOTFuncContext *func_ctx)
+{
+    LLVMValueRef stringref_obj, bytes, pos, value;
+
+    POP_I32(bytes);
+    POP_I32(pos);
+    POP_GC_REF(stringref_obj);
+
+    if (!(value = aot_call_wasm_string_advance(comp_ctx, func_ctx,
+                                               stringref_obj, bytes, pos))) {
+        goto fail;
+    }
+
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_stringview_wtf8_encode(AOTCompContext *comp_ctx,
+                                      AOTFuncContext *func_ctx, uint32 mem_idx,
+                                      uint32 encoding)
+{
+    LLVMValueRef param_values[6], func, value, offset, maddr, str_obj,
+        stringref_obj;
+    LLVMValueRef bytes, pos, next_pos;
+    LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
+    LLVMBasicBlockRef check_string_encode_succ;
+    LLVMValueRef cmp;
+
+    POP_I32(bytes);
+    POP_I32(pos);
+    POP_I32(offset);
+
+    next_pos = LLVMBuildAlloca(comp_ctx->builder, I32_TYPE, "next_pos");
+    if (!next_pos) {
+        aot_set_last_error("failed to build alloca");
+        goto fail;
+    }
+
+    if (!(maddr =
+              check_bulk_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+        goto fail;
+
+    POP_GC_REF(stringref_obj);
+
+    if (!(str_obj =
+              aot_stringref_obj_get_value(comp_ctx, func_ctx, stringref_obj))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = INT8_PTR_TYPE;
+    param_types[4] = INT8_PTR_TYPE;
+    param_types[5] = I32_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_encode, 6);
+
+    /* Call function wasm_string_measure() */
+    param_values[0] = str_obj;
+    param_values[1] = pos;
+    param_values[2] = bytes;
+    param_values[3] = maddr;
+    param_values[4] = next_pos;
+    param_values[5] = I32_CONST(encoding);
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 6, "string_encode"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    CHECK_STRING_ENCODE(value);
+
+    next_pos =
+        LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, next_pos, "next_pos");
+    if (!next_pos) {
+        aot_set_last_error("llvm build load failed.");
+        goto fail;
+    }
+
+    LLVMSetAlignment(next_pos, 4);
+
+    PUSH_I32(next_pos);
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_stringview_wtf8_slice(AOTCompContext *comp_ctx,
+                                     AOTFuncContext *func_ctx,
+                                     const uint8 *frame_ip_wtf8_slice)
+{
+    LLVMValueRef stringref_obj, start, end, stringref_obj_new, value;
+    DEFINE_STRINGREF_CHECK_VAR();
+
+    if (!aot_gen_commit_values(comp_ctx->aot_frame))
+        return false;
+
+    if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
+                              frame_ip_wtf8_slice))
+        return false;
+
+    POP_I32(start);
+    POP_I32(end);
+    POP_GC_REF(stringref_obj);
+
+    if (!(value = aot_call_wasm_string_slice(comp_ctx, func_ctx, stringref_obj,
+                                             start, end, STRING_VIEW_WTF8))) {
+        goto fail;
+    }
+    CHECK_STRING_OBJ(value);
+
+    if (!aot_call_wasm_stringref_obj_new(comp_ctx, func_ctx, value,
+                                         WASM_TYPE_STRINGREF, 0,
+                                         &stringref_obj_new)) {
+        goto fail;
+    }
+    CHECK_STRINGREF_OBJ(stringref_obj_new);
+
+    PUSH_GC_REF(stringref_obj_new);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_as_wtf16(AOTCompContext *comp_ctx,
+                               AOTFuncContext *func_ctx,
+                               const uint8 *frame_ip_string_as_wtf16)
+{
+    LLVMValueRef str_obj, stringref_obj, stringview_wtf16_obj;
+    DEFINE_STRINGREF_CHECK_VAR();
+
+    if (!aot_gen_commit_values(comp_ctx->aot_frame))
+        return false;
+
+    if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
+                              frame_ip_string_as_wtf16))
+        return false;
+
+    POP_GC_REF(stringref_obj);
+
+    if (!(str_obj = aot_call_wasm_string_create_view(
+              comp_ctx, func_ctx, stringref_obj, STRING_VIEW_WTF16))) {
+        goto fail;
+    }
+    CHECK_STRING_OBJ(str_obj);
+
+    if (!aot_call_wasm_stringref_obj_new(comp_ctx, func_ctx, str_obj,
+                                         WASM_TYPE_STRINGVIEWWTF16, 0,
+                                         &stringview_wtf16_obj)) {
+        goto fail;
+    }
+    CHECK_STRINGVIEW_OBJ(stringview_wtf16_obj);
+
+    PUSH_GC_REF(stringview_wtf16_obj);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_stringview_wtf16_length(AOTCompContext *comp_ctx,
+                                       AOTFuncContext *func_ctx)
+{
+    LLVMValueRef param_values[2], func, value, str_obj, stringview_wtf16_obj;
+    LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+
+    POP_GC_REF(stringview_wtf16_obj);
+
+    if (!(str_obj = aot_stringref_obj_get_value(comp_ctx, func_ctx,
+                                                stringview_wtf16_obj))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_wtf16_get_length, 6);
+
+    /* Call function wasm_string_wtf16_get_length() */
+    param_values[0] = str_obj;
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 1, "stringview_wtf16_length"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_stringview_wtf16_get_codeunit(AOTCompContext *comp_ctx,
+                                             AOTFuncContext *func_ctx)
+{
+    LLVMValueRef param_values[2], func, value, str_obj, stringview_wtf16_obj,
+        pos;
+    LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+
+    POP_I32(pos);
+    POP_GC_REF(stringview_wtf16_obj);
+
+    if (!(str_obj = aot_stringref_obj_get_value(comp_ctx, func_ctx,
+                                                stringview_wtf16_obj))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_get_wtf16_codeunit, 2);
+
+    /* Call function wasm_string_get_wtf16_codeunit() */
+    param_values[0] = str_obj;
+    param_values[1] = pos;
+
+    if (!(value =
+              LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values,
+                             2, "stringview_wtf16_get_codeunit"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_stringview_wtf16_encode(AOTCompContext *comp_ctx,
+                                       AOTFuncContext *func_ctx, uint32 mem_idx)
+{
+    LLVMValueRef param_values[6], func, value, offset, maddr, str_obj,
+        stringref_obj;
+    LLVMValueRef len, pos;
+    LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
+    LLVMBasicBlockRef check_string_encode_succ;
+    LLVMValueRef cmp;
+
+    POP_I32(len);
+    POP_I32(pos);
+    POP_I32(offset);
+
+    if (!(maddr = check_bulk_memory_overflow(
+              comp_ctx, func_ctx, offset,
+              LLVMBuildMul(comp_ctx->builder, len, I32_CONST(2), "wtf16_len"))))
+        goto fail;
+
+    POP_GC_REF(stringref_obj);
+
+    if (!check_memory_alignment(comp_ctx, func_ctx, maddr, 2)) {
+        goto fail;
+    }
+
+    if (!(str_obj =
+              aot_stringref_obj_get_value(comp_ctx, func_ctx, stringref_obj))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = INT8_PTR_TYPE;
+    param_types[4] = INT8_PTR_TYPE;
+    param_types[5] = I32_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_encode, 6);
+
+    /* Call function wasm_string_measure() */
+    param_values[0] = str_obj;
+    param_values[1] = pos;
+    param_values[2] = len;
+    param_values[3] = maddr;
+    param_values[4] = I8_PTR_NULL;
+    param_values[5] = I32_CONST(WTF16);
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 6, "string_encode"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    CHECK_STRING_ENCODE(value);
+
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_stringview_wtf16_slice(AOTCompContext *comp_ctx,
+                                      AOTFuncContext *func_ctx,
+                                      const uint8 *frame_ip_wtf16_slice)
+{
+    LLVMValueRef stringref_obj, start, end, stringref_obj_new, value;
+    DEFINE_STRINGREF_CHECK_VAR();
+
+    if (!aot_gen_commit_values(comp_ctx->aot_frame))
+        return false;
+
+    if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
+                              frame_ip_wtf16_slice))
+        return false;
+
+    POP_I32(end);
+    POP_I32(start);
+    POP_GC_REF(stringref_obj);
+
+    if (!(value = aot_call_wasm_string_slice(comp_ctx, func_ctx, stringref_obj,
+                                             start, end, STRING_VIEW_WTF16))) {
+        goto fail;
+    }
+    CHECK_STRING_OBJ(value);
+
+    if (!aot_call_wasm_stringref_obj_new(comp_ctx, func_ctx, value,
+                                         WASM_TYPE_STRINGREF, 0,
+                                         &stringref_obj_new)) {
+        goto fail;
+    }
+    CHECK_STRINGREF_OBJ(stringref_obj_new);
+
+    PUSH_GC_REF(stringref_obj_new);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_as_iter(AOTCompContext *comp_ctx,
+                              AOTFuncContext *func_ctx,
+                              const uint8 *frame_ip_string_as_iter)
+{
+    LLVMValueRef stringref_obj, stringview_iter_obj, str_obj;
+    DEFINE_STRINGREF_CHECK_VAR();
+
+    if (!aot_gen_commit_values(comp_ctx->aot_frame))
+        return false;
+
+    if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
+                              frame_ip_string_as_iter))
+        return false;
+
+    POP_GC_REF(stringref_obj);
+
+    if (!(str_obj = aot_call_wasm_string_create_view(
+              comp_ctx, func_ctx, stringref_obj, STRING_VIEW_WTF8))) {
+        goto fail;
+    }
+    CHECK_STRING_OBJ(str_obj);
+
+    if (!aot_call_wasm_stringref_obj_new(comp_ctx, func_ctx, stringref_obj,
+                                         WASM_TYPE_STRINGVIEWITER, 0,
+                                         &stringview_iter_obj)) {
+        goto fail;
+    }
+    CHECK_STRINGVIEW_OBJ(stringview_iter_obj);
+
+    PUSH_GC_REF(stringview_iter_obj);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_stringview_iter_next(AOTCompContext *comp_ctx,
+                                    AOTFuncContext *func_ctx)
+{
+    LLVMValueRef param_values[2], func, value, stringview_iter_obj, str_obj,
+        iter_pos_addr, pos;
+    LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+
+    POP_GC_REF(stringview_iter_obj);
+
+    if (!(str_obj = aot_stringref_obj_get_value(comp_ctx, func_ctx,
+                                                stringview_iter_obj))) {
+        goto fail;
+    }
+
+    if (!(iter_pos_addr = get_stringview_iter_pos_addr(comp_ctx, func_ctx,
+                                                       stringview_iter_obj))) {
+        goto fail;
+    }
+
+    pos = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, iter_pos_addr,
+                         "get_iter_pos");
+    LLVMSetAlignment(pos, 4);
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_next_codepoint, 2);
+
+    /* Call function wasm_string_measure() */
+    param_values[0] = str_obj;
+    param_values[1] = pos;
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 2, "stringview_iter_next"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+static bool
+stringview_iter_advance_or_rewind(AOTCompContext *comp_ctx,
+                                  AOTFuncContext *func_ctx, bool is_rewind)
+{
+    LLVMValueRef param_values[4], func, value, stringview_iter_obj, str_obj,
+        code_points_consumed, iter_pos_addr, pos, code_points_count, res;
+    LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type;
+
+    POP_I32(code_points_count);
+    POP_GC_REF(stringview_iter_obj);
+
+    if (!(str_obj = aot_stringref_obj_get_value(comp_ctx, func_ctx,
+                                                stringview_iter_obj))) {
+        goto fail;
+    }
+
+    if (!(iter_pos_addr = get_stringview_iter_pos_addr(comp_ctx, func_ctx,
+                                                       stringview_iter_obj))) {
+        goto fail;
+    }
+
+    if (!(pos = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, iter_pos_addr,
+                               "get_iter_pos"))) {
+        goto fail;
+    }
+    LLVMSetAlignment(pos, 4);
+
+    if (!(code_points_consumed = LLVMBuildAlloca(comp_ctx->builder, I32_TYPE,
+                                                 "code_points_consumed"))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = INT32_PTR_TYPE;
+    ret_type = I32_TYPE;
+
+    if (is_rewind) {
+        GET_AOT_FUNCTION(wasm_string_rewind, 4);
+    }
+    else {
+        GET_AOT_FUNCTION(wasm_string_advance, 4);
+    }
+
+    /* Call function wasm_string_advance() */
+    param_values[0] = str_obj;
+    param_values[1] = pos;
+    param_values[2] = code_points_count;
+    param_values[3] = code_points_consumed;
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 4, "string_advance"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    if (!(code_points_consumed =
+              LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, code_points_consumed,
+                             "get_code_points_consumed"))) {
+        aot_set_last_error("llvm build load failed.");
+        goto fail;
+    }
+    LLVMSetAlignment(code_points_consumed, 4);
+
+    if (!(res = LLVMBuildStore(comp_ctx->builder, code_points_consumed,
+                               iter_pos_addr))) {
+        aot_set_last_error("llvm build store failed.");
+        goto fail;
+    }
+    LLVMSetAlignment(res, 4);
+
+    PUSH_I32(code_points_consumed);
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_stringview_iter_advance(AOTCompContext *comp_ctx,
+                                       AOTFuncContext *func_ctx)
+{
+    return stringview_iter_advance_or_rewind(comp_ctx, func_ctx, false);
+}
+
+bool
+aot_compile_op_stringview_iter_rewind(AOTCompContext *comp_ctx,
+                                      AOTFuncContext *func_ctx)
+{
+    return stringview_iter_advance_or_rewind(comp_ctx, func_ctx, true);
+}
+
+bool
+aot_compile_op_stringview_iter_slice(
+    AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+    const uint8 *frame_ip_stringview_iter_slice)
+{
+    LLVMValueRef stringview_iter_obj, start, end, stringref_obj_new, value,
+        iter_pos_addr, code_points_count;
+    DEFINE_STRINGREF_CHECK_VAR();
+
+    if (!aot_gen_commit_values(comp_ctx->aot_frame))
+        return false;
+
+    if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
+                              frame_ip_stringview_iter_slice))
+        return false;
+
+    POP_I32(code_points_count);
+    POP_GC_REF(stringview_iter_obj);
+
+    if (!(iter_pos_addr = get_stringview_iter_pos_addr(comp_ctx, func_ctx,
+                                                       stringview_iter_obj))) {
+        goto fail;
+    }
+
+    if (!(start = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, iter_pos_addr,
+                                 "get_iter_pos"))) {
+        goto fail;
+    }
+    LLVMSetAlignment(start, 4);
+
+    if (!(end = LLVMBuildAdd(comp_ctx->builder, start, code_points_count,
+                             "calc_slice_end"))) {
+        goto fail;
+    }
+
+    if (!(value = aot_call_wasm_string_slice(comp_ctx, func_ctx,
+                                             stringview_iter_obj, start, end,
+                                             STRING_VIEW_ITER))) {
+        goto fail;
+    }
+    CHECK_STRING_OBJ(value);
+
+    if (!aot_call_wasm_stringref_obj_new(comp_ctx, func_ctx, value,
+                                         WASM_TYPE_STRINGREF, 0,
+                                         &stringref_obj_new)) {
+        goto fail;
+    }
+    CHECK_STRINGREF_OBJ(stringref_obj_new);
+
+    PUSH_GC_REF(stringref_obj_new);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_new_array(AOTCompContext *comp_ctx,
+                                AOTFuncContext *func_ctx, uint32 encoding,
+                                const uint8 *frame_ip_string_new_array)
+{
+    LLVMValueRef start, end, count, str_obj, stringref_obj, array_obj,
+        elem_data_ptr;
+    LLVMValueRef param_values[5], func, value;
+    LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
+    DEFINE_STRINGREF_CHECK_VAR();
+
+    if (!aot_gen_commit_values(comp_ctx->aot_frame))
+        return false;
+
+    if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
+                              frame_ip_string_new_array))
+        return false;
+
+    POP_I32(end);
+    POP_I32(start);
+    POP_GC_REF(array_obj);
+
+    if (!aot_array_obj_elem_addr(
+            comp_ctx, func_ctx, array_obj, start, &elem_data_ptr,
+            encoding == WTF16 ? PACKED_TYPE_I16 : PACKED_TYPE_I8)) {
+        goto fail;
+    }
+
+    if (!(count = LLVMBuildSub(comp_ctx->builder, end, start, "calc_count"))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    ret_type = INT8_PTR_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_new_with_encoding, 3);
+
+    /* Call function wasm_struct_obj_new() */
+    param_values[0] = elem_data_ptr;
+    param_values[1] = count;
+    param_values[2] = I32_CONST(encoding);
+
+    if (!(str_obj = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                   param_values, 3, "wasm_string_new"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+    CHECK_STRING_OBJ(str_obj);
+
+    if (!aot_call_wasm_stringref_obj_new(comp_ctx, func_ctx, str_obj,
+                                         WASM_TYPE_STRINGREF, 0,
+                                         &stringref_obj)) {
+        goto fail;
+    }
+    CHECK_STRINGREF_OBJ(stringref_obj);
+
+    PUSH_GC_REF(stringref_obj);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_string_encode_array(AOTCompContext *comp_ctx,
+                                   AOTFuncContext *func_ctx, uint32 encoding)
+{
+    LLVMValueRef param_values[6], func, value, count, start, str_obj,
+        stringref_obj, array_obj, elem_data_ptr, array_len;
+    LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
+    LLVMBasicBlockRef check_string_encode_succ, check_array_index_succ;
+    LLVMValueRef cmp;
+
+    POP_I32(start);
+    POP_GC_REF(array_obj);
+    POP_GC_REF(stringref_obj);
+
+    if (!(str_obj =
+              aot_stringref_obj_get_value(comp_ctx, func_ctx, stringref_obj))) {
+        goto fail;
+    }
+
+    if (!aot_array_obj_length(comp_ctx, array_obj, &array_len))
+        goto fail;
+
+    if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, start, array_len,
+                              "check_array_index"))) {
+        aot_set_last_error("llvm build icmp failed.");
+        goto fail;
+    }
+
+    ADD_BASIC_BLOCK(check_array_index_succ, "check array index succ");
+    MOVE_BLOCK_AFTER_CURR(check_array_index_succ);
+
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ARRAY_IDX_OOB, true, cmp,
+                            check_array_index_succ)) {
+        goto fail;
+    }
+
+    if (!aot_array_obj_elem_addr(
+            comp_ctx, func_ctx, stringref_obj, start, &elem_data_ptr,
+            encoding == WTF16 ? PACKED_TYPE_I16 : PACKED_TYPE_I8)) {
+        goto fail;
+    }
+
+    if (!(count = aot_call_wasm_string_measure(comp_ctx, func_ctx,
+                                               stringref_obj, encoding))) {
+        goto fail;
+    }
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = INT8_PTR_TYPE;
+    param_types[4] = INT8_PTR_TYPE;
+    param_types[5] = I32_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_string_encode, 6);
+
+    /* Call function wasm_string_measure() */
+    param_values[0] = str_obj;
+    param_values[1] = start;
+    param_values[2] = count;
+    param_values[3] = elem_data_ptr;
+    param_values[4] = I8_PTR_NULL;
+    param_values[5] = I32_CONST(encoding);
+
+    if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                 param_values, 6, "string_encode"))) {
+        aot_set_last_error("llvm build call failed.");
+        goto fail;
+    }
+
+    CHECK_STRING_ENCODE(value);
+
+    PUSH_I32(value);
+
+    return true;
+fail:
+    return false;
+}
+
+#endif /* WASM_ENABLE_STRINGREF != 0 */

+ 120 - 0
core/iwasm/compilation/aot_emit_stringref.h

@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _AOT_EMIT_STRINGREF_H_
+#define _AOT_EMIT_STRINGREF_H_
+
+#include "aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_op_string_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                          uint32 encoding, const uint8 *frame_ip_stringref_new);
+
+bool
+aot_compile_op_string_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                            uint32 contents,
+                            const uint8 *frame_ip_string_const);
+
+bool
+aot_compile_op_string_measure(AOTCompContext *comp_ctx,
+                              AOTFuncContext *func_ctx, uint32 encoding);
+
+bool
+aot_compile_op_string_encode(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                             uint32 mem_idx, uint32 encoding);
+
+bool
+aot_compile_op_string_concat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                             const uint8 *frame_ip_string_concat);
+
+bool
+aot_compile_op_string_eq(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_string_is_usv_sequence(AOTCompContext *comp_ctx,
+                                      AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_string_as_wtf8(AOTCompContext *comp_ctx,
+                              AOTFuncContext *func_ctx,
+                              const uint8 *frame_ip_string_as_wtf8);
+
+bool
+aot_compile_op_stringview_wtf8_advance(AOTCompContext *comp_ctx,
+                                       AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_stringview_wtf8_encode(AOTCompContext *comp_ctx,
+                                      AOTFuncContext *func_ctx, uint32 mem_idx,
+                                      uint32 encoding);
+
+bool
+aot_compile_op_stringview_wtf8_slice(AOTCompContext *comp_ctx,
+                                     AOTFuncContext *func_ctx,
+                                     const uint8 *frame_ip_wtf8_slice);
+
+bool
+aot_compile_op_string_as_wtf16(AOTCompContext *comp_ctx,
+                               AOTFuncContext *func_ctx,
+                               const uint8 *frame_ip_string_as_wtf16);
+
+bool
+aot_compile_op_stringview_wtf16_length(AOTCompContext *comp_ctx,
+                                       AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_stringview_wtf16_get_codeunit(AOTCompContext *comp_ctx,
+                                             AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_stringview_wtf16_encode(AOTCompContext *comp_ctx,
+                                       AOTFuncContext *func_ctx,
+                                       uint32 mem_idx);
+
+bool
+aot_compile_op_stringview_wtf16_slice(AOTCompContext *comp_ctx,
+                                      AOTFuncContext *func_ctx,
+                                      const uint8 *frame_ip_wtf16_slice);
+
+bool
+aot_compile_op_string_as_iter(AOTCompContext *comp_ctx,
+                              AOTFuncContext *func_ctx,
+                              const uint8 *frame_ip_string_as_iter);
+
+bool
+aot_compile_op_stringview_iter_next(AOTCompContext *comp_ctx,
+                                    AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_stringview_iter_advance(AOTCompContext *comp_ctx,
+                                       AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_stringview_iter_rewind(AOTCompContext *comp_ctx,
+                                      AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_stringview_iter_slice(
+    AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+    const uint8 *frame_ip_stringview_iter_slice);
+
+bool
+aot_compile_op_string_new_array(AOTCompContext *comp_ctx,
+                                AOTFuncContext *func_ctx, uint32 encoding,
+                                const uint8 *frame_ip_string_new_array);
+
+bool
+aot_compile_op_string_encode_array(AOTCompContext *comp_ctx,
+                                   AOTFuncContext *func_ctx, uint32 encoding);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _AOT_EMIT_STRINGREF_H_ */

+ 18 - 0
core/iwasm/compilation/aot_llvm.c

@@ -61,6 +61,12 @@ wasm_type_to_llvm_type(const AOTCompContext *comp_ctx,
         case REF_TYPE_I31REF:
         case REF_TYPE_STRUCTREF:
         case REF_TYPE_ARRAYREF:
+#if WASM_ENABLE_STRINGREF != 0
+        case REF_TYPE_STRINGREF:
+        case REF_TYPE_STRINGVIEWWTF8:
+        case REF_TYPE_STRINGVIEWWTF16:
+        case REF_TYPE_STRINGVIEWITER:
+#endif
         case VALUE_TYPE_GC_REF:
             bh_assert(comp_ctx->enable_gc);
             return llvm_types->gc_ref_type;
@@ -1107,6 +1113,12 @@ create_local_variables(const AOTCompData *comp_data,
             case REF_TYPE_I31REF:
             case REF_TYPE_STRUCTREF:
             case REF_TYPE_ARRAYREF:
+#if WASM_ENABLE_STRINGREF != 0
+            case REF_TYPE_STRINGREF:
+            case REF_TYPE_STRINGVIEWWTF8:
+            case REF_TYPE_STRINGVIEWWTF16:
+            case REF_TYPE_STRINGVIEWITER:
+#endif
                 local_value = GC_REF_NULL;
                 break;
 #endif
@@ -3485,6 +3497,12 @@ aot_build_zero_function_ret(const AOTCompContext *comp_ctx,
             case REF_TYPE_I31REF:
             case REF_TYPE_STRUCTREF:
             case REF_TYPE_ARRAYREF:
+#if WASM_ENABLE_STRINGREF != 0
+            case REF_TYPE_STRINGREF:
+            case REF_TYPE_STRINGVIEWWTF8:
+            case REF_TYPE_STRINGVIEWWTF16:
+            case REF_TYPE_STRINGVIEWITER:
+#endif
                 bh_assert(comp_ctx->enable_gc);
                 ret = LLVMBuildRet(comp_ctx->builder, GC_REF_NULL);
                 break;

+ 3 - 2
core/iwasm/interpreter/wasm.h

@@ -744,8 +744,9 @@ struct WASMModule {
 #endif
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_STRINGREF != 0
-    uint32 stringref_count;
-    char **string_consts;
+    uint32 string_literal_count;
+    uint32 *string_literal_lengths;
+    const uint8 **string_literal_ptrs;
 #endif
 #endif
 

+ 10 - 6
core/iwasm/interpreter/wasm_interp_classic.c

@@ -2734,7 +2734,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         read_leb_uint32(frame_ip, frame_ip_end, contents);
 
                         str_obj = wasm_string_new_const(
-                            wasm_module->string_consts[contents]);
+                            (const char *)
+                                wasm_module->string_literal_ptrs[contents],
+                            wasm_module->string_literal_lengths[contents]);
                         if (!str_obj) {
                             wasm_set_exception(module,
                                                "create string object failed");
@@ -3224,7 +3226,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         str_obj = wasm_string_slice(
                             (WASMString)wasm_stringview_iter_obj_get_value(
                                 stringview_iter_obj),
-                            cur_pos, code_points_count, STRING_VIEW_ITER);
+                            cur_pos, cur_pos + code_points_count,
+                            STRING_VIEW_ITER);
                         if (!str_obj) {
                             wasm_set_exception(module,
                                                "create string object failed");
@@ -3320,7 +3323,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     case WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY:
                     case WASM_OP_STRING_ENCODE_WTF8_ARRAY:
                     {
-                        uint32 start, array_len;
+                        uint32 start, array_len, count;
                         int32 bytes_written;
                         EncodingFlag flag = WTF8;
                         WASMArrayType *array_type;
@@ -3373,9 +3376,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             }
                         }
 
-                        bytes_written =
-                            wasm_string_encode(str_obj, start, array_len,
-                                               arr_start_addr, NULL, flag);
+                        count = wasm_string_measure(str_obj, flag);
+
+                        bytes_written = wasm_string_encode(
+                            str_obj, 0, count, arr_start_addr, NULL, flag);
 
                         if (bytes_written < 0) {
                             if (bytes_written == Isolated_Surrogate) {

+ 10 - 4
core/iwasm/interpreter/wasm_interp_fast.c

@@ -2679,7 +2679,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         contents = (uint32)read_uint32(frame_ip);
 
                         str_obj = wasm_string_new_const(
-                            wasm_module->string_consts[contents]);
+                            (const char *)
+                                wasm_module->string_literal_ptrs[contents],
+                            wasm_module->string_literal_lengths[contents]);
                         if (!str_obj) {
                             wasm_set_exception(module,
                                                "create string object failed");
@@ -3165,7 +3167,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         str_obj = wasm_string_slice(
                             (WASMString)wasm_stringview_iter_obj_get_value(
                                 stringview_iter_obj),
-                            cur_pos, code_points_count, STRING_VIEW_ITER);
+                            cur_pos, cur_pos + code_points_count,
+                            STRING_VIEW_ITER);
                         if (!str_obj) {
                             wasm_set_exception(module,
                                                "create string object failed");
@@ -3261,7 +3264,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     case WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY:
                     case WASM_OP_STRING_ENCODE_WTF8_ARRAY:
                     {
-                        uint32 start, array_len;
+                        uint32 start, array_len, count;
                         int32 bytes_written;
                         EncodingFlag flag = WTF8;
                         WASMArrayType *array_type;
@@ -3314,8 +3317,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             }
                         }
 
+                        count = wasm_string_measure(str_obj, flag);
+
                         bytes_written = wasm_string_encode(
-                            str_obj, 0, array_len, arr_start_addr, NULL, flag);
+                            str_obj, 0, count, arr_start_addr, NULL, flag);
+
                         if (bytes_written < 0) {
                             if (bytes_written == Isolated_Surrogate) {
                                 wasm_set_exception(

+ 31 - 9
core/iwasm/interpreter/wasm_loader.c

@@ -3739,21 +3739,24 @@ load_stringref_section(const uint8 *buf, const uint8 *buf_end,
 
     if (immediate_count > 0) {
         total_size = sizeof(char *) * (uint64)immediate_count;
-        if (!(module->string_consts =
+        if (!(module->string_literal_ptrs =
+                  loader_malloc(total_size, error_buf, error_buf_size))) {
+            goto fail;
+        }
+        module->string_literal_count = immediate_count;
+
+        total_size = sizeof(uint32) * (uint64)immediate_count;
+        if (!(module->string_literal_lengths =
                   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;
-            }
+            module->string_literal_ptrs[i] = p;
+            module->string_literal_lengths[i] = string_length;
             p += string_length;
         }
     }
@@ -5461,8 +5464,11 @@ 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);
+    if (module->string_literal_ptrs) {
+        wasm_runtime_free(module->string_literal_ptrs);
+    }
+    if (module->string_literal_lengths) {
+        wasm_runtime_free(module->string_literal_lengths);
     }
 #endif
 #endif
@@ -12175,6 +12181,10 @@ re_scan:
                     {
                         uint32 memidx;
 
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+                        func->has_memory_operations = true;
+#endif
+
                         read_leb_uint32(p, p_end, memidx);
 #if WASM_ENABLE_FAST_INTERP != 0
                         emit_uint32(loader_ctx, (uint32)memidx);
@@ -12212,6 +12222,10 @@ re_scan:
                     {
                         uint32 memidx;
 
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+                        func->has_memory_operations = true;
+#endif
+
                         read_leb_uint32(p, p_end, memidx);
 #if WASM_ENABLE_FAST_INTERP != 0
                         emit_uint32(loader_ctx, (uint32)memidx);
@@ -12262,6 +12276,10 @@ re_scan:
                     {
                         uint32 memidx;
 
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+                        func->has_memory_operations = true;
+#endif
+
                         read_leb_uint32(p, p_end, memidx);
 #if WASM_ENABLE_FAST_INTERP != 0
                         emit_uint32(loader_ctx, (uint32)memidx);
@@ -12306,6 +12324,10 @@ re_scan:
                     {
                         uint32 memidx;
 
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+                        func->has_memory_operations = true;
+#endif
+
                         read_leb_uint32(p, p_end, memidx);
 #if WASM_ENABLE_FAST_INTERP != 0
                         emit_uint32(loader_ctx, (uint32)memidx);

+ 4 - 0
core/iwasm/interpreter/wasm_runtime.h

@@ -79,6 +79,10 @@ typedef enum WASMExceptionID {
     EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ,
     EXCE_CAST_FAILURE,
     EXCE_ARRAY_IDX_OOB,
+    EXCE_FAILED_TO_CREATE_STRING,
+    EXCE_FAILED_TO_CREATE_STRINGREF,
+    EXCE_FAILED_TO_CREATE_STRINGVIEW,
+    EXCE_FAILED_TO_ENCODE_STRING,
     EXCE_ALREADY_THROWN,
     EXCE_NUM,
 } WASMExceptionID;

+ 3 - 0
wamr-compiler/CMakeLists.txt

@@ -53,6 +53,9 @@ if (WAMR_BUILD_GC_BINARYEN EQUAL 1)
   add_definitions(-DWASM_ENABLE_GC_BINARYEN=1)
 endif ()
 
+set (WAMR_BUILD_STRINGREF 1)
+set (WAMR_STRINGREF_IMPL_SOURCE "STUB")
+
 if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1)
   add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1)
 endif()