{"id":13689154,"url":"https://github.com/thautwarm/diojit","last_synced_at":"2025-09-07T17:34:15.140Z","repository":{"id":54435109,"uuid":"264485135","full_name":"thautwarm/diojit","owner":"thautwarm","description":"Fully compatible CPython jit compiler. Optimising Dynamic, Interpreted, and Object-oriented(DIO) programs.","archived":false,"fork":false,"pushed_at":"2021-02-18T07:37:05.000Z","size":9873,"stargazers_count":116,"open_issues_count":8,"forks_count":2,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-07-29T07:38:24.745Z","etag":null,"topics":["cpython","jit"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thautwarm.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-16T17:03:38.000Z","updated_at":"2024-09-13T10:07:07.000Z","dependencies_parsed_at":"2022-08-13T15:31:25.340Z","dependency_job_id":null,"html_url":"https://github.com/thautwarm/diojit","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/thautwarm/diojit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thautwarm%2Fdiojit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thautwarm%2Fdiojit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thautwarm%2Fdiojit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thautwarm%2Fdiojit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thautwarm","download_url":"https://codeload.github.com/thautwarm/diojit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thautwarm%2Fdiojit/sbom","scorecard":{"id":876880,"data":{"date":"2025-08-11","repo":{"name":"github.com/thautwarm/diojit","commit":"87b738a2edc9242ac82b2c34744d173f8c5005c2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.8,"checks":[{"name":"Code-Review","score":0,"reason":"Found 1/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: pipCommand not pinned by hash: test.sh:2","Warn: pipCommand not pinned by hash: test.sh:15","Info:   0 out of   2 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 2-Clause \"Simplified\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 1 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-24T06:22:58.829Z","repository_id":54435109,"created_at":"2025-08-24T06:22:58.829Z","updated_at":"2025-08-24T06:22:58.829Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273377153,"owners_count":25094528,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpython","jit"],"created_at":"2024-08-02T15:01:35.808Z","updated_at":"2025-09-07T17:34:14.754Z","avatar_url":"https://github.com/thautwarm.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"## DIO-JIT: General-purpose Python JIT\n\n[![中文README](https://img.shields.io/badge/i18n-%E4%B8%AD%E6%96%87%E6%96%87%E6%A1%A3-teal)](https://github.com/thautwarm/diojit/blob/master/README.zh_CN.md) [![PyPI version shields.io](https://img.shields.io/pypi/v/diojit.svg)](https://pypi.python.org/pypi/diojit/)\n[![JIT](https://img.shields.io/badge/cpython-3.8|3.9-green.svg)](https://pypi.python.org/pypi/diojit/)\n\nImportant:\n\n1. DIO-JIT now works for Python \u003e= 3.8. We heavily rely on the `LOAD_METHOD` bytecode instruction.\n2. DIO-JIT is not production-ready. a large number of specialisation rules are required to make DIO-JIT batteries-included.\n3. This document is mainly provided for prospective developers. Users are not required to write any specialisation rules, which means that users need to learn nothing but `@jit.jit` and `jit.spec_call`.\n\n### Benchmark\n\n| Item                                                                                       | PY38   | JIT PY38 | PY39   | JIT PY39 |\n| ------------------------------------------------------------------------------------------ | ------ | -------- | ------ | -------- |\n| [BF](https://github.com/thautwarm/diojit/blob/master/benchmarks/brainfuck.py)              | 265.74 | 134.23   | 244.50 | 140.34   |\n| [append3](https://github.com/thautwarm/diojit/blob/master/benchmarks/append3.py)           | 23.94  | 10.70    | 22.29  | 11.21    |\n| [DNA READ](https://github.com/thautwarm/diojit/blob/master/benchmarks/dna_read.py)         | 16.96  | 14.82    | 15.03  | 14.38    |\n| [fib(15)](https://github.com/thautwarm/diojit/blob/master/benchmarks/fib.py)               | 11.63  | 1.54     | 10.41  | 1.51     |\n| [hypot(str, str)](https://github.com/thautwarm/diojit/blob/master/benchmarks/hypot.py)     | 6.19   | 3.87     | 6.53   | 4.29     |\n| [selectsort](https://github.com/thautwarm/diojit/blob/master/benchmarks/selection_sort.py) | 46.95  | 33.88    | 38.71  | 29.49    |\n| [trans](https://github.com/thautwarm/diojit/blob/master/benchmarks/trans.py)               | 24.22  | 7.79     | 23.23  | 7.71     |\n\nThe benchmark item \"DNA READ\" does not show a significant performance gain, this is because \"DNA READ\" heavily uses `bytearray` and `bytes`, whose specialised C-APIs\nare not exposed. In this case, although the JIT can infer the types, we have to fall back to CPython's default behaviour, or even worse: after all, the interpreter can access internal things, while we cannot.\n\nP.S:\nDIO-JIT can do very powerful partial evaluation, which is disabled in default but you can\nleverage it in your domain specific tasks. Here is an example of achieving **500x** speed up against pure Python: [fibs.py](https://github.com/thautwarm/diojit/blob/master/benchmarks/const_fib.py)\n\n## Install Instructions\n\n\u003cdetails\u003e\u003csummary\u003eStep 1: Install Julia as an in-process native code compiler for DIO-JIT\u003c/summary\u003e\n\u003cp\u003e\n\nThere are several options for you to install Julia:\n\n- [scoop](http://scoop.sh/) (Windows)\n- [julialang.org](https://julialang.org/downloads) (recommended for Windows users)\n- [jill.py](https://github.com/johnnychen94/jill.py):\n\n```bash\n$ pip install jill \u0026\u0026 jill install 1.6 --upstream Official\n```\n\n- [jill](https://github.com/abelsiqueira/jill) (Mac and Linux only!):\n\n```bash\n$ bash -ci \"$(curl -fsSL https://raw.githubusercontent.com/abelsiqueira/jill/master/jill.sh)\"\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eStep 2: Install DIO.jl in Julia\u003c/summary\u003e\n\u003cp\u003e\n\nType `julia` and open the REPL, then\n\n```julia\njulia\u003e\n# press ]\npkg\u003e add https://github.com/thautwarm/DIO.jl\n# press backspace\njulia\u003e using DIO # precompile\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eStep 3: Install Python Package\u003c/summary\u003e\n\u003cp\u003e\n\n```bash\n$ pip install git+https://github.com/thautwarm/diojit\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eHow to fetch latest DIO-JIT?(if you have installed DIO)\u003c/summary\u003e\n\n\u003cp\u003e\n\n```bash\n$ pip install -U diojit\n$ julia -e \"using Pkg; Pkg.update(string(:DIO));using DIO\"\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\nUsage from Python side is quite similar to that from Numba.\n\n```python\nimport diojit\nfrom math import sqrt\n# eagerjit: assuming all global references are fixed\n@diojit.eagerjit\ndef fib(a):\n    if a \u003c= 2:\n        return 1\n    return fib(a + -1) + fib(a + -2)\n\njit_fib = diojit.spec_call(fib, diojit.oftype(int), diojit.oftype(int))\njit_fib(15) # 600% faster than pure python\n```\n\nIt might look strange to you that we use `a + -1` and `a + -2` here.\n\nClever observation! And that's the point!\n\nDIO-JIT relies on specilisation rules. We have written one for additions, more specifically, `operator.__add__`: [specilisation for `operator.__add__`](https://github.com/thautwarm/diojit/blob/175aab5f4cb65fee923b9f6cb97c256252fc49f5/diojit/absint/prescr.py#L226).\n\nHowever, due to the bandwidth limitation, rules for `operator.__sub__` is not implemented yet.\n\n(P.S: [why `operator.__add__`](https://github.com/thautwarm/diojit/blob/3ceb9513377234f476566f70792632ce08c13373/diojit/stack2reg/translate.py#L30).)\n\nAlthough specilisation is common in the scope of optimisation, unlike many other JIT attempts, DIO-JIT doesn't need to\nhard encode rules at compiler level. The DIO-JIT compiler implements the skeleton of abstract interpretation, but concrete\nrules for specialisation and other inferences can be added within Python itself in an extensible way!\n\nSee an example below.\n\n## Contribution Example: Add a specialisation rule for `list.append`\n\n1. Python Side:\n\n```python\nimport diojit as jit\nimport timeit\njit.create_shape(list, oop=True)\n@jit.register(list, attr=\"append\")\ndef list_append_analysis(self: jit.Judge, *args: jit.AbsVal):\n    if len(args) != 2:\n        # rollback to CPython's default code\n        return NotImplemented\n    lst, elt = args\n\n    return jit.CallSpec(\n        instance=None,  # return value is not static\n        e_call=jit.S(jit.intrinsic(\"PyList_Append\"))(lst, elt),\n        possibly_return_types=tuple({jit.S(type(None))}),\n    )\n```\n\n\n`jit.intrinsic(\"PyList_Append\")` mentioned in above code means the intrinsic provided by the Julia codegen backend.\nUsually it's calling a CPython C API, but sometimes may not.\n\nNo matter if it is an existing CPython C API, we can implement intrinsics in Julia.\n\n- [import PyList_Append symbol](https://github.com/thautwarm/DIO.jl/blob/c3ec304645437da6bb02c9e5acb0c91e5e3800a8/src/symbols.jl#L53)\n\n- [generate PyList_Append calling convention](https://github.com/thautwarm/DIO.jl/blob/5fa79357798ff3eaee561d14d4f04a271213282c/src/dynamic.jl#L120):\n\n    ```julia\n    @autoapi PyList_Append(PyPtr, PyPtr)::Cint != Cint(-1) cast(_cint2none) nocastexc\n    ```\n\n    As a consequence, we automatically generate an instrinsic function for DIO-JIT. This intrinsic function\n    is capable of handling CPython exception and reference counting.\n\nYou can either do step 2) at Python side. It might looks more intuitive.\n\n```python\nimport diojit as jit\nfrom diojit.runtime.julia_rt import jl_eval\njl_implemented_intrinsic = \"\"\"\nfunction PyList_Append(lst::Ptr, elt::PyPtr)\n    if ccall(PyAPI.PyList_Append, Cint, (PyPtr, PyPtr), lst, elt) == -1\n        return Py_NULL\n    end\n    nothing # automatically maps to a Python None\nend\nDIO.DIO_ExceptCode(::typeof(PyList_Append)) != Py_NULL\n\"\"\"\njl_eval(jl_implemented_intrinsic)\n```\n\nYou immediately get a \u003e**100%** time speed up:\n\n```python\n@jit.jit\ndef append3(xs, x):\n    xs.append(x)\n    xs.append(x)\n    xs.append(x)\n\njit_append3 = jit.spec_call(append3, jit.oftype(list), jit.Top) # 'Top' means 'Any'\nxs = [1]\njit_append3(xs, 3)\n\nprint(\"test jit_append3, [1] append 3 for 3 times:\", xs)\n# test jit func, [1] append 3 for 3 times: [1, 3, 3, 3]\n\nxs = []\n%timeit append3(xs, 1)\n# 293 ns ± 26.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n\nxs = []\n%timeit jit_append3(xs, 1)\n# 142 ns ± 14.9 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n```\n\n## Why Julia?\n\nWe don't want to maintain a C compiler, and calling `gcc` or others will introduce cross-process IO, which is slow.\nWe prefer compiling JITed code with LLVM, and **Julia is quite a killer tool for this use case**.\n\n## Current Limitations\n\n1. Support for `*varargs` and `**kwargs` are not ready: we do can immediately support them with very tiny JIT performance gain, but considering backward compatibility we decide not to do this.\n\n2. Exception handling is not yet supported inside JIT functions.\n\n    \u003cdetails\u003e\u003csummary\u003eWhy?\u003c/summary\u003e\n    \u003cp\u003e\n\n    We haven't implemented the translation from exception handling bytecode to untyped DIO IR (`jit.absint.abs.In_Stmt`).\n\n    \u003c/p\u003e\n    \u003c/details\u003e\n\n    \u003cdetails\u003e\u003csummary\u003eWill support?\u003c/summary\u003e\n    \u003cp\u003e\n\n    Yes.\n\n    In fact, now a callsite in any JIT function can raise an exception. It will not be handled by JIT functions, instead, it is lifted up to the root call, which is a pure Python call.\n\n    Exception handling will be supported when we have efforts on translating CPython bytecode about exception handling into untyped DIO IR (`jit.absint.abs.In_Stmt`).\n\n    P.S: This will be finished simultaneously with the support for `for` loop.\n\n    \u003c/p\u003e\n    \u003c/details\u003e\n\n3. Support for `for` loop is missing.\n\n    \u003cdetails\u003e\u003csummary\u003eWhy?\u003c/summary\u003e\n    \u003cp\u003e\n\n    Firstly, in CPython, `for` loop relies on exception handling, which is not supported yet.\n\n    Secondly, we're considering a fast path for `for` loop, maybe proposing a `__citer__` protocol for faster iteration for JIT functions, which requires communications with Python developers.\n\n    \u003c/p\u003e\n    \u003c/details\u003e\n\n    \u003cdetails\u003e\u003csummary\u003eWill support?\u003c/summary\u003e\n    \u003cp\u003e\n\n    Yes.\n\n    This will be finished simultaneously with support for exception handling (faster `for` loop might come later).\n\n    \u003c/p\u003e\n    \u003c/details\u003e\n\n4. Closure support is missing.\n\n    \u003cdetails\u003e\u003csummary\u003eWhy?\u003c/summary\u003e\n    \u003cp\u003e\n\n    In imperative languages, closures use *cell* structures to achieve mutable free/cell variables.\n\n    However, a writable cell makes it hard to optimise in a dynamic language.\n\n    We recommend using `types.MethodType` to create immutable closures，which can be highly optimised in DIO-JIT(near future).\n\n    ```python\n    import types\n    def f(freevars, z):\n            x, y = freevars\n            return x + y + z\n\n    def hof(x, y):\n        return types.MethodType(f, (x, y))\n    ```\n\n    \u003c/p\u003e\n    \u003c/details\u003e\n\n    \u003cdetails\u003e\u003csummary\u003eWill support?\u003c/summary\u003e\n    \u003cp\u003e\n\n    Still yes. However, don't expect much about the performance gain for Python's vanilla closures.\n\n    \u003c/p\u003e\n    \u003c/details\u003e\n\n5. Specifying fixed global references(`@diojit.jit(fixed_references=['isinstance', 'str', ...]`) too annoying?\n\n    Sorry, you have to. We are thinking about the possibility about automatic JIT covering all existing CPython code, but the biggest impediment is the volatile global variables.\n\n    You might use `@eagerjit`, and in this case you'd be cautious in making global variables unchangeable.\n\n    \u003cdetails\u003e\u003csummary\u003ePossibility?\u003c/summary\u003e\n    \u003cp\u003e\n\n    Recently we found CPython's newly(`:)`) added feature `Dict.ma_version_tag` might be used to automatically notifying JITed functions to re-compile when the global references change.\n\n    More research is required.\n\n    \u003c/p\u003e\n    \u003c/details\u003e\n\n## Contributions\n\n1. Add more prescribed specialisation rules at `jit.absint.prescr`.\n2. TODO\n\n## Benchmarks\n\nCheck `benchmarks` directory.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthautwarm%2Fdiojit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthautwarm%2Fdiojit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthautwarm%2Fdiojit/lists"}