aboutsummaryrefslogtreecommitdiff
path: root/src/modules.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules.js')
-rw-r--r--src/modules.js43
1 files changed, 32 insertions, 11 deletions
diff --git a/src/modules.js b/src/modules.js
index 6b3c5ffb..e4093078 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -229,6 +229,8 @@ var Types = {
preciseI64MathUsed: (PRECISE_I64_MATH == 2)
};
+var firstTableIndex = (ASM_JS ? 2*RESERVED_FUNCTION_POINTERS : 0) + 2;
+
var Functions = {
// All functions that will be implemented in this file. Maps id to signature
implementedFunctions: {},
@@ -236,7 +238,9 @@ var Functions = {
unimplementedFunctions: {}, // library etc. functions that we need to index, maps id to signature
indexedFunctions: {},
- nextIndex: (ASM_JS ? 2*RESERVED_FUNCTION_POINTERS : 0) + 2, // Start at a non-0 (even, see below) value
+ nextIndex: firstTableIndex, // Start at a non-0 (even, see below) value
+ neededTables: set('v', 'vi', 'ii', 'iii'), // signatures that appeared (initialized with library stuff
+ // we always use), and we will need a function table for
blockAddresses: {}, // maps functions to a map of block labels to label ids
@@ -261,6 +265,7 @@ var Functions = {
if (!doNotCreate) this.indexedFunctions[ident] = 0; // tell python we need this indexized
return "'{{ FI_" + toNiceIdent(ident) + " }}'"; // something python will replace later
} else {
+ if (!singlePhase) return 'NO_INDEX'; // Should not index functions in post
var ret = this.indexedFunctions[ident];
if (!ret) {
if (doNotCreate) return '0';
@@ -278,25 +283,25 @@ var Functions = {
// Generate code for function indexing
generateIndexing: function() {
- var total = this.nextIndex;
- if (ASM_JS) total = ceilPowerOfTwo(total); // must be power of 2 for mask
- function emptyTable(sig) {
- return zeros(total);
- }
var tables = { pre: '' };
if (ASM_JS) {
- ['v', 'vi', 'ii', 'iii'].forEach(function(sig) { // add some default signatures that are used in the library
- tables[sig] = emptyTable(sig); // TODO: make them compact
+ keys(Functions.neededTables).forEach(function(sig) { // add some default signatures that are used in the library
+ tables[sig] = zeros(firstTableIndex);
});
}
for (var ident in this.indexedFunctions) {
var sig = ASM_JS ? Functions.implementedFunctions[ident] || Functions.unimplementedFunctions[ident] || LibraryManager.library[ident.substr(1) + '__sig'] : 'x';
assert(sig, ident);
- if (!tables[sig]) tables[sig] = emptyTable(sig); // TODO: make them compact
- tables[sig][this.indexedFunctions[ident]] = ident;
+ if (!tables[sig]) tables[sig] = zeros(firstTableIndex);
+ var index = this.indexedFunctions[ident];
+ for (var i = tables[sig].length; i < index; i++) {
+ tables[sig][i] = 0; // keep flat
+ }
+ tables[sig][index] = ident;
}
var generated = false;
var wrapped = {};
+ var maxTable = 0;
for (var t in tables) {
if (t == 'pre') continue;
generated = true;
@@ -305,7 +310,7 @@ var Functions = {
// Resolve multi-level aliases all the way down
while (1) {
var varData = Variables.globals[table[i]];
- if (!(varData && varData.resolvedAlias)) break;
+ if (!(varData && varData.resolvedAlias && varData.resolvedAlias.indexOf('FUNCTION_TABLE_OFFSET') < 0)) break;
table[i] = table[+varData.resolvedAlias || eval(varData.resolvedAlias)]; // might need to eval to turn (6) into 6
}
// Resolve library aliases
@@ -351,6 +356,21 @@ var Functions = {
j += 10;
}
}
+ maxTable = Math.max(maxTable, table.length);
+ }
+ if (ASM_JS) maxTable = ceilPowerOfTwo(maxTable);
+ for (var t in tables) {
+ if (t == 'pre') continue;
+ var table = tables[t];
+ if (ASM_JS) {
+ // asm function table mask must be power of two
+ // if nonaliasing, then standardize function table size, to avoid aliasing pointers through the &M mask (in a small table using a big index)
+ var fullSize = ALIASING_FUNCTION_POINTERS ? ceilPowerOfTwo(table.length) : maxTable;
+ for (var i = table.length; i < fullSize; i++) {
+ table[i] = 0;
+ }
+ }
+ // finalize table
var indices = table.toString().replace('"', '');
if (BUILD_AS_SHARED_LIB) {
// Shared libraries reuse the parent's function table.
@@ -428,6 +448,7 @@ var PassManager = {
indexedFunctions: Functions.indexedFunctions,
implementedFunctions: ASM_JS ? Functions.implementedFunctions : [],
unimplementedFunctions: Functions.unimplementedFunctions,
+ neededTables: Functions.neededTables
}
}));
} else if (phase == 'post') {