Commit b5e9630f authored by Michael Droettboom's avatar Michael Droettboom Committed by GitHub

Merge pull request #70 from iodide-project/chromedriver

Add testing with Chrome
parents e2ab1ee9 a4b6b60e
......@@ -17,7 +17,7 @@ jobs:
# Set up the Debian testing repo, and then install g++ from there...
sudo bash -c "echo \"deb http://ftp.us.debian.org/debian testing main contrib non-free\" >> /etc/apt/sources.list"
sudo apt-get update
sudo apt-get install node-less cmake build-essential clang-format-6.0 flake8 uglifyjs python3-yaml
sudo apt-get install node-less cmake build-essential clang-format-6.0 flake8 uglifyjs python3-yaml chromium
sudo apt-get install -t testing g++-8
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-6
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 80 --slave /usr/bin/g++ g++ /usr/bin/g++-8
......@@ -28,10 +28,14 @@ jobs:
# Get recent version of Firefox and geckodriver
wget -O firefox.tar.bz2 https://download.mozilla.org/\?product\=firefox-nightly-latest-ssl\&os\=linux64\&lang\=en-US
tar jxf firefox.tar.bz2
wget https://github.com/mozilla/geckodriver/releases/download/v0.20.1/geckodriver-v0.20.1-linux64.tar.gz
tar zxf geckodriver-v0.20.1-linux64.tar.gz -C firefox
# Get recent version of chromedriver
wget https://chromedriver.storage.googleapis.com/2.40/chromedriver_linux64.zip
unzip chromedriver_linux64.zip
mv chromedriver firefox
# This Debian is so old, it doesn't know about wasm as a mime type, which then
# causes Firefox to complain when loading it. Let's just add the new mime type.
sudo bash -c "echo 'application/wasm wasm' >> /etc/mime.types"
......@@ -43,9 +47,7 @@ jobs:
- restore_cache:
keys:
- v1-emsdk-{{ checksum "emsdk/Makefile" }}-v2
# fallback to using the latest cache if no exact match is found
- v1-emsdk-
- v1-emsdk-{{ checksum "emsdk/Makefile" }}-v4
- run:
name: build
......@@ -56,7 +58,7 @@ jobs:
- save_cache:
paths:
- ./emsdk/emsdk
key: v1-emsdk-{{ checksum "emsdk/Makefile" }}-v2
key: v1-emsdk-{{ checksum "emsdk/Makefile" }}-v4
- run:
name: test
......
......@@ -96,10 +96,14 @@ build/renderedhtml.css: src/renderedhtml.less
lessc $< $@
test: all build/test.html
test: all build/test.html build/test_data.txt
py.test test -v
build/test_data.txt: test/data.txt
cp test/data.txt build/test_data.txt
lint:
flake8 src
flake8 test
......
......@@ -23,8 +23,8 @@ def run_native(hostpython, code):
return float(output.strip().split()[-1])
def run_wasm(code):
s = conftest.SeleniumWrapper()
def run_wasm(code, cls):
s = cls()
try:
s.load_package('numpy')
s.run(code)
......@@ -38,12 +38,18 @@ def run_wasm(code):
return runtime
def run_both(hostpython, code):
def run_all(hostpython, code):
a = run_native(hostpython, code)
print(a)
b = run_wasm(code)
print(b)
result = (a, b)
print("native:", a)
b = run_wasm(code, conftest.FirefoxWrapper)
print("firefox:", b)
c = run_wasm(code, conftest.ChromeWrapper)
print("chrome:", c)
result = {
'native': a,
'firefox': b,
'chrome': c
}
return result
......@@ -92,7 +98,7 @@ def main(hostpython):
results = {}
for k, v in get_benchmarks():
print(k)
results[k] = run_both(hostpython, v)
results[k] = run_all(hostpython, v)
return results
......
......@@ -11,20 +11,24 @@ with open(sys.argv[-2]) as fp:
results = []
for k, v in content.items():
results.append((k, v[1] / v[0]))
results.append((k, v['firefox'] / v['native'], v['chrome'] / v['native']))
results.sort(key=lambda x: x[1], reverse=True)
names = [x[0] for x in results]
values = [x[1] for x in results]
firefox = [x[1] for x in results]
chrome = [x[2] for x in results]
width = 0.35
y_pos = np.arange(len(results))
ax.barh(y_pos, values, align='center')
ax.set_yticks(y_pos)
ax.barh(y_pos, firefox, width, color='#ff9400', label='firefox')
ax.barh(y_pos + width, chrome, width, color='#45a1ff', label='chrome')
ax.set_yticks(y_pos + width / 2)
ax.set_yticklabels(names)
ax.invert_yaxis()
ax.set_xlabel('Slowdown factor (WebAssembly:Native)')
ax.set_title('Python benchmarks')
ax.axvline(1.0, color='red')
ax.grid()
ax.legend(loc='lower right')
plt.savefig(sys.argv[-1])
......@@ -11,9 +11,11 @@ emsdk/emsdk:
./emsdk install --build=Release sdk-tag-1.38.4-64bit binaryen-tag-1.38.4-64bit ; \
cd .. ; \
(cat patches/*.patch | patch -p1) ; \
cp files/* emsdk/emscripten/tag-1.38.4/src/ ; \
cd emsdk/binaryen/tag-1.38.4_64bit_binaryen/ ; \
make ; \
cd ../.. ; \
cp binaryen/tag-1.38.4/bin/binaryen.js binaryen/tag-1.38.4_64bit_binaryen/bin ; \
./emsdk activate --embedded --build=Release sdk-tag-1.38.4-64bit binaryen-tag-1.38.4-64bit \
)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
diff --git a/src/library.js b/src/library.js
index 5fc87ab16..b8ead8fc0 100644
--- a/src/library.js
+++ b/src/library.js
@@ -1755,39 +1755,44 @@ LibraryManager.library = {
return handle;
}
+ var lib_module;
if (filename === '__self__') {
var handle = -1;
- var lib_module = Module;
+ lib_module = Module;
} else {
- var target = FS.findObject(filename);
- if (!target || target.isFolder || target.isDevice) {
- DLFCN.errorMsg = 'Could not find dynamic lib: ' + filename;
- return 0;
- }
- FS.forceLoadFile(target);
+ if (Module['preloadedWasm'] !== undefined &&
+ Module['preloadedWasm'][filename] !== undefined) {
+ lib_module = Module['preloadedWasm'][filename];
+ } else {
+ var target = FS.findObject(filename);
+ if (!target || target.isFolder || target.isDevice) {
+ DLFCN.errorMsg = 'Could not find dynamic lib: ' + filename;
+ return 0;
+ }
+ FS.forceLoadFile(target);
- var lib_module;
- try {
+ try {
#if WASM
- // the shared library is a shared wasm library (see tools/shared.py WebAssembly.make_shared_library)
- var lib_data = FS.readFile(filename, { encoding: 'binary' });
- if (!(lib_data instanceof Uint8Array)) lib_data = new Uint8Array(lib_data);
- //Module.printErr('libfile ' + filename + ' size: ' + lib_data.length);
- lib_module = loadWebAssemblyModule(lib_data);
+ // the shared library is a shared wasm library (see tools/shared.py WebAssembly.make_shared_library)
+ var lib_data = FS.readFile(filename, { encoding: 'binary' });
+ if (!(lib_data instanceof Uint8Array)) lib_data = new Uint8Array(lib_data);
+ //Module.printErr('libfile ' + filename + ' size: ' + lib_data.length);
+ lib_module = loadWebAssemblyModule(lib_data);
#else
- // the shared library is a JS file, which we eval
- var lib_data = FS.readFile(filename, { encoding: 'utf8' });
- lib_module = eval(lib_data)(
- alignFunctionTables(),
- Module
- );
+ // the shared library is a JS file, which we eval
+ var lib_data = FS.readFile(filename, { encoding: 'utf8' });
+ lib_module = eval(lib_data)(
+ alignFunctionTables(),
+ Module
+ );
#endif
- } catch (e) {
+ } catch (e) {
#if ASSERTIONS
- Module.printErr('Error in loading dynamic library: ' + e);
+ Module.printErr('Error in loading dynamic library: ' + e);
#endif
- DLFCN.errorMsg = 'Could not evaluate dynamic lib: ' + filename + '\n' + e;
- return 0;
+ DLFCN.errorMsg = 'Could not evaluate dynamic lib: ' + filename + '\n' + e;
+ return 0;
+ }
}
// Not all browsers support Object.keys().
diff --git a/src/library_browser.js b/src/library_browser.js
index 36738391e..4258835ea 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -225,6 +225,33 @@ var LibraryBrowser = {
};
Module['preloadPlugins'].push(audioPlugin);
+#if (WASM != 0) && (MAIN_MODULE != 0)
+ var wasmPlugin = {};
+ wasmPlugin['asyncWasmLoadPromise'] = new Promise(
+ function(resolve, reject) { return resolve(); });
+ wasmPlugin['canHandle'] = function(name) {
+ return !Module.noWasmDecoding && (name.endsWith('.so') || name.endsWith('.wasm'));
+ };
+ wasmPlugin['handle'] = function(byteArray, name, onload, onerror) {
+ // loadWebAssemblyModule can not load modules out-of-order, so rather
+ // than just running the promises in parallel, this makes a chain of
+ // promises to run in series.
+ this.asyncWasmLoadPromise = this.asyncWasmLoadPromise.then(
+ function() {
+ return Module.loadWebAssemblyModule(byteArray, true)
+ }).then(
+ function(module) {
+ Module.preloadedWasm[name] = module;
+ onload();
+ },
+ function(err) {
+ console.warn("Couldn't instantiate wasm: " + name + " '" + err + "'");
+ onerror();
+ });
+ };
+ Module['preloadPlugins'].push(wasmPlugin);
+#endif
+
// Canvas event setup
function pointerLockChange() {
diff --git a/src/preamble.js b/src/preamble.js
index a757e8300..f529fe148 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -1822,6 +1822,9 @@ function removeRunDependency(id) {
Module["preloadedImages"] = {}; // maps url to image data
Module["preloadedAudios"] = {}; // maps url to audio data
+#if (WASM != 0) && (MAIN_MODULE != 0)
+Module["preloadedWasm"] = {}; // maps url to wasm instance exports
+#endif
#if PGO
var PGOMonitor = {
diff --git a/src/support.js b/src/support.js
index f6c9842ff..99367db70 100644
--- a/src/support.js
+++ b/src/support.js
@@ -86,7 +86,7 @@ function loadDynamicLibrary(lib) {
#if WASM
// Loads a side module from binary data
-function loadWebAssemblyModule(binary) {
+function loadWebAssemblyModule(binary, loadAsync) {
var int32View = new Uint32Array(new Uint8Array(binary.subarray(0, 24)).buffer);
assert(int32View[0] == 0x6d736100, 'need to see wasm magic number'); // \0wasm
// we should see the dylink section right after the magic number and wasm version
@@ -166,59 +166,71 @@ function loadWebAssemblyModule(binary) {
oldTable.push(table.get(i));
}
#endif
- // create a module from the instance
- var instance = new WebAssembly.Instance(new WebAssembly.Module(binary), info);
+
+ function postInstantiation(instance) {
+ var exports = {};
#if ASSERTIONS
- // the table should be unchanged
- assert(table === originalTable);
- assert(table === Module['wasmTable']);
- if (instance.exports['table']) {
- assert(table === instance.exports['table']);
- }
- // the old part of the table should be unchanged
- for (var i = 0; i < oldTableSize; i++) {
- assert(table.get(i) === oldTable[i], 'old table entries must remain the same');
- }
- // verify that the new table region was filled in
- for (var i = 0; i < tableSize; i++) {
- assert(table.get(oldTableSize + i) !== undefined, 'table entry was not filled in');
- }
-#endif
- var exports = {};
- for (var e in instance.exports) {
- var value = instance.exports[e];
- if (typeof value === 'object') {
- // a breaking change in the wasm spec, globals are now objects
- // https://github.com/WebAssembly/mutable-global/issues/1
- value = value.value;
+ // the table should be unchanged
+ assert(table === originalTable);
+ assert(table === Module['wasmTable']);
+ if (instance.exports['table']) {
+ assert(table === instance.exports['table']);
+ }
+ // the old part of the table should be unchanged
+ for (var i = 0; i < oldTableSize; i++) {
+ assert(table.get(i) === oldTable[i], 'old table entries must remain the same');
+ }
+ // verify that the new table region was filled in
+ for (var i = 0; i < tableSize; i++) {
+ assert(table.get(oldTableSize + i) !== undefined, 'table entry was not filled in');
}
- if (typeof value === 'number') {
- // relocate it - modules export the absolute value, they can't relocate before they export
+#endif
+ for (var e in instance.exports) {
+ var value = instance.exports[e];
+ if (typeof value === 'object') {
+ // a breaking change in the wasm spec, globals are now objects
+ // https://github.com/WebAssembly/mutable-global/issues/1
+ value = value.value;
+ }
+ if (typeof value === 'number') {
+ // relocate it - modules export the absolute value, they can't relocate before they export
#if EMULATED_FUNCTION_POINTERS
- // it may be a function pointer
- if (e.substr(0, 3) == 'fp$' && typeof instance.exports[e.substr(3)] === 'function') {
- value = value + env['tableBase'];
- } else {
+ // it may be a function pointer
+ if (e.substr(0, 3) == 'fp$' && typeof instance.exports[e.substr(3)] === 'function') {
+ value = value + env['tableBase'];
+ } else {
#endif
- value = value + env['memoryBase'];
+ value = value + env['memoryBase'];
#if EMULATED_FUNCTION_POINTERS
- }
+ }
#endif
+ }
+ exports[e] = value;
}
- exports[e] = value;
- }
- // initialize the module
- var init = exports['__post_instantiate'];
- if (init) {
- if (runtimeInitialized) {
- init();
- } else {
- // we aren't ready to run compiled code yet
- __ATINIT__.push(init);
+ // initialize the module
+ var init = exports['__post_instantiate'];
+ if (init) {
+ if (runtimeInitialized) {
+ init();
+ } else {
+ // we aren't ready to run compiled code yet
+ __ATINIT__.push(init);
+ }
}
+ return exports;
+ }
+
+ if (loadAsync) {
+ return WebAssembly.instantiate(binary, info).then(function(result) {
+ return postInstantiation(result.instance);
+ });
+ } else {
+ var instance = new WebAssembly.Instance(new WebAssembly.Module(binary), info);
+ return postInstantiation(instance);
}
- return exports;
}
+Module['loadWebAssemblyModule'] = loadWebAssemblyModule;
+
#endif // WASM
#endif // RELOCATABLE
......@@ -79,6 +79,7 @@ var languagePluginLoader = new Promise((resolve, reject) => {
Module.noAudioDecoding = true;
let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if (isFirefox) {
console.log("Skipping wasm decoding");
Module.noWasmDecoding = true;
}
......
......@@ -142,6 +142,12 @@ EM_JS(int, pyproxy_init, (), {
isPyProxy: function(jsobj) {
return jsobj['$$'] !== undefined && jsobj['$$']['type'] === 'PyProxy';
},
addExtraKeys: function(result) {
result.push('toString');
result.push('prototype');
result.push('arguments');
result.push('caller');
},
isExtensible: function() { return true },
has: function (jsobj, jskey) {
ptrobj = this.getPtr(jsobj);
......@@ -197,8 +203,7 @@ EM_JS(int, pyproxy_init, (), {
var idresult = __pyproxy_ownKeys(ptrobj);
var jsresult = Module.hiwire_get_value(idresult);
Module.hiwire_decref(idresult);
jsresult.push('toString');
jsresult.push('prototype');
this.addExtraKeys(jsresult);
return jsresult;
},
enumerate: function (jsobj) {
......@@ -206,8 +211,7 @@ EM_JS(int, pyproxy_init, (), {
var idresult = __pyproxy_enumerate(ptrobj);
var jsresult = Module.hiwire_get_value(idresult);
Module.hiwire_decref(idresult);
jsresult.push('toString');
jsresult.push('prototype');
this.addExtraKeys(jsresult);
return jsresult;
},
apply: function (jsobj, jsthis, jsargs) {
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment