dynamic languages need dynamic compilers
play

Dynamic Languages need Dynamic Compilers Maxime Chevalier-Boisvert - PowerPoint PPT Presentation

Dynamic Languages need Dynamic Compilers Maxime Chevalier-Boisvert mloc.js 2014 Introduction PhD candidate at the Universit de Montral, prof. Marc Feeley Research: compilers, optimizing dynamic languages, JS This talk is about:


  1. Dynamic Languages need Dynamic Compilers Maxime Chevalier-Boisvert mloc.js 2014

  2. Introduction ● PhD candidate at the Université de Montréal, prof. Marc Feeley ● Research: compilers, optimizing dynamic languages, JS ● This talk is about: – Dynamic languages – JIT compilation & optimization – The Higgs JS compiler – Basic block versioning – Lazy incremental compilation 2

  3. Dynamic languages ● JS is not an "interpreted language" – Originally ran in an interpreter, back in 1995 – Today, all browsers have JIT compilers ● Family of languages sharing “dynamic” characteristics – e.g.: JS, Python, Ruby, PHP, Perl, MATLAB, LISPs ● Huge gain in popularity with web development – Rapid prototyping, short development cycles 3

  4. Defining dynamic languages ● Dynamic typing – Variables can change type over time – Types associated with values – No type annotations ● Late binding – Symbols resolved dynamically (e.g.: globals) – Dynamic loading of code (eval, load) ● Dynamic growth of objects – Dynamic arrays – Objects as dictionaries/maps 4

  5. "I think of a programming language as a tool to convert a programmer's mental images into precise operations that a machine can perform. The main idea is to match the user's intuition as well as possible . […]" – Donald Knuth 5

  6. Higher-level thinking ● Reduce the cognitive burden on programmers ● Hope to make you more productive – Write less code for the same result – Each line of code conveys more meaning ● Leave more details implicit, assumed – Invisible work happen behind the scenes – This invisible work carries extra overhead 6

  7. Dynamic type tests ● Operators change meaning based on types – Different operations for different inputs ● For example, the + operator could mean: – Integer addition – Floating-point addition – String concatenation – Array appending ● Inside each operator hide many type tests – Functions with cascades of if statements testing types 7

  8. 8

  9. 9

  10. JIT compilation ● Key advantages over static compilers – Observe, monitor programs as they run – Modify code at run time ● In theory, JITs can produce faster code – Code adapted to program's behavior – Don't account for unexecuted code ● Opinion: modern JITs still overly static – Compiler books are all about AOT compilers 11

  11. Higgs ● JavaScript JIT compiler for x86-64 – Open source, mostly written in D – Self-hosted runtime library, in JS – Relatively small codebase (~ 50 KLOC) ● Support for most of ECMAScript 5 – No with statement, no getters/setters – Extras: Foreign Function Interface (FFI) ● Experimental platform – Try new ideas, uncharted territory – Basic block versioning, lazy incremental compilation 12

  12. Self-hosting ● Runtime and standard library are self-hosted ● JS primitives (e.g.: + operator) written in extended JS – Exposes low-level operations (e.g.: machine integer ops) ● Primitives compiled & inlined like any other JS code – Avoids opaque calls into C or D code ● Easy to change & extend runtime ● Inlining critical for performance 13

  13. Basic block versioning ● Similarities with tracing, procedure cloning ● As you compile code, accumulate facts – e.g.: type information – Branch tests add type & shape information ● Specialize based on accumulated facts – Type information: type tags, variables, objects – Potentially: register allocation state ● May compile multiple versions of code

  14. true false A B C D 15

  15. true false is_int32(n)? B C D 16

  16. if ( is_int32(n) ) { // B ... } else { // C ... } // D ... 17

  17. true false is_int32(n)? B C D 18

  18. true false is_int32(n)? n is int32 B C D 19

  19. true false is_int32(n)? n is int32 n is not int32 B C D 20

  20. true false is_int32(n)? n is int32 n is not int32 B C n is ??? D 21

  21. true false is_int32(n)? n is int32 n is not int32 B C n is int32 n is not int32 D' D'' 22

  22. var v = 4294967296; for (var i = 0; i < 600000; i++) v = v & i; // From the SunSpider bitwise-and benchmark 23

  23. var v = 4294967296; for (var i = 0; less_than (i,600000); i = add (i,1)) v = bitwise_and (v,i); 24

  24. var v = 4294967296; for (var i = 0; less_than(i,600000); i = add(i,1)) v = bitwise_and (v,i); function bitwise_and (x,y) { if ( is_int32 (x) && is_int32 (y)) return bitwise_and_int32(x,y); // Fast path return bitwise_and_int32(toInt32(x), toInt32(y)); } 25

  25. var v = 4294967296; for (var i = 0; less_than(i,600000); i = add (i,1)) v = bitwise_and(v,i); function bitwise_and(x,y) { if ( is_int32 (x) && is_int32 (y)) return bitwise_and_int32(x,y); // Fast path return bitwise_and_int32(toInt32(x), toInt32(y)); } function add (x,y) { if ( is_int32 (x) && is_int32 (y)) { var r = add_int32(x,y); // Fast path if (cpu_overflow_flag) r = add_double(toDouble(x), toDouble(y)); return r; } return add_general(x,y); 26 }

  26. var v = 4294967296; for (var i = 0; less_than(i,600000); i = add (i,1)) v = bitwise_and(v,i); function bitwise_and(x,y) { if ( is_int32 (x) && is_int32 (y)) return bitwise_and_int32(x,y); // Fast path return bitwise_and_int32(toInt32(x), toInt32(y)); } function add (x,y) { if ( is_int32 (x) && is_int32 (y)) { var r = add_int32(x,y); // Fast path if ( cpu_overflow_flag ) r = add_double(toDouble(x), toDouble(y)); return r; } return add_general(x,y); 27 }

  27. var v = 4294967296; var i = 0; for (;;) { // if (i >= 600000) break; if ( is_int32 (i) && is_int32 (600000)) if (greater_eq_int32(i, 600000)) break; else if (greater_eq_general(i, 600000) break; // v = v & i if ( is_int32 (v) && is_int32 (i)) v = bitwise_and_int32(v,i); else v = bitwise_and _int32 (toInt32(v), toInt32(i)); // i = i + 1 if ( is_int32 (i) && is_int32 (1)) { i = add_int32(i,1); if (cpu_overflow_flag) i = add_double(toDouble(i), toDouble(1)); } else i = add_general(i,1); 28 }

  28. var v = 4294967296; var i = 0; for (;;) { // if (i >= 600000) break; if (is_int32(i) && is_int32 (600000)) if (greater_eq_int32(i, 600000)) break; else if (greater_eq_general(i, 600000) break; // v = v & i if (is_int32(v) && is_int32(i)) v = bitwise_and_int32(v,i); else v = bitwise_and _int32 (toInt32(v), toInt32(i)); // i = i + 1 if (is_int32(i) && is_int32 (1)) { i = add_int32(i,1); if (cpu_overflow_flag) i = add_double(toDouble(i), toDouble(1)); } else i = add_general(i,1); 29 }

  29. var v = 4294967296; var i = 0; for (;;) { // if (i >= 600000) break; if ( is_int32 (i)) if (greater_eq_int32(i, 600000)) break; else if (greater_eq_general(i, 600000) break; // v = v & i if ( is_int32 (v) && is_int32 (i)) v = bitwise_and_int32(v,i); else v = bitwise_and _int32 (toInt32(v), toInt32(i)); // i = i + 1 if ( is_int32 (i)) { i = add_int32(i,1); if (cpu_overflow_flag) i = add_double(toDouble(i), toDouble(1)); } else i = add_general(i,1); 30 }

  30. var v = 4294967296; var i = 0; // when we enter the loop, i is int32 for (;;) { // if (i >= 600000) break; if ( is_int32 (i)) if (greater_eq_int32(i, 600000)) break; else if (greater_eq_general(i, 600000) break; // v = v & i if ( is_int32 (v) && is_int32 (i)) v = bitwise_and_int32(v,i); else v = bitwise_and _int32 (toInt32(v), toInt32(i)); // i = i + 1 if ( is_int32 (i)) { i = add_int32(i,1); if (cpu_overflow_flag) i = add_double(toDouble(i), toDouble(1)); } else i = add_general(i,1); 31 }

  31. var v = 4294967296; var i = 0; for (;;) { // assume i is int32 when entering loop // if (i >= 600000) break; if ( is_int32 (i)) if (greater_eq_int32(i, 600000)) break; else if (greater_eq_general(i, 600000) break; // v = v & i if ( is_int32 (v) && is_int32 (i)) v = bitwise_and_int32(v,i); else v = bitwise_and _int32 (toInt32(v), toInt32(i)); // i = i + 1 if ( is_int32 (i)) { i = add_int32(i,1); if (cpu_overflow_flag) i = add_double(toDouble(i), toDouble(1)); } else i = add_general(i,1); 32 }

  32. var v = 4294967296; var i = 0; for (;;) { // assume i is int32 when entering loop // if (i >= 600000) break; if ( is_int32 (i)) if (greater_eq_int32(i, 600000)) break; else if (greater_eq_general(i, 600000) break; // v = v & i if ( is_int32 (v) && is_int32 (i)) v = bitwise_and_int32(v,i); else v = bitwise_and _int32 (toInt32(v), toInt32(i)); // i = i + 1 if ( is_int32 (i)) { i = add_int32(i,1); if (cpu_overflow_flag) i = add_double(toDouble(i), toDouble(1)); } else i = add_general(i,1); 33 }

  33. var v = 4294967296; var i = 0; for (;;) { // if (i >= 600000) break; if (greater_eq_int32(i, 600000)) break; // v = v & i if ( is_int32 (v) && is_int32 (i)) v = bitwise_and_int32(v,i); else v = bitwise_and_int32(toInt32(v), toInt32(i)); // i = i + 1 if ( is_int32 (i)) { i = add_int32(i,1); if (cpu_overflow_flag) i = add_double(toDouble(i), toDouble(1)); } else i = add_general(i,1); } 34

  34. var v = 4294967296; var i = 0; for (;;) { // if (i >= 600000) break; if (greater_eq_int32(i, 600000)) break; // v = v & i if ( is_int32 (v) && is_int32 (i)) v = bitwise_and_int32(v,i); else v = bitwise_and_int32(toInt32(v), toInt32(i)); // i = i + 1 if ( is_int32 (i)) { i = add_int32(i,1); if (cpu_overflow_flag) i = add_double(toDouble(i), toDouble(1)); } else i = add_general(i,1); } 35

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend