Showing the changes to src/vm/thread.cpp (1 of 8 files). Show all
Unified · Split
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <exceptions.h> |
| 13 | 13 | #include <vm_memory.h> |
| 14 | 14 | #include <debug.h> |
| 15 | +#include <utils.h> | |
| 15 | 16 | #include "execution_table.h" |
| 16 | 17 | #include "tool_dispatch.h" |
| 17 | 18 | |
| @@ -51,10 +52,11 @@ namespace · 33 unmodified lines | ||
| 51 | 52 | } |
| 52 | 53 | |
| 53 | 54 | vm_registers_t::vm_registers_t( |
| 54 | − const vm_thread_t &thread, | |
| 55 | + vm_thread_t &thread, | |
| 55 | 56 | vm_module_ref_t &entry) |
| 56 | 57 | : current_thread_state{ vm_thread_state_t::ready } |
| 57 | 58 | , current_thread_quanta{ 0 } |
| 59 | + , trap_flags{ vm_trap_flags_t::none } | |
| 58 | 60 | , module_ref{ &entry } |
| 59 | 61 | , mp_base{ entry.mp_base } |
| 60 | 62 | , thread{ thread } |
| @@ -174,25 +176,37 @@ namespace · 113 unmodified lines | ||
| 174 | 176 | { |
| 175 | 177 | struct execute_with_tool_t final |
| 176 | 178 | { |
| 177 | − static void begin_exec_loop(vm_registers_t ®isters, vm_t &) | |
| 179 | + static void begin_exec_loop(vm_registers_t &r, vm_t &) | |
| 178 | 180 | { |
| 179 | − auto tool_dispatch = registers.tool_dispatch.load(); | |
| 181 | + auto tool_dispatch = r.tool_dispatch.load(); | |
| 180 | 182 | assert(tool_dispatch != nullptr); |
| 181 | 183 | |
| 182 | − tool_dispatch->block_if_thread_suspended(registers.thread.get_thread_id()); | |
| 184 | + tool_dispatch->block_if_thread_suspended(r.thread.get_thread_id()); | |
| 185 | + } | |
| 186 | + | |
| 187 | + static void after_exec(vm_registers_t &r, vm_t &) | |
| 188 | + { | |
| 189 | + if (r.trap_flags == vm_trap_flags_t::none | |
| 190 | + || !util::has_flag(r.trap_flags, vm_trap_flags_t::instruction)) | |
| 191 | + return; | |
| 192 | + | |
| 193 | + auto tool_dispatch = r.tool_dispatch.load(); | |
| 194 | + assert(tool_dispatch != nullptr); | |
| 195 | + | |
| 196 | + tool_dispatch->on_trap(r, vm_trap_flags_t::instruction); | |
| 183 | 197 | } |
| 184 | 198 | }; |
| 185 | 199 | |
| 186 | 200 | struct execute_normal_t final |
| 187 | 201 | { |
| 188 | 202 | static void begin_exec_loop(vm_registers_t &, vm_t &) { } |
| 203 | + static void after_exec(vm_registers_t &, vm_t &) { } | |
| 189 | 204 | }; |
| 190 | 205 | |
| 191 | 206 | template<typename EXEC_DETOUR> |
| 192 | 207 | void execute_impl(vm_registers_t &r, vm_t &vm) |
| 193 | 208 | { |
| 194 | − auto &execution_duration = r.current_thread_quanta; | |
| 195 | − for (; 0 != execution_duration; --execution_duration) | |
| 209 | + for (; 0 != r.current_thread_quanta; --r.current_thread_quanta) | |
| 196 | 210 | { |
| 197 | 211 | EXEC_DETOUR::begin_exec_loop(r, vm); |
| 198 | 212 | assert(r.stack.peek_frame() != nullptr && "Thread state should not be running with empty stack"); |
| @@ -212,6 +226,8 @@ namespace · 13 unmodified lines | ||
| 212 | 226 | vm_exec_table[opcode](r, vm); |
| 213 | 227 | r.pc = r.next_pc; |
| 214 | 228 | |
| 229 | + EXEC_DETOUR::after_exec(r, vm); | |
| 230 | + | |
| 215 | 231 | if (r.current_thread_state != vm_thread_state_t::running) |
| 216 | 232 | break; |
| 217 | 233 | } |
| @@ -306,11 +322,6 @@ void vm_thread_t::set_tool_dispatch(vm_tool_dispatch_t *dispatch) · 88 unmodified lines | ||
| 306 | 322 | _registers.tool_dispatch = dispatch; |
| 307 | 323 | } |
| 308 | 324 | |
| 309 | −vm_thread_state_t vm_thread_t::get_state() const | |
| 310 | −{ | |
| 311 | − return _registers.current_thread_state; | |
| 312 | −} | |
| 313 | − | |
| 314 | 325 | const char *vm_thread_t::get_error_message() const |
| 315 | 326 | { |
| 316 | 327 | return _error_message; |
| @@ -329,4 +340,4 @@ uint32_t vm_thread_t::get_parent_thread_id() const · 12 unmodified lines | ||
| 329 | 340 | const vm_registers_t& vm_thread_t::get_registers() const |
| 330 | 341 | { |
| 331 | 342 | return _registers; |
| 332 | −} | |
| 343 | +} | |