diff options
-rw-r--r-- | src/jsifier.js | 79 | ||||
-rw-r--r-- | src/parseTools.js | 16 | ||||
-rw-r--r-- | src/settings.js | 5 |
3 files changed, 68 insertions, 32 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index d6cd188c..73cc7740 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -285,42 +285,59 @@ 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 not using indexed globals, go ahead and early out (it doesn't need to + // be explicitly allocated). + if (!NAMED_GLOBALS) { + return ret; + } + // If using named globals, shorten the call to allocate() by just passing an + // integer representing the length of the chunk of memory we need to alloc. + 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 +1585,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/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/settings.js b/src/settings.js index 3e530c52..4b6f033b 100644 --- a/src/settings.js +++ b/src/settings.js @@ -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. |