aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2011-10-16 09:48:32 -0700
committerAlon Zakai <alonzakai@gmail.com>2011-10-16 09:48:32 -0700
commit85817285da7a17f8cd914486fdd1f8766a271354 (patch)
treef5598bbfb20ede742a0ae84a3c5432898cff2ce6 /src
parent7e6a5e1ed8627f7d9444708d0e36a67263578bbd (diff)
inline specific library functions for speed
Diffstat (limited to 'src')
-rw-r--r--src/jsifier.js30
-rw-r--r--src/library.js34
-rw-r--r--src/modules.js4
-rw-r--r--src/parseTools.js22
4 files changed, 67 insertions, 23 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index 9c34ddf1..86f62c41 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -42,6 +42,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
substrate = new Substrate('JSifyer');
var GLOBAL_VARIABLES = !mainPass ? givenGlobalVariables : data.globalVariables;
+ Variables.globals = GLOBAL_VARIABLES;
Functions.currFunctions = !mainPass ? givenFunctions.currFunctions : {};
Functions.currExternalFunctions = !mainPass ? givenFunctions.currExternalFunctions : {};
@@ -831,28 +832,13 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
// We cannot compile assembly. See comment in intertyper.js:'Call'
assert(ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
- // Special cases
- if (ident == '_llvm_va_start') {
- // varargs - we received a pointer to the varargs as a final 'extra' parameter
- var data = 'arguments[' + Framework.currItem.funcData.ident + '.length]';
- return makeSetValue(params[0].ident, 0, data, 'void*');
- } else if (ident == '_llvm_va_end') {
- return ';';
- } else if (ident == '_EMSCRIPTEN_COMMENT') {
- var param = finalizeParam(params[0]);
- if (param.indexOf('CHECK_OVERFLOW') >= 0) {
- param = param.split('(')[1].split(',')[0];
- }
- return '// ' + GLOBAL_VARIABLES[param].value.text.replace('\\00', '') + ' ';
- }
-
+ var shortident = LibraryManager.getRootIdent(ident.slice(1)) || ident.slice(1); // ident may not be in library, if all there is is ident__inline
var func = Functions.currFunctions[ident] || Functions.currExternalFunctions[ident];
-
var args = [];
var argsTypes = [];
var varargs = [];
var varargsTypes = [];
- var useJSArgs = (ident.slice(1) + '__jsargs') in LibraryManager.library;
+ var useJSArgs = (shortident + '__jsargs') in LibraryManager.library;
params.forEach(function(param, i) {
var val = finalizeParam(param);
@@ -878,11 +864,19 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
varargs = makePointer('[' + varargs + ']', 0, 'ALLOC_STACK', varargsTypes);
}
+ args = args.concat(varargs);
+ var argsText = args.join(', ');
+
+ var inline = LibraryManager.library[shortident + '__inline'];
+ if (inline) {
+ return inline.apply(null, args); // Warning: inlining does not prevent recalculation of the arguments. They should be simple identifiers
+ }
+
if (getVarData(funcData, ident)) {
ident = 'FUNCTION_TABLE[' + ident + ']';
}
- return ident + '(' + args.concat(varargs).join(', ') + ')';
+ return ident + '(' + args.join(', ') + ')';
}
makeFuncLineActor('getelementptr', function(item) { return finalizeLLVMFunctionCall(item) });
makeFuncLineActor('call', function(item) {
diff --git a/src/library.js b/src/library.js
index a626f729..f8112af9 100644
--- a/src/library.js
+++ b/src/library.js
@@ -3578,13 +3578,21 @@ LibraryManager.library = {
// string.h
// ==========================================================================
+ memcpy__inline: function (dest, src, num, idunno) {
+ var ret = '';
+#if ASSERTIONS
+ ret += "assert(" + num + " % 1 === 0, 'memcpy given ' + " + num + " + ' bytes to copy. Problem with QUANTUM_SIZE=1 corrections perhaps?');";
+#endif
+ ret += makeCopyValues(dest, src, num, 'null');
+ return ret;
+ },
memcpy: function (dest, src, num, idunno) {
#if ASSERTIONS
assert(num % 1 === 0, 'memcpy given ' + num + ' bytes to copy. Problem with QUANTUM_SIZE=1 corrections perhaps?');
#endif
- // || 0, since memcpy sometimes copies uninitialized areas XXX: Investigate why initializing alloc'ed memory does not fix that too
- {{{ makeCopyValues('dest', 'src', 'num', 'null', ' || 0') }}};
+ {{{ makeCopyValues('dest', 'src', 'num', 'null') }}};
},
+
llvm_memcpy_i32: 'memcpy',
llvm_memcpy_i64: 'memcpy',
llvm_memcpy_p0i8_p0i8_i32: 'memcpy',
@@ -3604,6 +3612,9 @@ LibraryManager.library = {
llvm_memmove_p0i8_p0i8_i32: 'memmove',
llvm_memmove_p0i8_p0i8_i64: 'memmove',
+ memset__inline: function(ptr, value, num) {
+ return makeSetValues(ptr, 0, value, 'null', num);
+ },
memset: function(ptr, value, num) {
{{{ makeSetValues('ptr', '0', 'value', 'null', 'num') }}}
},
@@ -3984,6 +3995,14 @@ LibraryManager.library = {
// LLVM specifics
// ==========================================================================
+ llvm_va_start__inline: function(ptr) {
+ // varargs - we received a pointer to the varargs as a final 'extra' parameter
+ var data = 'arguments[' + Framework.currItem.funcData.ident + '.length]';
+ return makeSetValue(ptr, 0, data, 'void*');
+ },
+
+ llvm_va_end: function() {},
+
llvm_va_copy: function(ppdest, ppsrc) {
{{{ makeCopyValues('ppdest', 'ppsrc', QUANTUM_SIZE, 'null') }}}
/* Alternate implementation that copies the actual DATA; it assumes the va_list is prefixed by its size
@@ -4173,8 +4192,8 @@ LibraryManager.library = {
return ret;
},
- llvm_expect_i32: function(x, y) {
- return x == y; // TODO: inline this
+ llvm_expect_i32__inline: function(x, y) {
+ return '((' + x + ')==(' + y + '))';
},
llvm_lifetime_start: function() {},
@@ -5389,6 +5408,13 @@ LibraryManager.library = {
_Z21emscripten_run_scriptPKc: function(ptr) {
eval(Pointer_stringify(ptr));
+ },
+
+ EMSCRIPTEN_COMMENT__inline: function(param) {
+ if (param.indexOf('CHECK_OVERFLOW') >= 0) {
+ param = param.split('(')[1].split(',')[0];
+ }
+ return '// ' + Variables.globals[param].value.text.replace('\\00', '') + ' ';
}
};
diff --git a/src/modules.js b/src/modules.js
index 2341b575..b18fd13c 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -186,6 +186,10 @@ var Debugging = {
}
};
+var Variables = {
+ globals: null
+};
+
var Types = {
types: {},
fatTypes: {}, // With QUANTUM_SIZE=1, we store the full-size type data here
diff --git a/src/parseTools.js b/src/parseTools.js
index f9ef419a..f50092c7 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -793,14 +793,23 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore) {
}
}
+var UNROLL_LOOP_LIMIT = 5;
+
function makeSetValues(ptr, pos, value, type, num) {
function safety(where) {
where = where || getFastValue(ptr, '+', pos) + '+$mspi$';
return ';' + (SAFE_HEAP ? 'SAFE_HEAP_ACCESS(' + where + ', ' + type + ', 1)' : '');
}
if (USE_TYPED_ARRAYS in set(0, 1)) {
+ if (isNumber(num)) {
+ if (num < UNROLL_LOOP_LIMIT) {
+ return range(num).map(function(i) {
+ return makeSetValue(ptr, getFastValue(pos, '+', i), value, type);
+ }).join('; ');
+ }
+ }
return 'for (var $mspi$ = 0; $mspi$ < ' + num + '; $mspi$++) {\n' +
- makeSetValue(ptr, getFastValue(pos, '+', '$mspi$'), value, type) + ';\n}';
+ makeSetValue(ptr, getFastValue(pos, '+', '$mspi$'), value, type) + '\n}';
} else { // USE_TYPED_ARRAYS == 2
/*
return 'for (var $mspi$ = 0; $mspi$ < ' + num + '; $mspi$++) {\n' +
@@ -837,6 +846,17 @@ function makeCopyValues(dest, src, num, type, modifier) {
return (SAFE_HEAP ? 'SAFE_HEAP_COPY_HISTORY(' + to + ', ' + from + ')' : '');
}
if (USE_TYPED_ARRAYS in set(0, 1)) {
+ if (isNumber(num)) {
+ if (num < UNROLL_LOOP_LIMIT) {
+ return range(num).map(function(i) {
+ return type !== 'null' ? makeSetValue(dest, i, makeGetValue(src, i, type) + (modifier || ''), type)
+ : // Null is special-cased: We copy over all heaps
+ makeGetSlabs(dest, 'null', true).map(function(slab) {
+ return slab + '[' + dest + '+' + i + ']=' + slab + '[' + src + '+' + i + ']';
+ }).join('; ') + '; ' + safety(dest + '+' + i, src + '+' + i)
+ }).join('; ');
+ }
+ }
return 'for (var $mcpi$ = 0; $mcpi$ < ' + num + '; $mcpi$++) {\n' +
(type !== 'null' ? makeSetValue(dest, '$mcpi$', makeGetValue(src, '$mcpi$', type) + (modifier || ''), type)
: // Null is special-cased: We copy over all heaps