Metal Script Baremetal Java Script for small embedded
Metal. Script Bare-metal Java. Script for small embedded devices Michael Hunter elec. mike@gmail. com coder-mike. com metalscript. com 2018 -10 -16 For ECMA TC 53, October 2018, Boston U. S. A
Existing Solutions Node JS Approach 2018 -10 -16 • Embedded Linux • Tessel Michael Hunter ECMA TC 53
Existing Solutions Node JS 2018 -10 -16 GCC Michael Hunter ECMA TC 53
Existing Solutions Node JS 2018 -10 -16 Moddable XS Michael Hunter Espruino ECMA TC 53
Metal. Script Existing Solutions 2018 -10 -16 Michael Hunter ECMA TC 53
Metal. Script – Bare-metal Java. Script Source Code 2018 -10 -16 JS Metal. Script (Compiler) Michael Hunter binary MCU ECMA TC 53
Metal. Script – Bare-metal Java. Script Source Code 2018 -10 -16 Binary JS Michael Hunter MCU ECMA TC 53
Metal. Script Two big Ideas 1. Partial execution – MCU. start() 2. Symbolic execution Please attribute me if you borrow/steal these ideas : -) 2018 -10 -16 Michael Hunter ECMA TC 53
Partial Execution • Program starts executing in the compiler • Program is suspended when it calls MCU. start() • Program is resumed on the device 2018 -10 -16 Michael Hunter ECMA TC 53
Metal. Script Partial Execution // blinky. js Compile time (interpreted) Runtime (compiled) 2018 -10 -16 const blink. Interval = 500; const led = MCU. gpio('B 4'); const blink = () => led. toggle(); MCU. start(); set. Interval(blink, blink. Interval); Michael Hunter ECMA TC 53
Metal. Script – Partial Execution This division is not lexical, it’s dynamic Dynamic Process Evolution Compile time (interpreted) Runtime (compiled) 2018 -10 -16 1. 2. 3. 4. 5. 6. 7. Realm created Script loaded Job queue (event loop) started Script parsed initialize function instantiated initialize function is called MCU. start() is called 8. MCU. start() returns 9. start. Blinker is called // blinky. js const start. Blinker = initialize(); MCU. start(); start. Blinker(); function initialize() { const blink. Interval = 500; const led = MCU. gpio('B 4’); const blink = () => led. toggle(); function start. Blinker() { set. Interval(blink, blink. Interval); } return start. Blinker; } Michael Hunter ECMA TC 53
Metal. Script – Partial Execution Dynamic Process Evolution 1. 2. 3. 4. 5. 6. 7. Realm created Script loaded Job queue (event loop) started Script parsed initialize function instantiated initialize function is called MCU. start() is called Application “timeline” Virtual Machine Compile time (interpreted) Runtime (compiled) 8. MCU. start() returns 9. start. Blinker is called 2018 -10 -16 Michael Hunter Bare metal ECMA TC 53
Metal. Script – Partial Execution Dynamic Process Evolution 1. 2. 3. 4. 5. 6. 7. Compile time (interpreted) Runtime (compiled) Realm created Script loaded Job queue (event loop) started Script parsed initialize function instantiated initialize function is called MCU. start() is called 7. 1 Compilation 7. 2 Memory layout & linking 7. 3 Download 7. 4 Reset interrupt vector 7. 5 MCU. start() completes 8. MCU. start() returns 9. start. Blinker is called 2018 -10 -16 Michael Hunter Application “timeline” Virtual Machine Compiler Bare metal ECMA TC 53
Metal. Script – Partial Execution - Why? “Instant” startup time Faster than C 2018 -10 -16 Michael Hunter ECMA TC 53
Metal. Script – Partial Execution - Why? True dynamic import/require and dependency resolution • require(some. Condition ? 'driver 1' : 'driver 2'); • Without hacky/non-compliant lexical analysis • Without configuration file (à la tsconfig. json | webpack. config. js | manifest. json ) 2018 -10 -16 Michael Hunter ECMA TC 53
Metal. Script – Partial Execution - Why? No need for a “different language” for compile-time behavior • C preprocessor • C++ template metaprogramming • Linker scripts • Makefiles 2018 -10 -16 Michael Hunter ECMA TC 53
Metal. Script – Partial Execution - Why? Precompute data/functions at compile time (ROM) • DSP FIR filters • Encryption/CRC tables • Conversion/calibration tables • Internal registries 2018 -10 -16 Michael Hunter ECMA TC 53
Metal. Script – Partial Execution - Why? Shared code • Shared between compile time and runtime • Code at any time can use third party libraries (e. g. NPM) 2018 -10 -16 Michael Hunter ECMA TC 53
Metal. Script Big idea #2: Symbolic execution 2018 -10 -16 Michael Hunter ECMA TC 53
Metal. Script Symbolic Execution • For code after MCU. start • The symbolic interpreter “executes” the runtime code at compile time • Deals with non-determinism and ambiguity • Ambiguity: information is unknown at compile time • Non determinism : behavior and control flow is unknown at compile time • Symbolic interpreter manipulates a symbolic machine Overall effect: • Global constant propagation • Binary type inference • “Template” instantiation 2018 -10 -16 Michael Hunter ECMA TC 53
Metal. Script – Symbolic Execution Caveat Symbolic execution in Metal. Script is a work-in-progress (started recently) 2018 -10 -16 Michael Hunter ECMA TC 53
Metal. Script – Symbolic Execution - Example • MCU object is known • gpio property can be statically resolved • gpio function can be statically invoked • Resulting GPIO object can exist statically (at compile time only) • Toggle method can be invoked inline (zero overhead for call) 2018 -10 -16 Michael Hunter MCU. gpio('B 4'). toggle() ECMA TC 53
Java. Script MCU. gpio('B 4'). toggle() 2018 -10 -16 IL t 0_18 = sys_op("resolve. Binding ", "MCU" , false, undefined); t 0_19 = sys_op("get. Value ", t 0_18); t 0_20 = sys_op("require. Object. Coercible", t 0_19); t 0_21 = sys_op("new. Ref ", t 0_20, "gpio" , false); t 0_22 = sys_op("get. Value ", t 0_21); t 0_23 = sys_op("get. This. Value", t 0_21); t 0_24 = list_new (); t 0_25 = copy("B 4"); t 0_26 = sys_op("get. Value", t 0_25); list_push (t 0_24, t 0_26); t 0_28 = sys_op("throw. If. Not. Callable", t 0_22); t 0_29 = sys_op("call", t 0_22, t 0_23, t 0_24); t 0_30 = sys_op("get. Value", t 0_29); t 0_31 = sys_op("require. Object. Coercible", t 0_30); t 0_32 = sys_op("new. Ref ", t 0_31, "toggle" , false); t 0_33 = sys_op("get. Value ", t 0_32); t 0_34 = sys_op("get. This. Value", t 0_32); t 0_35 = list_new (); t 0_36 = sys_op("throw. If. Not. Callable", t 0_33); t 0_37 = sys_op("call", t 0_33, t 0_34, t 0_35); t 0_38 = sys_op("get. Value", t 0_37); Michael Hunter ECMA TC 53
// --------- SYSTEM INITIALIZATION -----------const io. Map = { //. . . 'B 4': { address: 0 x 40020814, mask: 0 x 10 } //. . . } GPIO Toggle Example – Full Code function gpio(name) { const pin. Info = io. Map[name]; return { toggle() { const value = MCU. get. IO(pin. Info. address); const new. Value = value ^ pin. Info. mask; MCU. set. IO(pin. Info. address, new. Value); } }; } MCU. gpio = gpio; // ------------ USER CODE --------------MCU. start(); MCU. gpio('B 4'). toggle() 2018 -10 -16 Michael Hunter ECMA TC 53
GPIO Toggle Example – Output ARM Assembly Java. Script 11, 557 symbolic instruction cycles 2018 -10 -16 Compiles to . globl resume ; -- Begin function resume . p 2 align 2 . code 32 ; @resume: ; BB#0: ; %block 1 ldr r 0, . LCPI 0_0 Read ldr r 1, [r 0] XOR eor r 1, #16 Write str r 1, [r 0] mov pc, lr . p 2 align 2 ; BB#1: . LCPI 0_0: . long 1073874964 ; 0 x 40020814 ; -- End function Michael Hunter ECMA TC 53
GPIO Toggle Example – Output Java. Script x 86 Assembly 11, 557 symbolic instruction cycles 2018 -10 -16 Compiles to . globl _resume # -- Begin function resume . p 2 align 4, 0 x 90 _resume: # @resume # BB#0: # %block 1 xorl $16, 1073874964 retl # -- End function Michael Hunter ECMA TC 53
Metal. Script – Symbolic Execution – Why? • Efficient • Low-overhead abstraction • Dependency injection • Inversion of control/callbacks • Options-hashes • Generic library can handle a lot of cases, specialized on-the-fly for your use case • Application can adapt to different hardware • (e. g. product variations) • Might previously be done with #if directives • Unit testing • APIs can be designed for usability and generality 2018 -10 -16 Michael Hunter ECMA TC 53
</end> Read more on my blog… coder-mike. com 2018 -10 -16 Michael Hunter ECMA TC 53
Questions/Discussion 2018 -10 -16 Michael Hunter ECMA TC 53
Extra Sides 2018 -10 -16 Michael Hunter ECMA TC 53
Residing in Compiler Other JS files 2018 -10 -16 GPIO Target info Application FFI Residing on MCU Timers MCU. start() … File system Michael Hunter … ECMA TC 53
Residing in Compiler Other JS files Target info Application FFI 2018 -10 -16 … Michael Hunter ECMA TC 53
Suspended state Application (Java. Script) ECMAScript Abstract Operations (Sys. Script) JS-to-IL Sys. Script compiler Majority of ECMAScript spec is impl. here IL Pre-start VM Symbolic interpreter IR Emitter Compile-time behavior Static analysis Runtime behavior (LLVM IR) 2018 -10 -16 Michael Hunter ECMA TC 53
- Slides: 34