Branch data Line data Source code
1 : : #include "backend/WebAssembly.hpp" 2 : : 3 : : #include "backend/WasmOperator.hpp" 4 : : #include <binaryen-c.h> 5 : : #include <iostream> 6 : : #include <sys/mman.h> 7 : : #include <utility> 8 : : 9 : : 10 : : using namespace m; 11 : : 12 : : 13 : : /*====================================================================================================================== 14 : : * WasmModule 15 : : *====================================================================================================================*/ 16 : : 17 : 0 : WasmModule::WasmModule() : ref_(BinaryenModuleCreate()) { } 18 : : 19 [ # # ]: 0 : WasmModule::~WasmModule() { BinaryenModuleDispose(ref_); } 20 : : 21 : 0 : std::pair<uint8_t*, std::size_t> WasmModule::binary() const 22 : : { 23 : 0 : auto result = BinaryenModuleAllocateAndWrite(ref_, nullptr); 24 : 0 : return std::make_pair(reinterpret_cast<uint8_t*>(result.binary), result.binaryBytes); 25 : : } 26 : : 27 : : M_LCOV_EXCL_START 28 : : std::ostream & m::operator<<(std::ostream &out, const WasmModule &module) 29 : : { 30 : : auto result = BinaryenModuleAllocateAndWriteText(module.ref_); 31 : : out << result; 32 : : free(result); 33 : : return out; 34 : : } 35 : : 36 : : void WasmModule::dump(std::ostream &out) const { 37 : : out << *this; 38 : : auto [buffer, length] = binary(); 39 : : out << '[' << std::hex; 40 : : for (auto ptr = buffer, end = buffer + length; ptr != end; ++ptr) { 41 : : if (ptr != buffer) out << ", "; 42 : : out << "0x" << uint32_t(*ptr); 43 : : } 44 : : out << std::dec; 45 : : out << ']' << std::endl; 46 : : free(buffer); 47 : : } 48 : : void WasmModule::dump() const { dump(std::cerr); } 49 : : M_LCOV_EXCL_STOP 50 : : 51 : : 52 : : /*====================================================================================================================== 53 : : * WasmEngine 54 : : *====================================================================================================================*/ 55 : : 56 : 268 : WasmEngine::WasmContext::WasmContext(uint32_t id, const MatchBase &plan, config_t config, std::size_t size) 57 : 134 : : config_(config) 58 : 134 : , id(id) 59 : 134 : , plan(plan) 60 [ + - ]: 134 : , vm(size) 61 : : { 62 [ + - ]: 134 : install_guard_page(); // map nullptr page 63 : : 64 [ + - ]: 134 : M_insist(size <= WASM_MAX_MEMORY); 65 : 134 : } 66 : : 67 : 10 : uint32_t WasmEngine::WasmContext::map_table(const Table &table) 68 : : { 69 : 10 : M_insist(Is_Page_Aligned(heap)); 70 : : 71 : 10 : const auto num_rows_per_instance = table.layout().child().num_tuples(); 72 : 10 : const auto instance_stride_in_bytes = table.layout().stride_in_bits() / 8U; 73 : 10 : const std::size_t num_instances = (table.store().num_rows() + num_rows_per_instance - 1) / num_rows_per_instance; 74 : 11 : const std::size_t bytes = instance_stride_in_bytes * num_instances; 75 : : 76 : : /* Map entry into WebAssembly linear memory. */ 77 : 10 : const auto off = heap; 78 : 10 : const auto aligned_bytes = Ceil_To_Next_Page(bytes); 79 : 10 : const auto &mem = table.store().memory(); 80 [ + - ]: 10 : if (aligned_bytes) { 81 : 10 : mem.map(aligned_bytes, 0, vm, off); 82 : 10 : heap += aligned_bytes; 83 : 10 : install_guard_page(); 84 : 10 : } 85 : 10 : M_insist(Is_Page_Aligned(heap)); 86 : : 87 : 10 : return off; 88 : : } 89 : : 90 : 144 : void WasmEngine::WasmContext::install_guard_page() 91 : : { 92 : 144 : M_insist(Is_Page_Aligned(heap)); 93 [ - + ]: 144 : if (not config(TRAP_GUARD_PAGES)) { 94 : : /* Map the guard page to a fresh, zeroed page. */ 95 : 144 : M_DISCARD mmap(vm.as<uint8_t*>() + heap, get_pagesize(), PROT_READ, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 96 : 144 : } 97 : 144 : heap += get_pagesize(); // install guard page 98 : 144 : M_insist(Is_Page_Aligned(heap)); 99 : 144 : } 100 : : 101 : : 102 : : /*====================================================================================================================== 103 : : * WasmBackend 104 : : *====================================================================================================================*/ 105 : : 106 : 0 : void WasmBackend::register_operators(PhysicalOptimizer &phys_opt) const { register_wasm_operators(phys_opt); } 107 : 0 : void WasmBackend::execute(const MatchBase &plan) const { engine_->execute(plan); }