JavaScript Engines: Under the Hood

85
Monday, November 29, 2010

description

A browser's JavaScript engine can seem like a magical black box. During this session, we'll show you how they work from 10,000 feet and give you the tricks to compile all the popular engines out there including JavaScriptCore, V8, and SpiderMonkey). We'll inspect the internals of the engine, and debug+profile your favorite code snippets. Armed with just a little extra knowledge about this black box, you will be ready to take a new look at JavaScript apps.

Transcript of JavaScript Engines: Under the Hood

Page 1: JavaScript Engines: Under the Hood

Monday, November 29, 2010

Page 2: JavaScript Engines: Under the Hood

JavaScript EnginesUnder the Hood

ARIYA HIDAYATENGINEERING DIRECTOR, SENCHA

Monday, November 29, 2010

Page 3: JavaScript Engines: Under the Hood

Get It

See It

Tweak It

JavaScript Engines

Monday, November 29, 2010

Page 4: JavaScript Engines: Under the Hood

JavaScript Engines

Monday, November 29, 2010

Page 5: JavaScript Engines: Under the Hood

SpiderMonkeyJavaScriptCore

V8

JavaScript Engines

Open

Opera CarakanMicrosoft JScript...

Closed

Monday, November 29, 2010

Page 6: JavaScript Engines: Under the Hood

SpiderMonkeyJavaScriptCore

V8

JavaScript Engines

Open

Monday, November 29, 2010

Page 7: JavaScript Engines: Under the Hood

SpiderMonkeyFirst JavaScript enginecreated by Brendan Eich

Written in CMostly used in Mozilla, Firefox, ...

License: MPL/LGPL/GPL

Monday, November 29, 2010

Page 8: JavaScript Engines: Under the Hood

JavaScriptCore (JSC)Built into WebKitForked from KDE’s KJS a long time ago

License: LGPL

Monday, November 29, 2010

Page 9: JavaScript Engines: Under the Hood

Other Names of JSCSquirrelFishbyte-code interpreter

SquirrelFish Extreme (SFX)native/machine code

Nitro, Nitro ExtremeApple’s marketing terms

Monday, November 29, 2010

Page 10: JavaScript Engines: Under the Hood

Google V8Written in C++License: BSD

Used in Chromium (Google Chrome)

Monday, November 29, 2010

Page 11: JavaScript Engines: Under the Hood

Qt ScriptUses JSC as the back-endDoes not power any web browser

Powerful bindings, debuggerUseful to make applications scriptable

Monday, November 29, 2010

Page 12: JavaScript Engines: Under the Hood

Let’s Go UNDER THE HOOD

Monday, November 29, 2010

Page 13: JavaScript Engines: Under the Hood

Let’s Go UNDER THE HOOD

Platform +Compiler

Monday, November 29, 2010

Page 14: JavaScript Engines: Under the Hood

Monday, November 29, 2010

Page 15: JavaScript Engines: Under the Hood

Get the real V8

svn checkout http://v8.googlecode.com/svn/trunk v8cd v8

git clone git://github.com/v8/v8.git v8cd v8

Monday, November 29, 2010

Page 16: JavaScript Engines: Under the Hood

Build V8

scons sample=shell mode=release snapshot=on

Monday, November 29, 2010

Page 17: JavaScript Engines: Under the Hood

Build V8

scons sample=shell mode=release snapshot=on

--jobs 4

Monday, November 29, 2010

Page 18: JavaScript Engines: Under the Hood

Build V8

scons sample=shell mode=release snapshot=on

--jobs 4

arch=x64

Monday, November 29, 2010

Page 19: JavaScript Engines: Under the Hood

perl sunspider --shell=/path/to/v8/directory/shell --args=-expose-gc

Run your-favorite-benchmark

Monday, November 29, 2010

Page 20: JavaScript Engines: Under the Hood

perl sunspider --shell=/path/to/v8/directory/shell --args=-expose-gc

Run your-favorite-benchmark

garbage collector

Monday, November 29, 2010

Page 21: JavaScript Engines: Under the Hood

Let’s Get DIRTY

Monday, November 29, 2010

Page 22: JavaScript Engines: Under the Hood

Building Blocks

Parser

Interpreter

Runtime

Monday, November 29, 2010

Page 23: JavaScript Engines: Under the Hood

Parser

Monday, November 29, 2010

Page 24: JavaScript Engines: Under the Hood

Tokenize

var answer = 42;

Monday, November 29, 2010

Page 25: JavaScript Engines: Under the Hood

Tokenize

var answer = 42;keyword equal sign

semicolon

identifier number

Monday, November 29, 2010

Page 26: JavaScript Engines: Under the Hood

>>>

>>>

Look Ahead

greater than

right shift

zero-filled right shift

Monday, November 29, 2010

Page 27: JavaScript Engines: Under the Hood

>>>

>>>

Look Ahead

greater than

right shift

zero-filled right shift

>=>>=>>>=

Monday, November 29, 2010

Page 28: JavaScript Engines: Under the Hood

Tokenizer on V8

src/scanner.*

Monday, November 29, 2010

Page 29: JavaScript Engines: Under the Hood

Tokenizer on V8

src/scanner.*

hand-writtenstate machine

Monday, November 29, 2010

Page 30: JavaScript Engines: Under the Hood

Keyword vs Identifier

instanceof instanceComponent

requires checking 9 chars

Monday, November 29, 2010

Page 31: JavaScript Engines: Under the Hood

Keyword vs Identifier

instanceof instanceComponent

requires checking 9 chars

a g h j k l m o p q x y zMonday, November 29, 2010

Page 32: JavaScript Engines: Under the Hood

Grammar

SourceElement :: (Statement)*

FunctionDeclaration :: 'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}'

Monday, November 29, 2010

Page 33: JavaScript Engines: Under the Hood

Syntax Tree

Variable Declaration

IdentifierLiteral Constant

answer 42Monday, November 29, 2010

Page 34: JavaScript Engines: Under the Hood

Another Syntax Tree

Condition Consequent

age < 25 “young”

Alternate

“old”

Branch

Monday, November 29, 2010

Page 35: JavaScript Engines: Under the Hood

Parser on V8

src/parser.*

Monday, November 29, 2010

Page 36: JavaScript Engines: Under the Hood

Parser on V8

src/parser.*

hand-writtenrecursive descent

Monday, November 29, 2010

Page 37: JavaScript Engines: Under the Hood

Code Trace

Script::Compile

Script::New

internal::Compiler::Compile

internal::MakeFunctionInfo

internal::ParserApi::Parse

Monday, November 29, 2010

Page 38: JavaScript Engines: Under the Hood

Interpreter

Monday, November 29, 2010

Page 39: JavaScript Engines: Under the Hood

From Code to Execution

Declare a local objectCall it “answer”

Create a (small integer) number 42Assign it to “answer”

var answer = 42;

Monday, November 29, 2010

Page 40: JavaScript Engines: Under the Hood

Traverse and Run

Variable Declaration

IdentifierLiteral Constant

answer 42Monday, November 29, 2010

Page 41: JavaScript Engines: Under the Hood

Bytecode

Serialize tree traversal intoa list of “actions”

Monday, November 29, 2010

Page 42: JavaScript Engines: Under the Hood

Machine Code

Compile the bytecodes intomachine instructions

Monday, November 29, 2010

Page 43: JavaScript Engines: Under the Hood

Machine Code

JIT (=just-in-time) compile

Compile the bytecodes intomachine instructions

Monday, November 29, 2010

Page 44: JavaScript Engines: Under the Hood

Machine Code on V8

shell_g --print-code

Global

When needed

shell_g --expose-debug-as deb

Monday, November 29, 2010

Page 45: JavaScript Engines: Under the Hood

Machine Code on V8

shell_g --print-code

Global

When needed

shell_g --expose-debug-as deb

deb.Debug.disassemble(f)

Monday, November 29, 2010

Page 46: JavaScript Engines: Under the Hood

“Lazy” Approach

foobar = function(x, y, z){....}

foobar(x, y, z);

Monday, November 29, 2010

Page 47: JavaScript Engines: Under the Hood

“Lazy” Approach

foobar = function(x, y, z){....}

foobar(x, y, z);

Analyze the syntaxMark the position of

function ‘foobar’

Monday, November 29, 2010

Page 48: JavaScript Engines: Under the Hood

“Lazy” Approach

foobar = function(x, y, z){....}

foobar(x, y, z);

Analyze the syntaxMark the position of

function ‘foobar’

Compile and run the function ‘foobar’

Monday, November 29, 2010

Page 49: JavaScript Engines: Under the Hood

Runtime

Monday, November 29, 2010

Page 50: JavaScript Engines: Under the Hood

Date.now()

JavaScriptworld

“native”world

Monday, November 29, 2010

Page 51: JavaScript Engines: Under the Hood

Let’s GoOFF ROAD

Monday, November 29, 2010

Page 52: JavaScript Engines: Under the Hood

Bridge

Monday, November 29, 2010

Page 53: JavaScript Engines: Under the Hood

V8 Embedder’s Guide

http://code.google.com/apis/v8/embed.htmlMonday, November 29, 2010

Page 54: JavaScript Engines: Under the Hood

Handle: Local vs Persistent

{ HandleScope scope;

Handle<Value> foobar = .... .... ....}

Monday, November 29, 2010

Page 55: JavaScript Engines: Under the Hood

Handle: Local vs Persistent

{ HandleScope scope;

Handle<Value> foobar = .... .... ....}

long lived

short lived

Monday, November 29, 2010

Page 56: JavaScript Engines: Under the Hood

C++-side of Objects

Value Primitive BooleanStringNumber

Date

Object

Array

Function

ExternalMonday, November 29, 2010

Page 57: JavaScript Engines: Under the Hood

Expose a Variable

Handle<ObjectTemplate> global = ObjectTemplate::New();global->Set("foobar", String::New(“Hello”));

Monday, November 29, 2010

Page 58: JavaScript Engines: Under the Hood

Expose a Function

Handle<FunctionTemplate> systemObject = FunctionTemplate::New();systemObject->Set(String::New("exit"), FunctionTemplate::New(system_exit)->GetFunction());

static Handle<Value> system_exit(const Arguments& args){ int status = args[0]->Int32Value(); ::exit(status); return Undefined();}

Monday, November 29, 2010

Page 59: JavaScript Engines: Under the Hood

DemoCode Formatter

Monday, November 29, 2010

Page 60: JavaScript Engines: Under the Hood

DemoSyntax Checker

Monday, November 29, 2010

Page 61: JavaScript Engines: Under the Hood

DemoCanvas-based Game

Monday, November 29, 2010

Page 62: JavaScript Engines: Under the Hood

http://10k.aneventapart.com/Entry/392

Monday, November 29, 2010

Page 63: JavaScript Engines: Under the Hood

DemoSyntax Parser

Monday, November 29, 2010

Page 64: JavaScript Engines: Under the Hood

Ext.extend

Ext.ComponentFoo = Ext.extend(Ext.ComponentBar, ....

depend

declare

Monday, November 29, 2010

Page 65: JavaScript Engines: Under the Hood

DemoCode Analyzer

Monday, November 29, 2010

Page 66: JavaScript Engines: Under the Hood

"type": "IfStatement","test": { "type": "BinaryExpression", "operator": "==", "left": { "type": "Identifier", "name": "x" }, "right": { "type": "Identifier", "name": "y" } }, "consequent": { "type": "ExpressionStatement", "expression": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "foo" }, "arguments": [] } }, "alternate": null

if (x == y) foo();

Monday, November 29, 2010

Page 67: JavaScript Engines: Under the Hood

"type": "IfStatement","test": { "type": "BinaryExpression", "operator": "==", "left": { "type": "Identifier", "name": "x" }, "right": { "type": "Identifier", "name": "y" } }, "consequent": { "type": "ExpressionStatement", "expression": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "foo" }, "arguments": [] } }, "alternate": null

if (x == y) foo();

Monday, November 29, 2010

Page 68: JavaScript Engines: Under the Hood

"type": "IfStatement","test": { "type": "BinaryExpression", "operator": "==", "left": { "type": "Identifier", "name": "x" }, "right": { "type": "Identifier", "name": "y" } }, "consequent": { "type": "ExpressionStatement", "expression": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "foo" }, "arguments": [] } }, "alternate": null

if (x == y) foo();

Danger!

Monday, November 29, 2010

Page 69: JavaScript Engines: Under the Hood

Debugging

Monday, November 29, 2010

Page 70: JavaScript Engines: Under the Hood

http://code.google.com/p/chromedevtoolsMonday, November 29, 2010

Page 71: JavaScript Engines: Under the Hood

(Remote) Debugging

v8::Debug::EnableAgent("foobar", 5858);

Monday, November 29, 2010

Page 72: JavaScript Engines: Under the Hood

(Remote) Debugging

v8::Debug::EnableAgent("foobar", 5858);

listening port

application name

Monday, November 29, 2010

Page 73: JavaScript Engines: Under the Hood

Profiling

Monday, November 29, 2010

Page 74: JavaScript Engines: Under the Hood

Activate Profiler

scons prof=on ...

shell --prof ....

tools/mac-tick-processor v8.log

Monday, November 29, 2010

Page 75: JavaScript Engines: Under the Hood

Function-Level Profile [JavaScript]: ticks total nonlib name 3125 5.9% 5.9% LazyCompile: am3 crypto.js:108 1036 2.0% 2.0% KeyedLoadIC: A keyed load IC from the snapshot 386 0.7% 0.7% LazyCompile: StringReplaceRegExp native string.js:243 362 0.7% 0.7% LazyCompile: Scheduler.schedule richards.js:188 326 0.6% 0.6% LazyCompile: one_way_unify1_nboyer earley-boyer.js:3635 301 0.6% 0.6% LazyCompile: exec native regexp.js:156 280 0.5% 0.5% LazyCompile: TaskControlBlock.isHeldOrSuspended richards.js:309 279 0.5% 0.5% KeyedStoreIC: A keyed store IC from the snapshot 278 0.5% 0.5% LazyCompile: rewrite_nboyer earley-boyer.js:3604 259 0.5% 0.5% LazyCompile: BuildResultFromMatchInfo native regexp.js:121 244 0.5% 0.5% LazyCompile: TaskControlBlock.run richards.js:324 186 0.4% 0.4% Stub: Instanceof

Monday, November 29, 2010

Page 76: JavaScript Engines: Under the Hood

THANK YOU!

Monday, November 29, 2010

Page 77: JavaScript Engines: Under the Hood

QUESTIONS?

ariya @ sencha.com

ariyahidayat

ariya.blogspot.com

Monday, November 29, 2010

Page 78: JavaScript Engines: Under the Hood

ADDENDUM

Monday, November 29, 2010

Page 79: JavaScript Engines: Under the Hood

Get SpiderMonkey

hg clone http://hg.mozilla.org/mozilla-central/cd mozilla-central/js/src

Monday, November 29, 2010

Page 80: JavaScript Engines: Under the Hood

Get JavaScriptCoresvn checkout http://svn.webkit.org/repository/webkit/trunk webkitcd webkit/JavaScriptCore

git clone git://git.webkit.org/WebKit.gitcd WebKit/JavaScriptCore

Monday, November 29, 2010

Page 81: JavaScript Engines: Under the Hood

Build SpiderMonkey

autoconf213./configure --disable-debug --enable-optimizemake

Monday, November 29, 2010

Page 82: JavaScript Engines: Under the Hood

Build JavaScriptCore

JavaScriptCore/JavaScriptCore.xcodeproj

JavaScriptCore

jsc

Monday, November 29, 2010

Page 83: JavaScript Engines: Under the Hood

perl sunspider --shell=/path/to/mozilla-central/js/src/build-release/js --args=-j

perl sunspider --shell=/path/to/webkit/JavaScriptCore/jsc

perl sunspider --shell=/path/to/v8/directory/shell --args=-expose-gc

Run your-favorite-benchmark

Monday, November 29, 2010

Page 84: JavaScript Engines: Under the Hood

perl sunspider --shell=/path/to/mozilla-central/js/src/build-release/js --args=-j

perl sunspider --shell=/path/to/webkit/JavaScriptCore/jsc

perl sunspider --shell=/path/to/v8/directory/shell --args=-expose-gc

Run your-favorite-benchmark

garbage collector

Monday, November 29, 2010

Page 85: JavaScript Engines: Under the Hood

Build JavaScriptCoreqmake -r DerivedSources.procd JavaScriptCoremake -f Makefile.DerivedSourcesqmake && makeqmake jsc.pro && make

Monday, November 29, 2010