// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/wasm/wasm-objects.h" #include "src/base/iterator.h" #include "src/base/vector.h" #include "src/codegen/assembler-inl.h" #include "src/codegen/code-factory.h" #include "src/compiler/wasm-compiler.h" #include "src/debug/debug-interface.h" #include "src/logging/counters.h" #include "src/objects/debug-objects-inl.h" #include "src/objects/managed-inl.h" #include "src/objects/objects-inl.h" #include "src/objects/shared-function-info.h" #include "src/objects/struct-inl.h" #include "src/trap-handler/trap-handler.h" #include "src/utils/utils.h" #include "src/wasm/code-space-access.h" #include "src/wasm/jump-table-assembler.h" #include "src/wasm/module-compiler.h" #include "src/wasm/module-decoder.h" #include "src/wasm/module-instantiate.h" #include "src/wasm/value-type.h" #include "src/wasm/wasm-code-manager.h" #include "src/wasm/wasm-engine.h" #include "src/wasm/wasm-limits.h" #include "src/wasm/wasm-module.h" #include "src/wasm/wasm-objects-inl.h" #include "src/wasm/wasm-subtyping.h" #include "src/wasm/wasm-value.h" #define TRACE_IFT(...) \ do { \ if (false) PrintF(__VA_ARGS__); \ } while (false) namespace v8 { namespace internal { // Import a few often used types from the wasm namespace. using WasmFunction = wasm::WasmFunction; using WasmModule = wasm::WasmModule; namespace { // Manages the natively-allocated memory for a WasmInstanceObject. Since // an instance finalizer is not guaranteed to run upon isolate shutdown, // we must use a Managed to guarantee // it is freed. // Native allocations are the signature ids and targets for indirect call // targets, as well as the call targets for imported functions. class WasmInstanceNativeAllocations { public: // Helper macro to set an internal field and the corresponding field // on an instance. #define SET(instance, field, value) \ instance->set_##field((this->field##_ = value).get()); // Allocates initial native storage for a given instance. WasmInstanceNativeAllocations(Handle instance, size_t num_imported_functions, size_t num_imported_mutable_globals, size_t num_data_segments, size_t num_elem_segments) { SET(instance, imported_function_targets, std::make_unique(num_imported_functions)); SET(instance, imported_mutable_globals, std::make_unique(num_imported_mutable_globals)); SET(instance, data_segment_starts, std::make_unique(num_data_segments)); SET(instance, data_segment_sizes, std::make_unique(num_data_segments)); SET(instance, dropped_elem_segments, std::make_unique(num_elem_segments)); } uint32_t indirect_function_table_capacity() const { return indirect_function_table_capacity_; } // Resizes the indirect function table. void resize_indirect_function_table(Isolate* isolate, Handle instance, uint32_t new_capacity) { uint32_t old_capacity = indirect_function_table_capacity_; DCHECK_LT(old_capacity, new_capacity); // Grow exponentially to support repeated re-allocation. new_capacity = std::max(new_capacity, 2 * old_capacity); CHECK_GE(kMaxInt, old_capacity); CHECK_GE(kMaxInt, new_capacity); SET(instance, indirect_function_table_sig_ids, grow(indirect_function_table_sig_ids_.get(), old_capacity, new_capacity)); SET(instance, indirect_function_table_targets, grow(indirect_function_table_targets_.get(), old_capacity, new_capacity)); Handle old_refs(instance->indirect_function_table_refs(), isolate); Handle new_refs = isolate->factory()->CopyFixedArrayAndGrow( old_refs, static_cast(new_capacity - old_capacity)); instance->set_indirect_function_table_refs(*new_refs); indirect_function_table_capacity_ = new_capacity; } private: template std::unique_ptr grow(T* old_arr, size_t old_size, size_t new_size) { std::unique_ptr new_arr = std::make_unique(new_size); std::copy_n(old_arr, old_size, new_arr.get()); return new_arr; } uint32_t indirect_function_table_capacity_ = 0; std::unique_ptr indirect_function_table_sig_ids_; std::unique_ptr indirect_function_table_targets_; std::unique_ptr imported_function_targets_; std::unique_ptr imported_mutable_globals_; std::unique_ptr data_segment_starts_; std::unique_ptr data_segment_sizes_; std::unique_ptr dropped_elem_segments_; #undef SET }; size_t EstimateNativeAllocationsSize(const WasmModule* module) { size_t estimate = sizeof(WasmInstanceNativeAllocations) + (1 * kSystemPointerSize * module->num_imported_mutable_globals) + (2 * kSystemPointerSize * module->num_imported_functions) + ((kSystemPointerSize + sizeof(uint32_t) + sizeof(uint8_t)) * module->num_declared_data_segments); for (auto& table : module->tables) { estimate += 3 * kSystemPointerSize * table.initial_size; } return estimate; } WasmInstanceNativeAllocations* GetNativeAllocations( WasmInstanceObject instance) { return Managed::cast( instance.managed_native_allocations()) .raw(); } enum DispatchTableElements : int { kDispatchTableInstanceOffset, kDispatchTableIndexOffset, kDispatchTableFunctionTableOffset, // Marker: kDispatchTableNumElements }; } // namespace // static Handle WasmModuleObject::New( Isolate* isolate, std::shared_ptr native_module, Handle