summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader-interpreter.cc206
-rw-r--r--src/interpreter.cc194
-rw-r--r--src/interpreter.h111
-rw-r--r--src/tools/wasm-interp.cc228
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, &param_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, &param_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;
}