SlideShare a Scribd company logo
Arbitrary code execution in Rust
or how to roll out custom DSL without getting hurt
Ingvar Stepanyan

@RReverser
Let's build a simple DSL
Let's build a simple DSL
...or use one that everyone knows and loves?
Let's build a simple DSL
...or use one that everyone knows and loves?
z = x * x + y * y - 2 * x * y
AST representation
pub enum BinOp {
Add,
Sub,
Mul,
Div,
}
AST representation
pub enum Variable {
X,
Y,
}
AST representation
pub enum Expr {
Literal(f64),
Variable(Variable),
Binary {
lhs: Box<Expr>,
op: BinOp,
rhs: Box<Expr>,
},
}
Parsing
Parsing
https://github.com/Geal/nom
Parsing
named!(var<CompleteStr, Variable>, alt!(
tag!("x") => { |_| Variable ::X } |
tag!("y") => { |_| Variable ::Y }
));
Parsing
named!(atom<CompleteStr, Expr>, alt!(
double => { Expr ::Literal } |
var => { Expr ::Variable } |
delimited!(char!('('), add_op, char!(')'))
));
Parsing
named!(mul_op<CompleteStr, Expr>, do_parse!(
init: atom >>
res: fold_many0!(
tuple!(
alt!(
char!('*') => { |_| BinOp ::Mul } |
char!('/') => { |_| BinOp ::Div }
),
atom
),
init,
|lhs, (op, rhs)| Expr ::Binary {
lhs: Box ::new(lhs),
op,
rhs: Box ::new(rhs),
}
) >>
(res)
));
Parsing
named!(add_op<CompleteStr, Expr>, do_parse!(
init: mul_op >>
res: fold_many0!(
tuple!(
alt!(
char!('+') => { |_| BinOp ::Add } |
char!('-') => { |_| BinOp ::Sub }
),
mul_op
),
init,
|lhs, (op, rhs)| Expr ::Binary {
lhs: Box ::new(lhs),
op,
rhs: Box ::new(rhs),
}
) >>
(res)
));
Parsing
• nom (combinators) - https://github.com/Geal/nom 

• combine - https://github.com/Marwes/combine

• peg - https://crates.io/crates/peg

• lalrpop (LR / LALR) - https://github.com/lalrpop/lalrpop

• ...https://crates.io/keywords/parsing
AST interpretation
Binary {
    lhs: Binary {
        lhs: Literal(2.0),
        op: Mul,
        rhs: Variable(X),
    },
    op: Mul,
    rhs: Variable(Y),
}
z = 2 * x * y
AST interpretation
Binary {
    lhs: Binary {
        lhs: Literal(2.0),
        op: Mul,
        rhs: Variable(X),
    },
    op: Mul,
    rhs: Variable(Y),
}
z = 2 * x * y
AST interpretation
Binary {
    lhs: Binary {
        lhs: Literal(2.0),
        op: Mul,
        rhs: Variable(X),
    },
    op: Mul,
    rhs: Variable(Y),
}
z = 2 * x * y
AST interpretation
Binary {
    lhs: Binary {
        lhs: Literal(2.0),
        op: Mul,
        rhs: Variable(X),
    },
    op: Mul,
    rhs: Variable(Y),
}
z = 2 * x * y
AST interpretation
Binary {
    lhs: Binary {
        lhs: Literal(2.0),
        op: Mul,
        rhs: Variable(X),
    },
    op: Mul,
    rhs: Variable(Y),
}
z = 2 * x * y
AST interpretation
Binary {
    lhs: Binary {
        lhs: Literal(2.0),
        op: Mul,
        rhs: Variable(X),
    },
    op: Mul,
    rhs: Variable(Y),
}
z = 2 * x * y
AST interpretation
Binary {
    lhs: Binary {
        lhs: Literal(2.0),
        op: Mul,
        rhs: Variable(X),
    },
    op: Mul,
    rhs: Variable(Y),
}
z = 2 * x * y
AST interpretation
Binary {
    lhs: Binary {
        lhs: Literal(2.0),
        op: Mul,
        rhs: Variable(X),
    },
    op: Mul,
    rhs: Variable(Y),
}
z = 2 * x * y
AST interpretation
Binary {
    lhs: Binary {
        lhs: Literal(2.0),
        op: Mul,
        rhs: Variable(X),
    },
    op: Mul,
    rhs: Variable(Y),
}
z = 2 * x * y
AST interpretation
Expr ::Literal(lit) => *lit,
Expr ::Variable(var) => var.calc(ctx),
Expr ::Binary { lhs, op, rhs } => {
let lhs = lhs.calc(ctx);
let rhs = rhs.calc(ctx);
op.apply(lhs, rhs)
}
AST interpretation
AST: 28.13 ns
0
500
1,000
1,500
2,000
0 10 20 30 40 50 60 70 80 90 100
Bytecode interpretation
z = 2 * x * y
Bytecode interpretation
z = 2 * x * y
2 x * y *
Bytecode interpretation
z = 2 x * y *
[ ]
Bytecode interpretation
z = 2 x * y *
[ ]
Bytecode interpretation
z = 2 x * y *
[ 2 ]
Bytecode interpretation
z = 2 x * y *
[ 2, x ]
Bytecode interpretation
z = 2 x * y *
[ 2 * x ]
Bytecode interpretation
z = 2 x * y *
[ 2 * x, y ]
Bytecode interpretation
z = 2 x * y *
[ (2 * x) * y ]
Bytecode interpretation
enum BytecodeOp {
Literal(f64),
Variable(Variable),
BinOp(BinOp),
}
Bytecode interpretation
Expr ::Literal(lit) => bc.push(BytecodeOp ::Literal(*lit)),
Expr ::Variable(v) => bc.push(BytecodeOp ::Variable(*v)),
Expr ::Binary { lhs, op, rhs } => {
lhs.compile(bc);
rhs.compile(bc);
bc.push(BytecodeOp ::BinOp(*op));
}
Bytecode interpretation
for op in &self.ops {
match op {
BytecodeOp ::Literal(lit) => stack.push(*lit),
BytecodeOp ::Variable(var) => stack.push(var.calc(ctx)),
BytecodeOp ::BinOp(op) => {
let rhs = stack.pop().unwrap();
let lhs = stack.pop().unwrap();
stack.push(op.apply(lhs, rhs));
}
}
}
Bytecode interpretation
AST: 28.13 ns
Bytecode: 27.79 ns
Bytecode compilation: 207.72 ns
0
500
1,000
1,500
2,000
0 10 20 30 40 50 60 70 80 90 100
AST Bytecode
Closures kind-of-JIT
Closures kind-of-JIT
pub type CompiledExpr = Box<dyn Fn(&Context) -> f64>;
Closures kind-of-JIT
Expr ::Literal(lit) => Box ::new(move |_ctx| lit),
Expr ::Variable(var) => match var {
Variable ::X => Box ::new(move |ctx| ctx.x),
...
},
Expr ::Binary { lhs, op, rhs } => {
let lhs = lhs.compile();
let rhs = rhs.compile();
match op {
BinOp ::Add => Box ::new(move |ctx| lhs(ctx) + rhs(ctx)),
...,
}
}
Closures kind-of-JIT
AST: 28.13 ns
Bytecode: 27.79 ns | Closure: 20.62 ns
Bytecode compilation: 207.72 ns | Closure: 200.68 ns
0
500
1,000
1,500
2,000
0 10 20 30 40 50 60 70 80 90 100
AST Bytecode Closure
JIT compilation
JIT compilation
https://llvm.org/
JIT compilation: SSA form
z = x * y + y * x
JIT compilation: SSA form
z = x * y + y * x
JIT compilation: SSA form
z = x * y + y * x
define double @z(double %x, double %y) unnamed_addr #0 {
%0 = fmul double %x, %y
%1 = fmul double %y, %x
%2 = fadd double %0, %1
ret double %2
}
JIT compilation: SSA form
z = x * y + y * x
define double @z(double %x, double %y) unnamed_addr #0 {
%0 = fmul double %x, %y
%1 = fmul double %y, %x
%2 = fadd double %0, %1
ret double %2
}
JIT compilation: SSA form
z = x * y + y * x
define double @z(double %x, double %y) unnamed_addr #0 {
%0 = fmul double %x, %y
%1 = fadd double %0, %0
ret double %1
}
LLVM from Rust
• Raw C API bindings:

https://github.com/tari/llvm-sys.rs

• llvm-rs (high-level wrappers, unmaintained):

https://github.com/TomBebbington/llvm-rs 

• Inkwell (high-level wrappers, maintained):

https://github.com/TheDan64/inkwell
LLVM from Rust
let context = Context ::create();
let f64type = context.f64_type();
let builder = context.create_builder();
LLVM from Rust
let module = context.create_module("module");
let func = module.add_function(
"jit_compiled",
f64type.fn_type(&[
f64type.into(),
f64type.into()
], false),
None,
);
LLVM from Rust
let block = func.append_basic_block("entry");
builder.position_at_end(&block);
let result = ...;
builder.build_return(Some(&result));
LLVM from Rust
Expr ::Literal(lit) => f64type.const_float(*lit),
Expr ::Variable(var) => func.get_nth_param( ...).into_float_value(),
Expr ::Binary { lhs, op, rhs } => {
let lhs = lhs.compile( ...);
let rhs = rhs.compile( ...);
match op {
BinOp ::Add => builder.build_float_add(lhs, rhs, "add"),
...
}
}
LLVM from Rust
let engine = module.create_jit_execution_engine(
OptimizationLevel ::None
)?;
unsafe {
engine.get_function("jit_compiled")?
}
LLVM from Rust
EXC_BAD_ACCESS (code=1, address=0x6d)
0x0000000100324790 jit`llvm ::verifyModule(llvm ::Module const&,
llvm ::raw_ostream*, bool*) + 121
0x0000000100180266 jit`LLVMVerifyModule + 119
0x000000010000b030 jit`verify(self =<unavailable>) at module.rs:634
0x000000010000b11a jit`clone(self =<unavailable>) at module.rs:1323
0x000000010000ad06 jit`create_jit_execution_engine(self =<unavailable>,
opt_level =<unavailable>) at module.rs:502
LLVM from Rust
EXC_BAD_ACCESS (code=1, address=0x0)
0x000000010085c19e jit`llvm ::LLVMContext ::removeModule(llvm ::Module*) + 4
0x00000001008840f3 jit`llvm ::Module ::~Module() + 31
0x0000000100407123
jit`llvm ::MCJIT ::OwningModuleContainer ::freeModulePtrSet(llvm ::SmallPtrSet<l
lvm ::Module*, 4u>&) + 97
0x0000000100407044
jit`llvm ::MCJIT ::OwningModuleContainer ::~OwningModuleContainer() + 18
0x0000000100404452 jit`llvm ::MCJIT ::~MCJIT() + 214
0x0000000100404654 jit`llvm ::MCJIT ::~MCJIT() + 14
0x0000000100008090
jit`_$LT$inkwell ..execution_engine ..ExecEngineInner$u20$as$u20$core ..ops ..dr
op ..Drop$GT$ ::drop ::h86f518daac700ebf(self=0x00007ffeefbff310) at
execution_engine.rs:421
0x0000000100001a05
jit`core ::ptr ::drop_in_place ::h91efe68b20f1058b((null)=0x00007ffeefbff310)at
ptr.rs:59
0x0000000100001783
jit`core ::ptr ::drop_in_place ::h198dbc589dc5920e((null)=0x00007ffeefbff310)at
ptr.rs:59
LLVM JIT
AST: 28.13 ns
LLVM: 1.79 ns
LLVM JIT
AST: 28.13 ns
LLVM: 1.79 ns
LLVM compilation: 820.98 us
LLVM JIT
AST: 28.13 ns
LLVM: 1.79 ns
1
10
100
1,000
10,000
100,000
1,000,000
10,000,000
100,000,000
1,000,000,000
1 10 100 1,000 10,000 100,000 1,000,000 10,000,000
AST LLVM
LLVM compilation: 820.98 us
LLVM JIT (optimised)
AST: 28.13 ns
LLVM: 1.79 ns / 1.50 ns
LLVM compilation: 820.98 us / 1.79 ms
1
10
100
1,000
10,000
100,000
1,000,000
10,000,000
100,000,000
1,000,000,000
1 10 100 1,000 10,000 100,000 1,000,000 10,000,000
AST LLVM LLVM (opt)
JIT compilation
JIT compilation
https://github.com/CraneStation/cranelift:
JIT compilation
https://github.com/CraneStation/cranelift:


Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be
useful elsewhere too. The initial planned uses that affected its design are:
JIT compilation
https://github.com/CraneStation/cranelift:


Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be
useful elsewhere too. The initial planned uses that affected its design are:
• WebAssembly compiler for the SpiderMonkey engine in Firefox.
JIT compilation
https://github.com/CraneStation/cranelift:


Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be
useful elsewhere too. The initial planned uses that affected its design are:
• WebAssembly compiler for the SpiderMonkey engine in Firefox.
• Backend for the IonMonkey JavaScript JIT compiler in Firefox.
JIT compilation
https://github.com/CraneStation/cranelift:


Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be
useful elsewhere too. The initial planned uses that affected its design are:
• WebAssembly compiler for the SpiderMonkey engine in Firefox.
• Backend for the IonMonkey JavaScript JIT compiler in Firefox.
• Debug build backend for the Rust compiler.
JIT compilation
https://github.com/CraneStation/cranelift:


Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be
useful elsewhere too. The initial planned uses that affected its design are:
• WebAssembly compiler for the SpiderMonkey engine in Firefox.
• Backend for the IonMonkey JavaScript JIT compiler in Firefox.
• Debug build backend for the Rust compiler.
...

Cranelift's APIs are not yet stable.
Cranelift
let builder = SimpleJITBuilder ::new();
let mut module: Module<SimpleJITBackend> = Module ::new(builder);
let mut ctx = module.make_context();
let mut func_builder_ctx = FunctionBuilderContext ::new();
Cranelift
let sig = &mut ctx.func.signature;
sig.params.push(AbiParam ::new(types ::F64)); // X
sig.params.push(AbiParam ::new(types ::F64)); // Y
sig.returns.push(AbiParam ::new(types ::F64));
Cranelift
let mut builder = FunctionBuilder ::new(
&mut ctx.func,
&mut func_builder_ctx
);
Cranelift
let entry_ebb = builder.create_ebb();
builder.append_ebb_params_for_function_params(entry_ebb);
builder.switch_to_block(entry_ebb);
builder.seal_block(entry_ebb);
let result = ...;
builder.ins().return_(&[result]);
builder.finalize();
Cranelift
Expr ::Literal(lit) => {
let ins = builder.ins();
ins.f64const(Ieee64 ::with_float(*lit))
}
Expr ::Variable(var) => builder.ebb_params(ebb)[ ...],
Expr ::Binary { lhs, op, rhs } => {
let lhs = lhs.compile( ...);
let rhs = rhs.compile( ...);
let ins = builder.ins();
match op {
BinOp ::Add => ins.fadd(lhs, rhs),
...
}
}
Cranelift
let id = module.declare_function(
"jit_compiled",
Linkage ::Local,
&ctx.func.signature
)?;
module.define_function(id, &mut ctx)?;
module.clear_context(&mut ctx);
module.finalize_definitions();
Ok(unsafe {
::std ::mem ::transmute(module.get_finalized_function(id))
})
Cranelift JIT
Cranelift JIT
AST: 28.131 ns
Cranelift: 2.36 ns
Cranelift JIT
AST: 28.131 ns
Cranelift: 2.36 ns
Cranelift compilation: 71.75 us
Cranelift JIT
AST: 28.131 ns
Cranelift: 2.36 ns
1
10
100
1,000
10,000
100,000
1,000,000
10,000,000
100,000,000
1,000,000,000
1 10 100 1,000 10,000 100,000 1,000,000 10,000,000
AST Cranelift
Cranelift compilation: 71.75 us
Cranelift JIT
AST: 28.131 ns
LLVM: 1.79 ns | Cranelift: 2.36 ns
1
10
100
1,000
10,000
100,000
1,000,000
10,000,000
100,000,000
1,000,000,000
1 10 100 1,000 10,000 100,000 1,000,000 10,000,000
AST LLVM Cranelift
LLVM compilation: 820.98 us | Cranelift: 71.75 us
Full comparison
1
10
100
1,000
10,000
100,000
1,000,000
10,000,000
100,000,000
1,000,000,000
1 10 100 1,000 10,000 100,000 1,000,000 10,000,000
AST LLVM Cranelift Closure

More Related Content

What's hot

Kubernetes University, Cap sur l’orchestration Docker
Kubernetes University, Cap sur l’orchestration DockerKubernetes University, Cap sur l’orchestration Docker
Kubernetes University, Cap sur l’orchestration Docker
Jean-Baptiste Claramonte
 
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
Valeriy Kravchuk
 
PostgreSQL and Benchmarks
PostgreSQL and BenchmarksPostgreSQL and Benchmarks
PostgreSQL and Benchmarks
Jignesh Shah
 
Lifetime in Rust
Lifetime in RustLifetime in Rust
Lifetime in Rust
Knoldus Inc.
 
PostgreSQL continuous backup and PITR with Barman
 PostgreSQL continuous backup and PITR with Barman PostgreSQL continuous backup and PITR with Barman
PostgreSQL continuous backup and PITR with Barman
EDB
 
Introduction to OpenStack Trove & Database as a Service
Introduction to OpenStack Trove & Database as a ServiceIntroduction to OpenStack Trove & Database as a Service
Introduction to OpenStack Trove & Database as a Service
Tesora
 
Ownership System in Rust
Ownership System in RustOwnership System in Rust
Ownership System in Rust
Chih-Hsuan Kuo
 
Redis Introduction
Redis IntroductionRedis Introduction
Redis IntroductionAlex Su
 
Devoxx : being productive with JHipster
Devoxx : being productive with JHipsterDevoxx : being productive with JHipster
Devoxx : being productive with JHipster
Julien Dubois
 
Rust vs C++
Rust vs C++Rust vs C++
Rust vs C++
corehard_by
 
Boltdb - an embedded key value database
Boltdb - an embedded key value databaseBoltdb - an embedded key value database
Boltdb - an embedded key value database
Manoj Awasthi
 
The Rust Programming Language
The Rust Programming LanguageThe Rust Programming Language
The Rust Programming Language
Mario Alexandro Santini
 
[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩
NHN FORWARD
 
Write microservice in golang
Write microservice in golangWrite microservice in golang
Write microservice in golang
Bo-Yi Wu
 
Introduction to redis
Introduction to redisIntroduction to redis
Introduction to redis
Tanu Siwag
 
Patroni - HA PostgreSQL made easy
Patroni - HA PostgreSQL made easyPatroni - HA PostgreSQL made easy
Patroni - HA PostgreSQL made easy
Alexander Kukushkin
 
Analyze Virtual Machine Overhead Compared to Bare Metal with Tracing
Analyze Virtual Machine Overhead Compared to Bare Metal with TracingAnalyze Virtual Machine Overhead Compared to Bare Metal with Tracing
Analyze Virtual Machine Overhead Compared to Bare Metal with Tracing
ScyllaDB
 
Deploy Prometheus - Grafana and EFK stack on Kubic k8s Clusters
Deploy Prometheus - Grafana and EFK stack on Kubic k8s ClustersDeploy Prometheus - Grafana and EFK stack on Kubic k8s Clusters
Deploy Prometheus - Grafana and EFK stack on Kubic k8s Clusters
Syah Dwi Prihatmoko
 
Prometheus Overview
Prometheus OverviewPrometheus Overview
Prometheus Overview
Brian Brazil
 
Cloud Native ClickHouse at Scale--Using the Altinity Kubernetes Operator-2022...
Cloud Native ClickHouse at Scale--Using the Altinity Kubernetes Operator-2022...Cloud Native ClickHouse at Scale--Using the Altinity Kubernetes Operator-2022...
Cloud Native ClickHouse at Scale--Using the Altinity Kubernetes Operator-2022...
Altinity Ltd
 

What's hot (20)

Kubernetes University, Cap sur l’orchestration Docker
Kubernetes University, Cap sur l’orchestration DockerKubernetes University, Cap sur l’orchestration Docker
Kubernetes University, Cap sur l’orchestration Docker
 
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
 
PostgreSQL and Benchmarks
PostgreSQL and BenchmarksPostgreSQL and Benchmarks
PostgreSQL and Benchmarks
 
Lifetime in Rust
Lifetime in RustLifetime in Rust
Lifetime in Rust
 
PostgreSQL continuous backup and PITR with Barman
 PostgreSQL continuous backup and PITR with Barman PostgreSQL continuous backup and PITR with Barman
PostgreSQL continuous backup and PITR with Barman
 
Introduction to OpenStack Trove & Database as a Service
Introduction to OpenStack Trove & Database as a ServiceIntroduction to OpenStack Trove & Database as a Service
Introduction to OpenStack Trove & Database as a Service
 
Ownership System in Rust
Ownership System in RustOwnership System in Rust
Ownership System in Rust
 
Redis Introduction
Redis IntroductionRedis Introduction
Redis Introduction
 
Devoxx : being productive with JHipster
Devoxx : being productive with JHipsterDevoxx : being productive with JHipster
Devoxx : being productive with JHipster
 
Rust vs C++
Rust vs C++Rust vs C++
Rust vs C++
 
Boltdb - an embedded key value database
Boltdb - an embedded key value databaseBoltdb - an embedded key value database
Boltdb - an embedded key value database
 
The Rust Programming Language
The Rust Programming LanguageThe Rust Programming Language
The Rust Programming Language
 
[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩
 
Write microservice in golang
Write microservice in golangWrite microservice in golang
Write microservice in golang
 
Introduction to redis
Introduction to redisIntroduction to redis
Introduction to redis
 
Patroni - HA PostgreSQL made easy
Patroni - HA PostgreSQL made easyPatroni - HA PostgreSQL made easy
Patroni - HA PostgreSQL made easy
 
Analyze Virtual Machine Overhead Compared to Bare Metal with Tracing
Analyze Virtual Machine Overhead Compared to Bare Metal with TracingAnalyze Virtual Machine Overhead Compared to Bare Metal with Tracing
Analyze Virtual Machine Overhead Compared to Bare Metal with Tracing
 
Deploy Prometheus - Grafana and EFK stack on Kubic k8s Clusters
Deploy Prometheus - Grafana and EFK stack on Kubic k8s ClustersDeploy Prometheus - Grafana and EFK stack on Kubic k8s Clusters
Deploy Prometheus - Grafana and EFK stack on Kubic k8s Clusters
 
Prometheus Overview
Prometheus OverviewPrometheus Overview
Prometheus Overview
 
Cloud Native ClickHouse at Scale--Using the Altinity Kubernetes Operator-2022...
Cloud Native ClickHouse at Scale--Using the Altinity Kubernetes Operator-2022...Cloud Native ClickHouse at Scale--Using the Altinity Kubernetes Operator-2022...
Cloud Native ClickHouse at Scale--Using the Altinity Kubernetes Operator-2022...
 

Similar to Building fast interpreters in Rust

Spark workshop
Spark workshopSpark workshop
Spark workshop
Wojciech Pituła
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming ii
Prashant Kalkar
 
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data EcosystemWprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Sages
 
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
PROIDEA
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
Dmitry Soshnikov
 
JVM performance options. How it works
JVM performance options. How it worksJVM performance options. How it works
JVM performance options. How it works
Dmitriy Dumanskiy
 
FunScript 2013 (with speakers notes)
FunScript 2013 (with speakers notes)FunScript 2013 (with speakers notes)
FunScript 2013 (with speakers notes)
Zach Bray
 
JavaScript - Agora nervoso
JavaScript - Agora nervosoJavaScript - Agora nervoso
JavaScript - Agora nervoso
Luis Vendrame
 
Short intro to the Rust language
Short intro to the Rust languageShort intro to the Rust language
Short intro to the Rust language
Gines Espada
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
Łukasz Bałamut
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
Sigma Software
 
Intel JIT Talk
Intel JIT TalkIntel JIT Talk
Intel JIT Talkiamdvander
 
User Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryUser Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love Story
Databricks
 
User Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryUser Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love Story
Databricks
 
Implement an MPI program to perform matrix-matrix multiplication AB .pdf
Implement an MPI program to perform matrix-matrix multiplication AB .pdfImplement an MPI program to perform matrix-matrix multiplication AB .pdf
Implement an MPI program to perform matrix-matrix multiplication AB .pdf
meerobertsonheyde608
 
Артём Акуляков - F# for Data Analysis
Артём Акуляков - F# for Data AnalysisАртём Акуляков - F# for Data Analysis
Артём Акуляков - F# for Data Analysis
SpbDotNet Community
 
How to add an optimization for C# to RyuJIT
How to add an optimization for C# to RyuJITHow to add an optimization for C# to RyuJIT
How to add an optimization for C# to RyuJIT
Egor Bogatov
 
Scala @ TomTom
Scala @ TomTomScala @ TomTom
Scala @ TomTom
Eric Bowman
 

Similar to Building fast interpreters in Rust (20)

Faster Python, FOSDEM
Faster Python, FOSDEMFaster Python, FOSDEM
Faster Python, FOSDEM
 
Spark workshop
Spark workshopSpark workshop
Spark workshop
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming ii
 
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data EcosystemWprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
 
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
JVM performance options. How it works
JVM performance options. How it worksJVM performance options. How it works
JVM performance options. How it works
 
FunScript 2013 (with speakers notes)
FunScript 2013 (with speakers notes)FunScript 2013 (with speakers notes)
FunScript 2013 (with speakers notes)
 
JavaScript - Agora nervoso
JavaScript - Agora nervosoJavaScript - Agora nervoso
JavaScript - Agora nervoso
 
Short intro to the Rust language
Short intro to the Rust languageShort intro to the Rust language
Short intro to the Rust language
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
 
Intel JIT Talk
Intel JIT TalkIntel JIT Talk
Intel JIT Talk
 
User Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryUser Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love Story
 
User Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryUser Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love Story
 
Implement an MPI program to perform matrix-matrix multiplication AB .pdf
Implement an MPI program to perform matrix-matrix multiplication AB .pdfImplement an MPI program to perform matrix-matrix multiplication AB .pdf
Implement an MPI program to perform matrix-matrix multiplication AB .pdf
 
Артём Акуляков - F# for Data Analysis
Артём Акуляков - F# for Data AnalysisАртём Акуляков - F# for Data Analysis
Артём Акуляков - F# for Data Analysis
 
How to add an optimization for C# to RyuJIT
How to add an optimization for C# to RyuJITHow to add an optimization for C# to RyuJIT
How to add an optimization for C# to RyuJIT
 
Scala @ TomTom
Scala @ TomTomScala @ TomTom
Scala @ TomTom
 

More from Ingvar Stepanyan

A very quick intro to astrophotography
A very quick intro to astrophotographyA very quick intro to astrophotography
A very quick intro to astrophotography
Ingvar Stepanyan
 
Asyncifying WebAssembly for the modern Web
Asyncifying WebAssembly for the modern WebAsyncifying WebAssembly for the modern Web
Asyncifying WebAssembly for the modern Web
Ingvar Stepanyan
 
Rust ⇋ JavaScript
Rust ⇋ JavaScriptRust ⇋ JavaScript
Rust ⇋ JavaScript
Ingvar Stepanyan
 
How I tried to compile JavaScript
How I tried to compile JavaScriptHow I tried to compile JavaScript
How I tried to compile JavaScript
Ingvar Stepanyan
 
Your code is not a string
Your code is not a stringYour code is not a string
Your code is not a string
Ingvar Stepanyan
 
es6.concurrency()
es6.concurrency()es6.concurrency()
es6.concurrency()
Ingvar Stepanyan
 
React for WinRT apps
React for WinRT appsReact for WinRT apps
React for WinRT apps
Ingvar Stepanyan
 
AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptIngvar Stepanyan
 
Creating own language made easy
Creating own language made easyCreating own language made easy
Creating own language made easy
Ingvar Stepanyan
 
JS: Audio Data Processing
JS: Audio Data ProcessingJS: Audio Data Processing
JS: Audio Data Processing
Ingvar Stepanyan
 

More from Ingvar Stepanyan (10)

A very quick intro to astrophotography
A very quick intro to astrophotographyA very quick intro to astrophotography
A very quick intro to astrophotography
 
Asyncifying WebAssembly for the modern Web
Asyncifying WebAssembly for the modern WebAsyncifying WebAssembly for the modern Web
Asyncifying WebAssembly for the modern Web
 
Rust ⇋ JavaScript
Rust ⇋ JavaScriptRust ⇋ JavaScript
Rust ⇋ JavaScript
 
How I tried to compile JavaScript
How I tried to compile JavaScriptHow I tried to compile JavaScript
How I tried to compile JavaScript
 
Your code is not a string
Your code is not a stringYour code is not a string
Your code is not a string
 
es6.concurrency()
es6.concurrency()es6.concurrency()
es6.concurrency()
 
React for WinRT apps
React for WinRT appsReact for WinRT apps
React for WinRT apps
 
AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScript
 
Creating own language made easy
Creating own language made easyCreating own language made easy
Creating own language made easy
 
JS: Audio Data Processing
JS: Audio Data ProcessingJS: Audio Data Processing
JS: Audio Data Processing
 

Recently uploaded

Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Product School
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
Elena Simperl
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
Product School
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 

Recently uploaded (20)

Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 

Building fast interpreters in Rust

  • 1. Arbitrary code execution in Rust or how to roll out custom DSL without getting hurt Ingvar Stepanyan @RReverser
  • 2. Let's build a simple DSL
  • 3. Let's build a simple DSL ...or use one that everyone knows and loves?
  • 4. Let's build a simple DSL ...or use one that everyone knows and loves? z = x * x + y * y - 2 * x * y
  • 5. AST representation pub enum BinOp { Add, Sub, Mul, Div, }
  • 6. AST representation pub enum Variable { X, Y, }
  • 7. AST representation pub enum Expr { Literal(f64), Variable(Variable), Binary { lhs: Box<Expr>, op: BinOp, rhs: Box<Expr>, }, }
  • 10. Parsing named!(var<CompleteStr, Variable>, alt!( tag!("x") => { |_| Variable ::X } | tag!("y") => { |_| Variable ::Y } ));
  • 11. Parsing named!(atom<CompleteStr, Expr>, alt!( double => { Expr ::Literal } | var => { Expr ::Variable } | delimited!(char!('('), add_op, char!(')')) ));
  • 12. Parsing named!(mul_op<CompleteStr, Expr>, do_parse!( init: atom >> res: fold_many0!( tuple!( alt!( char!('*') => { |_| BinOp ::Mul } | char!('/') => { |_| BinOp ::Div } ), atom ), init, |lhs, (op, rhs)| Expr ::Binary { lhs: Box ::new(lhs), op, rhs: Box ::new(rhs), } ) >> (res) ));
  • 13. Parsing named!(add_op<CompleteStr, Expr>, do_parse!( init: mul_op >> res: fold_many0!( tuple!( alt!( char!('+') => { |_| BinOp ::Add } | char!('-') => { |_| BinOp ::Sub } ), mul_op ), init, |lhs, (op, rhs)| Expr ::Binary { lhs: Box ::new(lhs), op, rhs: Box ::new(rhs), } ) >> (res) ));
  • 14. Parsing • nom (combinators) - https://github.com/Geal/nom • combine - https://github.com/Marwes/combine • peg - https://crates.io/crates/peg • lalrpop (LR / LALR) - https://github.com/lalrpop/lalrpop • ...https://crates.io/keywords/parsing
  • 15. AST interpretation Binary {     lhs: Binary {         lhs: Literal(2.0),         op: Mul,         rhs: Variable(X),     },     op: Mul,     rhs: Variable(Y), } z = 2 * x * y
  • 16. AST interpretation Binary {     lhs: Binary {         lhs: Literal(2.0),         op: Mul,         rhs: Variable(X),     },     op: Mul,     rhs: Variable(Y), } z = 2 * x * y
  • 17. AST interpretation Binary {     lhs: Binary {         lhs: Literal(2.0),         op: Mul,         rhs: Variable(X),     },     op: Mul,     rhs: Variable(Y), } z = 2 * x * y
  • 18. AST interpretation Binary {     lhs: Binary {         lhs: Literal(2.0),         op: Mul,         rhs: Variable(X),     },     op: Mul,     rhs: Variable(Y), } z = 2 * x * y
  • 19. AST interpretation Binary {     lhs: Binary {         lhs: Literal(2.0),         op: Mul,         rhs: Variable(X),     },     op: Mul,     rhs: Variable(Y), } z = 2 * x * y
  • 20. AST interpretation Binary {     lhs: Binary {         lhs: Literal(2.0),         op: Mul,         rhs: Variable(X),     },     op: Mul,     rhs: Variable(Y), } z = 2 * x * y
  • 21. AST interpretation Binary {     lhs: Binary {         lhs: Literal(2.0),         op: Mul,         rhs: Variable(X),     },     op: Mul,     rhs: Variable(Y), } z = 2 * x * y
  • 22. AST interpretation Binary {     lhs: Binary {         lhs: Literal(2.0),         op: Mul,         rhs: Variable(X),     },     op: Mul,     rhs: Variable(Y), } z = 2 * x * y
  • 23. AST interpretation Binary {     lhs: Binary {         lhs: Literal(2.0),         op: Mul,         rhs: Variable(X),     },     op: Mul,     rhs: Variable(Y), } z = 2 * x * y
  • 24. AST interpretation Expr ::Literal(lit) => *lit, Expr ::Variable(var) => var.calc(ctx), Expr ::Binary { lhs, op, rhs } => { let lhs = lhs.calc(ctx); let rhs = rhs.calc(ctx); op.apply(lhs, rhs) }
  • 25. AST interpretation AST: 28.13 ns 0 500 1,000 1,500 2,000 0 10 20 30 40 50 60 70 80 90 100
  • 27. Bytecode interpretation z = 2 * x * y 2 x * y *
  • 30. Bytecode interpretation z = 2 x * y * [ 2 ]
  • 31. Bytecode interpretation z = 2 x * y * [ 2, x ]
  • 32. Bytecode interpretation z = 2 x * y * [ 2 * x ]
  • 33. Bytecode interpretation z = 2 x * y * [ 2 * x, y ]
  • 34. Bytecode interpretation z = 2 x * y * [ (2 * x) * y ]
  • 35. Bytecode interpretation enum BytecodeOp { Literal(f64), Variable(Variable), BinOp(BinOp), }
  • 36. Bytecode interpretation Expr ::Literal(lit) => bc.push(BytecodeOp ::Literal(*lit)), Expr ::Variable(v) => bc.push(BytecodeOp ::Variable(*v)), Expr ::Binary { lhs, op, rhs } => { lhs.compile(bc); rhs.compile(bc); bc.push(BytecodeOp ::BinOp(*op)); }
  • 37. Bytecode interpretation for op in &self.ops { match op { BytecodeOp ::Literal(lit) => stack.push(*lit), BytecodeOp ::Variable(var) => stack.push(var.calc(ctx)), BytecodeOp ::BinOp(op) => { let rhs = stack.pop().unwrap(); let lhs = stack.pop().unwrap(); stack.push(op.apply(lhs, rhs)); } } }
  • 38. Bytecode interpretation AST: 28.13 ns Bytecode: 27.79 ns Bytecode compilation: 207.72 ns 0 500 1,000 1,500 2,000 0 10 20 30 40 50 60 70 80 90 100 AST Bytecode
  • 40. Closures kind-of-JIT pub type CompiledExpr = Box<dyn Fn(&Context) -> f64>;
  • 41. Closures kind-of-JIT Expr ::Literal(lit) => Box ::new(move |_ctx| lit), Expr ::Variable(var) => match var { Variable ::X => Box ::new(move |ctx| ctx.x), ... }, Expr ::Binary { lhs, op, rhs } => { let lhs = lhs.compile(); let rhs = rhs.compile(); match op { BinOp ::Add => Box ::new(move |ctx| lhs(ctx) + rhs(ctx)), ..., } }
  • 42. Closures kind-of-JIT AST: 28.13 ns Bytecode: 27.79 ns | Closure: 20.62 ns Bytecode compilation: 207.72 ns | Closure: 200.68 ns 0 500 1,000 1,500 2,000 0 10 20 30 40 50 60 70 80 90 100 AST Bytecode Closure
  • 45. JIT compilation: SSA form z = x * y + y * x
  • 46. JIT compilation: SSA form z = x * y + y * x
  • 47. JIT compilation: SSA form z = x * y + y * x define double @z(double %x, double %y) unnamed_addr #0 { %0 = fmul double %x, %y %1 = fmul double %y, %x %2 = fadd double %0, %1 ret double %2 }
  • 48. JIT compilation: SSA form z = x * y + y * x define double @z(double %x, double %y) unnamed_addr #0 { %0 = fmul double %x, %y %1 = fmul double %y, %x %2 = fadd double %0, %1 ret double %2 }
  • 49. JIT compilation: SSA form z = x * y + y * x define double @z(double %x, double %y) unnamed_addr #0 { %0 = fmul double %x, %y %1 = fadd double %0, %0 ret double %1 }
  • 50. LLVM from Rust • Raw C API bindings:
 https://github.com/tari/llvm-sys.rs • llvm-rs (high-level wrappers, unmaintained):
 https://github.com/TomBebbington/llvm-rs • Inkwell (high-level wrappers, maintained):
 https://github.com/TheDan64/inkwell
  • 51. LLVM from Rust let context = Context ::create(); let f64type = context.f64_type(); let builder = context.create_builder();
  • 52. LLVM from Rust let module = context.create_module("module"); let func = module.add_function( "jit_compiled", f64type.fn_type(&[ f64type.into(), f64type.into() ], false), None, );
  • 53. LLVM from Rust let block = func.append_basic_block("entry"); builder.position_at_end(&block); let result = ...; builder.build_return(Some(&result));
  • 54. LLVM from Rust Expr ::Literal(lit) => f64type.const_float(*lit), Expr ::Variable(var) => func.get_nth_param( ...).into_float_value(), Expr ::Binary { lhs, op, rhs } => { let lhs = lhs.compile( ...); let rhs = rhs.compile( ...); match op { BinOp ::Add => builder.build_float_add(lhs, rhs, "add"), ... } }
  • 55. LLVM from Rust let engine = module.create_jit_execution_engine( OptimizationLevel ::None )?; unsafe { engine.get_function("jit_compiled")? }
  • 56. LLVM from Rust EXC_BAD_ACCESS (code=1, address=0x6d) 0x0000000100324790 jit`llvm ::verifyModule(llvm ::Module const&, llvm ::raw_ostream*, bool*) + 121 0x0000000100180266 jit`LLVMVerifyModule + 119 0x000000010000b030 jit`verify(self =<unavailable>) at module.rs:634 0x000000010000b11a jit`clone(self =<unavailable>) at module.rs:1323 0x000000010000ad06 jit`create_jit_execution_engine(self =<unavailable>, opt_level =<unavailable>) at module.rs:502
  • 57. LLVM from Rust EXC_BAD_ACCESS (code=1, address=0x0) 0x000000010085c19e jit`llvm ::LLVMContext ::removeModule(llvm ::Module*) + 4 0x00000001008840f3 jit`llvm ::Module ::~Module() + 31 0x0000000100407123 jit`llvm ::MCJIT ::OwningModuleContainer ::freeModulePtrSet(llvm ::SmallPtrSet<l lvm ::Module*, 4u>&) + 97 0x0000000100407044 jit`llvm ::MCJIT ::OwningModuleContainer ::~OwningModuleContainer() + 18 0x0000000100404452 jit`llvm ::MCJIT ::~MCJIT() + 214 0x0000000100404654 jit`llvm ::MCJIT ::~MCJIT() + 14 0x0000000100008090 jit`_$LT$inkwell ..execution_engine ..ExecEngineInner$u20$as$u20$core ..ops ..dr op ..Drop$GT$ ::drop ::h86f518daac700ebf(self=0x00007ffeefbff310) at execution_engine.rs:421 0x0000000100001a05 jit`core ::ptr ::drop_in_place ::h91efe68b20f1058b((null)=0x00007ffeefbff310)at ptr.rs:59 0x0000000100001783 jit`core ::ptr ::drop_in_place ::h198dbc589dc5920e((null)=0x00007ffeefbff310)at ptr.rs:59
  • 58. LLVM JIT AST: 28.13 ns LLVM: 1.79 ns
  • 59. LLVM JIT AST: 28.13 ns LLVM: 1.79 ns LLVM compilation: 820.98 us
  • 60. LLVM JIT AST: 28.13 ns LLVM: 1.79 ns 1 10 100 1,000 10,000 100,000 1,000,000 10,000,000 100,000,000 1,000,000,000 1 10 100 1,000 10,000 100,000 1,000,000 10,000,000 AST LLVM LLVM compilation: 820.98 us
  • 61. LLVM JIT (optimised) AST: 28.13 ns LLVM: 1.79 ns / 1.50 ns LLVM compilation: 820.98 us / 1.79 ms 1 10 100 1,000 10,000 100,000 1,000,000 10,000,000 100,000,000 1,000,000,000 1 10 100 1,000 10,000 100,000 1,000,000 10,000,000 AST LLVM LLVM (opt)
  • 64. JIT compilation https://github.com/CraneStation/cranelift: 
 Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be useful elsewhere too. The initial planned uses that affected its design are:
  • 65. JIT compilation https://github.com/CraneStation/cranelift: 
 Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be useful elsewhere too. The initial planned uses that affected its design are: • WebAssembly compiler for the SpiderMonkey engine in Firefox.
  • 66. JIT compilation https://github.com/CraneStation/cranelift: 
 Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be useful elsewhere too. The initial planned uses that affected its design are: • WebAssembly compiler for the SpiderMonkey engine in Firefox. • Backend for the IonMonkey JavaScript JIT compiler in Firefox.
  • 67. JIT compilation https://github.com/CraneStation/cranelift: 
 Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be useful elsewhere too. The initial planned uses that affected its design are: • WebAssembly compiler for the SpiderMonkey engine in Firefox. • Backend for the IonMonkey JavaScript JIT compiler in Firefox. • Debug build backend for the Rust compiler.
  • 68. JIT compilation https://github.com/CraneStation/cranelift: 
 Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be useful elsewhere too. The initial planned uses that affected its design are: • WebAssembly compiler for the SpiderMonkey engine in Firefox. • Backend for the IonMonkey JavaScript JIT compiler in Firefox. • Debug build backend for the Rust compiler. ...
 Cranelift's APIs are not yet stable.
  • 69. Cranelift let builder = SimpleJITBuilder ::new(); let mut module: Module<SimpleJITBackend> = Module ::new(builder); let mut ctx = module.make_context(); let mut func_builder_ctx = FunctionBuilderContext ::new();
  • 70. Cranelift let sig = &mut ctx.func.signature; sig.params.push(AbiParam ::new(types ::F64)); // X sig.params.push(AbiParam ::new(types ::F64)); // Y sig.returns.push(AbiParam ::new(types ::F64));
  • 71. Cranelift let mut builder = FunctionBuilder ::new( &mut ctx.func, &mut func_builder_ctx );
  • 72. Cranelift let entry_ebb = builder.create_ebb(); builder.append_ebb_params_for_function_params(entry_ebb); builder.switch_to_block(entry_ebb); builder.seal_block(entry_ebb); let result = ...; builder.ins().return_(&[result]); builder.finalize();
  • 73. Cranelift Expr ::Literal(lit) => { let ins = builder.ins(); ins.f64const(Ieee64 ::with_float(*lit)) } Expr ::Variable(var) => builder.ebb_params(ebb)[ ...], Expr ::Binary { lhs, op, rhs } => { let lhs = lhs.compile( ...); let rhs = rhs.compile( ...); let ins = builder.ins(); match op { BinOp ::Add => ins.fadd(lhs, rhs), ... } }
  • 74. Cranelift let id = module.declare_function( "jit_compiled", Linkage ::Local, &ctx.func.signature )?; module.define_function(id, &mut ctx)?; module.clear_context(&mut ctx); module.finalize_definitions(); Ok(unsafe { ::std ::mem ::transmute(module.get_finalized_function(id)) })
  • 76. Cranelift JIT AST: 28.131 ns Cranelift: 2.36 ns
  • 77. Cranelift JIT AST: 28.131 ns Cranelift: 2.36 ns Cranelift compilation: 71.75 us
  • 78. Cranelift JIT AST: 28.131 ns Cranelift: 2.36 ns 1 10 100 1,000 10,000 100,000 1,000,000 10,000,000 100,000,000 1,000,000,000 1 10 100 1,000 10,000 100,000 1,000,000 10,000,000 AST Cranelift Cranelift compilation: 71.75 us
  • 79. Cranelift JIT AST: 28.131 ns LLVM: 1.79 ns | Cranelift: 2.36 ns 1 10 100 1,000 10,000 100,000 1,000,000 10,000,000 100,000,000 1,000,000,000 1 10 100 1,000 10,000 100,000 1,000,000 10,000,000 AST LLVM Cranelift LLVM compilation: 820.98 us | Cranelift: 71.75 us
  • 80. Full comparison 1 10 100 1,000 10,000 100,000 1,000,000 10,000,000 100,000,000 1,000,000,000 1 10 100 1,000 10,000 100,000 1,000,000 10,000,000 AST LLVM Cranelift Closure