aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/intertyper.js2
-rw-r--r--src/jsifier.js26
-rw-r--r--src/library.js3
-rw-r--r--src/library_browser.js19
-rw-r--r--src/library_gl.js38
-rw-r--r--src/library_glut.js2
-rw-r--r--src/library_sdl.js34
-rw-r--r--src/parseTools.js36
-rw-r--r--src/preamble.js15
-rw-r--r--src/relooper/Relooper.cpp16
-rw-r--r--src/relooper/test.txt4
-rw-r--r--src/runtime.js2
12 files changed, 133 insertions, 64 deletions
diff --git a/src/intertyper.js b/src/intertyper.js
index b34d0c08..10822e48 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -241,7 +241,7 @@ function intertyper(lines, sidePass, baseLineNums) {
if (mainPass && /^}.*/.test(line)) {
inFunction = false;
if (mainPass) {
- var func = funcHeaderHandler({ tokens: tokenize(currFunctionLines[0], currFunctionLineNum) });
+ var func = funcHeaderHandler({ tokens: tokenize(currFunctionLines[0]) });
if (SKIP_STACK_IN_SMALL && /emscripten_autodebug/.exec(func.ident)) {
warnOnce('Disabling SKIP_STACK_IN_SMALL because we are apparently processing autodebugger data');
diff --git a/src/jsifier.js b/src/jsifier.js
index 6b831b04..8de20c80 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -6,7 +6,6 @@
// Handy sets
var STRUCT_LIST = set('struct', 'list');
-var UNDERSCORE_OPENPARENS = set('_', '(');
var RELOOP_IGNORED_LASTS = set('return', 'unreachable', 'resume');
var addedLibraryItems = {};
@@ -19,7 +18,7 @@ var INDENTATION = ' ';
var functionStubSigs = {};
// JSifier
-function JSify(data, functionsOnly, givenFunctions) {
+function JSify(data, functionsOnly) {
//B.start('jsifier');
var mainPass = !functionsOnly;
@@ -96,19 +95,6 @@ function JSify(data, functionsOnly, givenFunctions) {
// Functions
- Functions.currExternalFunctions = !mainPass ? givenFunctions.currExternalFunctions : {};
-
- data.functionStubs.forEach(function(func) {
- // Don't overwrite stubs that have more info.
- if (!Functions.currExternalFunctions.hasOwnProperty(func.ident) ||
- !Functions.currExternalFunctions[func.ident].numParams === undefined) {
- Functions.currExternalFunctions[func.ident] = {
- hasVarArgs: func.hasVarArgs,
- numParams: func.params && func.params.length
- };
- }
- });
-
if (phase == 'funcs') { // || phase == 'pre') { // pre has function shells, just to defined implementedFunctions
var MAX_BATCH_FUNC_LINES = 1000;
while (data.unparsedFunctions.length > 0) {
@@ -123,7 +109,7 @@ function JSify(data, functionsOnly, givenFunctions) {
dprint('unparsedFunctions','====================\n// Processing function batch of ' + currBaseLineNums.length +
' functions, ' + currFuncLines.length + ' lines, functions left: ' + data.unparsedFunctions.length);
if (DEBUG_MEMORY) MemoryDebugger.tick('pre-func');
- JSify(analyzer(intertyper(currFuncLines, true, currBaseLineNums), true), true, Functions);
+ JSify(analyzer(intertyper(currFuncLines, true, currBaseLineNums), true), true);
if (DEBUG_MEMORY) MemoryDebugger.tick('post-func');
}
currFuncLines = currBaseLineNums = null; // Do not hold on to anything from inside that loop (JS function scoping..)
@@ -639,8 +625,8 @@ function JSify(data, functionsOnly, givenFunctions) {
}
}
- if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */';
if (!ASM_JS) {
+ if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */';
func.JS += INDENTATION + 'var label=0;\n';
}
@@ -892,8 +878,8 @@ function JSify(data, functionsOnly, givenFunctions) {
function makeAssign(item) {
var valueJS = item.JS;
item.JS = '';
- if (CLOSURE_ANNOTATIONS) item.JS += '/** @type {number} */ ';
if (!ASM_JS || item.intertype != 'alloca' || item.funcData.variables[item.assignTo].impl == VAR_EMULATED) { // asm only needs non-allocas
+ if (CLOSURE_ANNOTATIONS) item.JS += '/** @type {number} */ ';
item.JS += ((ASM_JS || item.overrideSSA) ? '' : 'var ') + toNiceIdent(item.assignTo);
}
var value = parseNumerical(valueJS);
@@ -1810,7 +1796,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
}
- JSify(globalsData, true, Functions);
+ JSify(globalsData, true);
globalsData = null;
data.unparsedGlobalss = null;
@@ -1824,7 +1810,7 @@ function JSify(data, functionsOnly, givenFunctions) {
print('staticSealed = true; // seal the static portion of memory\n');
print('STACK_MAX = STACK_BASE + ' + TOTAL_STACK + ';\n');
print('DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX);\n');
- print('assert(DYNAMIC_BASE < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY\n');
+ print('assert(DYNAMIC_BASE < TOTAL_MEMORY, "TOTAL_MEMORY not big enough for stack");\n');
}
if (asmLibraryFunctions.length > 0) {
diff --git a/src/library.js b/src/library.js
index fc731e01..354e5549 100644
--- a/src/library.js
+++ b/src/library.js
@@ -8858,7 +8858,8 @@ LibraryManager.library = {
}
}
str += ')';
- args = args.callee.caller.arguments;
+ var caller = args.callee.caller;
+ args = caller ? caller.arguments : [];
if (first)
str = '';
return [args, funcname, str];
diff --git a/src/library_browser.js b/src/library_browser.js
index b368c6ac..e0f53052 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -478,19 +478,30 @@ mergeInto(LibraryManager.library, {
// in the coordinates.
var rect = Module["canvas"].getBoundingClientRect();
var x, y;
+
+ // Neither .scrollX or .pageXOffset are defined in a spec, but
+ // we prefer .scrollX because it is currently in a spec draft.
+ // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/)
+ var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset);
+ var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset);
+#if ASSERTIONS
+ // If this assert lands, it's likely because the browser doesn't support scrollX or pageXOffset
+ // and we have no viable fallback.
+ assert((typeof scrollX !== 'undefined') && (typeof scrollY !== 'undefined'), 'Unable to retrieve scroll position, mouse positions likely broken.');
+#endif
if (event.type == 'touchstart' ||
event.type == 'touchend' ||
event.type == 'touchmove') {
var t = event.touches.item(0);
if (t) {
- x = t.pageX - (window.scrollX + rect.left);
- y = t.pageY - (window.scrollY + rect.top);
+ x = t.pageX - (scrollX + rect.left);
+ y = t.pageY - (scrollY + rect.top);
} else {
return;
}
} else {
- x = event.pageX - (window.scrollX + rect.left);
- y = event.pageY - (window.scrollY + rect.top);
+ x = event.pageX - (scrollX + rect.left);
+ y = event.pageY - (scrollY + rect.top);
}
// the canvas might be CSS-scaled compared to its backbuffer;
diff --git a/src/library_gl.js b/src/library_gl.js
index efe3b868..075d7cb5 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -268,11 +268,27 @@ var LibraryGL = {
return;
case "object":
if (result === null) {
- GL.recordError(0x0500); // GL_INVALID_ENUM
+ // null is a valid result for some (e.g., which buffer is bound - perhaps nothing is bound), but otherwise
+ // can mean an invalid name_, which we need to report as an error
+ switch(name_) {
+ case 0x8894: // ARRAY_BUFFER_BINDING
+ case 0x8B8D: // CURRENT_PROGRAM
+ case 0x8895: // ELEMENT_ARRAY_BUFFER_BINDING
+ case 0x8CA6: // FRAMEBUFFER_BINDING
+ case 0x8CA7: // RENDERBUFFER_BINDING
+ case 0x8069: // TEXTURE_BINDING_2D
+ case 0x8514: { // TEXTURE_BINDING_CUBE_MAP
+ ret = 0;
+ break;
+ }
+ default: {
+ GL.recordError(0x0500); // GL_INVALID_ENUM
#if GL_ASSERTIONS
- Module.printErr('GL_INVALID_ENUM in glGet' + type + 'v(' + name_ + ') and it returns null!');
+ Module.printErr('GL_INVALID_ENUM in glGet' + type + 'v(' + name_ + ') and it returns null!');
#endif
- return;
+ return;
+ }
+ }
} else if (result instanceof Float32Array ||
result instanceof Uint32Array ||
result instanceof Int32Array ||
@@ -1688,7 +1704,7 @@ var LibraryGL = {
glGetFramebufferAttachmentParameteriv__sig: 'viiii',
glGetFramebufferAttachmentParameteriv: function(target, attachment, pname, params) {
var result = Module.ctx.getFramebufferAttachmentParameter(target, attachment, pname);
- {{{ makeSetValue('params', '0', 'params', 'i32') }}};
+ {{{ makeSetValue('params', '0', 'result', 'i32') }}};
},
glIsFramebuffer__sig: 'ii',
@@ -1919,6 +1935,13 @@ var LibraryGL = {
return id;
};
+ function ensurePrecision(source) {
+ if (!/precision +(low|medium|high)p +float *;/.test(source)) {
+ source = 'precision mediump float;\n' + source;
+ }
+ return source;
+ }
+
var glShaderSource = _glShaderSource;
_glShaderSource = function _glShaderSource(shader, count, string, length) {
var source = GL.getSource(shader, count, string, length);
@@ -1992,6 +2015,7 @@ var LibraryGL = {
source = 'varying float v_fogFragCoord; \n' +
source.replace(/gl_FogFragCoord/g, 'v_fogFragCoord');
}
+ source = ensurePrecision(source);
} else { // Fragment shader
for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
var old = source;
@@ -2023,7 +2047,7 @@ var LibraryGL = {
source = 'varying float v_fogFragCoord; \n' +
source.replace(/gl_FogFragCoord/g, 'v_fogFragCoord');
}
- source = 'precision mediump float;\n' + source;
+ source = ensurePrecision(source);
}
#if GL_DEBUG
GL.shaderSources[shader] = source;
@@ -4973,7 +4997,7 @@ var LibraryGL = {
GL.instancedArraysExt.vertexAttribDivisorANGLE(index, divisor);
},
- glDrawArraysInstanced_sig: 'viiii',
+ glDrawArraysInstanced__sig: 'viiii',
glDrawArraysInstanced: function(mode, first, count, primcount) {
#if GL_ASSERTIONS
assert(GL.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
@@ -4981,7 +5005,7 @@ var LibraryGL = {
GL.instancedArraysExt.drawArraysInstancedANGLE(mode, first, count, primcount);
},
- glDrawElementsInstanced_sig: 'viiiii',
+ glDrawElementsInstanced__sig: 'viiiii',
glDrawElementsInstanced: function(mode, count, type, indices, primcount) {
#if GL_ASSERTIONS
assert(GL.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
diff --git a/src/library_glut.js b/src/library_glut.js
index ba4d75ab..76a52b73 100644
--- a/src/library_glut.js
+++ b/src/library_glut.js
@@ -126,6 +126,8 @@ var LibraryGLUT = {
return keycode - 106 + 42; // *,+-./ TODO handle shift?
switch (keycode) {
+ case 9: // tab key
+ case 13: // return key
case 27: // escape
case 32: // space
case 61: // equal
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 1c1e8107..fc38dd1c 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -1059,11 +1059,35 @@ var LibrarySDL = {
var src = buffer >> 2;
var dst = 0;
var isScreen = surf == SDL.screen;
- var data32 = new Uint32Array(data.buffer);
- var num = data32.length;
- while (dst < num) {
- // HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
- data32[dst++] = HEAP32[src++] | (isScreen ? 0xff000000 : 0);
+ var num;
+ if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) {
+ // IE10/IE11: ImageData objects are backed by the deprecated CanvasPixelArray,
+ // not UInt8ClampedArray. These don't have buffers, so we need to revert
+ // to copying a byte at a time. We do the undefined check because modern
+ // browsers do not define CanvasPixelArray anymore.
+ num = data.length;
+ while (dst < num) {
+ var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
+ data[dst ] = val & 0xff;
+ data[dst+1] = (val >> 8) & 0xff;
+ data[dst+2] = (val >> 16) & 0xff;
+ data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
+ src++;
+ dst += 4;
+ }
+ } else {
+ var data32 = new Uint32Array(data.buffer);
+ num = data32.length;
+ if (isScreen) {
+ while (dst < num) {
+ // HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
+ data32[dst++] = HEAP32[src++] | 0xff000000;
+ }
+ } else {
+ while (dst < num) {
+ data32[dst++] = HEAP32[src++];
+ }
+ }
}
#else
var num = surfData.image.data.length;
diff --git a/src/parseTools.js b/src/parseTools.js
index ff981264..22e9b94c 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -16,6 +16,7 @@ function processMacros(text) {
// Simple #if/else/endif preprocessing for a file. Checks if the
// ident checked is true in our global.
+// Also handles #include x.js (similar to C #include <file>)
function preprocess(text) {
var lines = text.split('\n');
var ret = '';
@@ -30,25 +31,30 @@ function preprocess(text) {
ret += line + '\n';
}
} else {
- if (line[1] && line[1] == 'i') { // if
- var parts = line.split(' ');
- var ident = parts[1];
- var op = parts[2];
- var value = parts[3];
- if (op) {
- if (op === '==') {
- showStack.push(ident in this && this[ident] == value);
- } else if (op === '!=') {
- showStack.push(!(ident in this && this[ident] == value));
+ if (line[1] == 'i') {
+ if (line[2] == 'f') { // if
+ var parts = line.split(' ');
+ var ident = parts[1];
+ var op = parts[2];
+ var value = parts[3];
+ if (op) {
+ if (op === '==') {
+ showStack.push(ident in this && this[ident] == value);
+ } else if (op === '!=') {
+ showStack.push(!(ident in this && this[ident] == value));
+ } else {
+ error('unsupported preprecessor op ' + op);
+ }
} else {
- error('unsupported preprecessor op ' + op);
+ showStack.push(ident in this && this[ident] > 0);
}
- } else {
- showStack.push(ident in this && this[ident] > 0);
+ } else if (line[2] == 'n') { // include
+ var included = read(line.substr(line.indexOf(' ')+1));
+ ret += '\n' + preprocess(included) + '\n'
}
- } else if (line[2] && line[2] == 'l') { // else
+ } else if (line[2] == 'l') { // else
showStack.push(!showStack.pop());
- } else if (line[2] && line[2] == 'n') { // endif
+ } else if (line[2] == 'n') { // endif
showStack.pop();
} else {
throw "Unclear preprocessor command: " + line;
diff --git a/src/preamble.js b/src/preamble.js
index 832ec2c3..f9fccdf6 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -866,6 +866,21 @@ var TOTAL_STACK = Module['TOTAL_STACK'] || {{{ TOTAL_STACK }}};
var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || {{{ TOTAL_MEMORY }}};
var FAST_MEMORY = Module['FAST_MEMORY'] || {{{ FAST_MEMORY }}};
+#if ASM_JS
+var totalMemory = 4096;
+while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) {
+ if (totalMemory < 16*1024*1024) {
+ totalMemory *= 2;
+ } else {
+ totalMemory += 16*1024*1024
+ }
+}
+if (totalMemory !== TOTAL_MEMORY) {
+ Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be more reasonable');
+ TOTAL_MEMORY = totalMemory;
+}
+#endif
+
// Initialize the runtime's memory
#if USE_TYPED_ARRAYS
// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index 70cf844b..389d7447 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -308,7 +308,7 @@ void MultipleShape::Render(bool InLoop) {
}
RenderLoopPostfix();
if (Next) Next->Render(InLoop);
-};
+}
// LoopShape
@@ -323,7 +323,7 @@ void LoopShape::Render(bool InLoop) {
Indenter::Unindent();
PrintIndented("}\n");
if (Next) Next->Render(InLoop);
-};
+}
// EmulatedShape
@@ -350,7 +350,7 @@ void EmulatedShape::Render(bool InLoop) {
Indenter::Unindent();
PrintIndented("}\n");
if (Next) Next->Render(InLoop);
-};
+}
// Relooper
@@ -358,8 +358,8 @@ Relooper::Relooper() : Root(NULL), Emulate(false), BlockIdCounter(1), ShapeIdCou
}
Relooper::~Relooper() {
- for (int i = 0; i < Blocks.size(); i++) delete Blocks[i];
- for (int i = 0; i < Shapes.size(); i++) delete Shapes[i];
+ for (unsigned i = 0; i < Blocks.size(); i++) delete Blocks[i];
+ for (unsigned i = 0; i < Shapes.size(); i++) delete Shapes[i];
}
void Relooper::AddBlock(Block *New) {
@@ -399,7 +399,7 @@ void Relooper::Calculate(Block *Entry) {
// RAII cleanup. Without splitting, we will be forced to introduce labelled loops to allow
// reaching the final block
void SplitDeadEnds() {
- int TotalCodeSize = 0;
+ unsigned TotalCodeSize = 0;
for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) {
Block *Curr = *iter;
TotalCodeSize += strlen(Curr->Code);
@@ -417,7 +417,7 @@ void Relooper::Calculate(Block *Entry) {
for (BlockSet::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) {
Block *Prior = *iter;
Block *Split = new Block(Original->Code, Original->BranchVar);
- Parent->Blocks.push_back(Split);
+ Parent->AddBlock(Split);
PrintDebug(" to %d\n", Split->Id);
Split->BranchesIn.insert(Prior);
Branch *Details = Prior->BranchesOut[Original];
@@ -451,7 +451,7 @@ void Relooper::Calculate(Block *Entry) {
Pre.FindLive(Entry);
// Add incoming branches from live blocks, ignoring dead code
- for (int i = 0; i < Blocks.size(); i++) {
+ for (unsigned i = 0; i < Blocks.size(); i++) {
Block *Curr = Blocks[i];
if (!contains(Pre.Live, Curr)) continue;
for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
diff --git a/src/relooper/test.txt b/src/relooper/test.txt
index 540f7bdb..9bdd4093 100644
--- a/src/relooper/test.txt
+++ b/src/relooper/test.txt
@@ -91,7 +91,7 @@
}
default: {
var $x_1 = $x_0;
- label = -1;
+ label = 8;
break L1;
}
}
@@ -106,7 +106,7 @@
}
}
}
- if (label == -1) {
+ if (label == 8) {
// code 7
}
// code 4
diff --git a/src/runtime.js b/src/runtime.js
index 8ba5d08d..cd3afb4b 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -250,7 +250,7 @@ var Runtime = {
prev = curr;
return curr;
});
- if (type.name_[0] === '[') {
+ if (type.name_ && type.name_[0] === '[') {
// arrays have 2 elements, so we get the proper difference. then we scale here. that way we avoid
// allocating a potentially huge array for [999999 x i8] etc.
type.flatSize = parseInt(type.name_.substr(1))*type.flatSize/2;