This document aims to lay out the high level design and goals of the ORC runtime, and the relationships between key components.
4.4 KiB
ORC Runtime Design
The ORC runtime provides APIs for executor processes in an ORC JIT session (as opposed to the LLVM ORC libraries which provide APIs for controller processes). This includes support for both JIT'd code itself, and for users of JIT'd code.
Background
LLVM's On Request Compilation (ORC) APIs support cross-process loading of JIT'd
code. We call the process that defines and links the JIT'd code the controller
and the process that executes JIT'd code the executor. Controller processes
will link LLVM's ORC library, and construct a JIT'd program using an
llvm::orc::ExecutionSession instance (typically through an convenience wrapper
like llvm::orc::LLJIT). Executor processes construct an orc_rt::Session
object to manage resources for, and access to, JIT'd code within the executor
process.
APIs
Session
The Session object is the root object for a JIT'd program. It owns the ResourceManager instances that manage resources supporting JIT'd code (e.g. JIT'd memory, unwind info registrations, dynamic library handles, etc.).
The Session object must be constructed prior to adding any JIT'd code, and must outlive execution of any JIT'd code.
An executor may have more than one Session object, in which case each Session object must outlive execution of any JIT'd code added to that specific session.
ControllerAccess
ControllerAccess objects support bidirectional RPC between JIT'd code in the executor and the ExecutionSession in the controller.
Calls in both directions are to "wrapper functions" with a fixed signature (a function that takes a blob of bytes and returns a blob of bytes as its result). ControllerAccess objects can not generally assume anything about the format of the bytes being sent (their interpretation is up to the called function). The RPC is not fully symmetric: Calls from the controller to the executor specify wrapper function addresses (i.e. the controller can invoke any code in the executor). Calls from the executor to the controller specify tags, which are addresses in the executor processes that are associated with handlers in the controller. This ensures that the executing process can only call deliberately exposed entry points in the controller.
ControllerAccess objects may be detached before the session ends, at which point JIT'd code may continue executing, but will receive no further calls from the controller and can make no further calls to the controller.
ResourceManager
ResourceManager is an interface for classes that manage resources that support
a JIT'd program, for example memory or loaded dylib handles. It provides two
operations: detach and shutdown. The shutdown operation will be called at
Session destruction time. The detach operation may be called if the
controller detaches: since this means that no further requests for resource
allocation or release will occur prior to the end of the Session
ResourceManagers may implement this operation to abandon any fine-grained
tracking or pre-reserved resources (e.g. address space).
TaskDispatcher
Runs Tasks within the ORC runtime. In particular, calls originating from the controller (via ControllerAccess) will be dispatched as Tasks.
TaskDispatchers are responsible for ensuring that all dispatched Tasks have completed or been destroyed during Session shutdown.
WrapperFunction
A wrapper function is any function with the following C signature:
void (orc_rt_SessionRef Session, uint64_t CallId,
orc_rt_WrapperFunctionReturn Return,
orc_rt_WrapperFunctionBuffer ArgBytes);
where orc_rt_WrapperFunctionReturn and orc_rt_WrapperFunctionBuffer are
defined as:
typedef struct {
orc_rt_WrapperFunctionBufferDataUnion Data;
size_t Size;
} orc_rt_WrapperFunctionBuffer;
/**
* Asynchronous return function for an orc-rt wrapper function.
*/
typedef void (*orc_rt_WrapperFunctionReturn)(
orc_rt_SessionRef Session, uint64_t CallId,
orc_rt_WrapperFunctionBuffer ResultBytes);
The orc_rt::WrapperFunction class provides APIs for implementing and calling wrapper functions.
SPSWrapperFunction
An SPS wrapper function is a wrapper function that uses the SimplePackedSerialization scheme (see documentation in orc-rt/include/orc-rt/SimplePackedSerialization.h).
TODO:
Document...
- C API
- Error handling
- RTTI
- ExecutorAddr / ExecutorAddrRange
- SimpleNativeMemoryMap
- Memory Access (unimplemented)
- Platform classes (unimplemented)
- Other utilities