diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/intertyper.js | 2 | ||||
-rw-r--r-- | src/jsifier.js | 26 | ||||
-rw-r--r-- | src/library.js | 3 | ||||
-rw-r--r-- | src/library_browser.js | 19 | ||||
-rw-r--r-- | src/library_gl.js | 38 | ||||
-rw-r--r-- | src/library_glut.js | 2 | ||||
-rw-r--r-- | src/library_sdl.js | 34 | ||||
-rw-r--r-- | src/parseTools.js | 36 | ||||
-rw-r--r-- | src/preamble.js | 15 | ||||
-rw-r--r-- | src/relooper/Relooper.cpp | 16 | ||||
-rw-r--r-- | src/relooper/test.txt | 4 | ||||
-rw-r--r-- | src/runtime.js | 2 |
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; |