aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jsifier.js1
-rw-r--r--src/library.js3
-rw-r--r--src/library_gl.js11
-rw-r--r--src/modules.js41
-rw-r--r--src/settings.js4
5 files changed, 45 insertions, 15 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index 8270b443..3f52337f 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -1463,6 +1463,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (!byPointerForced && !funcData.setjmpTable) {
// normal asm function pointer call
callIdent = '(' + callIdent + ')&{{{ FTM_' + sig + ' }}}'; // the function table mask is set in emscripten.py
+ Functions.neededTables[sig] = 1;
} else {
// This is a call through an invoke_*, either a forced one, or a setjmp-required one
// note: no need to update argsTypes at this point
diff --git a/src/library.js b/src/library.js
index 84071b68..d19fd531 100644
--- a/src/library.js
+++ b/src/library.js
@@ -3482,7 +3482,8 @@ LibraryManager.library = {
} else if (oldObj.isRoot || oldObj.path == FS.currentPath) {
___setErrNo(ERRNO_CODES.EBUSY);
return -1;
- } else if (newObj.path && newObj.path.indexOf(oldObj.path) == 0) {
+ } else if (newObj.parentPath &&
+ newObj.parentPath.indexOf(oldObj.path) == 0) {
___setErrNo(ERRNO_CODES.EINVAL);
return -1;
} else if (newObj.exists && newObj.object.isFolder) {
diff --git a/src/library_gl.js b/src/library_gl.js
index 0f6fb670..2e59f0d0 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -2880,7 +2880,7 @@ var LibraryGL = {
// Vertex array object (VAO) support. TODO: when the WebGL extension is popular, use that and remove this code and GL.vaos
glGenVertexArrays__deps: ['$GLEMulation'],
- glGenVertexArrays__sig: ['vii'],
+ glGenVertexArrays__sig: 'vii',
glGenVertexArrays: function(n, vaos) {
for (var i = 0; i < n; i++) {
var id = GL.getNewId(GLEmulation.vaos);
@@ -2895,7 +2895,7 @@ var LibraryGL = {
{{{ makeSetValue('vaos', 'i*4', 'id', 'i32') }}};
}
},
- glDeleteVertexArrays__sig: ['vii'],
+ glDeleteVertexArrays__sig: 'vii',
glDeleteVertexArrays: function(n, vaos) {
for (var i = 0; i < n; i++) {
var id = {{{ makeGetValue('vaos', 'i*4', 'i32') }}};
@@ -2903,7 +2903,7 @@ var LibraryGL = {
if (GLEmulation.currentVao && GLEmulation.currentVao.id == id) GLEmulation.currentVao = null;
}
},
- glBindVertexArray__sig: ['vi'],
+ glBindVertexArray__sig: 'vi',
glBindVertexArray: function(vao) {
// undo vao-related things, wipe the slate clean, both for vao of 0 or an actual vao
GLEmulation.currentVao = null; // make sure the commands we run here are not recorded
@@ -3331,7 +3331,10 @@ for (var item in LibraryGL) {
}
LibraryGL.$GLEmulation__deps = LibraryGL.$GLEmulation__deps.concat(glFuncs);
LibraryGL.$GLEmulation__deps.push(function() {
- for (var func in Functions.getIndex.tentative) Functions.getIndex(func);
+ for (var func in Functions.getIndex.tentative) {
+ Functions.getIndex(func);
+ Functions.unimplementedFunctions[func] = LibraryGL[func.substr(1) + '__sig'];
+ }
});
if (FORCE_GL_EMULATION) {
diff --git a/src/modules.js b/src/modules.js
index 2775bfbd..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;
@@ -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') {
diff --git a/src/settings.js b/src/settings.js
index 8766277b..d3abb06e 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -142,6 +142,10 @@ var SAFE_DYNCALLS = 0; // Show stack traces on missing function pointer/virtual
var RESERVED_FUNCTION_POINTERS = 0; // In asm.js mode, we cannot simply add function pointers to
// function tables, so we reserve some slots for them.
+var ALIASING_FUNCTION_POINTERS = 0; // Whether to allow function pointers to alias if they have
+ // a different type. This can greatly decrease table sizes
+ // in asm.js, but can break code that compares function
+ // pointers across different types.
var ASM_HEAP_LOG = 0; // Simple heap logging, like SAFE_HEAP_LOG but cheaper, and in asm.js