From dd37ae0c35b61368ab4f55ebb5d0efba9e563a4a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 1 Apr 2015 09:56:04 -0700 Subject: [PATCH 1/7] update triple to asm in test_lifetime --- tests/lifetime.ll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/lifetime.ll b/tests/lifetime.ll index 058d6b4a60a97..88692eab01f8b 100644 --- a/tests/lifetime.ll +++ b/tests/lifetime.ll @@ -1,6 +1,6 @@ -; ModuleID = '/tmp/emscripten/tmp/src.cpp.o' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" -target triple = "i386-pc-linux-gnu" +; ModuleID = 'tests/hello_world.bc' +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:128-n32-S128" +target triple = "asmjs-unknown-emscripten" %struct.vec2 = type { float, float } From a6bf73cb1cd08797e5e6645d2f1fd0b78541cdd1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 1 Apr 2015 10:58:06 -0700 Subject: [PATCH 2/7] fix error reporting in idbstore --- src/library_idbstore.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/library_idbstore.js b/src/library_idbstore.js index 73fc81ba14cde..2985b7a602fab 100644 --- a/src/library_idbstore.js +++ b/src/library_idbstore.js @@ -83,7 +83,7 @@ var LibraryIDBStore = { callback(); }; req.onerror = function(error) { - errback(error); + callback(error); }; }); }, @@ -94,7 +94,7 @@ var LibraryIDBStore = { callback(); }; req.onerror = function(error) { - errback(error); + callback(error); }; }); }, @@ -105,7 +105,7 @@ var LibraryIDBStore = { callback(null, event.target.result > 0); }; req.onerror = function(error) { - errback(error); + callback(error); }; }); }, From 0dfae4f2a4368d67f6abbbbb35388ff6c89a8223 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 1 Apr 2015 11:05:22 -0700 Subject: [PATCH 3/7] notice early errors in idbstore --- src/library_idbstore.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/library_idbstore.js b/src/library_idbstore.js index 2985b7a602fab..64d6ce6e9fcd4 100644 --- a/src/library_idbstore.js +++ b/src/library_idbstore.js @@ -62,6 +62,7 @@ var LibraryIDBStore = { // External API getFile: function(dbName, id, callback) { IDBStore.getStore(dbName, 'readonly', function(err, store) { + if (err) return callback(err); var req = store.get(id); req.onsuccess = function(event) { var result = event.target.result; @@ -78,6 +79,7 @@ var LibraryIDBStore = { }, setFile: function(dbName, id, data, callback) { IDBStore.getStore(dbName, 'readwrite', function(err, store) { + if (err) return callback(err); var req = store.put(data, id); req.onsuccess = function(event) { callback(); @@ -89,6 +91,7 @@ var LibraryIDBStore = { }, deleteFile: function(dbName, id, callback) { IDBStore.getStore(dbName, 'readwrite', function(err, store) { + if (err) return callback(err); var req = store.delete(id); req.onsuccess = function(event) { callback(); @@ -100,6 +103,7 @@ var LibraryIDBStore = { }, existsFile: function(dbName, id, callback) { IDBStore.getStore(dbName, 'readonly', function(err, store) { + if (err) return callback(err); var req = store.count(id); req.onsuccess = function(event) { callback(null, event.target.result > 0); From a5279386047c43482c574a4a2a09508242ac0bb3 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 1 Apr 2015 11:20:38 -0700 Subject: [PATCH 4/7] ensure a non-null error is reported from IDBStore.getStore --- src/library_idbstore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library_idbstore.js b/src/library_idbstore.js index 64d6ce6e9fcd4..53bf9db718c02 100644 --- a/src/library_idbstore.js +++ b/src/library_idbstore.js @@ -52,7 +52,7 @@ var LibraryIDBStore = { IDBStore.getDB(dbName, function(error, db) { var transaction = db.transaction([IDBStore.DB_STORE_NAME], type); transaction.onerror = function(e) { - callback(this.error); + callback(this.error || 'unknown error'); e.preventDefault(); }; var store = transaction.objectStore(IDBStore.DB_STORE_NAME); From cf0723e6020c8548258cbfb8c1ce8c00c85189b1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 1 Apr 2015 11:36:31 -0700 Subject: [PATCH 5/7] add blob operations for idbstore in workers --- src/library_idbstore.js | 42 +++++++++++ system/include/emscripten/emscripten.h | 5 ++ tests/idbstore_sync_worker.c | 96 ++++++++++++++++++++++++++ tests/test_browser.py | 5 ++ 4 files changed, 148 insertions(+) create mode 100644 tests/idbstore_sync_worker.c diff --git a/src/library_idbstore.js b/src/library_idbstore.js index 53bf9db718c02..f1b47d20e961d 100644 --- a/src/library_idbstore.js +++ b/src/library_idbstore.js @@ -15,6 +15,7 @@ var LibraryIDBStore = { DB_VERSION: 22, DB_STORE_NAME: 'FILE_DATA', dbs: {}, + blobs: [0], getDB: function(name, callback) { // check the cache first var db = IDBStore.dbs[name]; @@ -203,6 +204,47 @@ var LibraryIDBStore = { }); }); }, + // extra worker methods + emscripten_idb_load_blob__deps: ['$EmterpreterAsync'], + emscripten_idb_load_blob: function(db, id, pblob, perror) { + EmterpreterAsync.handle(function(resume) { + IDBStore.getFile(Pointer_stringify(db), Pointer_stringify(id), function(error, blob) { + if (error) { + {{{ makeSetValueAsm('perror', 0, '1', 'i32') }}}; + resume(); + return; + } + assert(blob instanceof Blob); + var blobId = IDBStore.blobs.length; + IDBStore.blobs.push(blob); + {{{ makeSetValueAsm('pblob', 0, 'blobId', 'i32') }}}; + resume(); + }); + }); + }, + emscripten_idb_store_blob__deps: ['$EmterpreterAsync'], + emscripten_idb_store_blob: function(db, id, ptr, num, perror) { + EmterpreterAsync.handle(function(resume) { + IDBStore.setFile(Pointer_stringify(db), Pointer_stringify(id), new Blob([new Uint8Array(HEAPU8.subarray(ptr, ptr+num))]), function(error) { + {{{ makeSetValueAsm('perror', 0, '!!error', 'i32') }}}; + resume(); + }); + }); + }, + emscripten_idb_read_from_blob__deps: ['$EmterpreterAsync'], + emscripten_idb_read_from_blob: function(blobId, start, num, buffer) { + var blob = EmterpreterAsync.blobs[blobId]; + if (!blob) return 1; + if (start+num > blob.size) return 2; + var byteArray = (new FileReaderSync()).readAsArrayBuffer(Blob.slice(start, start+num)); + HEAPU8.set(byteArray, buffer); + return 0; + }, + emscripten_idb_free_blob__deps: ['$EmterpreterAsync'], + emscripten_idb_free_blob: function(blobId) { + assert(EmterpreterAsync.blobs[blobId]); + EmterpreterAsync.blobs[blobId] = null; + }, #else emscripten_idb_load: function() { throw 'Please compile your program with async support in order to use synchronous operations like emscripten_idb_load, etc.'; diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index c1dd3e52af34e..40b0f7072b17b 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -191,6 +191,11 @@ void emscripten_idb_store(const char *db_name, const char *file_id, void* buffer void emscripten_idb_delete(const char *db_name, const char *file_id, int *perror); void emscripten_idb_exists(const char *db_name, const char *file_id, int* pexists, int *perror); +void emscripten_idb_load_blob(const char *db_name, const char *file_id, int* pblob, int *perror); +void emscripten_idb_store_blob(const char *db_name, const char *file_id, void* buffer, int num, int *perror); +void emscripten_idb_read_from_blob(int blob, int start, int num, void* buffer); +void emscripten_idb_free_blob(int blob); + // other async utilities int emscripten_async_prepare(const char* file, em_str_callback_func onload, em_str_callback_func onerror); diff --git a/tests/idbstore_sync_worker.c b/tests/idbstore_sync_worker.c new file mode 100644 index 0000000000000..69081056be370 --- /dev/null +++ b/tests/idbstore_sync_worker.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include + +#include + +#define DB "THE_DB" + +void test() { + void *buffer; + int num, error, exists; + int sum = 0; + + printf("storing %s\n", SECRET); + emscripten_idb_store(DB, "the_secret", SECRET, strlen(SECRET)+1, &error); + assert(!error); + sum++; + + printf("checking\n"); + emscripten_idb_exists(DB, "the_secret", &exists, &error); + assert(!error); + assert(exists); + sum++; + + printf("loading\n"); + emscripten_idb_load(DB, "the_secret", &buffer, &num, &error); + assert(!error); + char *ptr = buffer; + printf("loaded %s\n", ptr); + assert(num == strlen(SECRET)+1); + assert(strcmp(ptr, SECRET) == 0); + free(buffer); + sum++; + + printf("deleting the_secret\n"); + emscripten_idb_delete(DB, "the_secret", &error); + assert(!error); + sum++; + + printf("loading, should fail as we deleted\n"); + emscripten_idb_load(DB, "the_secret", &buffer, &num, &error); + assert(error); // expected error! + sum++; + + printf("last checking\n"); + emscripten_idb_exists(DB, "the_secret", &exists, &error); + assert(!error); + assert(!exists); + sum++; + + // worker-specific code + + printf("save blobs\n"); + const int CHUNK = 50*1024*1024; + buffer = malloc(CHUNK); + char *cbuffer = (char*)buffer; + cbuffer[0] = 1; + emscripten_idb_store_blob(DB, "chunk1", buffer, CHUNK, &error); + cbuffer[0] = 2; + emscripten_idb_store_blob(DB, "chunk2", buffer, CHUNK, &error); + assert(!error); + printf("blobs stored\n"); + int blob1, blob2; + emscripten_idb_load_blob(DB, "chunk1", &blob1, &error); + assert(!error); + emscripten_idb_load_blob(DB, "chunk2", &blob2, &error); + assert(!error); + printf("blobs loaded\n"); + emscripten_idb_read_from_blob(blob1, 0, CHUNK, buffer); + assert(cbuffer[0] == 1); + emscripten_idb_read_from_blob(blob2, 0, CHUNK, buffer); + assert(cbuffer[0] == 2); + EM_ASM({ alert('freeze') }); + printf("freeing blobs\n"); + emscripten_idb_free_blob(blob1); + emscripten_idb_free_blob(blob2); + + // finish up + + int result = sum; + REPORT_RESULT(); +} + +void never() { + EM_ASM({ alert('this should never be reached! runtime must not be shut down!') }); + assert(0); + while (1) {} +} + +int main() { + atexit(never); + test(); + return 0; +} + diff --git a/tests/test_browser.py b/tests/test_browser.py index b755e4fe641bc..3710bdf830722 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1181,6 +1181,11 @@ def test_idbstore_sync(self): self.clear() self.btest(path_from_root('tests', 'idbstore_sync.c'), '6', force_c=True, args=['-DSECRET=\"' + secret + '\"', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '--memory-init-file', '1', '-O3', '-g2']) + def zzztest_idbstore_sync_worker(self): + secret = str(time.time()) + self.clear() + self.btest(path_from_root('tests', 'idbstore_sync_worker.c'), '6', force_c=True, args=['-DSECRET=\"' + secret + '\"', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '--memory-init-file', '1', '-O3', '-g2', '--proxy-to-worker', '-s', 'TOTAL_MEMORY=75000000']) + def test_force_exit(self): self.btest('force_exit.c', force_c=True, expected='17') From 9df2b3a82c2ae9cfcf278194c718be09ce126750 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 1 Apr 2015 20:30:15 -0700 Subject: [PATCH 6/7] handle int|double casts in EMULATE_FUNCTION_POINTER_CASTS; fixes #3300 --- emscripten.py | 3 +++ tests/test_core.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/emscripten.py b/emscripten.py index 39f301b0acfb1..272b24145ecf4 100755 --- a/emscripten.py +++ b/emscripten.py @@ -1049,6 +1049,9 @@ def make_emulated_param(i): if proper_sig[0] != 'v': # proper sig has a return, which the wrapper may or may not use proper_code = shared.JS.make_coercion(proper_code, proper_sig[0], settings) + if proper_sig[0] != sig[0]: + # first coercion ensured we call the target ok; this one ensures we return the right type in the wrapper + proper_code = shared.JS.make_coercion(proper_code, sig[0], settings, convert_from=proper_sig[0]) if sig[0] != 'v': proper_code = 'return ' + proper_code else: diff --git a/tests/test_core.py b/tests/test_core.py index 99b51f8d9d91b..155f80879b713 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6338,6 +6338,25 @@ def test_getFuncWrapper_sig_alias(self): ''' self.do_run(src, 'func1\nfunc2\n') + def test_emulate_function_pointer_casts(self): + Settings.EMULATE_FUNCTION_POINTER_CASTS = 1 + + src = r''' + #include + #include + + typedef double (*ddd)(double x, double unused); + typedef int (*iii)(int x, int unused); + + int main() { + volatile ddd d = (ddd)acos; + volatile iii i = (iii)acos; + printf("|%.3f,%d|\n", d(0.3, 0.6), i(0, 0)); + return 0; + } + ''' + self.do_run(src, '|1.266,1|\n') + def test_demangle_stacks(self): if Settings.ASM_JS: return self.skip('spidermonkey has stack trace issues') From 06d7b410a8e2c13b64d8553211abc44da1f94045 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 Apr 2015 17:09:21 -0700 Subject: [PATCH 7/7] 1.30.3 --- emscripten-version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emscripten-version.txt b/emscripten-version.txt index 5677c30f98274..7cef0af154383 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.30.2 +1.30.3