History

Initial public commit for Dis VM

arr committed 10 years ago

Commit f95902eNo parent (first commit)40 files · +9358 −0Browse files

Showing the changes to src/vm/vm_exception_handler.cpp (1 of 40 files). Show all

Unified · Split

src/vm/vm_exception_handler.cpp+71−0
@@ -0,0 +1,71 @@
1+//
2+// Dis VM
3+// File: vm_exception_handler.cpp
4+// Author: arr
5+//
6+
7+#include <cstdint>
8+#include <runtime.h>
9+#include <vm_memory.h>
10+#include <exceptions.h>
11+#include <debug.h>
12+
13+using namespace disvm;
14+using namespace disvm::runtime;
15+
16+std::tuple<const handler_t *, vm_frame_t *, vm_pc_t> disvm::runtime::find_exception_handler(
17+ const vm_stack_t &stack,
18+ const vm_module_ref_t &faulting_module,
19+ const vm_pc_t faulting_pc,
20+ const vm_string_t &exception_id)
21+{
22+ auto unwind_depth = uint32_t{ 0 };
23+ auto current_module = &faulting_module;
24+ auto current_pc = faulting_pc;
25+ auto current_frame = stack.peek_frame();
26+
27+ while (current_frame != nullptr)
28+ {
29+ debug::log_msg(debug::component_trace_t::exception, debug::log_level_t::debug, "begin: handler: %d\n", unwind_depth);
30+
31+ auto &handler_section = current_module->module->handler_section;
32+
33+ for (auto &handler : handler_section)
34+ {
35+ // Outside pc range of this handler
36+ if (current_pc < handler.begin_pc || handler.end_pc <= current_pc)
37+ continue;
38+
39+ // Find the appropriate exception case
40+ for (const auto &exception : handler.exception_table)
41+ {
42+ auto exception_name = exception.name.get();
43+ if (exception_id.compare_to(exception_name) == 0)
44+ {
45+ debug::log_msg(debug::component_trace_t::exception, debug::log_level_t::debug, "end: handler: match: %d\n", unwind_depth);
46+ return std::tuple<const handler_t *, vm_frame_t *, std::size_t>{ &handler, current_frame, exception.pc };
47+ }
48+ else if (exception_name == nullptr && exception.pc != runtime_constants::invalid_program_counter)
49+ {
50+ debug::log_msg(debug::component_trace_t::exception, debug::log_level_t::debug, "end: handler: fallback: %d\n", unwind_depth);
51+ return std::tuple<const handler_t *, vm_frame_t *, std::size_t>{ &handler, current_frame, exception.pc };
52+ }
53+ }
54+ }
55+
56+ // Decrement the frame program counter. See raise instruction for details.
57+ current_pc = static_cast<word_t>(current_frame->prev_pc() - 1);
58+
59+ // Update the current module if it changes walking up the stack.
60+ auto prev_mod_ref = current_frame->prev_module_ref();
61+ if (prev_mod_ref != nullptr)
62+ current_module = prev_mod_ref;
63+
64+ // Move up the stack.
65+ current_frame = current_frame->prev_frame();
66+ ++unwind_depth;
67+ }
68+
69+ auto faulting_module_name = faulting_module.module->module_name->str();
70+ throw unhandled_user_exception{ exception_id.str(), faulting_module_name, faulting_pc };
71+}