Skip to content

Commit 31bb9b5

Browse files
author
Meghana Gupta
committed
Initial commit
1 parent c6759d6 commit 31bb9b5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+33065
-0
lines changed

test/benchmarks/ARES-6/ARES-6.svg

+4
Loading

test/benchmarks/ARES-6/Air/README.md

+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# All about Air.js
2+
3+
Air.js is an ES6 benchmark. It tries to faithfully use new features like arrow
4+
functions, classes, for-of, and Map/Set, among others. Air.js doesn't avoid any
5+
features out of fear that they might be slow, in the hope that we might learn
6+
how to make those features fast by looking at how Air.js and other benchmarks
7+
use them.
8+
9+
This documents the motivation, design, and license of Air.js.
10+
11+
To run Air.js, simply open "[Air.js/test.html](test.html)" in your browser. It
12+
will only run correctly if your browser supports ES6.
13+
14+
## Motivation
15+
16+
At the time that Air.js was written, most JavaScript benchmarks used ES5 or
17+
older versions of the language. ES6 testing mostly relied on microbenchmarks or
18+
conversions of existing tests to ES6. We try to use larger benchmarks to avoid
19+
over-optimizing for small pieces of code, and we avoid making changes to
20+
existing benchmarks because that approach has no limiting principle: if it's OK
21+
to change a benchmark to use a feature, does that mean we can also change it to
22+
remove the use of a feature we don't like? We feel that the best way to avoid
23+
falling into the trap of creating benchmarks that reinforce what some JS engine
24+
is already good at is to create a new benchmark from first principles.
25+
26+
We only recently completed our new JavaScript compiler, called
27+
[B3](https://webkit.org/blog/5852/introducing-the-b3-jit-compiler/). B3's
28+
backend, called
29+
[Air](https://webkit.org/docs/b3/assembly-intermediate-representation.html), is
30+
very CPU-intensive and uses a combination of object-oriented and functional
31+
idioms in C++. Additionally, it relies heavily on high speed maps and sets. It
32+
goes so far as to use customized map/set implementations - even more so than
33+
the rest of WebKit. This makes Air a great candidate for ES6 benchmarking.
34+
Air.js is a faithful ES6 implementation of Air. It pulls no punches: just as
35+
the original C++ Air was written with expressiveness as a top priority, Air.js
36+
is liberal in its use of modern ES6 idioms whenever this helps make the code
37+
more readable. Unlike the original C++ Air, Air.js doesn't exploit a deep
38+
understanding of compilers to make the code easy to compile.
39+
40+
## Design
41+
42+
Air.js runs one of the more expensive Air phases, Air::allocateStack(). This
43+
turns abstract stack references into concrete stack references, by selecting
44+
how to lay out stack slots in the stack frame. This requires liveness analysis
45+
and an interference graph.
46+
47+
Air.js relies on three major ES6 features more so than most of the others:
48+
49+
- Arrow functions. Like the C++ Air, Air.js uses a functional style of
50+
iterating most non-trivial data-structures:
51+
52+
inst.forEachArg((arg, role, type, width) => ...)
53+
54+
This is because the functional style allows the callbacks to mutate the data
55+
being iterated: if the callback returns a non-null value, forEachArg() will
56+
replace the argument with that value. This would not have been possible with
57+
for-of.
58+
59+
- For-of. Many Air data structures are amenable to for-of iteration. While the
60+
innermost loops tend to use functional iteration, pretty much all of the
61+
outer logic uses for-of heavily. For example:
62+
63+
for (let block of code) // Iterate over the basic blocks
64+
for (let inst of block) // Iterate over the instructions in a block
65+
...
66+
67+
- Map/Set. The liveness analysis and Air::allocateStack() rely on maps and
68+
sets. For example, we use a liveAtHead map that is keyed by basic block. Its
69+
values are sets of live stack slots. This is a relatively crude way of doing
70+
liveness, but it is exactly how the original Air::LivenessAnalysis worked, so
71+
we view it as being quite faithful to how a sensible programmer might use Map
72+
and Set.
73+
74+
Air.js also uses some other ES6 features. For example, it uses a Proxy
75+
in one place, though we doubt that it's on a critical path. Air.js uses classes
76+
and let/const extensively, as well a symbols. Symbols are used as enumeration
77+
elements, and so they frequently show up as cases in switch statements.
78+
79+
The workflow of an Air.js run is pretty simple: we do 150 runs of allocateStack
80+
on four IR payloads.
81+
82+
Each IR payload is a large piece of ES6 code that constructs an Air.js Code
83+
object, complete with blocks, temporaries, stack slots, and instructions. These
84+
payloads are generated by running Air::dumpAsJS() phase just prior to the
85+
native allocateStack phase on the largest hot function in four major JS
86+
benchmarks according to JavaScriptCore's internal profiling:
87+
88+
- Octane/GBEmu, the executeIteration function.
89+
- Kraken/imaging-gaussian-blur, the gaussianBlur function.
90+
- Octane/Typescript, the scanIdentifier function,
91+
- Air.js, an anonymous closure identified by our profiler as ACLj8C.
92+
93+
These payloads allow Air.js to precisely replay allocateStack on those actual
94+
functions.
95+
96+
It was an a priori goal of Air.js to spend most of the time in the
97+
allocateStack phase. This is a faithful reproduction of the C++ allocateStack
98+
phase, including its use of an abstract liveness analysis. It's abstract in the
99+
sense that the same liveness algorithm can be reused for temporaries,
100+
registers, or stack slots. In C++ this meant using templates, while in ES6 it
101+
means more run-time dynamic dispatch.
102+
103+
Each IR payload is executable code that allocates the IR, and about 15% of
104+
benchmark execution time is spent in that code. This is significant, but having
105+
learned this, we don't feel that it would be honest to try to change the
106+
efficiency of payload initialization. What if the payload initialization was
107+
more expensive on our engine than others? If it was, then such a change would
108+
not be fair.
109+
110+
Air.js validates its results. We added a Code hashing capability to both the
111+
C++ Air and Air.js, and we assert each payload looks identical after
112+
allocateStack to what it would have looked like after the original C++
113+
allocateStack. We also validate that payloads hash properly before
114+
allcoateStack, to help catch bugs during payload initialization. We have not
115+
measured how long hashing takes, but it's a O(N) operation, while allocateStack
116+
is closer to O(N^2). We suspect that barring some engine pathologies, hashing
117+
should be much faster than allocateStack, and allocateStack should be where the
118+
bulk of time is spent.
119+
120+
## License
121+
122+
Copyright (C) 2016 Apple Inc. All rights reserved.
123+
124+
Redistribution and use in source and binary forms, with or without
125+
modification, are permitted provided that the following conditions
126+
are met:
127+
128+
1. Redistributions of source code must retain the above copyright
129+
notice, this list of conditions and the following disclaimer.
130+
131+
2. Redistributions in binary form must reproduce the above copyright
132+
notice, this list of conditions and the following disclaimer in the
133+
documentation and/or other materials provided with the distribution.
134+
135+
THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
136+
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
137+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
138+
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
139+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
140+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
141+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
142+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
143+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
144+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
145+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
146+
147+
## Summary
148+
149+
At the time that Air.js was written, we weren't happy with the ES6 benchmarks
150+
that were available to us. Air.js uses some ES6 features in anger, in the hope
151+
that we can learn about possible optimization strategies by looking at this and
152+
other benchmarks.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright (C) 2016 Apple Inc. All rights reserved.
2+
#
3+
# Redistribution and use in source and binary forms, with or without
4+
# modification, are permitted provided that the following conditions
5+
# are met:
6+
#
7+
# 1. Redistributions of source code must retain the above copyright
8+
# notice, this list of conditions and the following disclaimer.
9+
# 2. Redistributions in binary form must reproduce the above copyright
10+
# notice, this list of conditions and the following disclaimer in the
11+
# documentation and/or other materials provided with the distribution.
12+
#
13+
# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
14+
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16+
# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22+
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23+
24+
- path: .
25+
tests:
26+
- stress-test.js
27+
cmd: defaultRunNoisyTest unless parseRunCommands
28+

test/benchmarks/ARES-6/Air/all.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"use strict";
2+
3+
load("symbols.js");
4+
load("tmp_base.js");
5+
load("arg.js");
6+
load("basic_block.js");
7+
load("code.js");
8+
load("frequented_block.js");
9+
load("inst.js");
10+
load("opcode.js");
11+
load("reg.js");
12+
load("stack_slot.js");
13+
load("tmp.js");
14+
load("util.js");
15+
load("custom.js");
16+
load("liveness.js");
17+
load("insertion_set.js");
18+
load("allocate_stack.js");

0 commit comments

Comments
 (0)