summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--em++.bat2
-rw-r--r--em-config.bat2
-rw-r--r--emar.bat2
-rwxr-xr-xemcc58
-rw-r--r--emcc.bat2
-rw-r--r--emconfigure.bat2
-rw-r--r--emlibtool.bat2
-rw-r--r--emmake.bat2
-rw-r--r--emranlib.bat2
-rw-r--r--src/library_browser.js7
-rw-r--r--src/library_fs.js12
-rw-r--r--src/library_memfs.js51
-rw-r--r--src/settings.js19
-rw-r--r--src/shell.html2
-rw-r--r--system/include/emscripten/emscripten.h16
-rw-r--r--tests/aniso.c1
-rw-r--r--tests/cubegeom_color.c1
-rw-r--r--tests/cubegeom_pre.c1
-rw-r--r--tests/cubegeom_pre2.c1
-rw-r--r--tests/cubegeom_pre2_vao.c1
-rw-r--r--tests/cubegeom_pre2_vao2.c1
-rw-r--r--tests/cubegeom_pre3.c1
-rw-r--r--tests/cubegeom_pre_vao.c1
-rw-r--r--tests/cubegeom_texturematrix.c1
-rw-r--r--tests/float_tex.cpp2
-rw-r--r--tests/gl_matrix_identity.c1
-rw-r--r--tests/glshaderinfo.cpp2
-rw-r--r--tests/http.h1
-rw-r--r--tests/s3tc.c1
-rw-r--r--tests/s3tc_crunch.c1
-rw-r--r--tests/sdl_canvas.c11
-rw-r--r--tests/sdl_image_prepare_data.c2
-rw-r--r--tests/sockets/test_enet_client.c2
-rw-r--r--tests/sockets/test_sockets_partial_server.c3
-rw-r--r--tests/sockets/test_sockets_select_server_down_client.c (renamed from tests/sockets/test_sockets_select_server_no_accept_client.c)0
-rw-r--r--tests/sockets/test_sockets_select_server_down_server.c (renamed from tests/sockets/test_sockets_select_server_no_accept_server.c)41
-rw-r--r--tests/test_browser.py16
-rw-r--r--tests/test_core.py46
-rw-r--r--tests/test_sockets.py9
-rw-r--r--tests/tex_nonbyte.c1
-rw-r--r--tests/unistd/misc.out7
-rw-r--r--tools/file_packager.py107
-rw-r--r--tools/js-optimizer.js23
-rw-r--r--tools/test-js-optimizer-asm-outline1-output.js136
-rw-r--r--tools/test-js-optimizer-asm-outline1.js48
45 files changed, 478 insertions, 172 deletions
diff --git a/em++.bat b/em++.bat
index b639ff29..e486fcea 100644
--- a/em++.bat
+++ b/em++.bat
@@ -1,2 +1,2 @@
@echo off
-python %~dp0\em++ %* \ No newline at end of file
+python "%~dp0\em++" %* \ No newline at end of file
diff --git a/em-config.bat b/em-config.bat
index 63b15ea4..52d1af0e 100644
--- a/em-config.bat
+++ b/em-config.bat
@@ -1,2 +1,2 @@
@echo off
-python %~dp0\em-config %* \ No newline at end of file
+python "%~dp0\em-config" %* \ No newline at end of file
diff --git a/emar.bat b/emar.bat
index 2cfb0850..9ebc2d41 100644
--- a/emar.bat
+++ b/emar.bat
@@ -1,2 +1,2 @@
@echo off
-python %~dp0\emar %* \ No newline at end of file
+python "%~dp0\emar" %* \ No newline at end of file
diff --git a/emcc b/emcc
index 0cd8ca2d..a07ce4f1 100755
--- a/emcc
+++ b/emcc
@@ -1577,6 +1577,35 @@ try:
js_transform_tempfiles = [final]
+ if memory_init_file:
+ if shared.Settings.USE_TYPED_ARRAYS != 2:
+ if type(memory_init_file) == int: logging.warning('memory init file requires typed arrays mode 2')
+ else:
+ memfile = target + '.mem'
+ shared.try_delete(memfile)
+ def repl(m):
+ # handle chunking of the memory initializer
+ s = re.sub('[\[\]\n\(\)\. ]', '', m.groups(0)[0])
+ s = s.replace('concat', ',')
+ if s[-1] == ',': s = s[:-1]
+ open(memfile, 'wb').write(''.join(map(lambda x: chr(int(x or '0')), s.split(','))))
+ if DEBUG:
+ # Copy into temp dir as well, so can be run there too
+ temp_memfile = os.path.join(shared.EMSCRIPTEN_TEMP_DIR, os.path.basename(memfile))
+ if os.path.abspath(memfile) != os.path.abspath(memfile):
+ shutil.copyfile(memfile, temp_memfile)
+ return 'loadMemoryInitializer("%s");' % os.path.basename(memfile)
+ src = re.sub(shared.JS.memory_initializer_pattern, repl, open(final).read(), count=1)
+ open(final + '.mem.js', 'w').write(src)
+ final += '.mem.js'
+ js_transform_tempfiles[-1] = final # simple text substitution preserves comment line number mappings
+ if DEBUG:
+ if os.path.exists(memfile):
+ save_intermediate('meminit')
+ logging.debug('wrote memory initialization to %s' % memfile)
+ else:
+ logging.debug('did not see memory initialization')
+
# It is useful to run several js optimizer passes together, to save on unneeded unparsing/reparsing
js_optimizer_queue = []
js_optimizer_extra_info = {}
@@ -1654,35 +1683,6 @@ try:
src = re.sub(r'\n+[ \n]*\n+', '\n', src)
open(final, 'w').write(src)
- if memory_init_file:
- if shared.Settings.USE_TYPED_ARRAYS != 2:
- if type(memory_init_file) == int: logging.warning('memory init file requires typed arrays mode 2')
- else:
- memfile = target + '.mem'
- shared.try_delete(memfile)
- def repl(m):
- # handle chunking of the memory initializer
- s = re.sub('[\[\]\n\(\)\. ]', '', m.groups(0)[0])
- s = s.replace('concat', ',')
- if s[-1] == ',': s = s[:-1]
- open(memfile, 'wb').write(''.join(map(lambda x: chr(int(x or '0')), s.split(','))))
- if DEBUG:
- # Copy into temp dir as well, so can be run there too
- temp_memfile = os.path.join(shared.EMSCRIPTEN_TEMP_DIR, os.path.basename(memfile))
- if os.path.abspath(memfile) != os.path.abspath(memfile):
- shutil.copyfile(memfile, temp_memfile)
- return 'loadMemoryInitializer("%s");' % os.path.basename(memfile)
- src = re.sub(shared.JS.memory_initializer_pattern, repl, src, count=1)
- open(final + '.mem.js', 'w').write(src)
- final += '.mem.js'
- js_transform_tempfiles[-1] = final # simple text substitution preserves comment line number mappings
- if DEBUG:
- if os.path.exists(memfile):
- save_intermediate('meminit')
- logging.debug('wrote memory initialization to %s' % memfile)
- else:
- logging.debug('did not see memory initialization')
-
def generate_source_map(map_file_base_name, offset=0):
jsrun.run_js(shared.path_from_root('tools', 'source-maps', 'sourcemapper.js'),
shared.NODE_JS, js_transform_tempfiles +
diff --git a/emcc.bat b/emcc.bat
index 2cb3a3e1..e1ca45c7 100644
--- a/emcc.bat
+++ b/emcc.bat
@@ -1,2 +1,2 @@
@echo off
-python %~dp0\emcc %* \ No newline at end of file
+python "%~dp0\emcc" %* \ No newline at end of file
diff --git a/emconfigure.bat b/emconfigure.bat
index f900f407..651ccf05 100644
--- a/emconfigure.bat
+++ b/emconfigure.bat
@@ -1,2 +1,2 @@
@echo off
-python %~dp0\emconfigure %* \ No newline at end of file
+python "%~dp0\emconfigure" %* \ No newline at end of file
diff --git a/emlibtool.bat b/emlibtool.bat
index 76ce48c3..4ea705be 100644
--- a/emlibtool.bat
+++ b/emlibtool.bat
@@ -1,2 +1,2 @@
@echo off
-python %~dp0\emlibtool %* \ No newline at end of file
+python "%~dp0\emlibtool" %* \ No newline at end of file
diff --git a/emmake.bat b/emmake.bat
index 2db09d07..a86ba6e2 100644
--- a/emmake.bat
+++ b/emmake.bat
@@ -1,2 +1,2 @@
@echo off
-python %~dp0\emmake %* \ No newline at end of file
+python "%~dp0\emmake" %* \ No newline at end of file
diff --git a/emranlib.bat b/emranlib.bat
index 69bf8aa4..a8af4ef7 100644
--- a/emranlib.bat
+++ b/emranlib.bat
@@ -1,2 +1,2 @@
@echo off
-python %~dp0\emranlib %* \ No newline at end of file
+python "%~dp0\emranlib" %* \ No newline at end of file
diff --git a/src/library_browser.js b/src/library_browser.js
index 558c9a59..591a3c11 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -821,6 +821,13 @@ mergeInto(LibraryManager.library, {
emscripten_set_canvas_size: function(width, height) {
Browser.setCanvasSize(width, height);
},
+
+ emscripten_get_canvas_size: function(width, height, isFullscreen) {
+ var canvas = Module['canvas'];
+ {{{ makeSetValue('width', '0', 'canvas.width', 'i32') }}};
+ {{{ makeSetValue('height', '0', 'canvas.height', 'i32') }}};
+ {{{ makeSetValue('isFullscreen', '0', 'Browser.isFullScreen ? 1 : 0', 'i32') }}};
+ },
emscripten_get_now: function() {
if (ENVIRONMENT_IS_NODE) {
diff --git a/src/library_fs.js b/src/library_fs.js
index 9d1f0cfd..e1397356 100644
--- a/src/library_fs.js
+++ b/src/library_fs.js
@@ -509,7 +509,7 @@ mergeInto(LibraryManager.library, {
var mode = FS.getMode(canRead, canWrite);
return FS.create(path, mode);
},
- createDataFile: function(parent, name, data, canRead, canWrite) {
+ createDataFile: function(parent, name, data, canRead, canWrite, canOwn) {
var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
var mode = FS.getMode(canRead, canWrite);
var node = FS.create(path, mode);
@@ -522,7 +522,7 @@ mergeInto(LibraryManager.library, {
// make sure we can write to the file
FS.chmod(path, mode | {{{ cDefine('S_IWUGO') }}});
var stream = FS.open(path, 'w');
- FS.write(stream, data, 0, data.length, 0);
+ FS.write(stream, data, 0, data.length, 0, canOwn);
FS.close(stream);
FS.chmod(path, mode);
}
@@ -766,7 +766,7 @@ mergeInto(LibraryManager.library, {
// You can also call this with a typed array instead of a url. It will then
// do preloading for the Image/Audio part, as if the typed array were the
// result of an XHR that you did manually.
- createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile) {
+ createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn) {
Browser.init();
// TODO we should allow people to just pass in a complete filename instead
// of parent and name being that we just join them anyways
@@ -774,7 +774,7 @@ mergeInto(LibraryManager.library, {
function processData(byteArray) {
function finish(byteArray) {
if (!dontCreateFile) {
- FS.createDataFile(parent, name, byteArray, canRead, canWrite);
+ FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
}
if (onload) onload();
removeRunDependency('cp ' + fullname);
@@ -1323,7 +1323,7 @@ mergeInto(LibraryManager.library, {
if (!seeking) stream.position += bytesRead;
return bytesRead;
},
- write: function(stream, buffer, offset, length, position) {
+ write: function(stream, buffer, offset, length, position, canOwn) {
if (length < 0 || position < 0) {
throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
}
@@ -1347,7 +1347,7 @@ mergeInto(LibraryManager.library, {
// seek to the end before writing in append mode
FS.llseek(stream, 0, {{{ cDefine('SEEK_END') }}});
}
- var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position);
+ var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
if (!seeking) stream.position += bytesWritten;
return bytesWritten;
},
diff --git a/src/library_memfs.js b/src/library_memfs.js
index 0fa6cdfb..63326c42 100644
--- a/src/library_memfs.js
+++ b/src/library_memfs.js
@@ -1,6 +1,22 @@
mergeInto(LibraryManager.library, {
$MEMFS__deps: ['$FS'],
$MEMFS: {
+ // content modes
+ CONTENT_OWNING: 1, // contains a subarray into the heap, and we own it - need to free() when no longer needed
+ CONTENT_FLEXIBLE: 2, // has been modified or never set to anything, and is a flexible js array that can grow/shrink
+ CONTENT_FIXED: 3, // contains some fixed-size content written into it, in a typed array
+ ensureFlexible: function(node) {
+ if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) {
+ var contents = node.contents;
+ node.contents = Array.prototype.slice.call(contents);
+ if (node.contentMode === MEMFS.CONTENT_OWNING) {
+ assert(contents.byteOffset);
+ Module['_free'](contents.byteOffset);
+ }
+ node.contentMode = MEMFS.CONTENT_FLEXIBLE;
+ }
+ },
+
mount: function(mount) {
return MEMFS.create_node(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0);
},
@@ -40,6 +56,7 @@ mergeInto(LibraryManager.library, {
mmap: MEMFS.stream_ops.mmap
};
node.contents = [];
+ node.contentMode = MEMFS.CONTENT_FLEXIBLE;
} else if (FS.isLink(node.mode)) {
node.node_ops = {
getattr: MEMFS.node_ops.getattr,
@@ -98,6 +115,7 @@ mergeInto(LibraryManager.library, {
node.timestamp = attr.timestamp;
}
if (attr.size !== undefined) {
+ MEMFS.ensureFlexible(node);
var contents = node.contents;
if (attr.size < contents.length) contents.length = attr.size;
else while (attr.size > contents.length) contents.push(0);
@@ -165,7 +183,7 @@ mergeInto(LibraryManager.library, {
var contents = stream.node.contents;
var size = Math.min(contents.length - position, length);
#if USE_TYPED_ARRAYS == 2
- if (contents.subarray) { // typed array
+ if (size > 8 && contents.subarray) { // non-trivial, and typed array
buffer.set(contents.subarray(position, position + size), offset);
} else
#endif
@@ -176,13 +194,30 @@ mergeInto(LibraryManager.library, {
}
return size;
},
- write: function(stream, buffer, offset, length, position) {
- var contents = stream.node.contents;
+ write: function(stream, buffer, offset, length, position, canOwn) {
+ var node = stream.node;
+ node.timestamp = Date.now();
+ var contents = node.contents;
+#if USE_TYPED_ARRAYS == 2
+ if (length && contents.length === 0 && position === 0 && buffer.subarray) {
+ // just replace it with the new data
+ assert(buffer.length);
+ if (canOwn && buffer.buffer === HEAP8.buffer && offset === 0) {
+ node.contents = buffer; // this is a subarray of the heap, and we can own it
+ node.contentMode = MEMFS.CONTENT_OWNING;
+ } else {
+ node.contents = new Uint8Array(buffer.subarray(offset, offset+length));
+ node.contentMode = MEMFS.CONTENT_FIXED;
+ }
+ return length;
+ }
+#endif
+ MEMFS.ensureFlexible(node);
+ var contents = node.contents;
while (contents.length < position) contents.push(0);
for (var i = 0; i < length; i++) {
contents[position + i] = buffer[offset + i];
}
- stream.node.timestamp = Date.now();
return length;
},
llseek: function(stream, offset, whence) {
@@ -202,6 +237,7 @@ mergeInto(LibraryManager.library, {
return position;
},
allocate: function(stream, offset, length) {
+ MEMFS.ensureFlexible(stream.node);
var contents = stream.node.contents;
var limit = offset + length;
while (limit > contents.length) contents.push(0);
@@ -214,10 +250,10 @@ mergeInto(LibraryManager.library, {
var allocated;
var contents = stream.node.contents;
// Only make a new copy when MAP_PRIVATE is specified.
- if (!(flags & {{{ cDefine('MAP_PRIVATE') }}})) {
+ if ( !(flags & {{{ cDefine('MAP_PRIVATE') }}}) &&
+ (contents.buffer === buffer || contents.buffer === buffer.buffer) ) {
// We can't emulate MAP_SHARED when the file is not backed by the buffer
// we're mapping to (e.g. the HEAP buffer).
- assert(contents.buffer === buffer || contents.buffer === buffer.buffer);
allocated = false;
ptr = contents.byteOffset;
} else {
@@ -240,4 +276,5 @@ mergeInto(LibraryManager.library, {
},
}
}
-}); \ No newline at end of file
+});
+
diff --git a/src/settings.js b/src/settings.js
index cb64bfd9..03b4ed64 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -6,6 +6,11 @@
// emcc -s OPTION1=VALUE1 -s OPTION2=VALUE2 [..other stuff..]
//
// See https://github.com/kripken/emscripten/wiki/Code-Generation-Modes/
+//
+// Note that the values here are the defaults in -O0, that is, unoptimized
+// mode. See apply_opt_level in tools/shared.py for how -O1,2,3 affect these
+// flags.
+//
// Tuning
var QUANTUM_SIZE = 4; // This is the size of an individual field in a structure. 1 would
@@ -131,6 +136,16 @@ var OUTLINING_LIMIT = 0; // A function size above which we try to automatically
// large functions (JS engines often compile them very slowly,
// compile them with lower optimizations, or do not optimize them
// at all). If 0, we do not perform outlining at all.
+ // To see which funcs are large, you can inspect the source
+ // in a debug build (-g2 or -g for example), and can run
+ // tools/find_bigfuncs.py on that to get a sorted list by size.
+ // Another possibility is to look in the web console in firefox,
+ // which will note slowly-compiling functions.
+ // You will probably want to experiment with various values to
+ // see the impact on compilation time, code size and runtime
+ // throughput. It is hard to say what values to start testing
+ // with, but something around 20,000 to 100,000 might make sense.
+ // (The unit size is number of AST nodes.)
// Generated code debugging options
var SAFE_HEAP = 0; // Check each write to the heap, for example, this will give a clear
@@ -380,9 +395,7 @@ var HEADLESS = 0; // If 1, will include shim code that tries to 'fake' a browser
var BENCHMARK = 0; // If 1, will just time how long main() takes to execute, and not
// print out anything at all whatsoever. This is useful for benchmarking.
-var ASM_JS = 0; // If 1, generate code in asm.js format. XXX This is highly experimental,
- // and will not work on most codebases yet. It is NOT recommended that you
- // try this yet.
+var ASM_JS = 0; // If 1, generate code in asm.js format.
var PGO = 0; // Enables profile-guided optimization in the form of runtime checks for
// which functions are actually called. Emits a list during shutdown that you
diff --git a/src/shell.html b/src/shell.html
index 22bc9de9..ff5f6e35 100644
--- a/src/shell.html
+++ b/src/shell.html
@@ -87,6 +87,6 @@
};
Module.setStatus('Downloading...');
</script>
- <script type='text/javascript'>{{{ SCRIPT_CODE }}}</script>
+ <script async type='text/javascript'>{{{ SCRIPT_CODE }}}</script>
</body>
</html>
diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h
index f0df8dca..1b9a8f25 100644
--- a/system/include/emscripten/emscripten.h
+++ b/system/include/emscripten/emscripten.h
@@ -19,6 +19,16 @@ extern "C" {
#endif
/*
+ * Convenient syntax for inline assembly/js. Allows stuff like
+ *
+ * EM_ASM(window.alert('hai'));
+ *
+ * Note: double-quotes (") are not supported, but you can use
+ * single-quotes (') in js anyhow.
+ */
+#define EM_ASM(...) asm(#__VA_ARGS__)
+
+/*
* Forces LLVM to not dead-code-eliminate a function. Note that
* you still need to use EXPORTED_FUNCTIONS so it stays alive
* in JS, e.g.
@@ -160,6 +170,12 @@ void emscripten_hide_mouse();
void emscripten_set_canvas_size(int width, int height);
/*
+ * Get the current pixel width and height of the <canvas> element
+ * as well as whether the canvas is fullscreen or not.
+ */
+void emscripten_get_canvas_size(int *width, int *height, int *isFullscreen);
+
+/*
* Returns the highest-precision representation of the
* current time that the browser provides. This uses either
* Date.now or performance.now. The result is *not* an
diff --git a/tests/aniso.c b/tests/aniso.c
index f210e5a5..e8d7bd3f 100644
--- a/tests/aniso.c
+++ b/tests/aniso.c
@@ -27,6 +27,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#include "SDL/SDL_opengl.h"
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/cubegeom_color.c b/tests/cubegeom_color.c
index 7d384324..ff30e1a9 100644
--- a/tests/cubegeom_color.c
+++ b/tests/cubegeom_color.c
@@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/cubegeom_pre.c b/tests/cubegeom_pre.c
index fb1a5e02..40b03cf7 100644
--- a/tests/cubegeom_pre.c
+++ b/tests/cubegeom_pre.c
@@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/cubegeom_pre2.c b/tests/cubegeom_pre2.c
index 51961bf7..df04ae31 100644
--- a/tests/cubegeom_pre2.c
+++ b/tests/cubegeom_pre2.c
@@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/cubegeom_pre2_vao.c b/tests/cubegeom_pre2_vao.c
index cba262ff..733c8fc6 100644
--- a/tests/cubegeom_pre2_vao.c
+++ b/tests/cubegeom_pre2_vao.c
@@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/cubegeom_pre2_vao2.c b/tests/cubegeom_pre2_vao2.c
index 3784006c..69096833 100644
--- a/tests/cubegeom_pre2_vao2.c
+++ b/tests/cubegeom_pre2_vao2.c
@@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/cubegeom_pre3.c b/tests/cubegeom_pre3.c
index 4ba2a779..ceaa757e 100644
--- a/tests/cubegeom_pre3.c
+++ b/tests/cubegeom_pre3.c
@@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/cubegeom_pre_vao.c b/tests/cubegeom_pre_vao.c
index cae68cfc..8c598143 100644
--- a/tests/cubegeom_pre_vao.c
+++ b/tests/cubegeom_pre_vao.c
@@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/cubegeom_texturematrix.c b/tests/cubegeom_texturematrix.c
index 99a4469e..abb667eb 100644
--- a/tests/cubegeom_texturematrix.c
+++ b/tests/cubegeom_texturematrix.c
@@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/float_tex.cpp b/tests/float_tex.cpp
index 61531124..c40ff786 100644
--- a/tests/float_tex.cpp
+++ b/tests/float_tex.cpp
@@ -113,7 +113,7 @@ static void gl_init(void) {
/* Store the vertices in a vertex buffer object (VBO) */
glGenBuffers(1, &indicesVBO);
glBindBuffer(GL_ARRAY_BUFFER, indicesVBO);
- glBufferData(GL_ARRAY_BUFFER, elements.size() * sizeof(uint), &elements[0], GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, elements.size() * sizeof(float), &elements[0], GL_STATIC_DRAW);
/* Get the locations of the uniforms so we can access them */
nodeSamplerLocation = glGetUniformLocation(program, "nodeInfo");
glBindAttribLocation(program, 0, "indices");
diff --git a/tests/gl_matrix_identity.c b/tests/gl_matrix_identity.c
index 98b1c21f..9f990a77 100644
--- a/tests/gl_matrix_identity.c
+++ b/tests/gl_matrix_identity.c
@@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/glshaderinfo.cpp b/tests/glshaderinfo.cpp
index 8ec393a8..56da2414 100644
--- a/tests/glshaderinfo.cpp
+++ b/tests/glshaderinfo.cpp
@@ -1,8 +1,6 @@
#define GL_GLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES
-#define _GNU_SOURCE
-
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
diff --git a/tests/http.h b/tests/http.h
index 7eff7013..d20f012b 100644
--- a/tests/http.h
+++ b/tests/http.h
@@ -8,6 +8,7 @@
#ifndef __HTTP_H__
#define __HTTP_H__
+#include <stdarg.h>
#include <string>
diff --git a/tests/s3tc.c b/tests/s3tc.c
index 16ee783f..5f7bee83 100644
--- a/tests/s3tc.c
+++ b/tests/s3tc.c
@@ -27,6 +27,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#include "SDL/SDL_opengl.h"
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/s3tc_crunch.c b/tests/s3tc_crunch.c
index 90ed02d9..c2606c8f 100644
--- a/tests/s3tc_crunch.c
+++ b/tests/s3tc_crunch.c
@@ -27,6 +27,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#include "SDL/SDL_opengl.h"
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/sdl_canvas.c b/tests/sdl_canvas.c
index 10044ff4..6bd659b8 100644
--- a/tests/sdl_canvas.c
+++ b/tests/sdl_canvas.c
@@ -1,4 +1,5 @@
#include <stdio.h>
+#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <emscripten.h>
@@ -43,6 +44,16 @@ int main(int argc, char **argv) {
SDL_Flip(screen);
SDL_LockSurface(screen);
+
+ int width, height, isFullscreen;
+ emscripten_get_canvas_size(&width, &height, &isFullscreen);
+
+ if (width != 600 && height != 450)
+ {
+ printf("error: wrong width/height\n");
+ abort();
+ }
+
int sum = 0;
for (int i = 0; i < screen->h; i++) {
sum += *((char*)screen->pixels + i*screen->w*4 + i*4 + 0);
diff --git a/tests/sdl_image_prepare_data.c b/tests/sdl_image_prepare_data.c
index d45a2e60..043ace47 100644
--- a/tests/sdl_image_prepare_data.c
+++ b/tests/sdl_image_prepare_data.c
@@ -58,7 +58,7 @@ int main() {
printf("prepare..\n");
#define SIZE 203164
- FILE *f = open("screenshot.not", "rb");
+ FILE *f = fopen("screenshot.not", "rb");
char *buffer = malloc(SIZE);
fread(buffer, SIZE, 1, f);
fclose(f);
diff --git a/tests/sockets/test_enet_client.c b/tests/sockets/test_enet_client.c
index bf14375c..afcdcae8 100644
--- a/tests/sockets/test_enet_client.c
+++ b/tests/sockets/test_enet_client.c
@@ -93,6 +93,7 @@ int main (int argc, char ** argv)
}
#if EMSCRIPTEN
+#if USE_IFRAME
emscripten_run_script("console.log('adding iframe');"
"var iframe = document.createElement('iframe');"
"iframe.src = 'server.html';"
@@ -101,6 +102,7 @@ int main (int argc, char ** argv)
"document.body.appendChild(iframe);"
"console.log('added.');");
#endif
+#endif
#if EMSCRIPTEN
emscripten_set_main_loop(main_loop, 3, 1);
diff --git a/tests/sockets/test_sockets_partial_server.c b/tests/sockets/test_sockets_partial_server.c
index 21096552..44ad40a3 100644
--- a/tests/sockets/test_sockets_partial_server.c
+++ b/tests/sockets/test_sockets_partial_server.c
@@ -38,13 +38,12 @@ void do_send(int sockfd) {
int i;
int res;
char *buffer;
- struct sockaddr_in addr;
socklen_t addrlen;
for (i = 0; i < sizeof(buffers) / sizeof(char*); i++) {
buffer = buffers[i];
- res = sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&addr, sizeof(addr));
+ res = send(sockfd, buffer, strlen(buffer), 0);
if (res == -1) {
perror("send failed");
exit(EXIT_FAILURE);
diff --git a/tests/sockets/test_sockets_select_server_no_accept_client.c b/tests/sockets/test_sockets_select_server_down_client.c
index e05bd4c8..e05bd4c8 100644
--- a/tests/sockets/test_sockets_select_server_no_accept_client.c
+++ b/tests/sockets/test_sockets_select_server_down_client.c
diff --git a/tests/sockets/test_sockets_select_server_no_accept_server.c b/tests/sockets/test_sockets_select_server_down_server.c
index 4a399ed1..c2e70f33 100644
--- a/tests/sockets/test_sockets_select_server_no_accept_server.c
+++ b/tests/sockets/test_sockets_select_server_down_server.c
@@ -14,38 +14,13 @@
#include <emscripten.h>
#endif
-int serverfd = -1;
-
-void iter(void *arg) {
- int res;
- fd_set fdr;
- fd_set fdw;
-
- // see if there are any connections to accept / write to
- FD_ZERO(&fdr);
- FD_ZERO(&fdw);
- FD_SET(serverfd, &fdr);
- if (clientfd != -1) FD_SET(clientfd, &fdw);
- res = select(64, &fdr, &fdw, NULL, NULL);
- if (res == -1) {
- perror("select failed");
- exit(EXIT_SUCCESS);
- }
-
- if (FD_ISSET(serverfd, &fdr)) {
- printf("accepted someone\n");
- clientfd = accept(serverfd, NULL, NULL);
- assert(clientfd != -1);
- }
-
- if (FD_ISSET(clientfd, &fdw)) {
- do_send(clientfd);
- }
+void main_loop(void *arg) {
}
int main() {
struct sockaddr_in addr;
int res;
+ int serverfd;
// create the socket
serverfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -55,7 +30,7 @@ int main() {
}
fcntl(serverfd, F_SETFL, O_NONBLOCK);
- // bind and listen to the supplied port
+ // bind to the supplied port
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(SOCKK);
@@ -70,16 +45,12 @@ int main() {
exit(EXIT_FAILURE);
}
- res = listen(serverfd, 50);
- if (res == -1) {
- perror("listen failed");
- exit(EXIT_FAILURE);
- }
+ close(serverfd);
#if EMSCRIPTEN
- emscripten_set_main_loop(iter, 60, 0);
+ emscripten_set_main_loop(main_loop, 60, 0);
#else
- while (1) iter(NULL);
+ while (1) main_loop(NULL); sleep(1);
#endif
return EXIT_SUCCESS;
diff --git a/tests/test_browser.py b/tests/test_browser.py
index 7c387071..4b42eedd 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -38,8 +38,6 @@ class browser(BrowserCore):
message='You should see "hello, world!" and a colored cube.')
def test_html_source_map(self):
- if 'test_html_source_map' not in str(sys.argv): return self.skip('''This test
-requires manual intervention; will not be run unless explicitly requested''')
cpp_file = os.path.join(self.get_dir(), 'src.cpp')
html_file = os.path.join(self.get_dir(), 'src.html')
# browsers will try to 'guess' the corresponding original line if a
@@ -64,14 +62,20 @@ requires manual intervention; will not be run unless explicitly requested''')
''')
# use relative paths when calling emcc, because file:// URIs can only load
# sourceContent when the maps are relative paths
+ try_delete(html_file)
+ try_delete(html_file + '.map')
Popen([PYTHON, EMCC, 'src.cpp', '-o', 'src.html', '-g4'],
cwd=self.get_dir()).communicate()
+ assert os.path.exists(html_file)
+ assert os.path.exists(html_file + '.map')
+ import webbrowser, time
webbrowser.open_new('file://' + html_file)
+ time.sleep(1)
print '''
-Set the debugger to pause on exceptions
-You should see an exception thrown at src.cpp:7.
-Press any key to continue.'''
- raw_input()
+If manually bisecting:
+ Check that you see src.cpp among the page sources.
+ Even better, add a breakpoint, e.g. on the printf, then reload, then step through and see the print (best to run with EM_SAVE_DIR=1 for the reload).
+'''
def build_native_lzma(self):
lzma_native = path_from_root('third_party', 'lzma.js', 'lzma-native')
diff --git a/tests/test_core.py b/tests/test_core.py
index a477c05e..7eff0d2f 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -3752,7 +3752,7 @@ def process(filename):
}
'''
- self.do_run(src, 'Inline JS is very cool\n3.64')
+ self.do_run(src, 'Inline JS is very cool\n3.64\n')
def test_inlinejs2(self):
if Settings.ASM_JS: return self.skip('asm does not support random code, TODO: something that works in asm')
@@ -3779,6 +3779,27 @@ def process(filename):
self.do_run(src, '4\n200\n')
+ def test_inlinejs3(self):
+ if Settings.ASM_JS: return self.skip('asm does not support random code, TODO: something that works in asm')
+ src = r'''
+ #include <stdio.h>
+ #include <emscripten.h>
+
+ int main() {
+ EM_ASM(Module.print('hello dere1'));
+ EM_ASM(
+ Module.print('hello dere2');
+ );
+ EM_ASM(
+ Module.print('hello dere3');
+ Module.print('hello dere' + 4);
+ );
+ return 0;
+ }
+ '''
+
+ self.do_run(src, 'hello dere1\nhello dere2\nhello dere3\nhello dere4\n')
+
def test_memorygrowth(self):
if Settings.USE_TYPED_ARRAYS == 0: return self.skip('memory growth is only supported with typed arrays')
if Settings.ASM_JS: return self.skip('asm does not support memory growth yet')
@@ -5546,7 +5567,6 @@ The current type of b is: 9
if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
Settings.NAMED_GLOBALS = 1
- Settings.LINKABLE = 1
lib_src = '''
#include <cstdio>
@@ -6741,6 +6761,7 @@ date: 18.07.2013w; day 18, month 7, year 2013, extra: 201, 3
def test_files(self):
if self.emcc_args is not None and '-O2' in self.emcc_args:
self.emcc_args += ['--closure', '1'] # Use closure here, to test we don't break FS stuff
+ self.emcc_args = filter(lambda x: x != '-g', self.emcc_args) # ensure we test --closure 1 --memory-init-file 1 (-g would disable closure)
Settings.CORRECT_SIGNS = 1 # Just so our output is what we expect. Can flip them both.
post = '''
@@ -6767,8 +6788,13 @@ def process(filename):
other.close()
src = open(path_from_root('tests', 'files.cpp'), 'r').read()
+
+ mem_file = 'src.cpp.o.js.mem'
+ try_delete(mem_file)
self.do_run(src, ('size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\nok.\ntexte\n', 'size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\ntexte\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\nok.\n'),
post_build=post, extra_emscripten_args=['-H', 'libc/fcntl.h'])
+ if self.emcc_args and '--memory-init-file' in self.emcc_args:
+ assert os.path.exists(mem_file)
def test_files_m(self):
# Test for Module.stdin etc.
@@ -8301,13 +8327,15 @@ def process(filename):
shutil.copyfile(path_from_root('tests', 'freetype', 'LiberationSansBold.ttf'), os.path.join(self.get_dir(), 'font.ttf'))
# Main
- self.do_run(open(path_from_root('tests', 'freetype', 'main.c'), 'r').read(),
- open(path_from_root('tests', 'freetype', 'ref.txt'), 'r').read(),
- ['font.ttf', 'test!', '150', '120', '25'],
- libraries=self.get_freetype(),
- includes=[path_from_root('tests', 'freetype', 'include')],
- post_build=post)
- #build_ll_hook=self.do_autodebug)
+ for outlining in [0, 5000]:
+ Settings.OUTLINING_LIMIT = outlining
+ print >> sys.stderr, 'outlining:', outlining
+ self.do_run(open(path_from_root('tests', 'freetype', 'main.c'), 'r').read(),
+ open(path_from_root('tests', 'freetype', 'ref.txt'), 'r').read(),
+ ['font.ttf', 'test!', '150', '120', '25'],
+ libraries=self.get_freetype(),
+ includes=[path_from_root('tests', 'freetype', 'include')],
+ post_build=post)
# github issue 324
print '[issue 324]'
diff --git a/tests/test_sockets.py b/tests/test_sockets.py
index 4f6ee2a9..82ddc6fe 100644
--- a/tests/test_sockets.py
+++ b/tests/test_sockets.py
@@ -142,11 +142,12 @@ class sockets(BrowserCore):
# def test_sockets_gethostbyname(self):
# self.btest(os.path.join('sockets', 'test_sockets_gethostbyname.c'), expected='0', args=['-O2', '-DSOCKK=8997'])
- def test_sockets_select_server_no_accept(self):
+ def test_sockets_select_server_down(self):
for harness in [
- WebsockifyServerHarness(os.path.join('sockets', 'test_sockets_select_server_no_accept_server.c'), ['-DSOCKK=8995'], 8996, 8995)
+ WebsockifyServerHarness(os.path.join('sockets', 'test_sockets_select_server_down_server.c'), ['-DSOCKK=9002'], 9003, 9002)
]:
- self.btest(os.path.join('sockets', 'test_sockets_select_server_no_accept_client.c'), expected='266', args=['-DSOCKK=8996'])
+ with harness:
+ self.btest(os.path.join('sockets', 'test_sockets_select_server_down_client.c'), expected='266', args=['-DSOCKK=9003'])
def test_sockets_select_server_closes_connection_rw(self):
sockets_include = '-I'+path_from_root('tests', 'sockets')
@@ -178,7 +179,7 @@ class sockets(BrowserCore):
try:
proc = make_relay_server(2234, 2236)
pids.append(proc.pid)
- self.btest(os.path.join('sockets', 'test_enet_client.c'), expected='0', args=['-DSOCKK=2237'] + enet)
+ self.btest(os.path.join('sockets', 'test_enet_client.c'), expected='0', args=['-DSOCKK=2237', '-DUSE_IFRAME'] + enet)
finally:
clean_pids(pids);
diff --git a/tests/tex_nonbyte.c b/tests/tex_nonbyte.c
index 8f2ec162..960d0efb 100644
--- a/tests/tex_nonbyte.c
+++ b/tests/tex_nonbyte.c
@@ -37,6 +37,7 @@ REDISTRIBUTION OF THIS SOFTWARE.
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/tests/unistd/misc.out b/tests/unistd/misc.out
index 43971955..8f03f688 100644
--- a/tests/unistd/misc.out
+++ b/tests/unistd/misc.out
@@ -44,3 +44,10 @@ setgid: -1, errno: 1
setegid: -1, errno: 1
setuid: -1, errno: 1
seteuid: -1, errno: 1
+setpgrp: -1, errno: 1
+setsid: -1, errno: 1
+setpgid: -1, errno: 1
+setregid: -1, errno: 1
+setreuid: -1, errno: 1
+getgroups: 1, result: 0, errno: 0
+setgroups: -1, errno: 1
diff --git a/tools/file_packager.py b/tools/file_packager.py
index 33ccebad..bb62e905 100644
--- a/tools/file_packager.py
+++ b/tools/file_packager.py
@@ -329,13 +329,55 @@ if has_preloaded:
# Data requests - for getting a block of data out of the big archive - have a similar API to XHRs
code += '''
- function DataRequest() {}
+ function DataRequest(start, end, crunched, audio) {
+ this.start = start;
+ this.end = end;
+ this.crunched = crunched;
+ this.audio = audio;
+ }
DataRequest.prototype = {
requests: {},
open: function(mode, name) {
+ this.name = name;
this.requests[name] = this;
+ Module['addRunDependency']('fp ' + this.name);
+ },
+ send: function() {},
+ onload: function() {
+ var data = this.byteArray.subarray(this.start, this.end);
+ var size = this.end - this.start;
+ var ptr = Module['_malloc'](size); // XXX leaked if a preload plugin replaces with new data
+ Module['HEAPU8'].set(data, ptr);
+ var arrayBuffer = Module['HEAPU8'].subarray(ptr, ptr + size);
+ assert(arrayBuffer, 'Loading file ' + name + ' failed');
+ var byteArray = !arrayBuffer.subarray ? new Uint8Array(arrayBuffer) : arrayBuffer;
+
+ if (this.crunched) {
+ var ddsHeader = byteArray.subarray(0, 128);
+ var that = this;
+ requestDecrunch(this.name, byteArray.subarray(128), function(ddsData) {
+ byteArray = new Uint8Array(ddsHeader.length + ddsData.length);
+ byteArray.set(ddsHeader, 0);
+ byteArray.set(ddsData, 128);
+ that.finish(byteArray);
+ });
+ } else {
+ this.finish(byteArray);
+ }
+ },
+ finish: function(byteArray) {
+ var that = this;
+ Module['FS_createPreloadedFile'](PATH.dirname(this.name), PATH.basename(this.name), byteArray, true, true, function() {
+ Module['removeRunDependency']('fp ' + that.name);
+ }, function() {
+ if (that.audio) {
+ Module['removeRunDependency']('fp ' + that.name); // workaround for chromium bug 124926 (still no audio with this, but at least we don't hang)
+ } else {
+ Runtime.warn('Preloading file ' + that.name + ' failed');
+ }
+ });
+ this.requests[this.name] = null;
},
- send: function() {}
};
'''
@@ -364,66 +406,23 @@ for file_ in data_files:
# Preload
varname = 'filePreload%d' % counter
counter += 1
- dds = crunch and filename.endswith(CRUNCH_INPUT_SUFFIX)
-
- prepare = ''
- finish = "Module['removeRunDependency']('fp %s');\n" % filename
-
- if dds:
- # decompress crunch format into dds
- prepare = '''
- var ddsHeader = byteArray.subarray(0, %(dds_header_size)d);
- requestDecrunch('%(filename)s', byteArray.subarray(%(dds_header_size)d), function(ddsData) {
- byteArray = new Uint8Array(ddsHeader.length + ddsData.length);
- byteArray.set(ddsHeader, 0);
- byteArray.set(ddsData, %(dds_header_size)d);
-''' % { 'filename': filename, 'dds_header_size': DDS_HEADER_SIZE }
-
- finish += '''
- });
-'''
-
- code += '''
- var %(varname)s = new %(request)s();
- %(varname)s.open('GET', '%(filename)s', true);
- %(varname)s.responseType = 'arraybuffer';
- %(varname)s.onload = function() {
- var arrayBuffer = %(varname)s.response;
- assert(arrayBuffer, 'Loading file %(filename)s failed.');
- var byteArray = !arrayBuffer.subarray ? new Uint8Array(arrayBuffer) : arrayBuffer;
- %(prepare)s
- Module['FS_createPreloadedFile']('%(dirname)s', '%(basename)s', byteArray, true, true, function() {
- %(finish)s
- }%(fail)s);
- };
- Module['addRunDependency']('fp %(filename)s');
- %(varname)s.send(null);
+ code += ''' new DataRequest(%(start)d, %(end)d, %(crunched)s, %(audio)s).open('GET', '%(filename)s');
''' % {
- 'request': 'DataRequest', # In the past we also supported XHRs here
- 'varname': varname,
- 'filename': filename,
- 'dirname': dirname,
- 'basename': basename,
- 'prepare': prepare,
- 'finish': finish,
- 'fail': '' if filename[-4:] not in AUDIO_SUFFIXES else ''', function() { Module['removeRunDependency']('fp %s') }''' % filename # workaround for chromium bug 124926 (still no audio with this, but at least we don't hang)
- }
+ 'filename': file_['dstpath'],
+ 'start': file_['data_start'],
+ 'end': file_['data_end'],
+ 'crunched': '1' if crunch and filename.endswith(CRUNCH_INPUT_SUFFIX) else '0',
+ 'audio': '1' if filename[-4:] in AUDIO_SUFFIXES else '0',
+ }
else:
assert 0
if has_preloaded:
# Get the big archive and split it up
- use_data = ''
+ use_data = ' DataRequest.prototype.byteArray = byteArray;\n'
for file_ in data_files:
if file_['mode'] == 'preload':
- use_data += '''
- curr = DataRequest.prototype.requests['%s'];
- var data = byteArray.subarray(%d, %d);
- var ptr = Module['_malloc'](%d);
- Module['HEAPU8'].set(data, ptr);
- curr.response = Module['HEAPU8'].subarray(ptr, ptr + %d);
- curr.onload();
- ''' % (file_['dstpath'], file_['data_start'], file_['data_end'], file_['data_end'] - file_['data_start'], file_['data_end'] - file_['data_start'])
+ use_data += ' DataRequest.prototype.requests["%s"].onload();\n' % (file_['dstpath'])
use_data += " Module['removeRunDependency']('datafile_%s');\n" % data_target
if Compression.on:
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index a673e019..9a5104bf 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -1236,7 +1236,7 @@ function vacuum(ast) {
}
} break;
case 'label': {
- if (node[2][0] === 'toplevel' && (!node[2][1] || node[2][1].length === 0)) {
+ if (node[2] && node[2][0] === 'toplevel' && (!node[2][1] || node[2][1].length === 0)) {
return emptyNode();
}
} break;
@@ -3057,16 +3057,24 @@ function outline(ast) {
var chunks = [];
var currSize = 0;
var currChunk = [];
+ var force = false; // when we hit a case X: that falls through, we force inclusion of everything until a full case
parts.forEach(function(part) {
var size = (part.condition ? measureSize(part.condition) : 0) + measureSize(part.body) + 5; // add constant for overhead of extra code
assert(size > 0);
- if (size + currSize >= minSize && currSize) {
+ if (size + currSize >= minSize && currSize && !force) {
chunks.push(currChunk);
currChunk = [];
currSize = 0;
}
currChunk.push(part);
currSize += size;
+ if (!isIf) {
+ var last = part.body;
+ last = last[stats.length-1];
+ if (last && last[0] === 'block') last = last[1][last[1].length-1];
+ if (last && last[0] === 'stat') last = last[1];
+ force = !last || last[0] !== 'break';
+ }
});
assert(currSize);
chunks.push(currChunk);
@@ -3115,6 +3123,8 @@ function outline(ast) {
});
}
+ var maxTotalOutlinings = Infinity; // debugging tool
+
// Prepares information for spilling of local variables
function analyzeFunction(func, asmData) {
var stack = []; // list of variables, each gets 8 bytes
@@ -3134,7 +3144,7 @@ function outline(ast) {
// The control variables are zeroed out when calling an outlined function, and after using
// the value after they return.
var size = measureSize(func);
- asmData.maxOutlinings = Math.round(3*size/extraInfo.sizeToOutline);
+ asmData.maxOutlinings = Math.min(Math.round(3*size/extraInfo.sizeToOutline), maxTotalOutlinings);
asmData.intendedPieces = Math.ceil(size/extraInfo.sizeToOutline);
asmData.totalStackSize = stackSize + (stack.length + 2*asmData.maxOutlinings)*8;
asmData.controlStackPos = function(i) { return stackSize + (stack.length + i)*8 };
@@ -3464,6 +3474,7 @@ function outline(ast) {
asmData.splitCounter--;
return [];
}
+ maxTotalOutlinings--;
for (var v in owned) {
if (v != 'sp') delete asmData.vars[v]; // parent does not need these anymore
}
@@ -3620,6 +3631,8 @@ function outline(ast) {
var funcs = ast[1];
+ var maxTotalFunctions = Infinity; // debugging tool
+
var more = true;
while (more) {
more = false;
@@ -3627,9 +3640,11 @@ function outline(ast) {
var newFuncs = [];
funcs.forEach(function(func) {
+ vacuum(func); // clear out empty nodes that affect code size
var asmData = normalizeAsm(func);
var size = measureSize(func);
- if (size >= extraInfo.sizeToOutline) {
+ if (size >= extraInfo.sizeToOutline && maxTotalFunctions > 0) {
+ maxTotalFunctions--;
aggressiveVariableElimination(func, asmData);
flatten(func, asmData);
analyzeFunction(func, asmData);
diff --git a/tools/test-js-optimizer-asm-outline1-output.js b/tools/test-js-optimizer-asm-outline1-output.js
index d8ea9446..895004d8 100644
--- a/tools/test-js-optimizer-asm-outline1-output.js
+++ b/tools/test-js-optimizer-asm-outline1-output.js
@@ -321,6 +321,48 @@ function chain() {
helper$0 = HEAP32[sp + 8 >> 2] | 0;
STACKTOP = sp;
}
+function switchh() {
+ var helper$0 = 0, helper$1 = 0, sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 296 | 0;
+ helper$0 = 1;
+ helper$1 = x;
+ if (helper$0) {
+ helper$0 = 0;
+ switch (helper$1 | 0) {
+ case 0:
+ {
+ f(0);
+ g();
+ break;
+ }
+ default:
+ {
+ helper$0 = 1;
+ }
+ }
+ }
+ HEAP32[sp + 8 >> 2] = helper$0;
+ HEAP32[sp + 16 >> 2] = helper$1;
+ HEAP32[sp + 40 >> 2] = 0;
+ HEAP32[sp + 44 >> 2] = 0;
+ switchh$2(sp);
+ helper$0 = HEAP32[sp + 8 >> 2] | 0;
+ HEAP32[sp + 8 >> 2] = helper$0;
+ HEAP32[sp + 16 >> 2] = helper$1;
+ HEAP32[sp + 32 >> 2] = 0;
+ HEAP32[sp + 36 >> 2] = 0;
+ switchh$1(sp);
+ helper$0 = HEAP32[sp + 8 >> 2] | 0;
+ if (helper$0) {
+ helper$0 = 0;
+ HEAP32[sp + 16 >> 2] = helper$1;
+ HEAP32[sp + 24 >> 2] = 0;
+ HEAP32[sp + 28 >> 2] = 0;
+ switchh$0(sp);
+ }
+ STACKTOP = sp;
+}
function lin$0(sp) {
sp = sp | 0;
c(14);
@@ -645,4 +687,98 @@ function chain$4(sp) {
}
HEAP32[sp + 8 >> 2] = helper$0;
}
+function switchh$0(sp) {
+ sp = sp | 0;
+ var helper$1 = 0;
+ helper$1 = HEAP32[sp + 16 >> 2] | 0;
+ switch (helper$1 | 0) {
+ case 4:
+ {
+ f(4);
+ g();
+ }
+ case 5:
+ {
+ f(5);
+ g();
+ }
+ case 6:
+ {
+ f(6);
+ g();
+ }
+ default:
+ {
+ print(9);
+ }
+ }
+}
+function switchh$1(sp) {
+ sp = sp | 0;
+ var helper$0 = 0, helper$1 = 0;
+ helper$0 = HEAP32[sp + 8 >> 2] | 0;
+ helper$1 = HEAP32[sp + 16 >> 2] | 0;
+ if (helper$0) {
+ helper$0 = 0;
+ switch (helper$1 | 0) {
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 3:
+ {
+ f(3);
+ g();
+ break;
+ }
+ default:
+ {
+ helper$0 = 1;
+ }
+ }
+ }
+ HEAP32[sp + 8 >> 2] = helper$0;
+}
+function switchh$2(sp) {
+ sp = sp | 0;
+ var helper$0 = 0, helper$1 = 0;
+ helper$0 = HEAP32[sp + 8 >> 2] | 0;
+ helper$1 = HEAP32[sp + 16 >> 2] | 0;
+ if (helper$0) {
+ helper$0 = 0;
+ switch (helper$1 | 0) {
+ case 1:
+ {
+ f(1);
+ g();
+ break;
+ }
+ default:
+ {
+ helper$0 = 1;
+ }
+ }
+ }
+ if (helper$0) {
+ helper$0 = 0;
+ switch (helper$1 | 0) {
+ case 2:
+ {
+ f(2);
+ g();
+ break;
+ }
+ default:
+ {
+ helper$0 = 1;
+ }
+ }
+ }
+ HEAP32[sp + 8 >> 2] = helper$0;
+}
diff --git a/tools/test-js-optimizer-asm-outline1.js b/tools/test-js-optimizer-asm-outline1.js
index 311cb206..3c454182 100644
--- a/tools/test-js-optimizer-asm-outline1.js
+++ b/tools/test-js-optimizer-asm-outline1.js
@@ -259,5 +259,53 @@ function chain() {
print(99);
}
}
+function switchh() {
+ switch (x) {
+ case 0: {
+ f(0);
+ g();
+ break;
+ }
+ case 1: {
+ f(1);
+ g();
+ break;
+ }
+ case 2: {
+ f(2);
+ g();
+ break;
+ }
+ case 21: // gotta keem em unseparated
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 3: { // these too
+ f(3);
+ g();
+ break;
+ }
+ case 4: {
+ f(4);
+ g();
+ }
+ case 5: {
+ f(5);
+ g();
+ }
+ case 6: {
+ f(6);
+ g();
+ }
+ default: {
+ print(9);
+ }
+ }
+}
// EMSCRIPTEN_GENERATED_FUNCTIONS
// EXTRA_INFO: { "sizeToOutline": 30, "allowCostlyOutlines": 1 }