It should be easy to run ES6SampleBench from the jsc shell
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Aug 2016 03:39:33 +0000 (03:39 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Aug 2016 03:39:33 +0000 (03:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161085

Reviewed by Yusuke Suzuki.

PerformanceTests:

This patch makes ES6 sample bench runnable through the `jsc` shell.
To do that, you need to be in the PerformanceTests/ES6SampleBench
directory and run `jsc cli.js`. To make this work, the benchmark
is now aware of being run in two modes: via the browser, and via
the shell. Each entry point will set a variable `isInBrowser`,
and the benchmark will do different things based on if that
variable is true or false.

* ES6SampleBench/Air/benchmark.js:
* ES6SampleBench/Air/stress-test.js:
* ES6SampleBench/Basic/benchmark.js:
(runBenchmark):
* ES6SampleBench/Basic/stress-test.js:
* ES6SampleBench/air_benchmark.js:
* ES6SampleBench/basic_benchmark.js:
* ES6SampleBench/cli.js: Added.
(return.doRun):
(makeBenchmarkRunner):
* ES6SampleBench/driver.js:
(Driver):
(Driver.prototype._recomputeSummary):
(Driver.prototype._iterate.window.setTimeout):
(Driver.prototype._iterate):
(Driver.prototype._updateIterations):
* ES6SampleBench/glue.js:
(reportResult):
* ES6SampleBench/index.html:
* ES6SampleBench/results.js:
(Results):
(Results.prototype.reportRunning):
(Results.prototype.reportDone):
(Results.prototype.reportError):
* ES6SampleBench/stats.js:
(Stats):
(Stats.prototype.toString):
(Stats.prototype._update):

Source/JavaScriptCore:

This patch adds a new function called `runString` to the shell.
It takes in a string, and executes it in a new global object.
Then, it returns the global object it executed the code in.
This allows the code to stash some kind of a result on the global,
and then have the caller of `runString` extract the result.

* jsc.cpp:
(GlobalObject::finishCreation):
(functionRunString):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@204882 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
PerformanceTests/ChangeLog
PerformanceTests/ES6SampleBench/Air/benchmark.js
PerformanceTests/ES6SampleBench/Air/stress-test.js
PerformanceTests/ES6SampleBench/Basic/benchmark.js
PerformanceTests/ES6SampleBench/Basic/stress-test.js
PerformanceTests/ES6SampleBench/air_benchmark.js
PerformanceTests/ES6SampleBench/basic_benchmark.js
PerformanceTests/ES6SampleBench/cli.js [new file with mode: 0644]
PerformanceTests/ES6SampleBench/driver.js
PerformanceTests/ES6SampleBench/glue.js
PerformanceTests/ES6SampleBench/index.html
PerformanceTests/ES6SampleBench/results.js
PerformanceTests/ES6SampleBench/stats.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/jsc.cpp

index c879108..3a6ad32 100644 (file)
@@ -1,3 +1,47 @@
+2016-08-23  Saam Barati  <sbarati@apple.com>
+
+        It should be easy to run ES6SampleBench from the jsc shell
+        https://bugs.webkit.org/show_bug.cgi?id=161085
+
+        Reviewed by Yusuke Suzuki.
+
+        This patch makes ES6 sample bench runnable through the `jsc` shell.
+        To do that, you need to be in the PerformanceTests/ES6SampleBench
+        directory and run `jsc cli.js`. To make this work, the benchmark
+        is now aware of being run in two modes: via the browser, and via
+        the shell. Each entry point will set a variable `isInBrowser`,
+        and the benchmark will do different things based on if that
+        variable is true or false.
+
+        * ES6SampleBench/Air/benchmark.js:
+        * ES6SampleBench/Air/stress-test.js:
+        * ES6SampleBench/Basic/benchmark.js:
+        (runBenchmark):
+        * ES6SampleBench/Basic/stress-test.js:
+        * ES6SampleBench/air_benchmark.js:
+        * ES6SampleBench/basic_benchmark.js:
+        * ES6SampleBench/cli.js: Added.
+        (return.doRun):
+        (makeBenchmarkRunner):
+        * ES6SampleBench/driver.js:
+        (Driver):
+        (Driver.prototype._recomputeSummary):
+        (Driver.prototype._iterate.window.setTimeout):
+        (Driver.prototype._iterate):
+        (Driver.prototype._updateIterations):
+        * ES6SampleBench/glue.js:
+        (reportResult):
+        * ES6SampleBench/index.html:
+        * ES6SampleBench/results.js:
+        (Results):
+        (Results.prototype.reportRunning):
+        (Results.prototype.reportDone):
+        (Results.prototype.reportError):
+        * ES6SampleBench/stats.js:
+        (Stats):
+        (Stats.prototype.toString):
+        (Stats.prototype._update):
+
 2016-08-01  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         Add an option to run the MotionMark tests with classic tile size (512x512)
index de49a37..278f201 100644 (file)
@@ -24,7 +24,7 @@
  */
 "use strict";
 
-class Benchmark {
+class AirBenchmark {
     constructor(verbose = 0)
     {
         this._verbose = verbose;
index 02bf937..b2cfa43 100644 (file)
@@ -31,7 +31,7 @@ load("payload-airjs-ACLj8C.js");
 load("payload-typescript-scanIdentifier.js");
 load("benchmark.js");
 
-let benchmark = new Benchmark();
+let benchmark = new AirBenchmark();
 let before = preciseTime();
 
 // Run for at least 10 iterations.
index 9ec071c..7730411 100644 (file)
@@ -24,7 +24,7 @@
  */
 "use strict";
 
-class Benchmark {
+class BasicBenchmark {
     constructor(verbose = 0)
     {
         this._verbose = verbose;
@@ -63,4 +63,3 @@ function runBenchmark()
     let after = currentTime();
     return after - before;
 }
-
index 75a5b42..c169c07 100644 (file)
@@ -35,7 +35,7 @@ load("state.js");
 load("util.js");
 load("benchmark.js");
 
-let benchmark = new Benchmark();
+let benchmark = new BasicBenchmark();
 let before = preciseTime();
 
 // Run for at least 10 iterations.
index 33cac4e..6397c4f 100644 (file)
@@ -48,7 +48,7 @@ const AirBenchmarkCode = String.raw`
 <script src="Air/benchmark.js"></script>
 <script>
 var results = [];
-var benchmark = new Benchmark();
+var benchmark = new AirBenchmark();
 var numIterations = 200;
 for (var i = 0; i < numIterations; ++i) {
     var before = currentTime();
@@ -59,13 +59,47 @@ for (var i = 0; i < numIterations; ++i) {
 reportResult(results);
 </script>`;
 
-const AirBenchmark = {
+let runAirBenchmark = null;
+if (!isInBrowser) {
+    let sources = [
+        "Air/symbols.js"
+        , "Air/tmp_base.js"
+        , "Air/arg.js"
+        , "Air/basic_block.js"
+        , "Air/code.js"
+        , "Air/frequented_block.js"
+        , "Air/inst.js"
+        , "Air/opcode.js"
+        , "Air/reg.js"
+        , "Air/stack_slot.js"
+        , "Air/tmp.js"
+        , "Air/util.js"
+        , "Air/custom.js"
+        , "Air/liveness.js"
+        , "Air/insertion_set.js"
+        , "Air/allocate_stack.js"
+        , "Air/payload-gbemu-executeIteration.js"
+        , "Air/payload-imaging-gaussian-blur-gaussianBlur.js"
+        , "Air/payload-airjs-ACLj8C.js"
+        , "Air/payload-typescript-scanIdentifier.js"
+        , "Air/benchmark.js"
+    ];
+
+    runAirBenchmark = makeBenchmarkRunner(sources, "AirBenchmark");
+}
+
+const AirBenchmarkRunner = {
     code: AirBenchmarkCode,
-    cells: {
+    run: runAirBenchmark,
+    cells: { },
+    name: "Air"
+};
+
+if (isInBrowser) {
+    AirBenchmarkRunner.cells = {
         firstIteration: document.getElementById("AirFirstIteration"),
         averageWorstCase: document.getElementById("AirAverageWorstCase"),
         steadyState: document.getElementById("AirSteadyState"),
         message: document.getElementById("AirMessage")
     }
-};
-
+}
index 4ed5ab5..8e7df84 100644 (file)
@@ -37,7 +37,7 @@ const BasicBenchmarkCode = String.raw`
 <script src="Basic/benchmark.js"></script>
 <script>
 var results = [];
-var benchmark = new Benchmark();
+var benchmark = new BasicBenchmark();
 var numIterations = 200;
 for (var i = 0; i < numIterations; ++i) {
     var before = currentTime();
@@ -48,12 +48,37 @@ for (var i = 0; i < numIterations; ++i) {
 reportResult(results);
 </script>`;
 
-const BasicBenchmark = {
+
+let runBasicBenchmark = null;
+if (!isInBrowser) {
+    let sources = [
+        "Basic/ast.js"
+        , "Basic/basic.js"
+        , "Basic/caseless_map.js"
+        , "Basic/lexer.js"
+        , "Basic/number.js"
+        , "Basic/parser.js"
+        , "Basic/random.js"
+        , "Basic/state.js"
+        , "Basic/util.js"
+        , "Basic/benchmark.js"
+    ];
+
+    runBasicBenchmark = makeBenchmarkRunner(sources, "BasicBenchmark");
+}
+
+const BasicBenchmarkRunner = {
+    name: "Basic",
     code: BasicBenchmarkCode,
-    cells: {
+    run: runBasicBenchmark,
+    cells: {}
+};
+
+if (isInBrowser) {
+    BasicBenchmarkRunner.cells = {
         firstIteration: document.getElementById("BasicFirstIteration"),
         averageWorstCase: document.getElementById("BasicAverageWorstCase"),
         steadyState: document.getElementById("BasicSteadyState"),
         message: document.getElementById("BasicMessage")
-    }
-};
+    };
+}
diff --git a/PerformanceTests/ES6SampleBench/cli.js b/PerformanceTests/ES6SampleBench/cli.js
new file mode 100644 (file)
index 0000000..c1dd3a8
--- /dev/null
@@ -0,0 +1,33 @@
+const isInBrowser = false;
+
+function makeBenchmarkRunner(sources, benchmarkConstructor) {
+    let source = "'use strict';"
+    for (let file of sources) {
+        source += readFile(file);
+    }
+    source += `
+        this.results = [];
+        var benchmark = new ${benchmarkConstructor}();
+        var numIterations = 200;
+        for (var i = 0; i < numIterations; ++i) {
+            var before = currentTime();
+            benchmark.runIteration();
+            var after = currentTime();
+            results.push(after - before);
+        }
+    `;
+    return function doRun() {
+        let globalObjectOfScript = runString(source);
+        let results = globalObjectOfScript.results;
+        reportResult(results);
+    }
+}
+
+load("driver.js");
+load("results.js");
+load("stats.js");
+load("air_benchmark.js");
+load("basic_benchmark.js");
+load("glue.js");
+
+driver.start(10);
index 2152eca..609a562 100644 (file)
@@ -31,10 +31,11 @@ class Driver {
         this._triggerCell = triggerCell;
         this._triggerLink = triggerLink;
         this._magicCell = magicCell;
-        this._summary = new Stats(summaryCell);
+        this._summary = new Stats(summaryCell, "summary");
         this._key = key;
         this._hadErrors = false;
-        window[key] = this;
+        if (isInBrowser)
+            window[key] = this;
     }
     
     addBenchmark(benchmark)
@@ -96,7 +97,7 @@ class Driver {
             for (let subResult of Results.subResults)
                 statses.push(results[subResult]);
         }
-        
+
         let numIterations = Math.min(...statses.map(stats => stats.numIterations));
         let data = new Array(numIterations);
         for (let i = 0; i < data.length; ++i)
@@ -117,9 +118,12 @@ class Driver {
         this._benchmark = this._iterator ? this._iterator.next().value : null;
         if (!this._benchmark) {
             if (!this._numIterations) {
-                this._triggerCell.innerHTML =
-                    (this._hadErrors ? "Failures encountered!" : "Success!") +
-                    ` <a href="${this._triggerLink}">Restart Benchmark</a>`;
+                if (isInBrowser) {
+                    this._triggerCell.innerHTML =
+                        (this._hadErrors ? "Failures encountered!" : "Success!") +
+                        ` <a href="${this._triggerLink}">Restart Benchmark</a>`;
+                } else
+                    print(this._hadErrors ? "Failures encountered!" : "Success! Benchmark is now finished.");
                 return;
             }
             this._numIterations--;
@@ -130,31 +134,48 @@ class Driver {
         
         this._benchmarks.get(this._benchmark).reportRunning();
         
-        window.setTimeout(() => {
-            if (!this._isRunning)
-                return;
-            
-            this._magicCell.contentDocument.body.textContent = "";
-            this._magicCell.contentDocument.body.innerHTML = "<iframe id=\"magicFrame\" frameborder=\"0\">";
-            
-            let magicFrame = this._magicCell.contentDocument.getElementById("magicFrame");
-            magicFrame.contentDocument.open();
-            magicFrame.contentDocument.write(
-                `<!DOCTYPE html><head><title>benchmark payload</title></head><body><script>` +
-                `window.onerror = top.${this._key}.reportError;\n` +
-                `function reportResult()\n` +
-                `{\n` +
-                `    var driver = top.${this._key};\n` +
-                `    driver.reportResult.apply(driver, arguments);\n` +
-                `}\n` +
-                `</script>\n` +
-                `${this._benchmark.code}</body></html>`);
-        }, 100);
+        let benchmark = this._benchmark;
+        if (isInBrowser) {
+            window.setTimeout(() => {
+                if (!this._isRunning)
+                    return;
+                
+                this._magicCell.contentDocument.body.textContent = "";
+                this._magicCell.contentDocument.body.innerHTML = "<iframe id=\"magicFrame\" frameborder=\"0\">";
+                
+                let magicFrame = this._magicCell.contentDocument.getElementById("magicFrame");
+                magicFrame.contentDocument.open();
+                magicFrame.contentDocument.write(
+                    `<!DOCTYPE html><head><title>benchmark payload</title></head><body><script>` +
+                    `window.onerror = top.${this._key}.reportError;\n` +
+                    `function reportResult()\n` +
+                    `{\n` +
+                    `    var driver = top.${this._key};\n` +
+                    `    driver.reportResult.apply(driver, arguments);\n` +
+                    `}\n` +
+                    `</script>\n` +
+                    `${this._benchmark.code}</body></html>`);
+            }, 100);
+        } else {
+            Promise.resolve(20).then(() => {
+                if (!this._isRunning)
+                    return;
+                
+                try {
+                    print(`Running... ${this._benchmark.name} ( ${this._numIterations + 1}  to go)`);
+                    benchmark.run();
+                    print("\n");
+                } catch(e) {
+                    print(e);
+                    print(e.stack);
+                }
+            });
+        }
     }
     
     _updateIterations()
     {
-        this._triggerCell.innerHTML = "Running... (" + (this._numIterations + 1) + " to go)";
+        if (isInBrowser)
+            this._triggerCell.innerHTML = "Running... (" + (this._numIterations + 1) + " to go)";
     }
 }
-
index a4e0b42..ce8912b 100644 (file)
 "use strict";
 
 const driver = new Driver(
-    document.getElementById("trigger"),
+    isInBrowser ? document.getElementById("trigger") : null,
     "driver.start(10)",
-    document.getElementById("magic"),
-    document.getElementById("Geomean"),
+    isInBrowser ? document.getElementById("magic") : null,
+    isInBrowser ? document.getElementById("Geomean") : null,
     "sampleBench");
 
-driver.addBenchmark(AirBenchmark);
-driver.addBenchmark(BasicBenchmark);
+function reportResult(...args) {
+    driver.reportResult(...args);
+}
+
+driver.addBenchmark(AirBenchmarkRunner);
+driver.addBenchmark(BasicBenchmarkRunner);
index cf1f7db..5860e02 100644 (file)
@@ -8,6 +8,8 @@ window.onerror = function(message, url, lineNumber)
 {
     document.getElementById("trigger").innerHTML = "ERROR: " + url + ":" + lineNumber + ": " + message;
 }
+
+const isInBrowser = true;
 </script>
 <script src="driver.js"></script>
 <script src="results.js"></script>
index b4ed0c4..113590b 100644 (file)
@@ -29,7 +29,7 @@ class Results {
     {
         this._benchmark = benchmark;
         for (let subResult of Results.subResults)
-            this[subResult] = new Stats(benchmark.cells[subResult]);
+            this[subResult] = new Stats(benchmark.cells[subResult], subResult);
     }
     
     get benchmark() { return this._benchmark; }
@@ -42,12 +42,14 @@ class Results {
     
     reportRunning()
     {
-        this._benchmark.cells.message.innerHTML = "Running...";
+        if (isInBrowser)
+            this._benchmark.cells.message.innerHTML = "Running...";
     }
     
     reportDone()
     {
-        this._benchmark.cells.message.innerHTML = "";
+        if (isInBrowser)
+            this._benchmark.cells.message.innerHTML = "";
     }
     
     reportResult(times)
@@ -99,7 +101,8 @@ class Results {
     {
         for (let subResult of Results.subResults)
             this[subResult].reportResult(Stats.error);
-        this._benchmark.cells.message.innerHTML = url + ":" + lineNumber + ": " + message;
+        if (isInBrowser)
+            this._benchmark.cells.message.innerHTML = url + ":" + lineNumber + ": " + message;
     }
 }
 
index 31ec316..15ae0f4 100644 (file)
 "use strict";
 
 class Stats {
-    constructor(cell)
+    constructor(cell, prefix)
     {
         this._cell = cell;
         this._data = [];
+        this._prefix = "";
+        if (!isInBrowser && prefix) {
+            this._prefix = prefix + ": ";
+            if (this._prefix.length < 20)
+                this._prefix += " ".repeat(20 - this._prefix.length);
+        }
     }
     
     reset(...data)
@@ -91,15 +97,18 @@ class Stats {
             return "ERROR";
         
         if ("interval" in result)
-            return `${result.mean.toFixed(2)} ms &plusmn; ${result.interval.toFixed(2)} ms`;
+            return `${this._prefix}${result.mean.toFixed(2)} ms +- ${result.interval.toFixed(2)} ms`;
 
-        return `${result.mean.toFixed(2)} ms`;
+        return `${this._prefix}${result.mean.toFixed(2)} ms`;
     }
     
     _update()
     {
-        if (this._cell)
-            this._cell.innerHTML = this.toString();
+        if (isInBrowser) {
+            if (this._cell)
+                this._cell.innerHTML = this.toString();
+        } else
+            print(this.toString());
     }
 }
 
index e667cd4..a175cdb 100644 (file)
@@ -1,3 +1,20 @@
+2016-08-23  Saam Barati  <sbarati@apple.com>
+
+        It should be easy to run ES6SampleBench from the jsc shell
+        https://bugs.webkit.org/show_bug.cgi?id=161085
+
+        Reviewed by Yusuke Suzuki.
+
+        This patch adds a new function called `runString` to the shell.
+        It takes in a string, and executes it in a new global object.
+        Then, it returns the global object it executed the code in.
+        This allows the code to stash some kind of a result on the global,
+        and then have the caller of `runString` extract the result.
+
+        * jsc.cpp:
+        (GlobalObject::finishCreation):
+        (functionRunString):
+
 2016-08-23  Benjamin Poulain  <benjamin@webkit.org>
 
         [JSC] Make ArithLog works with any type
index aac50e2..914f5a0 100644 (file)
@@ -589,6 +589,7 @@ static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
 #endif
 static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionRunString(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
@@ -785,6 +786,7 @@ protected:
 #endif
         addFunction(vm, "version", functionVersion, 1);
         addFunction(vm, "run", functionRun, 1);
+        addFunction(vm, "runString", functionRunString, 1);
         addFunction(vm, "load", functionLoad, 1);
         addFunction(vm, "loadString", functionLoadString, 1);
         addFunction(vm, "readFile", functionReadFile, 1);
@@ -1443,6 +1445,31 @@ EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
 }
 
+EncodedJSValue JSC_HOST_CALL functionRunString(ExecState* exec)
+{
+    String source = exec->argument(0).toWTFString(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>());
+
+    JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
+    for (unsigned i = 1; i < exec->argumentCount(); ++i)
+        array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
+    globalObject->putDirect(
+        exec->vm(), Identifier::fromString(globalObject->globalExec(), "arguments"), array);
+
+    NakedPtr<Exception> exception;
+    evaluate(globalObject->globalExec(), makeSource(source), JSValue(), exception);
+
+    if (exception) {
+        exec->vm().throwException(globalObject->globalExec(), exception);
+        return JSValue::encode(jsUndefined());
+    }
+    
+    return JSValue::encode(globalObject);
+}
+
 EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
 {
     String fileName = exec->argument(0).toWTFString(exec);