allow limited the amount of named globals
This commit is contained in:
Родитель
915d48e596
Коммит
a27c01ed25
|
@ -507,6 +507,9 @@ function intertyper(data, sidePass, baseLineNums) {
|
|||
private_: private_,
|
||||
lineNum: item.lineNum
|
||||
};
|
||||
if (NUM_NAMED_GLOBALS >= 0) {
|
||||
Variables.globals[ret.ident].type = ret.type;
|
||||
}
|
||||
Types.needAnalysis[ret.type] = 0;
|
||||
if (ident == '@llvm.global_ctors') {
|
||||
ret.ctors = [];
|
||||
|
|
|
@ -262,6 +262,20 @@ function JSify(data, functionsOnly, givenFunctions) {
|
|||
'\n]);\n';
|
||||
return ret;
|
||||
} else {
|
||||
var constant = null;
|
||||
var allocator = (BUILD_AS_SHARED_LIB && !item.external) ? 'ALLOC_NORMAL' : 'ALLOC_STATIC';
|
||||
var index = null;
|
||||
if (NUM_NAMED_GLOBALS >= 0) {
|
||||
if (Variables.seenGlobals < NUM_NAMED_GLOBALS) {
|
||||
Variables.seenGlobals++; // named
|
||||
} else {
|
||||
// indexed
|
||||
Variables.indexedGlobals[item.ident] = Variables.nextIndexedOffset;
|
||||
index = makeGlobalUse(item.ident);
|
||||
Variables.nextIndexedOffset += Runtime.alignMemory(calcAllocatedSize(Variables.globals[item.ident].type));
|
||||
allocator = 'ALLOC_NONE';
|
||||
}
|
||||
}
|
||||
if (item.external && BUILD_AS_SHARED_LIB) {
|
||||
// External variables in shared libraries should not be declared as
|
||||
// they would shadow similarly-named globals in the parent.
|
||||
|
@ -269,7 +283,7 @@ function JSify(data, functionsOnly, givenFunctions) {
|
|||
} else {
|
||||
item.JS = makeGlobalDef(item.ident);
|
||||
}
|
||||
var constant = null;
|
||||
|
||||
if (item.external) {
|
||||
// Import external global variables from the library if available.
|
||||
var shortident = item.ident.slice(1);
|
||||
|
@ -284,7 +298,7 @@ function JSify(data, functionsOnly, givenFunctions) {
|
|||
padding = makeEmptyStruct(item.type);
|
||||
}
|
||||
var padded = val.concat(padding.slice(val.length));
|
||||
var js = item.ident + '=' + makePointer(JSON.stringify(padded), null, 'ALLOC_STATIC', item.type) + ';'
|
||||
var js = item.ident + '=' + makePointer(JSON.stringify(padded), null, allocator, item.type, index) + ';'
|
||||
if (LibraryManager.library[shortident + '__postset']) {
|
||||
js += '\n' + LibraryManager.library[shortident + '__postset'];
|
||||
}
|
||||
|
@ -314,15 +328,14 @@ function JSify(data, functionsOnly, givenFunctions) {
|
|||
}
|
||||
// NOTE: This is the only place that could potentially create static
|
||||
// allocations in a shared library.
|
||||
constant = makePointer(constant, null, BUILD_AS_SHARED_LIB ? 'ALLOC_NORMAL' : 'ALLOC_STATIC', item.type);
|
||||
|
||||
constant = makePointer(constant, null, allocator, item.type, index);
|
||||
var js;
|
||||
|
||||
js = makeGlobalUse(item.ident) + '=' + constant + ';';
|
||||
js = (index !== null ? '' : item.ident + '=') + constant + ';';
|
||||
|
||||
// Special case: class vtables. We make sure they are null-terminated, to allow easy runtime operations
|
||||
if (item.ident.substr(0, 5) == '__ZTV') {
|
||||
js += '\n' + makePointer('[0]', null, BUILD_AS_SHARED_LIB ? 'ALLOC_NORMAL' : 'ALLOC_STATIC', ['void*']) + ';';
|
||||
js += '\n' + makePointer('[0]', null, allocator, ['void*'], index) + ';';
|
||||
}
|
||||
if (EXPORT_ALL || (item.ident in EXPORTED_GLOBALS)) {
|
||||
js += '\nModule["' + item.ident + '"] = ' + item.ident + ';';
|
||||
|
@ -1270,6 +1283,15 @@ function JSify(data, functionsOnly, givenFunctions) {
|
|||
//
|
||||
|
||||
if (!mainPass) {
|
||||
if (phase == 'pre' && !Variables.generatedGlobalBase) {
|
||||
Variables.generatedGlobalBase = true;
|
||||
if (Variables.nextIndexedOffset > 0) {
|
||||
// Variables have been calculated, print out the base generation before we print them
|
||||
print('var GLOBAL_BASE = STATICTOP;\n');
|
||||
print('STATICTOP += ' + Variables.nextIndexedOffset + ';\n');
|
||||
print('assert(STATICTOP < TOTAL_MEMORY);\n');
|
||||
}
|
||||
}
|
||||
var generated = itemsDict.function.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.GlobalVariable).concat(itemsDict.GlobalVariablePostSet);
|
||||
if (!DEBUG_MEMORY) print(generated.map(function(item) { return item.JS }).join('\n'));
|
||||
return;
|
||||
|
|
|
@ -174,7 +174,11 @@ var PreProcessor = {
|
|||
};
|
||||
|
||||
var Variables = {
|
||||
globals: {}
|
||||
globals: {},
|
||||
indexedGlobals: {}, // for indexed globals, ident ==> index
|
||||
// Used in calculation of indexed globals
|
||||
nextIndexedOffset: 0,
|
||||
seenGlobals: 0,
|
||||
};
|
||||
|
||||
var Types = {
|
||||
|
|
|
@ -357,10 +357,12 @@ function hasVarArgs(params) {
|
|||
}
|
||||
|
||||
function makeGlobalDef(ident) {
|
||||
if (ident in Variables.indexedGlobals) return '';
|
||||
return 'var ' + ident + ';'; // TODO: add option for namespacing or offsetting to allow reducing the number of globals
|
||||
}
|
||||
|
||||
function makeGlobalUse(ident) {
|
||||
if (ident in Variables.indexedGlobals) return getFastValue('GLOBAL_BASE', '+', Variables.indexedGlobals[ident]);
|
||||
return ident; // TODO: add option for namespacing or offsetting to allow reducing the number of globals
|
||||
}
|
||||
|
||||
|
@ -1267,7 +1269,7 @@ function makeGetPos(ptr) {
|
|||
|
||||
var IHEAP_FHEAP = set('IHEAP', 'IHEAPU', 'FHEAP');
|
||||
|
||||
function makePointer(slab, pos, allocator, type) {
|
||||
function makePointer(slab, pos, allocator, type, ptr) {
|
||||
assert(type, 'makePointer requires type info');
|
||||
if (slab.substr(0, 4) === 'HEAP' || (USE_TYPED_ARRAYS == 1 && slab in IHEAP_FHEAP)) return pos;
|
||||
var types = generateStructTypes(type);
|
||||
|
@ -1297,7 +1299,7 @@ function makePointer(slab, pos, allocator, type) {
|
|||
types = de[0];
|
||||
}
|
||||
}
|
||||
return 'allocate(' + slab + ', ' + JSON.stringify(types) + (allocator ? ', ' + allocator : '') + ')';
|
||||
return 'allocate(' + slab + ', ' + JSON.stringify(types) + (allocator ? ', ' + allocator : '') + (allocator == 'ALLOC_NONE' ? ', ' + ptr : '') + ')';
|
||||
}
|
||||
|
||||
function makeGetSlabs(ptr, type, allowMultiple, unsigned) {
|
||||
|
|
|
@ -472,9 +472,11 @@ Module['getValue'] = getValue;
|
|||
var ALLOC_NORMAL = 0; // Tries to use _malloc()
|
||||
var ALLOC_STACK = 1; // Lives for the duration of the current function call
|
||||
var ALLOC_STATIC = 2; // Cannot be freed
|
||||
var ALLOC_NONE = 3; // Do not allocate
|
||||
Module['ALLOC_NORMAL'] = ALLOC_NORMAL;
|
||||
Module['ALLOC_STACK'] = ALLOC_STACK;
|
||||
Module['ALLOC_STATIC'] = ALLOC_STATIC;
|
||||
Module['ALLOC_NONE'] = ALLOC_NONE;
|
||||
|
||||
// allocate(): This is for internal use. You can use it yourself as well, but the interface
|
||||
// is a little tricky (see docs right below). The reason is that it is optimized
|
||||
|
@ -489,7 +491,7 @@ Module['ALLOC_STATIC'] = ALLOC_STATIC;
|
|||
// is initial data - if @slab is a number, then this does not matter at all and is
|
||||
// ignored.
|
||||
// @allocator: How to allocate memory, see ALLOC_*
|
||||
function allocate(slab, types, allocator) {
|
||||
function allocate(slab, types, allocator, ptr) {
|
||||
var zeroinit, size;
|
||||
if (typeof slab === 'number') {
|
||||
zeroinit = true;
|
||||
|
@ -501,7 +503,12 @@ function allocate(slab, types, allocator) {
|
|||
|
||||
var singleType = typeof types === 'string' ? types : null;
|
||||
|
||||
var ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
|
||||
var ret;
|
||||
if (allocator == ALLOC_NONE) {
|
||||
ret = ptr;
|
||||
} else {
|
||||
ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
|
||||
}
|
||||
|
||||
if (zeroinit) {
|
||||
_memset(ret, 0, size);
|
||||
|
|
|
@ -194,6 +194,11 @@ var PGO = 0; // Profile-guided optimization.
|
|||
// All CORRECT_* options default to 1 with PGO builds.
|
||||
// See https://github.com/kripken/emscripten/wiki/Optimizing-Code for more info
|
||||
|
||||
var NUM_NAMED_GLOBALS = -1; // If >= 0, the number of globals we allow to be named. Other globals
|
||||
// are then referred to by a base plus an offset (called an indexed global),
|
||||
// saving global variables but adding runtime overhead. If -1, then we
|
||||
// allow all globals to be named.
|
||||
|
||||
var PROFILE = 0; // Enables runtime profiling. See test_profiling for a usage example.
|
||||
|
||||
var EXPORT_ALL = 0; // If true, we export all the symbols
|
||||
|
|
|
@ -1645,7 +1645,15 @@ c5,de,15,8a
|
|||
return 0;
|
||||
}
|
||||
'''
|
||||
self.do_run(src, '4:10,177,543,def\n4\nwowie\ntoo\n76\n5\n(null)\n/* a comment */\n// another\ntest\n', ['wowie', 'too', '74'])
|
||||
for named, expected in [(-1, 0), (0, 100), (1, 98), (5, 88), (1000, 0)]:
|
||||
print named
|
||||
Settings.NUM_NAMED_GLOBALS = named
|
||||
self.do_run(src, '4:10,177,543,def\n4\nwowie\ntoo\n76\n5\n(null)\n/* a comment */\n// another\ntest\n', ['wowie', 'too', '74'])
|
||||
if self.emcc_args == []:
|
||||
gen = open(self.in_dir('src.cpp.o.js')).read()
|
||||
count = gen.count('GLOBAL_BASE')
|
||||
assert count == expected
|
||||
print ' counted'
|
||||
|
||||
def test_strcmp_uni(self):
|
||||
src = '''
|
||||
|
|
Загрузка…
Ссылка в новой задаче