aboutsummaryrefslogtreecommitdiff
path: root/src/preamble.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/preamble.js')
-rw-r--r--src/preamble.js221
1 files changed, 86 insertions, 135 deletions
diff --git a/src/preamble.js b/src/preamble.js
index aab50e9a..9bc68d8f 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -150,51 +150,24 @@ function SAFE_HEAP_COPY_HISTORY(dest, src) {
//==========================================
#endif
-var CorrectionsMonitor = {
-#if PGO
- MAX_ALLOWED: Infinity,
-#else
- MAX_ALLOWED: 0, // XXX
+#if CHECK_HEAP_ALIGN
+//========================================
+// Debugging tools - alignment check
+//========================================
+function CHECK_ALIGN_8(addr) {
+ assert((addr & 7) == 0, "address must be 8-byte aligned, is " + addr + "!");
+ return addr;
+}
+function CHECK_ALIGN_4(addr) {
+ assert((addr & 3) == 0, "address must be 4-byte aligned, is " + addr + "!");
+ return addr;
+}
+function CHECK_ALIGN_2(addr) {
+ assert((addr & 1) == 0, "address must be 2-byte aligned!");
+ return addr;
+}
#endif
- corrections: 0,
- sigs: {},
- note: function(type, succeed, sig) {
- if (!succeed) {
- this.corrections++;
- if (this.corrections >= this.MAX_ALLOWED) abort('\n\nToo many corrections!');
- }
-#if PGO
- if (!sig)
- sig = (new Error().stack).toString().split('\n')[2].split(':').slice(-1)[0]; // Spidermonkey-specific FIXME
- sig = type + '|' + sig;
- if (!this.sigs[sig]) {
- //Module.print('Correction: ' + sig);
- this.sigs[sig] = [0, 0]; // fail, succeed
- }
- this.sigs[sig][succeed ? 1 : 0]++;
-#endif
- },
-
- print: function() {
-#if PGO
- var items = [];
- for (var sig in this.sigs) {
- items.push({
- sig: sig,
- fails: this.sigs[sig][0],
- succeeds: this.sigs[sig][1],
- total: this.sigs[sig][0] + this.sigs[sig][1]
- });
- }
- items.sort(function(x, y) { return y.total - x.total; });
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- Module.print(item.sig + ' : ' + item.total + ' hits, %' + (Math.ceil(100*item.fails/item.total)) + ' failures');
- }
-#endif
- }
-};
#if CHECK_OVERFLOWS
//========================================
@@ -207,24 +180,20 @@ function CHECK_OVERFLOW(value, bits, ignore, sig) {
// For signedness issue here, see settings.js, CHECK_SIGNED_OVERFLOWS
#if CHECK_SIGNED_OVERFLOWS
if (value === Infinity || value === -Infinity || value >= twopbits1 || value < -twopbits1) {
- CorrectionsMonitor.note('SignedOverflow', 0, sig);
- if (value === Infinity || value === -Infinity || Math.abs(value) >= twopbits) CorrectionsMonitor.note('Overflow');
+ throw 'SignedOverflow';
+ if (value === Infinity || value === -Infinity || Math.abs(value) >= twopbits) throw 'Overflow';
+ }
#else
if (value === Infinity || value === -Infinity || Math.abs(value) >= twopbits) {
- CorrectionsMonitor.note('Overflow', 0, sig);
+ throw 'Overflow';
+ }
#endif
#if CORRECT_OVERFLOWS
- // Fail on >32 bits - we warned at compile time
- if (bits <= 32) {
- value = value & (twopbits - 1);
- }
-#endif
- } else {
-#if CHECK_SIGNED_OVERFLOWS
- CorrectionsMonitor.note('SignedOverflow', 1, sig);
-#endif
- CorrectionsMonitor.note('Overflow', 1, sig);
+ // Fail on >32 bits - we warned at compile time
+ if (bits <= 32) {
+ value = value & (twopbits - 1);
}
+#endif
return value;
}
#endif
@@ -243,39 +212,6 @@ var INDENT = '';
var START_TIME = Date.now();
#endif
-#if PROFILE
-var PROFILING = 0;
-var PROFILING_ROOT = { time: 0, children: {}, calls: 0 };
-var PROFILING_NODE;
-
-function startProfiling() {
- PROFILING_NODE = PROFILING_ROOT;
- PROFILING = 1;
-}
-Module['startProfiling'] = startProfiling;
-
-function stopProfiling() {
- PROFILING = 0;
- assert(PROFILING_NODE === PROFILING_ROOT, 'Must have popped all the profiling call stack');
-}
-Module['stopProfiling'] = stopProfiling;
-
-function printProfiling() {
- function dumpData(name_, node, indent) {
- Module.print(indent + ('________' + node.time).substr(-8) + ': ' + name_ + ' (' + node.calls + ')');
- var children = [];
- for (var child in node.children) {
- children.push(node.children[child]);
- children[children.length-1].name_ = child;
- }
- children.sort(function(x, y) { return y.time - x.time });
- children.forEach(function(child) { dumpData(child.name_, child, indent + ' ') });
- }
- dumpData('root', PROFILING_ROOT, ' ');
-}
-Module['printProfiling'] = printProfiling;
-#endif
-
//========================================
// Runtime essentials
//========================================
@@ -334,11 +270,9 @@ Module["ccall"] = ccall;
// Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
function getCFunc(ident) {
try {
- var func = eval('_' + ident);
+ var func = globalScope['Module']['_' + ident]; // closure exported function
+ if (!func) func = eval('_' + ident); // explicit lookup
} catch(e) {
- try {
- func = globalScope['Module']['_' + ident]; // closure exported function
- } catch(e) {}
}
assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)');
return func;
@@ -478,14 +412,6 @@ Module['ALLOC_STACK'] = ALLOC_STACK;
Module['ALLOC_STATIC'] = ALLOC_STATIC;
Module['ALLOC_NONE'] = ALLOC_NONE;
-// Simple unoptimized memset - necessary during startup
-var _memset = function(ptr, value, num) {
- var stop = ptr + num;
- while (ptr < stop) {
- {{{ makeSetValue('ptr++', 0, 'value', 'i8', null, true) }}};
- }
-}
-
// 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
@@ -519,7 +445,18 @@ function allocate(slab, types, allocator, ptr) {
}
if (zeroinit) {
- _memset(ret, 0, size);
+ var ptr = ret, stop;
+#if USE_TYPED_ARRAYS == 2
+ assert((ret & 3) == 0);
+ stop = ret + (size & ~3);
+ for (; ptr < stop; ptr += 4) {
+ {{{ makeSetValue('ptr', '0', '0', 'i32', null, true) }}};
+ }
+#endif
+ stop = ret + size;
+ while (ptr < stop) {
+ {{{ makeSetValue('ptr++', '0', '0', 'i8', null, true) }}};
+ }
return ret;
}
@@ -530,7 +467,7 @@ function allocate(slab, types, allocator, ptr) {
}
#endif
- var i = 0, type;
+ var i = 0, type, typeSize, previousType;
while (i < size) {
var curr = slab[i];
@@ -552,7 +489,13 @@ function allocate(slab, types, allocator, ptr) {
#endif
setValue(ret+i, curr, type);
- i += Runtime.getNativeTypeSize(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;
@@ -626,6 +569,7 @@ function enlargeMemory() {
while (TOTAL_MEMORY <= STATICTOP) { // Simple heuristic. Override enlargeMemory() if your program has something more optimal for it
TOTAL_MEMORY = alignMemoryPage(2*TOTAL_MEMORY);
}
+ assert(TOTAL_MEMORY <= Math.pow(2, 30)); // 2^30==1GB is a practical maximum - 2^31 is already close to possible negative numbers etc.
#if USE_TYPED_ARRAYS == 1
var oldIHEAP = IHEAP;
Module['HEAP'] = Module['IHEAP'] = HEAP = IHEAP = new Int32Array(TOTAL_MEMORY);
@@ -655,47 +599,43 @@ function enlargeMemory() {
#endif
var TOTAL_STACK = Module['TOTAL_STACK'] || {{{ TOTAL_STACK }}};
-#if ASM_JS == 0
var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || {{{ TOTAL_MEMORY }}};
-#else
-var TOTAL_MEMORY = {{{ TOTAL_MEMORY }}}; // in asm, we hardcode the mask, so cannot adjust memory at runtime
-#endif
var FAST_MEMORY = Module['FAST_MEMORY'] || {{{ FAST_MEMORY }}};
// Initialize the runtime's memory
#if USE_TYPED_ARRAYS
// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
- assert(!!Int32Array && !!Float64Array && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']),
- 'Cannot fallback to non-typed array case: Code is too specialized');
+assert(!!Int32Array && !!Float64Array && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']),
+ 'Cannot fallback to non-typed array case: Code is too specialized');
#if USE_TYPED_ARRAYS == 1
- HEAP = IHEAP = new Int32Array(TOTAL_MEMORY);
- IHEAPU = new Uint32Array(IHEAP.buffer);
+HEAP = IHEAP = new Int32Array(TOTAL_MEMORY);
+IHEAPU = new Uint32Array(IHEAP.buffer);
#if USE_FHEAP
- FHEAP = new Float64Array(TOTAL_MEMORY);
+FHEAP = new Float64Array(TOTAL_MEMORY);
#endif
#endif
#if USE_TYPED_ARRAYS == 2
- var buffer = new ArrayBuffer(TOTAL_MEMORY);
- HEAP8 = new Int8Array(buffer);
- HEAP16 = new Int16Array(buffer);
- HEAP32 = new Int32Array(buffer);
- HEAPU8 = new Uint8Array(buffer);
- HEAPU16 = new Uint16Array(buffer);
- HEAPU32 = new Uint32Array(buffer);
- HEAPF32 = new Float32Array(buffer);
- HEAPF64 = new Float64Array(buffer);
-
- // Endianness check (note: assumes compiler arch was little-endian)
- HEAP32[0] = 255;
- assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system');
+var buffer = new ArrayBuffer(TOTAL_MEMORY);
+HEAP8 = new Int8Array(buffer);
+HEAP16 = new Int16Array(buffer);
+HEAP32 = new Int32Array(buffer);
+HEAPU8 = new Uint8Array(buffer);
+HEAPU16 = new Uint16Array(buffer);
+HEAPU32 = new Uint32Array(buffer);
+HEAPF32 = new Float32Array(buffer);
+HEAPF64 = new Float64Array(buffer);
+
+// Endianness check (note: assumes compiler arch was little-endian)
+HEAP32[0] = 255;
+assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system');
#endif
#else
- // Make sure that our HEAP is implemented as a flat array.
- HEAP = []; // Hinting at the size with |new Array(TOTAL_MEMORY)| should help in theory but makes v8 much slower
- for (var i = 0; i < FAST_MEMORY; i++) {
- HEAP[i] = 0; // XXX We do *not* use {{| makeSetValue(0, 'i', 0, 'null') |}} here, since this is done just to optimize runtime speed
- }
+// Make sure that our HEAP is implemented as a flat array.
+HEAP = []; // Hinting at the size with |new Array(TOTAL_MEMORY)| should help in theory but makes v8 much slower
+for (var i = 0; i < FAST_MEMORY; i++) {
+ HEAP[i] = 0; // XXX We do *not* use {{| makeSetValue(0, 'i', 0, 'null') |}} here, since this is done just to optimize runtime speed
+}
#endif
Module['HEAP'] = HEAP;
@@ -722,7 +662,7 @@ STACK_MAX = TOTAL_STACK; // we lose a little stack here, but TOTAL_STACK is nice
#if USE_TYPED_ARRAYS == 2
var tempDoublePtr = Runtime.alignMemory(allocate(12, 'i8', ALLOC_STACK), 8);
assert(tempDoublePtr % 8 == 0);
-function copyTempFloat(ptr) { // functions, because inlining this code is increases code size too much
+function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much
HEAP8[tempDoublePtr] = HEAP8[ptr];
HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
@@ -773,9 +713,6 @@ function preMain() {
}
function exitRuntime() {
callRuntimeCallbacks(__ATEXIT__);
-
- // Print summary of correction activity
- CorrectionsMonitor.print();
}
// Tools
@@ -832,6 +769,20 @@ Module['writeArrayToMemory'] = writeArrayToMemory;
{{{ unSign }}}
{{{ reSign }}}
+#if PRECISE_I32_MUL
+if (!Math.imul) Math.imul = function(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;
+};
+#else
+Math.imul = function(a, b) {
+ return (a*b)|0; // fast but imprecise
+};
+#endif
+
// 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