Everything that is done with libjit is done relative to a context. It is possible to have more than one context at a time - each acts as an independent environment for compiling and managing code.

When you want to compile a function, you create it with jit_function_create, and then populate its body with calls to the value and instruction functions.  See Values, and Instructions for more information on how to do this.

Using libjit in a multi-threaded environment
============================================

The library does not handle the creation, management, and destruction of threads itself.  It is up to the front-end environment to take care of that.  But the library is thread-aware, as long as you take some very simple steps.

In a multi-threaded environment, you must ensure that only one thread can build functions at any one time.  Otherwise the JIT's context may become corrupted.  To protect the system, you should call jit_context_build_start before creating the function.  And then call jit_context_build_end once the function has been fully compiled.

You can compile multiple functions during the one build process if you wish, which is the normal case when compiling a class.

It is usually a good idea to suspend the finalization of garbage-collected objects while function building is in progress. Otherwise you may get a deadlock when the finalizer thread tries to call the builder to compile a finalization routine.  Suspension of finalization is the responsibility of the caller.

Context functions
=================

The following functions are available to create, manage, and ultimately destroy JIT contexts:

 -- Function: jit_context_t jit_context_create (void)
     Create a new context block for the JIT.  Returns NULL if out of memory.

 -- Function: void jit_context_destroy (jit_context_t CONTEXT)
     Destroy a JIT context block and everything that is associated with it. It is very important that no threads within the program are currently running compiled code when this function is called.

 -- Function: void jit_context_build_start (jit_context_t CONTEXT)
     This routine should be called before you start building a function to be JIT'ed.  It acquires a lock on the context to prevent other threads from accessing the build process, since only one thread can be performing build operations at any one time.

 -- Function: void jit_context_build_end (jit_context_t CONTEXT)
     This routine should be called once you have finished building and compiling a function and are ready to resume normal execution. This routine will release the build lock, allowing other threads that are waiting on the builder to proceed.

 -- Function: void jit_context_set_on_demand_driver (jit_context_t CONTEXT, jit_on_demand_driver_func DRIVER)
     Specify the C function to be called to drive on-demand compilation.

     When on-demand compilation is requested the default driver provided by libjit takes the following actions:

      1. The context is locked by calling jit_context_build_start.

      2. If the function has already been compiled, libjit unlocks the context and returns immediately.  This can happen because of race conditions between threads: some other thread may have beaten us to the on-demand compiler.

      3. The user's on-demand compiler is called.  It is responsible for building the instructions in the function's body.  It should return one of the result codes JIT_RESULT_OK, JIT_RESULT_COMPILE_ERROR, or JIT_RESULT_OUT_OF_MEMORY.

      4. If the user's on-demand function hasn't already done so, libjit will call jit_function_compile to compile the function.

      5. The context is unlocked by calling jit_context_build_end and libjit jumps to the newly-compiled entry point.  If an error occurs, a built-in exception of type JIT_RESULT_COMPILE_ERROR or JIT_RESULT_OUT_OF_MEMORY will be thrown.

      6. The entry point of the compiled function is returned from the driver.

     You may need to provide your own driver if some additional actions are required.

 -- Function: void jit_context_set_memory_manager (jit_context_t CONTEXT, jit_memory_manager_t MANAGER)
     Specify the memory manager plug-in.

 -- Function: int jit_context_set_meta (jit_context_t CONTEXT, int TYPE, void *DATA, jit_meta_free_func FREE_DATA)
     Tag a context with some metadata.  Returns zero if out of memory.

     Metadata may be used to store dependency graphs, branch prediction information, or any other information that is useful to optimizers or code generators.  It can also be used by higher level user code to store information about the context that is specific to the virtual machine or language.

     If the TYPE already has some metadata associated with it, then the previous value will be freed.

 -- Function: int jit_context_set_meta_numeric (jit_context_t CONTEXT, int TYPE, jit_nuint DATA)
     Tag a context with numeric metadata.  Returns zero if out of memory. This function is more convenient for accessing the context's special option values:

     JIT_OPTION_CACHE_LIMIT
          A numeric option that indicates the maximum size in bytes of the function cache.  If set to zero (the default), the function cache is unlimited in size.

     JIT_OPTION_CACHE_PAGE_SIZE
          A numeric option that indicates the size in bytes of a single page in the function cache.  Memory is allocated for the cache in chunks of this size.  If set to zero, the cache page size is set to an internally-determined default (usually 128k).  The cache page size also determines the maximum size of a single compiled function.

     JIT_OPTION_PRE_COMPILE
          A numeric option that indicates that this context is being used for pre-compilation if it is set to a non-zero value.  Code within pre-compiled contexts cannot be executed directly.  Instead, they can be written out to disk in ELF format to be reloaded at some future time.

     JIT_OPTION_DONT_FOLD
          A numeric option that disables constant folding when it is set to a non-zero value.  This is useful for debugging, as it forces libjit to always execute constant expressions at run time, instead of at compile time.

     JIT_OPTION_POSITION_INDEPENDENT
          A numeric option that forces generation of position-independent code (PIC) if it is set to a non-zero value. This may be mainly useful for pre-compiled contexts.

     Metadata type values of 10000 or greater are reserved for internal use.

 -- Function: void * jit_context_get_meta (jit_context_t CONTEXT, int TYPE)
     Get the metadata associated with a particular tag.  Returns NULL if TYPE does not have any metadata associated with it.

 -- Function: jit_nuint jit_context_get_meta_numeric (jit_context_t CONTEXT, int TYPE)
     Get the metadata associated with a particular tag.  Returns zero if TYPE does not have any metadata associated with it. This version is more convenient for the pre-defined numeric option values.

 -- Function: void jit_context_free_meta (jit_context_t CONTEXT, int TYPE)
     Free metadata of a specific type on a context.  Does nothing if the TYPE does not have any metadata associated with it.