diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-reader-interpreter.cc | 206 | ||||
-rw-r--r-- | src/interpreter.cc | 194 | ||||
-rw-r--r-- | src/interpreter.h | 111 | ||||
-rw-r--r-- | src/tools/wasm-interp.cc | 228 |
4 files changed, 334 insertions, 405 deletions
diff --git a/src/binary-reader-interpreter.cc b/src/binary-reader-interpreter.cc index 030774e7..52642b44 100644 --- a/src/binary-reader-interpreter.cc +++ b/src/binary-reader-interpreter.cc @@ -35,7 +35,7 @@ #define CHECK_LOCAL(ctx, local_index) \ do { \ uint32_t max_local_index = \ - (ctx)->current_func->defined.param_and_local_types.size; \ + (ctx)->current_func->param_and_local_types.size(); \ if ((local_index) >= max_local_index) { \ print_error((ctx), "invalid local_index: %d (max %d)", (local_index), \ max_local_index); \ @@ -70,7 +70,7 @@ struct Context { BinaryErrorHandler* error_handler; InterpreterEnvironment* env; DefinedInterpreterModule* module; - InterpreterFunc* current_func; + DefinedInterpreterFunc* current_func; TypeChecker typechecker; LabelVector label_stack; Uint32VectorVector func_fixups; @@ -129,8 +129,7 @@ static uint32_t translate_sig_index_to_env(Context* ctx, uint32_t sig_index) { static InterpreterFuncSignature* get_signature_by_env_index( Context* ctx, uint32_t sig_index) { - assert(sig_index < ctx->env->sigs.size); - return &ctx->env->sigs.data[sig_index]; + return &ctx->env->sigs[sig_index]; } static InterpreterFuncSignature* get_signature_by_module_index( @@ -153,8 +152,7 @@ static uint32_t translate_module_func_index_to_defined(Context* ctx, static InterpreterFunc* get_func_by_env_index(Context* ctx, uint32_t func_index) { - assert(func_index < ctx->env->funcs.size); - return &ctx->env->funcs.data[func_index]; + return ctx->env->funcs[func_index].get(); } static InterpreterFunc* get_func_by_module_index(Context* ctx, @@ -165,14 +163,12 @@ static InterpreterFunc* get_func_by_module_index(Context* ctx, static uint32_t translate_global_index_to_env(Context* ctx, uint32_t global_index) { - assert(global_index < ctx->global_index_mapping.size); return ctx->global_index_mapping.data[global_index]; } static InterpreterGlobal* get_global_by_env_index(Context* ctx, uint32_t global_index) { - assert(global_index < ctx->env->globals.size); - return &ctx->env->globals.data[global_index]; + return &ctx->env->globals[global_index]; } static InterpreterGlobal* get_global_by_module_index(Context* ctx, @@ -189,8 +185,7 @@ static Type get_global_type_by_module_index(Context* ctx, static Type get_local_type_by_index(InterpreterFunc* func, uint32_t local_index) { assert(!func->is_host); - assert(local_index < func->defined.param_and_local_types.size); - return func->defined.param_and_local_types.data[local_index]; + return func->as_defined()->param_and_local_types[local_index]; } static uint32_t get_istream_offset(Context* ctx) { @@ -297,7 +292,7 @@ static Result get_return_drop_keep_count(Context* ctx, return Result::Error; } - *out_drop_count += ctx->current_func->defined.param_and_local_types.size; + *out_drop_count += ctx->current_func->param_and_local_types.size(); return Result::Ok; } @@ -338,14 +333,14 @@ static Result fixup_top_label(Context* ctx) { } static Result emit_func_offset(Context* ctx, - InterpreterFunc* func, + DefinedInterpreterFunc* func, uint32_t func_index) { - if (func->defined.offset == WABT_INVALID_OFFSET) { + if (func->offset == WABT_INVALID_OFFSET) { uint32_t defined_index = translate_module_func_index_to_defined(ctx, func_index); CHECK_RESULT(append_fixup(ctx, &ctx->func_fixups, defined_index)); } - CHECK_RESULT(emit_i32(ctx, func->defined.offset)); + CHECK_RESULT(emit_i32(ctx, func->offset)); return Result::Ok; } @@ -357,9 +352,8 @@ static Result on_signature_count(uint32_t count, void* user_data) { Context* ctx = static_cast<Context*>(user_data); resize_uint32_vector(&ctx->sig_index_mapping, count); for (uint32_t i = 0; i < count; ++i) - ctx->sig_index_mapping.data[i] = ctx->env->sigs.size + i; - resize_interpreter_func_signature_vector(&ctx->env->sigs, - ctx->env->sigs.size + count); + ctx->sig_index_mapping.data[i] = ctx->env->sigs.size() + i; + ctx->env->sigs.resize(ctx->env->sigs.size() + count); return Result::Ok; } @@ -371,14 +365,10 @@ static Result on_signature(uint32_t index, void* user_data) { Context* ctx = static_cast<Context*>(user_data); InterpreterFuncSignature* sig = get_signature_by_module_index(ctx, index); - - reserve_types(&sig->param_types, param_count); - sig->param_types.size = param_count; - memcpy(sig->param_types.data, param_types, param_count * sizeof(Type)); - - reserve_types(&sig->result_types, result_count); - sig->result_types.size = result_count; - memcpy(sig->result_types.data, result_types, result_count * sizeof(Type)); + sig->param_types.insert(sig->param_types.end(), param_types, + param_types + param_count); + sig->result_types.insert(sig->result_types.end(), result_types, + result_types + result_count); return Result::Ok; } @@ -479,13 +469,11 @@ static Result append_export(Context* ctx, return Result::Error; } - InterpreterExport* export_ = append_interpreter_export(&module->exports); - export_->name = dup_string_slice(name); - export_->kind = kind; - export_->index = item_index; + module->exports.emplace_back(dup_string_slice(name), kind, item_index); + InterpreterExport* export_ = &module->exports.back(); Binding* binding = insert_binding(&module->export_bindings, &export_->name); - binding->index = module->exports.size - 1; + binding->index = module->exports.size() - 1; return Result::Ok; } @@ -509,32 +497,29 @@ static Result on_import_func(uint32_t import_index, void* user_data) { Context* ctx = static_cast<Context*>(user_data); InterpreterImport* import = &ctx->module->imports[import_index]; - assert(sig_index < ctx->env->sigs.size); import->func.sig_index = translate_sig_index_to_env(ctx, sig_index); uint32_t func_env_index; if (ctx->is_host_import) { - InterpreterFunc* func = append_interpreter_func(&ctx->env->funcs); - func->is_host = true; - func->sig_index = import->func.sig_index; - func->host.module_name = import->module_name; - func->host.field_name = import->field_name; + HostInterpreterFunc* func = new HostInterpreterFunc( + import->module_name, import->field_name, import->func.sig_index); + + ctx->env->funcs.emplace_back(func); InterpreterHostImportDelegate* host_delegate = &ctx->host_import_module->import_delegate; - InterpreterFuncSignature* sig = &ctx->env->sigs.data[func->sig_index]; + InterpreterFuncSignature* sig = &ctx->env->sigs[func->sig_index]; CHECK_RESULT(host_delegate->import_func(import, func, sig, make_print_error_callback(ctx), host_delegate->user_data)); - assert(func->host.callback); + assert(func->callback); - func_env_index = ctx->env->funcs.size - 1; + func_env_index = ctx->env->funcs.size() - 1; append_export(ctx, ctx->host_import_module, ExternalKind::Func, func_env_index, import->field_name); } else { CHECK_RESULT(check_import_kind(ctx, import, ExternalKind::Func)); - assert(ctx->import_env_index < ctx->env->funcs.size); - InterpreterFunc* func = &ctx->env->funcs.data[ctx->import_env_index]; + InterpreterFunc* func = ctx->env->funcs[ctx->import_env_index].get(); if (!func_signatures_are_equal(ctx->env, import->func.sig_index, func->sig_index)) { print_error(ctx, "import signature mismatch"); @@ -604,7 +589,8 @@ static Result on_import_memory(uint32_t import_index, InterpreterImport* import = &ctx->module->imports[import_index]; if (ctx->is_host_import) { - InterpreterMemory* memory = append_interpreter_memory(&ctx->env->memories); + ctx->env->memories.emplace_back(); + InterpreterMemory* memory = &ctx->env->memories.back(); InterpreterHostImportDelegate* host_delegate = &ctx->host_import_module->import_delegate; @@ -612,16 +598,14 @@ static Result on_import_memory(uint32_t import_index, make_print_error_callback(ctx), host_delegate->user_data)); - assert(memory->data); CHECK_RESULT(check_import_limits(ctx, page_limits, &memory->page_limits)); - ctx->module->memory_index = ctx->env->memories.size - 1; + ctx->module->memory_index = ctx->env->memories.size() - 1; append_export(ctx, ctx->host_import_module, ExternalKind::Memory, ctx->module->memory_index, import->field_name); } else { CHECK_RESULT(check_import_kind(ctx, import, ExternalKind::Memory)); - assert(ctx->import_env_index < ctx->env->memories.size); - InterpreterMemory* memory = &ctx->env->memories.data[ctx->import_env_index]; + InterpreterMemory* memory = &ctx->env->memories[ctx->import_env_index]; CHECK_RESULT(check_import_limits(ctx, page_limits, &memory->page_limits)); import->memory.limits = *page_limits; @@ -640,11 +624,10 @@ static Result on_import_global(uint32_t import_index, Context* ctx = static_cast<Context*>(user_data); InterpreterImport* import = &ctx->module->imports[import_index]; - uint32_t global_env_index = ctx->env->globals.size - 1; + uint32_t global_env_index = ctx->env->globals.size() - 1; if (ctx->is_host_import) { - InterpreterGlobal* global = append_interpreter_global(&ctx->env->globals); - global->typed_value.type = type; - global->mutable_ = mutable_; + ctx->env->globals.emplace_back(InterpreterTypedValue(type), mutable_); + InterpreterGlobal* global = &ctx->env->globals.back(); InterpreterHostImportDelegate* host_delegate = &ctx->host_import_module->import_delegate; @@ -652,7 +635,7 @@ static Result on_import_global(uint32_t import_index, make_print_error_callback(ctx), host_delegate->user_data)); - global_env_index = ctx->env->globals.size - 1; + global_env_index = ctx->env->globals.size() - 1; append_export(ctx, ctx->host_import_module, ExternalKind::Global, global_env_index, import->field_name); } else { @@ -672,9 +655,8 @@ static Result on_function_signatures_count(uint32_t count, void* user_data) { size_t old_size = ctx->func_index_mapping.size; resize_uint32_vector(&ctx->func_index_mapping, old_size + count); for (uint32_t i = 0; i < count; ++i) - ctx->func_index_mapping.data[old_size + i] = ctx->env->funcs.size + i; - resize_interpreter_func_vector(&ctx->env->funcs, - ctx->env->funcs.size + count); + ctx->func_index_mapping.data[old_size + i] = ctx->env->funcs.size() + i; + ctx->env->funcs.reserve(ctx->env->funcs.size() + count); resize_uint32_vector_vector(&ctx->func_fixups, count); return Result::Ok; } @@ -683,9 +665,9 @@ static Result on_function_signature(uint32_t index, uint32_t sig_index, void* user_data) { Context* ctx = static_cast<Context*>(user_data); - InterpreterFunc* func = get_func_by_module_index(ctx, index); - func->defined.offset = WABT_INVALID_OFFSET; - func->sig_index = translate_sig_index_to_env(ctx, sig_index); + DefinedInterpreterFunc* func = + new DefinedInterpreterFunc(translate_sig_index_to_env(ctx, sig_index)); + ctx->env->funcs.emplace_back(func); return Result::Ok; } @@ -711,11 +693,8 @@ static Result on_memory(uint32_t index, print_error(ctx, "only one memory allowed"); return Result::Error; } - InterpreterMemory* memory = append_interpreter_memory(&ctx->env->memories); - memory->page_limits = *page_limits; - memory->byte_size = page_limits->initial * WABT_PAGE_SIZE; - memory->data = new char[memory->byte_size](); - ctx->module->memory_index = ctx->env->memories.size - 1; + ctx->env->memories.emplace_back(*page_limits); + ctx->module->memory_index = ctx->env->memories.size() - 1; return Result::Ok; } @@ -724,9 +703,8 @@ static Result on_global_count(uint32_t count, void* user_data) { size_t old_size = ctx->global_index_mapping.size; resize_uint32_vector(&ctx->global_index_mapping, old_size + count); for (uint32_t i = 0; i < count; ++i) - ctx->global_index_mapping.data[old_size + i] = ctx->env->globals.size + i; - resize_interpreter_global_vector(&ctx->env->globals, - ctx->env->globals.size + count); + ctx->global_index_mapping.data[old_size + i] = ctx->env->globals.size() + i; + ctx->env->globals.resize(ctx->env->globals.size() + count); return Result::Ok; } @@ -830,7 +808,7 @@ static Result on_export(uint32_t index, case ExternalKind::Global: { item_index = translate_global_index_to_env(ctx, item_index); - InterpreterGlobal* global = &ctx->env->globals.data[item_index]; + InterpreterGlobal* global = &ctx->env->globals[item_index]; if (global->mutable_) { print_error(ctx, "mutable globals cannot be exported"); return Result::Error; @@ -847,11 +825,11 @@ static Result on_start_function(uint32_t func_index, void* user_data) { InterpreterFunc* start_func = get_func_by_env_index(ctx, start_func_index); InterpreterFuncSignature* sig = get_signature_by_env_index(ctx, start_func->sig_index); - if (sig->param_types.size != 0) { + if (sig->param_types.size() != 0) { print_error(ctx, "start function must be nullary"); return Result::Error; } - if (sig->result_types.size != 0) { + if (sig->result_types.size() != 0) { print_error(ctx, "start function must not return anything"); return Result::Error; } @@ -890,8 +868,6 @@ static Result on_elem_segment_function_index_check(uint32_t index, return Result::Error; } - table->func_indexes[ctx->table_offset++] = - translate_func_index_to_env(ctx, func_index); return Result::Ok; } @@ -912,8 +888,7 @@ static Result on_data_segment_data_check(uint32_t index, void* user_data) { Context* ctx = static_cast<Context*>(user_data); assert(ctx->module->memory_index != WABT_INVALID_INDEX); - InterpreterMemory* memory = - &ctx->env->memories.data[ctx->module->memory_index]; + InterpreterMemory* memory = &ctx->env->memories[ctx->module->memory_index]; if (ctx->init_expr_value.type != Type::I32) { print_error(ctx, "type mismatch in data segment, expected i32 but got %s", get_type_name(ctx->init_expr_value.type)); @@ -922,10 +897,11 @@ static Result on_data_segment_data_check(uint32_t index, uint32_t address = ctx->init_expr_value.value.i32; uint64_t end_address = static_cast<uint64_t>(address) + static_cast<uint64_t>(size); - if (end_address > memory->byte_size) { - print_error(ctx, "data segment is out of bounds: [%u, %" PRIu64 - ") >= max value %u", - address, end_address, memory->byte_size); + if (end_address > memory->data.size()) { + print_error(ctx, + "data segment is out of bounds: [%u, %" PRIu64 + ") >= max value %" PRIzd, + address, end_address, memory->data.size()); return Result::Error; } return Result::Ok; @@ -936,11 +912,12 @@ static Result on_data_segment_data(uint32_t index, uint32_t size, void* user_data) { Context* ctx = static_cast<Context*>(user_data); - assert(ctx->module->memory_index != WABT_INVALID_INDEX); - InterpreterMemory* memory = - &ctx->env->memories.data[ctx->module->memory_index]; - uint32_t address = ctx->init_expr_value.value.i32; - memcpy(memory->data + address, src_data, size); + if (size > 0) { + assert(ctx->module->memory_index != WABT_INVALID_INDEX); + InterpreterMemory* memory = &ctx->env->memories[ctx->module->memory_index]; + uint32_t address = ctx->init_expr_value.value.i32; + memcpy(&memory->data[address], src_data, size); + } return Result::Ok; } @@ -963,17 +940,29 @@ static void pop_label(Context* ctx) { } } +// TODO(binji): remove this when the rest of the code is using std::vector +#define INTERPRETER_TYPE_VECTOR_TO_TYPE_VECTOR(out, in) \ + TypeVector out; \ + { \ + size_t byte_size = (in).size() * sizeof((in)[0]); \ + (out).data = static_cast<decltype((out).data)>(alloca(byte_size)); \ + (out).size = (in).size(); \ + if (byte_size) { \ + memcpy((out).data, (in).data(), byte_size); \ + } \ + } + static Result begin_function_body(BinaryReaderContext* context, uint32_t index) { Context* ctx = static_cast<Context*>(context->user_data); - InterpreterFunc* func = get_func_by_module_index(ctx, index); + DefinedInterpreterFunc* func = + get_func_by_module_index(ctx, index)->as_defined(); InterpreterFuncSignature* sig = get_signature_by_env_index(ctx, func->sig_index); - func->is_host = false; - func->defined.offset = get_istream_offset(ctx); - func->defined.local_decl_count = 0; - func->defined.local_count = 0; + func->offset = get_istream_offset(ctx); + func->local_decl_count = 0; + func->local_count = 0; ctx->current_func = func; ctx->depth_fixups.size = 0; @@ -983,16 +972,14 @@ static Result begin_function_body(BinaryReaderContext* context, uint32_t defined_index = translate_module_func_index_to_defined(ctx, index); Uint32Vector* fixups = &ctx->func_fixups.data[defined_index]; for (uint32_t i = 0; i < fixups->size; ++i) - CHECK_RESULT(emit_i32_at(ctx, fixups->data[i], func->defined.offset)); + CHECK_RESULT(emit_i32_at(ctx, fixups->data[i], func->offset)); /* append param types */ - for (uint32_t i = 0; i < sig->param_types.size; ++i) { - append_type_value(&func->defined.param_and_local_types, - &sig->param_types.data[i]); - } + for (uint32_t i = 0; i < sig->param_types.size(); ++i) + func->param_and_local_types.push_back(sig->param_types[i]); - CHECK_RESULT( - typechecker_begin_function(&ctx->typechecker, &sig->result_types)); + INTERPRETER_TYPE_VECTOR_TO_TYPE_VECTOR(result_types, sig->result_types); + CHECK_RESULT(typechecker_begin_function(&ctx->typechecker, &result_types)); /* push implicit func label (equivalent to return) */ push_label(ctx, WABT_INVALID_OFFSET, WABT_INVALID_OFFSET); @@ -1014,8 +1001,7 @@ static Result end_function_body(uint32_t index, void* user_data) { static Result on_local_decl_count(uint32_t count, void* user_data) { Context* ctx = static_cast<Context*>(user_data); - InterpreterFunc* func = ctx->current_func; - func->defined.local_decl_count = count; + ctx->current_func->local_decl_count = count; return Result::Ok; } @@ -1024,17 +1010,15 @@ static Result on_local_decl(uint32_t decl_index, Type type, void* user_data) { Context* ctx = static_cast<Context*>(user_data); - InterpreterFunc* func = ctx->current_func; - func->defined.local_count += count; + ctx->current_func->local_count += count; - for (uint32_t i = 0; i < count; ++i) { - append_type_value(&func->defined.param_and_local_types, &type); - } + for (uint32_t i = 0; i < count; ++i) + ctx->current_func->param_and_local_types.push_back(type); - if (decl_index == func->defined.local_decl_count - 1) { + if (decl_index == ctx->current_func->local_decl_count - 1) { /* last local declaration, allocate space for all locals. */ CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Alloca)); - CHECK_RESULT(emit_i32(ctx, func->defined.local_count)); + CHECK_RESULT(emit_i32(ctx, ctx->current_func->local_count)); } return Result::Ok; } @@ -1191,15 +1175,17 @@ static Result on_call_expr(uint32_t func_index, void* user_data) { InterpreterFunc* func = get_func_by_module_index(ctx, func_index); InterpreterFuncSignature* sig = get_signature_by_env_index(ctx, func->sig_index); - CHECK_RESULT(typechecker_on_call(&ctx->typechecker, &sig->param_types, - &sig->result_types)); + INTERPRETER_TYPE_VECTOR_TO_TYPE_VECTOR(param_types, sig->param_types); + INTERPRETER_TYPE_VECTOR_TO_TYPE_VECTOR(result_types, sig->result_types); + CHECK_RESULT( + typechecker_on_call(&ctx->typechecker, ¶m_types, &result_types)); if (func->is_host) { CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::CallHost)); CHECK_RESULT(emit_i32(ctx, translate_func_index_to_env(ctx, func_index))); } else { CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Call)); - CHECK_RESULT(emit_func_offset(ctx, func, func_index)); + CHECK_RESULT(emit_func_offset(ctx, func->as_defined(), func_index)); } return Result::Ok; @@ -1212,8 +1198,10 @@ static Result on_call_indirect_expr(uint32_t sig_index, void* user_data) { return Result::Error; } InterpreterFuncSignature* sig = get_signature_by_module_index(ctx, sig_index); - CHECK_RESULT(typechecker_on_call_indirect( - &ctx->typechecker, &sig->param_types, &sig->result_types)); + INTERPRETER_TYPE_VECTOR_TO_TYPE_VECTOR(param_types, sig->param_types); + INTERPRETER_TYPE_VECTOR_TO_TYPE_VECTOR(result_types, sig->result_types); + CHECK_RESULT(typechecker_on_call_indirect(&ctx->typechecker, ¶m_types, + &result_types)); CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::CallIndirect)); CHECK_RESULT(emit_i32(ctx, ctx->module->table_index)); @@ -1288,7 +1276,7 @@ static Result on_set_global_expr(uint32_t global_index, void* user_data) { static uint32_t translate_local_index(Context* ctx, uint32_t local_index) { return ctx->typechecker.type_stack.size + - ctx->current_func->defined.param_and_local_types.size - local_index; + ctx->current_func->param_and_local_types.size() - local_index; } static Result on_get_local_expr(uint32_t local_index, void* user_data) { diff --git a/src/interpreter.cc b/src/interpreter.cc index cbcb7306..b20ac467 100644 --- a/src/interpreter.cc +++ b/src/interpreter.cc @@ -59,23 +59,6 @@ void init_interpreter_environment(InterpreterEnvironment* env) { init_output_buffer(&env->istream, INITIAL_ISTREAM_CAPACITY); } -static void destroy_interpreter_func_signature(InterpreterFuncSignature* sig) { - destroy_type_vector(&sig->param_types); - destroy_type_vector(&sig->result_types); -} - -static void destroy_interpreter_func(InterpreterFunc* func) { - if (!func->is_host) - destroy_type_vector(&func->defined.param_and_local_types); -} - -static void destroy_interpreter_memory(InterpreterMemory* memory) { - delete [] memory->data; -} - -InterpreterTable::InterpreterTable(const Limits& limits) - : limits(limits), func_indexes(limits.initial, WABT_INVALID_INDEX) {} - InterpreterImport::~InterpreterImport() { destroy_string_slice(&module_name); destroy_string_slice(&field_name); @@ -86,7 +69,6 @@ InterpreterModule::InterpreterModule(bool is_host) table_index(WABT_INVALID_INDEX), is_host(is_host) { WABT_ZERO_MEMORY(name); - WABT_ZERO_MEMORY(exports); WABT_ZERO_MEMORY(export_bindings); } @@ -95,12 +77,10 @@ InterpreterModule::InterpreterModule(const StringSlice& name, bool is_host) memory_index(WABT_INVALID_INDEX), table_index(WABT_INVALID_INDEX), is_host(is_host) { - WABT_ZERO_MEMORY(exports); WABT_ZERO_MEMORY(export_bindings); } InterpreterModule::~InterpreterModule() { - destroy_interpreter_export_vector(&exports); destroy_binding_hash(&export_bindings); destroy_string_slice(&name); } @@ -115,10 +95,6 @@ HostInterpreterModule::HostInterpreterModule(const StringSlice& name) : InterpreterModule(name, true) {} void destroy_interpreter_environment(InterpreterEnvironment* env) { - WABT_DESTROY_VECTOR_AND_ELEMENTS(env->sigs, interpreter_func_signature); - WABT_DESTROY_VECTOR_AND_ELEMENTS(env->funcs, interpreter_func); - WABT_DESTROY_VECTOR_AND_ELEMENTS(env->memories, interpreter_memory); - destroy_interpreter_global_vector(&env->globals); destroy_output_buffer(&env->istream); destroy_binding_hash(&env->module_bindings); destroy_binding_hash(&env->registered_module_bindings); @@ -129,25 +105,17 @@ InterpreterEnvironmentMark mark_interpreter_environment( InterpreterEnvironmentMark mark; WABT_ZERO_MEMORY(mark); mark.modules_size = env->modules.size(); - mark.sigs_size = env->sigs.size; - mark.funcs_size = env->funcs.size; - mark.memories_size = env->memories.size; + mark.sigs_size = env->sigs.size(); + mark.funcs_size = env->funcs.size(); + mark.memories_size = env->memories.size(); mark.tables_size = env->tables.size(); - mark.globals_size = env->globals.size; + mark.globals_size = env->globals.size(); mark.istream_size = env->istream.size; return mark; } void reset_interpreter_environment_to_mark(InterpreterEnvironment* env, InterpreterEnvironmentMark mark) { -#define DESTROY_PAST_MARK(destroy_name, names) \ - do { \ - assert(mark.names##_size <= env->names.size); \ - for (size_t i = mark.names##_size; i < env->names.size; ++i) \ - destroy_interpreter_##destroy_name(&env->names.data[i]); \ - env->names.size = mark.names##_size; \ - } while (0) - /* Destroy entries in the binding hash. */ for (size_t i = mark.modules_size; i < env->modules.size(); ++i) { const StringSlice* name = &env->modules[i]->name; @@ -169,14 +137,14 @@ void reset_interpreter_environment_to_mark(InterpreterEnvironment* env, env->modules.erase(env->modules.begin() + mark.modules_size, env->modules.end()); - DESTROY_PAST_MARK(func_signature, sigs); - DESTROY_PAST_MARK(func, funcs); - DESTROY_PAST_MARK(memory, memories); + env->sigs.erase(env->sigs.begin() + mark.sigs_size, env->sigs.end()); + env->funcs.erase(env->funcs.begin() + mark.funcs_size, env->funcs.end()); + env->memories.erase(env->memories.begin() + mark.memories_size, + env->memories.end()); env->tables.erase(env->tables.begin() + mark.tables_size, env->tables.end()); - env->globals.size = mark.globals_size; + env->globals.erase(env->globals.begin() + mark.globals_size, + env->globals.end()); env->istream.size = mark.istream_size; - -#undef DESTROY_PAST_MARK } HostInterpreterModule* append_host_module(InterpreterEnvironment* env, @@ -221,12 +189,7 @@ InterpreterExport* get_interpreter_export_by_name(InterpreterModule* module, int field_index = find_binding_index_by_name(&module->export_bindings, name); if (field_index < 0) return nullptr; - assert(static_cast<size_t>(field_index) < module->exports.size); - return &module->exports.data[field_index]; -} - -void destroy_interpreter_thread(InterpreterThread* thread) { - destroy_interpreter_typed_value_vector(&thread->host_args); + return &module->exports[field_index]; } /* 3 32222222 222...00 @@ -530,37 +493,34 @@ DEFINE_BITCAST(bitcast_u64_to_f64, uint64_t, double) #define POP_CALL() (*--thread->call_stack_top) -#define GET_MEMORY(var) \ - uint32_t memory_index = read_u32(&pc); \ - assert(memory_index < env->memories.size); \ - InterpreterMemory* var = &env->memories.data[memory_index] - -#define LOAD(type, mem_type) \ - do { \ - GET_MEMORY(memory); \ - uint64_t offset = static_cast<uint64_t>(POP_I32()) + read_u32(&pc); \ - MEM_TYPE_##mem_type value; \ - TRAP_IF(offset + sizeof(value) > memory->byte_size, \ - MemoryAccessOutOfBounds); \ - void* src = \ - reinterpret_cast<void*>(reinterpret_cast<intptr_t>(memory->data) + \ - static_cast<uint32_t>(offset)); \ - memcpy(&value, src, sizeof(MEM_TYPE_##mem_type)); \ - PUSH_##type(static_cast<MEM_TYPE_EXTEND_##type##_##mem_type>(value)); \ +#define GET_MEMORY(var) \ + uint32_t memory_index = read_u32(&pc); \ + InterpreterMemory* var = &env->memories[memory_index] + +#define LOAD(type, mem_type) \ + do { \ + GET_MEMORY(memory); \ + uint64_t offset = static_cast<uint64_t>(POP_I32()) + read_u32(&pc); \ + MEM_TYPE_##mem_type value; \ + TRAP_IF(offset + sizeof(value) > memory->data.size(), \ + MemoryAccessOutOfBounds); \ + void* src = static_cast<void*>(memory->data.data() + \ + static_cast<uint32_t>(offset)); \ + memcpy(&value, src, sizeof(MEM_TYPE_##mem_type)); \ + PUSH_##type(static_cast<MEM_TYPE_EXTEND_##type##_##mem_type>(value)); \ } while (0) -#define STORE(type, mem_type) \ - do { \ - GET_MEMORY(memory); \ - VALUE_TYPE_##type value = POP_##type(); \ - uint64_t offset = static_cast<uint64_t>(POP_I32()) + read_u32(&pc); \ - MEM_TYPE_##mem_type src = static_cast<MEM_TYPE_##mem_type>(value); \ - TRAP_IF(offset + sizeof(src) > memory->byte_size, \ - MemoryAccessOutOfBounds); \ - void* dst = \ - reinterpret_cast<void*>(reinterpret_cast<intptr_t>(memory->data) + \ - static_cast<uint32_t>(offset)); \ - memcpy(dst, &src, sizeof(MEM_TYPE_##mem_type)); \ +#define STORE(type, mem_type) \ + do { \ + GET_MEMORY(memory); \ + VALUE_TYPE_##type value = POP_##type(); \ + uint64_t offset = static_cast<uint64_t>(POP_I32()) + read_u32(&pc); \ + MEM_TYPE_##mem_type src = static_cast<MEM_TYPE_##mem_type>(value); \ + TRAP_IF(offset + sizeof(src) > memory->data.size(), \ + MemoryAccessOutOfBounds); \ + void* dst = static_cast<void*>(memory->data.data() + \ + static_cast<uint32_t>(offset)); \ + memcpy(dst, &src, sizeof(MEM_TYPE_##mem_type)); \ } while (0) #define BINOP(rtype, type, op) \ @@ -750,43 +710,36 @@ bool func_signatures_are_equal(InterpreterEnvironment* env, uint32_t sig_index_1) { if (sig_index_0 == sig_index_1) return true; - InterpreterFuncSignature* sig_0 = &env->sigs.data[sig_index_0]; - InterpreterFuncSignature* sig_1 = &env->sigs.data[sig_index_1]; - return type_vectors_are_equal(&sig_0->param_types, &sig_1->param_types) && - type_vectors_are_equal(&sig_0->result_types, &sig_1->result_types); + InterpreterFuncSignature* sig_0 = &env->sigs[sig_index_0]; + InterpreterFuncSignature* sig_1 = &env->sigs[sig_index_1]; + return sig_0->param_types == sig_1->param_types && + sig_0->result_types == sig_1->result_types; } -InterpreterResult call_host(InterpreterThread* thread, InterpreterFunc* func) { - assert(func->is_host); - assert(func->sig_index < thread->env->sigs.size); - InterpreterFuncSignature* sig = &thread->env->sigs.data[func->sig_index]; +InterpreterResult call_host(InterpreterThread* thread, + HostInterpreterFunc* func) { + InterpreterFuncSignature* sig = &thread->env->sigs[func->sig_index]; - uint32_t num_args = sig->param_types.size; - if (thread->host_args.size < num_args) { - resize_interpreter_typed_value_vector(&thread->host_args, num_args); - } + size_t num_params = sig->param_types.size(); + size_t num_results = sig->result_types.size(); + // + 1 is a workaround for using data() below; UBSAN doesn't like calling + // data() with an empty vector. + std::vector<InterpreterTypedValue> params(num_params + 1); + std::vector<InterpreterTypedValue> results(num_results + 1); - for (uint32_t i = num_args; i > 0; --i) { - InterpreterValue value = POP(); - InterpreterTypedValue* arg = &thread->host_args.data[i - 1]; - arg->type = sig->param_types.data[i - 1]; - arg->value = value; + for (size_t i = num_params; i > 0; --i) { + params[i - 1].value = POP(); + params[i - 1].type = sig->param_types[i - 1]; } - uint32_t num_results = sig->result_types.size; - InterpreterTypedValue* call_result_values = - static_cast<InterpreterTypedValue*>( - alloca(sizeof(InterpreterTypedValue) * num_results)); - - Result call_result = func->host.callback( - func, sig, num_args, thread->host_args.data, num_results, - call_result_values, func->host.user_data); + Result call_result = + func->callback(func, sig, num_params, params.data(), num_results, + results.data(), func->user_data); TRAP_IF(call_result != Result::Ok, HostTrapped); - for (uint32_t i = 0; i < num_results; ++i) { - TRAP_IF(call_result_values[i].type != sig->result_types.data[i], - HostResultTypeMismatch); - PUSH(call_result_values[i].value); + for (size_t i = 0; i < num_results; ++i) { + TRAP_IF(results[i].type != sig->result_types[i], HostResultTypeMismatch); + PUSH(results[i].value); } return InterpreterResult::Ok; @@ -870,15 +823,15 @@ InterpreterResult run_interpreter(InterpreterThread* thread, case InterpreterOpcode::GetGlobal: { uint32_t index = read_u32(&pc); - assert(index < env->globals.size); - PUSH(env->globals.data[index].typed_value.value); + assert(index < env->globals.size()); + PUSH(env->globals[index].typed_value.value); break; } case InterpreterOpcode::SetGlobal: { uint32_t index = read_u32(&pc); - assert(index < env->globals.size); - env->globals.data[index].typed_value.value = POP(); + assert(index < env->globals.size()); + env->globals[index].typed_value.value = POP(); break; } @@ -907,31 +860,27 @@ InterpreterResult run_interpreter(InterpreterThread* thread, case InterpreterOpcode::CallIndirect: { uint32_t table_index = read_u32(&pc); - assert(table_index < env->tables.size()); InterpreterTable* table = &env->tables[table_index]; uint32_t sig_index = read_u32(&pc); - assert(sig_index < env->sigs.size); VALUE_TYPE_I32 entry_index = POP_I32(); TRAP_IF(entry_index >= table->func_indexes.size(), UndefinedTableIndex); uint32_t func_index = table->func_indexes[entry_index]; TRAP_IF(func_index == WABT_INVALID_INDEX, UninitializedTableElement); - InterpreterFunc* func = &env->funcs.data[func_index]; + InterpreterFunc* func = env->funcs[func_index].get(); TRAP_UNLESS(func_signatures_are_equal(env, func->sig_index, sig_index), IndirectCallSignatureMismatch); if (func->is_host) { - call_host(thread, func); + call_host(thread, func->as_host()); } else { PUSH_CALL(); - GOTO(func->defined.offset); + GOTO(func->as_defined()->offset); } break; } case InterpreterOpcode::CallHost: { uint32_t func_index = read_u32(&pc); - assert(func_index < env->funcs.size); - InterpreterFunc* func = &env->funcs.data[func_index]; - call_host(thread, func); + call_host(thread, env->funcs[func_index]->as_host()); break; } @@ -1036,7 +985,6 @@ InterpreterResult run_interpreter(InterpreterThread* thread, case InterpreterOpcode::GrowMemory: { GET_MEMORY(memory); uint32_t old_page_size = memory->page_limits.initial; - uint32_t old_byte_size = memory->byte_size; VALUE_TYPE_I32 grow_pages = POP_I32(); uint32_t new_page_size = old_page_size + grow_pages; uint32_t max_page_size = memory->page_limits.has_max @@ -1045,14 +993,8 @@ InterpreterResult run_interpreter(InterpreterThread* thread, PUSH_NEG_1_AND_BREAK_IF(new_page_size > max_page_size); PUSH_NEG_1_AND_BREAK_IF( static_cast<uint64_t>(new_page_size) * WABT_PAGE_SIZE > UINT32_MAX); - uint32_t new_byte_size = new_page_size * WABT_PAGE_SIZE; - char* new_data = new char [new_byte_size]; - memcpy(new_data, memory->data, old_byte_size); - memset(new_data + old_byte_size, 0, new_byte_size - old_byte_size); - delete [] memory->data; - memory->data = new_data; + memory->data.resize(new_page_size * WABT_PAGE_SIZE); memory->page_limits.initial = new_page_size; - memory->byte_size = new_byte_size; PUSH_I32(old_page_size); break; } diff --git a/src/interpreter.h b/src/interpreter.h index b36c4799..c30ce9fa 100644 --- a/src/interpreter.h +++ b/src/interpreter.h @@ -101,26 +101,29 @@ enum class InterpreterOpcode { }; static const int kInterpreterOpcodeCount = WABT_ENUM_COUNT(InterpreterOpcode); -/* TODO(binji): identical to FuncSignature. Share? */ struct InterpreterFuncSignature { - TypeVector param_types; - TypeVector result_types; + std::vector<Type> param_types; + std::vector<Type> result_types; }; -WABT_DEFINE_VECTOR(interpreter_func_signature, InterpreterFuncSignature); struct InterpreterTable { - explicit InterpreterTable(const Limits&); + explicit InterpreterTable(const Limits& limits) + : limits(limits), func_indexes(limits.initial, WABT_INVALID_INDEX) {} Limits limits; std::vector<uint32_t> func_indexes; }; struct InterpreterMemory { - char* data; + InterpreterMemory() { + WABT_ZERO_MEMORY(page_limits); + } + explicit InterpreterMemory(const Limits& limits) + : page_limits(limits), data(limits.initial * WABT_PAGE_SIZE) {} + Limits page_limits; - uint32_t byte_size; /* Cached from page_limits. */ + std::vector<char> data; }; -WABT_DEFINE_VECTOR(interpreter_memory, InterpreterMemory); union InterpreterValue { uint32_t i32; @@ -130,17 +133,24 @@ union InterpreterValue { }; struct InterpreterTypedValue { + InterpreterTypedValue() {} + explicit InterpreterTypedValue(Type type): type(type) {} + InterpreterTypedValue(Type type, const InterpreterValue& value) + : type(type), value(value) {} + Type type; InterpreterValue value; }; -WABT_DEFINE_VECTOR(interpreter_typed_value, InterpreterTypedValue); struct InterpreterGlobal { + InterpreterGlobal() : mutable_(false), import_index(WABT_INVALID_INDEX) {} + InterpreterGlobal(const InterpreterTypedValue& typed_value, bool mutable_) + : typed_value(typed_value), mutable_(mutable_) {} + InterpreterTypedValue typed_value; bool mutable_; uint32_t import_index; /* or INVALID_INDEX if not imported */ }; -WABT_DEFINE_VECTOR(interpreter_global, InterpreterGlobal); struct InterpreterImport { ~InterpreterImport(); @@ -165,7 +175,7 @@ struct InterpreterImport { struct InterpreterFunc; typedef Result (*InterpreterHostFuncCallback)( - const struct InterpreterFunc* func, + const struct HostInterpreterFunc* func, const InterpreterFuncSignature* sig, uint32_t num_args, InterpreterTypedValue* args, @@ -174,31 +184,62 @@ typedef Result (*InterpreterHostFuncCallback)( void* user_data); struct InterpreterFunc { + InterpreterFunc(uint32_t sig_index, bool is_host) + : sig_index(sig_index), is_host(is_host) {} + virtual ~InterpreterFunc() {} + + inline struct DefinedInterpreterFunc* as_defined(); + inline struct HostInterpreterFunc* as_host(); + uint32_t sig_index; bool is_host; - union { - struct { - uint32_t offset; - uint32_t local_decl_count; - uint32_t local_count; - TypeVector param_and_local_types; - } defined; - struct { - StringSlice module_name; - StringSlice field_name; - InterpreterHostFuncCallback callback; - void* user_data; - } host; - }; }; -WABT_DEFINE_VECTOR(interpreter_func, InterpreterFunc); + +struct DefinedInterpreterFunc : InterpreterFunc { + DefinedInterpreterFunc(uint32_t sig_index) + : InterpreterFunc(sig_index, false), + offset(WABT_INVALID_INDEX), + local_decl_count(0), + local_count(0) {} + + uint32_t offset; + uint32_t local_decl_count; + uint32_t local_count; + std::vector<Type> param_and_local_types; +}; + +struct HostInterpreterFunc : InterpreterFunc { + HostInterpreterFunc(const StringSlice& module_name, + const StringSlice& field_name, + uint32_t sig_index) + : InterpreterFunc(sig_index, true), + module_name(module_name), + field_name(field_name) {} + + StringSlice module_name; + StringSlice field_name; + InterpreterHostFuncCallback callback; + void* user_data; +}; + +DefinedInterpreterFunc* InterpreterFunc::as_defined() { + assert(!is_host); + return static_cast<DefinedInterpreterFunc*>(this); +} + +HostInterpreterFunc* InterpreterFunc::as_host() { + assert(is_host); + return static_cast<HostInterpreterFunc*>(this); +} struct InterpreterExport { + InterpreterExport(const StringSlice& name, ExternalKind kind, uint32_t index) + : name(name), kind(kind), index(index) {} + StringSlice name; /* Owned by the export_bindings hash */ ExternalKind kind; uint32_t index; }; -WABT_DEFINE_VECTOR(interpreter_export, InterpreterExport); struct PrintErrorCallback { void* user_data; @@ -235,7 +276,7 @@ struct InterpreterModule { inline struct HostInterpreterModule* as_host(); StringSlice name; - InterpreterExportVector exports; + std::vector<InterpreterExport> exports; BindingHash export_bindings; uint32_t memory_index; /* INVALID_INDEX if not defined */ uint32_t table_index; /* INVALID_INDEX if not defined */ @@ -280,11 +321,11 @@ struct InterpreterEnvironmentMark { struct InterpreterEnvironment { std::vector<std::unique_ptr<InterpreterModule>> modules; - InterpreterFuncSignatureVector sigs; - InterpreterFuncVector funcs; - InterpreterMemoryVector memories; + std::vector<InterpreterFuncSignature> sigs; + std::vector<std::unique_ptr<InterpreterFunc>> funcs; + std::vector<InterpreterMemory> memories; std::vector<InterpreterTable> tables; - InterpreterGlobalVector globals; + std::vector<InterpreterGlobal> globals; OutputBuffer istream; BindingHash module_bindings; BindingHash registered_module_bindings; @@ -299,9 +340,6 @@ struct InterpreterThread { uint32_t* call_stack_top; uint32_t* call_stack_end; uint32_t pc; - - /* a temporary buffer that is for passing args to host functions */ - InterpreterTypedValueVector host_args; }; #define WABT_INTERPRETER_THREAD_OPTIONS_DEFAULT \ @@ -333,7 +371,8 @@ void init_interpreter_thread(InterpreterEnvironment* env, InterpreterResult push_thread_value(InterpreterThread* thread, InterpreterValue value); void destroy_interpreter_thread(InterpreterThread* thread); -InterpreterResult call_host(InterpreterThread* thread, InterpreterFunc* func); +InterpreterResult call_host(InterpreterThread* thread, + HostInterpreterFunc* func); InterpreterResult run_interpreter(InterpreterThread* thread, uint32_t num_instructions, uint32_t* call_stack_return_top); diff --git a/src/tools/wasm-interp.cc b/src/tools/wasm-interp.cc index edde4a50..dae791fc 100644 --- a/src/tools/wasm-interp.cc +++ b/src/tools/wasm-interp.cc @@ -234,20 +234,15 @@ static void print_typed_value(const InterpreterTypedValue* tv) { printf("%s", buffer); } -static void print_typed_values(const InterpreterTypedValue* values, - size_t num_values) { - for (size_t i = 0; i < num_values; ++i) { +static void print_typed_value_vector( + const std::vector<InterpreterTypedValue>& values) { + for (size_t i = 0; i < values.size(); ++i) { print_typed_value(&values[i]); - if (i != num_values - 1) + if (i != values.size() - 1) printf(", "); } } -static void print_typed_value_vector( - const InterpreterTypedValueVector* values) { - print_typed_values(&values->data[0], values->size); -} - static void print_interpreter_result(const char* desc, InterpreterResult iresult) { printf("%s: %s\n", desc, s_trap_strings[static_cast<size_t>(iresult)]); @@ -255,8 +250,8 @@ static void print_interpreter_result(const char* desc, static void print_call(StringSlice module_name, StringSlice func_name, - const InterpreterTypedValueVector* args, - const InterpreterTypedValueVector* results, + const std::vector<InterpreterTypedValue>& args, + const std::vector<InterpreterTypedValue>& results, InterpreterResult iresult) { if (module_name.length) printf(PRIstringslice ".", WABT_PRINTF_STRING_SLICE_ARG(module_name)); @@ -264,7 +259,7 @@ static void print_call(StringSlice module_name, print_typed_value_vector(args); printf(") =>"); if (iresult == InterpreterResult::Ok) { - if (results->size > 0) { + if (results.size() > 0) { printf(" "); print_typed_value_vector(results); } @@ -291,17 +286,18 @@ static InterpreterResult run_defined_function(InterpreterThread* thread, return InterpreterResult::Ok; } -static InterpreterResult push_args(InterpreterThread* thread, - const InterpreterFuncSignature* sig, - const InterpreterTypedValueVector* args) { - if (sig->param_types.size != args->size) +static InterpreterResult push_args( + InterpreterThread* thread, + const InterpreterFuncSignature* sig, + const std::vector<InterpreterTypedValue>& args) { + if (sig->param_types.size() != args.size()) return InterpreterResult::ArgumentTypeMismatch; - for (size_t i = 0; i < sig->param_types.size; ++i) { - if (sig->param_types.data[i] != args->data[i].type) + for (size_t i = 0; i < sig->param_types.size(); ++i) { + if (sig->param_types[i] != args[i].type) return InterpreterResult::ArgumentTypeMismatch; - InterpreterResult iresult = push_thread_value(thread, args->data[i].value); + InterpreterResult iresult = push_thread_value(thread, args[i].value); if (iresult != InterpreterResult::Ok) { thread->value_stack_top = thread->value_stack.data(); return iresult; @@ -312,39 +308,34 @@ static InterpreterResult push_args(InterpreterThread* thread, static void copy_results(InterpreterThread* thread, const InterpreterFuncSignature* sig, - InterpreterTypedValueVector* out_results) { - size_t expected_results = sig->result_types.size; + std::vector<InterpreterTypedValue>* out_results) { + size_t expected_results = sig->result_types.size(); size_t value_stack_depth = thread->value_stack_top - thread->value_stack.data(); WABT_USE(value_stack_depth); assert(expected_results == value_stack_depth); - /* Don't clear out the vector, in case it is being reused. Just reset the - * size to zero. */ - out_results->size = 0; - resize_interpreter_typed_value_vector(out_results, expected_results); - for (size_t i = 0; i < expected_results; ++i) { - out_results->data[i].type = sig->result_types.data[i]; - out_results->data[i].value = thread->value_stack[i]; - } + out_results->clear(); + for (size_t i = 0; i < expected_results; ++i) + out_results->emplace_back(sig->result_types[i], thread->value_stack[i]); } static InterpreterResult run_function( InterpreterThread* thread, uint32_t func_index, - const InterpreterTypedValueVector* args, - InterpreterTypedValueVector* out_results) { - assert(func_index < thread->env->funcs.size); - InterpreterFunc* func = &thread->env->funcs.data[func_index]; + const std::vector<InterpreterTypedValue>& args, + std::vector<InterpreterTypedValue>* out_results) { + assert(func_index < thread->env->funcs.size()); + InterpreterFunc* func = thread->env->funcs[func_index].get(); uint32_t sig_index = func->sig_index; - assert(sig_index < thread->env->sigs.size); - InterpreterFuncSignature* sig = &thread->env->sigs.data[sig_index]; + assert(sig_index < thread->env->sigs.size()); + InterpreterFuncSignature* sig = &thread->env->sigs[sig_index]; InterpreterResult iresult = push_args(thread, sig, args); if (iresult == InterpreterResult::Ok) { iresult = func->is_host - ? call_host(thread, func) - : run_defined_function(thread, func->defined.offset); + ? call_host(thread, func->as_host()) + : run_defined_function(thread, func->as_defined()->offset); if (iresult == InterpreterResult::Ok) copy_results(thread, sig, out_results); } @@ -362,21 +353,19 @@ static InterpreterResult run_start_function(InterpreterThread* thread, if (s_trace) printf(">>> running start function:\n"); - InterpreterTypedValueVector args; - InterpreterTypedValueVector results; - WABT_ZERO_MEMORY(args); - WABT_ZERO_MEMORY(results); - + std::vector<InterpreterTypedValue> args; + std::vector<InterpreterTypedValue> results; InterpreterResult iresult = - run_function(thread, module->start_func_index, &args, &results); - assert(results.size == 0); + run_function(thread, module->start_func_index, args, &results); + assert(results.size() == 0); return iresult; } -static InterpreterResult run_export(InterpreterThread* thread, - const InterpreterExport* export_, - const InterpreterTypedValueVector* args, - InterpreterTypedValueVector* out_results) { +static InterpreterResult run_export( + InterpreterThread* thread, + const InterpreterExport* export_, + const std::vector<InterpreterTypedValue>& args, + std::vector<InterpreterTypedValue>* out_results) { if (s_trace) { printf(">>> running export \"" PRIstringslice "\":\n", WABT_PRINTF_STRING_SLICE_ARG(export_->name)); @@ -390,8 +379,8 @@ static InterpreterResult run_export_by_name( InterpreterThread* thread, InterpreterModule* module, const StringSlice* name, - const InterpreterTypedValueVector* args, - InterpreterTypedValueVector* out_results, + const std::vector<InterpreterTypedValue>& args, + std::vector<InterpreterTypedValue>* out_results, RunVerbosity verbose) { InterpreterExport* export_ = get_interpreter_export_by_name(module, name); if (!export_) @@ -405,39 +394,31 @@ static InterpreterResult get_global_export_by_name( InterpreterThread* thread, InterpreterModule* module, const StringSlice* name, - InterpreterTypedValueVector* out_results) { + std::vector<InterpreterTypedValue>* out_results) { InterpreterExport* export_ = get_interpreter_export_by_name(module, name); if (!export_) return InterpreterResult::UnknownExport; if (export_->kind != ExternalKind::Global) return InterpreterResult::ExportKindMismatch; - assert(export_->index < thread->env->globals.size); - InterpreterGlobal* global = &thread->env->globals.data[export_->index]; - - /* Don't clear out the vector, in case it is being reused. Just reset the - * size to zero. */ - out_results->size = 0; - append_interpreter_typed_value_value(out_results, &global->typed_value); + InterpreterGlobal* global = &thread->env->globals[export_->index]; + out_results->clear(); + out_results->push_back(global->typed_value); return InterpreterResult::Ok; } static void run_all_exports(InterpreterModule* module, InterpreterThread* thread, RunVerbosity verbose) { - InterpreterTypedValueVector args; - InterpreterTypedValueVector results; - WABT_ZERO_MEMORY(args); - WABT_ZERO_MEMORY(results); - for (uint32_t i = 0; i < module->exports.size; ++i) { - InterpreterExport* export_ = &module->exports.data[i]; - InterpreterResult iresult = run_export(thread, export_, &args, &results); + std::vector<InterpreterTypedValue> args; + std::vector<InterpreterTypedValue> results; + for (uint32_t i = 0; i < module->exports.size(); ++i) { + InterpreterExport* export_ = &module->exports[i]; + InterpreterResult iresult = run_export(thread, export_, args, &results); if (verbose == RunVerbosity::Verbose) { - print_call(empty_string_slice(), export_->name, &args, &results, iresult); + print_call(empty_string_slice(), export_->name, args, results, iresult); } } - destroy_interpreter_typed_value_vector(&args); - destroy_interpreter_typed_value_vector(&results); } static Result read_module(const char* module_filename, @@ -464,7 +445,7 @@ static Result read_module(const char* module_filename, return result; } -static Result default_host_callback(const InterpreterFunc* func, +static Result default_host_callback(const HostInterpreterFunc* func, const InterpreterFuncSignature* sig, uint32_t num_args, InterpreterTypedValue* args, @@ -473,19 +454,15 @@ static Result default_host_callback(const InterpreterFunc* func, void* user_data) { memset(out_results, 0, sizeof(InterpreterTypedValue) * num_results); for (uint32_t i = 0; i < num_results; ++i) - out_results[i].type = sig->result_types.data[i]; + out_results[i].type = sig->result_types[i]; - InterpreterTypedValueVector vec_args; - vec_args.size = num_args; - vec_args.data = args; - - InterpreterTypedValueVector vec_results; - vec_results.size = num_results; - vec_results.data = out_results; + std::vector<InterpreterTypedValue> vec_args(args, args + num_args); + std::vector<InterpreterTypedValue> vec_results(out_results, + out_results + num_results); printf("called host "); - print_call(func->host.module_name, func->host.field_name, &vec_args, - &vec_results, InterpreterResult::Ok); + print_call(func->module_name, func->field_name, vec_args, vec_results, + InterpreterResult::Ok); return Result::Ok; } @@ -506,7 +483,7 @@ static Result spectest_import_func(InterpreterImport* import, PrintErrorCallback callback, void* user_data) { if (string_slice_eq_cstr(&import->field_name, "print")) { - func->host.callback = default_host_callback; + func->as_host()->callback = default_host_callback; return Result::Ok; } else { print_error(callback, "unknown host function import " PRIimport, @@ -539,8 +516,7 @@ static Result spectest_import_memory(InterpreterImport* import, memory->page_limits.has_max = true; memory->page_limits.initial = 1; memory->page_limits.max = 2; - memory->byte_size = memory->page_limits.initial * WABT_MAX_PAGES; - memory->data = new char[memory->byte_size](); + memory->data.resize(memory->page_limits.initial * WABT_MAX_PAGES); return Result::Ok; } else { print_error(callback, "unknown host memory import " PRIimport, @@ -617,7 +593,6 @@ static Result read_and_run_module(const char* module_filename) { print_interpreter_result("error running start function", iresult); } } - destroy_interpreter_thread(&thread); destroy_interpreter_environment(&env); return result; } @@ -655,7 +630,7 @@ struct Action { ActionType type; StringSlice module_name; StringSlice field_name; - InterpreterTypedValueVector args; + std::vector<InterpreterTypedValue> args; }; #define CHECK_RESULT(x) \ @@ -950,9 +925,10 @@ static Result parse_const(Context* ctx, InterpreterTypedValue* out_value) { } } -static Result parse_const_vector(Context* ctx, - InterpreterTypedValueVector* out_values) { - WABT_ZERO_MEMORY(*out_values); +static Result parse_const_vector( + Context* ctx, + std::vector<InterpreterTypedValue>* out_values) { + out_values->clear(); EXPECT("["); bool first = true; while (!match(ctx, "]")) { @@ -960,7 +936,7 @@ static Result parse_const_vector(Context* ctx, EXPECT(","); InterpreterTypedValue value; CHECK_RESULT(parse_const(ctx, &value)); - append_interpreter_typed_value_value(out_values, &value); + out_values->push_back(value); first = false; } return Result::Ok; @@ -1050,9 +1026,9 @@ static Result on_module_command(Context* ctx, static Result run_action(Context* ctx, Action* action, InterpreterResult* out_iresult, - InterpreterTypedValueVector* out_results, + std::vector<InterpreterTypedValue>* out_results, RunVerbosity verbose) { - WABT_ZERO_MEMORY(*out_results); + out_results->clear(); int module_index; if (!string_slice_is_empty(&action->module_name)) { @@ -1069,10 +1045,10 @@ static Result run_action(Context* ctx, case ActionType::Invoke: *out_iresult = run_export_by_name(&ctx->thread, module, &action->field_name, - &action->args, out_results, verbose); + action->args, out_results, verbose); if (verbose == RunVerbosity::Verbose) { - print_call(empty_string_slice(), action->field_name, &action->args, - out_results, *out_iresult); + print_call(empty_string_slice(), action->field_name, action->args, + *out_results, *out_iresult); } return Result::Ok; @@ -1090,7 +1066,7 @@ static Result run_action(Context* ctx, } static Result on_action_command(Context* ctx, Action* action) { - InterpreterTypedValueVector results; + std::vector<InterpreterTypedValue> results; InterpreterResult iresult; ctx->total++; @@ -1106,7 +1082,6 @@ static Result on_action_command(Context* ctx, Action* action) { } } - destroy_interpreter_typed_value_vector(&results); return result; } @@ -1300,10 +1275,11 @@ static bool typed_values_are_equal(const InterpreterTypedValue* tv1, } } -static Result on_assert_return_command(Context* ctx, - Action* action, - InterpreterTypedValueVector* expected) { - InterpreterTypedValueVector results; +static Result on_assert_return_command( + Context* ctx, + Action* action, + const std::vector<InterpreterTypedValue>& expected) { + std::vector<InterpreterTypedValue> results; InterpreterResult iresult; ctx->total++; @@ -1312,10 +1288,10 @@ static Result on_assert_return_command(Context* ctx, if (WABT_SUCCEEDED(result)) { if (iresult == InterpreterResult::Ok) { - if (results.size == expected->size) { - for (size_t i = 0; i < results.size; ++i) { - const InterpreterTypedValue* expected_tv = &expected->data[i]; - const InterpreterTypedValue* actual_tv = &results.data[i]; + if (results.size() == expected.size()) { + for (size_t i = 0; i < results.size(); ++i) { + const InterpreterTypedValue* expected_tv = &expected[i]; + const InterpreterTypedValue* actual_tv = &results[i]; if (!typed_values_are_equal(expected_tv, actual_tv)) { char expected_str[MAX_TYPED_VALUE_CHARS]; char actual_str[MAX_TYPED_VALUE_CHARS]; @@ -1331,7 +1307,7 @@ static Result on_assert_return_command(Context* ctx, print_command_error( ctx, "result length mismatch in assert_return: expected %" PRIzd ", got %" PRIzd, - expected->size, results.size); + expected.size(), results.size()); result = Result::Error; } } else { @@ -1344,12 +1320,11 @@ static Result on_assert_return_command(Context* ctx, if (WABT_SUCCEEDED(result)) ctx->passed++; - destroy_interpreter_typed_value_vector(&results); return result; } static Result on_assert_return_nan_command(Context* ctx, Action* action) { - InterpreterTypedValueVector results; + std::vector<InterpreterTypedValue> results; InterpreterResult iresult; ctx->total++; @@ -1357,18 +1332,18 @@ static Result on_assert_return_nan_command(Context* ctx, Action* action) { run_action(ctx, action, &iresult, &results, RunVerbosity::Quiet); if (WABT_SUCCEEDED(result)) { if (iresult == InterpreterResult::Ok) { - if (results.size != 1) { + if (results.size() != 1) { print_command_error(ctx, "expected one result, got %" PRIzd, - results.size); + results.size()); result = Result::Error; } - const InterpreterTypedValue* actual = &results.data[0]; - switch (actual->type) { + const InterpreterTypedValue& actual = results[0]; + switch (actual.type) { case Type::F32: - if (!is_nan_f32(actual->value.f32_bits)) { + if (!is_nan_f32(actual.value.f32_bits)) { char actual_str[MAX_TYPED_VALUE_CHARS]; - sprint_typed_value(actual_str, sizeof(actual_str), actual); + sprint_typed_value(actual_str, sizeof(actual_str), &actual); print_command_error(ctx, "expected result to be nan, got %s", actual_str); result = Result::Error; @@ -1376,9 +1351,9 @@ static Result on_assert_return_nan_command(Context* ctx, Action* action) { break; case Type::F64: - if (!is_nan_f64(actual->value.f64_bits)) { + if (!is_nan_f64(actual.value.f64_bits)) { char actual_str[MAX_TYPED_VALUE_CHARS]; - sprint_typed_value(actual_str, sizeof(actual_str), actual); + sprint_typed_value(actual_str, sizeof(actual_str), &actual); print_command_error(ctx, "expected result to be nan, got %s", actual_str); result = Result::Error; @@ -1388,7 +1363,7 @@ static Result on_assert_return_nan_command(Context* ctx, Action* action) { default: print_command_error(ctx, "expected result type to be f32 or f64, got %s", - get_type_name(actual->type)); + get_type_name(actual.type)); result = Result::Error; break; } @@ -1402,14 +1377,13 @@ static Result on_assert_return_nan_command(Context* ctx, Action* action) { if (WABT_SUCCEEDED(result)) ctx->passed++; - destroy_interpreter_typed_value_vector(&results); return Result::Ok; } static Result on_assert_trap_command(Context* ctx, Action* action, StringSlice text) { - InterpreterTypedValueVector results; + std::vector<InterpreterTypedValue> results; InterpreterResult iresult; ctx->total++; @@ -1425,12 +1399,11 @@ static Result on_assert_trap_command(Context* ctx, } } - destroy_interpreter_typed_value_vector(&results); return result; } static Result on_assert_exhaustion_command(Context* ctx, Action* action) { - InterpreterTypedValueVector results; + std::vector<InterpreterTypedValue> results; InterpreterResult iresult; ctx->total++; @@ -1446,14 +1419,9 @@ static Result on_assert_exhaustion_command(Context* ctx, Action* action) { } } - destroy_interpreter_typed_value_vector(&results); return result; } -static void destroy_action(Action* action) { - destroy_interpreter_typed_value_vector(&action->args); -} - static Result parse_command(Context* ctx) { EXPECT("{"); EXPECT_KEY("type"); @@ -1478,7 +1446,6 @@ static Result parse_command(Context* ctx) { EXPECT(","); CHECK_RESULT(parse_action(ctx, &action)); on_action_command(ctx, &action); - destroy_action(&action); } else if (match(ctx, "\"register\"")) { StringSlice as; StringSlice name; @@ -1542,9 +1509,8 @@ static Result parse_command(Context* ctx) { on_assert_uninstantiable_command(ctx, filename, text); } else if (match(ctx, "\"assert_return\"")) { Action action; - InterpreterTypedValueVector expected; + std::vector<InterpreterTypedValue> expected; WABT_ZERO_MEMORY(action); - WABT_ZERO_MEMORY(expected); EXPECT(","); CHECK_RESULT(parse_line(ctx)); @@ -1553,9 +1519,7 @@ static Result parse_command(Context* ctx) { EXPECT(","); EXPECT_KEY("expected"); CHECK_RESULT(parse_const_vector(ctx, &expected)); - on_assert_return_command(ctx, &action, &expected); - destroy_interpreter_typed_value_vector(&expected); - destroy_action(&action); + on_assert_return_command(ctx, &action, expected); } else if (match(ctx, "\"assert_return_nan\"")) { Action action; TypeVector expected; @@ -1571,7 +1535,6 @@ static Result parse_command(Context* ctx) { CHECK_RESULT(parse_type_vector(ctx, &expected)); on_assert_return_nan_command(ctx, &action); destroy_type_vector(&expected); - destroy_action(&action); } else if (match(ctx, "\"assert_trap\"")) { Action action; StringSlice text; @@ -1585,7 +1548,6 @@ static Result parse_command(Context* ctx) { EXPECT(","); PARSE_KEY_STRING_VALUE("text", &text); on_assert_trap_command(ctx, &action, text); - destroy_action(&action); } else if (match(ctx, "\"assert_exhaustion\"")) { Action action; StringSlice text; @@ -1597,7 +1559,6 @@ static Result parse_command(Context* ctx) { EXPECT(","); CHECK_RESULT(parse_action(ctx, &action)); on_assert_exhaustion_command(ctx, &action); - destroy_action(&action); } else { print_command_error(ctx, "unknown command type"); return Result::Error; @@ -1624,7 +1585,6 @@ static Result parse_commands(Context* ctx) { } static void destroy_context(Context* ctx) { - destroy_interpreter_thread(&ctx->thread); destroy_interpreter_environment(&ctx->env); delete[] ctx->json_data; } |