V8: An Open-Source, High-Performance JavaScript EngineKasper LundOctober 4, 2008
Who Am I?
• Kasper Lund, virtual machine addict– 2000-2002: CLDC HI (Sun Microsystems)
– 2002-2006: Resilient (OOVM)
– 2006-2008: V8 (Google)
• Primary areas of interests:– Dynamic programming languages
– Interpretation and dynamic code generation
– Method dispatching
3
Challenges in Implementing JavaScript
• A very dynamic programming language
• Objects contain properties (ie, fields or methods)
• Properties can be added or removed on the fly
• Objects with completely different sets of properties can appear at the same property access site
• Properties can be found in an object's prototype chain
• Functions can be moved from one object to another
4
Motivation for a New JavaScript Engine
• When starting the project:– Browsers had slow JavaScript implementations
– They did not scale to large applications with many objects
– They even had memory leaks when running web apps
• The solution seemed simple:– Build a completely new engine from the ground up
– Find a way to categorize objects into classes
– Bring to bear techniques from static class-based languages
5
V8: A Scalable High-performance JS Engine
• The goal was to raise the performance bar for JavaScript execution
• Key design ideas in V8:– Hidden classes and hidden class transitions
– Inline caching
– Compilation to native code
– Efficient memory-management system
6
Hidden Classes
• In a static object-oriented language, a particular property is always found at a known offset in instances of a particular class– This is fast to access
• In JavaScript, there are no classes– Objects appearing at a property access site may have a
given property or not, found at various places in the object
– This is slow - we need to speed it up
• Hidden classes encode object layout and shared structure– Introduced behind-the-scenes
– Enable class-based optimizations
7
Hidden Classes
Example:function Point(x, y) { this.x = x; this.y = y;}
var p = new Point(1, 2);var q = new Point(3, 4);
Point p
Class0
Point q
Class1 Class2
1 2
3 4
Δx x:0
Δy
x:0
y:1
8
How Dynamic is JavaScript at Runtime?
• Introducing hidden classes allows us to measure how many different classes are seen at a site in the code
• Roughly 90% of all access sites see objects with the same hidden class
• Conclusion:– JavaScript is not as dynamic at runtime as you might think
– We can use class-based object-oriented optimization techniques
9
Inline Caching
• Each property access and function call is governed by an inline cache stub
• Stubs are in one of three states:1. Uninitialized: not executed yet
2. Monomorphic: only one class of objects seen
3. Megamorphic: more than one class of objects seen
10
Monomorphic Stub for Loading a Property
0xf7c0d32d: [Code]Instructions (size = 37)0xf7c0d344 0 8b442404 mov eax,[esp+0x4]0xf7c0d348 4 a801 test al,0x10xf7c0d34a 6 0f8414000000 jz 320xf7c0d350 12 8178ff81ab8ff7 cmp [eax+0xff],0xf78fab810xf7c0d357 19 0f8507000000 jnz 320xf7c0d35d 25 8b5803 mov ebx,[eax+0x3]0xf7c0d360 28 8b4307 mov eax,[ebx+0x7]0xf7c0d363 31 c3 ret0xf7c0d364 32 e993daffff jmp LoadIC_Miss
Megamorphic State
• Lookup monomorphic stub in global lookup table– Hashed lookup based on address of class and hash code of
the property name
• Verify that the stub is suitable– Check that the stub type matches (load, store, call)
– Check that the property name matches
• Call the monomorphic stub– Class check automatically handled by the stub
– Access is reasonably fast if all checks pass
Does It Really Matter?
• Property load timings:– Monomorphic: 0.000249 usec
– Megamorphic: 0.001390 usec (x5.5)
– No inline caching: 0.008665 usec (x34.8)
• Overall:– Inline caching speeds up benchmarks with a factor of ~11
– Faster property access is important to real apps too
13
Native-code Compiler
• JavaScript source code is translated directly into machine code
• There is no intermediate bytecode, because there is no interpreter
• Functions are compiled JIT-style– Source code is parsed into syntax trees
– A simple one-pass code generator is used
– Only a few optimizations are applied
• Code generators are implemented for x86 and ARM
14
Efficient Memory Management
• Design goals:– Fast object allocation
– Scalable object heap
– Small garbage collection pause times
• V8 uses a generational garbage collector
15
Object Heap Organization
• Young Generation– New space: newly allocated objects, collected frequently
• Old Generation– Code space: executable code objects
– Old data space: objects with no pointers to the young gen.
– Large object space: to avoid moving objects > 8KB
– Hidden class space: requires special GC processing
– Old pointer space: the rest of the old objects
16
Types of Garbage Collection
• Scavenge collections are most frequent– Copying collector operating on the young generation
– Allows single-pointer allocation
– Pause times bounded by live data in young gen
– Typical pause times: 1-2 ms
• Mark-sweep collections for most full collections– Processes all spaces
– Uses single-pointer and free-list allocation
– Pause times bound by size of heap
– Typical pause times: 30-50 ms
• Mark-sweep-compact to eliminate fragmentation– Typical pause times: 50-150 ms
17
Where is the JavaScript Library?
• All library functions are implemented in JavaScript– Examples: Array.prototype.join, String.prototype.replace
• The benefits of not implementing it inside the engine:– Keeps the core engine cleaner
– Easier to change and extend
– Capitalizes on the performance of the JavaScript compiler
• One drawback is startup time ~30 ms ...
... but there is a solution
18
Snapshotting of the Object Heap
• V8 allows saving the initial heap in a snapshot– Serialized form is very fast to read
– Includes pre-compiled code for JavaScript builtins
– Integrated in the build system and embedded directly in V8
• With snapshots, the startup time is reduced to 4-8 ms
Open-Source
• Open-source code and developed in the open– Permissive standard three clause BSD license
– Developed in the open, all code reviews are public
– See http://code.google.com/p/v8
• Interesting projects already using V8:– Chromium
– V8R: Extensible JavaScript scripting shell
– PyV8: Python running on top of V8
Benchmarks
• Benchmarking a new scripting engine is tricky– V8 is optimized for property accesses and function calls
– No existing benchmark suites really exercise that
– But it’s important to a lot of real world web apps
• The industry needs realistic and well-written benchmarks– No single existing benchmark suite covers all of JavaScript
– How do we go about measuring performance today?
21
http://code.google.com/apis/v8/run.html
• Richards– OS kernel simulation benchmark, originally written in BCPL
by Martin Richards (539 lines)
• DeltaBlue– One-way constraint solver, originally written in Smalltalk by
John Maloney and Mario Wolczko (880 lines)
• Crypto– Encryption and decryption benchmark based on code by
Tom Wu (1689 lines)
• RayTrace– Ray tracer benchmark based on code by Adam Burmister
(3418 lines)
• EarleyBoyer– Classic Scheme benchmarks, translated to JavaScript by
Florian Loitsch's Scheme2Js compiler (4682 lines)
Summary
• V8 is a high-performance JavaScript engine– Runs well-structured applications really fast
– Raises the performance bar for scripting languages
– Scales to larger applications
• V8 is open-source and developed in the open– Embed it in your own projects
– Use it for scripting on your computer
– Incorporate the best ideas into your own scripting engine
Questions?