diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/jsifier.js | 84 | ||||
-rw-r--r-- | src/library_browser.js | 31 | ||||
-rw-r--r-- | src/library_glut.js | 37 | ||||
-rw-r--r-- | src/parseTools.js | 16 | ||||
-rw-r--r-- | src/relooper/Relooper.cpp | 74 | ||||
-rw-r--r-- | src/relooper/Relooper.h | 2 | ||||
-rw-r--r-- | src/settings.js | 9 | ||||
-rw-r--r-- | src/shell.html | 6 |
8 files changed, 154 insertions, 105 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index ac6c259b..14c9cfbe 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -285,42 +285,60 @@ function JSify(data, functionsOnly, givenFunctions) { index = makeGlobalUse(item.ident); // index !== null indicates we are indexing this allocator = 'ALLOC_NONE'; } - if (item.external) { - if (Runtime.isNumberType(item.type) || isPointerType(item.type)) { - constant = zeros(Runtime.getNativeFieldSize(item.type)); - } else { - constant = makeEmptyStruct(item.type); + + if (isBSS(item)) { + var length = calcAllocatedSize(item.type); + length = Runtime.alignMemory(length); + + // If using indexed globals, go ahead and early out (no need to explicitly + // initialize). + if (!NAMED_GLOBALS) { + return ret; + } + // If using named globals, we can at least shorten the call to allocate by + // passing an integer representing the size of memory to alloc instead of + // an array of 0s of size length. + else { + constant = length; } } else { - constant = parseConst(item.value, item.type, item.ident); - } - assert(typeof constant === 'object');//, [typeof constant, JSON.stringify(constant), item.external]); - - // This is a flattened object. We need to find its idents, so they can be assigned to later - constant.forEach(function(value, i) { - if (needsPostSet(value)) { // ident, or expression containing an ident - ret.push({ - intertype: 'GlobalVariablePostSet', - JS: makeSetValue(makeGlobalUse(item.ident), i, value, 'i32', false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors - }); - constant[i] = '0'; + if (item.external) { + if (Runtime.isNumberType(item.type) || isPointerType(item.type)) { + constant = zeros(Runtime.getNativeFieldSize(item.type)); + } else { + constant = makeEmptyStruct(item.type); + } + } else { + constant = parseConst(item.value, item.type, item.ident); } - }); + assert(typeof constant === 'object');//, [typeof constant, JSON.stringify(constant), item.external]); + + // This is a flattened object. We need to find its idents, so they can be assigned to later + constant.forEach(function(value, i) { + if (needsPostSet(value)) { // ident, or expression containing an ident + ret.push({ + intertype: 'GlobalVariablePostSet', + JS: makeSetValue(makeGlobalUse(item.ident), i, value, 'i32', false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors + }); + constant[i] = '0'; + } + }); - if (item.external) { - // External variables in shared libraries should not be declared as - // they would shadow similarly-named globals in the parent, so do nothing here. - if (BUILD_AS_SHARED_LIB) return ret; - // Library items need us to emit something, but everything else requires nothing. - if (!LibraryManager.library[item.ident.slice(1)]) return ret; - } + if (item.external) { + // External variables in shared libraries should not be declared as + // they would shadow similarly-named globals in the parent, so do nothing here. + if (BUILD_AS_SHARED_LIB) return ret; + // Library items need us to emit something, but everything else requires nothing. + if (!LibraryManager.library[item.ident.slice(1)]) return ret; + } - // ensure alignment - constant = constant.concat(zeros(Runtime.alignMemory(constant.length) - constant.length)); + // ensure alignment + constant = constant.concat(zeros(Runtime.alignMemory(constant.length) - constant.length)); - // Special case: class vtables. We make sure they are null-terminated, to allow easy runtime operations - if (item.ident.substr(0, 5) == '__ZTV') { - constant = constant.concat(zeros(Runtime.alignMemory(QUANTUM_SIZE))); + // Special case: class vtables. We make sure they are null-terminated, to allow easy runtime operations + if (item.ident.substr(0, 5) == '__ZTV') { + constant = constant.concat(zeros(Runtime.alignMemory(QUANTUM_SIZE))); + } } // NOTE: This is the only place that could potentially create static @@ -695,7 +713,9 @@ function JSify(data, functionsOnly, givenFunctions) { } } i++; - return JS + (Debugging.on ? Debugging.getComment(line.lineNum) : ''); + // invoke instructions span two lines, and the debug info is located + // on the second line, hence the +1 + return JS + (Debugging.on ? Debugging.getComment(line.lineNum + (line.intertype === 'invoke' ? 1 : 0)) : ''); }) .join('\n') .split('\n') // some lines include line breaks @@ -1566,7 +1586,7 @@ function JSify(data, functionsOnly, givenFunctions) { print('STATICTOP = STATIC_BASE + ' + Runtime.alignMemory(Variables.nextIndexedOffset) + ';\n'); } var generated = itemsDict.function.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.GlobalVariable); - print(generated.map(function(item) { return item.JS }).join('\n')); + print(generated.map(function(item) { return item.JS; }).join('\n')); if (phase == 'pre') { if (memoryInitialization.length > 0) { diff --git a/src/library_browser.js b/src/library_browser.js index 925b64e2..d007d9a7 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -426,8 +426,17 @@ mergeInto(LibraryManager.library, { Browser.mouseMovementX = Browser.getMovementX(event); Browser.mouseMovementY = Browser.getMovementY(event); } - Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; - Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + + // check if SDL is available + if (typeof SDL != "undefined") { + Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; + Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + } else { + // just add the mouse delta to the current absolut mouse position + // FIXME: ideally this should be clamped against the canvas size and zero + Browser.mouseX += Browser.mouseMovementX; + Browser.mouseY += Browser.mouseMovementY; + } } else { // Otherwise, calculate the movement based on the changes // in the coordinates. @@ -504,9 +513,12 @@ mergeInto(LibraryManager.library, { this.windowedHeight = canvas.height; canvas.width = screen.width; canvas.height = screen.height; - var flags = {{{ makeGetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'i32', 0, 1) }}}; - flags = flags | 0x00800000; // set SDL_FULLSCREEN flag - {{{ makeSetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'flags', 'i32') }}} + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = {{{ makeGetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'i32', 0, 1) }}}; + flags = flags | 0x00800000; // set SDL_FULLSCREEN flag + {{{ makeSetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'flags', 'i32') }}} + } Browser.updateResizeListeners(); }, @@ -514,9 +526,12 @@ mergeInto(LibraryManager.library, { var canvas = Module['canvas']; canvas.width = this.windowedWidth; canvas.height = this.windowedHeight; - var flags = {{{ makeGetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'i32', 0, 1) }}}; - flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag - {{{ makeSetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'flags', 'i32') }}} + // check if SDL is available + if (typeof SDL != "undefined") { + var flags = {{{ makeGetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'i32', 0, 1) }}}; + flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag + {{{ makeSetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'flags', 'i32') }}} + } Browser.updateResizeListeners(); } diff --git a/src/library_glut.js b/src/library_glut.js index 38cfe55b..36d47787 100644 --- a/src/library_glut.js +++ b/src/library_glut.js @@ -117,9 +117,9 @@ var LibraryGLUT = { if (48 <= keycode && keycode <= 57) return keycode; // numeric TODO handle shift? if (65 <= keycode && keycode <= 90) - return event['shiftKey'] ? keycode : keycode + 32; + return event['shiftKey'] ? keycode : keycode + 32; if (106 <= keycode && keycode <= 111) - return keycode - 106 + 42; // *,+-./ TODO handle shift? + return keycode - 106 + 42; // *,+-./ TODO handle shift? switch (keycode) { case 27: // escape @@ -227,7 +227,7 @@ var LibraryGLUT = { } else { width = GLUT.windowWidth; height = GLUT.windowHeight; - // TODO set position + // TODO set position document.removeEventListener('fullscreenchange', GLUT.onFullScreenEventChange, true); document.removeEventListener('mozfullscreenchange', GLUT.onFullScreenEventChange, true); document.removeEventListener('webkitfullscreenchange', GLUT.onFullScreenEventChange, true); @@ -255,13 +255,14 @@ var LibraryGLUT = { document['cancelFullScreen'] || document['mozCancelFullScreen'] || document['webkitCancelFullScreen'] || - (function() {}); + (function() {}); CFS.apply(document, []); } }, glutGetModifiers: function() { return GLUT.modifiers; }, + glutInit__deps: ['$Browser'], glutInit: function(argcp, argv) { // Ignore arguments GLUT.initTime = Date.now(); @@ -271,6 +272,12 @@ var LibraryGLUT = { window.addEventListener("mousemove", GLUT.onMousemove, true); window.addEventListener("mousedown", GLUT.onMouseButtonDown, true); window.addEventListener("mouseup", GLUT.onMouseButtonUp, true); + + Browser.resizeListeners.push(function(width, height) { + if (GLUT.reshapeFunc) { + Runtime.dynCall('vii', GLUT.reshapeFunc, [width, height]); + } + }); __ATEXIT__.push({ func: function() { window.removeEventListener("keydown", GLUT.onKeydown, true); @@ -294,21 +301,25 @@ var LibraryGLUT = { glutGet: function(type) { switch (type) { case 100: /* GLUT_WINDOW_X */ - return 0; /* TODO */ + return 0; /* TODO */ case 101: /* GLUT_WINDOW_Y */ - return 0; /* TODO */ + return 0; /* TODO */ case 102: /* GLUT_WINDOW_WIDTH */ - return Module['canvas'].width; + return Module['canvas'].width; case 103: /* GLUT_WINDOW_HEIGHT */ - return Module['canvas'].height; + return Module['canvas'].height; + case 200: /* GLUT_SCREEN_WIDTH */ + return Module['canvas'].width; + case 201: /* GLUT_SCREEN_HEIGHT */ + return Module['canvas'].height; case 500: /* GLUT_INIT_WINDOW_X */ - return 0; /* TODO */ + return 0; /* TODO */ case 501: /* GLUT_INIT_WINDOW_Y */ - return 0; /* TODO */ + return 0; /* TODO */ case 502: /* GLUT_INIT_WINDOW_WIDTH */ - return GLUT.initWindowWidth; + return GLUT.initWindowWidth; case 503: /* GLUT_INIT_WINDOW_HEIGHT */ - return GLUT.initWindowHeight; + return GLUT.initWindowHeight; case 700: /* GLUT_ELAPSED_TIME */ var now = Date.now(); return now - GLUT.initTime; @@ -386,10 +397,8 @@ var LibraryGLUT = { glutReshapeWindow__deps: ['$GLUT', 'glutPostRedisplay'], glutReshapeWindow: function(width, height) { GLUT.cancelFullScreen(); - // console.log("glutReshapeWindow: " + width + ", " + height); Browser.setCanvasSize(width, height); if (GLUT.reshapeFunc) { - // console.log("GLUT.reshapeFunc: " + width + ", " + height); Runtime.dynCall('vii', GLUT.reshapeFunc, [width, height]); } _glutPostRedisplay(); diff --git a/src/parseTools.js b/src/parseTools.js index 0b83a12b..babb2692 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -467,6 +467,17 @@ function isIndexableGlobal(ident) { return !data.alias && !data.external; } +function isBSS(item) { + if (!USE_BSS) { + return false; + } + + // return true if a global is uninitialized or initialized to 0 + return item.external || + (item.value && item.value.intertype === 'emptystruct') || + (item.value && item.value.value !== undefined && item.value.value === '0'); +} + function makeGlobalDef(ident) { if (!NAMED_GLOBALS && isIndexableGlobal(ident)) return ''; return 'var ' + ident + ';'; @@ -490,7 +501,10 @@ function sortGlobals(globals) { ks.sort(); var inv = invertArray(ks); return values(globals).sort(function(a, b) { - return inv[b.ident] - inv[a.ident]; + // sort globals based on if they need to be explicitly initialized or not (moving + // values that don't need to be to the end of the array). if equal, sort by name. + return (Number(isBSS(a)) - Number(isBSS(b))) || + (inv[b.ident] - inv[a.ident]); }); } diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp index aa7e71a1..ca9c6ab1 100644 --- a/src/relooper/Relooper.cpp +++ b/src/relooper/Relooper.cpp @@ -10,6 +10,10 @@ // TODO: move all set to unorderedset +template <class T, class U> bool contains(const T& container, const U& contained) { + return container.find(contained) != container.end(); +} + #if DEBUG static void PrintDebug(const char *Format, ...); #define DebugDump(x, ...) Debugging::Dump(x, __VA_ARGS__) @@ -100,7 +104,7 @@ void Branch::Render(Block *Target, bool SetLabel) { int Block::IdCounter = 1; // 0 is reserved for clearings -Block::Block(const char *CodeInit) : Parent(NULL), Id(Block::IdCounter++), DefaultTarget(NULL), IsCheckedMultipleEntry(false) { +Block::Block(const char *CodeInit) : Parent(NULL), Id(Block::IdCounter++), IsCheckedMultipleEntry(false) { Code = strdup(CodeInit); } @@ -113,7 +117,7 @@ Block::~Block() { } void Block::AddBranchTo(Block *Target, const char *Condition, const char *Code) { - assert(BranchesOut.find(Target) == BranchesOut.end()); // cannot add more than one branch to the same target + assert(!contains(BranchesOut, Target)); // cannot add more than one branch to the same target BranchesOut[Target] = new Branch(Condition, Code); } @@ -174,6 +178,8 @@ void Block::Render(bool InLoop) { } } + Block *DefaultTarget(NULL); // The block we branch to without checking the condition, if none of the other conditions held. + // We must do this here, because blocks can be split and even comparing their Ids is not enough. We must check the conditions. for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin(); iter != ProcessedBranchesOut.end(); iter++) { if (!iter->second->Condition) { @@ -181,7 +187,7 @@ void Block::Render(bool InLoop) { DefaultTarget = iter->first; } } - assert(DefaultTarget); // Must be a default + assert(DefaultTarget); // Since each block *must* branch somewhere, this must be set ministring RemainingConditions; bool First = true; @@ -198,7 +204,7 @@ void Block::Render(bool InLoop) { Details = ProcessedBranchesOut[DefaultTarget]; } bool SetCurrLabel = SetLabel && Target->IsCheckedMultipleEntry; - bool HasFusedContent = Fused && Fused->InnerMap.find(Target) != Fused->InnerMap.end(); + bool HasFusedContent = Fused && contains(Fused->InnerMap, Target); bool HasContent = SetCurrLabel || Details->Type != Branch::Direct || HasFusedContent || Details->Code; if (iter != ProcessedBranchesOut.end()) { // If there is nothing to show in this branch, omit the condition @@ -356,7 +362,7 @@ void Relooper::Calculate(Block *Entry) { while (ToInvestigate.size() > 0) { Block *Curr = ToInvestigate.front(); ToInvestigate.pop_front(); - if (Live.find(Curr) != Live.end()) continue; + if (contains(Live, Curr)) continue; Live.insert(Curr); for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { ToInvestigate.push_back(iter->first); @@ -380,7 +386,7 @@ void Relooper::Calculate(Block *Entry) { for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) { Block *Original = *iter; if (Original->BranchesIn.size() <= 1 || Original->BranchesOut.size() > 0) continue; // only dead ends, for now - if (Original->BranchesOut.find(Original) != Original->BranchesOut.end()) continue; // cannot split a looping node + if (contains(Original->BranchesOut, Original)) continue; // cannot split a looping node if (strlen(Original->Code)*(Original->BranchesIn.size()-1) > TotalCodeSize/5) continue; // if splitting increases raw code size by a significant amount, abort // Split the node (for simplicity, we replace all the blocks, even though we could have reused the original) PrintDebug("Splitting block %d\n", Original->Id); @@ -423,7 +429,7 @@ void Relooper::Calculate(Block *Entry) { // Add incoming branches from live blocks, ignoring dead code for (int i = 0; i < Blocks.size(); i++) { Block *Curr = Blocks[i]; - if (Pre.Live.find(Curr) == Pre.Live.end()) continue; + if (!contains(Pre.Live, Curr)) continue; for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { iter->first->BranchesIn.insert(Curr); } @@ -445,7 +451,7 @@ void Relooper::Calculate(Block *Entry) { // will appear void GetBlocksOut(Block *Source, BlockSet& Entries, BlockSet *LimitTo=NULL) { for (BlockBranchMap::iterator iter = Source->BranchesOut.begin(); iter != Source->BranchesOut.end(); iter++) { - if (!LimitTo || LimitTo->find(iter->first) != LimitTo->end()) { + if (!LimitTo || contains(*LimitTo, iter->first)) { Entries.insert(iter->first); } } @@ -457,7 +463,7 @@ void Relooper::Calculate(Block *Entry) { DebugDump(From, " relevant to solipsize: "); for (BlockSet::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) { Block *Prior = *iter; - if (From.find(Prior) == From.end()) { + if (!contains(From, Prior)) { iter++; continue; } @@ -502,7 +508,7 @@ void Relooper::Calculate(Block *Entry) { while (Queue.size() > 0) { Block *Curr = *(Queue.begin()); Queue.erase(Queue.begin()); - if (InnerBlocks.find(Curr) == InnerBlocks.end()) { + if (!contains(InnerBlocks, Curr)) { // This element is new, mark it as inner and remove from outer InnerBlocks.insert(Curr); Blocks.erase(Curr); @@ -518,7 +524,7 @@ void Relooper::Calculate(Block *Entry) { Block *Curr = *iter; for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { Block *Possible = iter->first; - if (InnerBlocks.find(Possible) == InnerBlocks.end()) { + if (!contains(InnerBlocks, Possible)) { NextEntries.insert(Possible); } } @@ -615,7 +621,7 @@ void Relooper::Calculate(Block *Entry) { Block *Invalidatee = ToInvalidate.front(); ToInvalidate.pop_front(); Block *Owner = Ownership[Invalidatee]; - if (IndependentGroups.find(Owner) != IndependentGroups.end()) { // Owner may have been invalidated, do not add to IndependentGroups! + if (contains(IndependentGroups, Owner)) { // Owner may have been invalidated, do not add to IndependentGroups! IndependentGroups[Owner].erase(Invalidatee); } if (Ownership[Invalidatee]) { // may have been seen before and invalidated already @@ -688,7 +694,7 @@ void Relooper::Calculate(Block *Entry) { Block *Child = *iter; for (BlockSet::iterator iter = Child->BranchesIn.begin(); iter != Child->BranchesIn.end(); iter++) { Block *Parent = *iter; - if (Ignore && Ignore->find(Parent) != Ignore->end()) continue; + if (Ignore && contains(*Ignore, Parent)) continue; if (Helper.Ownership[Parent] != Helper.Ownership[Child]) { ToInvalidate.push_back(Child); } @@ -739,7 +745,7 @@ void Relooper::Calculate(Block *Entry) { Block *CurrTarget = iter->first; BlockBranchMap::iterator Next = iter; Next++; - if (CurrBlocks.find(CurrTarget) == CurrBlocks.end()) { + if (!contains(CurrBlocks, CurrTarget)) { NextEntries.insert(CurrTarget); Solipsize(CurrTarget, Branch::Break, Multiple, CurrBlocks); } @@ -756,7 +762,7 @@ void Relooper::Calculate(Block *Entry) { // Add entries not handled as next entries, they are deferred for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { Block *Entry = *iter; - if (IndependentGroups.find(Entry) == IndependentGroups.end()) { + if (!contains(IndependentGroups, Entry)) { NextEntries.insert(Entry); } } @@ -820,7 +826,7 @@ void Relooper::Calculate(Block *Entry) { BlockBlockSetMap::iterator curr = iter++; // iterate carefully, we may delete for (BlockSet::iterator iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) { Block *Origin = *iterBranch; - if (Group.find(Origin) == Group.end()) { + if (!contains(Group, Origin)) { // Reached from outside the group, so we cannot handle this PrintDebug("Cannot handle group with entry %d because of incoming branch from %d\n", Entry->Id, Origin->Id); IndependentGroups.erase(curr); @@ -858,7 +864,7 @@ void Relooper::Calculate(Block *Entry) { Block *Curr = *iter; for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { Block *Target = iter->first; - if (SmallGroup.find(Target) == SmallGroup.end()) { + if (!contains(SmallGroup, Target)) { DeadEnd = false; break; } @@ -909,13 +915,13 @@ void Relooper::Calculate(Block *Entry) { PostOptimizer(Relooper *ParentInit) : Parent(ParentInit), Closure(NULL) {} - #define RECURSE_MULTIPLE_MANUAL(func, manual) \ - for (BlockShapeMap::iterator iter = manual->InnerMap.begin(); iter != manual->InnerMap.end(); iter++) { \ + #define RECURSE_Multiple(shape, func) \ + for (BlockShapeMap::iterator iter = shape->InnerMap.begin(); iter != shape->InnerMap.end(); iter++) { \ func(iter->second); \ } - #define RECURSE_MULTIPLE(func) RECURSE_MULTIPLE_MANUAL(func, Multiple); - #define RECURSE_LOOP(func) \ - func(Loop->Inner); + #define RECURSE_Loop(shape, func) \ + func(shape->Inner); + #define RECURSE(shape, func) RECURSE_##shape(shape, func); #define SHAPE_SWITCH(var, simple, multiple, loop) \ if (SimpleShape *Simple = Shape::IsSimple(var)) { \ @@ -926,20 +932,6 @@ void Relooper::Calculate(Block *Entry) { loop; \ } - #define SHAPE_SWITCH_AUTO(var, simple, multiple, loop, func) \ - if (SimpleShape *Simple = Shape::IsSimple(var)) { \ - simple; \ - func(Simple->Next); \ - } else if (MultipleShape *Multiple = Shape::IsMultiple(var)) { \ - multiple; \ - RECURSE_MULTIPLE(func) \ - func(Multiple->Next); \ - } else if (LoopShape *Loop = Shape::IsLoop(var)) { \ - loop; \ - RECURSE_LOOP(func); \ - func(Loop->Next); \ - } - // Find the blocks that natural control flow can get us directly to, or through a multiple that we ignore void FollowNaturalFlow(Shape *S, BlockSet &Out) { SHAPE_SWITCH(S, { @@ -992,7 +984,7 @@ void Relooper::Calculate(Block *Entry) { for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) { Block *Target = iter->first; Branch *Details = iter->second; - if (Details->Type != Branch::Direct && NaturalBlocks.find(Target) != NaturalBlocks.end()) { // note: cannot handle split blocks + if (Details->Type != Branch::Direct && contains(NaturalBlocks, Target)) { // note: cannot handle split blocks Details->Type = Branch::Direct; if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) { Multiple->NeedLoop--; @@ -1036,7 +1028,7 @@ void Relooper::Calculate(Block *Entry) { // If we are fusing a Multiple with a loop into this Simple, then visit it now if (Fused && Fused->NeedLoop) { LoopStack.push(Fused); - RECURSE_MULTIPLE_MANUAL(FindLabeledLoops, Fused); + RECURSE_Multiple(Fused, FindLabeledLoops); } for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) { Block *Target = iter->first; @@ -1062,14 +1054,14 @@ void Relooper::Calculate(Block *Entry) { if (Multiple->NeedLoop) { LoopStack.push(Multiple); } - RECURSE_MULTIPLE(FindLabeledLoops); + RECURSE(Multiple, FindLabeledLoops); if (Multiple->NeedLoop) { LoopStack.pop(); } Next = Root->Next; }, { LoopStack.push(Loop); - RECURSE_LOOP(FindLabeledLoops); + RECURSE(Loop, FindLabeledLoops); LoopStack.pop(); Next = Root->Next; }); @@ -1123,7 +1115,7 @@ void Debugging::Dump(BlockSet &Blocks, const char *prefix) { for (BlockBranchMap::iterator iter2 = Curr->BranchesOut.begin(); iter2 != Curr->BranchesOut.end(); iter2++) { Block *Other = iter2->first; printf(" -> %d\n", Other->Id); - assert(Other->BranchesIn.find(Curr) != Other->BranchesIn.end()); + assert(contains(Other->BranchesIn, Curr)); } } } diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h index fe56a133..e54b578c 100644 --- a/src/relooper/Relooper.h +++ b/src/relooper/Relooper.h @@ -59,8 +59,6 @@ struct Block { Shape *Parent; // The shape we are directly inside int Id; // A unique identifier const char *Code; // The string representation of the code in this block. Owning pointer (we copy the input) - Block *DefaultTarget; // The block we branch to without checking the condition, if none of the other conditions held. - // Since each block *must* branch somewhere, this must be set bool IsCheckedMultipleEntry; // If true, we are a multiple entry, so reaching us requires setting the label variable Block(const char *CodeInit); diff --git a/src/settings.js b/src/settings.js index 3a91b488..4b6f033b 100644 --- a/src/settings.js +++ b/src/settings.js @@ -67,9 +67,9 @@ var RELOOP = 0; // Recreate js native loops from llvm data var RELOOPER = 'relooper.js'; // Loads the relooper from this path relative to compiler.js var USE_TYPED_ARRAYS = 2; // Use typed arrays for the heap. See https://github.com/kripken/emscripten/wiki/Code-Generation-Modes/ - // 0 means no typed arrays are used. + // 0 means no typed arrays are used. This mode disallows LLVM optimizations // 1 has two heaps, IHEAP (int32) and FHEAP (double), - // and addresses there are a match for normal addresses. This is deprecated. + // and addresses there are a match for normal addresses. This mode disallows LLVM optimizations. // 2 is a single heap, accessible through views as int8, int32, etc. This is // the recommended mode both for performance and for compatibility. var USE_FHEAP = 1; // Relevant in USE_TYPED_ARRAYS == 1. If this is disabled, only IHEAP will be used, and FHEAP @@ -236,6 +236,11 @@ var FS_LOG = 0; // Log all FS operations. This is especially helpful when you'r // a new project and want to see a list of file system operations happening // so that you can create a virtual file system with all of the required files. +var USE_BSS = 1; // https://en.wikipedia.org/wiki/.bss + // When enabled, 0-initialized globals are sorted to the end of the globals list, + // enabling us to not explicitly store the initialization value for each 0 byte. + // This significantly lowers the memory initialization array size. + var NAMED_GLOBALS = 0; // If 1, we use global variables for globals. Otherwise // they are referred to by a base plus an offset (called an indexed global), // saving global variables but adding runtime overhead. diff --git a/src/shell.html b/src/shell.html index f7eb9e1f..00765271 100644 --- a/src/shell.html +++ b/src/shell.html @@ -87,10 +87,6 @@ }; Module.setStatus('Downloading...'); </script> - <script type='text/javascript'> - - {{{ SCRIPT_CODE }}} - - </script> + <script type='text/javascript'>{{{ SCRIPT_CODE }}}</script> </body> </html> |