Revision a8637a8e43f8023d742727c1463ac01992860940 authored by Alon Zakai on 04 January 2016, 22:57:24 UTC, committed by Alon Zakai on 04 January 2016, 22:57:24 UTC
1 parent 907b627
preamble.js
// {{PREAMBLE_ADDITIONS}}
// === Preamble library stuff ===
// Documentation for the public APIs defined in this file must be updated in:
// site/source/docs/api_reference/preamble.js.rst
// A prebuilt local version of the documentation is available at:
// site/build/text/docs/api_reference/preamble.js.txt
// You can also build docs locally as HTML or other formats in site/
// An online HTML version (which may be of a different version of Emscripten)
// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
//========================================
// Runtime code shared with compiler
//========================================
{{RUNTIME}}
#if RELOCATABLE
Runtime.GLOBAL_BASE = Runtime.alignMemory(Runtime.GLOBAL_BASE, {{{ MAX_GLOBAL_ALIGN || 1 }}});
#endif
{{{ maybeExport('Runtime') }}}
#if USE_CLOSURE_COMPILER
Runtime['addFunction'] = Runtime.addFunction;
Runtime['removeFunction'] = Runtime.removeFunction;
#endif
#if BENCHMARK
Module.realPrint = Module.print;
Module.print = Module.printErr = function(){};
#endif
#if SAFE_HEAP
function getSafeHeapType(bytes, isFloat) {
switch (bytes) {
case 1: return 'i8';
case 2: return 'i16';
case 4: return isFloat ? 'float' : 'i32';
case 8: return 'double';
default: assert(0);
}
}
#if SAFE_HEAP_LOG
var SAFE_HEAP_COUNTER = 0;
#endif
function SAFE_HEAP_STORE(dest, value, bytes, isFloat) {
#if SAFE_HEAP_LOG
Module.print('SAFE_HEAP store: ' + [dest, value, bytes, isFloat, SAFE_HEAP_COUNTER++]);
#endif
if (dest <= 0) abort('segmentation fault storing ' + bytes + ' bytes to address ' + dest);
if (dest % bytes !== 0) abort('alignment error storing to address ' + dest + ', which was expected to be aligned to a multiple of ' + bytes);
if (dest + bytes > Math.max(DYNAMICTOP, STATICTOP)) abort('segmentation fault, exceeded the top of the available heap when storing ' + bytes + ' bytes to address ' + dest + '. STATICTOP=' + STATICTOP + ', DYNAMICTOP=' + DYNAMICTOP);
assert(DYNAMICTOP <= TOTAL_MEMORY);
setValue(dest, value, getSafeHeapType(bytes, isFloat), 1);
}
function SAFE_HEAP_STORE_D(dest, value, bytes) {
SAFE_HEAP_STORE(dest, value, bytes, true);
}
function SAFE_HEAP_LOAD(dest, bytes, unsigned, isFloat) {
if (dest <= 0) abort('segmentation fault loading ' + bytes + ' bytes from address ' + dest);
if (dest % bytes !== 0) abort('alignment error loading from address ' + dest + ', which was expected to be aligned to a multiple of ' + bytes);
if (dest + bytes > Math.max(DYNAMICTOP, STATICTOP)) abort('segmentation fault, exceeded the top of the available heap when loading ' + bytes + ' bytes from address ' + dest + '. STATICTOP=' + STATICTOP + ', DYNAMICTOP=' + DYNAMICTOP);
assert(DYNAMICTOP <= TOTAL_MEMORY);
var type = getSafeHeapType(bytes, isFloat);
var ret = getValue(dest, type, 1);
if (unsigned) ret = unSign(ret, parseInt(type.substr(1)), 1);
#if SAFE_HEAP_LOG
Module.print('SAFE_HEAP load: ' + [dest, ret, bytes, isFloat, unsigned, SAFE_HEAP_COUNTER++]);
#endif
return ret;
}
function SAFE_HEAP_LOAD_D(dest, bytes, unsigned) {
return SAFE_HEAP_LOAD(dest, bytes, unsigned, true);
}
function SAFE_FT_MASK(value, mask) {
var ret = value & mask;
if (ret !== value) {
abort('Function table mask error: function pointer is ' + value + ' which is masked by ' + mask + ', the likely cause of this is that the function pointer is being called by the wrong type.');
}
return ret;
}
function segfault() {
abort('segmentation fault');
}
function alignfault() {
abort('alignment fault');
}
function ftfault() {
abort('Function table mask error');
}
#endif
//========================================
// Runtime essentials
//========================================
var __THREW__ = 0; // Used in checking for thrown exceptions.
var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort()
var EXITSTATUS = 0;
var undef = 0;
// tempInt is used for 32-bit signed values or smaller. tempBigInt is used
// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt
var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat;
var tempI64, tempI64b;
var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9;
function assert(condition, text) {
if (!condition) {
abort('Assertion failed: ' + text);
}
}
var globalScope = this;
// Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
function getCFunc(ident) {
var func = Module['_' + ident]; // closure exported function
if (!func) {
{{{ makeEval("try { func = eval('_' + ident); } catch(e) {}") }}}
}
assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)');
return func;
}
var cwrap, ccall;
(function(){
var JSfuncs = {
// Helpers for cwrap -- it can't refer to Runtime directly because it might
// be renamed by closure, instead it calls JSfuncs['stackSave'].body to find
// out what the minified function name is.
'stackSave': function() {
Runtime.stackSave()
},
'stackRestore': function() {
Runtime.stackRestore()
},
// type conversion from js to c
'arrayToC' : function(arr) {
var ret = Runtime.stackAlloc(arr.length);
writeArrayToMemory(arr, ret);
return ret;
},
'stringToC' : function(str) {
var ret = 0;
if (str !== null && str !== undefined && str !== 0) { // null string
// at most 4 bytes per UTF-8 code point, +1 for the trailing '\0'
ret = Runtime.stackAlloc((str.length << 2) + 1);
writeStringToMemory(str, ret);
}
return ret;
}
};
// For fast lookup of conversion functions
var toC = {'string' : JSfuncs['stringToC'], 'array' : JSfuncs['arrayToC']};
// C calling interface.
ccall = function ccallFunc(ident, returnType, argTypes, args, opts) {
var func = getCFunc(ident);
var cArgs = [];
var stack = 0;
#if ASSERTIONS
assert(returnType !== 'array', 'Return type should not be "array".');
#endif
if (args) {
for (var i = 0; i < args.length; i++) {
var converter = toC[argTypes[i]];
if (converter) {
if (stack === 0) stack = Runtime.stackSave();
cArgs[i] = converter(args[i]);
} else {
cArgs[i] = args[i];
}
}
}
var ret = func.apply(null, cArgs);
#if ASSERTIONS
if ((!opts || !opts.async) && typeof EmterpreterAsync === 'object') {
assert(!EmterpreterAsync.state, 'cannot start async op with normal JS calling ccall');
}
if (opts && opts.async) assert(!returnType, 'async ccalls cannot return values');
#endif
if (returnType === 'string') ret = Pointer_stringify(ret);
if (stack !== 0) {
if (opts && opts.async) {
EmterpreterAsync.asyncFinalizers.push(function() {
Runtime.stackRestore(stack);
});
return;
}
Runtime.stackRestore(stack);
}
return ret;
}
#if NO_DYNAMIC_EXECUTION == 0
var sourceRegex = /^function\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;
function parseJSFunc(jsfunc) {
// Match the body and the return value of a javascript function source
var parsed = jsfunc.toString().match(sourceRegex).slice(1);
return {arguments : parsed[0], body : parsed[1], returnValue: parsed[2]}
}
var JSsource = {};
for (var fun in JSfuncs) {
if (JSfuncs.hasOwnProperty(fun)) {
// Elements of toCsource are arrays of three items:
// the code, and the return value
JSsource[fun] = parseJSFunc(JSfuncs[fun]);
}
}
cwrap = function cwrap(ident, returnType, argTypes) {
argTypes = argTypes || [];
var cfunc = getCFunc(ident);
// When the function takes numbers and returns a number, we can just return
// the original function
var numericArgs = argTypes.every(function(type){ return type === 'number'});
var numericRet = (returnType !== 'string');
if ( numericRet && numericArgs) {
return cfunc;
}
// Creation of the arguments list (["$1","$2",...,"$nargs"])
var argNames = argTypes.map(function(x,i){return '$'+i});
var funcstr = "(function(" + argNames.join(',') + ") {";
var nargs = argTypes.length;
if (!numericArgs) {
// Generate the code needed to convert the arguments from javascript
// values to pointers
funcstr += 'var stack = ' + JSsource['stackSave'].body + ';';
for (var i = 0; i < nargs; i++) {
var arg = argNames[i], type = argTypes[i];
if (type === 'number') continue;
var convertCode = JSsource[type + 'ToC']; // [code, return]
funcstr += 'var ' + convertCode.arguments + ' = ' + arg + ';';
funcstr += convertCode.body + ';';
funcstr += arg + '=(' + convertCode.returnValue + ');';
}
}
// When the code is compressed, the name of cfunc is not literally 'cfunc' anymore
var cfuncname = parseJSFunc(function(){return cfunc}).returnValue;
// Call the function
funcstr += 'var ret = ' + cfuncname + '(' + argNames.join(',') + ');';
if (!numericRet) { // Return type can only by 'string' or 'number'
// Convert the result to a string
var strgfy = parseJSFunc(function(){return Pointer_stringify}).returnValue;
funcstr += 'ret = ' + strgfy + '(ret);';
}
#if ASSERTIONS
funcstr += "if (typeof EmterpreterAsync === 'object') { assert(!EmterpreterAsync.state, 'cannot start async op with normal JS calling cwrap') }";
#endif
if (!numericArgs) {
// If we had a stack, restore it
funcstr += JSsource['stackRestore'].body.replace('()', '(stack)') + ';';
}
funcstr += 'return ret})';
return eval(funcstr);
};
#else
// NO_DYNAMIC_EXECUTION is on, so we can't use the fast version of cwrap.
// Fall back to returning a bound version of ccall.
cwrap = function cwrap(ident, returnType, argTypes) {
return function() {
#if ASSERTIONS
Runtime.warnOnce('NO_DYNAMIC_EXECUTION was set, '
+ 'using slow cwrap implementation');
#endif
return ccall(ident, returnType, argTypes, arguments);
}
}
#endif
})();
{{{ maybeExport("ccall") }}}
{{{ maybeExport("cwrap") }}}
function setValue(ptr, value, type, noSafe) {
type = type || 'i8';
if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
#if SAFE_HEAP
if (noSafe) {
switch(type) {
case 'i1': {{{ makeSetValue('ptr', '0', 'value', 'i1', undefined, undefined, undefined, '1') }}}; break;
case 'i8': {{{ makeSetValue('ptr', '0', 'value', 'i8', undefined, undefined, undefined, '1') }}}; break;
case 'i16': {{{ makeSetValue('ptr', '0', 'value', 'i16', undefined, undefined, undefined, '1') }}}; break;
case 'i32': {{{ makeSetValue('ptr', '0', 'value', 'i32', undefined, undefined, undefined, '1') }}}; break;
case 'i64': {{{ makeSetValue('ptr', '0', 'value', 'i64', undefined, undefined, undefined, '1') }}}; break;
case 'float': {{{ makeSetValue('ptr', '0', 'value', 'float', undefined, undefined, undefined, '1') }}}; break;
case 'double': {{{ makeSetValue('ptr', '0', 'value', 'double', undefined, undefined, undefined, '1') }}}; break;
default: abort('invalid type for setValue: ' + type);
}
} else {
#endif
switch(type) {
case 'i1': {{{ makeSetValue('ptr', '0', 'value', 'i1') }}}; break;
case 'i8': {{{ makeSetValue('ptr', '0', 'value', 'i8') }}}; break;
case 'i16': {{{ makeSetValue('ptr', '0', 'value', 'i16') }}}; break;
case 'i32': {{{ makeSetValue('ptr', '0', 'value', 'i32') }}}; break;
case 'i64': {{{ makeSetValue('ptr', '0', 'value', 'i64') }}}; break;
case 'float': {{{ makeSetValue('ptr', '0', 'value', 'float') }}}; break;
case 'double': {{{ makeSetValue('ptr', '0', 'value', 'double') }}}; break;
default: abort('invalid type for setValue: ' + type);
}
#if SAFE_HEAP
}
#endif
}
{{{ maybeExport("setValue") }}}
function getValue(ptr, type, noSafe) {
type = type || 'i8';
if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
#if SAFE_HEAP
if (noSafe) {
switch(type) {
case 'i1': return {{{ makeGetValue('ptr', '0', 'i1', undefined, undefined, undefined, undefined, '1') }}};
case 'i8': return {{{ makeGetValue('ptr', '0', 'i8', undefined, undefined, undefined, undefined, '1') }}};
case 'i16': return {{{ makeGetValue('ptr', '0', 'i16', undefined, undefined, undefined, undefined, '1') }}};
case 'i32': return {{{ makeGetValue('ptr', '0', 'i32', undefined, undefined, undefined, undefined, '1') }}};
case 'i64': return {{{ makeGetValue('ptr', '0', 'i64', undefined, undefined, undefined, undefined, '1') }}};
case 'float': return {{{ makeGetValue('ptr', '0', 'float', undefined, undefined, undefined, undefined, '1') }}};
case 'double': return {{{ makeGetValue('ptr', '0', 'double', undefined, undefined, undefined, undefined, '1') }}};
default: abort('invalid type for setValue: ' + type);
}
} else {
#endif
switch(type) {
case 'i1': return {{{ makeGetValue('ptr', '0', 'i1') }}};
case 'i8': return {{{ makeGetValue('ptr', '0', 'i8') }}};
case 'i16': return {{{ makeGetValue('ptr', '0', 'i16') }}};
case 'i32': return {{{ makeGetValue('ptr', '0', 'i32') }}};
case 'i64': return {{{ makeGetValue('ptr', '0', 'i64') }}};
case 'float': return {{{ makeGetValue('ptr', '0', 'float') }}};
case 'double': return {{{ makeGetValue('ptr', '0', 'double') }}};
default: abort('invalid type for setValue: ' + type);
}
#if SAFE_HEAP
}
#endif
return null;
}
{{{ maybeExport("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_DYNAMIC = 3; // Cannot be freed except through sbrk
var ALLOC_NONE = 4; // Do not allocate
{{{ maybeExport('ALLOC_NORMAL') }}}
{{{ maybeExport('ALLOC_STACK') }}}
{{{ maybeExport('ALLOC_STATIC') }}}
{{{ maybeExport('ALLOC_DYNAMIC') }}}
{{{ maybeExport('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
// for multiple syntaxes to save space in generated code. So you should
// normally not use allocate(), and instead allocate memory using _malloc(),
// initialize it with setValue(), and so forth.
// @slab: An array of data, or a number. If a number, then the size of the block to allocate,
// in *bytes* (note that this is sometimes confusing: the next parameter does not
// affect this!)
// @types: Either an array of types, one for each byte (or 0 if no type at that position),
// or a single type which is used for the entire block. This only matters if there
// 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, ptr) {
var zeroinit, size;
if (typeof slab === 'number') {
zeroinit = true;
size = slab;
} else {
zeroinit = false;
size = slab.length;
}
var singleType = typeof types === 'string' ? types : null;
var ret;
if (allocator == ALLOC_NONE) {
ret = ptr;
} else {
ret = [typeof _malloc === 'function' ? _malloc : Runtime.staticAlloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
}
if (zeroinit) {
var ptr = ret, stop;
assert((ret & 3) == 0);
stop = ret + (size & ~3);
for (; ptr < stop; ptr += 4) {
{{{ makeSetValue('ptr', '0', '0', 'i32', null, true) }}};
}
stop = ret + size;
while (ptr < stop) {
{{{ makeSetValue('ptr++', '0', '0', 'i8', null, true) }}};
}
return ret;
}
if (singleType === 'i8') {
if (slab.subarray || slab.slice) {
HEAPU8.set(slab, ret);
} else {
HEAPU8.set(new Uint8Array(slab), ret);
}
return ret;
}
var i = 0, type, typeSize, previousType;
while (i < size) {
var curr = slab[i];
if (typeof curr === 'function') {
curr = Runtime.getFunctionIndex(curr);
}
type = singleType || types[i];
if (type === 0) {
i++;
continue;
}
#if ASSERTIONS
assert(type, 'Must know what type to store in allocate!');
#endif
if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
setValue(ret+i, curr, type);
// no need to look up size unless type changes, so cache it
if (previousType !== type) {
typeSize = Runtime.getNativeTypeSize(type);
previousType = type;
}
i += typeSize;
}
return ret;
}
{{{ maybeExport('allocate') }}}
// Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready
function getMemory(size) {
if (!staticSealed) return Runtime.staticAlloc(size);
if ((typeof _sbrk !== 'undefined' && !_sbrk.called) || !runtimeInitialized) return Runtime.dynamicAlloc(size);
return _malloc(size);
}
{{{ maybeExport('getMemory') }}}
function Pointer_stringify(ptr, /* optional */ length) {
if (length === 0 || !ptr) return '';
// TODO: use TextDecoder
// Find the length, and check for UTF while doing so
var hasUtf = 0;
var t;
var i = 0;
while (1) {
#if ASSERTIONS
assert(ptr + i < TOTAL_MEMORY);
#endif
t = {{{ makeGetValue('ptr', 'i', 'i8', 0, 1) }}};
hasUtf |= t;
if (t == 0 && !length) break;
i++;
if (length && i == length) break;
}
if (!length) length = i;
var ret = '';
if (hasUtf < 128) {
var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack
var curr;
while (length > 0) {
curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
ret = ret ? ret + curr : curr;
ptr += MAX_CHUNK;
length -= MAX_CHUNK;
}
return ret;
}
return Module['UTF8ToString'](ptr);
}
{{{ maybeExport('Pointer_stringify') }}}
// Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns
// a copy of that string as a Javascript String object.
function AsciiToString(ptr) {
var str = '';
while (1) {
var ch = {{{ makeGetValue('ptr++', 0, 'i8') }}};
if (!ch) return str;
str += String.fromCharCode(ch);
}
}
{{{ maybeExport('AsciiToString') }}}
// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
// null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP.
function stringToAscii(str, outPtr) {
return writeAsciiToMemory(str, outPtr, false);
}
{{{ maybeExport('stringToAscii') }}}
// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns
// a copy of that string as a Javascript String object.
function UTF8ArrayToString(u8Array, idx) {
var u0, u1, u2, u3, u4, u5;
var str = '';
while (1) {
// For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629
u0 = u8Array[idx++];
if (!u0) return str;
if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
u1 = u8Array[idx++] & 63;
if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
u2 = u8Array[idx++] & 63;
if ((u0 & 0xF0) == 0xE0) {
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
} else {
u3 = u8Array[idx++] & 63;
if ((u0 & 0xF8) == 0xF0) {
u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | u3;
} else {
u4 = u8Array[idx++] & 63;
if ((u0 & 0xFC) == 0xF8) {
u0 = ((u0 & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4;
} else {
u5 = u8Array[idx++] & 63;
u0 = ((u0 & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5;
}
}
}
if (u0 < 0x10000) {
str += String.fromCharCode(u0);
} else {
var ch = u0 - 0x10000;
str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
}
}
}
{{{ maybeExport('UTF8ArrayToString') }}}
// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns
// a copy of that string as a Javascript String object.
function UTF8ToString(ptr) {
return UTF8ArrayToString({{{ heapAndOffset('HEAPU8', 'ptr') }}});
}
{{{ maybeExport('UTF8ToString') }}}
// Copies the given Javascript String object 'str' to the given byte array at address 'outIdx',
// encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP.
// Use the function lengthBytesUTF8() to compute the exact number of bytes (excluding null terminator) that this function will write.
// Parameters:
// str: the Javascript string to copy.
// outU8Array: the array to copy to. Each index in this array is assumed to be one 8-byte element.
// outIdx: The starting offset in the array to begin the copying.
// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
// terminator, i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else.
// maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator.
// Returns the number of bytes written, EXCLUDING the null terminator.
function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) {
if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes.
return 0;
var startIdx = outIdx;
var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.
for (var i = 0; i < str.length; ++i) {
// Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8.
// See http://unicode.org/faq/utf_bom.html#utf16-3
// For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629
var u = str.charCodeAt(i); // possibly a lead surrogate
if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
if (u <= 0x7F) {
if (outIdx >= endIdx) break;
outU8Array[outIdx++] = u;
} else if (u <= 0x7FF) {
if (outIdx + 1 >= endIdx) break;
outU8Array[outIdx++] = 0xC0 | (u >> 6);
outU8Array[outIdx++] = 0x80 | (u & 63);
} else if (u <= 0xFFFF) {
if (outIdx + 2 >= endIdx) break;
outU8Array[outIdx++] = 0xE0 | (u >> 12);
outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
outU8Array[outIdx++] = 0x80 | (u & 63);
} else if (u <= 0x1FFFFF) {
if (outIdx + 3 >= endIdx) break;
outU8Array[outIdx++] = 0xF0 | (u >> 18);
outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
outU8Array[outIdx++] = 0x80 | (u & 63);
} else if (u <= 0x3FFFFFF) {
if (outIdx + 4 >= endIdx) break;
outU8Array[outIdx++] = 0xF8 | (u >> 24);
outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63);
outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
outU8Array[outIdx++] = 0x80 | (u & 63);
} else {
if (outIdx + 5 >= endIdx) break;
outU8Array[outIdx++] = 0xFC | (u >> 30);
outU8Array[outIdx++] = 0x80 | ((u >> 24) & 63);
outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63);
outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
outU8Array[outIdx++] = 0x80 | (u & 63);
}
}
// Null-terminate the pointer to the buffer.
outU8Array[outIdx] = 0;
return outIdx - startIdx;
}
{{{ maybeExport('stringToUTF8Array') }}}
// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
// null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP.
// Use the function lengthBytesUTF8() to compute the exact number of bytes (excluding null terminator) that this function will write.
// Returns the number of bytes written, EXCLUDING the null terminator.
function stringToUTF8(str, outPtr, maxBytesToWrite) {
#if ASSERTIONS
assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
#endif
return stringToUTF8Array(str, {{{ heapAndOffset('HEAPU8', 'outPtr') }}}, maxBytesToWrite);
}
{{{ maybeExport('stringToUTF8') }}}
// Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte.
function lengthBytesUTF8(str) {
var len = 0;
for (var i = 0; i < str.length; ++i) {
// Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8.
// See http://unicode.org/faq/utf_bom.html#utf16-3
var u = str.charCodeAt(i); // possibly a lead surrogate
if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
if (u <= 0x7F) {
++len;
} else if (u <= 0x7FF) {
len += 2;
} else if (u <= 0xFFFF) {
len += 3;
} else if (u <= 0x1FFFFF) {
len += 4;
} else if (u <= 0x3FFFFFF) {
len += 5;
} else {
len += 6;
}
}
return len;
}
{{{ maybeExport('lengthBytesUTF8') }}}
// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns
// a copy of that string as a Javascript String object.
function UTF16ToString(ptr) {
var i = 0;
var str = '';
while (1) {
var codeUnit = {{{ makeGetValue('ptr', 'i*2', 'i16') }}};
if (codeUnit == 0)
return str;
++i;
// fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through.
str += String.fromCharCode(codeUnit);
}
}
{{{ maybeExport('UTF16ToString') }}}
// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
// null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP.
// Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write.
// Parameters:
// str: the Javascript string to copy.
// outPtr: Byte address in Emscripten HEAP where to write the string to.
// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
// terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else.
// maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator.
// Returns the number of bytes written, EXCLUDING the null terminator.
function stringToUTF16(str, outPtr, maxBytesToWrite) {
#if ASSERTIONS
assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
#endif
// Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
if (maxBytesToWrite === undefined) {
maxBytesToWrite = 0x7FFFFFFF;
}
if (maxBytesToWrite < 2) return 0;
maxBytesToWrite -= 2; // Null terminator.
var startPtr = outPtr;
var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length;
for (var i = 0; i < numCharsToWrite; ++i) {
// charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
{{{ makeSetValue('outPtr', 0, 'codeUnit', 'i16') }}};
outPtr += 2;
}
// Null-terminate the pointer to the HEAP.
{{{ makeSetValue('outPtr', 0, 0, 'i16') }}};
return outPtr - startPtr;
}
{{{ maybeExport('stringToUTF16') }}}
// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
function lengthBytesUTF16(str) {
return str.length*2;
}
{{{ maybeExport('lengthBytesUTF16') }}}
function UTF32ToString(ptr) {
var i = 0;
var str = '';
while (1) {
var utf32 = {{{ makeGetValue('ptr', 'i*4', 'i32') }}};
if (utf32 == 0)
return str;
++i;
// Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing.
// See http://unicode.org/faq/utf_bom.html#utf16-3
if (utf32 >= 0x10000) {
var ch = utf32 - 0x10000;
str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
} else {
str += String.fromCharCode(utf32);
}
}
}
{{{ maybeExport('UTF32ToString') }}}
// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
// null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP.
// Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write.
// Parameters:
// str: the Javascript string to copy.
// outPtr: Byte address in Emscripten HEAP where to write the string to.
// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
// terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else.
// maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator.
// Returns the number of bytes written, EXCLUDING the null terminator.
function stringToUTF32(str, outPtr, maxBytesToWrite) {
#if ASSERTIONS
assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
#endif
// Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
if (maxBytesToWrite === undefined) {
maxBytesToWrite = 0x7FFFFFFF;
}
if (maxBytesToWrite < 4) return 0;
var startPtr = outPtr;
var endPtr = startPtr + maxBytesToWrite - 4;
for (var i = 0; i < str.length; ++i) {
// Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
// See http://unicode.org/faq/utf_bom.html#utf16-3
var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
var trailSurrogate = str.charCodeAt(++i);
codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
}
{{{ makeSetValue('outPtr', 0, 'codeUnit', 'i32') }}};
outPtr += 4;
if (outPtr + 4 > endPtr) break;
}
// Null-terminate the pointer to the HEAP.
{{{ makeSetValue('outPtr', 0, 0, 'i32') }}};
return outPtr - startPtr;
}
{{{ maybeExport('stringToUTF32') }}}
// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
function lengthBytesUTF32(str) {
var len = 0;
for (var i = 0; i < str.length; ++i) {
// Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
// See http://unicode.org/faq/utf_bom.html#utf16-3
var codeUnit = str.charCodeAt(i);
if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate.
len += 4;
}
return len;
}
{{{ maybeExport('lengthBytesUTF32') }}}
function demangle(func) {
var hasLibcxxabi = !!Module['___cxa_demangle'];
if (hasLibcxxabi) {
try {
var buf = _malloc(func.length);
writeStringToMemory(func.substr(1), buf);
var status = _malloc(4);
var ret = Module['___cxa_demangle'](buf, 0, 0, status);
if (getValue(status, 'i32') === 0 && ret) {
return Pointer_stringify(ret);
}
// otherwise, libcxxabi failed, we can try ours which may return a partial result
} catch(e) {
// failure when using libcxxabi, we can try ours which may return a partial result
} finally {
if (buf) _free(buf);
if (status) _free(status);
if (ret) _free(ret);
}
}
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': '...'
};
var subs = [];
var first = true;
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 + '^');
}
function parseNested() {
i++;
if (func[i] === 'K') i++; // ignore const
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;
}
if (func[i] === 'C') { // constructor
parts.push(parts[parts.length-1]);
i += 2;
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') {
// namespaced N-E
name = parseNested().join('::');
limit--;
if (limit === 0) return rawList ? [name] : name;
} else {
// not namespaced
if (func[i] === 'K' || (first && func[i] === 'L')) i++; // ignore const and first 'L'
var size = parseInt(func.substr(i));
if (size) {
var pre = size.toString().length;
name = func.substr(i + pre, size);
i += pre + size;
}
}
first = false;
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)
if (rawList) {
if (ret) {
list.push(ret + '?');
}
return list;
} else {
return ret + flushList();
}
}
var parsed = func;
try {
// Special-case the entry point, since its name differs from other name mangling.
if (func == 'Object._main' || func == '_main') {
return 'main()';
}
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;
switch (func[3]) {
case 'n': return 'operator new()';
case 'd': return 'operator delete()';
}
parsed = parse();
} catch(e) {
parsed += '?';
}
if (parsed.indexOf('?') >= 0 && !hasLibcxxabi) {
Runtime.warnOnce('warning: a problem occurred in builtin C++ name demangling; build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling');
}
return parsed;
}
function demangleAll(text) {
return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') });
}
function jsStackTrace() {
var err = new Error();
if (!err.stack) {
// IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown,
// so try that as a special-case.
try {
throw new Error(0);
} catch(e) {
err = e;
}
if (!err.stack) {
return '(no stack trace available)';
}
}
return err.stack.toString();
}
function stackTrace() {
return demangleAll(jsStackTrace());
}
{{{ maybeExport('stackTrace') }}}
// Memory management
var PAGE_SIZE = 4096;
function alignMemoryPage(x) {
if (x % 4096 > 0) {
x += (4096 - (x % 4096));
}
return x;
}
var HEAP;
var buffer;
var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
function updateGlobalBuffer(buf) {
Module['buffer'] = buffer = buf;
}
function updateGlobalBufferViews() {
Module['HEAP8'] = HEAP8 = new Int8Array(buffer);
Module['HEAP16'] = HEAP16 = new Int16Array(buffer);
Module['HEAP32'] = HEAP32 = new Int32Array(buffer);
Module['HEAPU8'] = HEAPU8 = new Uint8Array(buffer);
Module['HEAPU16'] = HEAPU16 = new Uint16Array(buffer);
Module['HEAPU32'] = HEAPU32 = new Uint32Array(buffer);
Module['HEAPF32'] = HEAPF32 = new Float32Array(buffer);
Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer);
}
var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area
var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area
var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk
#if USE_PTHREADS
if (ENVIRONMENT_IS_PTHREAD) {
staticSealed = true; // The static memory area has been initialized already in the main thread, pthreads skip this.
#if SEPARATE_ASM != 0
importScripts('{{{ SEPARATE_ASM }}}'); // load the separated-out asm.js
#endif
}
#endif
#if ALLOW_MEMORY_GROWTH == 0
function abortOnCannotGrowMemory() {
abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which adjusts the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ');
}
#else // ALLOW_MEMORY_GROWTH
if (!Module['reallocBuffer']) Module['reallocBuffer'] = function(size) {
var ret;
try {
if (ArrayBuffer.transfer) {
ret = ArrayBuffer.transfer(buffer, size);
} else {
var oldHEAP8 = HEAP8;
ret = new ArrayBuffer(size);
var temp = new Int8Array(ret);
temp.set(oldHEAP8);
}
} catch(e) {
return false;
}
var success = _emscripten_replace_memory(ret);
if (!success) return false;
return ret;
};
#endif
function enlargeMemory() {
#if USE_PTHREADS
abort('Cannot enlarge memory arrays, since compiling with pthreads support enabled (-s USE_PTHREADS=1).');
#else
#if ALLOW_MEMORY_GROWTH == 0
#if ABORTING_MALLOC
abortOnCannotGrowMemory();
#else
return false; // malloc will report failure
#endif
#else
// TOTAL_MEMORY is the current size of the actual array, and DYNAMICTOP is the new top.
#if ASSERTIONS
assert(DYNAMICTOP >= TOTAL_MEMORY);
assert(TOTAL_MEMORY > 4); // So the loop below will not be infinite
#endif
var OLD_TOTAL_MEMORY = TOTAL_MEMORY;
#if EMSCRIPTEN_TRACING
// Report old layout one last time
_emscripten_trace_report_memory_layout();
#endif
var LIMIT = Math.pow(2, 31); // 2GB is a practical maximum, as we use signed ints as pointers
// and JS engines seem unhappy to give us 2GB arrays currently
if (DYNAMICTOP >= LIMIT) return false;
while (TOTAL_MEMORY <= DYNAMICTOP) { // Simple heuristic.
if (TOTAL_MEMORY < LIMIT/2) {
TOTAL_MEMORY = alignMemoryPage(2*TOTAL_MEMORY); // double until 1GB
} else {
var last = TOTAL_MEMORY;
TOTAL_MEMORY = alignMemoryPage((3*TOTAL_MEMORY + LIMIT)/4); // add smaller increments towards 2GB, which we cannot reach
if (TOTAL_MEMORY <= last) return false;
}
}
TOTAL_MEMORY = Math.max(TOTAL_MEMORY, 16*1024*1024);
if (TOTAL_MEMORY >= LIMIT) return false;
#if ASSERTIONS
Module.printErr('Warning: Enlarging memory arrays, this is not fast! ' + [OLD_TOTAL_MEMORY, TOTAL_MEMORY]);
#endif
#if EMSCRIPTEN_TRACING
_emscripten_trace_js_log_message("Emscripten", "Enlarging memory arrays from " + OLD_TOTAL_MEMORY + " to " + TOTAL_MEMORY);
// And now report the new layout
_emscripten_trace_report_memory_layout();
#endif
#if ASSERTIONS
var start = Date.now();
#endif
var replacement = Module['reallocBuffer'](TOTAL_MEMORY);
if (!replacement) return false;
// everything worked
updateGlobalBuffer(replacement);
updateGlobalBufferViews();
#if ASSERTIONS
Module.printErr('enlarged memory arrays from ' + OLD_TOTAL_MEMORY + ' to ' + TOTAL_MEMORY + ', took ' + (Date.now() - start) + ' ms (has ArrayBuffer.transfer? ' + (!!ArrayBuffer.transfer) + ')');
#endif
return true;
#endif // ALLOW_MEMORY_GROWTH
#endif // USE_PTHREADS
}
#if ALLOW_MEMORY_GROWTH
var byteLength;
try {
byteLength = Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, 'byteLength').get);
byteLength(new ArrayBuffer(4)); // can fail on older ie
} catch(e) { // can fail on older node/v8
byteLength = function(buffer) { return buffer.byteLength; };
}
#endif
var TOTAL_STACK = Module['TOTAL_STACK'] || {{{ TOTAL_STACK }}};
var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || {{{ TOTAL_MEMORY }}};
var totalMemory = 64*1024;
while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) {
if (totalMemory < 16*1024*1024) {
totalMemory *= 2;
} else {
totalMemory += 16*1024*1024
}
}
#if ALLOW_MEMORY_GROWTH
totalMemory = Math.max(totalMemory, 16*1024*1024);
#endif
if (totalMemory !== TOTAL_MEMORY) {
#if ASSERTIONS
Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be compliant with the asm.js spec (and given that TOTAL_STACK=' + TOTAL_STACK + ')');
#endif
TOTAL_MEMORY = totalMemory;
}
// Initialize the runtime's memory
// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']),
'JS engine does not provide full typed array support');
#if IN_TEST_HARNESS
#if USE_PTHREADS == 1
if (typeof SharedArrayBuffer === 'undefined' || typeof Atomics === 'undefined') {
xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8888/report_result?skipped:%20SharedArrayBuffer%20is%20not%20supported!');
xhr.send();
setTimeout(function() { window.close() }, 2000);
}
#endif
#endif
#if USE_PTHREADS
if (typeof SharedArrayBuffer !== 'undefined') {
if (!ENVIRONMENT_IS_PTHREAD) buffer = new SharedArrayBuffer(TOTAL_MEMORY);
// Currently SharedArrayBuffer does not have a slice() operation, so polyfill it in.
// Adapted from https://github.com/ttaubert/node-arraybuffer-slice, (c) 2014 Tim Taubert <tim@timtaubert.de>
// arraybuffer-slice may be freely distributed under the MIT license.
(function (undefined) {
"use strict";
function clamp(val, length) {
val = (val|0) || 0;
if (val < 0) return Math.max(val + length, 0);
return Math.min(val, length);
}
if (typeof SharedArrayBuffer !== 'undefined' && !SharedArrayBuffer.prototype.slice) {
SharedArrayBuffer.prototype.slice = function (from, to) {
var length = this.byteLength;
var begin = clamp(from, length);
var end = length;
if (to !== undefined) end = clamp(to, length);
if (begin > end) return new ArrayBuffer(0);
var num = end - begin;
var target = new ArrayBuffer(num);
var targetArray = new Uint8Array(target);
var sourceArray = new Uint8Array(this, begin, num);
targetArray.set(sourceArray);
return target;
};
}
})();
} else {
if (!ENVIRONMENT_IS_PTHREAD) buffer = new ArrayBuffer(TOTAL_MEMORY);
}
updateGlobalBufferViews();
if (typeof Atomics === 'undefined') {
// Polyfill singlethreaded atomics ops from http://lars-t-hansen.github.io/ecmascript_sharedmem/shmem.html#Atomics.add
// No thread-safety needed since we don't have multithreading support.
Atomics = {};
Atomics['add'] = function(t, i, v) { var w = t[i]; t[i] += v; return w; }
Atomics['and'] = function(t, i, v) { var w = t[i]; t[i] &= v; return w; }
Atomics['compareExchange'] = function(t, i, e, r) { var w = t[i]; if (w == e) t[i] = r; return w; }
Atomics['futexWait'] = function(t, i, v, o) { if (t[i] != v) abort('Multithreading is not supported, cannot sleep to wait for futex!'); }
Atomics['futexWake'] = function(t, i, c) {}
Atomics['futexWakeOrRequeue'] = function(t, i1, c, i2, v) {}
Atomics['isLockFree'] = function(s) { return true; }
Atomics['load'] = function(t, i) { return t[i]; }
Atomics['or'] = function(t, i, v) { var w = t[i]; t[i] |= v; return w; }
Atomics['store'] = function(t, i, v) { t[i] = v; return v; }
Atomics['sub'] = function(t, i, v) { var w = t[i]; t[i] -= v; return w; }
Atomics['xor'] = function(t, i, v) { var w = t[i]; t[i] ^= v; return w; }
}
#else // USE_PTHREADS
#if SPLIT_MEMORY == 0
// Use a provided buffer, if there is one, or else allocate a new one
if (Module['buffer']) {
buffer = Module['buffer'];
assert(buffer.byteLength === TOTAL_MEMORY, 'provided buffer should be ' + TOTAL_MEMORY + ' bytes, but it is ' + buffer.byteLength);
} else {
buffer = new ArrayBuffer(TOTAL_MEMORY);
}
updateGlobalBufferViews();
#else // SPLIT_MEMORY
// make sure total memory is a multiple of the split memory size
var SPLIT_MEMORY = {{{ SPLIT_MEMORY }}};
var SPLIT_MEMORY_MASK = SPLIT_MEMORY - 1;
var SPLIT_MEMORY_BITS = -1;
var ALLOW_MEMORY_GROWTH = {{{ ALLOW_MEMORY_GROWTH }}};
var ABORTING_MALLOC = {{{ ABORTING_MALLOC }}};
Module['SPLIT_MEMORY'] = SPLIT_MEMORY;
totalMemory = TOTAL_MEMORY;
if (totalMemory % SPLIT_MEMORY) {
totalMemory += SPLIT_MEMORY - (totalMemory % SPLIT_MEMORY);
}
if (totalMemory === SPLIT_MEMORY) totalMemory *= 2;
if (totalMemory !== TOTAL_MEMORY) {
TOTAL_MEMORY = totalMemory;
#if ASSERTIONS == 2
Module.printErr('increasing TOTAL_MEMORY to ' + TOTAL_MEMORY + ' to be a multiple>1 of the split memory size ' + SPLIT_MEMORY + ')');
#endif
}
var buffers = [], HEAP8s = [], HEAP16s = [], HEAP32s = [], HEAPU8s = [], HEAPU16s = [], HEAPU32s = [], HEAPF32s = [], HEAPF64s = [];
// Allocates a split chunk, a range of memory of size SPLIT_MEMORY. Generally data is not provided, and a new
// buffer is allocated, this is what happens when malloc works. However, you can provide your own buffer,
// which then lets you access it at address [ i*SPLIT_MEMORY, (i+1)*SPLIT_MEMORY ).
// The function returns true if it succeeds. It can also throw an exception if no data is provided and
// the browser fails to allocate the buffer.
function allocateSplitChunk(i, data) {
if (buffers[i]) return false; // already taken
var curr = data ? data : new ArrayBuffer(SPLIT_MEMORY);
assert(curr instanceof ArrayBuffer);
buffers[i] = curr;
HEAP8s[i] = new Int8Array(curr);
HEAP16s[i] = new Int16Array(curr);
HEAP32s[i] = new Int32Array(curr);
HEAPU8s[i] = new Uint8Array(curr);
HEAPU16s[i] = new Uint16Array(curr);
HEAPU32s[i] = new Uint32Array(curr);
HEAPF32s[i] = new Float32Array(curr);
HEAPF64s[i] = new Float64Array(curr);
return true;
}
function freeSplitChunk(i) {
assert(buffers[i] && HEAP8s[i]);
assert(i > 0); // cannot free the first chunk
buffers[i] = HEAP8s[i] = HEAP16s[i] = HEAP32s[i] = HEAPU8s[i] = HEAPU16s[i] = HEAPU32s[i] = HEAPF32s[i] = HEAPF64s[i] = null;
}
(function() {
for (var i = 0; i < TOTAL_MEMORY / SPLIT_MEMORY; i++) {
buffers[i] = HEAP8s[i] = HEAP16s[i] = HEAP32s[i] = HEAPU8s[i] = HEAPU16s[i] = HEAPU32s[i] = HEAPF32s[i] = HEAPF64s[i] = null;
}
var temp = SPLIT_MEMORY;
while (temp) {
temp >>= 1;
SPLIT_MEMORY_BITS++;
}
allocateSplitChunk(0); // first chunk is for core runtime, static, stack, etc., always must be initialized
// support HEAP8.subarray etc.
var SHIFT_TABLE = [0, 0, 1, 0, 2, 0, 0, 0, 3];
function fake(real) {
var bytes = real[0].BYTES_PER_ELEMENT;
var shifts = SHIFT_TABLE[bytes];
assert(shifts > 0 || bytes == 1);
var that = {
BYTES_PER_ELEMENT: bytes,
set: function(array, offset) {
if (offset === undefined) offset = 0;
// potentially split over multiple chunks
while (array.length > 0) {
var chunk = offset >> SPLIT_MEMORY_BITS;
var relative = offset & SPLIT_MEMORY_MASK;
if (relative + (array.length << shifts) < SPLIT_MEMORY) {
real[chunk].set(array, relative); // all fits in this chunk
break;
} else {
var currSize = SPLIT_MEMORY - relative;
assert(currSize % that.BYTES_PER_ELEMENT === 0);
var lastIndex = currSize >> shifts;
real[chunk].set(array.subarray(0, lastIndex), relative);
// increments
array = array.subarray(lastIndex);
offset += currSize;
}
}
},
subarray: function(from, to) {
from = from << shifts;
var start = from >> SPLIT_MEMORY_BITS;
if (to === undefined) {
to = (start + 1) << SPLIT_MEMORY_BITS;
} else {
to = to << shifts;
}
to = Math.max(from, to); // if to is smaller, we'll get nothing anyway, same as to == from
if (from < to) {
var end = (to - 1) >> SPLIT_MEMORY_BITS; // -1, since we do not actually read the last address
assert(start === end, 'subarray cannot span split chunks');
}
if (to > from && (to & SPLIT_MEMORY_MASK) == 0) {
// avoid the mask on the next line giving 0 for the end
return real[start].subarray((from & SPLIT_MEMORY_MASK) >> shifts); // just return to the end of the chunk
}
return real[start].subarray((from & SPLIT_MEMORY_MASK) >> shifts, (to & SPLIT_MEMORY_MASK) >> shifts);
},
buffer: {
slice: function(from, to) {
assert(to, 'TODO: this is an actual copy, so we could support a slice across multiple chunks');
return new Uint8Array(HEAPU8.subarray(from, to)).buffer;
},
},
};
return that;
}
HEAP8 = fake(HEAP8s);
HEAP16 = fake(HEAP16s);
HEAP32 = fake(HEAP32s);
HEAPU8 = fake(HEAPU8s);
HEAPU16 = fake(HEAPU16s);
HEAPU32 = fake(HEAPU32s);
HEAPF32 = fake(HEAPF32s);
HEAPF64 = fake(HEAPF64s);
})();
#if SAFE_SPLIT_MEMORY
function checkPtr(ptr, shifts) {
if (ptr <= 0) abort('segmentation fault storing to address ' + ptr);
if (ptr !== ((ptr >> shifts) << shifts)) abort('alignment error storing to address ' + ptr + ', which was expected to be aligned to a shift of ' + shifts);
if ((ptr >> SPLIT_MEMORY_BITS) !== (ptr + Math.pow(2, shifts) - 1 >> SPLIT_MEMORY_BITS)) abort('segmentation fault, write spans split chunks ' + [ptr, shifts]);
}
#endif
function get8(ptr) {
ptr = ptr | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 0);
#endif
return HEAP8s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 0] | 0;
}
function get16(ptr) {
ptr = ptr | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 1);
#endif
return HEAP16s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 1] | 0;
}
function get32(ptr) {
ptr = ptr | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 2);
#endif
return HEAP32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2] | 0;
}
function getU8(ptr) {
ptr = ptr | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 0);
#endif
return HEAPU8s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 0] | 0;
}
function getU16(ptr) {
ptr = ptr | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 1);
#endif
return HEAPU16s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 1] | 0;
}
function getU32(ptr) {
ptr = ptr | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 2);
#endif
return HEAPU32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2] | 0;
}
function getF32(ptr) {
ptr = ptr | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 2);
#endif
return +HEAPF32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2];
}
function getF64(ptr) {
ptr = ptr | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 3);
#endif
return +HEAPF64s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 3];
}
function set8(ptr, value) {
ptr = ptr | 0;
value = value | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 0);
#endif
HEAP8s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 0] = value;
}
function set16(ptr, value) {
ptr = ptr | 0;
value = value | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 1);
#endif
HEAP16s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 1] = value;
}
function set32(ptr, value) {
ptr = ptr | 0;
value = value | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 2);
#endif
HEAP32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2] = value;
}
function setU8(ptr, value) {
ptr = ptr | 0;
value = value | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 0);
#endif
HEAPU8s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 0] = value;
}
function setU16(ptr, value) {
ptr = ptr | 0;
value = value | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 1);
#endif
HEAPU16s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 1] = value;
}
function setU32(ptr, value) {
ptr = ptr | 0;
value = value | 0;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 2);
#endif
HEAPU32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2] = value;
}
function setF32(ptr, value) {
ptr = ptr | 0;
value = +value;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 2);
#endif
HEAPF32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2] = value;
}
function setF64(ptr, value) {
ptr = ptr | 0;
value = +value;
#if SAFE_SPLIT_MEMORY
checkPtr(ptr, 3);
#endif
HEAPF64s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 3] = value;
}
#endif // SPLIT_MEMORY
#endif // USE_PTHREADS
// Endianness check (note: assumes compiler arch was little-endian)
#if SAFE_SPLIT_MEMORY == 0
HEAP32[0] = 255;
assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system');
#endif
Module['HEAP'] = HEAP;
Module['buffer'] = buffer;
Module['HEAP8'] = HEAP8;
Module['HEAP16'] = HEAP16;
Module['HEAP32'] = HEAP32;
Module['HEAPU8'] = HEAPU8;
Module['HEAPU16'] = HEAPU16;
Module['HEAPU32'] = HEAPU32;
Module['HEAPF32'] = HEAPF32;
Module['HEAPF64'] = HEAPF64;
function callRuntimeCallbacks(callbacks) {
while(callbacks.length > 0) {
var callback = callbacks.shift();
if (typeof callback == 'function') {
callback();
continue;
}
var func = callback.func;
if (typeof func === 'number') {
if (callback.arg === undefined) {
Runtime.dynCall('v', func);
} else {
Runtime.dynCall('vi', func, [callback.arg]);
}
} else {
func(callback.arg === undefined ? null : callback.arg);
}
}
}
var __ATPRERUN__ = []; // functions called before the runtime is initialized
var __ATINIT__ = []; // functions called during startup
var __ATMAIN__ = []; // functions called when main() is to be run
var __ATEXIT__ = []; // functions called during shutdown
var __ATPOSTRUN__ = []; // functions called after the runtime has exited
var runtimeInitialized = false;
var runtimeExited = false;
#if USE_PTHREADS
if (ENVIRONMENT_IS_PTHREAD) runtimeInitialized = true; // The runtime is hosted in the main thread, and bits shared to pthreads via SharedArrayBuffer. No need to init again in pthread.
#endif
function preRun() {
#if USE_PTHREADS
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
#endif
// compatibility - merge in anything from Module['preRun'] at this time
if (Module['preRun']) {
if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
while (Module['preRun'].length) {
addOnPreRun(Module['preRun'].shift());
}
}
callRuntimeCallbacks(__ATPRERUN__);
}
function ensureInitRuntime() {
#if USE_PTHREADS
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
#endif
if (runtimeInitialized) return;
runtimeInitialized = true;
callRuntimeCallbacks(__ATINIT__);
}
function preMain() {
#if USE_PTHREADS
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
#endif
callRuntimeCallbacks(__ATMAIN__);
}
function exitRuntime() {
#if USE_PTHREADS
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
#endif
callRuntimeCallbacks(__ATEXIT__);
runtimeExited = true;
}
function postRun() {
#if USE_PTHREADS
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
#endif
// compatibility - merge in anything from Module['postRun'] at this time
if (Module['postRun']) {
if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
while (Module['postRun'].length) {
addOnPostRun(Module['postRun'].shift());
}
}
callRuntimeCallbacks(__ATPOSTRUN__);
}
function addOnPreRun(cb) {
__ATPRERUN__.unshift(cb);
}
{{{ maybeExport('addOnPreRun') }}}
function addOnInit(cb) {
__ATINIT__.unshift(cb);
}
{{{ maybeExport('addOnInit') }}}
function addOnPreMain(cb) {
__ATMAIN__.unshift(cb);
}
{{{ maybeExport('addOnPreMain') }}}
function addOnExit(cb) {
__ATEXIT__.unshift(cb);
}
{{{ maybeExport('addOnExit') }}}
function addOnPostRun(cb) {
__ATPOSTRUN__.unshift(cb);
}
{{{ maybeExport('addOnPostRun') }}}
// Tools
function intArrayFromString(stringy, dontAddNull, length /* optional */) {
var len = length > 0 ? length : lengthBytesUTF8(stringy)+1;
var u8array = new Array(len);
var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
if (dontAddNull) u8array.length = numBytesWritten;
return u8array;
}
{{{ maybeExport('intArrayFromString') }}}
function intArrayToString(array) {
var ret = [];
for (var i = 0; i < array.length; i++) {
var chr = array[i];
if (chr > 0xFF) {
#if ASSERTIONS
assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.');
#endif
chr &= 0xFF;
}
ret.push(String.fromCharCode(chr));
}
return ret.join('');
}
{{{ maybeExport('intArrayToString') }}}
function writeStringToMemory(string, buffer, dontAddNull) {
var array = intArrayFromString(string, dontAddNull);
var i = 0;
while (i < array.length) {
var chr = array[i];
{{{ makeSetValue('buffer', 'i', 'chr', 'i8') }}};
i = i + 1;
}
}
{{{ maybeExport('writeStringToMemory') }}}
function writeArrayToMemory(array, buffer) {
for (var i = 0; i < array.length; i++) {
{{{ makeSetValue('buffer++', 0, 'array[i]', 'i8') }}};
}
}
{{{ maybeExport('writeArrayToMemory') }}}
function writeAsciiToMemory(str, buffer, dontAddNull) {
for (var i = 0; i < str.length; ++i) {
#if ASSERTIONS
assert(str.charCodeAt(i) === str.charCodeAt(i)&0xff);
#endif
{{{ makeSetValue('buffer++', 0, 'str.charCodeAt(i)', 'i8') }}};
}
// Null-terminate the pointer to the HEAP.
if (!dontAddNull) {{{ makeSetValue('buffer', 0, 0, 'i8') }}};
}
{{{ maybeExport('writeAsciiToMemory') }}}
{{{ unSign }}}
{{{ reSign }}}
#if USE_PTHREADS
// Atomics.exchange is not yet implemented in the spec, so polyfill that in via compareExchange in the meanwhile.
// TODO: Keep an eye out for the opportunity to remove this once Atomics.exchange is available.
if (typeof Atomics !== 'undefined' && !Atomics['exchange']) {
Atomics['exchange'] = function(heap, index, val) {
var oldVal, oldVal2;
do {
oldVal = Atomics['load'](heap, index);
oldVal2 = Atomics['compareExchange'](heap, index, oldVal, val);
} while(oldVal != oldVal2);
return oldVal;
}
}
#endif
// check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 )
if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) {
var ah = a >>> 16;
var al = a & 0xffff;
var bh = b >>> 16;
var bl = b & 0xffff;
return (al*bl + ((ah*bl + al*bh) << 16))|0;
};
Math.imul = Math['imul'];
#if PRECISE_F32
#if PRECISE_F32 == 1
if (!Math['fround']) {
var froundBuffer = new Float32Array(1);
Math['fround'] = function(x) { froundBuffer[0] = x; return froundBuffer[0] };
}
#else // 2
if (!Math['fround']) Math['fround'] = function(x) { return x };
#endif
Math.fround = Math['fround'];
#else
#if SIMD
if (!Math['fround']) Math['fround'] = function(x) { return x };
#endif
#endif
if (!Math['clz32']) Math['clz32'] = function(x) {
x = x >>> 0;
for (var i = 0; i < 32; i++) {
if (x & (1 << (31 - i))) return i;
}
return 32;
};
Math.clz32 = Math['clz32']
var Math_abs = Math.abs;
var Math_cos = Math.cos;
var Math_sin = Math.sin;
var Math_tan = Math.tan;
var Math_acos = Math.acos;
var Math_asin = Math.asin;
var Math_atan = Math.atan;
var Math_atan2 = Math.atan2;
var Math_exp = Math.exp;
var Math_log = Math.log;
var Math_sqrt = Math.sqrt;
var Math_ceil = Math.ceil;
var Math_floor = Math.floor;
var Math_pow = Math.pow;
var Math_imul = Math.imul;
var Math_fround = Math.fround;
var Math_min = Math.min;
var Math_clz32 = Math.clz32;
// A counter of dependencies for calling run(). If we need to
// do asynchronous work before running, increment this and
// decrement it. Incrementing must happen in a place like
// PRE_RUN_ADDITIONS (used by emcc to add file preloading).
// Note that you can add dependencies in preRun, even though
// it happens right before run - run will be postponed until
// the dependencies are met.
var runDependencies = 0;
var runDependencyWatcher = null;
var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
#if ASSERTIONS
var runDependencyTracking = {};
#endif
function getUniqueRunDependency(id) {
#if ASSERTIONS
var orig = id;
while (1) {
if (!runDependencyTracking[id]) return id;
id = orig + Math.random();
}
#endif
return id;
}
function addRunDependency(id) {
runDependencies++;
if (Module['monitorRunDependencies']) {
Module['monitorRunDependencies'](runDependencies);
}
#if ASSERTIONS
if (id) {
assert(!runDependencyTracking[id]);
runDependencyTracking[id] = 1;
if (runDependencyWatcher === null && typeof setInterval !== 'undefined') {
// Check for missing dependencies every few seconds
runDependencyWatcher = setInterval(function() {
if (ABORT) {
clearInterval(runDependencyWatcher);
runDependencyWatcher = null;
return;
}
var shown = false;
for (var dep in runDependencyTracking) {
if (!shown) {
shown = true;
Module.printErr('still waiting on run dependencies:');
}
Module.printErr('dependency: ' + dep);
}
if (shown) {
Module.printErr('(end of list)');
}
}, 10000);
}
} else {
Module.printErr('warning: run dependency added without ID');
}
#endif
}
{{{ maybeExport('addRunDependency') }}}
function removeRunDependency(id) {
runDependencies--;
if (Module['monitorRunDependencies']) {
Module['monitorRunDependencies'](runDependencies);
}
#if ASSERTIONS
if (id) {
assert(runDependencyTracking[id]);
delete runDependencyTracking[id];
} else {
Module.printErr('warning: run dependency removed without ID');
}
#endif
if (runDependencies == 0) {
if (runDependencyWatcher !== null) {
clearInterval(runDependencyWatcher);
runDependencyWatcher = null;
}
if (dependenciesFulfilled) {
var callback = dependenciesFulfilled;
dependenciesFulfilled = null;
callback(); // can add another dependenciesFulfilled
}
}
}
{{{ maybeExport('removeRunDependency') }}}
Module["preloadedImages"] = {}; // maps url to image data
Module["preloadedAudios"] = {}; // maps url to audio data
#if PGO
var PGOMonitor = {
called: {},
dump: function() {
var dead = [];
for (var i = 0; i < this.allGenerated.length; i++) {
var func = this.allGenerated[i];
if (!this.called[func]) dead.push(func);
}
Module.print('-s DEAD_FUNCTIONS=\'' + JSON.stringify(dead) + '\'\n');
}
};
Module['PGOMonitor'] = PGOMonitor;
__ATEXIT__.push(function() { PGOMonitor.dump() });
addOnPreRun(function() { addRunDependency('pgo') });
#endif
#if RELOCATABLE
{{{
(function() {
// add in RUNTIME_LINKED_LIBS, if provided
if (RUNTIME_LINKED_LIBS.length > 0) {
return "if (!Module['dynamicLibraries']) Module['dynamicLibraries'] = [];\n" +
"Module['dynamicLibraries'] = " + JSON.stringify(RUNTIME_LINKED_LIBS) + ".concat(Module['dynamicLibraries']);\n";
}
return '';
})()
}}}
addOnPreRun(function() {
if (Module['dynamicLibraries']) {
Module['dynamicLibraries'].forEach(function(lib) {
Runtime.loadDynamicLibrary(lib);
});
}
asm['runPostSets']();
});
#if ASSERTIONS
function lookupSymbol(ptr) { // for a pointer, print out all symbols that resolve to it
var ret = [];
for (var i in Module) {
if (Module[i] === ptr) ret.push(i);
}
print(ptr + ' is ' + ret);
}
#endif
#endif
var memoryInitializer = null;
#if USE_PTHREADS
#if PTHREAD_HINT_NUM_CORES < 0
if (!ENVIRONMENT_IS_PTHREAD) addOnPreRun(function() {
addRunDependency('pthreads_querycores');
var bg = document.createElement('div');
bg.style = "position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index:1001; -moz-opacity: 0.8; opacity:.80; filter: alpha(opacity=80);";
var div = document.createElement('div');
var default_num_cores = navigator.hardwareConcurrency || 4;
var hwConcurrency = navigator.hardwareConcurrency ? ("says " + navigator.hardwareConcurrency) : "is not available";
var html = '<div style="width: 100%; text-align:center;"> Thread setup</div> <br /> Number of logical cores: <input type="number" style="width: 50px;" value="'
+ default_num_cores + '" min="1" max="32" id="thread_setup_num_logical_cores"></input> <br /><span style="font-size: 75%;">(<span style="font-family: monospace;">navigator.hardwareConcurrency</span> '
+ hwConcurrency + ')</span> <br />';
#if PTHREAD_POOL_SIZE < 0
html += 'PThread pool size: <input type="number" style="width: 50px;" value="'
+ default_num_cores + '" min="1" max="32" id="thread_setup_pthread_pool_size"></input> <br />';
#endif
html += ' <br /> <input type="button" id="thread_setup_button_go" value="Go"></input>';
div.innerHTML = html;
div.style = 'position: absolute; top: 35%; left: 35%; width: 30%; height: 150px; padding: 16px; border: 16px solid gray; background-color: white; z-index:1002; overflow: auto;';
document.body.appendChild(bg);
document.body.appendChild(div);
var goButton = document.getElementById('thread_setup_button_go');
goButton.onclick = function() {
var num_logical_cores = parseInt(document.getElementById('thread_setup_num_logical_cores').value);
_emscripten_force_num_logical_cores(num_logical_cores);
#if PTHREAD_POOL_SIZE < 0
var pthread_pool_size = parseInt(document.getElementById('thread_setup_pthread_pool_size').value);
PThread.allocateUnusedWorkers(pthread_pool_size, function() { removeRunDependency('pthreads_querycores'); });
#else
removeRunDependency('pthreads_querycores');
#endif
document.body.removeChild(bg);
document.body.removeChild(div);
}
});
#endif
#endif
#if PTHREAD_POOL_SIZE > 0
// To work around https://bugzilla.mozilla.org/show_bug.cgi?id=1049079, warm up a worker pool before starting up the application.
if (!ENVIRONMENT_IS_PTHREAD) addOnPreRun(function() { if (typeof SharedArrayBuffer !== 'undefined') { addRunDependency('pthreads'); PThread.allocateUnusedWorkers({{{PTHREAD_POOL_SIZE}}}, function() { removeRunDependency('pthreads'); }); }});
#endif
// === Body ===
Computing file changes ...