diff options
Diffstat (limited to 'src/preamble.js')
-rw-r--r-- | src/preamble.js | 149 |
1 files changed, 143 insertions, 6 deletions
diff --git a/src/preamble.js b/src/preamble.js index 88aaff77..aedb0e7c 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -36,7 +36,7 @@ var SAFE_HEAP_ERRORS = 0; var ACCEPTABLE_SAFE_HEAP_ERRORS = 0; function SAFE_HEAP_ACCESS(dest, type, store, ignore, storeValue) { - //if (dest === A_NUMBER) Module.print ([dest, type, store, ignore, storeValue] + ' ' + new Error().stack); // Something like this may be useful, in debugging + //if (dest === A_NUMBER) Module.print ([dest, type, store, ignore, storeValue] + ' ' + stackTrace()); // Something like this may be useful, in debugging assert(dest > 0, 'segmentation fault'); @@ -63,7 +63,7 @@ function SAFE_HEAP_ACCESS(dest, type, store, ignore, storeValue) { try { if (HEAP[dest].toString() === 'NaN') error = false; // NaN is acceptable, as a double value } catch(e){} - if (error) throw('Warning: Reading an invalid value at ' + dest + ' :: ' + new Error().stack + '\n'); + if (error) throw('Warning: Reading an invalid value at ' + dest + ' :: ' + stackTrace() + '\n'); } #endif if (type === null) return; @@ -72,14 +72,14 @@ function SAFE_HEAP_ACCESS(dest, type, store, ignore, storeValue) { if (!ignore) assert(history, 'Must have a history for a safe heap load! ' + dest + ':' + type); // Warning - bit fields in C structs cause loads+stores for each store, so // they will show up here... -// assert((history && history[0]) /* || HEAP[dest] === 0 */, "Loading from where there was no store! " + dest + ',' + HEAP[dest] + ',' + type + ', \n\n' + new Error().stack + '\n'); +// assert((history && history[0]) /* || HEAP[dest] === 0 */, "Loading from where there was no store! " + dest + ',' + HEAP[dest] + ',' + type + ', \n\n' + stackTrace() + '\n'); // if (history[0].type !== type) { if (history !== type && !ignore) { Module.print('Load-store consistency assumption failure! ' + dest); Module.print('\n'); Module.print(JSON.stringify(history)); Module.print('\n'); - Module.print('LOAD: ' + type + ', ' + new Error().stack); + Module.print('LOAD: ' + type + ', ' + stackTrace()); Module.print('\n'); SAFE_HEAP_ERRORS++; assert(SAFE_HEAP_ERRORS <= ACCEPTABLE_SAFE_HEAP_ERRORS, 'Load-store consistency assumption failure!'); @@ -93,9 +93,9 @@ function SAFE_HEAP_STORE(dest, value, type, ignore) { #endif if (!ignore && !value && (value === null || value === undefined)) { - throw('Warning: Writing an invalid value of ' + JSON.stringify(value) + ' at ' + dest + ' :: ' + new Error().stack + '\n'); + throw('Warning: Writing an invalid value of ' + JSON.stringify(value) + ' at ' + dest + ' :: ' + stackTrace() + '\n'); } - //if (!ignore && (value === Infinity || value === -Infinity || isNaN(value))) throw [value, typeof value, new Error().stack]; + //if (!ignore && (value === Infinity || value === -Infinity || isNaN(value))) throw [value, typeof value, stackTrace()]; SAFE_HEAP_ACCESS(dest, type, true, ignore, value); if (dest in HEAP_WATCHED) { @@ -640,6 +640,143 @@ function stringToUTF32(str, outPtr) { } Module['stringToUTF32'] = stringToUTF32; +function demangle(func) { + try { + if (typeof func === 'number') func = Pointer_stringify(func); + if (func[0] !== '_') return func; + if (func[1] !== '_') return func; // C function + if (func[2] !== 'Z') return func; + var i = 3; + // params, etc. + var basicTypes = { + 'v': 'void', + 'b': 'bool', + 'c': 'char', + 's': 'short', + 'i': 'int', + 'l': 'long', + 'f': 'float', + 'd': 'double', + 'w': 'wchar_t', + 'a': 'signed char', + 'h': 'unsigned char', + 't': 'unsigned short', + 'j': 'unsigned int', + 'm': 'unsigned long', + 'x': 'long long', + 'y': 'unsigned long long', + 'z': '...' + }; + function dump(x) { + //return; + if (x) Module.print(x); + Module.print(func); + var pre = ''; + for (var a = 0; a < i; a++) pre += ' '; + Module.print (pre + '^'); + } + var subs = []; + function parseNested() { + i++; + if (func[i] === 'K') i++; + var parts = []; + while (func[i] !== 'E') { + if (func[i] === 'S') { // substitution + i++; + var next = func.indexOf('_', i); + var num = func.substring(i, next) || 0; + parts.push(subs[num] || '?'); + i = next+1; + continue; + } + var size = parseInt(func.substr(i)); + var pre = size.toString().length; + if (!size || !pre) { i--; break; } // counter i++ below us + var curr = func.substr(i + pre, size); + parts.push(curr); + subs.push(curr); + i += pre + size; + } + i++; // skip E + return parts; + } + function parse(rawList, limit, allowVoid) { // main parser + limit = limit || Infinity; + var ret = '', list = []; + function flushList() { + return '(' + list.join(', ') + ')'; + } + var name; + if (func[i] !== 'N') { + // not namespaced + if (func[i] === 'K') i++; + var size = parseInt(func.substr(i)); + if (size) { + var pre = size.toString().length; + name = func.substr(i + pre, size); + i += pre + size; + } + } else { + // namespaced N-E + name = parseNested().join('::'); + limit--; + if (limit === 0) return rawList ? [name] : name; + } + if (func[i] === 'I') { + i++; + var iList = parse(true); + var iRet = parse(true, 1, true); + ret += iRet[0] + ' ' + name + '<' + iList.join(', ') + '>'; + } else { + ret = name; + } + paramLoop: while (i < func.length && limit-- > 0) { + //dump('paramLoop'); + var c = func[i++]; + if (c in basicTypes) { + list.push(basicTypes[c]); + } else { + switch (c) { + case 'P': list.push(parse(true, 1, true)[0] + '*'); break; // pointer + case 'R': list.push(parse(true, 1, true)[0] + '&'); break; // reference + case 'L': { // literal + i++; // skip basic type + var end = func.indexOf('E', i); + var size = end - i; + list.push(func.substr(i, size)); + i += size + 2; // size + 'EE' + break; + } + case 'A': { // array + var size = parseInt(func.substr(i)); + i += size.toString().length; + if (func[i] !== '_') throw '?'; + i++; // skip _ + list.push(parse(true, 1, true)[0] + ' [' + size + ']'); + break; + } + case 'E': break paramLoop; + default: ret += '?' + c; break paramLoop; + } + } + } + if (!allowVoid && list.length === 1 && list[0] === 'void') list = []; // avoid (void) + return rawList ? list : ret + flushList(); + } + return parse(); + } catch(e) { + return func; + } +} + +function demangleAll(text) { + return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') }); +} + +function stackTrace() { + return demangleAll(new Error().stack); +} + // Memory management var PAGE_SIZE = 4096; |