aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jsifier.js12
-rw-r--r--src/library.js2
-rw-r--r--src/library_browser.js7
-rw-r--r--src/modules.js16
-rw-r--r--src/parseTools.js13
-rw-r--r--src/preamble.js6
-rw-r--r--src/settings.js5
7 files changed, 50 insertions, 11 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index 4af522b4..ff43c8c6 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -505,7 +505,7 @@ function JSify(data, functionsOnly, givenFunctions) {
item.JS = '';
} else if (LibraryManager.library.hasOwnProperty(shortident)) {
item.JS = addFromLibrary(shortident);
- } else {
+ } else if (!LibraryManager.library.hasOwnProperty(shortident + '__inline')) {
item.JS = 'var ' + item.ident + '; // stub for ' + item.ident;
if (WARN_ON_UNDEFINED_SYMBOLS || ASM_JS) { // always warn on undefs in asm, since it breaks validation
warn('Unresolved symbol: ' + item.ident);
@@ -1401,6 +1401,8 @@ function JSify(data, functionsOnly, givenFunctions) {
if (ASM_JS) {
assert(returnType.search(/\("'\[,/) == -1); // XXX need isFunctionType(type, out)
callIdent = '(' + callIdent + ')&{{{ FTM_' + sig + ' }}}'; // the function table mask is set in emscripten.py
+ } else if (SAFE_DYNCALLS) {
+ callIdent = '(tempInt=' + callIdent + ',tempInt < 0 || tempInt >= FUNCTION_TABLE.length-1 ? abort("dyncall error") : tempInt)';
}
callIdent = Functions.getTable(sig) + '[' + callIdent + ']';
}
@@ -1567,9 +1569,11 @@ function JSify(data, functionsOnly, givenFunctions) {
var shellParts = read(shellFile).split('{{BODY}}');
print(shellParts[1]);
// Print out some useful metadata (for additional optimizations later, like the eliminator)
- print('// EMSCRIPTEN_GENERATED_FUNCTIONS: ' + JSON.stringify(keys(Functions.implementedFunctions).filter(function(func) {
- return IGNORED_FUNCTIONS.indexOf(func.ident) < 0;
- })) + '\n');
+ if (EMIT_GENERATED_FUNCTIONS) {
+ print('// EMSCRIPTEN_GENERATED_FUNCTIONS: ' + JSON.stringify(keys(Functions.implementedFunctions).filter(function(func) {
+ return IGNORED_FUNCTIONS.indexOf(func.ident) < 0;
+ })) + '\n');
+ }
PassManager.serialize();
diff --git a/src/library.js b/src/library.js
index 885fe1e0..d0f73fdd 100644
--- a/src/library.js
+++ b/src/library.js
@@ -4533,7 +4533,7 @@ LibraryManager.library = {
while ((i|0) < (num|0)) {
var v1 = {{{ makeGetValueAsm('p1', 'i', 'i8', true) }}};
var v2 = {{{ makeGetValueAsm('p2', 'i', 'i8', true) }}};
- if ((v1|0) != (v2|0)) return (v1|0) > (v2|0) ? 1 : -1;
+ if ((v1|0) != (v2|0)) return ((v1|0) > (v2|0) ? 1 : -1)|0;
i = (i+1)|0;
}
return 0;
diff --git a/src/library_browser.js b/src/library_browser.js
index e9396d69..5b19a360 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -204,7 +204,12 @@ mergeInto(LibraryManager.library, {
var ctx;
try {
if (useWebGL) {
- ctx = canvas.getContext('experimental-webgl', { alpha: false });
+ ctx = canvas.getContext('experimental-webgl', {
+ alpha: false,
+#if GL_TESTING
+ preserveDrawingBuffer: true
+#endif
+ });
} else {
ctx = canvas.getContext('2d');
}
diff --git a/src/modules.js b/src/modules.js
index 695abbe7..7f8a959b 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -330,6 +330,22 @@ var Functions = {
}
}
}
+ if (SAFE_DYNCALLS) {
+ assert(!ASM_JS, 'cannot emit safe dyncalls in asm');
+ for (var j = 0; j < table.length; j++) {
+ if (table[j] == 0) {
+ table[j] = "function() { abort('dyncall error') }";
+ }
+ }
+ }
+ if (table.length > 20) {
+ // add some newlines in the table, for readability
+ var j = 10;
+ while (j+10 < table.length) {
+ table[j] += '\n';
+ j += 10;
+ }
+ }
var indices = table.toString().replace('"', '');
if (BUILD_AS_SHARED_LIB) {
// Shared libraries reuse the parent's function table.
diff --git a/src/parseTools.js b/src/parseTools.js
index 7d1a7cd9..6e0d6e32 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -103,6 +103,11 @@ function isNiceIdent(ident, loose) {
}
}
+function isJSVar(ident) {
+ return /^\(?[$_]?[\w$_\d ]*\)+$/.test(ident);
+
+}
+
function isStructPointerType(type) {
// This test is necessary for clang - in llvm-gcc, we
// could check for %struct. The downside is that %1 can
@@ -988,7 +993,8 @@ function getHeapOffset(offset, type, forceAsm) {
if (shifts != 0) {
return '(' + offset + '>>' + shifts + ')';
} else {
- return offset;
+ // we need to guard against overflows here, HEAP[U]8 expects a guaranteed int
+ return isJSVar(offset) ? offset : '(' + offset + '|0)';
}
}
}
@@ -1393,7 +1399,8 @@ function getFastValue(a, op, b, type) {
if (!(type in Runtime.FLOAT_TYPES)) {
// if guaranteed small enough to not overflow into a double, do a normal multiply
var bits = getBits(type) || 32; // default is 32-bit multiply for things like getelementptr indexes
- if ((isNumber(a) && Math.abs(a) < TWO_TWENTY) || (isNumber(b) && Math.abs(b) < TWO_TWENTY) || bits < 32) {
+ // Note that we can emit simple multiple in non-asm.js mode, but asm.js will not parse "16-bit" multiple, so must do imul there
+ if ((isNumber(a) && Math.abs(a) < TWO_TWENTY) || (isNumber(b) && Math.abs(b) < TWO_TWENTY) || (bits < 32 && !ASM_JS)) {
return '(((' + a + ')*(' + b + '))&' + ((Math.pow(2, bits)-1)|0) + ')'; // keep a non-eliminatable coercion directly on this
}
return 'Math.imul(' + a + ',' + b + ')';
@@ -1541,7 +1548,7 @@ function makePointer(slab, pos, allocator, type, ptr) {
var ret = '';
var index = 0;
while (index < array.length) {
- ret = (ret ? ret + '.concat(' : '') + '[' + array.slice(index, index + chunkSize).map(JSON.stringify) + ']' + (ret ? ')' : '');
+ ret = (ret ? ret + '.concat(' : '') + '[' + array.slice(index, index + chunkSize).map(JSON.stringify) + ']' + (ret ? ')\n' : '');
index += chunkSize;
}
return ret;
diff --git a/src/preamble.js b/src/preamble.js
index 05269c6e..a7731e7f 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -742,17 +742,19 @@ Module['writeArrayToMemory'] = writeArrayToMemory;
{{{ unSign }}}
{{{ reSign }}}
-if (!Math.imul) Math.imul = function(a, b) {
#if PRECISE_I32_MUL
+if (!Math.imul) Math.imul = function(a, b) {
var ah = a >>> 16;
var al = a & 0xffff;
var bh = b >>> 16;
var bl = b & 0xffff;
return (al*bl + ((ah*bl + al*bh) << 16))|0;
+};
#else
+Math.imul = function(a, b) {
return (a*b)|0; // fast but imprecise
-#endif
};
+#endif
// A counter of dependencies for calling run(). If we need to
// do asynchronous work before running, increment this and
diff --git a/src/settings.js b/src/settings.js
index df9da926..308afddc 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -128,6 +128,8 @@ var SAFE_HEAP = 0; // Check each write to the heap, for example, this will give
// that 3 is the option you usually want here.
var SAFE_HEAP_LOG = 0; // Log out all SAFE_HEAP operations
+var SAFE_DYNCALLS = 0; // Show stack traces on missing function pointer/virtual method calls
+
var ASM_HEAP_LOG = 0; // Simple heap logging, like SAFE_HEAP_LOG but cheaper, and in asm.js
var CORRUPTION_CHECK = 0; // When enabled, will emit a buffer area at the beginning and
@@ -158,6 +160,7 @@ var SOCKET_DEBUG = 0; // Log out socket/network data transfer.
var GL_DEBUG = 0; // Print out all calls into WebGL. As with LIBRARY_DEBUG, you can set a runtime
// option, in this case GL.debug.
+var GL_TESTING = 0; // When enabled, sets preserveDrawingBuffer in the context, to allow tests to work (but adds overhead)
var GL_MAX_TEMP_BUFFER_SIZE = 2097152; // How large GL emulation temp buffers are
var GL_UNSAFE_OPTS = 1; // Enables some potentially-unsafe optimizations in GL emulation code
@@ -326,6 +329,8 @@ var EXPLICIT_ZEXT = 0; // If 1, generate an explicit conversion of zext i1 to i3
var NECESSARY_BLOCKADDRS = []; // List of (function, block) for all block addresses that are taken.
+var EMIT_GENERATED_FUNCTIONS = 0; // whether to emit the list of generated functions, needed for external JS optimization passes
+
// Compiler debugging options
var DEBUG_TAGS_SHOWING = [];
// Some useful items: