mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Merge pull request #2153 from skinny121/use-libffi
Use libffi to call jitted functions.
This commit is contained in:
8
.github/workflows/ci.yaml
vendored
8
.github/workflows/ci.yaml
vendored
@@ -20,8 +20,12 @@ jobs:
|
||||
- uses: actions/checkout@master
|
||||
- name: Set up the Windows environment
|
||||
run: |
|
||||
choco install llvm
|
||||
powershell.exe scripts/symlinks-to-hardlinks.ps1
|
||||
if: runner.os == 'Windows'
|
||||
- name: Set up the Mac environment
|
||||
run: brew install autoconf automake libtool
|
||||
if: runner.os == 'macOS'
|
||||
- name: Cache cargo dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
@@ -52,8 +56,12 @@ jobs:
|
||||
- uses: actions/checkout@master
|
||||
- name: Set up the Windows environment
|
||||
run: |
|
||||
choco install llvm
|
||||
powershell.exe scripts/symlinks-to-hardlinks.ps1
|
||||
if: runner.os == 'Windows'
|
||||
- name: Set up the Mac environment
|
||||
run: brew install autoconf automake libtool
|
||||
if: runner.os == 'macOS'
|
||||
- name: Cache cargo dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
|
||||
139
Cargo.lock
generated
139
Cargo.lock
generated
@@ -6,6 +6,12 @@ version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
|
||||
|
||||
[[package]]
|
||||
name = "abort_on_panic"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "955f37ac58af2416bac687c8ab66a4ccba282229bd7422a28d2281a5e66a6116"
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "0.2.3"
|
||||
@@ -117,6 +123,30 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1c85344eb535a31b62f0af37be84441ba9e7f0f4111eb0530f43d15e513fe57"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"cfg-if",
|
||||
"clang-sys",
|
||||
"clap",
|
||||
"env_logger",
|
||||
"lazy_static 1.4.0",
|
||||
"lazycell",
|
||||
"log",
|
||||
"peeking_take_while",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.2"
|
||||
@@ -234,6 +264,15 @@ version = "1.0.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
@@ -253,6 +292,17 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
@@ -722,6 +772,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.8.2"
|
||||
@@ -868,6 +924,12 @@ version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.7.4"
|
||||
@@ -887,6 +949,39 @@ version = "0.2.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3"
|
||||
|
||||
[[package]]
|
||||
name = "libffi"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c18efe55925cc7f83bf60a61394696a734ae90e668d1f2bbd954354416fec6f2"
|
||||
dependencies = [
|
||||
"abort_on_panic",
|
||||
"libc",
|
||||
"libffi-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libffi-sys"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f00e48ce437c5741a4da3b51738498343b5158c37bfa02bcb969efcc44e4e06"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
"make-cmd",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.0"
|
||||
@@ -932,6 +1027,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "make-cmd"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3"
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
@@ -999,6 +1100,16 @@ dependencies = [
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "4.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.3.0"
|
||||
@@ -1195,6 +1306,12 @@ dependencies = [
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.5.1"
|
||||
@@ -1539,6 +1656,7 @@ dependencies = [
|
||||
"cranelift",
|
||||
"cranelift-module",
|
||||
"cranelift-simplejit",
|
||||
"libffi",
|
||||
"num-traits",
|
||||
"rustpython-bytecode",
|
||||
"thiserror",
|
||||
@@ -1810,6 +1928,12 @@ dependencies = [
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.3"
|
||||
@@ -2204,6 +2328,12 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
@@ -2298,6 +2428,15 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
||||
24
README.md
24
README.md
@@ -74,6 +74,30 @@ cargo build --release --target wasm32-wasi --features="freeze-stdlib"
|
||||
|
||||
> Note: we use the `freeze-stdlib` to include the standard library inside the binary.
|
||||
|
||||
### JIT(Just in time) compiler
|
||||
|
||||
RustPython has an **very** experimental JIT compiler that compile python functions into native code.
|
||||
|
||||
#### Building
|
||||
|
||||
By default the JIT compiler isn't enabled, it's enabled with the `jit` cargo feature.
|
||||
|
||||
$ cargo run --features jit
|
||||
|
||||
This requires autoconf, automake, libtool, and clang to be installed.
|
||||
|
||||
#### Using
|
||||
|
||||
To compile a function, call `__jit__()` on it.
|
||||
|
||||
```python
|
||||
def foo():
|
||||
a = 5
|
||||
return 10 + a
|
||||
|
||||
foo.__jit__() # this will compile foo to native code and subsequent calls will execute that native code
|
||||
assert foo() == 15
|
||||
```
|
||||
|
||||
## Embedding RustPython into your Rust Applications
|
||||
|
||||
|
||||
@@ -12,5 +12,6 @@ cranelift = "0.66.0"
|
||||
cranelift-module = "0.66.0"
|
||||
cranelift-simplejit = "0.66.0"
|
||||
num-traits = "0.2"
|
||||
libffi = "0.9.0"
|
||||
rustpython-bytecode = { path = "../bytecode", version = "0.1.1" }
|
||||
thiserror = "1.0"
|
||||
|
||||
@@ -10,6 +10,16 @@ pub struct JitSig {
|
||||
pub ret: Option<JitType>,
|
||||
}
|
||||
|
||||
impl JitSig {
|
||||
pub fn to_cif(&self) -> libffi::middle::Cif {
|
||||
let ret = match self.ret {
|
||||
Some(ref ty) => ty.to_libffi(),
|
||||
None => libffi::middle::Type::void(),
|
||||
};
|
||||
libffi::middle::Cif::new(Vec::new(), ret)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum JitType {
|
||||
Int,
|
||||
@@ -23,6 +33,13 @@ impl JitType {
|
||||
Self::Float => types::F64,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_libffi(&self) -> libffi::middle::Type {
|
||||
match self {
|
||||
Self::Int => libffi::middle::Type::i64(),
|
||||
Self::Float => libffi::middle::Type::f64(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -132,8 +149,9 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
|
||||
Ok(())
|
||||
}
|
||||
Instruction::BinaryOperation { op, .. } => {
|
||||
let a = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
|
||||
// the rhs is popped off first
|
||||
let b = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
|
||||
let a = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
|
||||
match (a.ty, b.ty) {
|
||||
(JitType::Int, JitType::Int) => match op {
|
||||
BinaryOperator::Add => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
|
||||
use cranelift::prelude::*;
|
||||
use cranelift_module::{Backend, FuncId, Linkage, Module, ModuleError};
|
||||
@@ -98,20 +97,13 @@ pub struct CompiledCode {
|
||||
|
||||
impl CompiledCode {
|
||||
pub fn invoke(&self) -> Option<AbiValue> {
|
||||
match self.sig.ret {
|
||||
Some(JitType::Int) => {
|
||||
let func = unsafe { mem::transmute::<_, fn() -> i64>(self.code) };
|
||||
Some(AbiValue::Int(func()))
|
||||
}
|
||||
Some(JitType::Float) => {
|
||||
let func = unsafe { mem::transmute::<_, fn() -> f64>(self.code) };
|
||||
Some(AbiValue::Float(func()))
|
||||
}
|
||||
None => {
|
||||
let func = unsafe { mem::transmute::<_, fn()>(self.code) };
|
||||
func();
|
||||
None
|
||||
}
|
||||
let cif = self.sig.to_cif();
|
||||
unsafe {
|
||||
let value = cif.call::<UnTypedAbiValue>(
|
||||
libffi::middle::CodePtr::from_ptr(self.code as *const _),
|
||||
&[],
|
||||
);
|
||||
self.sig.ret.as_ref().map(|ty| value.to_typed(ty))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,6 +113,21 @@ pub enum AbiValue {
|
||||
Int(i64),
|
||||
}
|
||||
|
||||
union UnTypedAbiValue {
|
||||
float: f64,
|
||||
int: i64,
|
||||
_void: (),
|
||||
}
|
||||
|
||||
impl UnTypedAbiValue {
|
||||
unsafe fn to_typed(&self, ty: &JitType) -> AbiValue {
|
||||
match ty {
|
||||
JitType::Int => AbiValue::Int(self.int),
|
||||
JitType::Float => AbiValue::Float(self.float),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for CompiledCode {}
|
||||
unsafe impl Sync for CompiledCode {}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ def foo():
|
||||
a = 5
|
||||
return 10 + a
|
||||
|
||||
|
||||
def bar():
|
||||
a = 1e6
|
||||
return a / 5.0
|
||||
@@ -12,9 +13,11 @@ def tests():
|
||||
assert foo() == 15
|
||||
assert bar() == 2e5
|
||||
|
||||
|
||||
tests()
|
||||
|
||||
if hasattr(foo, "__jit__"):
|
||||
print("Has jit")
|
||||
foo.__jit__()
|
||||
bar.__jit__()
|
||||
tests()
|
||||
|
||||
Reference in New Issue
Block a user