Package: pyjion
Pyjion, a JIT extension for CPython that compiles your Python code into native CIL and executes it using the.NET 7CLR.You can test out Pyjion now atlive.trypyjion.com.Read the full documentation atpyjion.readthedocs.io.Installing$pipinstallpyjionCompiling from sourcePrerequisites:CPython 3.10CMake 3.13 +.NET 7scikit-build$gitclonegit@github.com:tonybaloney/pyjion--recurse-submodules$cdpyjion$python-mpipinstall.Using PyjionTo get started, you need to have .NET installed, with Python 3.10 and the Pyjion package (I also recommend using a virtual environment).After importing pyjion, enable it by callingpyjion.enable()which sets a compilation threshold to 0 (the code only needs to be run once to be compiled by the JIT):>>>importpyjion>>>pyjion.enable()Any Python code you define or import after enabling pyjion will be JIT compiled. You don't need to execute functions in any special API, its completely transparent:>>>defhalf(x):...returnx/2>>>half(2)1.0Pyjion will have compiled thehalffunction into machine code on-the-fly and stored a cached version of that compiled function inside the function object.
You can see some basic stats by runningpyjion.info(f), wherefis the function object:>>>pyjion.info(half)JitInfo(failed=False, compile_result=<CompilationResult.Success: 1>, compiled=True, optimizations=<OptimizationFlags.InlineFramePushPop|InlineDecref: 10>, pgc=1, run_count=1)You can also execute Pyjion against any script or module:pyjion my_script.pyOr, for an existing Python module:pyjion -m calendarOptimization levelsPyjion has 3 optimization levels, 0 is the lowest and 2 is the highest. By default, Pyjion will compile at level 1.The level can be changed using theconfig()function:pyjion.config(level=2)Once you've run your code and tests on level 1, try level 2 to compare performance.
If you have problems, try lowering the level.TroubleshootingPGC Unboxing errorIf you get apyjion.PyjionUnboxingErrorwhen running the code, this means that Pyjion optimized a function which had floats, ints or boolean values, but those types have changed in subsequent calls.
To avoid this, you can disable PGC (pyjion.config(pgc=False)) or lower the optimization level.
Both options will hurt the overall performance, so if you can, refactor the function to not have general operations for a mixture of types.DisassemblyYou can see the machine code for the compiled function by disassembling it in the Python REPL.
Pyjion has essentially compiled your small Python function into a small, standalone application.
Installdistorm3andrichfirst to disassemble x86-64 assembly and runpyjion.dis.dis_native(f):>>>importpyjion.dis>>>pyjion.dis.dis_native(half)00000000: PUSH RBP00000001: MOV RBP, RSP00000004: PUSH R1400000006: PUSH RBX00000007: MOV RBX, RSI0000000a: MOV R14, [RDI+0x40]0000000e: CALL 0x1b3400000013: CMP DWORD [RAX+0x30], 0x000000017: JZ 0x3100000019: CMP QWORD [RAX+0x40], 0x00000001e: JZ 0x3100000020: MOV RDI, RAX00000023: MOV RSI, RBX00000026: XOR EDX, EDX00000028: POP RBX00000029: POP R14...The complex logic of converting a portable instruction set into low-level machine instructions is done by .NET's CLR JIT compiler.All Python code executed after the JIT is enabled will be compiled into native machine code at runtime and cached on disk. For example, to enable the JIT on a simpleapp.pyfor a Flask web app:fromsrcimportpyjionpyjion.enable()fromflaskimportFlaskapp=Flask(__name__)@app.route('/')defhello_world():return'Hello, World!'app.run()FAQHow do you pronounce "Pyjion"?Like the word "pigeon". @DinoV wanted a name that had something with "Python"
-- the "Py" part -- and something with "JIT" -- the "JI" part -- and have it be
pronounceable.How do this compare toPyPy?PyPyis an implementation of Python with its own JIT. The
biggest difference compared to Pyjion is that PyPy doesn't support all C extension
modules without modification unless they useCFFIor work with the select subset of CPython's C API that PyPy does support.
Pyjion also aims to support many JIT compilers while PyPy only supports their
custom JIT compiler.Pyston?Pystonis an implementation of Python usingLLVMas a JIT compiler. Compared to Pyjion, Pyston has
partial CPython C API support but not complete support. Pyston also only
supports LLVM as a JIT compiler.Numba?Numbais a JIT compiler for "array-oriented and
math-heavy Python code". This means that Numba is focused on scientific
computing while Pyjion tries to optimize all Python code. Numba also only
supports LLVM.IronPython?IronPythonis an implementation of Python that is
implemented using.NET. While IronPython tries to
be usable from within .NET, Pyjion does not have a compatibility story with .NET.
This also means IronPython cannot use C extension modules while Pyjion can.Psyco?Psycowas a module that monkeypatched CPython
to add a custom JIT compiler. Pyjion wants to introduce a proper C API for
adding a JIT compiler to CPython instead of monkeypatching it. It should be
noted the creator of Psyco went on to be one of the co-founders of PyPy.Unladen Swallow?Unladen Swallowwas an attempt
to make LLVM be a JIT compiler for CPython. Unfortunately the project lost
funding before finishing their work after having to spend a large amount of
time fixing issues in LLVM's JIT compiler (which has greatly improved over the
subsequent years).NuitkaandShedskin?BothNuitkaandShedskinare Python-to-C++ transpilers,
which means they translate Python code into equivalent C++ code. Being a JIT,
Pyjion is not a transpiler.Will this ever ship with CPython?Goal #1 is explicitly to add a C API to CPython to support JIT compilers. There
is no expectation, though, to ship a JIT compiler with CPython. This is because
CPython compiles with nothing more than a C89 compiler, which allows it to run
on many platforms. But adding a JIT compiler to CPython would immediately limit
it to only the platforms that the JIT supports.Does this help with using CPython w/ .NET or UWP?No. UsePython.NETif you want integration with Python and .NET 4.Code of ConductThis project has adopted theMicrosoft Open Source Code of Conduct.
For more information see theCode of Conduct FAQor contactopencode@microsoft.comwith any additional questions or comments.Release notes2.0.0Updated to .NET 71.2.7Fix a bug in the native x86_64 disassembler giving an error about compatibility on Windows Intel CPUs1.2.6Extend optimizations inRelWithDebInfomode1.2.5Changed thepyjion.config(debug=)setting to allow True or False (as before), or 0 (Release), 1 (Debug), 2 (ReleaseWithDebugInfo)1.2.4Updated to rich 11.0Fix a bug in the CIL disassembler for constant double (LDC_R8) opcodes1.2.3Unboxed operations won't update frame last instruction since they're unable to raise exceptions (making them faster)1.2.2Addedpyjion.dis.flow_graph()function to get a DOT control flow-graph of CIL basic blocksAddedpyjion.dis.cil_instructions()function to get a list of CIL instructions from a compiled functionEnable ASAN for Windows (compile-time option)CIL compiles to short branch opcodes when target is within 1 byteShow effective branch target on CIL disassembly output1.2.1Fixes a bug in OPT-12 (method caching) where it would store the incorrect cache address for a global type of subclass. Bug seen in SQLalchemy.1.2.0PGC unboxing errors are avoided when functions are called with different argument types to those it was optimized with.PGC types will now be inferred across jump statements, for loops and other small scopes, improving performanceLOAD_METHOD will use cached pointers for builtin types likedict,list, etc. meaning LOAD_METHOD is faster in many casesDictionary merge operators,|and|=will assert the return type as dictFixes a crash on Windows when referencing call points or sequence points for a free'd moduleFixes an issue runningpyjion -m modulewith arguments1.1.1Fixed a critical bug where recursive functions that use a mutable container type (e.g. list) causes a decref to the wrong object and subsequent crash.Fixes a bug on graph generation for recursive functions causing a crash in some situationsFixes a bug on method calls, which called the wrong method when the class was copied usingcopy.copy()Reduced memory consumption for method calls1.1.0Added unboxed integer operations for BINARY_LSHIFT, BINARY_RSHIFT, BINARY_AND, BINARY_OR, BINARY_XORBINARY_MULTIPLY and BINARY_POWER will stay unboxed if the right-hand operator is a constant that won't overflow (e.g. x ** 2)Added unboxed UNARY_NOT,UNARY_POSITIVE and UNARY_NEGATIVE operation for float, bool and int typesAdded unboxed UNARY_INVERT for int and bool typesAdded unboxed STORE_SUBSCR for bytearraysThe types of global variables are profiled at compile-timeImproved performance of bytearrays, by adding an unboxed bytearray type and unboxed slice operations for bytearrays, yielding unboxed integersFixed a reference count bug with unboxed range iteratorsPGC will now allow an int of value 0 or 1 to be unboxed into a boolUnboxing of integers is now more efficient and allows for True to be unboxed into 1 and False into 01.0.0Fix a bug onpyjion.config()crashing when called with invalid arguments (#401)Update to .NET 6 GALOAD_GLOBAL is faster when neither globals or builtins have changed since compiling, by caching the object address.Calls to Python functions are now routed through Vector Call (faster)Improved performance of calling builtin types, like int(), str(), etc.Calls to C Functions are fasterAdded an OptimisticIntegers optimization to level 2 to inspect integer values and unbox them if they're smallAbstract value profiler will assert tuples of constant values (e.g. float, int) based on valueLOAD_ATTR will infer the attribute type of classes using a cached attribute lookup table when optimizationAttrTypeTable(level 1) is enabledFix a bug that would reset the optimization level to 1 wheneverpyjion.enable()was calledFix a bug that would cause an invalid jump operation and a failed compilation for EXTENDED_ARG jumps which occur in big functions1.0.0 (rc4)Added ARM64 for Apple macOS (M1 Silicon). The JIT will emit native ARM64 assembly. Disassembler not supported.Added Linux/ARM64 support and a manylinux wheelAdded Windows/ARM64 supportAll JIT configuration is now set using thepyjion.config()function instead ofenable_feature()/disable_feature()Fixed a bug wherepyjion.graph()would cause an exception if graphing was not enabled when the function was compiledAdded support for theSETUP_ANNOTATIONSopcodeAdded support for generators in 3.10Fixed a bug in the DUP_TOP_TWO opcode with escaped variablesUNPACK_SEQUENCE will emit types for constant tuples of string, int and floatSTORE_FAST is now profiled during the probe stage of PGC, leading to drastically improved performance in many cases where unboxed ints and floats can be usedAdded a simple benchmark suite script (Tests/benchmarks/suite.py)Upgraded scikit-build to 0.12 for native VS2019 support1.0.0 (rc3)Updated to .NET 6 RC1Added Python 3.10 supportExperimentaltry..exceptstatements, stacked exception handlers and exception filtering. Disabled by defaultFixed a bug on LOAD_METHOD not raising an exception immediately if the method could not be resolvedRemoveenable_tracing()andenable_profilingfunctions in 3.10 builds. Profiling and tracing is detected on compilation and available via the.info()methodAdded support for PEP626 (fast line tracing)Extended profiling support for CFunction callsPyTrace_RETURN now correctly sends the return value as an argument as per CPython specFixed a bug causing SEG when range iterators are escaped1.0.0 (rc2)BINARY_MULTIPLY and BINARY_POWER will assume the resulting integer is a big integer (not unboxed)Introduced two optimizations IntegerUnboxingMultiply and IntegerUnboxingPower which are applied at optimization level 2. Try level two if you work with integers, but at smaller values to see better performance.Pyjion will infer thatrange(n)generates integers in iterator to improve unboxingLOAD_BUILD_CLASS will infer a function type instead of Any (#42)Instruction graphs will include the name of fast localsInstruction graph const values are capped to 40 charactersAdded abstract types for all builtins (#339)pyjion.info()will now return a JitInfo objectOptimization flags that were applied to a function during compilation are available inJitInfo.optimizationsAll optimizations are now runtime flags instead of compile-time featuresUnboxing PGC errors will raisepyjion.PyjionUnboxingError(ValueError) instead of ValueErrorInstruction graphs will show conditional branches (in orange)Fixed a bug in generators where mixed unboxed/boxed fast locals would yield the wrong values with PGC between the first and second compilation stagesFixed a de-optimization that happened in rc1 due to PGC asserting the abstract kind on the profiling phase and then always asserting that integers were big-integersFixed a bug where unboxed locals were decrefing frame locals on yieldGenerators will not unbox fast locals for stability reasonsFixed a regression on unboxed integers, caused by PGC values being set as AnyAssert return types for float object methods (as_integer_ratio, conjugate, is_integer, hex)1.0.0 (rc1)Addedpyjioncommand-line script to complement thepython -m pyjioncommandThe pyjion CLI has flags for enabling profiling, tracing, optimization level, graphs and debuggingUnboxing integers that don't fit intolong longwill raise a ValueError.Pyjion will mark any values above 1 billion as "big integers" and not escape them to reduce the chance of overflows.Floating point__pow__with negative values matches all behaviour of CPythonRaising0to a negative power will raise aZeroDivisionErrorPGC no longer uses a reference to probed values, dramatically reducing memory consumption between the first and second compile cyclesFixed a bug wherestatistics.variance([0, 0, 1])would raise an assertion error because of an overflow raised in Fraction arithmetic (#326)Fixed a bug on callingsys.settrace(None)would cause a segmentation fault (#330)Fixed a bug on optimized calls to custom types would crash on the 3rd execution because of the way PGC held and released references.Refactored Pyjion's test suite to PytestRewrote the documentation siteFixed a bug in the native disassembler printing empty comment linesCorrected the type signature ofpyjion.get_offsets()Fixed a bug on changed methods for object (like a global) causing crashes because of the way load_method was optimized (#335)1.0.0 (beta7)Addedpyjion.symbols(callable)API to fetch the dictionary of external call tokensExtended thedis()anddis_native()methods with a flag to not print the program counter (print_pc=False)Improved thedis_native()method to print the name of the method call after thecallinstructions as a line commentFixed a bug indis_native()which showed unresolved sequence points at the top of the printoutFixed a bug wherein(CONTAINS_OP) result wasn't being checked for exceptions and the next operation would segfault if theinoperation returned an error result.The IL indis()is closer in syntax to ILDasm and easier to readAdded apyjion.status()method to get runtime data on the JITWindows will now observe theDOTNET_ROOTandDOTNET_LIB_PATHenvironment variables1.0.0 (beta6)Updated to .NET 6 preview 6Fixed a bug whereord()builtin would return the wrong type (#315)pyjion.dis.dis()andpyjion.dis.dis_native()will show sequence points as commentsThe BINARY_POWER and INPLACE_POWER opcodes will always return a native python long instead of an escaped integer, to avoid overflows1.0.0 (beta5)Fixed a bug on large dictionary literals (>100 keys)Improved the efficiency of the BUILD_TUPLE, BUILD_LIST, BUILD_CONST_KEY_MAP, and BUILD_SET opcodesFixed a bug with comparison of numpy arrays being unboxed into a boolean instead of staying as an array (#310)1.0.0 (beta4)Support for theyieldkeyword and Python generators1.0.0 (beta3)Instruction graphs can be enabled withpyjion.enable_graphs()and then exported bypyjion.get_graph(f)Pyjion will raise an ImportError if .NET is missing instead of a system exit1.0.0 (beta2)Fast locals can store unboxed valuesMethod calls are optimized for known types by asserting the return type, e.g.str.upper()returns a stringUpdated to .NET 6 preview 5Pyjion can be run usingpython -m pyjion <command>, e.g.python -m pyjion script.pyorpython -m pyjion -m unittest1.0.0 (beta1)Added unboxing for integers (OPT-16)Added unboxing for boolFixed a bug with interned hash maps on Windows1.0.0 (alpha4)Added unboxing and escape analysis for floating point objects (OPT-16)Removed OPT-8 as it is superseded by OPT-161.0.0 (alpha3)Updated to .NET 6 preview 41.0.0 (alpha2)Debuggable JIT methods can be toggled at runtime usingpyjion.enable_debug()/pyjion.disable_debug()Added option for including Python bytecode disassembly in Pyjion disassemble printouts onpyjion.dis.dis()andpyjion.dis.dis_native()Added APIpyjion.get_offsets(callable)to get the offsets of Python Opcode <> IL offset <> native offset.Moved internal representations to fixed width standard types.1.0.0 (alpha1)Pyjion uses .NET 6 Preview 3 as the compiler, for Linux and macOS make sure you have installed it firstRich comparisons (==, <, >) of floating point numbers are significantly faster (OPT-17)All method calls are faster by enforcing vectorcall protocol and inlining anything below 10 arguments (OPT-16)0.15.0PGC now observes and optimizes heap-allocated (user-defined) typesFixed a crash on certain recursive functions with PGC enabled0.14.1Fixed macOS wheel name0.14.0LOAD_ATTR is now optimized by for types that implement the tp_getattr by prehashing the names (OPT-15)JIT will emit a direct call to LOAD_ATTR tp_getattro/tp_getattr slots for builtin typesmacOS wheels are now compiled with Clang PGOPGC will only profile non heap-allocated types (ie not user specified types) as type objects could be deallocated between compilation cyclesReduced stack effect during frame calls/function callsImproved performance on function callsPy_MakePendingCalls will be called every 100 instructions (previously 10), configurable at compile-time through theEMIT_PENDING_CALL_COUNTERdefinitionUpdated to .NET 5.0.5 (5.0.202)Fixed a bug in PGC for large functions meaning they wouldn't be optimizedImplemented PGC for BINARY_SUBSCR (OPT-5)Implemented PGC for STORE_SUBSCR (OPT-6)Implemented PGC for all inplace and regular binary operators (+, -, / etc) see OPT-130.13.0The compiler will now fail (and default back to CPython) if .NET emits a FAST_FAIL helperUNPACK_SEQUENCE is rewritten to be more efficient and use optimized  paths for LIST and TUPLE typesf-string (BUILD_STRING) is rewritten to be more efficientUNPACK_EX is rewritten to remove the requirement for dynamic heap allocation (and the stack canary) and leverage .NET compiler's dynamic eval stackPGC implemented for UNPACK_SEQUENCEPGC implemented for BINARY_SUBSCRPGC implemented for CALL_FUNCTION/OPT-140.12.0Added PGC emitter to first compile passDrastically simplified the compilation process, resulting in a smaller call stack and allowing for more recursion (and better performance)Added a field to the pyjion.info() dictinary,compile_result, indicating cause of compilation failure (if failed), seeAbstractInterpreterResultfor enumerationsFixed a bug in pyjion.dump_native/pyjion.dis.dis_native disassembling the wrapper functionIncompatible functions (those with async, yield keyword) are marked as incompatible early in the compilation processFixed a bug in OPT-13 if the type changed under certain circumstancesArguments to a frame are now marked as volatile and requiring type guards for certain optimizationsAny Python type passed as an argument is now available to be optimized by OPT-13, OPT-12Fixed a bug occuring on Linux and Windows in sre_parse._compile which caused a GuardStackException when doing an inline decref operation.Added an environment variable DOTNET_LIB_PATH to allow specifying the exact path to libclrjit0.11.0Added OPT-13 (OPTIMIZE_TYPESLOT_LOOKUPS) to optimize the type slots for all binary operators and resolve the precedence at compile-time (only for known types)Added OPT-14 (OPTIMIZE_FUNCTION_CALLS) to optimize calls to builtin functionsOptimize all frame locals by determining abstract types on compilationBugfix: Fixed a crash on f-strings with lots (>255) argumentsBugfix: Will now skip all functions containing the use ofexec()as it contains frame globals which are not supportedUpdated to .NET 5.0.3Updated the containers to Ubuntu 20Added fileobject abstract typeAdded enumerator abstract typeAdded code object abstract typeAdded integration tests for reference leaks for all binary operations (thanks @amaeckelberghe)Added module type (thanks @vacowboy75)0.10.0Added OPT-12 (OPTIMIZE_BUILTIN_METHOD) to pre-lookup methods for builtin types and bypass LOAD_METHOD (PyObject_GetMethod)Optimized LOAD_METHOD to recycle lookups for the same objectExpanded OPT-8, OPT-9, OPT-11, OPT-12 for nested stacks (e.g. inside expressions)Added a frozen set abstract type0.9.0Added OPT-11 (OPTIMIZE_BINARY_SLICE) to optimize the BUILD_SLICE and BINARY_SUBSCR operations into a single function when the slice start, stop and step is None or a const number.Fixed a bug in the set_optimization_level() being reset (thanks @tetsuo-cpp)Added a bytearray abstract value kind (thanks @tetsuo-cpp)Added a type abstract value kind  (thanks @tetsuo-cpp)Optimized the compiled instructions to only update the frame last instruction field on error/exit branchRemoved the "periodic work" method which was called for every for/while loop and put a function to call Py_MakePendingCalls for every 10th loopAdded an improvement to the process stage to infer the abstract types of return values to methods of builtin types, e.g. str.encodeAdded a check in dis_native for when the compiled function wasn't compiled (thanks @tetsuo-cpp)dis_native will now pretty print the assembly code when therichpackage is installed (thanks @C4ptainCrunch)pyjion[dis]is a new package bundled with pystorm3 and rich (thanks @C4ptainCrunch)0.8.0Enhanced the process stage of the compiler with new abstract types, iterable, bytearray, codeobject, frozenset, enumerator, file, type and moduleProcess stage will assert the abstract return type of any call to a builtin function (e.g. list(), tuple()), which will kick in the optimizations for a broader set of scenariosAdded OPT-8 (OPTIMIZE_BINARY_FUNCTIONS) to combine 2 sequential binary operations into a single operation. Adds about 15-20% performance gain on PyFloat operations.Added OPT-9 (OPTIMIZE_ITERATORS) to inline the FOR_ITER opcode of a listiter (List iterator) into native assembly instructions.Added OPT-10 (OPTIMIZE_HASHED_NAMES) to precompute the hashes for LOAD_NAME and LOAD_GLOBAL dictionary lookupsFixed a bug where looking up a known hash for a dictionary object (optimized BINARY_SUBSCR) wouldn't raise a KeyError. Seen in #1570.7.0Fixed a bug in JUMP_IF_FALSE_OR_POP/JUMP_IF_TRUE_OR_POP opcodes emitting a stack growth, which would cause a stack underflow on subsequent branch checks. JIT will compile a broader range of functions nowImplemented PEP590 vector calls for methods with 10+ arguments (thanks @tetsuo-cpp)Implemented PEP590 vector calls for functions with 10+ argumentsFixed a reference leak on method calls with large number of argumentsSupport for tracing of function calls with 10+ argumentsDisabled OPT-4 as it is causing reference leaks0.6.0Added OPT-6 optimization. Frame constants are now used to speed up assignments to lists and dictionaries. STORE_SUBSCR will assert if something is a list, or dict and shortcut
the assignment logic.Added OPT-7 optimization. The binary subscript operator is compiled to faster path under a set of circumstances, especially if the index/key is a frame constant. Hashes are precomputed
and indexes for integer constants are converted to native numbers at compile-time.The native machine-code disassembler will show the actual position of the JITed code in memory, instead of starting the offset at 0Thepyjion.dump_native()function returns a tuple with bytes, length and positionType inferencing has been improved for all inplace and binary operationsWindows builds from source are fixed for when the user wants to compile against a checkout of .NETImplemented FAST_DISPATCH for additional opcodesAdded a test runner for the CPython regression suite that tests the JIT in isolationFixed a reference leak of (self) for the LOAD_METHOD opcodeFixed a reference leak of non C functions being called via Call (CALL_FUNCTION)Fixed a bug where (very) large tuples being created via the BUILD_TUPLE opcode would cause an overflow errorFixed a bug on BUILD_MAP being called with very large dictionaries caused a fatal error0.5.0Added OPT-4 optimization. Frame locals (named variables known at compilation) using the LOAD_FAST, STORE_FAST and DELETE_FAST
opcodes will use native .NET locals instead of using the frame's f_localsplus array.Improved performance in LOAD_FAST and STORE_FAST through OPT-4Added OPT-5 optimization. Frame push/pop on entry/exit are now inline CIL instructions.LOAD_FAST skips unbound local checks when proceeded by a STORE_FAST (i.e. slot is definitely assigned)0.4.0Fixed a crash bug where CPython checks recursion depth from ceval state, which may not be setImplemented a faster check for recursion depthFixed a bug on LOAD_CLOSURE operator not being setFixed OPT-2 on Windows and LinuxFixed a bug where the wrong CIL opcode was being used to subtract values, would throw an overflow error and fail back into EFD.Implemented the .NET EE exception handlers for guard stack canaries, overflow errors, and null reference exceptionsImplemented a more efficient case of ld_i(1)Corrected cases of ob_refcnt to use 64-bit signed integersNo longer print error messages on release code for unimplemented .NET EE methodsFixed a bug on the incorrect vtable relative field being setFixed a bug where tracing and profiling would be emitted even when not explicitly enabled.NET Exceptions are transferred into Python exceptions at runtime0.3.0Added an optimization (OPT-1/OPTIMIZE_IS) to inline the "is"/ "is not" statement into a simple pointer comparison with jump statement. Compiles to inline machine code instead of a method callAdded an optimization (OPT-2/OPTIMIZE_DECREF) to decrement the refcount without a method call, when the object refcount is >1 and then call _Py_dealloc if the ref count becomes 0. Replaces the previous method callWindows now uses the system page size instead of the default value of 1MB0.2.1Added support for .NET 5.0.1Implemented a CIL modulus emitter0.2.0Added support for profiling compiled functions by enabling profiling (pyjion.enable_profiling())Added support for profiling C function calls, returns and exceptionsImplemented a faster call path for functions and methods for 5-10 argumentsFixed a bug where the page size defaulted to 0 in the .NET EE, which caused a failed assertion (and fails to compile the function), would fix a large % of functions that previously failed to compile0.1.0Added support for debugging compiled functions and modules by enabling tracing (pyjion.enable_tracing())Added support for debugging to catch unhandled/handled exceptions at runtime when tracing is enabledAdded support for opcode-level tracingFixed a bug on executing Pyjion with pydevd (VScode/PyCharm debugger) would cause the Python process to crash because of a doubly-freed code object (#7)0.0.7Added a WSGI middleware function to enable Pyjion for Flask and Django (#67)Fix a bug on dictionary merging for mapping types incorrectly raising a type error (#66)0.0.6Implemented supported for disassembling "large" methods into CIL (#27)Added type stubs for the pyjion C extensionFix a bug where merging or updating a subclassed dictionary would fail with a type error. (#28)0.0.5Fixed a critical bug where method calls with large numbers of arguments, and the argument was a tuple could cause a segmentation fault on GC collection.Tested support for IPython REPLFixed a bug where importing pyjion.dis after enabling the JIT would cause a stack overflowHas around 50% chance of working and not causing your computer to explode, or worse, segmentation fault0.0.4Added a stack probe helper for Linux (will use JIT in more scenarios)Enabled support for running unit tests in LinuxFixed a bug where JIT would crash when a method call failed because of a bad-lookupImplemented helper method redirection for Linux to support PIC compiled symbolsHas around 35% chance of working and not causing your computer to explode, or worse, segmentation faultImproved discovery of .NET libraries on LinuxFixed a bug where a garble-named log file would be generated (should be JIT timings log)0.0.3Installable bdist_wheel for Ubuntu, Debian, macOS 10.15, 11 (10.16) and Windows x64Installable manylinux2014 wheel with clrjit.so bundled inAdded multithreading/multiprocessing supportFixed a bug where the wheel would be broken if there are two distributions of Python 3.9 on the systemHas around 30% chance of working and not causing your computer to explode, or worse, segmentation fault.0.0.2Installable source distribution support for macOS, Windows and (barely) Linux.0.0.1It compiles on my machine