diff options
Diffstat (limited to 'src/interpreter.cc')
-rw-r--r-- | src/interpreter.cc | 194 |
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; } |