├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── LICENSE_1_0.txt
├── README.md
├── benchmark
├── base.js
├── crypto.js
├── deltablue.js
├── earley-boyer.js
├── raytrace.js
├── regexp.js
├── richards.js
├── run.ds
├── splay.js
└── v8 run.html
├── build.bat
├── build.sh
├── ds-ext
├── dub.json
└── source
│ └── ext.d
├── ds
├── dub.json
└── source
│ └── testscript.d
├── dub.json
├── engine
├── dub.json
└── source
│ └── dmdscript
│ ├── RandAA.d
│ ├── darguments.d
│ ├── darray.d
│ ├── dboolean.d
│ ├── ddate.d
│ ├── ddeclaredfunction.d
│ ├── derror.d
│ ├── dfunction.d
│ ├── dglobal.d
│ ├── dmath.d
│ ├── dnative.d
│ ├── dnumber.d
│ ├── dobject.d
│ ├── dregexp.d
│ ├── dstring.d
│ ├── errmsgs.d
│ ├── expression.d
│ ├── extending.d
│ ├── functiondefinition.d
│ ├── identifier.d
│ ├── ir.d
│ ├── irstate.d
│ ├── iterator.d
│ ├── lexer.d
│ ├── opcodes.d
│ ├── outbuffer.d
│ ├── parse.d
│ ├── patches.d
│ ├── program.d
│ ├── property.d
│ ├── protoerror.d
│ ├── scopex.d
│ ├── script.d
│ ├── statement.d
│ ├── symbol.d
│ ├── text.d
│ ├── threadcontext.d
│ ├── utf.d
│ └── value.d
├── ext.ds
├── readme.txt
├── run-test262.sh
├── samples
├── eval.ds
├── seive.ds
└── simple.ds
├── test262-patches
├── test262-_monkeyYaml.py.patch
├── test262-parseTestRecord.py.patch
└── test262-test262.py.patch
├── textgen.d
└── timed-dmdscript.sh
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Test Suite
2 |
3 | # Only triggers on pushes/PRs to master
4 | on:
5 | pull_request:
6 | branches:
7 | - master
8 | push:
9 | branches:
10 | - master
11 |
12 | jobs:
13 | test:
14 | name: CI
15 | strategy:
16 | fail-fast: false
17 | matrix:
18 | os: [ubuntu-latest, windows-latest]
19 | dc: [dmd-latest, ldc-latest, ldc-1.15.0]
20 | arch: [x86_64]
21 | include:
22 | - {os: windows-latest, dc: ldc-latest, arch: x86}
23 |
24 | runs-on: ${{ matrix.os }}
25 | steps:
26 | - uses: actions/checkout@v4
27 |
28 | - name: Install D compiler
29 | uses: dlang-community/setup-dlang@v2
30 | with:
31 | compiler: ${{ matrix.dc }}
32 |
33 | - name: Run tests
34 | shell: bash
35 | run: dub test :engine -a ${{matrix.arch}}
36 | testsuite:
37 | name: Test262
38 | strategy:
39 | fail-fast: false
40 | matrix:
41 | os: [ubuntu-latest]
42 | dc: [ldc-latest]
43 |
44 | runs-on: ${{ matrix.os }}
45 | steps:
46 | - uses: actions/checkout@v4
47 |
48 | - name: Install D compiler
49 | uses: dlang-community/setup-dlang@v2
50 | with:
51 | compiler: ${{matrix.dc}}
52 |
53 | - name: Run tests
54 | shell: bash
55 | run: ./run-test262.sh
56 |
57 | - name: Upload log
58 | uses: actions/upload-artifact@v3
59 | if: always()
60 | with:
61 | name: runtest262 log
62 | path: dmdscript-test262.log
63 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.a
2 | *.dll
3 | *.dylib
4 | *.exe
5 | *.lib
6 | *.lst
7 | *.o
8 | *.obj
9 | *.so
10 |
11 | .dub
12 | dub.selections.json
13 |
14 | /dmdscript
15 | /dmdscript-ext
16 | /ds/dmdscript_ds
17 | /ds-ext/dmdscript_ds-ext
18 |
--------------------------------------------------------------------------------
/LICENSE_1_0.txt:
--------------------------------------------------------------------------------
1 | Boost Software License - Version 1.0 - August 17th, 2003
2 |
3 | Permission is hereby granted, free of charge, to any person or organization
4 | obtaining a copy of the software and accompanying documentation covered by
5 | this license (the "Software") to use, reproduce, display, distribute,
6 | execute, and transmit the Software, and to prepare derivative works of the
7 | Software, and to permit third-parties to whom the Software is furnished to
8 | do so, all subject to the following:
9 |
10 | The copyright notices in the Software and this entire statement, including
11 | the above license grant, this restriction and the following disclaimer,
12 | must be included in all copies of the Software, in whole or in part, and
13 | all derivative works of the Software, unless such copies or derivative
14 | works are solely in the form of machine-executable object code generated by
15 | a source language processor.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | DMDScript
2 | =========
3 |
4 | An implementation of the ECMA 262 (Javascript) programming language
5 |
--------------------------------------------------------------------------------
/benchmark/base.js:
--------------------------------------------------------------------------------
1 | // Copyright 2008 the V8 project authors. All rights reserved.
2 | // Redistribution and use in source and binary forms, with or without
3 | // modification, are permitted provided that the following conditions are
4 | // met:
5 | //
6 | // * Redistributions of source code must retain the above copyright
7 | // notice, this list of conditions and the following disclaimer.
8 | // * Redistributions in binary form must reproduce the above
9 | // copyright notice, this list of conditions and the following
10 | // disclaimer in the documentation and/or other materials provided
11 | // with the distribution.
12 | // * Neither the name of Google Inc. nor the names of its
13 | // contributors may be used to endorse or promote products derived
14 | // from this software without specific prior written permission.
15 | //
16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
28 |
29 | // Simple framework for running the benchmark suites and
30 | // computing a score based on the timing measurements.
31 |
32 |
33 | // A benchmark has a name (string) and a function that will be run to
34 | // do the performance measurement. The optional setup and tearDown
35 | // arguments are functions that will be invoked before and after
36 | // running the benchmark, but the running time of these functions will
37 | // not be accounted for in the benchmark score.
38 | function Benchmark(name, run, setup, tearDown) {
39 | this.name = name;
40 | this.run = run;
41 | this.Setup = setup ? setup : function() { };
42 | this.TearDown = tearDown ? tearDown : function() { };
43 | }
44 |
45 |
46 | // Benchmark results hold the benchmark and the measured time used to
47 | // run the benchmark. The benchmark score is computed later once a
48 | // full benchmark suite has run to completion.
49 | function BenchmarkResult(benchmark, time) {
50 | this.benchmark = benchmark;
51 | this.time = time;
52 | }
53 |
54 |
55 | // Automatically convert results to numbers. Used by the geometric
56 | // mean computation.
57 | BenchmarkResult.prototype.valueOf = function() {
58 | return this.time;
59 | }
60 |
61 |
62 | // Suites of benchmarks consist of a name and the set of benchmarks in
63 | // addition to the reference timing that the final score will be based
64 | // on. This way, all scores are relative to a reference run and higher
65 | // scores implies better performance.
66 | function BenchmarkSuite(name, reference, benchmarks) {
67 | this.name = name;
68 | this.reference = reference;
69 | this.benchmarks = benchmarks;
70 | BenchmarkSuite.suites.push(this);
71 | }
72 |
73 |
74 | // Keep track of all declared benchmark suites.
75 | BenchmarkSuite.suites = [];
76 |
77 |
78 | // Scores are not comparable across versions. Bump the version if
79 | // you're making changes that will affect that scores, e.g. if you add
80 | // a new benchmark or change an existing one.
81 | BenchmarkSuite.version = '6';
82 |
83 |
84 | // To make the benchmark results predictable, we replace Math.random
85 | // with a 100% deterministic alternative.
86 | Math.random = (function() {
87 | var seed = 49734321;
88 | return function() {
89 | // Robert Jenkins' 32 bit integer hash function.
90 | seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff;
91 | seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
92 | seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff;
93 | seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff;
94 | seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff;
95 | seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
96 | return (seed & 0xfffffff) / 0x10000000;
97 | };
98 | })();
99 |
100 |
101 | // Runs all registered benchmark suites and optionally yields between
102 | // each individual benchmark to avoid running for too long in the
103 | // context of browsers. Once done, the final score is reported to the
104 | // runner.
105 | BenchmarkSuite.RunSuites = function(runner) {
106 | var continuation = null;
107 | var suites = BenchmarkSuite.suites;
108 | var length = suites.length;
109 | BenchmarkSuite.scores = [];
110 | var index = 0;
111 | function RunStep() {
112 | while (continuation || index < length) {
113 | if (continuation) {
114 | continuation = continuation();
115 | } else {
116 | var suite = suites[index++];
117 | if (runner.NotifyStart) runner.NotifyStart(suite.name);
118 | continuation = suite.RunStep(runner);
119 | }
120 | if (continuation && typeof window != 'undefined' && window.setTimeout) {
121 | window.setTimeout(RunStep, 25);
122 | return;
123 | }
124 | }
125 | if (runner.NotifyScore) {
126 | var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores);
127 | var formatted = BenchmarkSuite.FormatScore(100 * score);
128 | runner.NotifyScore(formatted);
129 | }
130 | }
131 | RunStep();
132 | }
133 |
134 |
135 | // Counts the total number of registered benchmarks. Useful for
136 | // showing progress as a percentage.
137 | BenchmarkSuite.CountBenchmarks = function() {
138 | var result = 0;
139 | var suites = BenchmarkSuite.suites;
140 | for (var i = 0; i < suites.length; i++) {
141 | result += suites[i].benchmarks.length;
142 | }
143 | return result;
144 | }
145 |
146 |
147 | // Computes the geometric mean of a set of numbers.
148 | BenchmarkSuite.GeometricMean = function(numbers) {
149 | var log = 0;
150 | for (var i = 0; i < numbers.length; i++) {
151 | log += Math.log(numbers[i]);
152 | }
153 | return Math.pow(Math.E, log / numbers.length);
154 | }
155 |
156 |
157 | // Converts a score value to a string with at least three significant
158 | // digits.
159 | BenchmarkSuite.FormatScore = function(value) {
160 | if (value > 100) {
161 | return value.toFixed(0);
162 | } else {
163 | return value.toPrecision(3);
164 | }
165 | }
166 |
167 | // Notifies the runner that we're done running a single benchmark in
168 | // the benchmark suite. This can be useful to report progress.
169 | BenchmarkSuite.prototype.NotifyStep = function(result) {
170 | this.results.push(result);
171 | if (this.runner.NotifyStep) this.runner.NotifyStep(result.benchmark.name);
172 | }
173 |
174 |
175 | // Notifies the runner that we're done with running a suite and that
176 | // we have a result which can be reported to the user if needed.
177 | BenchmarkSuite.prototype.NotifyResult = function() {
178 | var mean = BenchmarkSuite.GeometricMean(this.results);
179 | var score = this.reference / mean;
180 | BenchmarkSuite.scores.push(score);
181 | if (this.runner.NotifyResult) {
182 | var formatted = BenchmarkSuite.FormatScore(100 * score);
183 | this.runner.NotifyResult(this.name, formatted);
184 | }
185 | }
186 |
187 |
188 | // Notifies the runner that running a benchmark resulted in an error.
189 | BenchmarkSuite.prototype.NotifyError = function(error) {
190 | if (this.runner.NotifyError) {
191 | this.runner.NotifyError(this.name, error);
192 | }
193 | if (this.runner.NotifyStep) {
194 | this.runner.NotifyStep(this.name);
195 | }
196 | }
197 |
198 |
199 | // Runs a single benchmark for at least a second and computes the
200 | // average time it takes to run a single iteration.
201 | BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) {
202 | function Measure(data) {
203 | var elapsed = 0;
204 | var start = new Date();
205 | for (var n = 0; elapsed < 1000; n++) {
206 | benchmark.run();
207 | elapsed = new Date() - start;
208 | }
209 | if (data != null) {
210 | data.runs += n;
211 | data.elapsed += elapsed;
212 | }
213 | }
214 |
215 | if (data == null) {
216 | // Measure the benchmark once for warm up and throw the result
217 | // away. Return a fresh data object.
218 | Measure(null);
219 | return { runs: 0, elapsed: 0 };
220 | } else {
221 | Measure(data);
222 | // If we've run too few iterations, we continue for another second.
223 | if (data.runs < 32) return data;
224 | var usec = (data.elapsed * 1000) / data.runs;
225 | this.NotifyStep(new BenchmarkResult(benchmark, usec));
226 | return null;
227 | }
228 | }
229 |
230 |
231 | // This function starts running a suite, but stops between each
232 | // individual benchmark in the suite and returns a continuation
233 | // function which can be invoked to run the next benchmark. Once the
234 | // last benchmark has been executed, null is returned.
235 | BenchmarkSuite.prototype.RunStep = function(runner) {
236 | this.results = [];
237 | this.runner = runner;
238 | var length = this.benchmarks.length;
239 | var index = 0;
240 | var suite = this;
241 | var data;
242 |
243 | // Run the setup, the actual benchmark, and the tear down in three
244 | // separate steps to allow the framework to yield between any of the
245 | // steps.
246 |
247 | function RunNextSetup() {
248 | if (index < length) {
249 | try {
250 | suite.benchmarks[index].Setup();
251 | } catch (e) {
252 | suite.NotifyError(e);
253 | return null;
254 | }
255 | return RunNextBenchmark;
256 | }
257 | suite.NotifyResult();
258 | return null;
259 | }
260 |
261 | function RunNextBenchmark() {
262 | try {
263 | data = suite.RunSingleBenchmark(suite.benchmarks[index], data);
264 | } catch (e) {
265 | suite.NotifyError(e);
266 | return null;
267 | }
268 | // If data is null, we're done with this benchmark.
269 | return (data == null) ? RunNextTearDown : RunNextBenchmark();
270 | }
271 |
272 | function RunNextTearDown() {
273 | try {
274 | suite.benchmarks[index++].TearDown();
275 | } catch (e) {
276 | suite.NotifyError(e);
277 | return null;
278 | }
279 | return RunNextSetup;
280 | }
281 |
282 | // Start out running the setup.
283 | return RunNextSetup();
284 | }
285 |
--------------------------------------------------------------------------------
/benchmark/run.ds:
--------------------------------------------------------------------------------
1 | function Run() {
2 | BenchmarkSuite.RunSuites({ NotifyStep: ShowProgress,
3 | NotifyError: AddError,
4 | NotifyResult: AddResult,
5 | NotifyScore: AddScore });
6 | }
7 | var completed = 0;
8 | var benchmarks = BenchmarkSuite.CountBenchmarks();
9 | var success = true;
10 |
11 | function ShowProgress(name) {
12 | var percentage = ((++completed) / benchmarks) * 100;
13 | println("\rRunning: " + Math.round(percentage) + "% completed.");
14 | }
15 |
16 | function AddResult(name, result) {
17 | var text = name + ': ' + result;
18 | println(text);
19 | }
20 |
21 |
22 | function AddError(name, error) {
23 | AddResult(name, 'error');
24 | //println(text);
25 | success = false;
26 | }
27 |
28 |
29 | function AddScore(score) {
30 | if (success) {
31 | //results.push("Score: " + score);
32 | }
33 | }
34 |
35 | function Run() {
36 | BenchmarkSuite.RunSuites({ NotifyStep: ShowProgress,
37 | NotifyError: AddError,
38 | NotifyResult: AddResult,
39 | NotifyScore: AddScore });
40 | }
41 |
42 |
43 | println("Version: ", BenchmarkSuite.version);
44 | Run();
45 |
46 |
--------------------------------------------------------------------------------
/benchmark/splay.js:
--------------------------------------------------------------------------------
1 | // Copyright 2009 the V8 project authors. All rights reserved.
2 | // Redistribution and use in source and binary forms, with or without
3 | // modification, are permitted provided that the following conditions are
4 | // met:
5 | //
6 | // * Redistributions of source code must retain the above copyright
7 | // notice, this list of conditions and the following disclaimer.
8 | // * Redistributions in binary form must reproduce the above
9 | // copyright notice, this list of conditions and the following
10 | // disclaimer in the documentation and/or other materials provided
11 | // with the distribution.
12 | // * Neither the name of Google Inc. nor the names of its
13 | // contributors may be used to endorse or promote products derived
14 | // from this software without specific prior written permission.
15 | //
16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
28 | // This benchmark is based on a JavaScript log processing module used
29 | // by the V8 profiler to generate execution time profiles for runs of
30 | // JavaScript applications, and it effectively measures how fast the
31 | // JavaScript engine is at allocating nodes and reclaiming the memory
32 | // used for old nodes. Because of the way splay trees work, the engine
33 | // also has to deal with a lot of changes to the large tree object
34 | // graph.
35 |
36 | var Splay = new BenchmarkSuite('Splay', 81491, [
37 | new Benchmark("Splay", SplayRun, SplaySetup, SplayTearDown)
38 | ]);
39 |
40 |
41 | // Configuration.
42 | var kSplayTreeSize = 8000;
43 | var kSplayTreeModifications = 80;
44 | var kSplayTreePayloadDepth = 5;
45 |
46 | var splayTree = null;
47 |
48 |
49 | function GeneratePayloadTree(depth, tag) {
50 | if (depth == 0) {
51 | return {
52 | array : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
53 | string : 'String for key ' + tag + ' in leaf node'
54 | };
55 | } else {
56 | return {
57 | left: GeneratePayloadTree(depth - 1, tag),
58 | right: GeneratePayloadTree(depth - 1, tag)
59 | };
60 | }
61 | }
62 |
63 |
64 | function GenerateKey() {
65 | // The benchmark framework guarantees that Math.random is
66 | // deterministic; see base.js.
67 | return Math.random();
68 | }
69 |
70 |
71 | function InsertNewNode() {
72 | // Insert new node with a unique key.
73 | var key;
74 | do {
75 | key = GenerateKey();
76 | } while (splayTree.find(key) != null);
77 | var payload = GeneratePayloadTree(kSplayTreePayloadDepth, String(key));
78 | splayTree.insert(key, payload);
79 | return key;
80 | }
81 |
82 |
83 |
84 | function SplaySetup() {
85 | splayTree = new SplayTree();
86 | for (var i = 0; i < kSplayTreeSize; i++) InsertNewNode();
87 | }
88 |
89 |
90 | function SplayTearDown() {
91 | // Allow the garbage collector to reclaim the memory
92 | // used by the splay tree no matter how we exit the
93 | // tear down function.
94 | var keys = splayTree.exportKeys();
95 | splayTree = null;
96 |
97 | // Verify that the splay tree has the right size.
98 | var length = keys.length;
99 | if (length != kSplayTreeSize) {
100 | throw new Error("Splay tree has wrong size");
101 | }
102 |
103 | // Verify that the splay tree has sorted, unique keys.
104 | for (var i = 0; i < length - 1; i++) {
105 | if (keys[i] >= keys[i + 1]) {
106 | throw new Error("Splay tree not sorted");
107 | }
108 | }
109 | }
110 |
111 |
112 | function SplayRun() {
113 | // Replace a few nodes in the splay tree.
114 | for (var i = 0; i < kSplayTreeModifications; i++) {
115 | var key = InsertNewNode();
116 | var greatest = splayTree.findGreatestLessThan(key);
117 | if (greatest == null) splayTree.remove(key);
118 | else splayTree.remove(greatest.key);
119 | }
120 | }
121 |
122 |
123 | /**
124 | * Constructs a Splay tree. A splay tree is a self-balancing binary
125 | * search tree with the additional property that recently accessed
126 | * elements are quick to access again. It performs basic operations
127 | * such as insertion, look-up and removal in O(log(n)) amortized time.
128 | *
129 | * @constructor
130 | */
131 | function SplayTree() {
132 | };
133 |
134 |
135 | /**
136 | * Pointer to the root node of the tree.
137 | *
138 | * @type {SplayTree.Node}
139 | * @private
140 | */
141 | SplayTree.prototype.root_ = null;
142 |
143 |
144 | /**
145 | * @return {boolean} Whether the tree is empty.
146 | */
147 | SplayTree.prototype.isEmpty = function() {
148 | return !this.root_;
149 | };
150 |
151 |
152 | /**
153 | * Inserts a node into the tree with the specified key and value if
154 | * the tree does not already contain a node with the specified key. If
155 | * the value is inserted, it becomes the root of the tree.
156 | *
157 | * @param {number} key Key to insert into the tree.
158 | * @param {*} value Value to insert into the tree.
159 | */
160 | SplayTree.prototype.insert = function(key, value) {
161 | if (this.isEmpty()) {
162 | this.root_ = new SplayTree.Node(key, value);
163 | return;
164 | }
165 | // Splay on the key to move the last node on the search path for
166 | // the key to the root of the tree.
167 | this.splay_(key);
168 | if (this.root_.key == key) {
169 | return;
170 | }
171 | var node = new SplayTree.Node(key, value);
172 | if (key > this.root_.key) {
173 | node.left = this.root_;
174 | node.right = this.root_.right;
175 | this.root_.right = null;
176 | } else {
177 | node.right = this.root_;
178 | node.left = this.root_.left;
179 | this.root_.left = null;
180 | }
181 | this.root_ = node;
182 | };
183 |
184 |
185 | /**
186 | * Removes a node with the specified key from the tree if the tree
187 | * contains a node with this key. The removed node is returned. If the
188 | * key is not found, an exception is thrown.
189 | *
190 | * @param {number} key Key to find and remove from the tree.
191 | * @return {SplayTree.Node} The removed node.
192 | */
193 | SplayTree.prototype.remove = function(key) {
194 | if (this.isEmpty()) {
195 | throw Error('Key not found: ' + key);
196 | }
197 | this.splay_(key);
198 | if (this.root_.key != key) {
199 | throw Error('Key not found: ' + key);
200 | }
201 | var removed = this.root_;
202 | if (!this.root_.left) {
203 | this.root_ = this.root_.right;
204 | } else {
205 | var right = this.root_.right;
206 | this.root_ = this.root_.left;
207 | // Splay to make sure that the new root has an empty right child.
208 | this.splay_(key);
209 | // Insert the original right child as the right child of the new
210 | // root.
211 | this.root_.right = right;
212 | }
213 | return removed;
214 | };
215 |
216 |
217 | /**
218 | * Returns the node having the specified key or null if the tree doesn't contain
219 | * a node with the specified key.
220 | *
221 | * @param {number} key Key to find in the tree.
222 | * @return {SplayTree.Node} Node having the specified key.
223 | */
224 | SplayTree.prototype.find = function(key) {
225 | if (this.isEmpty()) {
226 | return null;
227 | }
228 | this.splay_(key);
229 | return this.root_.key == key ? this.root_ : null;
230 | };
231 |
232 |
233 | /**
234 | * @return {SplayTree.Node} Node having the maximum key value.
235 | */
236 | SplayTree.prototype.findMax = function(opt_startNode) {
237 | if (this.isEmpty()) {
238 | return null;
239 | }
240 | var current = opt_startNode || this.root_;
241 | while (current.right) {
242 | current = current.right;
243 | }
244 | return current;
245 | };
246 |
247 |
248 | /**
249 | * @return {SplayTree.Node} Node having the maximum key value that
250 | * is less than the specified key value.
251 | */
252 | SplayTree.prototype.findGreatestLessThan = function(key) {
253 | if (this.isEmpty()) {
254 | return null;
255 | }
256 | // Splay on the key to move the node with the given key or the last
257 | // node on the search path to the top of the tree.
258 | this.splay_(key);
259 | // Now the result is either the root node or the greatest node in
260 | // the left subtree.
261 | if (this.root_.key < key) {
262 | return this.root_;
263 | } else if (this.root_.left) {
264 | return this.findMax(this.root_.left);
265 | } else {
266 | return null;
267 | }
268 | };
269 |
270 |
271 | /**
272 | * @return {Array<*>} An array containing all the keys of tree's nodes.
273 | */
274 | SplayTree.prototype.exportKeys = function() {
275 | var result = [];
276 | if (!this.isEmpty()) {
277 | this.root_.traverse_(function(node) { result.push(node.key); });
278 | }
279 | return result;
280 | };
281 |
282 |
283 | /**
284 | * Perform the splay operation for the given key. Moves the node with
285 | * the given key to the top of the tree. If no node has the given
286 | * key, the last node on the search path is moved to the top of the
287 | * tree. This is the simplified top-down splaying algorithm from:
288 | * "Self-adjusting Binary Search Trees" by Sleator and Tarjan
289 | *
290 | * @param {number} key Key to splay the tree on.
291 | * @private
292 | */
293 | SplayTree.prototype.splay_ = function(key) {
294 | if (this.isEmpty()) {
295 | return;
296 | }
297 | // Create a dummy node. The use of the dummy node is a bit
298 | // counter-intuitive: The right child of the dummy node will hold
299 | // the L tree of the algorithm. The left child of the dummy node
300 | // will hold the R tree of the algorithm. Using a dummy node, left
301 | // and right will always be nodes and we avoid special cases.
302 | var dummy, left, right;
303 | dummy = left = right = new SplayTree.Node(null, null);
304 | var current = this.root_;
305 | while (true) {
306 | if (key < current.key) {
307 | if (!current.left) {
308 | break;
309 | }
310 | if (key < current.left.key) {
311 | // Rotate right.
312 | var tmp = current.left;
313 | current.left = tmp.right;
314 | tmp.right = current;
315 | current = tmp;
316 | if (!current.left) {
317 | break;
318 | }
319 | }
320 | // Link right.
321 | right.left = current;
322 | right = current;
323 | current = current.left;
324 | } else if (key > current.key) {
325 | if (!current.right) {
326 | break;
327 | }
328 | if (key > current.right.key) {
329 | // Rotate left.
330 | var tmp = current.right;
331 | current.right = tmp.left;
332 | tmp.left = current;
333 | current = tmp;
334 | if (!current.right) {
335 | break;
336 | }
337 | }
338 | // Link left.
339 | left.right = current;
340 | left = current;
341 | current = current.right;
342 | } else {
343 | break;
344 | }
345 | }
346 | // Assemble.
347 | left.right = current.left;
348 | right.left = current.right;
349 | current.left = dummy.right;
350 | current.right = dummy.left;
351 | this.root_ = current;
352 | };
353 |
354 |
355 | /**
356 | * Constructs a Splay tree node.
357 | *
358 | * @param {number} key Key.
359 | * @param {*} value Value.
360 | */
361 | SplayTree.Node = function(key, value) {
362 | this.key = key;
363 | this.value = value;
364 | };
365 |
366 |
367 | /**
368 | * @type {SplayTree.Node}
369 | */
370 | SplayTree.Node.prototype.left = null;
371 |
372 |
373 | /**
374 | * @type {SplayTree.Node}
375 | */
376 | SplayTree.Node.prototype.right = null;
377 |
378 |
379 | /**
380 | * Performs an ordered traversal of the subtree starting at
381 | * this SplayTree.Node.
382 | *
383 | * @param {function(SplayTree.Node)} f Visitor function.
384 | * @private
385 | */
386 | SplayTree.Node.prototype.traverse_ = function(f) {
387 | var current = this;
388 | while (current) {
389 | var left = current.left;
390 | if (left) left.traverse_(f);
391 | f(current);
392 | current = current.right;
393 | }
394 | };
395 |
--------------------------------------------------------------------------------
/benchmark/v8 run.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
96 | Warning! This is not the latest version of the V8 benchmark
97 | suite. Consider running the
98 |
99 | latest version.
100 |
101 |
102 |
103 |
104 | This page contains a suite of pure JavaScript benchmarks that we have
105 | used to tune V8. The final score is computed as the geometric mean of
106 | the individual results to make it independent of the running times of
107 | the individual benchmarks and of a reference system (score
108 | 100). Scores are not comparable across benchmark suite versions and
109 | higher scores means better performance: Bigger is better!
110 |
111 |
112 |
Richards OS kernel simulation benchmark, originally written in BCPL by Martin Richards (539 lines).
113 |
DeltaBlue One-way constraint solver, originally written in Smalltalk by John Maloney and Mario Wolczko (880 lines).
114 |
Crypto Encryption and decryption benchmark based on code by Tom Wu (1698 lines).
115 |
RayTrace Ray tracer benchmark based on code by Adam Burmister (904 lines).
116 |
EarleyBoyer Classic Scheme benchmarks, translated to JavaScript by Florian Loitsch's Scheme2Js compiler (4684 lines).
117 |
RegExp Regular expression benchmark generated by extracting regular expression operations from 50 of the most popular web pages
118 | (1761 lines).
119 |
120 |
Splay Data manipulation benchmark that deals with splay trees and exercises the automatic memory management subsystem (394 lines).
121 |
122 |
123 |
124 | Note that benchmark results are not comparable unless both results are
125 | run with the same revision of the benchmark suite. We will be making
126 | revisions from time to time in order to fix bugs or expand the scope
127 | of the benchmark suite. For previous revisions and the change log see
128 | the revisions page.
129 |