summaryrefslogtreecommitdiff
path: root/src/interpreter.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/interpreter.cc')
-rw-r--r--src/interpreter.cc194
1 files changed, 68 insertions, 126 deletions
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;
}