Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

22
Old Dog, New Tricks A Schemer’s Guide to JavaScript Implementations Quasiconf 2012 Andy Wingo

description

By Andy Wingo. Three talks in one: - The power of limits: Partial continuations in Scheme - Postcards from the web: Lessons from JavaScript - Guile in 2012: A look back at 2.0, a look forward to 2.2 The power of limits: Partial continuations in Scheme I’ll describe what delimited continuations are, how they are better than call/cc, and then go on to demonstrate and describe an event-based cooperative threading system built with delimited continuations, showing how it makes for much clearer code. I’ll show a simple implementation of the memcached protocol. Postcards from the web: Lessons from JavaScript In this talk I will mention some things that I have learned about language implementations from having worked on V8 and JavaScriptCore. Guile in 2012: A look back at 2.0, a look forward to 2.2 It will briefly summarize the 2.0 release series of Guile, how it went, what worked well and what didn’t. Then we’ll look forward to the next cycle, which is probably some 6 months away.

Transcript of Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Page 1: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Old Dog, New TricksA Schemer’s Guide to JavaScriptImplementations

Quasiconf 2012

Andy Wingo

Page 2: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

[email protected]

Compiler hacker at Igalia

Contract work on language implementations

V8, JavaScriptCore

Schemer

Page 3: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Scheme in one slide

Parse.

Expand.

Optimize.

Codegen.

Run.

Page 4: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

JavaScript in one slide

Pre-parse.

Run.

Parse.

Codegen.

Run.

Optimize.

Codegen.

Run.

...

Page 5: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

On optimization

Proof-driven program transformation

Scheme: Static proofs derived frominterprocedural flow analysis

JS: Dynamic proofs based on run-timeobservations, with ability to invalidatetransformations if assumptions fail to hold

Page 6: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Barriers to optimization inScheme

Mutable toplevels

Separate compilation

Incomplete type information

No information on what to inline

call/cc

Page 7: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

None of these inhibitJavaScript

Assume toplevels are immutable

No real separate compilation

A wealth of type information

Dynamic profiling identifies inline candidates

No call/cc

Page 8: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

“Adaptive optimization”

Types and hot spots not known until runtime

Types and hot spots can change over time

Assumptions can be invalidated over time

Adaptive optimization: speculative optimizationwith bailout

Page 9: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Deoptimization for debugging

Allow multi-leveled inlining and code motionwhile preserving programmer’s mental model ofhow evaluation works

Deoptimization already required by speculationfailures

Page 10: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Other common JSoptimizations

Unboxing

Common subexpression elimination

Loop invariant code motion (or loop peeling +CSE)

Range inference

Register allocation

Block reordering (?)

But to be clear: dynamic inlining is the big one

Page 11: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Different deployment models

Scheme implementations rarely run attacker- -controlled code

JS: Constant blinding to prevent vulnerabilitiesin non-JS code from using JS as a heap-spray

No threads in JS

Page 12: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Representation hacks

JS: NaN-boxing, sometimes

Rope strings

Page 13: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Dedicated regexp compilers

Matching word-at-a-time, hard to beat with ageneral compiler

Page 14: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Lazy tear-off in JSC

A static scope implementation trick

Page 15: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Implementing static scope

Chains: Activations on heap (!)

Closure creation: O(1) space and time❧

Free var access: O(n) time❧

Not “safe for space”❧

Displays: Activations on stack

Closure creation: O(n) space and time❧

Free var access: O(1) time❧

Mutated variables usually boxed❧

Page 16: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Lazy tear-off in JavaScriptCore

Activations on stack

Only allocate scope chain node if closure iscaptured

When control leaves function, tear off stack toheap, relocating pointer in scope node (nothreads in JS)

Memory advantages of chains with stackdiscipline of display closures

Free var access still O(n) but inlinable

Page 17: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Living with eval

Eval only evil if it defines new localsvar foo = 10;

function f(s){ eval(s); return foo; }

f('var foo=20;') ⇒ 20

Otherwise great: a compiler available to the user

Functions in which eval appears not fullyoptimizable: must expose symbol tables

Page 18: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Inline caches

Per-caller memoization, in code

Fundamental optimization for property access

Not as needed in Scheme because not muchpolymorphism

Can allow efficient generic arithmetic

Can make CLOS-style generics more efficient

Clojure-like sequence protocols

Function application?

Page 19: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Dealing with the devil

Runtime codegen in JS has a price: C++

Most Scheme implementations are self-hosted,with AOT compiler already

Challenge: add adaptive optimization to existingScheme implementation

Requires good AOT compiler!

Page 20: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

JS can change the way we code

Scheme’s static implementations encouragestatic programming

define-integrable

(declare (type fixnum x))

(declare (safety 0) (speed 3))

(declare (usual-integrations))

include instead of load

Adaptive optimization can bring backdynamicity

Page 21: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

Summary

In Smart vs Lazy, Schemers always chose Smart

A bit of laziness won’t hurt

Adaptive optimization in Scheme!

Page 22: Partial Continuations, Lessons From JavaScript and Guile in 2012 (Quasiconf 2012)

questions?

Work: http://www.igalia.com/compilers❧

Words: http://wingolog.org/❧

Slides: http://wingolog.org/pub/qc-2012-js-slides.pdf

Notes: http://wingolog.org/pub/qc-2012-js-notes.pdf