SlideShare a Scribd company logo
VIRTUAL MACHINES
HOW DO THEY WORK? DO THEY WORK? LET’S FIND OUT!
INTRODUCTION
Bartosz Sypytkowski
▪ @Horusiath
▪ b.sypytkowski@gmail.com
▪ bartoszsypytkowski.com
 What virtual machines are all about.
 Stack vs Register based VMs
 Bytecode and interpreters
 Demo
AGENDA
MOTIVATION
VIRTUAL
MACHINE
SYSTEM VIRTUAL
MACHINE
PROCESS VIRTUAL
MACHINE
STACK
VS.
REGISTER
STACK
const.i32 3
const.i32 2
add.i32
Stack
STACK
const.i32 3
const.i32 2
add.i32
Stack
3
STACK
const.i32 3
const.i32 2
add.i32
Stack
2
3
STACK
const.i32 3
const.i32 2
add.i32
Stack
3
2
5
ACTIVATION
FRAMES arity
return address
function arg0
Activation
frame fib(5)
arity
return address
function arg0
Activation
frame fib(4)
Frame
pointer
BYTECODE
20 00 42 00 51 04 7e
42 01 05 20 00 20 00
42 01 7d 10 00 7e 0b
TEXT FORMAT BINARY FORMAT
get_local 0
i64.const 0
i64.eq
if i64
i64.const 1
else
get_local 0
get_local 0
i64.const 1
i64.sub
call 0
i64.mul
end
WHY NOT AST?
Intermediate representations
1. .NET CIL
2. JVM bytecode
3. WASM
4. LLVM IR
5. MemSQL bytecode
BYTECODE
INTERPRETER
VS.
COMPILER
ASSEMBLY NOT LOW-LEVEL LANGUAGE ANYMORE
BUT SERIOUSLY…
WHO USES BYTECODE INTERPRETER ON PROD?
COMPAR
ING
VECTOR
CLOCKS
CASE
STUDIES
• pre 1.9 – AST interpreter
• v1.9 (25 Dec 207) – YARV: bytecode interpreter
• v2.6 (25 Dec 2018) – JIT (experimental)
RUBY MRI
CPYTHON
• ATM still bytecode interpreted
• Bytecode generated and cached in .pyc files
MULTI TIER
CODE
EXECUTION
TIME
Query
parsing
interpreter
compiler
execution
execution
Switch
point
compilation
DEMO
A MINIMAL
VIRTUAL
MACHINE
1. Program to execute
2. Instruction counter / program counter
3. Virtual stack (LIFO)
4. Stack pointer
5. Frame pointer
REMARKS 1. Not optimal
2. No debugger
3. No error handling
4. No local/global variables
5. Only one primitive supporter (Int32)
SSVM
Bytecode
1. Constant
2. Add
3. Sub
4. Mul
5. JumpIfTrue
6. JumpIfFalse
7. Equal
8. LessThan
9. GreaterThan
10. Call
11. LoadArgument
12. Return
13. Halt
14. Print
SAMPLE
PROGRAM
// int fib(n) {
// if(n == 0) return 0;
LoadArgument 0 // 0 - load last function argument N
Constant 0 // 2 - put 0
Equals // 4 - check equality: N == 0
JumpIfFalse 10 // 5 - if they are NOT equal, goto 10
Constant 0 // 7 - otherwise put 0
Return // 9 - and return it
// if(n < 3) return 1;
LoadArgument 0 // 10 - load last function argument N
Constant 3 // 12 - put 3
LessThan // 14 - check if 3 is less than N
JumpIfFalse 20 // 15 - if 3 is NOT less than N, goto 20
Constant 1 // 17 - otherwise put 1
Return // 19 - and return it
// else return fib(n-1) + fib(n-2);
LoadArgument 0 // 20 - load last function argument N
Constant 1 // 22 - put 1
Sub // 24 - calculate: N-1, result is on the stack
Call fib 1 // 25 - call fib function with 1 arg. from the stack
LoadArgument 0 // 28 - load N again
Constant 2 // 30 - put 2
Sub // 32 - calculate: N-2, result is on the stack
Call fib 1 // 33 - call fib function with 1 arg. from the stack
Add // 36 - since 2 fibs pushed their ret values on the stack, just add them
Return // 37 - return from procedure
// entrypoint - main function
Constant 6 // 38 - put 6
Call fib 1 // 40 - call function: fib(arg) where arg = 6;
Print // 43 - print result
Halt // 44 - stop program
Virtual Machine
typedef struct {
int* code; // program opcodes
int* stack; // virtual stack
int pc; // program counter
int sp; // stack pointer
int fp; // frame pointer
} VM;
// push value on top of the stack
#define PUSH(vm, v) vm->stack[++vm->sp] = v
// pop value from top of the stack
#define POP(vm) vm->stack[vm->sp--]
// get next bytecode
#define NEXT(vm) vm->code[vm->pc++]
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
Interpreter Loop
void (*op_handles[])(VM*) = {
// opcode function pointers
};
void vm_run(VM* vm) {
do {
int opcode = NEXT(vm);
if (opcode == Halt) {
return;
}
op_handles[opcode](vm);
} while(1);
}
Constant X
void op_constant(VM* vm) {
int x = NEXT(vm);
PUSH(vm, x);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
Constant X
void op_constant(VM* vm) {
int x = NEXT(vm);
PUSH(vm, x);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
x
Constant X
void op_constant(VM* vm) {
int x = NEXT(vm);
PUSH(vm, x);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
x
Print
void op_print(VM* vm) {
int x = POP(vm);
printf(“%dn”, x);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
x
Print
void op_print(VM* vm) {
int x = POP(vm);
printf(“%dn”, x);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
x
Print
void op_print(VM* vm) {
int x = POP(vm);
printf(“%dn”, x);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
x
STDOUT
Add / Sub / Mul / Div
void op_add(VM* vm) {
int b = POP(vm);
int a = POP(vm);
//TODO: check overflow
PUSH(vm, a + b);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
a
b
Add / Sub / Mul / Div
void op_add(VM* vm) {
int b = POP(vm);
int a = POP(vm);
//TODO: check overflow
PUSH(vm, a + b);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
a
b
Add / Sub / Mul / Div
void op_add(VM* vm) {
int b = POP(vm);
int a = POP(vm);
//TODO: check overflow
PUSH(vm, a + b);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
a
b
Add / Sub / Mul / Div
void op_add(VM* vm) {
int b = POP(vm);
int a = POP(vm);
//TODO: check overflow
PUSH(vm, a + b);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
a + b
Equal / Less / etc.
void op_eq(VM* vm) {
int b = POP(vm);
int a = POP(vm);
PUSH(vm, a == b ? 1 : 0);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
a
b
Equal / Less / etc.
void op_eq(VM* vm) {
int b = POP(vm);
int a = POP(vm);
PUSH(vm, a == b ? 1 : 0);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
a
b
Equal / Less / etc.
void op_eq(VM* vm) {
int b = POP(vm);
int a = POP(vm);
PUSH(vm, a == b ? 1 : 0);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
a
b
Equal / Less / etc.
void op_eq(VM* vm) {
int b = POP(vm);
int a = POP(vm);
PUSH(vm, a == b ? 1 : 0);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
1
Conditional
Branches
void op_jmp_eq(VM* vm) {
int address = NEXT(vm);
if (POP(vm)) {
vm->pc = address;
}
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
1
Conditional
Branches
void op_jmp_eq(VM* vm) {
int address = NEXT(vm);
if (POP(vm)) {
vm->pc = address;
}
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
1
addr
Conditional
Branches
void op_jmp_eq(VM* vm) {
int address = NEXT(vm);
if (POP(vm)) {
vm->pc = address;
}
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
1
addr
Conditional
Branches
void op_jmp_eq(VM* vm) {
int address = NEXT(vm);
if (POP(vm)) {
vm->pc = address;
}
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
addr
Call
void op_call(VM* vm) {
int addr = NEXT(vm);
int argc = NEXT(vm);
PUSH(vm, argc);
PUSH(vm, vm->fp);
PUSH(vm, vm->pc);
vm->fp = vm->sp;
vm->pc = addr;
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
Call
void op_call(VM* vm) {
int addr = NEXT(vm);
int argc = NEXT(vm);
PUSH(vm, argc);
PUSH(vm, vm->fp);
PUSH(vm, vm->pc);
vm->fp = vm->sp;
vm->pc = addr;
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
addr
Call
void op_call(VM* vm) {
int addr = NEXT(vm);
int argc = NEXT(vm);
PUSH(vm, argc);
PUSH(vm, vm->fp);
PUSH(vm, vm->pc);
vm->fp = vm->sp;
vm->pc = addr;
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
addr
argc
Call
void op_call(VM* vm) {
int addr = NEXT(vm);
int argc = NEXT(vm);
PUSH(vm, argc);
PUSH(vm, vm->fp);
PUSH(vm, vm->pc);
vm->fp = vm->sp;
vm->pc = addr;
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
addr
argc
Call
void op_call(VM* vm) {
int addr = NEXT(vm);
int argc = NEXT(vm);
PUSH(vm, argc);
PUSH(vm, vm->fp);
PUSH(vm, vm->pc);
vm->fp = vm->sp;
vm->pc = addr;
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
addr
argc
fp
Call
void op_call(VM* vm) {
int addr = NEXT(vm);
int argc = NEXT(vm);
PUSH(vm, argc);
PUSH(vm, vm->fp);
PUSH(vm, vm->pc);
vm->fp = vm->sp;
vm->pc = addr;
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
addr
argc
fp
pc
Call
void op_call(VM* vm) {
int addr = NEXT(vm);
int argc = NEXT(vm);
PUSH(vm, argc);
PUSH(vm, vm->fp);
PUSH(vm, vm->pc);
vm->fp = vm->sp;
vm->pc = addr;
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
addr
argc
fp
pc
activation
frame
Call
void op_call(VM* vm) {
int addr = NEXT(vm);
int argc = NEXT(vm);
PUSH(vm, argc);
PUSH(vm, vm->fp);
PUSH(vm, vm->pc);
vm->fp = vm->sp;
vm->pc = addr;
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
addr
argc
fp
pc
LoadArgument
void op_lda(VM* vm) {
int argx = NEXT(vm);
int v = vm->stack[vm->fp-argx-3];
PUSH(vm, v);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
arg0
argc
fp
pc
LoadArgument
void op_lda(VM* vm) {
int argx = NEXT(vm);
int v = vm->stack[vm->fp-argx-3];
PUSH(vm, v);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
arg0
argc
fp
pc
argx
LoadArgument
void op_lda(VM* vm) {
int argx = NEXT(vm);
int v = vm->stack[vm->fp-argx-3];
PUSH(vm, v);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
arg0
argc
fp
pc
v
frame pointer – 3 - argx
LoadArgument
void op_lda(VM* vm) {
int argx = NEXT(vm);
int v = vm->stack[vm->fp-argx-3];
PUSH(vm, v);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
arg0
argc
fp
pc
v
Return
void op_ret(VM* vm) {
int result = POP(vm);
vm->pc = POP(vm);
vm->fp = POP(vm);
int argc = POP(vm);
vm->sp -= argc;
PUSH(vm, result);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
arg0
argc
fp
pc
result
Return
void op_ret(VM* vm) {
int result = POP(vm);
vm->pc = POP(vm);
vm->fp = POP(vm);
int argc = POP(vm);
vm->sp -= argc;
PUSH(vm, result);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
arg0
argc
fp
pc
result
Return
void op_ret(VM* vm) {
int result = POP(vm);
vm->pc = POP(vm);
vm->fp = POP(vm);
int argc = POP(vm);
vm->sp -= argc;
PUSH(vm, result);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
arg0
argc
fp
pc
result
Return
void op_ret(VM* vm) {
int result = POP(vm);
vm->pc = POP(vm);
vm->fp = POP(vm);
int argc = POP(vm);
vm->sp -= argc;
PUSH(vm, result);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
arg0
argc
fp
result
Return
void op_ret(VM* vm) {
int result = POP(vm);
vm->pc = POP(vm);
vm->fp = POP(vm);
int argc = POP(vm);
vm->sp -= argc;
PUSH(vm, result);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
arg0
argc
result
Return
void op_ret(VM* vm) {
int result = POP(vm);
vm->pc = POP(vm);
vm->fp = POP(vm);
int argc = POP(vm);
vm->sp -= argc;
PUSH(vm, result);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
arg0
result
Return
void op_ret(VM* vm) {
int result = POP(vm);
vm->pc = POP(vm);
vm->fp = POP(vm);
int argc = POP(vm);
vm->sp -= argc;
PUSH(vm, result);
}
stack
20 00 42
00 51 04
7e 42 01
05 20 00
20 00 42
01 7d 10
00 7e 0b
code
stack pointer
program pointer
frame pointer
result
SUMMARY
 Crafting interpreters: https://craftinginterpreters.com/contents.html#a-bytecode-virtual-machine
 Register-based VM: https://github.com/skx/simple.vm
 Konrad Kokosa: “Pro .NET Memory Management”
 Database query compilation: https://www.youtube.com/watch?v=baOAbOdcnxs
 Adding new CIL instruction to .NET: https://mattwarren.org/2017/05/19/Adding-a-new-Bytecode-
Instruction-to-the-CLR/
 and many many more…
REFERENCES
THANK YOU

More Related Content

What's hot

Nefrock勉強会 in大岡山「FPGAでゲーム機を作ろう!の会」Day4
Nefrock勉強会 in大岡山「FPGAでゲーム機を作ろう!の会」Day4Nefrock勉強会 in大岡山「FPGAでゲーム機を作ろう!の会」Day4
Nefrock勉強会 in大岡山「FPGAでゲーム機を作ろう!の会」Day4
Kaku Tomohiro
 
Infix to-postfix examples
Infix to-postfix examplesInfix to-postfix examples
Infix to-postfix examples
mua99
 
VLSI experiments II
VLSI experiments IIVLSI experiments II
VLSI experiments II
Gouthaman V
 
Network lab manual
Network lab manualNetwork lab manual
Network lab manual
Prabhu D
 
Network lap pgms 7th semester
Network lap pgms 7th semesterNetwork lap pgms 7th semester
Network lap pgms 7th semester
DOSONKA Group
 

What's hot (20)

C++ Programming - 11th Study
C++ Programming - 11th StudyC++ Programming - 11th Study
C++ Programming - 11th Study
 
Nefrock勉強会 in大岡山「FPGAでゲーム機を作ろう!の会」Day4
Nefrock勉強会 in大岡山「FPGAでゲーム機を作ろう!の会」Day4Nefrock勉強会 in大岡山「FPGAでゲーム機を作ろう!の会」Day4
Nefrock勉強会 in大岡山「FPGAでゲーム機を作ろう!の会」Day4
 
Lecture05
Lecture05Lecture05
Lecture05
 
Infix to-postfix examples
Infix to-postfix examplesInfix to-postfix examples
Infix to-postfix examples
 
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java scriptCodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
 
Cse presentation ratul
Cse presentation ratulCse presentation ratul
Cse presentation ratul
 
VLSI experiments II
VLSI experiments IIVLSI experiments II
VLSI experiments II
 
C++ Programming - 4th Study
C++ Programming - 4th StudyC++ Programming - 4th Study
C++ Programming - 4th Study
 
Buffer OverFlow
Buffer OverFlowBuffer OverFlow
Buffer OverFlow
 
C++ file
C++ fileC++ file
C++ file
 
C++ Programming - 2nd Study
C++ Programming - 2nd StudyC++ Programming - 2nd Study
C++ Programming - 2nd Study
 
verilog code
verilog codeverilog code
verilog code
 
Unit2 C
Unit2 CUnit2 C
Unit2 C
 
Diving into HHVM Extensions (Brno PHP Conference 2015)
Diving into HHVM Extensions (Brno PHP Conference 2015)Diving into HHVM Extensions (Brno PHP Conference 2015)
Diving into HHVM Extensions (Brno PHP Conference 2015)
 
Network lab manual
Network lab manualNetwork lab manual
Network lab manual
 
week-16x
week-16xweek-16x
week-16x
 
C++ Programming - 1st Study
C++ Programming - 1st StudyC++ Programming - 1st Study
C++ Programming - 1st Study
 
Swift: Apple's New Programming Language for iOS and OS X
Swift: Apple's New Programming Language for iOS and OS XSwift: Apple's New Programming Language for iOS and OS X
Swift: Apple's New Programming Language for iOS and OS X
 
Network lap pgms 7th semester
Network lap pgms 7th semesterNetwork lap pgms 7th semester
Network lap pgms 7th semester
 
Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to Javascript
 

Similar to Virtual machines - how they work

Bytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreterBytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreter
akaptur
 
COMP360 Assembler Write an assembler that reads the source code of an.pdf
COMP360 Assembler Write an assembler that reads the source code of an.pdfCOMP360 Assembler Write an assembler that reads the source code of an.pdf
COMP360 Assembler Write an assembler that reads the source code of an.pdf
fazalenterprises
 
Vectorization on x86: all you need to know
Vectorization on x86: all you need to knowVectorization on x86: all you need to know
Vectorization on x86: all you need to know
Roberto Agostino Vitillo
 

Similar to Virtual machines - how they work (20)

Bytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreterBytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreter
 
Checking Oracle VM VirtualBox. Part 1
Checking Oracle VM VirtualBox. Part 1Checking Oracle VM VirtualBox. Part 1
Checking Oracle VM VirtualBox. Part 1
 
Wap to implement bitwise operators
Wap to implement bitwise operatorsWap to implement bitwise operators
Wap to implement bitwise operators
 
Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4
 
COMP360 Assembler Write an assembler that reads the source code of an.pdf
COMP360 Assembler Write an assembler that reads the source code of an.pdfCOMP360 Assembler Write an assembler that reads the source code of an.pdf
COMP360 Assembler Write an assembler that reads the source code of an.pdf
 
EcmaScript unchained
EcmaScript unchainedEcmaScript unchained
EcmaScript unchained
 
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
 
Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and C
 
node-rpi-ws281x
node-rpi-ws281xnode-rpi-ws281x
node-rpi-ws281x
 
Spectre(v1%2 fv2%2fv4) v.s. meltdown(v3)
Spectre(v1%2 fv2%2fv4) v.s. meltdown(v3)Spectre(v1%2 fv2%2fv4) v.s. meltdown(v3)
Spectre(v1%2 fv2%2fv4) v.s. meltdown(v3)
 
Ethereum virtual machine for Developers Part 1
Ethereum virtual machine for Developers Part 1Ethereum virtual machine for Developers Part 1
Ethereum virtual machine for Developers Part 1
 
OpenMP
OpenMPOpenMP
OpenMP
 
ITGM #9 - Коварный CodeType, или от segfault'а к работающему коду
ITGM #9 - Коварный CodeType, или от segfault'а к работающему кодуITGM #9 - Коварный CodeType, или от segfault'а к работающему коду
ITGM #9 - Коварный CodeType, или от segfault'а к работающему коду
 
Application of Stacks
Application of StacksApplication of Stacks
Application of Stacks
 
2.1 ### uVision Project, (C) Keil Software .docx
2.1   ### uVision Project, (C) Keil Software    .docx2.1   ### uVision Project, (C) Keil Software    .docx
2.1 ### uVision Project, (C) Keil Software .docx
 
Vectorization on x86: all you need to know
Vectorization on x86: all you need to knowVectorization on x86: all you need to know
Vectorization on x86: all you need to know
 
Reverse Engineering Dojo: Enhancing Assembly Reading Skills
Reverse Engineering Dojo: Enhancing Assembly Reading SkillsReverse Engineering Dojo: Enhancing Assembly Reading Skills
Reverse Engineering Dojo: Enhancing Assembly Reading Skills
 
Roberto Gallea: Workshop Arduino, giorno #2 Arduino + Processing
Roberto Gallea: Workshop Arduino, giorno #2 Arduino + ProcessingRoberto Gallea: Workshop Arduino, giorno #2 Arduino + Processing
Roberto Gallea: Workshop Arduino, giorno #2 Arduino + Processing
 
Arduino for Beginners
Arduino for BeginnersArduino for Beginners
Arduino for Beginners
 
When RV Meets CEP (RV 2016 Tutorial)
When RV Meets CEP (RV 2016 Tutorial)When RV Meets CEP (RV 2016 Tutorial)
When RV Meets CEP (RV 2016 Tutorial)
 

More from Bartosz Sypytkowski

More from Bartosz Sypytkowski (14)

Postgres indexes: how to make them work for your application
Postgres indexes: how to make them work for your applicationPostgres indexes: how to make them work for your application
Postgres indexes: how to make them work for your application
 
How do databases perform live backups and point-in-time recovery
How do databases perform live backups and point-in-time recoveryHow do databases perform live backups and point-in-time recovery
How do databases perform live backups and point-in-time recovery
 
Scaling connections in peer-to-peer applications
Scaling connections in peer-to-peer applicationsScaling connections in peer-to-peer applications
Scaling connections in peer-to-peer applications
 
Rich collaborative data structures for everyone
Rich collaborative data structures for everyoneRich collaborative data structures for everyone
Rich collaborative data structures for everyone
 
Postgres indexes
Postgres indexesPostgres indexes
Postgres indexes
 
Behind modern concurrency primitives
Behind modern concurrency primitivesBehind modern concurrency primitives
Behind modern concurrency primitives
 
Collaborative eventsourcing
Collaborative eventsourcingCollaborative eventsourcing
Collaborative eventsourcing
 
Behind modern concurrency primitives
Behind modern concurrency primitivesBehind modern concurrency primitives
Behind modern concurrency primitives
 
Living in eventually consistent reality
Living in eventually consistent realityLiving in eventually consistent reality
Living in eventually consistent reality
 
Short story of time
Short story of timeShort story of time
Short story of time
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streams
 
Collaborative text editing
Collaborative text editingCollaborative text editing
Collaborative text editing
 
The last mile from db to disk
The last mile from db to diskThe last mile from db to disk
The last mile from db to disk
 
GraphQL - an elegant weapon... for more civilized age
GraphQL - an elegant weapon... for more civilized ageGraphQL - an elegant weapon... for more civilized age
GraphQL - an elegant weapon... for more civilized age
 

Recently uploaded

AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
Alluxio, Inc.
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 

Recently uploaded (20)

Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 
AI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning FrameworkAI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning Framework
 
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Studiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting softwareStudiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting software
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
 
GraphAware - Transforming policing with graph-based intelligence analysis
GraphAware - Transforming policing with graph-based intelligence analysisGraphAware - Transforming policing with graph-based intelligence analysis
GraphAware - Transforming policing with graph-based intelligence analysis
 
AI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in MichelangeloAI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in Michelangelo
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
iGaming Platform & Lottery Solutions by Skilrock
iGaming Platform & Lottery Solutions by SkilrockiGaming Platform & Lottery Solutions by Skilrock
iGaming Platform & Lottery Solutions by Skilrock
 
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
Agnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in KrakówAgnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in Kraków
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
 

Virtual machines - how they work

  • 1. VIRTUAL MACHINES HOW DO THEY WORK? DO THEY WORK? LET’S FIND OUT!
  • 2. INTRODUCTION Bartosz Sypytkowski ▪ @Horusiath ▪ b.sypytkowski@gmail.com ▪ bartoszsypytkowski.com
  • 3.  What virtual machines are all about.  Stack vs Register based VMs  Bytecode and interpreters  Demo AGENDA
  • 12. ACTIVATION FRAMES arity return address function arg0 Activation frame fib(5) arity return address function arg0 Activation frame fib(4) Frame pointer
  • 14. 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b TEXT FORMAT BINARY FORMAT get_local 0 i64.const 0 i64.eq if i64 i64.const 1 else get_local 0 get_local 0 i64.const 1 i64.sub call 0 i64.mul end
  • 16. Intermediate representations 1. .NET CIL 2. JVM bytecode 3. WASM 4. LLVM IR 5. MemSQL bytecode BYTECODE
  • 18. ASSEMBLY NOT LOW-LEVEL LANGUAGE ANYMORE
  • 19. BUT SERIOUSLY… WHO USES BYTECODE INTERPRETER ON PROD?
  • 20. COMPAR ING VECTOR CLOCKS CASE STUDIES • pre 1.9 – AST interpreter • v1.9 (25 Dec 207) – YARV: bytecode interpreter • v2.6 (25 Dec 2018) – JIT (experimental) RUBY MRI CPYTHON • ATM still bytecode interpreted • Bytecode generated and cached in .pyc files
  • 22. DEMO
  • 23. A MINIMAL VIRTUAL MACHINE 1. Program to execute 2. Instruction counter / program counter 3. Virtual stack (LIFO) 4. Stack pointer 5. Frame pointer
  • 24. REMARKS 1. Not optimal 2. No debugger 3. No error handling 4. No local/global variables 5. Only one primitive supporter (Int32)
  • 25. SSVM Bytecode 1. Constant 2. Add 3. Sub 4. Mul 5. JumpIfTrue 6. JumpIfFalse 7. Equal 8. LessThan 9. GreaterThan 10. Call 11. LoadArgument 12. Return 13. Halt 14. Print
  • 26. SAMPLE PROGRAM // int fib(n) { // if(n == 0) return 0; LoadArgument 0 // 0 - load last function argument N Constant 0 // 2 - put 0 Equals // 4 - check equality: N == 0 JumpIfFalse 10 // 5 - if they are NOT equal, goto 10 Constant 0 // 7 - otherwise put 0 Return // 9 - and return it // if(n < 3) return 1; LoadArgument 0 // 10 - load last function argument N Constant 3 // 12 - put 3 LessThan // 14 - check if 3 is less than N JumpIfFalse 20 // 15 - if 3 is NOT less than N, goto 20 Constant 1 // 17 - otherwise put 1 Return // 19 - and return it // else return fib(n-1) + fib(n-2); LoadArgument 0 // 20 - load last function argument N Constant 1 // 22 - put 1 Sub // 24 - calculate: N-1, result is on the stack Call fib 1 // 25 - call fib function with 1 arg. from the stack LoadArgument 0 // 28 - load N again Constant 2 // 30 - put 2 Sub // 32 - calculate: N-2, result is on the stack Call fib 1 // 33 - call fib function with 1 arg. from the stack Add // 36 - since 2 fibs pushed their ret values on the stack, just add them Return // 37 - return from procedure // entrypoint - main function Constant 6 // 38 - put 6 Call fib 1 // 40 - call function: fib(arg) where arg = 6; Print // 43 - print result Halt // 44 - stop program
  • 27. Virtual Machine typedef struct { int* code; // program opcodes int* stack; // virtual stack int pc; // program counter int sp; // stack pointer int fp; // frame pointer } VM; // push value on top of the stack #define PUSH(vm, v) vm->stack[++vm->sp] = v // pop value from top of the stack #define POP(vm) vm->stack[vm->sp--] // get next bytecode #define NEXT(vm) vm->code[vm->pc++] stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer
  • 28. Interpreter Loop void (*op_handles[])(VM*) = { // opcode function pointers }; void vm_run(VM* vm) { do { int opcode = NEXT(vm); if (opcode == Halt) { return; } op_handles[opcode](vm); } while(1); }
  • 29. Constant X void op_constant(VM* vm) { int x = NEXT(vm); PUSH(vm, x); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer
  • 30. Constant X void op_constant(VM* vm) { int x = NEXT(vm); PUSH(vm, x); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer x
  • 31. Constant X void op_constant(VM* vm) { int x = NEXT(vm); PUSH(vm, x); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer x
  • 32. Print void op_print(VM* vm) { int x = POP(vm); printf(“%dn”, x); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer x
  • 33. Print void op_print(VM* vm) { int x = POP(vm); printf(“%dn”, x); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer x
  • 34. Print void op_print(VM* vm) { int x = POP(vm); printf(“%dn”, x); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer x STDOUT
  • 35. Add / Sub / Mul / Div void op_add(VM* vm) { int b = POP(vm); int a = POP(vm); //TODO: check overflow PUSH(vm, a + b); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer a b
  • 36. Add / Sub / Mul / Div void op_add(VM* vm) { int b = POP(vm); int a = POP(vm); //TODO: check overflow PUSH(vm, a + b); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer a b
  • 37. Add / Sub / Mul / Div void op_add(VM* vm) { int b = POP(vm); int a = POP(vm); //TODO: check overflow PUSH(vm, a + b); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer a b
  • 38. Add / Sub / Mul / Div void op_add(VM* vm) { int b = POP(vm); int a = POP(vm); //TODO: check overflow PUSH(vm, a + b); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer a + b
  • 39. Equal / Less / etc. void op_eq(VM* vm) { int b = POP(vm); int a = POP(vm); PUSH(vm, a == b ? 1 : 0); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer a b
  • 40. Equal / Less / etc. void op_eq(VM* vm) { int b = POP(vm); int a = POP(vm); PUSH(vm, a == b ? 1 : 0); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer a b
  • 41. Equal / Less / etc. void op_eq(VM* vm) { int b = POP(vm); int a = POP(vm); PUSH(vm, a == b ? 1 : 0); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer a b
  • 42. Equal / Less / etc. void op_eq(VM* vm) { int b = POP(vm); int a = POP(vm); PUSH(vm, a == b ? 1 : 0); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer 1
  • 43. Conditional Branches void op_jmp_eq(VM* vm) { int address = NEXT(vm); if (POP(vm)) { vm->pc = address; } } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer 1
  • 44. Conditional Branches void op_jmp_eq(VM* vm) { int address = NEXT(vm); if (POP(vm)) { vm->pc = address; } } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer 1 addr
  • 45. Conditional Branches void op_jmp_eq(VM* vm) { int address = NEXT(vm); if (POP(vm)) { vm->pc = address; } } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer 1 addr
  • 46. Conditional Branches void op_jmp_eq(VM* vm) { int address = NEXT(vm); if (POP(vm)) { vm->pc = address; } } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer addr
  • 47. Call void op_call(VM* vm) { int addr = NEXT(vm); int argc = NEXT(vm); PUSH(vm, argc); PUSH(vm, vm->fp); PUSH(vm, vm->pc); vm->fp = vm->sp; vm->pc = addr; } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer
  • 48. Call void op_call(VM* vm) { int addr = NEXT(vm); int argc = NEXT(vm); PUSH(vm, argc); PUSH(vm, vm->fp); PUSH(vm, vm->pc); vm->fp = vm->sp; vm->pc = addr; } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer addr
  • 49. Call void op_call(VM* vm) { int addr = NEXT(vm); int argc = NEXT(vm); PUSH(vm, argc); PUSH(vm, vm->fp); PUSH(vm, vm->pc); vm->fp = vm->sp; vm->pc = addr; } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer addr argc
  • 50. Call void op_call(VM* vm) { int addr = NEXT(vm); int argc = NEXT(vm); PUSH(vm, argc); PUSH(vm, vm->fp); PUSH(vm, vm->pc); vm->fp = vm->sp; vm->pc = addr; } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer addr argc
  • 51. Call void op_call(VM* vm) { int addr = NEXT(vm); int argc = NEXT(vm); PUSH(vm, argc); PUSH(vm, vm->fp); PUSH(vm, vm->pc); vm->fp = vm->sp; vm->pc = addr; } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer addr argc fp
  • 52. Call void op_call(VM* vm) { int addr = NEXT(vm); int argc = NEXT(vm); PUSH(vm, argc); PUSH(vm, vm->fp); PUSH(vm, vm->pc); vm->fp = vm->sp; vm->pc = addr; } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer addr argc fp pc
  • 53. Call void op_call(VM* vm) { int addr = NEXT(vm); int argc = NEXT(vm); PUSH(vm, argc); PUSH(vm, vm->fp); PUSH(vm, vm->pc); vm->fp = vm->sp; vm->pc = addr; } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer addr argc fp pc activation frame
  • 54. Call void op_call(VM* vm) { int addr = NEXT(vm); int argc = NEXT(vm); PUSH(vm, argc); PUSH(vm, vm->fp); PUSH(vm, vm->pc); vm->fp = vm->sp; vm->pc = addr; } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer addr argc fp pc
  • 55. LoadArgument void op_lda(VM* vm) { int argx = NEXT(vm); int v = vm->stack[vm->fp-argx-3]; PUSH(vm, v); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer arg0 argc fp pc
  • 56. LoadArgument void op_lda(VM* vm) { int argx = NEXT(vm); int v = vm->stack[vm->fp-argx-3]; PUSH(vm, v); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer arg0 argc fp pc argx
  • 57. LoadArgument void op_lda(VM* vm) { int argx = NEXT(vm); int v = vm->stack[vm->fp-argx-3]; PUSH(vm, v); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer arg0 argc fp pc v frame pointer – 3 - argx
  • 58. LoadArgument void op_lda(VM* vm) { int argx = NEXT(vm); int v = vm->stack[vm->fp-argx-3]; PUSH(vm, v); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer arg0 argc fp pc v
  • 59. Return void op_ret(VM* vm) { int result = POP(vm); vm->pc = POP(vm); vm->fp = POP(vm); int argc = POP(vm); vm->sp -= argc; PUSH(vm, result); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer arg0 argc fp pc result
  • 60. Return void op_ret(VM* vm) { int result = POP(vm); vm->pc = POP(vm); vm->fp = POP(vm); int argc = POP(vm); vm->sp -= argc; PUSH(vm, result); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer arg0 argc fp pc result
  • 61. Return void op_ret(VM* vm) { int result = POP(vm); vm->pc = POP(vm); vm->fp = POP(vm); int argc = POP(vm); vm->sp -= argc; PUSH(vm, result); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer arg0 argc fp pc result
  • 62. Return void op_ret(VM* vm) { int result = POP(vm); vm->pc = POP(vm); vm->fp = POP(vm); int argc = POP(vm); vm->sp -= argc; PUSH(vm, result); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer arg0 argc fp result
  • 63. Return void op_ret(VM* vm) { int result = POP(vm); vm->pc = POP(vm); vm->fp = POP(vm); int argc = POP(vm); vm->sp -= argc; PUSH(vm, result); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer arg0 argc result
  • 64. Return void op_ret(VM* vm) { int result = POP(vm); vm->pc = POP(vm); vm->fp = POP(vm); int argc = POP(vm); vm->sp -= argc; PUSH(vm, result); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer arg0 result
  • 65. Return void op_ret(VM* vm) { int result = POP(vm); vm->pc = POP(vm); vm->fp = POP(vm); int argc = POP(vm); vm->sp -= argc; PUSH(vm, result); } stack 20 00 42 00 51 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b code stack pointer program pointer frame pointer result
  • 67.  Crafting interpreters: https://craftinginterpreters.com/contents.html#a-bytecode-virtual-machine  Register-based VM: https://github.com/skx/simple.vm  Konrad Kokosa: “Pro .NET Memory Management”  Database query compilation: https://www.youtube.com/watch?v=baOAbOdcnxs  Adding new CIL instruction to .NET: https://mattwarren.org/2017/05/19/Adding-a-new-Bytecode- Instruction-to-the-CLR/  and many many more… REFERENCES