Slide 1

Slide 1 text

1 Joshua Thijssen jaytaph an introduction into compilers, interpreters and JIT From source to code

Slide 2

Slide 2 text

Computers are really dumb. 2

Slide 3

Slide 3 text

They do not understand: 3 http://blog.ruslans.com/2012_11_01_archive.html

Slide 4

Slide 4 text

56e9 5200 4641 4c46 5245 0020 0102 0001 e002 4000 f00b 0009 0012 0002 0000 0000 0000 0000 0000 ef29 adbe 52de 4641 4c46 5245 2020 2020 4146 3154 2032 2020 6152 6666 656c 4f72 3a53 0020 414e 454d 2053 2020 4144 0054 4900 fa37 c031 d88e c08e d08e 00bc fb7c 3ebe e87c 0117 00bb b880 0001 12bf e800 00a3 00bb b8a4 0013 0ebf e800 0097 bffc a400 4abe b97c 000b f357 5fa6 0d74 c781 0020 ff81 c000 ea76 fde9 8bff 1c45 55a3 bb7c c000 458b 501a abe8 5800 c381 0200 8953 d1c3 01eb 8bc3 0097 5b80 01a9 7500 8107 ffe2 e90f 0003 eac1 8104 f0fa 890f 72d0 31d4 cdc0 001a 5716 e87c 0088 ff25 8900 bec3 c000 f789 3e03 7c55 0ab4 2588 cbfe 0f74 39ac 7cfe be03 c000 0a3c f074 f1e9 56ff b046 3a0a 7504 c6f9 0004 e85e 006b fde9 50ff 0ae8 5800 c381 0200 4f40 f375 89c3 81e5 08ec be00 0012 d231 f6f7 c2fe 5688 beff 0002 d231 f6f7 5688 89fe fc46 01b0 6e8a 8afc fe76 4e8a b2ff b400 cd02 8913 c3ec 022d 3100 b1c9 f701 05e1 0021 bee8 c3ff 57a1 ba7c 8405 e2f7 063b 7c57 0375 d488 a340 7c57 d089 acc3 003c 0a74 0eb4 07bb cd00 e910 fff1 90c3 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 aa55 4

Slide 5

Slide 5 text

56e9 5200 4641 4c46 5245 0020 0102 0001 e002 4000 f00b 0009 0012 0002 0000 0000 0000 0000 0000 ef29 adbe 52de 4641 4c46 5245 2020 2020 4146 3154 2032 2020 6152 6666 656c 4f72 3a53 0020 414e 454d 2053 2020 4144 0054 4900 fa37 c031 d88e c08e d08e 00bc fb7c 3ebe e87c 0117 00bb b880 0001 12bf e800 00a3 00bb b8a4 0013 0ebf e800 0097 bffc a400 4abe b97c 000b f357 5fa6 0d74 c781 0020 ff81 c000 ea76 fde9 8bff 1c45 55a3 bb7c c000 458b 501a abe8 5800 c381 0200 8953 d1c3 01eb 8bc3 0097 5b80 01a9 7500 8107 ffe2 e90f 0003 eac1 8104 f0fa 890f 72d0 31d4 cdc0 001a 5716 e87c 0088 ff25 8900 bec3 c000 f789 3e03 7c55 0ab4 2588 cbfe 0f74 39ac 7cfe be03 c000 0a3c f074 f1e9 56ff b046 3a0a 7504 c6f9 0004 e85e 006b fde9 50ff 0ae8 5800 c381 0200 4f40 f375 89c3 81e5 08ec be00 0012 d231 f6f7 c2fe 5688 beff 0002 d231 f6f7 5688 89fe fc46 01b0 6e8a 8afc fe76 4e8a b2ff b400 cd02 8913 c3ec 022d 3100 b1c9 f701 05e1 0021 bee8 c3ff 57a1 ba7c 8405 e2f7 063b 7c57 0375 d488 a340 7c57 d089 acc3 003c 0a74 0eb4 07bb cd00 e910 fff1 90c3 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 aa55 4

Slide 6

Slide 6 text

5 mov ax, [di + 0x1A] ; Here starts FAT clusters loadClusters: push ax call ReadCluster pop ax add bx, 512 ; Next sector push bx mov bx, ax shr bx, 1 add bx, ax mov dx, [0x8000 + bx] pop bx test ax, 0x01 jnz oddCluster evenCluster: and dx, 0x0FFF jmp testCluster oddCluster: shr dx, 4 testCluster: cmp dx, 0xFF0 mov ax, dx jb loadClusters https://github.com/domcode/rafflers/blob/master/jaytaph-bootsector-asm/raffler.S

Slide 7

Slide 7 text

1 /** 2 * Return bucket for specified key 3 */ 4 static t_hash_table_bucket *find_bucket(t_hash_table *ht, t_hash_key *key) { 5 // Locate the hash value in the bucket list. 6 hash_t hash_value = ht_hash(ht, key); 7 hash_t hash_value_capped = hash_value % ht->bucket_count; 8 if (ht->bucket_list[hash_value_capped] == NULL) { 9 // Not found 10 return NULL; 11 } 12 13 // Found bucket. Try and find the key. Traverse linked list if needed. 14 int found = 0; 15 t_hash_table_bucket *htb = ht->bucket_list[hash_value_capped]; 16 17 18 // Cache the key hashval when we are dealing with objects. 19 char *key_hash_val = NULL; 20 if (key->type == HASH_KEY_OBJ) { 21 key_hash_val = object_get_hash((t_object *)(key->val.o)); 22 } 23 24 while (htb) { 25 switch (key->type) { 26 case HASH_KEY_STR : 27 if (strcmp(htb->key->val.s, key->val.s) == 0) found = 1; 28 break; 29 case HASH_KEY_NUM : 30 if (htb->key->val.n == key->val.n) found = 1; 6 https://github.com/jaytaph/saffire/blob/develop/src/components/general/hash/chained.c

Slide 8

Slide 8 text

1 public function isEmpty() 2 { 3 foreach ($this->children as $child) { 4 if (!$child->isEmpty()) { 5 return false; 6 } 7 } 8 9 return FormUtil::isEmpty($this->modelData) || 10 // arrays, countables 11 0 === count($this->modelData) || 12 // traversables that are not countable 13 ($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData)); 14 } 7 https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Form/Form.php

Slide 9

Slide 9 text

Let's write a language (in 5 minutes or less) 8

Slide 10

Slide 10 text

9 set a 1 set b 2 add a b c print c

Slide 11

Slide 11 text

9 set a 1 set b 2 add a b c print c operator

Slide 12

Slide 12 text

9 set a 1 set b 2 add a b c print c operator operands

Slide 13

Slide 13 text

9 set a 1 set b 2 add a b c print c 1

Slide 14

Slide 14 text

10 Interpreter

Slide 15

Slide 15 text

11

Slide 16

Slide 16 text

11 ➡ Parses and runs code directly from the source code by the interpreter.

Slide 17

Slide 17 text

11 ➡ Parses and runs code directly from the source code by the interpreter. ➡ Works on "any" platform (which runs the interpreter).

Slide 18

Slide 18 text

11 ➡ Parses and runs code directly from the source code by the interpreter. ➡ Works on "any" platform (which runs the interpreter). ➡ "platform" agnostic.

Slide 19

Slide 19 text

11 ➡ Parses and runs code directly from the source code by the interpreter. ➡ Works on "any" platform (which runs the interpreter). ➡ "platform" agnostic. ➡ Slow.

Slide 20

Slide 20 text

11 ➡ Parses and runs code directly from the source code by the interpreter. ➡ Works on "any" platform (which runs the interpreter). ➡ "platform" agnostic. ➡ Slow. ➡ Every instruction interpreted over and over again (for instance, loops).

Slide 21

Slide 21 text

12 PHP is an interpreted language (for now)

Slide 22

Slide 22 text

What if: we could convert our source code into machine code? 13

Slide 23

Slide 23 text

Compiler 14

Slide 24

Slide 24 text

Pro 15

Slide 25

Slide 25 text

Pro 15 ➡ Compiles source to machine code.

Slide 26

Slide 26 text

Pro 15 ➡ Compiles source to machine code. ➡ Runs very fast.

Slide 27

Slide 27 text

Pro 15 ➡ Compiles source to machine code. ➡ Runs very fast. ➡ No need for the source code.

Slide 28

Slide 28 text

Pro 15 ➡ Compiles source to machine code. ➡ Runs very fast. ➡ No need for the source code. ➡ Optimized for the running platform.

Slide 29

Slide 29 text

Cons 16 https://xkcd.com/303/

Slide 30

Slide 30 text

Cons ➡ Can ONLY run on the compiled architecture (x64, arm, sparc etc). 16 https://xkcd.com/303/

Slide 31

Slide 31 text

Cons ➡ Can ONLY run on the compiled architecture (x64, arm, sparc etc). ➡ A change in the source code means a recompilation is needed. 16 https://xkcd.com/303/

Slide 32

Slide 32 text

Cons ➡ Can ONLY run on the compiled architecture (x64, arm, sparc etc). ➡ A change in the source code means a recompilation is needed. ➡ 16 https://xkcd.com/303/

Slide 33

Slide 33 text

➡ Instruction Set Architecture (ISA) ➡ Application Binary Interface (ABI) 17

Slide 34

Slide 34 text

ISA ➡ The API of your computer / CPU. ➡ The specs are not funny. 18

Slide 35

Slide 35 text

19 http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf

Slide 36

Slide 36 text

ABI ➡ Again, an API ➡ How does a program need to be loaded in order to work on the given ISA? ➡ file formats, function calls, stacks etc. 20

Slide 37

Slide 37 text

21 #include int main(void) { int i = 41; i++; printf("The number is: %d\n", i); }

Slide 38

Slide 38 text

.file "test.c" .section .rodata .LC0: .string "The number is: %d\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp movl $41, 28(%esp) addl $1, 28(%esp) movl $.LC0, %eax movl 28(%esp), %edx movl %edx, 4(%esp) movl %eax, (%esp) call printf leave ret .size main, .-main .ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-16)" .section .note.GNU-stack,"",@progbits 21 #include int main(void) { int i = 41; i++; printf("The number is: %d\n", i); }

Slide 39

Slide 39 text

.file "test.c" .section .rodata .LC0: .string "The number is: %d\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp movl $41, 28(%esp) addl $1, 28(%esp) movl $.LC0, %eax movl 28(%esp), %edx movl %edx, 4(%esp) movl %eax, (%esp) call printf leave ret .size main, .-main .ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-16)" .section .note.GNU-stack,"",@progbits 21 #include int main(void) { int i = 41; i++; printf("The number is: %d\n", i); } .file "test.c" .section .rodata .LC0: .string "The number is: %d\n" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movl $41, -4(%rbp) addl $1, -4(%rbp) movl $.LC0, %eax movl -4(%rbp), %edx movl %edx, %esi movq %rax, %rdi movl $0, %eax call printf leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-16)" .section .note.GNU-stack,"",@progbits

Slide 40

Slide 40 text

This is why sane people do not write compilers* 22 * I'm currently writing a compiler.

Slide 41

Slide 41 text

Hybrid system 23

Slide 42

Slide 42 text

24 ➡ We "compile" source code to an intermediate code. ➡ Intermediate code looks very similar to machine code: few and simple instructions.

Slide 43

Slide 43 text

25

Slide 44

Slide 44 text

➡ Intermediate is very simple. 25

Slide 45

Slide 45 text

➡ Intermediate is very simple. ➡ Doesn't use any/very few optimizations. 25

Slide 46

Slide 46 text

➡ Intermediate is very simple. ➡ Doesn't use any/very few optimizations. ➡ Can be compiled at runtime, because it's very fast (compared to "real" compilation). 25

Slide 47

Slide 47 text

26

Slide 48

Slide 48 text

➡ Intermediate code gets "interpreted". 26

Slide 49

Slide 49 text

➡ Intermediate code gets "interpreted". ➡ Since intermediate code resembles machine code, interpretation and execution is relatively fast. 26

Slide 50

Slide 50 text

➡ Intermediate code gets "interpreted". ➡ Since intermediate code resembles machine code, interpretation and execution is relatively fast. ➡ Lots of error checks have been removed / dealt with during compilation phase. 26

Slide 51

Slide 51 text

27

Slide 52

Slide 52 text

➡ Interpreting is done through a "Virtual Machine" (not to be confused with: vmware, virtualbox) ➡ Java virtual machine (JVM) ➡ Python, Ruby, PHP 27

Slide 53

Slide 53 text

Finding entry points Branch analysis from position: 0 Jump found. Position 1 = -2 filename: /in/CQ5uJ function name: (null) number of ops: 6 compiled vars: !0 = $a, !1 = $b line #* E I O op fetch ext return operands ------------------------------------------------------------------------------------- 3 0 E > ASSIGN !0, 'hello+world' 5 1 ASSIGN !1, 41 7 2 ASSIGN_ADD 0 !1, 1 9 3 CONCAT ~5 !0, !1 4 ECHO ~5 5 > RETURN 1 Generated using Vulcan Logic Dumper, using php 7.0.0

Slide 54

Slide 54 text

29 compile PHP to bytecode Run PHP bytecode read PHP file into memory

Slide 55

Slide 55 text

29 compile PHP to bytecode Run PHP bytecode read PHP file into memory OPCache

Slide 56

Slide 56 text

30 compile PHP to bytecode read PHP file into memory OPCache Run PHP bytecode

Slide 57

Slide 57 text

JIT ( just in time ) 31

Slide 58

Slide 58 text

32 ➡ Many different "flavors" ➡ JIT != JIT != JIT

Slide 59

Slide 59 text

33

Slide 60

Slide 60 text

➡ Compiles to native machine code at runtime. 33

Slide 61

Slide 61 text

➡ Compiles to native machine code at runtime. ➡ Either compiles "block" first, then runs. 33

Slide 62

Slide 62 text

➡ Compiles to native machine code at runtime. ➡ Either compiles "block" first, then runs. ➡ Or, only compiles only on multiple calls. 33

Slide 63

Slide 63 text

➡ Compiles to native machine code at runtime. ➡ Either compiles "block" first, then runs. ➡ Or, only compiles only on multiple calls. ➡ Or, compiles per function. 33

Slide 64

Slide 64 text

➡ Compiles to native machine code at runtime. ➡ Either compiles "block" first, then runs. ➡ Or, only compiles only on multiple calls. ➡ Or, compiles per function. ➡ Or, interprets, compiles in the background, and switches to compiled code when compilation is finished. 33

Slide 65

Slide 65 text

init(); $a = 1; for ($i=0; $i!=1000; $i++) { // very CPU consuming functions $a = $i / 100 * sqrt($i / 163.21) + foobar($i)); echo $a; } 34

Slide 66

Slide 66 text

35

Slide 67

Slide 67 text

35 ➡ We don't have to "wait" for compilation.

Slide 68

Slide 68 text

35 ➡ We don't have to "wait" for compilation. ➡ Still runs fast (as in binary code).

Slide 69

Slide 69 text

35 ➡ We don't have to "wait" for compilation. ➡ Still runs fast (as in binary code). ➡ Can optimize even better than pre- compilation (it has more context).

Slide 70

Slide 70 text

PHP7 36

Slide 71

Slide 71 text

37 ➡ Hybrid / ByteCode VM ➡ AST ➡ No static analysis (yet) ➡ No JIT (yet)

Slide 72

Slide 72 text

Abstract Syntax Tree 38

Slide 73

Slide 73 text

39 Lexing & Parsing Bytecode Compilation Execution

Slide 74

Slide 74 text

40 AST Generation Bytecode Compiliation Execution Lexing & Parsing

Slide 75

Slide 75 text

41 AST Generation Bytecode Compiliation Execution Lexing & parsing Whatever you want to do

Slide 76

Slide 76 text

42 Abstract Syntax Tree https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Abstract_syntax_tree_for_Euclidean_algorithm.svg/400px-Abstract_syntax_tree_for_Euclidean_algorithm.svg.png while ($b != 0) { if ($a > $b) { $a = $a - $b; } else { $b = $b - $a; } } return $a;

Slide 77

Slide 77 text

43 ➡ Make changes to the tree (eg: remove all else-statements) ➡ Convert code back to older versions or other language (transpiling) ➡ Analyze code ➡ Optimize code

Slide 78

Slide 78 text

44 ➡ JIT system (other than hiphopvm) ➡ LLVM ➡ Bytecode interchange ➡ PhpPhp (php interpreter written in php?) The future

Slide 79

Slide 79 text

http://farm1.static.flickr.com/73/163450213_18478d3aa6_d.jpg 45

Slide 80

Slide 80 text

46 Find me on twitter: @jaytaph Find me for development and training: www.noxlogic.nl / www.techademy.nl Find me on email: jthijssen@noxlogic.nl Find me for blogs: www.adayinthelifeof.nl

Slide 81

Slide 81 text

class_declaration_statement: class_modifiers T_CLASS T_STRING extends_from implements_list '{' statement_list '}' | T_CLASS T_STRING extends_from implements_list '{' statement_list '}' ; class_modifiers: class_modifier | class_modifiers class_modifier { zend_add_class_modifiers($1, $2) } ; class_modifier: T_ABSTRACT | T_FINAL ; 47 abstract abstract final final class foo { }