History

Name the entry module in the exec program. Re-write stack walking function for debugger. System exceptions now print out call stack.

arr committed 10 years ago

Commit 794ecfc1 parent 4f6417b5 files · +54 −35Browse files

Unified · Split

5 files
  1. src/exec/main.cpp +3 −0
  2. src/include/runtime.h +8 −9
  3. src/vm/scheduler.cpp +19 −2
  4. src/vm/stack.cpp +0 −21
  5. src/vm/thread.cpp +24 −3
src/exec/main.cpp+3−0
@@ -73,6 +73,9 @@ namespace · 72 unmodified lines
73 e.header.entry_type = 0;73 e.header.entry_type = 0;
74 e.header.runtime_flag = (runtime_flags_t::has_import);74 e.header.runtime_flag = (runtime_flags_t::has_import);
75 75
76 std::array<uint8_t, 8> mod_name = { "_entry_" };
77 e.module_name = std::make_unique<vm_string_t>(mod_name.size() - 1, mod_name.data());
78
76 // Inherit the stack extent from the command module and add the entry frame size.79 // Inherit the stack extent from the command module and add the entry frame size.
77 e.header.stack_extent = command_module->header.stack_extent + sizeof(vm_entry_frame_t);80 e.header.stack_extent = command_module->header.stack_extent + sizeof(vm_entry_frame_t);
78 81
src/include/runtime.h+8−9
@@ -656,11 +656,6 @@ namespace disvm · 655 unmodified lines
656 pointer_t fixed_point_register_2() const;656 pointer_t fixed_point_register_2() const;
657 };657 };
658 658
659 // Callback for stack walk.
660 // Returning 'false' during the stack walk will terminate the walk.
661 // The second parameter is reserved for internal use by the VM and should not be manipulated.
662 using vm_stack_walk_callback_t = std::function<bool(const vm_frame_t *f, const void *reserved)>;
663
664 // VM stack659 // VM stack
665 class vm_stack_t final660 class vm_stack_t final
666 {661 {
@@ -680,10 +675,6 @@ namespace disvm · 13 unmodified lines
680 // Return the current top frame.675 // Return the current top frame.
681 vm_frame_t *peek_frame() const;676 vm_frame_t *peek_frame() const;
682 677
683 // Walk the stack getting a callback for each frame.
684 // This function is __not__ thread safe.
685 void walk_stack(vm_stack_walk_callback_t callback) const;
686
687 private:678 private:
688 std::unique_ptr<vm_alloc_t> _mem;679 std::unique_ptr<vm_alloc_t> _mem;
689 };680 };
@@ -741,6 +732,14 @@ namespace disvm · 51 unmodified lines
741 pointer_t dest;732 pointer_t dest;
742 };733 };
743 734
735 // Callback for stack walk.
736 // Returning 'false' during the stack walk will terminate the walk.
737 using vm_stack_walk_callback_t = std::function<bool(const pointer_t frame, const vm_pc_t pc, const vm_module_ref_t &module_ref)>;
738
739 // Walk the stack getting a callback for each frame.
740 // This function is __not__ thread safe if the vm thread being walked is not stopped.
741 void walk_stack(const vm_registers_t &r, vm_stack_walk_callback_t callback);
742
744 // VM thread743 // VM thread
745 class vm_thread_t final : public vm_alloc_t744 class vm_thread_t final : public vm_alloc_t
746 {745 {
src/vm/scheduler.cpp+19−2
@@ -5,6 +5,7 @@ · 4 unmodified lines
5//5//
6 6
7#include <debug.h>7#include <debug.h>
8#include <sstream>
8#include <exceptions.h>9#include <exceptions.h>
9#include "scheduler.h"10#include "scheduler.h"
10 11
@@ -45,8 +46,24 @@ void default_scheduler_t::worker_main(default_scheduler_t &instance) · 34 unmodified lines
45 }46 }
46 catch (const vm_system_exception &se)47 catch (const vm_system_exception &se)
47 {48 {
48 std::printf("%s\n", se.what());49 std::stringstream err_msg;
50 err_msg << se.what() << "\n";
49 51
52 if (current_thread != nullptr)
53 {
54 const auto &r = current_thread->vm_thread->get_registers();
55 walk_stack(r, [&err_msg](const pointer_t, const vm_pc_t pc, const vm_module_ref_t &module_ref)
56 {
57 auto module_name = "<No Name>";
58 if (module_ref.module->module_name != nullptr)
59 module_name = module_ref.module->module_name->str();
60
61 err_msg << "\t" << module_name << "@" << pc << "\n";
62 return true;
63 });
64 }
65
66 std::fprintf(stderr, "%s\n", err_msg.str().c_str());
50 instance._terminating = true;67 instance._terminating = true;
51 instance._worker_event.notify_all();68 instance._worker_event.notify_all();
52 }69 }
@@ -89,7 +106,7 @@ default_scheduler_t::~default_scheduler_t() · 36 unmodified lines
89bool default_scheduler_t::is_idle() const106bool default_scheduler_t::is_idle() const
90{107{
91 std::lock_guard<std::mutex> lock{ _vm_threads_lock };108 std::lock_guard<std::mutex> lock{ _vm_threads_lock };
92 return _running_vm_thread_count == 0 && _runnable_vm_threads.empty() && _blocked_vm_thread_ids.empty() && !_terminating;109 return (_terminating) || (_running_vm_thread_count == 0 && _runnable_vm_threads.empty() && _blocked_vm_thread_ids.empty());
93}110}
94 111
95vm_scheduler_control_t &default_scheduler_t::get_controller() const112vm_scheduler_control_t &default_scheduler_t::get_controller() const
src/vm/stack.cpp+0−21
@@ -295,24 +295,3 @@ vm_frame_t *vm_stack_t::peek_frame() const · 294 unmodified lines
295 auto layout = dynamic_cast<vm_stack_layout *>(_mem.get());295 auto layout = dynamic_cast<vm_stack_layout *>(_mem.get());
296 return layout->top_frame;296 return layout->top_frame;
297}297}
298
299void vm_stack_t::walk_stack(vm_stack_walk_callback_t callback) const
300{
301 if (callback == nullptr)
302 return;
303
304 auto layout = dynamic_cast<vm_stack_layout *>(_mem.get());
305 auto current_page = layout->top_page;
306 auto current_frame = layout->top_frame;
307
308 while (current_page != nullptr && current_frame != nullptr)
309 {
310 if (!callback(current_frame, current_page))
311 break;
312
313 current_frame = current_frame->prev_frame();
314
315 if (!current_page->contains_frame(current_frame))
316 current_page = current_page->prev_page;
317 }
318}
src/vm/thread.cpp+24−3
@@ -153,6 +153,27 @@ vm_registers_t::~vm_registers_t() · 152 unmodified lines
153 debug::assign_debug_pointer(&module_ref);153 debug::assign_debug_pointer(&module_ref);
154}154}
155 155
156void disvm::runtime::walk_stack(const vm_registers_t &r, vm_stack_walk_callback_t callback)
157{
158 assert(callback != nullptr);
159
160 auto current_pc = r.pc;
161 auto current_module = r.module_ref;
162 auto current_frame = r.stack.peek_frame();
163 while (current_frame != nullptr)
164 {
165 if (!callback(current_frame->base(), current_pc, *current_module))
166 break;
167
168 current_pc = current_frame->prev_pc();
169 auto prev_module_maybe = current_frame->prev_module_ref();
170 if (prev_module_maybe != nullptr)
171 current_module = prev_module_maybe;
172
173 current_frame = current_frame->prev_frame();
174 }
175}
176
156std::shared_ptr<const type_descriptor_t> vm_thread_t::type_desc()177std::shared_ptr<const type_descriptor_t> vm_thread_t::type_desc()
157{178{
158 return intrinsic_type_desc::type<vm_thread_t>();179 return intrinsic_type_desc::type<vm_thread_t>();
@@ -252,17 +273,17 @@ vm_thread_state_t vm_thread_t::execute(vm_t &virtual_machine, const uint32_t qua · 93 unmodified lines
252 catch (const unhandled_user_exception &uue)273 catch (const unhandled_user_exception &uue)
253 {274 {
254 // [TODO] Store the exception275 // [TODO] Store the exception
255 std::printf("%s - %s in %s at instruction %d\n", uue.what(), uue.exception_id, uue.module_name, uue.program_counter);276 std::fprintf(stderr, "%s - %s in %s at instruction %d\n", uue.what(), uue.exception_id, uue.module_name, uue.program_counter);
256 _registers.current_thread_state = vm_thread_state_t::broken;277 _registers.current_thread_state = vm_thread_state_t::broken;
257 }278 }
258 catch (const index_out_of_range_memory &ioor)279 catch (const index_out_of_range_memory &ioor)
259 {280 {
260 std::printf("%s - %d [%d,%d]\n", ioor.what(), ioor.invalid_value, ioor.valid_min, ioor.valid_max);281 std::fprintf(stderr, "%s - %d [%d,%d]\n", ioor.what(), ioor.invalid_value, ioor.valid_min, ioor.valid_max);
261 _registers.current_thread_state = vm_thread_state_t::broken;282 _registers.current_thread_state = vm_thread_state_t::broken;
262 }283 }
263 catch (const vm_user_exception &ue)284 catch (const vm_user_exception &ue)
264 {285 {
265 std::printf("%s\n", ue.what());286 std::fprintf(stderr, "%s\n", ue.what());
266 _registers.current_thread_state = vm_thread_state_t::broken;287 _registers.current_thread_state = vm_thread_state_t::broken;
267 }288 }
268 289