aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-02-16 19:24:26 -0800
committerAlon Zakai <alonzakai@gmail.com>2014-02-16 19:28:43 -0800
commit749325298aa5328429ee571f50034adaa4a6423d (patch)
tree5cfad392279bef01f1f20837d41cb91d489eb8cd
parent70797b08d802b50c96e79b55b2eb2b13c576971f (diff)
support memory growth in (non-validating) asm.js
-rwxr-xr-xemcc5
-rw-r--r--src/library.js29
-rw-r--r--src/preamble.js25
-rw-r--r--tests/test_core.py3
4 files changed, 40 insertions, 22 deletions
diff --git a/emcc b/emcc
index 22bf89c8..49785c37 100755
--- a/emcc
+++ b/emcc
@@ -1204,7 +1204,6 @@ try:
if fastcomp:
shared.Settings.ASM_JS = 1 if opt_level > 0 else 2
- assert shared.Settings.ALLOW_MEMORY_GROWTH == 0, 'memory growth not supported in fastcomp yet'
assert shared.Settings.UNALIGNED_MEMORY == 0, 'forced unaligned memory not supported in fastcomp'
assert shared.Settings.CHECK_HEAP_ALIGN == 0, 'check heap align not supported in fastcomp yet'
assert shared.Settings.SAFE_DYNCALLS == 0, 'safe dyncalls not supported in fastcomp'
@@ -1246,8 +1245,8 @@ try:
logging.warning('enabling js opts to allow SAFE_HEAP to work properly')
if shared.Settings.ALLOW_MEMORY_GROWTH:
- logging.error('Cannot enable ALLOW_MEMORY_GROWTH with asm.js, build with -s ASM_JS=0 if you need a growable heap');
- sys.exit(1);
+ logging.warning('Disabling asm.js validation for memory growth (memory can grow, but you lose some amount of speed)');
+ shared.Settings.ASM_JS = 2
if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2:
debug_level = 4 # must keep debug info to do line-by-line operations
diff --git a/src/library.js b/src/library.js
index 1b5e8b20..c1eb2219 100644
--- a/src/library.js
+++ b/src/library.js
@@ -9065,6 +9065,35 @@ LibraryManager.library = {
return cache[fullname] = allocate(intArrayFromString(ret + ''), 'i8', ALLOC_NORMAL);
},
+#if ASM_JS
+#if ALLOW_MEMORY_GROWTH
+ emscripten_replace_memory__asm: true, // this is used inside the asm module
+ emscripten_replace_memory__sig: 'viiiiiiii', // bogus
+ emscripten_replace_memory: function(_HEAP8, _HEAP16, _HEAP32, _HEAPU8, _HEAPU16, _HEAPU32, _HEAPF32, _HEAPF64) {
+ _HEAP8 = _HEAP8; // fake asm coercions
+ _HEAP16 = _HEAP16;
+ _HEAP32 = _HEAP32;
+ _HEAPU8 = _HEAPU8;
+ _HEAPU16 = _HEAPU16;
+ _HEAPU32 = _HEAPU32;
+ _HEAPF32 = _HEAPF32;
+ _HEAPF64 = _HEAPF64;
+ HEAP8 = _HEAP8; // replace the memory views
+ HEAP16 = _HEAP16;
+ HEAP32 = _HEAP32;
+ HEAPU8 = _HEAPU8;
+ HEAPU16 = _HEAPU16;
+ HEAPU32 = _HEAPU32;
+ HEAPF32 = _HEAPF32;
+ HEAPF64 = _HEAPF64;
+ },
+ // this function is inside the asm block, but prevents validation as asm.js
+ // the codebase still benefits from being in the general asm.js shape,
+ // but should not declare itself as validating (which is prevented in ASM_JS == 2).
+ {{{ (assert(ASM_JS === 2), DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.push('emscripten_replace_memory'), '') }}}
+#endif
+#endif
+
//============================
// emscripten vector ops
//============================
diff --git a/src/preamble.js b/src/preamble.js
index 5038e9c4..4f715167 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -860,33 +860,19 @@ var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk
#if USE_TYPED_ARRAYS
function enlargeMemory() {
#if ALLOW_MEMORY_GROWTH == 0
-#if ASM_JS == 0
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 ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.');
#else
- abort('Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', or (2) set Module.TOTAL_MEMORY before the program runs.');
-#endif
-#else
// TOTAL_MEMORY is the current size of the actual array, and DYNAMICTOP is the new top.
#if ASSERTIONS
- Module.printErr('Warning: Enlarging memory arrays, this is not fast, and ALLOW_MEMORY_GROWTH is not fully tested with all optimizations on! ' + [DYNAMICTOP, TOTAL_MEMORY]); // We perform safe elimination instead of elimination in this mode, but if you see this error, try to disable it and other optimizations entirely
+ Module.printErr('Warning: Enlarging memory arrays, this is not fast! ' + [DYNAMICTOP, TOTAL_MEMORY]);
assert(DYNAMICTOP >= TOTAL_MEMORY);
assert(TOTAL_MEMORY > 4); // So the loop below will not be infinite
#endif
- while (TOTAL_MEMORY <= DYNAMICTOP) { // Simple heuristic. Override enlargeMemory() if your program has something more optimal for it
+
+ while (TOTAL_MEMORY <= DYNAMICTOP) { // Simple heuristic.
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);
- IHEAP.set(oldIHEAP);
- IHEAPU = new Uint32Array(IHEAP.buffer);
-#if USE_FHEAP
- var oldFHEAP = FHEAP;
- Module['FHEAP'] = FHEAP = new Float64Array(TOTAL_MEMORY);
- FHEAP.set(oldFHEAP);
-#endif
-#endif
#if USE_TYPED_ARRAYS == 2
var oldHEAP8 = HEAP8;
var buffer = new ArrayBuffer(TOTAL_MEMORY);
@@ -899,6 +885,11 @@ function enlargeMemory() {
Module['HEAPF32'] = HEAPF32 = new Float32Array(buffer);
Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer);
HEAP8.set(oldHEAP8);
+#else
+ abort('cannot enlarge memory arrays in non-ta2 modes');
+#endif
+#if ASM_JS
+ _emscripten_replace_memory(HEAP8, HEAP16, HEAP32, HEAPU8, HEAPU16, HEAPU32, HEAPF32, HEAPF64);
#endif
#endif
}
diff --git a/tests/test_core.py b/tests/test_core.py
index 045b43c1..1349c6c8 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -1961,8 +1961,7 @@ def process(filename):
self.do_run_from_file(src, output)
def test_memorygrowth(self):
- if Settings.USE_TYPED_ARRAYS == 0: return self.skip('memory growth is only supported with typed arrays')
- if Settings.ASM_JS: return self.skip('asm does not support memory growth yet')
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('memory growth is only supported with typed arrays mode 2')
# With typed arrays in particular, it is dangerous to use more memory than TOTAL_MEMORY,
# since we then need to enlarge the heap(s).