NAME
XS::JIT - Lightweight JIT compiler for XS code
VERSION
Version 0.01
SYNOPSIS
use XS::JIT;
# Compile C code and install functions
XS::JIT->compile(
code => $c_code,
name => 'MyModule::JIT::Foo',
functions => {
'Foo::new' => 'jit_new',
'Foo::name' => 'jit_name',
},
cache_dir => '_CACHED_XS', # optional, defaults to _CACHED_XS
force => 0, # optional, force recompile
);
DESCRIPTION
XS::JIT is a lightweight alternative to Inline::C for runtime JIT compilation of XS code. It's specifically optimized for use cases where you're generating C code dynamically and need to compile and load it at runtime.
Unlike Inline::C, XS::JIT:
Skips C code parsing (no Parse::RecDescent dependency)
Skips xsubpp (generates C code directly)
Uses direct compiler invocation (no make/Makefile.PL)
Provides a C API for use from other XS modules
METHODS
compile
my $ok = XS::JIT->compile(%options);
Compiles C code and installs the specified functions into Perl namespaces.
Options:
- code (required)
-
The C source code to compile. This should be valid C code that uses the Perl C API (EXTERN.h, perl.h, XSUB.h are included automatically).
- name (required)
-
A unique module name for caching purposes (e.g., "MyApp::JIT::Class_0"). This is used to generate the boot function name and cache path.
- functions (required)
-
A hashref mapping target Perl function names to source C function names:
functions => { 'Package::method' => 'c_function_name', } - cache_dir
-
Optional. Directory for caching compiled modules. Defaults to "_CACHED_XS".
- force
-
Optional. If true, forces recompilation even if a cached version exists.
Returns 1 on success, 0 on failure.
is_cached
my $cached = XS::JIT->is_cached($code, $name, $cache_dir);
Checks if a compiled module exists in the cache.
Arguments:
- $code
-
The C source code.
- $name
-
The module name.
- $cache_dir
-
Optional. Cache directory. Defaults to "_CACHED_XS".
Returns 1 if cached, 0 otherwise.
generate_code
my $c_code = XS::JIT->generate_code($user_code, $name, \%functions);
Generates the complete C source code with XS wrappers and boot function, without compiling it. Useful for debugging or custom build processes.
Arguments:
- $user_code
-
The user's C source code.
- $name
-
The module name (used for boot function naming).
- \%functions
-
A hashref mapping Perl function names to C function names.
Returns the complete generated C code as a string.
WRITING C FUNCTIONS
C functions for XS::JIT should follow this pattern:
Simple Functions (no extra arguments)
SV* my_getter(SV* self) {
dTHX;
/* self is the invocant (class or object) */
return newSVpv("hello", 0);
}
Functions with Variable Arguments
Use JIT_ARGS or dTHX; dXSARGS to access additional arguments:
SV* my_setter(SV* self, ...) {
JIT_ARGS;
if (items < 2) {
croak("Value required");
}
SV* value = ST(1); /* First argument after self */
/* ... do something with value ... */
return newSVsv(value);
}
Returning Self for Method Chaining
When returning self for method chaining, you must increment the reference count:
SV* my_chainable(SV* self, ...) {
JIT_ARGS;
/* ... modify object ... */
SvREFCNT_inc(self);
return self;
}
Creating Objects
SV* my_constructor(SV* class_sv, ...) {
dTHX;
const char* classname = SvPV_nolen(class_sv);
HV* self_hv = newHV();
/* Store attributes */
hv_store(self_hv, "attr", 4, newSViv(0), 0);
/* Bless and return */
return sv_bless(newRV_noinc((SV*)self_hv),
gv_stashpv(classname, GV_ADD));
}
C API
XS::JIT provides a C API that can be used directly from other XS modules without Perl stack overhead. Include the header file:
#include "xs_jit.h"
Then use the C functions:
XS_JIT_Func funcs[] = {
{ "Foo::new", "jit_new", 1 },
{ "Foo::name", "jit_name", 0 },
{ NULL, NULL, 0 }
};
xs_jit_compile(aTHX_ c_code, "MyModule::JIT::Foo",
funcs, 2, NULL, 0);
The header file is installed to your Perl's site architecture directory and can be found using:
perl -MConfig -e 'print "$Config{installsitearch}/auto/XS/JIT\n"'
CONVENIENCE MACROS
JIT_ARGS
The JIT_ARGS macro initializes both the thread context and the XS argument stack in a single statement. Use this at the start of functions that need to access variable arguments:
SV* my_function(SV* self, ...) {
JIT_ARGS; /* expands to: dTHX; dXSARGS */
if (items < 2) croak("Need at least one argument");
SV* arg = ST(1);
return newSVsv(arg);
}
This is equivalent to:
SV* my_function(SV* self, ...) {
dTHX;
dXSARGS;
...
}
INLINE::C COMPATIBILITY
XS::JIT provides the following macros for compatibility with code written for Inline::C:
Inline_Stack_Vars - equivalent to dXSARGS
Inline_Stack_Items - number of arguments (items)
Inline_Stack_Item(x) - get argument x (ST(x))
Inline_Stack_Reset - reset stack pointer (sp = mark)
Inline_Stack_Push(x) - push value onto stack (XPUSHs(x))
Inline_Stack_Done - finalize stack (PUTBACK)
Inline_Stack_Return(x) - return x values (XSRETURN(x))
Inline_Stack_Void - return no values (XSRETURN(0))
BENCHMARK
============================================================
XS::JIT vs Inline::C Benchmark
============================================================
Testing XS::JIT...
----------------------------------------
First compile: 0.3311 seconds
Already loaded: 0.000026 seconds
Runtime (10k iterations): 0.0094 seconds
Testing Inline::C...
----------------------------------------
First compile: 0.7568 seconds
Runtime (10k iterations): 0.0127 seconds
============================================================
Summary
============================================================
First compile speedup: 2.3x faster
Runtime performance: 1.36x faster (XS::JIT)
SEE ALSO
Inline::C - The original runtime C compiler for Perl (which has more features)
perlxs - XS language reference
perlguts - Perl internal functions for XS programming
perlapi - Perl API listing
AUTHOR
LNATION <email@lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)