History

Update registers struct to include next_pc member. This allows the pc member to always point at the current PC instead of having been incremented to the 'next' PC.

arr committed 9 years ago

Commit a46f30c1 parent 87f2d5b6 files · +67 −68Browse files

Unified · Split

6 files
  1. src/exec/debugger.cpp +1 −2
  2. src/include/exceptions.h +1 −1
  3. src/include/runtime.h +2 −1
  4. src/vm/execution_table.cpp +44 −45
  5. src/vm/thread.cpp +18 −17
  6. src/vm/tool_dispatch.cpp +1 −2
src/exec/debugger.cpp+1−2
@@ -630,8 +630,7 @@ namespace · 629 unmodified lines
630630 const auto &r = *cxt.current_register;
631631 const auto &code_section = r.module_ref->code_section;
632632
633− // The current PC is actually the next PC to execute.
634− auto begin_pc = r.pc == 0 ? r.pc : r.pc - 1;
633+ auto begin_pc = r.pc;
635634 auto end_pc = begin_pc;
636635 if (absolute_pc)
637636 {
src/include/exceptions.h+1−1
@@ -36,7 +36,7 @@ namespace disvm · 35 unmodified lines
3636 { }
3737 };
3838
39− class vm_syscall_exception : public vm_system_exception
39+ class vm_syscall_exception final : public vm_system_exception
4040 {
4141 public:
4242 explicit vm_syscall_exception(disvm::vm_t &vm, const char *message)
src/include/runtime.h+2−1
@@ -745,7 +745,8 @@ namespace disvm · 744 unmodified lines
745745 const vm_thread_t &thread;
746746 std::atomic<vm_tool_dispatch_t *> tool_dispatch;
747747 vm_stack_t stack; // Frame pointer access (FP)
748− vm_pc_t pc; // Program counter (Index into module code section)
748+ vm_pc_t pc; // Current Program counter (Index into module code section)
749+ vm_pc_t next_pc; // Next Program counter
749750 vm_alloc_t *mp_base; // Module data base pointer (MP)
750751 vm_module_ref_t *module_ref; // Module reference
751752 vm_request_mutex_t request_mutex;
src/vm/execution_table.cpp+44−45
@@ -548,33 +548,33 @@ namespace · 547 unmodified lines
548548 // Compare and Branch operations
549549 //
550550
551− EXEC_DECL(bltb) { if (vt_ref<byte_t>(r.src) < vt_ref<byte_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
552− EXEC_DECL(bgtb) { if (vt_ref<byte_t>(r.src) > vt_ref<byte_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
553− EXEC_DECL(bleb) { if (vt_ref<byte_t>(r.src) <= vt_ref<byte_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
554− EXEC_DECL(bgeb) { if (vt_ref<byte_t>(r.src) >= vt_ref<byte_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
555− EXEC_DECL(beqb) { if (vt_ref<byte_t>(r.src) == vt_ref<byte_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
556− EXEC_DECL(bneb) { if (vt_ref<byte_t>(r.src) != vt_ref<byte_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
557−
558− EXEC_DECL(bltw) { if (vt_ref<word_t>(r.src) < vt_ref<word_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
559− EXEC_DECL(bgtw) { if (vt_ref<word_t>(r.src) > vt_ref<word_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
560− EXEC_DECL(blew) { if (vt_ref<word_t>(r.src) <= vt_ref<word_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
561− EXEC_DECL(bgew) { if (vt_ref<word_t>(r.src) >= vt_ref<word_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
562− EXEC_DECL(beqw) { if (vt_ref<word_t>(r.src) == vt_ref<word_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
563− EXEC_DECL(bnew) { if (vt_ref<word_t>(r.src) != vt_ref<word_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
564−
565− EXEC_DECL(bltf) { if (vt_ref<real_t>(r.src) < vt_ref<real_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
566− EXEC_DECL(bgtf) { if (vt_ref<real_t>(r.src) > vt_ref<real_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
567− EXEC_DECL(blef) { if (vt_ref<real_t>(r.src) <= vt_ref<real_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
568− EXEC_DECL(bgef) { if (vt_ref<real_t>(r.src) >= vt_ref<real_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
569− EXEC_DECL(beqf) { if (vt_ref<real_t>(r.src) == vt_ref<real_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
570− EXEC_DECL(bnef) { if (vt_ref<real_t>(r.src) != vt_ref<real_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
571−
572− EXEC_DECL(bltl) { if (vt_ref<big_t>(r.src) < vt_ref<big_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
573− EXEC_DECL(bgtl) { if (vt_ref<big_t>(r.src) > vt_ref<big_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
574− EXEC_DECL(blel) { if (vt_ref<big_t>(r.src) <= vt_ref<big_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
575− EXEC_DECL(bgel) { if (vt_ref<big_t>(r.src) >= vt_ref<big_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
576− EXEC_DECL(beql) { if (vt_ref<big_t>(r.src) == vt_ref<big_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
577− EXEC_DECL(bnel) { if (vt_ref<big_t>(r.src) != vt_ref<big_t>(r.mid)) r.pc = vt_ref<vm_pc_t>(r.dest); }
551+ EXEC_DECL(bltb) { if (vt_ref<byte_t>(r.src) < vt_ref<byte_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
552+ EXEC_DECL(bgtb) { if (vt_ref<byte_t>(r.src) > vt_ref<byte_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
553+ EXEC_DECL(bleb) { if (vt_ref<byte_t>(r.src) <= vt_ref<byte_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
554+ EXEC_DECL(bgeb) { if (vt_ref<byte_t>(r.src) >= vt_ref<byte_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
555+ EXEC_DECL(beqb) { if (vt_ref<byte_t>(r.src) == vt_ref<byte_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
556+ EXEC_DECL(bneb) { if (vt_ref<byte_t>(r.src) != vt_ref<byte_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
557+
558+ EXEC_DECL(bltw) { if (vt_ref<word_t>(r.src) < vt_ref<word_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
559+ EXEC_DECL(bgtw) { if (vt_ref<word_t>(r.src) > vt_ref<word_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
560+ EXEC_DECL(blew) { if (vt_ref<word_t>(r.src) <= vt_ref<word_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
561+ EXEC_DECL(bgew) { if (vt_ref<word_t>(r.src) >= vt_ref<word_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
562+ EXEC_DECL(beqw) { if (vt_ref<word_t>(r.src) == vt_ref<word_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
563+ EXEC_DECL(bnew) { if (vt_ref<word_t>(r.src) != vt_ref<word_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
564+
565+ EXEC_DECL(bltf) { if (vt_ref<real_t>(r.src) < vt_ref<real_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
566+ EXEC_DECL(bgtf) { if (vt_ref<real_t>(r.src) > vt_ref<real_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
567+ EXEC_DECL(blef) { if (vt_ref<real_t>(r.src) <= vt_ref<real_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
568+ EXEC_DECL(bgef) { if (vt_ref<real_t>(r.src) >= vt_ref<real_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
569+ EXEC_DECL(beqf) { if (vt_ref<real_t>(r.src) == vt_ref<real_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
570+ EXEC_DECL(bnef) { if (vt_ref<real_t>(r.src) != vt_ref<real_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
571+
572+ EXEC_DECL(bltl) { if (vt_ref<big_t>(r.src) < vt_ref<big_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
573+ EXEC_DECL(bgtl) { if (vt_ref<big_t>(r.src) > vt_ref<big_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
574+ EXEC_DECL(blel) { if (vt_ref<big_t>(r.src) <= vt_ref<big_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
575+ EXEC_DECL(bgel) { if (vt_ref<big_t>(r.src) >= vt_ref<big_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
576+ EXEC_DECL(beql) { if (vt_ref<big_t>(r.src) == vt_ref<big_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
577+ EXEC_DECL(bnel) { if (vt_ref<big_t>(r.src) != vt_ref<big_t>(r.mid)) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
578578
579579 // Define case table constants
580580 // [SPEC]Table format is partially defined in Dis VM specification
@@ -621,7 +621,7 @@ namespace · 40 unmodified lines
621621 }
622622
623623 assert(0 <= static_cast<std::size_t>(target_pc) && static_cast<std::size_t>(target_pc) < r.module_ref->code_section.size());
624− r.pc = static_cast<vm_pc_t>(target_pc);
624+ r.next_pc = static_cast<vm_pc_t>(target_pc);
625625 }
626626
627627 EXEC_DECL(casew) { _case<word_t>(r); }
@@ -675,19 +675,19 @@ namespace · 47 unmodified lines
675675 }
676676
677677 assert(0 <= static_cast<std::size_t>(target_pc) && static_cast<std::size_t>(target_pc) < r.module_ref->code_section.size());
678− r.pc = target_pc;
678+ r.next_pc = target_pc;
679679 }
680680
681681 //
682682 // String operations
683683 //
684684
685− EXEC_DECL(bltc) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) < 0) r.pc = vt_ref<vm_pc_t>(r.dest); }
686− EXEC_DECL(bgtc) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) > 0) r.pc = vt_ref<vm_pc_t>(r.dest); }
687− EXEC_DECL(blec) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) <= 0) r.pc = vt_ref<vm_pc_t>(r.dest); }
688− EXEC_DECL(bgec) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) >= 0) r.pc = vt_ref<vm_pc_t>(r.dest); }
689− EXEC_DECL(beqc) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) == 0) r.pc = vt_ref<vm_pc_t>(r.dest); }
690− EXEC_DECL(bnec) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) != 0) r.pc = vt_ref<vm_pc_t>(r.dest); }
685+ EXEC_DECL(bltc) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) < 0) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
686+ EXEC_DECL(bgtc) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) > 0) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
687+ EXEC_DECL(blec) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) <= 0) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
688+ EXEC_DECL(bgec) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) >= 0) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
689+ EXEC_DECL(beqc) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) == 0) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
690+ EXEC_DECL(bnec) { if (vm_string_t::compare(at_val<vm_string_t>(r.src), at_val<vm_string_t>(r.mid)) != 0) r.next_pc = vt_ref<vm_pc_t>(r.dest); }
691691
692692 EXEC_DECL(lenc)
693693 {
@@ -1454,7 +1454,7 @@ namespace · 760 unmodified lines
14541454 {
14551455 const auto current_top_frame = r.stack.peek_frame();
14561456 assert(current_top_frame != nullptr);
1457− r.pc = current_top_frame->prev_pc();
1457+ r.next_pc = current_top_frame->prev_pc();
14581458
14591459 if (current_top_frame->prev_module_ref() != nullptr)
14601460 {
@@ -1477,7 +1477,7 @@ namespace · 16 unmodified lines
14771477 EXEC_DECL(call)
14781478 {
14791479 auto top_frame = r.stack.push_frame();
1480− top_frame->prev_pc() = r.pc;
1480+ top_frame->prev_pc() = r.next_pc;
14811481
14821482 #ifndef NDEBUG
14831483 // Validate the stack state
@@ -1486,7 +1486,7 @@ namespace · 2 unmodified lines
14861486 assert(top_frame->base() == frame_base_pointer);
14871487 #endif
14881488
1489− r.pc = vt_ref<vm_pc_t>(r.dest);
1489+ r.next_pc = vt_ref<vm_pc_t>(r.dest);
14901490
14911491 debug::log_msg(debug::component_trace_t::stack, debug::log_level_t::debug, "enter: function");
14921492 }
@@ -1514,7 +1514,7 @@ namespace · 21 unmodified lines
15141514 #endif
15151515
15161516 // Store current state
1517− top_frame->prev_pc() = r.pc;
1517+ top_frame->prev_pc() = r.next_pc;
15181518 top_frame->prev_module_ref() = r.module_ref;
15191519
15201520 if (debug::is_component_tracing_enabled<debug::component_trace_t::stack>())
@@ -1533,7 +1533,7 @@ namespace · 12 unmodified lines
15331533 r.module_ref = target_module;
15341534 r.module_ref->add_ref();
15351535 r.mp_base = r.module_ref->mp_base;
1536− r.pc = function_pc;
1536+ r.next_pc = function_pc;
15371537
15381538 if (r.module_ref->is_builtin_module())
15391539 {
@@ -1554,7 +1554,7 @@ namespace · 14 unmodified lines
15541554 }
15551555 }
15561556
1557− EXEC_DECL(jmp) { r.pc = vt_ref<vm_pc_t>(r.dest); }
1557+ EXEC_DECL(jmp) { r.next_pc = vt_ref<vm_pc_t>(r.dest); }
15581558
15591559 EXEC_DECL(goto_)
15601560 {
@@ -1563,7 +1563,7 @@ namespace · 2 unmodified lines
15631563 assert(r.dest != nullptr);
15641564 const auto pc_table = reinterpret_cast<vm_pc_t *>(r.dest);
15651565
1566− r.pc = pc_table[pc_index];
1566+ r.next_pc = pc_table[pc_index];
15671567 }
15681568
15691569 //
@@ -1673,8 +1673,7 @@ namespace · 103 unmodified lines
16731673 vm_frame_t *target_frame;
16741674 vm_pc_t handler_pc;
16751675
1676− // The faulting pc is minus one since the VM has already incremented the counter.
1677− const auto faulting_pc = r.pc - 1;
1676+ const auto faulting_pc = r.pc;
16781677
16791678 assert(r.module_ref != nullptr);
16801679 std::tie(handler, target_frame, handler_pc) = find_exception_handler(r.stack, *r.module_ref, faulting_pc, *exception_id);
@@ -1718,7 +1717,7 @@ namespace · 37 unmodified lines
17181717 // Set the exception destination.
17191718 pt_ref(exception_destination) = e->get_allocation();
17201719
1721− r.pc = handler_pc;
1720+ r.next_pc = handler_pc;
17221721 }
17231722
17241723 // [SPEC] Added to support debugger.
src/vm/thread.cpp+18−17
@@ -59,6 +59,7 @@ vm_registers_t::vm_registers_t( · 58 unmodified lines
5959 , mp_base{ entry.mp_base }
6060 , thread{ thread }
6161 , pc{ entry.module->header.entry_pc }
62+ , next_pc { entry.module->header.entry_pc }
6263 , stack{ static_cast<std::size_t>(entry.module->header.stack_extent) }
6364 , tool_dispatch{ nullptr }
6465 , src{ nullptr }
@@ -171,9 +172,9 @@ vm_thread_t::~vm_thread_t() · 106 unmodified lines
171172
172173 namespace
173174 {
174− struct execute_with_tool_t
175+ struct execute_with_tool_t final
175176 {
176− void begin_exec_loop(vm_registers_t &registers, vm_t &)
177+ static void begin_exec_loop(vm_registers_t &registers, vm_t &)
177178 {
178179 auto tool_dispatch = registers.tool_dispatch.load();
179180 assert(tool_dispatch != nullptr);
@@ -182,36 +183,36 @@ namespace · 2 unmodified lines
182183 }
183184 };
184185
185− struct execute_normal_t
186+ struct execute_normal_t final
186187 {
187− void begin_exec_loop(vm_registers_t &, vm_t &) { }
188+ static void begin_exec_loop(vm_registers_t &, vm_t &) { }
188189 };
189190
190191 template<typename EXEC_DETOUR>
191− void execute_impl(vm_registers_t &registers, vm_t &vm)
192+ void execute_impl(vm_registers_t &r, vm_t &vm)
192193 {
193− EXEC_DETOUR detour{};
194− auto &execution_duration = registers.current_thread_quanta;
194+ auto &execution_duration = r.current_thread_quanta;
195195 for (; 0 != execution_duration; --execution_duration)
196196 {
197− detour.begin_exec_loop(registers, vm);
198− assert(registers.stack.peek_frame() != nullptr && "Thread state should not be running with empty stack");
197+ EXEC_DETOUR::begin_exec_loop(r, vm);
198+ assert(r.stack.peek_frame() != nullptr && "Thread state should not be running with empty stack");
199199
200− const auto &code_section = registers.module_ref->code_section;
201− assert(static_cast<std::size_t>(registers.pc) < code_section.size());
200+ const auto &code_section = r.module_ref->code_section;
201+ assert(static_cast<std::size_t>(r.pc) < code_section.size());
202202
203− assert(!registers.module_ref->is_builtin_module() && "Interpreter thread is unable to execute native instructions");
204− const auto &inst = code_section[registers.pc].op;
203+ assert(!r.module_ref->is_builtin_module() && "Interpreter thread is unable to execute native instructions");
204+ const auto &inst = code_section[r.pc].op;
205205 const auto opcode = static_cast<std::size_t>(inst.opcode);
206206 if (static_cast<std::size_t>(opcode_t::last_opcode) < opcode)
207207 throw vm_system_exception{ "Unknown op-code" };
208208
209209 // Instruction is valid, decode and update registers for operation
210− decode_address(inst, registers);
211− registers.pc++;
212− vm_exec_table[opcode](registers, vm);
210+ decode_address(inst, r);
211+ r.next_pc = (r.pc + 1);
212+ vm_exec_table[opcode](r, vm);
213+ r.pc = r.next_pc;
213214
214− if (registers.current_thread_state != vm_thread_state_t::running)
215+ if (r.current_thread_state != vm_thread_state_t::running)
215216 break;
216217 }
217218 }
src/vm/tool_dispatch.cpp+1−2
@@ -364,7 +364,6 @@ void vm_tool_dispatch_t::resume_all_threads() · 363 unmodified lines
364364 std::tuple<opcode_t, cookie_t> vm_tool_dispatch_t::get_original_opcode_and_cookie(const vm_registers_t &r)
365365 {
366366 const auto module = r.module_ref->module.get();
367− const auto current_pc = r.pc - 1;
368367
369368 if (module == nullptr || util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin))
370369 throw vm_system_exception{ "Unable to determine original opcode in supplied module" };
@@ -375,7 +374,7 @@ std::tuple<opcode_t, cookie_t> vm_tool_dispatch_t::get_original_opcode_and_cooki · 4 unmodified lines
375374 if (iter_orig != _breakpoints.original_opcodes.cend())
376375 {
377376 auto &pc_map = iter_orig->second;
378− auto iter_pc = pc_map.find(current_pc);
377+ auto iter_pc = pc_map.find(r.pc);
379378 if (iter_pc != pc_map.cend())
380379 return iter_pc->second;
381380 }