mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-28 11:02:36 +00:00 
			
		
		
		
	 563b402f04
			
		
	
	
		563b402f04
		
	
	
	
	
		
			
			This should make debugging and profiling much better, at little to no runtime cost. Also moves off the operator definitions to a separate header, so it should also improve the editing experience quite a bit.
		
			
				
	
	
		
			85 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <LibWasm/AbstractMachine/AbstractMachine.h>
 | |
| 
 | |
| namespace Wasm {
 | |
| 
 | |
| class Configuration {
 | |
| public:
 | |
|     explicit Configuration(Store& store)
 | |
|         : m_store(store)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     Optional<Label> nth_label(size_t label)
 | |
|     {
 | |
|         auto index = nth_label_index(label);
 | |
|         if (index.has_value())
 | |
|             return m_stack.entries()[index.value()].get<Label>();
 | |
|         return {};
 | |
|     }
 | |
|     Optional<size_t> nth_label_index(size_t);
 | |
|     void set_frame(Frame&& frame)
 | |
|     {
 | |
|         m_current_frame_index = m_stack.size();
 | |
|         Label label(frame.arity(), frame.expression().instructions().size());
 | |
|         m_stack.push(move(frame));
 | |
|         m_stack.push(label);
 | |
|     }
 | |
|     ALWAYS_INLINE auto& frame() const { return m_stack.entries()[m_current_frame_index].get<Frame>(); }
 | |
|     ALWAYS_INLINE auto& frame() { return m_stack.entries()[m_current_frame_index].get<Frame>(); }
 | |
|     ALWAYS_INLINE auto& ip() const { return m_ip; }
 | |
|     ALWAYS_INLINE auto& ip() { return m_ip; }
 | |
|     ALWAYS_INLINE auto& depth() const { return m_depth; }
 | |
|     ALWAYS_INLINE auto& depth() { return m_depth; }
 | |
|     ALWAYS_INLINE auto& stack() const { return m_stack; }
 | |
|     ALWAYS_INLINE auto& stack() { return m_stack; }
 | |
|     ALWAYS_INLINE auto& store() const { return m_store; }
 | |
|     ALWAYS_INLINE auto& store() { return m_store; }
 | |
| 
 | |
|     struct CallFrameHandle {
 | |
|         explicit CallFrameHandle(Configuration& configuration)
 | |
|             : frame_index(configuration.m_current_frame_index)
 | |
|             , stack_size(configuration.m_stack.size())
 | |
|             , ip(configuration.ip())
 | |
|             , configuration(configuration)
 | |
|         {
 | |
|             configuration.depth()++;
 | |
|         }
 | |
| 
 | |
|         ~CallFrameHandle()
 | |
|         {
 | |
|             configuration.unwind({}, *this);
 | |
|         }
 | |
| 
 | |
|         size_t frame_index { 0 };
 | |
|         size_t stack_size { 0 };
 | |
|         InstructionPointer ip { 0 };
 | |
|         Configuration& configuration;
 | |
|     };
 | |
| 
 | |
|     void unwind(Badge<CallFrameHandle>, CallFrameHandle const&);
 | |
|     Result call(Interpreter&, FunctionAddress, Vector<Value> arguments);
 | |
|     Result execute(Interpreter&);
 | |
| 
 | |
|     void enable_instruction_count_limit() { m_should_limit_instruction_count = true; }
 | |
|     bool should_limit_instruction_count() const { return m_should_limit_instruction_count; }
 | |
| 
 | |
|     void dump_stack();
 | |
| 
 | |
| private:
 | |
|     Store& m_store;
 | |
|     size_t m_current_frame_index { 0 };
 | |
|     Stack m_stack;
 | |
|     size_t m_depth { 0 };
 | |
|     InstructionPointer m_ip;
 | |
|     bool m_should_limit_instruction_count { false };
 | |
| };
 | |
| 
 | |
| }
 |