diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-09-09 18:33:48 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-09-09 18:33:48 -0700 |
commit | 24e61522f29d3796c0a1d2736d6008006b2e4ad6 (patch) | |
tree | 8f730aba89278f06856275a4c6f7c226d8082f5a | |
parent | b12e4059465169ae9302c3565b08fc30e9132781 (diff) | |
parent | 953ebf768763fe93a0af76f5007d1f69f91d6440 (diff) |
Merge branch 'incoming'
-rw-r--r-- | AUTHORS | 4 | ||||
-rwxr-xr-x | emcc | 15 | ||||
-rw-r--r-- | settings.py | 11 | ||||
-rw-r--r-- | src/experimental/sdl_key_forwarding.diff | 57 | ||||
-rw-r--r-- | src/library.js | 45 | ||||
-rw-r--r-- | src/library_browser.js | 31 | ||||
-rw-r--r-- | src/library_sdl.js | 119 | ||||
-rw-r--r-- | src/postamble.js | 26 | ||||
-rw-r--r-- | src/settings.js | 12 | ||||
-rw-r--r-- | system/include/sys/select.h | 3 | ||||
-rwxr-xr-x | tests/runner.py | 115 | ||||
-rw-r--r-- | tests/sdl_quit.c | 33 | ||||
-rw-r--r-- | tools/js-optimizer.js | 9 | ||||
-rwxr-xr-x | tools/reproduceriter.py | 311 | ||||
-rw-r--r-- | tools/test-js-optimizer-t3.js | 49 |
15 files changed, 762 insertions, 78 deletions
@@ -32,3 +32,7 @@ a license to everyone to use it as detailed in LICENSE.) * Xingxing Pan <forandom@gmail.com> * Justin Kerk <dopefishjustin@gmail.com> * Andrea Bedini <andrea.bedini@gmail.com> +* James Pike <totoro.friend@chilon.net> +* Mokhtar Naamani <mokhtar.naamani@gmail.com> +* Benjamin Stover <benjamin.stover@gmail.com> + @@ -285,6 +285,17 @@ Options that are modified or new in %s include: llvm-link's behavior is not as permissive as ld is. + --clear-cache Manually clears the cache of compiled + emscripten system libraries (libc++, + libc++abi, dlmalloc). This is normally + handled automatically, but if you update + llvm in-place (instead of having a different + directory for a new version), the caching + mechanism can get confused. Clearing the + cache can fix weird problems related to + cache incompatibilities, like clang failing + to link with library files. + The target file, if specified (-o <target>), defines what will be generated: @@ -519,6 +530,10 @@ try: elif newargs[i] == '--remove-duplicates': remove_duplicates = True newargs[i] = '' + elif newargs[i] == '--clear-cache': + newargs[i] = '' + print >> sys.stderr, 'emcc: clearing cache' + shared.Cache.erase() elif newargs[i].startswith(('-I/', '-L/')): print >> sys.stderr, 'emcc: warning: -I or -L of an absolute path encountered. If this is to a local system header/library, it may cause problems (local system files make sense for compiling natively on your system, but not necessarily to JavaScript)' # Of course an absolute path to a non-system-specific library or header is fine, and you can ignore this warning. The danger are system headers that are e.g. x86 specific and nonportable. The emscripten bundled headers are modified to be portable, local system ones are generally not newargs = [ arg for arg in newargs if arg is not '' ] diff --git a/settings.py b/settings.py index 1133a656..bb749945 100644 --- a/settings.py +++ b/settings.py @@ -2,14 +2,15 @@ # IMPORTANT: Edit the *copy* with the right paths! # Note: If you put paths relative to the home directory, do not forget os.path.expanduser -EMSCRIPTEN_ROOT = os.path.expanduser('~/Dev/emscripten') # this helps projects using emscripten find it - -LLVM_ROOT = os.path.expanduser('~/Dev/llvm/cbuild/bin') +# this helps projects using emscripten find it +EMSCRIPTEN_ROOT = os.path.expanduser(os.getenv('EMSCRIPTEN') or '/opt/emscripten') +LLVM_ROOT = os.path.expanduser(os.getenv('LLVM') or '/usr/bin') # See below for notes on which JS engine(s) you need NODE_JS = 'node' -SPIDERMONKEY_ENGINE = [os.path.expanduser('~/Dev/mozilla-central/js/src/js'), '-m', '-n'] -V8_ENGINE = os.path.expanduser('~/Dev/v8/d8') +SPIDERMONKEY_ENGINE = [ + os.path.expanduser(os.getenv('SPIDERMONKEY') or 'js'), '-m', '-n'] +V8_ENGINE = os.path.expanduser(os.getenv('V8') or 'd8') JAVA = 'java' diff --git a/src/experimental/sdl_key_forwarding.diff b/src/experimental/sdl_key_forwarding.diff new file mode 100644 index 00000000..395dc110 --- /dev/null +++ b/src/experimental/sdl_key_forwarding.diff @@ -0,0 +1,57 @@ +diff --git a/src/library_sdl.js b/src/library_sdl.js +index 8cb8db7..d46a089 100644 +--- a/src/library_sdl.js ++++ b/src/library_sdl.js +@@ -43,6 +43,7 @@ var LibrarySDL = { + DOMButtons: [0, 0, 0], + + DOMEventToSDLEvent: {}, ++ forwardedDOMKeys: {}, + + keyCodes: { // DOM code ==> SDL code. See https://developer.mozilla.org/en/Document_Object_Model_%28DOM%29/KeyboardEvent and SDL_keycode.h + 46: 127, // SDLK_DEL == '\177' +@@ -372,6 +373,11 @@ var LibrarySDL = { + if (!SDL.DOMButtons[event.button]) return false; // ignore extra ups, can happen if we leave the canvas while pressing down, then return, + // since we add a mouseup in that case + SDL.DOMButtons[event.button] = 0; ++ } else if (event.type == 'keydown' || event.type == 'keyup') { ++ // whitelist a few keycodes that we do want to let the browser handle ++ if (event.keyCode in SDL.forwardedDOMKeys) { ++ return true; ++ } + } + + SDL.events.push(event); +@@ -399,6 +405,10 @@ var LibrarySDL = { + // Force-run a main event loop, since otherwise this event will never be caught! + Browser.mainLoop.runner(); + return true; ++ case 'keypress': ++ if (event.ctrlKey) { ++ return true; // forward control-X events, see SDL.forwardedDOMKeys ++ } + } + return false; + }, +@@ -569,13 +579,20 @@ var LibrarySDL = { + window.onunload = SDL.receiveEvent; + SDL.keyboardState = _malloc(0x10000); + _memset(SDL.keyboardState, 0, 0x10000); +- // Initialize this structure carefully for closure ++ // Initialize these structures carefully for closure + SDL.DOMEventToSDLEvent['keydown'] = 0x300 /* SDL_KEYDOWN */; + SDL.DOMEventToSDLEvent['keyup'] = 0x301 /* SDL_KEYUP */; + SDL.DOMEventToSDLEvent['mousedown'] = 0x401 /* SDL_MOUSEBUTTONDOWN */; + SDL.DOMEventToSDLEvent['mouseup'] = 0x402 /* SDL_MOUSEBUTTONUP */; + SDL.DOMEventToSDLEvent['mousemove'] = 0x400 /* SDL_MOUSEMOTION */; + SDL.DOMEventToSDLEvent['unload'] = 0x100 /* SDL_QUIT */; ++ SDL.forwardedDOMKeys[17] = 1; // control - forward control-X to keep the page responsive ++ SDL.forwardedDOMKeys[173] = 1; // minus (shrink view) ++ SDL.forwardedDOMKeys[61] = 1; // plus (expand view) ++ SDL.forwardedDOMKeys[48] = 1; // 0 (return view to normal) ++ SDL.forwardedDOMKeys[84] = 1; // t (new tab) ++ SDL.forwardedDOMKeys[87] = 1; // w (close tab) ++ SDL.forwardedDOMKeys[82] = 1; // r (reload) + return 0; // success + }, + diff --git a/src/library.js b/src/library.js index 0eefea84..d2d61867 100644 --- a/src/library.js +++ b/src/library.js @@ -4755,10 +4755,19 @@ LibraryManager.library = { __cxa_is_number_type: function(type) { var isNumber = false; try { if (type == __ZTIi) isNumber = true } catch(e){} + try { if (type == __ZTIj) isNumber = true } catch(e){} try { if (type == __ZTIl) isNumber = true } catch(e){} + try { if (type == __ZTIm) isNumber = true } catch(e){} try { if (type == __ZTIx) isNumber = true } catch(e){} + try { if (type == __ZTIy) isNumber = true } catch(e){} try { if (type == __ZTIf) isNumber = true } catch(e){} try { if (type == __ZTId) isNumber = true } catch(e){} + try { if (type == __ZTIe) isNumber = true } catch(e){} + try { if (type == __ZTIc) isNumber = true } catch(e){} + try { if (type == __ZTIa) isNumber = true } catch(e){} + try { if (type == __ZTIh) isNumber = true } catch(e){} + try { if (type == __ZTIs) isNumber = true } catch(e){} + try { if (type == __ZTIt) isNumber = true } catch(e){} return isNumber; }, @@ -4839,22 +4848,22 @@ LibraryManager.library = { // RTTI hacks for exception handling, defining type_infos for common types. // The values are dummies. We simply use the addresses of these statically // allocated variables as unique identifiers. - // type_info for int. - _ZTIi: [0], - // type_info for long. - _ZTIl: [0], - // type_info for long long. - _ZTIx: [0], - // type_info for float. - _ZTIf: [0], - // type_info for double. - _ZTId: [0], - // type_info for char. - _ZTIc: [0], - // type_info for void. - _ZTIv: [0], - // type_info for void*. - _ZTIPv: [0], + _ZTIi: [0], // int + _ZTIj: [0], // unsigned int + _ZTIl: [0], // long + _ZTIm: [0], // unsigned long + _ZTIx: [0], // long long + _ZTIy: [0], // unsigned long long + _ZTIf: [0], // float + _ZTId: [0], // double + _ZTIe: [0], // long double + _ZTIc: [0], // char + _ZTIa: [0], // signed char + _ZTIh: [0], // unsigned char + _ZTIs: [0], // short + _ZTIt: [0], // signed short + _ZTIv: [0], // void + _ZTIPv: [0], // void* llvm_uadd_with_overflow_i8: function(x, y) { x = x & 0xff; @@ -5669,7 +5678,7 @@ LibraryManager.library = { // http://pubs.opengroup.org/onlinepubs/009695399/functions/times.html // NOTE: This is fake, since we can't calculate real CPU time usage in JS. if (buffer !== 0) { - memset(buffer, 0, ___tms_struct_layout.__size__); + _memset(buffer, 0, ___tms_struct_layout.__size__); } return 0; }, @@ -6295,7 +6304,7 @@ LibraryManager.library = { htonl: function(value) { return ((value & 0xff) << 24) + ((value & 0xff00) << 8) + - ((value & 0xff0000) >> 8) + ((value & 0xff000000) >> 24); + ((value & 0xff0000) >>> 8) + ((value & 0xff000000) >>> 24); }, htons: function(value) { return ((value & 0xff) << 8) + ((value & 0xff00) >> 8); diff --git a/src/library_browser.js b/src/library_browser.js index e6a8b7c6..bf235493 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -10,10 +10,6 @@ mergeInto(LibraryManager.library, { $Browser: { mainLoop: { scheduler: null, -#if PROFILE_MAIN_LOOP - meanTime: 0, - lastReport: 0, -#endif shouldPause: false, paused: false, queue: [], @@ -383,8 +379,14 @@ mergeInto(LibraryManager.library, { emscripten_set_main_loop: function(func, fps) { Module['noExitRuntime'] = true; +#if PROFILE_MAIN_LOOP + Module['totalTime'] = 0; + Module['iterations'] = 0; + Module['maxTime'] = 0; +#endif + var jsFunc = FUNCTION_TABLE[func]; - var wrapper = function() { + Browser.mainLoop.runner = function() { if (Browser.mainLoop.queue.length > 0) { var start = Date.now(); var blocker = Browser.mainLoop.queue.shift(); @@ -402,7 +404,7 @@ mergeInto(LibraryManager.library, { } console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + ' ms'); //, left: ' + Browser.mainLoop.remainingBlockers); Browser.mainLoop.updateStatus(); - setTimeout(wrapper, 0); + setTimeout(Browser.mainLoop.runner, 0); return; } if (Browser.mainLoop.shouldPause) { @@ -415,15 +417,14 @@ mergeInto(LibraryManager.library, { #if PROFILE_MAIN_LOOP var start = performance.now(); #endif + jsFunc(); + #if PROFILE_MAIN_LOOP - var now = performance.now(); - var time = now - start; - Browser.mainLoop.meanTime = (Browser.mainLoop.meanTime*9 + time)/10; - if (now - Browser.mainLoop.lastReport > 1000) { - console.log('main loop time: ' + Browser.mainLoop.meanTime); - Browser.mainLoop.lastReport = now; - } + var time = performance.now() - start; + Module['totalTime'] += time; + Module['iterations']++; + Module['maxTime'] = Math.max(Module['maxTime'], time); #endif if (Browser.mainLoop.shouldPause) { @@ -436,11 +437,11 @@ mergeInto(LibraryManager.library, { } if (fps && fps > 0) { Browser.mainLoop.scheduler = function() { - setTimeout(wrapper, 1000/fps); // doing this each time means that on exception, we stop + setTimeout(Browser.mainLoop.runner, 1000/fps); // doing this each time means that on exception, we stop } } else { Browser.mainLoop.scheduler = function() { - Browser.requestAnimationFrame(wrapper); + Browser.requestAnimationFrame(Browser.mainLoop.runner); } } Browser.mainLoop.scheduler(); diff --git a/src/library_sdl.js b/src/library_sdl.js index 48c18c8b..da1e88af 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -18,7 +18,9 @@ var LibrarySDL = { events: [], fonts: [null], + // The currently preloaded audio elements ready to be played audios: [null], + // The currently playing audio element. There's only one music track. music: { audio: null, volume: 1.0 @@ -346,9 +348,19 @@ var LibrarySDL = { receiveEvent: function(event) { switch(event.type) { case 'mousemove': - // workaround for firefox bug 750111 - event['movementX'] = event['mozMovementX']; - event['movementY'] = event['mozMovementY']; + if (Browser.pointerLock) { + // workaround for firefox bug 750111 + if ('mozMovementX' in event) { + event['movementX'] = event['mozMovementX']; + event['movementY'] = event['mozMovementY']; + } + // workaround for Firefox bug 782777 + if (event['movementX'] == 0 && event['movementY'] == 0) { + // ignore a mousemove event if it doesn't contain any movement info + // (without pointer lock, we infer movement from pageX/pageY, so this check is unnecessary) + return false; + } + } // fall through case 'keydown': case 'keyup': case 'mousedown': case 'mouseup': case 'DOMMouseScroll': case 'mousewheel': if (event.type == 'DOMMouseScroll' || event.type == 'mousewheel') { @@ -394,6 +406,11 @@ var LibrarySDL = { } } break; + case 'unload': + SDL.events.push(event); + // Force-run a main event loop, since otherwise this event will never be caught! + Browser.mainLoop.runner(); + return true; } return false; }, @@ -457,8 +474,14 @@ var LibrarySDL = { if (Browser.pointerLock) { // When the pointer is locked, calculate the coordinates // based on the movement of the mouse. - var movementX = Browser.getMovementX(event); - var movementY = Browser.getMovementY(event); + // Workaround for Firefox bug 764498 + if (event.type != 'mousemove' && + ('mozMovementX' in event)) { + var movementX = 0, movementY = 0; + } else { + var movementX = Browser.getMovementX(event); + var movementY = Browser.getMovementY(event); + } var x = SDL.mouseX + movementX; var y = SDL.mouseY + movementY; } else { @@ -488,6 +511,10 @@ var LibrarySDL = { SDL.mouseY = y; break; } + case 'unload': { + {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; + break; + } default: throw 'Unhandled SDL event: ' + event.type; } }, @@ -506,6 +533,10 @@ var LibrarySDL = { // Sound + // Channels are a SDL abstraction for allowing multiple sound tracks to be + // played at the same time. We don't need to actually implement the mixing + // since the browser engine handles that for us. Therefore, in JS we just + // maintain a list of channels and return IDs for them to the SDL consumer. allocateChannels: function(num) { // called from Mix_AllocateChannels and init if (SDL.numChannels && SDL.numChannels >= num) return; SDL.numChannels = num; @@ -557,6 +588,7 @@ var LibrarySDL = { document.onkeydown = SDL.receiveEvent; document.onkeyup = SDL.receiveEvent; document.onkeypress = SDL.receiveEvent; + window.onunload = SDL.receiveEvent; SDL.keyboardState = _malloc(0x10000); _memset(SDL.keyboardState, 0, 0x10000); // Initialize this structure carefully for closure @@ -565,6 +597,7 @@ var LibrarySDL = { SDL.DOMEventToSDLEvent['mousedown'] = 0x401 /* SDL_MOUSEBUTTONDOWN */; SDL.DOMEventToSDLEvent['mouseup'] = 0x402 /* SDL_MOUSEBUTTONUP */; SDL.DOMEventToSDLEvent['mousemove'] = 0x400 /* SDL_MOUSEMOTION */; + SDL.DOMEventToSDLEvent['unload'] = 0x100 /* SDL_QUIT */; return 0; // success }, @@ -640,8 +673,11 @@ var LibrarySDL = { }, SDL_Quit: function() { - for (var i = 0; i < SDL.audios; i++) { - SDL.audios[i].pause(); + for (var i = 0; i < SDL.numChannels; ++i) { + SDL.channels[i].audio.pause(); + } + if (SDL.music.audio) { + SDL.music.audio.pause(); } Module.print('SDL_Quit called (and ignored)'); }, @@ -1015,6 +1051,7 @@ var LibrarySDL = { // SDL_Audio + // TODO fix SDL_OpenAudio, and add some tests for it. It's currently broken. SDL_OpenAudio: function(desired, obtained) { SDL.allocateChannels(32); @@ -1065,6 +1102,7 @@ var LibrarySDL = { SDL.audio.paused = pauseOn; }, + SDL_CloseAudio__deps: ['SDL_PauseAudio', 'free'], SDL_CloseAudio: function() { if (SDL.audio) { _SDL_PauseAudio(1); @@ -1093,6 +1131,7 @@ var LibrarySDL = { Mix_OpenAudio: function(frequency, format, channels, chunksize) { SDL.allocateChannels(32); + // Just record the values for a later call to Mix_QuickLoad_RAW SDL.mixerFrequency = frequency; SDL.mixerFormat = format; SDL.mixerNumChannels = channels; @@ -1137,6 +1176,7 @@ var LibrarySDL = { Module["preloadedAudios"][filename] = null; } var id = SDL.audios.length; + // Keep the loaded audio in the audio arrays, ready for playback SDL.audios.push({ source: filename, audio: raw @@ -1146,12 +1186,15 @@ var LibrarySDL = { Mix_QuickLoad_RAW: function(mem, len) { var audio = new Audio(); - audio['mozSetup'](SDL.mixerNumChannels, SDL.mixerFrequency); - var numSamples = (len / (SDL.mixerNumChannels * 2)) | 0; + // Record the number of channels and frequency for later usage + audio.numChannels = SDL.mixerNumChannels; + audio.frequency = SDL.mixerFrequency; + var numSamples = len >> 1; // len is the length in bytes, and the array contains 16-bit PCM values var buffer = new Float32Array(numSamples); for (var i = 0; i < numSamples; ++i) { buffer[i] = ({{{ makeGetValue('mem', 'i*2', 'i16', 0, 0) }}}) / 0x8000; // hardcoded 16-bit audio, signed (TODO: reSign if not ta2?) } + // FIXME: doesn't make sense to keep the audio element in the buffer var id = SDL.audios.length; SDL.audios.push({ source: '', @@ -1167,10 +1210,15 @@ var LibrarySDL = { Mix_PlayChannel: function(channel, id, loops) { // TODO: handle loops + + // Get the audio element associated with the ID var info = SDL.audios[id]; if (!info) return 0; var audio = info.audio; if (!audio) return 0; + + // If the user asks us to allocate a channel automatically, get the first + // free one. if (channel == -1) { channel = 0; for (var i = 0; i < SDL.numChannels; i++) { @@ -1180,6 +1228,9 @@ var LibrarySDL = { } } } + + // We clone the audio node to utilize the preloaded audio buffer, since + // the browser has already preloaded the audio file. var channelInfo = SDL.channels[channel]; channelInfo.audio = audio = audio.cloneNode(true); if (SDL.channelFinished) { @@ -1187,9 +1238,55 @@ var LibrarySDL = { Runtime.getFuncWrapper(SDL.channelFinished)(channel); } } + // Either play the element, or load the dynamic data into it if (info.buffer) { - audio['mozSetup'](SDL.mixerNumChannels, SDL.mixerFrequency); - audio["mozWriteAudio"](info.buffer); + var contextCtor = null; + if (audio && ('mozSetup' in audio)) { // Audio Data API + try { + audio['mozSetup'](audio.numChannels, audio.frequency); + audio["mozWriteAudio"](info.buffer); + } catch (e) { + // Workaround for Firefox bug 783052 + // ignore this exception! + } + /* + } else if (contextCtor = (window.AudioContext || // WebAudio API + window.webkitAudioContext)) { + var currentIndex = 0; + var numChannels = parseInt(audio.numChannels); + var context = new contextCtor(); + var source = context.createBufferSource(); + source.loop = false; + source.buffer = context.createBuffer(numChannels, 1, audio.frequency); + var jsNode = context.createJavaScriptNode(2048, numChannels, numChannels); + jsNode.onaudioprocess = function(event) { + var buffers = new Array(numChannels); + for (var i = 0; i < numChannels; ++i) { + buffers[i] = event.outputBuffer.getChannelData(i); + } + var remaining = info.buffer.length - currentIndex; + if (remaining > 2048) { + remaining = 2048; + } + for (var i = 0; i < remaining;) { + for (var j = 0; j < numChannels; ++j) { + buffers[j][i] = info.buffer[currentIndex + i + j] * audio.volume; + } + i += j; + } + currentIndex += remaining * numChannels; + for (var i = remaining; i < 2048;) { + for (var j = 0; j < numChannels; ++j) { + buffers[j][i] = 0; // silence + } + i += j; + } + }; + source.connect(jsNode); + jsNode.connect(context.destination); + source.noteOn(0); + */ + } } else { audio.play(); } diff --git a/src/postamble.js b/src/postamble.js index e1dd495a..d164f049 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -32,14 +32,21 @@ Module.callMain = function callMain(args) { function run(args) { args = args || Module['arguments']; + if (runDependencies > 0) { + Module.printErr('run() called, but dependencies remain, so not running'); + return 0; + } + if (Module['preRun']) { if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; - while (Module['preRun'].length > 0) { - Module['preRun'].pop()(); - if (runDependencies > 0) { - // preRun added a dependency, run will be called later - return 0; - } + var toRun = Module['preRun']; + Module['preRun'] = []; + for (var i = toRun.length-1; i >= 0; i--) { + toRun[i](); + } + if (runDependencies > 0) { + // a preRun added a dependency, run will be called later + return 0; } } @@ -89,14 +96,15 @@ if (Module['preInit']) { initRuntime(); #if INVOKE_RUN +var shouldRunNow = true; #else -addRunDependency(); +var shouldRunNow = false; #endif if (Module['noInitialRun']) { - addRunDependency(); + shouldRunNow = false; } -if (runDependencies == 0) { +if (shouldRunNow) { var ret = run(); #if CATCH_EXIT_CODE Module.print('Exit Status: ' + ret); diff --git a/src/settings.js b/src/settings.js index cf329568..9f63622d 100644 --- a/src/settings.js +++ b/src/settings.js @@ -5,6 +5,7 @@ // // emcc -s OPTION1=VALUE1 -s OPTION2=VALUE2 [..other stuff..] // +// See https://github.com/kripken/emscripten/wiki/Code-Generation-Modes/ // Tuning var QUANTUM_SIZE = 4; // This is the size of an individual field in a structure. 1 would @@ -51,15 +52,10 @@ var FAST_MEMORY = 2*1024*1024; // The amount of memory to initialize to 0. This // Code embetterments var MICRO_OPTS = 1; // Various micro-optimizations, like nativizing variables var RELOOP = 0; // Recreate js native loops from llvm data -var USE_TYPED_ARRAYS = 2; // Use typed arrays for the heap +var USE_TYPED_ARRAYS = 2; // Use typed arrays for the heap. See https://github.com/kripken/emscripten/wiki/Code-Generation-Modes/ // 1 has two heaps, IHEAP (int32) and FHEAP (double), - // and addresses there are a match for normal addresses. This wastes memory but can be fast. - // 2 is a single heap, accessible through views as int8, int32, etc. This saves memory but - // has more overhead of pointer calculations. It also is limited to storing doubles as floats, - // simply because double stores are not necessarily 64-bit aligned, and we can only access - // 64-bit aligned values with a 64-bit typed array. Likewise int64s are stored as int32's, - // which is potentially very dangerous! - // TODO: require compiling with -malign-double, which does align doubles + // and addresses there are a match for normal addresses. + // 2 is a single heap, accessible through views as int8, int32, etc. var USE_FHEAP = 1; // Relevant in USE_TYPED_ARRAYS == 1. If this is disabled, only IHEAP will be used, and FHEAP // not generated at all. This is useful if your code is 100% ints without floats or doubles var DOUBLE_MODE = 1; // How to load and store 64-bit doubles. Without typed arrays or in typed array mode 1, diff --git a/system/include/sys/select.h b/system/include/sys/select.h index 47cef2e5..49bc034b 100644 --- a/system/include/sys/select.h +++ b/system/include/sys/select.h @@ -1,3 +1,6 @@ +#ifndef _SELECT_H +#define _SELECT_H int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); +#endif diff --git a/tests/runner.py b/tests/runner.py index c991a631..b81cee9a 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -5013,11 +5013,11 @@ def process(filename): #include <arpa/inet.h> int main() { - printf("*%x,%x,%x,%x*\n", htonl(0x12345678), htons(0xabcd), ntohl(0x43211234), ntohs(0xbeaf)); + printf("*%x,%x,%x,%x,%x,%x*\n", htonl(0xa1b2c3d4), htonl(0xfe3572e0), htonl(0x07abcdf0), htons(0xabcd), ntohl(0x43211234), ntohs(0xbeaf)); return 0; } ''' - self.do_run(src, '*78563412,cdab,34122143,afbe*') + self.do_run(src, '*d4c3b2a1,e07235fe,f0cdab07,cdab,34122143,afbe*') def test_ctype(self): # The bit fiddling done by the macros using __ctype_b_loc requires this. @@ -5219,7 +5219,85 @@ int main(int argc, char **argv) { return 1; } ''', 'hello world'); - + + def test_typeid(self): + self.do_run(r''' + #include <stdio.h> + #include <string.h> + #include <typeinfo> + int main() { + printf("*\n"); + #define MAX 100 + int ptrs[MAX]; + int groups[MAX]; + memset(ptrs, 0, MAX*sizeof(int)); + memset(groups, 0, MAX*sizeof(int)); + int next_group = 1; + #define TEST(X) { \ + int ptr = (int)&typeid(X); \ + int group = 0; \ + int i; \ + for (i = 0; i < MAX; i++) { \ + if (!groups[i]) break; \ + if (ptrs[i] == ptr) { \ + group = groups[i]; \ + break; \ + } \ + } \ + if (!group) { \ + groups[i] = group = next_group++; \ + ptrs[i] = ptr; \ + } \ + printf("%s:%d\n", #X, group); \ + } + TEST(int); + TEST(unsigned int); + TEST(unsigned); + TEST(signed int); + TEST(long); + TEST(unsigned long); + TEST(signed long); + TEST(long long); + TEST(unsigned long long); + TEST(signed long long); + TEST(short); + TEST(unsigned short); + TEST(signed short); + TEST(char); + TEST(unsigned char); + TEST(signed char); + TEST(float); + TEST(double); + TEST(long double); + TEST(void); + TEST(void*); + printf("*\n"); + } + ''', '''* +int:1 +unsigned int:2 +unsigned:2 +signed int:1 +long:3 +unsigned long:4 +signed long:3 +long long:5 +unsigned long long:6 +signed long long:5 +short:7 +unsigned short:8 +signed short:7 +char:9 +unsigned char:10 +signed char:11 +float:12 +double:13 +long double:14 +void:15 +void*:16 +* +'''); + def test_static_variable(self): if self.emcc_args is None: Settings.SAFE_HEAP = 0 # LLVM mixes i64 and i8 in the guard check src = ''' @@ -7442,6 +7520,9 @@ f.close() ['simplifyExpressionsPre', 'optimizeShiftsConservative']), (path_from_root('tools', 'test-js-optimizer-t2.js'), open(path_from_root('tools', 'test-js-optimizer-t2-output.js')).read(), ['simplifyExpressionsPre', 'optimizeShiftsAggressive']), + # Make sure that optimizeShifts handles functions with shift statements. + (path_from_root('tools', 'test-js-optimizer-t3.js'), open(path_from_root('tools', 'test-js-optimizer-t3.js')).read(), + ['optimizeShiftsAggressive']), (path_from_root('tools', 'test-js-optimizer-regs.js'), open(path_from_root('tools', 'test-js-optimizer-regs-output.js')).read(), ['registerize']), ]: @@ -7649,15 +7730,17 @@ elif 'browser' in str(sys.argv): print '(moving on..)' def with_report_result(self, code): - return code.replace('REPORT_RESULT();', ''' - char output[1000]; - sprintf(output, - "xhr = new XMLHttpRequest();" - "xhr.open('GET', 'http://localhost:8888/report_result?%d');" - "xhr.send();", result); - emscripten_run_script(output); + return ''' + #define REPORT_RESULT_INTERNAL(sync) \ + char output[1000]; \ + sprintf(output, \ + "xhr = new XMLHttpRequest();" \ + "xhr.open('GET', 'http://localhost:8888/report_result?%d'%s);" \ + "xhr.send();", result, sync ? ", false" : ""); \ + emscripten_run_script(output); \ emscripten_run_script("setTimeout(function() { window.close() }, 1000)"); -''') + #define REPORT_RESULT() REPORT_RESULT_INTERNAL(0) +''' + code def reftest(self, expected): basename = os.path.basename(expected) @@ -8157,6 +8240,9 @@ elif 'browser' in str(sys.argv): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) # preloaded *after* run self.btest('emscripten_fs_api_browser.cpp', '1') + def test_sdl_quit(self): + self.btest('sdl_quit.c', '1') + def test_gc(self): self.btest('browser_gc.cpp', '1') @@ -8798,6 +8884,7 @@ elif 'sanity' in str(sys.argv): def test_emcc_caching(self): INCLUDING_MESSAGE = 'emcc: including X' BUILDING_MESSAGE = 'emcc: building X for cache' + ERASING_MESSAGE = 'emcc: clearing cache' EMCC_CACHE = Cache.dirname @@ -8845,6 +8932,12 @@ elif 'sanity' in str(sys.argv): if emcc_debug: os.environ['EMCC_DEBUG'] = emcc_debug + # Manual cache clearing + assert os.path.exists(EMCC_CACHE) + output = self.do([EMCC, '--clear-cache']) + assert ERASING_MESSAGE in output + assert not os.path.exists(EMCC_CACHE) + else: raise Exception('Test runner is confused: ' + str(sys.argv)) diff --git a/tests/sdl_quit.c b/tests/sdl_quit.c new file mode 100644 index 00000000..1a07526f --- /dev/null +++ b/tests/sdl_quit.c @@ -0,0 +1,33 @@ +#include <stdio.h> +#include <SDL/SDL.h> +#include <SDL/SDL_ttf.h> +#include <assert.h> +#include <emscripten.h> + +int result = 0; + +void one() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_QUIT: { + if (!result) { // prevent infinite recursion since REPORT_RESULT does window.close too. + result = 1; + REPORT_RESULT_INTERNAL(1); + } + } + } + } +} + +void main_2(); + +int main() { + SDL_Init(SDL_INIT_VIDEO); + SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE); + + emscripten_set_main_loop(one, 0); + + emscripten_run_script("setTimeout(function() { window.close() }, 2000)"); +} + diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index d58c8c6c..e1cfbe65 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -485,13 +485,20 @@ function optimizeShiftsInternal(ast, conservative) |