diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler.js | 2 | ||||
-rw-r--r-- | src/jsifier.js | 80 | ||||
-rw-r--r-- | src/library.js | 17 | ||||
-rw-r--r-- | src/library_browser.js | 2 | ||||
-rw-r--r-- | src/parseTools.js | 17 | ||||
-rw-r--r-- | src/relooper/Relooper.cpp | 74 | ||||
-rw-r--r-- | src/relooper/Relooper.h | 2 | ||||
-rw-r--r-- | src/settings.js | 17 | ||||
-rw-r--r-- | src/shell.html | 2 |
9 files changed, 132 insertions, 81 deletions
diff --git a/src/compiler.js b/src/compiler.js index 94e77e26..365ff32f 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -176,6 +176,8 @@ DEAD_FUNCTIONS = numberedSet(DEAD_FUNCTIONS); RUNTIME_DEBUG = LIBRARY_DEBUG || GL_DEBUG; +if (SAFE_HEAP) USE_BSS = 0; // must initialize heap for safe heap + // Settings sanity checks assert(!(USE_TYPED_ARRAYS === 2 && QUANTUM_SIZE !== 4), 'For USE_TYPED_ARRAYS == 2, must have normal QUANTUM_SIZE of 4'); diff --git a/src/jsifier.js b/src/jsifier.js index b13d39a3..885fbc30 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 @@ -1568,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.js b/src/library.js index 01a67804..822f4319 100644 --- a/src/library.js +++ b/src/library.js @@ -7224,6 +7224,23 @@ LibraryManager.library = { return 1; }, + // netinet/in.h + + _in6addr_any: + 'allocate([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], "i8", ALLOC_STATIC)', + _in6addr_loopback: + 'allocate([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], "i8", ALLOC_STATIC)', + _in6addr_linklocal_allnodes: + 'allocate([255,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1], "i8", ALLOC_STATIC)', + _in6addr_linklocal_allrouters: + 'allocate([255,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2], "i8", ALLOC_STATIC)', + _in6addr_interfacelocal_allnodes: + 'allocate([255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], "i8", ALLOC_STATIC)', + _in6addr_interfacelocal_allrouters: + 'allocate([255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2], "i8", ALLOC_STATIC)', + _in6addr_sitelocal_allrouters: + 'allocate([255,5,0,0,0,0,0,0,0,0,0,0,0,0,0,2], "i8", ALLOC_STATIC)', + // ========================================================================== // netdb.h // ========================================================================== diff --git a/src/library_browser.js b/src/library_browser.js index d007d9a7..d9fd3ee5 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -805,7 +805,7 @@ mergeInto(LibraryManager.library, { var t = process['hrtime'](); return t[0] * 1e3 + t[1] / 1e6; } - else if (window['performance'] && window['performance']['now']) { + else if (ENVIRONMENT_IS_WEB && window['performance'] && window['performance']['now']) { return window['performance']['now'](); } else { return Date.now(); diff --git a/src/parseTools.js b/src/parseTools.js index 0b83a12b..6bc0b7ea 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -467,6 +467,18 @@ function isIndexableGlobal(ident) { return !data.alias && !data.external; } +function isBSS(item) { + if (!USE_BSS) { + return false; + } + + if (item.external) return false; // externals are typically implemented in a JS library, and must be accessed by name, explicitly + + // return true if a global is uninitialized or initialized to 0 + return (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 +502,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 39774690..dff52adf 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. @@ -1260,10 +1265,14 @@ var C_DEFINES = {'SI_MESGQ': '5', 'SIGTTOU': '22', '_CS_POSIX_V7_LP64_OFF64_LDFLAGS': '10', '_SC_TTY_NAME_MAX': '41', - 'AF_INET': '1', + 'AF_INET': '2', 'AF_INET6': '6', + 'PF_INET': '2', + 'PF_INET6': '6', 'FIONREAD': '1', 'SOCK_STREAM': '200', - 'IPPROTO_TCP': 1 + 'SOCK_DGRAM': '20', + 'IPPROTO_TCP': '1', + 'IPPROTO_UDP': '2' }; diff --git a/src/shell.html b/src/shell.html index 00765271..22bc9de9 100644 --- a/src/shell.html +++ b/src/shell.html @@ -86,7 +86,7 @@ } }; Module.setStatus('Downloading...'); - </script> + </script> <script type='text/javascript'>{{{ SCRIPT_CODE }}}</script> </body> </html> |