understanding javascript engines

21
JavaScript Engines Pop the hood

Upload: parashuram-n

Post on 14-Jan-2015

4.789 views

Category:

Technology


0 download

DESCRIPTION

A quick introduction to how Javascript engi

TRANSCRIPT

Page 1: Understanding Javascript Engines

JavaScript EnginesPop the hood

Page 2: Understanding Javascript Engines

z = x + y

Page 3: Understanding Javascript Engines

1. Read operation from memory2. Get location of x and y3. Read values for x and y 4. Unbox x and y.5. Choose meaning of “+”, perform

“+”6. Save z to memory7. Do garbage.

Executing z = x + y

Page 4: Understanding Javascript Engines

1. String “z = x + y” is passed into tokenizer.– Webkit uses Flex (LEX)– Accommodate semi colon insertion, etc.

2. Tokenizer output fed to parser – Webkit uses Bison, bottom up shift

reduce parser– Gecko has top down parser

3. Statement now available as Abstract Syntax Tree (AST)

1. Read operation from memory…

Page 5: Understanding Javascript Engines

• X & Y could be number, string, object, null, undefined, array, etc. – Offsets directly available for primitives

• Values also depend on context of execution– Closures (activation contexts)– Local Variables– Object properties– Scope modifiers – eval, with, etc.

2. Get locations of x and y

Page 6: Understanding Javascript Engines

• If x is a actually array - obj[x]– Dense array have offsets– Created using 0..N or push– Gecko creates sparse array on N..0– Adding obj[“name”] fails optimization

2. Get values of x – Array

Page 7: Understanding Javascript Engines

• If X is an object property (obj.x)– Looks up current object or up the prototype

chain– Inline Cache (IC) the value

• Objects have shape – {x:1} is different from {x:1,y:2}

• Webkit stores memory offsets in hidden classes• New shape created for every new property.• IC can read from prototype without walking tree• Closures only save path, still have to walk every

time.

– OpCodes generated for each shape• Obj.x ==> read shape1[member1]

2. Get values of x – Object

Page 8: Understanding Javascript Engines

• JavaScript variable assignments are un-typed. • Assignments stored as boxed inputs– x could be (int32 | 100) – indicating type and

value

• Javascript numbers are IEEE-754 floating point.– Who cares, just use 32 bit to optimize. – Overflow to doubles.

• Ways to Box values (ref)– Tagging the LSBs (ref)– Nan Boxing (ref) – 51 bit of NaN space for non-

doubles (Webkit)– Nun Boxing (favor doubles in NAN – Mozilla pun)

3. Read boxed input …

Page 9: Understanding Javascript Engines

From box, infer type and value, represent it in native type Int32 x = 100;

From NunBoxed Values 0x400c 0000 | 0x0000 0000 = not a nan, so

double (3.5) 0xFFFF0001 | 0x0000 0040 = Nan space, so

Int32 (0x0000 0040) From NanBoxed Values (0xFFFF80

00000040) Mask to get pointer, shift to get double X64 portability, fits in register, but harder to

decode

4. Unbox x and y

Page 10: Understanding Javascript Engines

If (typeof x == int32 && typeof y == int32) result = x <operator> y If (result overflows), result = float If (result Nan), result = NaN.

If (typeof x == int32 && typeof y === float) result = CoarceToFloat(x) + y // Same sanity checks

….. If (typeof x === Object) ….

5. Perform “+” : Interpreter

Page 11: Understanding Javascript Engines

If type of x and y are known, generate opcodes Fall to opcode when routine is hit. Save cost of boxing, unboxing.

Determined opcode Paths for each shape Multiple shapes mean multiple if-else

branches Still have to check for validity/dirtiness of

opcpdes Typical JagerMonkey JITing

5. Perform “+” : Basic JIT

Page 12: Understanding Javascript Engines

Observe and identify hot code 70 iterations Crankshaft – according to profiler Other heuristics

Execute opcode routine for specific type Initial compilation cost OpCodes may be thrown away if types

change Fallback to non-optimized version

(Performance fault) Classic Tracemonkey

5. Perform “+” : Typed JIT

Page 13: Understanding Javascript Engines

Static analysis of code to “prove” types

Reduce checks, ensure only one path taken at all times.

Type stable Javascript IonMonkey Internals. Use multicore processors

To box/unbox values To generate compiled opcodes (Chakra)

5. Perform “+” : Next Gen JIT

Page 14: Understanding Javascript Engines

Used by WebGL and Canvas render computation routines

Shaders and alpha channel (no direct JS code)

Super fast floating point math Note that variables is strongly typed

as Blobs

5. Perform “+” : GPU Enabled

Page 15: Understanding Javascript Engines

Strings Substring is O(1), Concat also optimized Concat fault on Opera, Chrome

Array Denser the better Named property is sparse in FF, IE Iterate using index, not for:in or

functional Functions

F() faster than f.call(), f.apply(). Using arguments slows down execution

5. Perform “+” : Datatypes

Page 16: Understanding Javascript Engines

Objects Prototypes are better than closures

Exceptions Try is mostly free, catch is expensive May cause optimizer to stop

Eval and With Cause scope sudden change, prevent JIT

5. Perform “+” : Datatypes

Page 17: Understanding Javascript Engines

Box “z” and put it on heap if required. Leave “z” in register if used

subsequently Create shape for “z” if object

6. Save Z

Page 18: Understanding Javascript Engines

Mark and Sweep Causes GC to pause main routine Jittery animation, unresponsive UI thread

Incremental GC Mark and sweep only parts

Generational GC Separate objects in nursery and tenured

areas Promoting young to old is expensive

Combine Generational and Incremental Frequent young cleanup, occasional old

cleanup

7. Garbage Collection

Page 19: Understanding Javascript Engines

Block Scope reduces variable lookups (let, var)

“Yeild” may need to save current context

Blob Data type – boxing/unboxing issues

Classes === Concrete Shapes ? Syntactic sugar, no impact

Assignment de-structuring Promises, modules, etc.

Changes due to ECMA.next

Page 20: Understanding Javascript Engines

Don’t write any code Practice type safety Leave hot loops alone – don’t create

shapes in them Make arrays dense Avoid operations that require different

type coercion every time.

Conclusions

Page 21: Understanding Javascript Engines

@nparashuramhttp://nparashuram.com