Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CoreCLR interpreter basic compilation and execution (#112369)
* Interpreter wire up This commit adds a new library for the interpreter. This library is meant to be used as an alt jit compiler, exporting the `getJit` method that returns an interface for method compilation. This library also exports the `getInterpreter` method that returns a separate interface to be used for obtaining any other data from the interpreter library. Method compilation has the following responsability: - create an InterpMethod* for the MethodDesc that it flags as compiled. On mono, InterpMethod serves as reference to the method to be called (which is embedded throughout the code) and later on, following compilation, it is filled with additional information relevant for execution, mainly the code pointer and size of the frame. On CoreCLR, this structure will likely lose some of its relevance, we will end up referencing MethodDesc's directly in interpreter instructions. In the future, it will probably make more sense to have a few common fields of the InterpMethod (like the frame size) stored as a code header to the interpreter IR, with a InterpMethod pointer to be stored as well in the code header for less frequent data. - set the CORINFO_FLG_INTERPRETER flag in the MethodDesc. This sets up the method to be called through the InterpreterStub. - some dummy data that is necessary by the runtime is being generated, mainly the code The interpreter execution is included in the main coreclr library for convenience and speed. It will be contained in interpexec.h and interpexec.cpp while also including the interpretershared.h header from the interpreter library. This header will contain any defines and types that are relevant both during compilation as well as execution (for example the InterpMethod data or the opcode values). For the execution, InterpFrame is a structure on the native stack that is created for each interpreter frame. It will reference the method being executed as well as pointers to the interpreter stack. InterpThreadContext is a thread local structure that contains execution relevant information for the interpreter, for now it just maintains the position of the interpreter stack pointer. * Add support for compilation and execution of a simple method This commit ports over some of the compilation machinery from mono. Method compilation takes place in GenerateCode. It allocates a basic block, goes over the IL code and emits code as it goes, while updating the IL stack state. Method code is kept as a linked list of basic blocks. Each basic block keeps a linked list of instructions. The instruction information is represented by an opcode, source and destination vars and additional instruction data. Once the IL code is imported, the var offset allocator needs to kick in in order to allocate an offset for each variable referenced in the code. Once offsets are allocated the final interpreter IR can be generated, writing the opcode and instruction data linearly in the code, while replacing variable indexes with the actual variable offset. Unlike the mono interpreter, that maintains the code as an uint16_t stream, we chose to use from the start an int32_t based stream. The mono interpreter runs into limitations when executing very large methods, where some offsets don't fit in the uint16_t space. There will be a performance penalty for this that will be addressed in the distant future, by adding short versions for common opcodes. * Add interpreter test The test contains one application that contains a method named `RunInterpreterTests` serving as the interpreter entry point. This application is built only, as it is not the test itself. This application is executed with corerun by the actual test, which waits for the corerun exit code to determine success. * Stop using a mapping table between MethodDesc and InterpMethod InterpMethod* is used to handle interpreted method execution on mono, but it is not really needed. For CoreCLR we will turn this structure in a header to the compiled IR code, and identify other methods directly by the IR code pointer. The first pointer slot in the IR code will contain a pointer to the InterpMethod containing any other relevant information needed in the method execution.
- Loading branch information