Showing the changes to src/vm/module_ref.cpp (1 of 40 files). Show all
Unified · Split
| @@ -0,0 +1,128 @@ | ||
| 1 | +// | |
| 2 | +// Dis VM | |
| 3 | +// File: module_ref.cpp | |
| 4 | +// Author: arr | |
| 5 | +// | |
| 6 | + | |
| 7 | +#include <runtime.h> | |
| 8 | +#include <exceptions.h> | |
| 9 | +#include <vm_memory.h> | |
| 10 | +#include <utils.h> | |
| 11 | +#include <debug.h> | |
| 12 | + | |
| 13 | +using namespace disvm; | |
| 14 | +using namespace disvm::runtime; | |
| 15 | + | |
| 16 | +namespace | |
| 17 | +{ | |
| 18 | + std::unique_ptr<vm_array_t> resolve_imports(const export_section_t &exports, const import_vm_module_t &imports) | |
| 19 | + { | |
| 20 | + static auto function_ref_type_desc = type_descriptor_t::create(sizeof(vm_module_function_ref_t), std::vector<byte_t>{}); | |
| 21 | + auto refs = std::make_unique<vm_array_t>(function_ref_type_desc, imports.functions.size()); | |
| 22 | + | |
| 23 | + for (auto index = std::size_t{ 0 }; index < imports.functions.size(); ++index) | |
| 24 | + { | |
| 25 | + const auto &import = imports.functions[index]; | |
| 26 | + | |
| 27 | + const auto exports_with_sig = exports.equal_range(import.sig); | |
| 28 | + if (exports_with_sig.first == exports.cend() && exports_with_sig.second == exports.cend()) | |
| 29 | + throw vm_user_exception{ "Module does not export a function with expected signature" }; | |
| 30 | + | |
| 31 | + auto export_match = exports_with_sig.first; | |
| 32 | + while (export_match != exports_with_sig.second) | |
| 33 | + { | |
| 34 | + // Look for the matching function name in those with matching signature | |
| 35 | + if (0 == vm_string_t::compare(export_match->second.name.get(), import.name.get())) | |
| 36 | + break; | |
| 37 | + | |
| 38 | + ++export_match; | |
| 39 | + } | |
| 40 | + | |
| 41 | + if (export_match == exports_with_sig.second) | |
| 42 | + throw vm_user_exception{ "Type check failure for exported function" }; | |
| 43 | + | |
| 44 | + const auto &export_entry = export_match->second; | |
| 45 | + | |
| 46 | + auto &ref = refs->at<vm_module_function_ref_t>(index); | |
| 47 | + ref.entry_pc = export_entry.pc; | |
| 48 | + ref.frame_type = export_entry.frame_type; | |
| 49 | + | |
| 50 | + if (debug::is_component_tracing_enabled<debug::component_trace_t::module>()) | |
| 51 | + { | |
| 52 | + debug::log_msg( | |
| 53 | + debug::component_trace_t::module, | |
| 54 | + debug::log_level_t::debug, | |
| 55 | + "export: %d %#08x >>%s<<\n", | |
| 56 | + index, | |
| 57 | + export_entry.sig, | |
| 58 | + export_entry.name->str()); | |
| 59 | + } | |
| 60 | + } | |
| 61 | + | |
| 62 | + return refs; | |
| 63 | + } | |
| 64 | +} | |
| 65 | + | |
| 66 | +std::shared_ptr<const type_descriptor_t> vm_module_ref_t::type_desc() | |
| 67 | +{ | |
| 68 | + return intrinsic_type_desc::type<vm_module_ref_t>(); | |
| 69 | +} | |
| 70 | + | |
| 71 | +vm_module_ref_t::vm_module_ref_t(std::shared_ptr<const vm_module_t> module) | |
| 72 | + : vm_alloc_t(vm_module_ref_t::type_desc()) | |
| 73 | + , code_section{ module->code_section } | |
| 74 | + , module{ module } | |
| 75 | + , mp_base{ nullptr } | |
| 76 | + , type_section{ module->type_section } | |
| 77 | + , _builtin_module{ util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin) } | |
| 78 | +{ | |
| 79 | + if (module->original_mp != nullptr) | |
| 80 | + mp_base = vm_alloc_t::copy(*module->original_mp); | |
| 81 | + | |
| 82 | + if (debug::is_component_tracing_enabled<debug::component_trace_t::memory>()) | |
| 83 | + debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "init: vm module ref\n"); | |
| 84 | +} | |
| 85 | + | |
| 86 | +vm_module_ref_t::vm_module_ref_t(std::shared_ptr<const vm_module_t> module, const import_vm_module_t &imports) | |
| 87 | + : vm_alloc_t(vm_module_ref_t::type_desc()) | |
| 88 | + , code_section{ module->code_section } | |
| 89 | + , module{ module } | |
| 90 | + , type_section{ module->type_section } | |
| 91 | + , _function_refs{ resolve_imports(module->export_section, imports) } | |
| 92 | + , _builtin_module{ util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin) } | |
| 93 | +{ | |
| 94 | + assert(module->header.data_size == 0 || module->original_mp != nullptr); | |
| 95 | + | |
| 96 | + if (module->original_mp != nullptr) | |
| 97 | + mp_base = vm_alloc_t::copy(*module->original_mp); | |
| 98 | + | |
| 99 | + if (debug::is_component_tracing_enabled<debug::component_trace_t::memory>()) | |
| 100 | + debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "init: vm module ref: exported %d\n", _function_refs->get_length()); | |
| 101 | +} | |
| 102 | + | |
| 103 | +vm_module_ref_t::~vm_module_ref_t() | |
| 104 | +{ | |
| 105 | + dec_ref_count_and_free(mp_base); | |
| 106 | + | |
| 107 | + if (_function_refs != nullptr) | |
| 108 | + _function_refs->release(); | |
| 109 | + | |
| 110 | + if (debug::is_component_tracing_enabled<debug::component_trace_t::memory>()) | |
| 111 | + debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "destroy: vm module ref\n"); | |
| 112 | +} | |
| 113 | + | |
| 114 | +bool vm_module_ref_t::is_builtin_module() const | |
| 115 | +{ | |
| 116 | + return _builtin_module; | |
| 117 | +} | |
| 118 | + | |
| 119 | +const vm_module_function_ref_t& vm_module_ref_t::get_function_ref(word_t index) const | |
| 120 | +{ | |
| 121 | + assert(_function_refs != nullptr); | |
| 122 | + | |
| 123 | + if (index < 0 || _function_refs->get_length() <= index) | |
| 124 | + throw vm_system_exception{ "Invalid function reference index into module reference functions" }; | |
| 125 | + | |
| 126 | + return _function_refs->at<vm_module_function_ref_t>(index); | |
| 127 | +} | |
| 128 | + | |