Skip to content

Commit 1655d72

Browse files
committed
Move enlargeMemory() and getTotalMemory() to library JS file
1 parent 7013ed9 commit 1655d72

File tree

9 files changed

+140
-145
lines changed

9 files changed

+140
-145
lines changed

emscripten.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,7 @@ def setup_function_pointers(function_table_sigs):
14051405

14061406

14071407
def create_basic_funcs(function_table_sigs, invoke_function_names):
1408-
basic_funcs = ['abort', 'assert', 'enlargeMemory', 'getTotalMemory', 'setTempRet0', 'getTempRet0']
1408+
basic_funcs = ['abort', 'assert', 'setTempRet0', 'getTempRet0']
14091409
if shared.Settings.ABORTING_MALLOC:
14101410
basic_funcs += ['abortOnCannotGrowMemory']
14111411
if shared.Settings.STACK_OVERFLOW_CHECK:
@@ -2136,7 +2136,7 @@ def create_em_js(forwarded_json, metadata):
21362136

21372137

21382138
def create_sending_wasm(invoke_funcs, jscall_sigs, forwarded_json, metadata):
2139-
basic_funcs = ['assert', 'enlargeMemory', 'getTotalMemory']
2139+
basic_funcs = ['assert']
21402140
if shared.Settings.ABORTING_MALLOC:
21412141
basic_funcs += ['abortOnCannotGrowMemory']
21422142
if shared.Settings.SAFE_HEAP:

site/source/docs/api_reference/preamble.js.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,6 @@ The :ref:`emscripten-memory-model` uses a typed array buffer (``ArrayBuffer``) t
419419
Module['HEAP'] = HEAP;
420420
Module['IHEAP'] = IHEAP;
421421
function alignUp(x, multiple)
422-
function enlargeMemory()
423422
function demangle(func)
424423
function demangleAll(text)
425424
function parseJSFunc(jsfunc)

src/embind/embind.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ var LibraryEmbind = {
728728
'free', 'malloc', '$readLatin1String', '$registerType',
729729
'$simpleReadValueFromPointer'],
730730
_embind_register_std_wstring: function(rawType, charSize, name) {
731-
// nb. do not cache HEAPU16 and HEAPU32, they may be destroyed by enlargeMemory().
731+
// nb. do not cache HEAPU16 and HEAPU32, they may be destroyed by emscripten_resize_heap().
732732
name = readLatin1String(name);
733733
var getHeap, shift;
734734
if (charSize === 2) {

src/fetch-worker.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ var ENVIRONMENT_IS_PTHREAD = true;
4444
var __pthread_is_main_runtime_thread=0;
4545
var DYNAMICTOP_PTR = 0;
4646
var TOTAL_MEMORY = 0;
47-
function enlargeMemory() {
48-
abort('Cannot enlarge memory arrays, since compiling with pthreads support enabled (-s USE_PTHREADS=1).');
49-
}
5047
var nan = NaN;
5148
var inf = Infinity;
5249

src/library.js

Lines changed: 122 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -467,21 +467,129 @@ LibraryManager.library = {
467467
return -1;
468468
},
469469

470+
emscripten_get_heap_size: function() {
471+
return TOTAL_MEMORY;
472+
},
473+
474+
emscripten_resize_heap__deps: ['emscripten_get_heap_size'],
475+
emscripten_resize_heap: function(requestedSize) {
476+
#if USE_PTHREADS
477+
abort('Cannot enlarge memory arrays, since compiling with pthreads support enabled (-s USE_PTHREADS=1).');
478+
#else
479+
#if ALLOW_MEMORY_GROWTH == 0
480+
#if ABORTING_MALLOC
481+
abortOnCannotGrowMemory();
482+
#else
483+
return false; // malloc will report failure
484+
#endif
485+
#else
486+
var oldSize = _emscripten_get_heap_size();
487+
// TOTAL_MEMORY is the current size of the actual array, and DYNAMICTOP is the new top.
488+
#if ASSERTIONS
489+
assert(requestedSize > oldSize); // This function should only ever be called after the ceiling of the dynamic heap has already been bumped to exceed the current total size of the asm.js heap.
490+
#endif
491+
492+
#if EMSCRIPTEN_TRACING
493+
// Report old layout one last time
494+
_emscripten_trace_report_memory_layout();
495+
#endif
496+
497+
var PAGE_MULTIPLE = {{{ getPageSize() }}};
498+
var LIMIT = 2147483648 - PAGE_MULTIPLE; // We can do one page short of 2GB as theoretical maximum.
499+
500+
if (requestedSize > LIMIT) {
501+
#if ASSERTIONS
502+
err('Cannot enlarge memory, asked to go up to ' + requestedSize + ' bytes, but the limit is ' + LIMIT + ' bytes!');
503+
#endif
504+
return false;
505+
}
506+
507+
var MIN_TOTAL_MEMORY = 16777216;
508+
var newSize = Math.max(oldSize, MIN_TOTAL_MEMORY); // So the loop below will not be infinite, and minimum asm.js memory size is 16MB.
509+
510+
while (newSize < requestedSize) { // Keep incrementing the heap size as long as it's less than what is requested.
511+
if (newSize <= 536870912) {
512+
newSize = alignUp(2 * newSize, PAGE_MULTIPLE); // Simple heuristic: double until 1GB...
513+
} else {
514+
// ..., but after that, add smaller increments towards 2GB, which we cannot reach
515+
newSize = Math.min(alignUp((3 * newSize + 2147483648) / 4, PAGE_MULTIPLE), LIMIT);
516+
#if ASSERTIONS
517+
if (newSize === oldSize) {
518+
warnOnce('Cannot ask for more memory since we reached the practical limit in browsers (which is just below 2GB), so the request would have failed. Requesting only ' + TOTAL_MEMORY);
519+
}
520+
#endif
521+
}
522+
}
523+
524+
#if WASM_MEM_MAX != -1
525+
// A limit was set for how much we can grow. We should not exceed that
526+
// (the wasm binary specifies it, so if we tried, we'd fail anyhow). That is,
527+
// if we are at say 64MB, and the max is 100MB, then we should *not* try to
528+
// grow 64->128MB which is the default behavior (doubling), as 128MB will
529+
// fail because of the max limit. Instead, we should only try to grow
530+
// 64->100MB in this example, which has a chance of succeeding (but may
531+
// still fail for another reason, of actually running out of memory).
532+
newSize = Math.min(newSize, {{{ WASM_MEM_MAX }}});
533+
if (newSize == oldSize) {
534+
#if ASSERTIONS
535+
err('Failed to grow the heap from ' + oldSize + ', as we reached the WASM_MEM_MAX limit (' + {{{ WASM_MEM_MAX }}} + ') set during compilation');
536+
#endif
537+
return false;
538+
}
539+
#endif
540+
541+
#if ASSERTIONS
542+
var start = Date.now();
543+
#endif
544+
545+
var replacement = Module['reallocBuffer'](newSize);
546+
if (!replacement || replacement.byteLength != newSize) {
547+
#if ASSERTIONS
548+
err('Failed to grow the heap from ' + oldSize + ' bytes to ' + newSize + ' bytes, not enough memory!');
549+
if (replacement) {
550+
err('Expected to get back a buffer of size ' + newSize + ' bytes, but instead got back a buffer of size ' + replacement.byteLength);
551+
}
552+
#endif
553+
return false;
554+
}
555+
556+
// everything worked
557+
updateGlobalBuffer(replacement);
558+
updateGlobalBufferViews();
559+
560+
TOTAL_MEMORY = newSize;
561+
HEAPU32[DYNAMICTOP_PTR>>2] = requestedSize;
562+
563+
#if ASSERTIONS && !WASM
564+
err('Warning: Enlarging memory arrays, this is not fast! ' + [oldSize, newSize]);
565+
#endif
566+
567+
#if EMSCRIPTEN_TRACING
568+
_emscripten_trace_js_log_message("Emscripten", "Enlarging memory arrays from " + oldSize + " to " + newSize);
569+
// And now report the new layout
570+
_emscripten_trace_report_memory_layout();
571+
#endif
572+
573+
return true;
574+
#endif // ALLOW_MEMORY_GROWTH
575+
#endif // USE_PTHREADS
576+
},
577+
470578
// Implement a Linux-like 'memory area' for our 'process'.
471579
// Changes the size of the memory area by |bytes|; returns the
472580
// address of the previous top ('break') of the memory area
473581
// We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP
474582
sbrk__asm: true,
475583
sbrk__sig: ['ii'],
476-
sbrk__deps: ['__setErrNo'],
584+
sbrk__deps: ['__setErrNo', 'emscripten_get_heap_size', 'emscripten_resize_heap'],
477585
sbrk: function(increment) {
478586
increment = increment|0;
479587
var oldDynamicTop = 0;
480588
var oldDynamicTopOnChange = 0;
481589
var newDynamicTop = 0;
482590
var totalMemory = 0;
483591
#if USE_PTHREADS
484-
totalMemory = getTotalMemory()|0;
592+
totalMemory = _emscripten_get_heap_size()|0;
485593

486594
// Perform a compare-and-swap loop to update the new dynamic top value. This is because
487595
// this function can becalled simultaneously in multiple threads.
@@ -517,11 +625,11 @@ LibraryManager.library = {
517625
return -1;
518626
}
519627

520-
HEAP32[DYNAMICTOP_PTR>>2] = newDynamicTop;
521-
totalMemory = getTotalMemory()|0;
522-
if ((newDynamicTop|0) > (totalMemory|0)) {
523-
if ((enlargeMemory()|0) == 0) {
524-
HEAP32[DYNAMICTOP_PTR>>2] = oldDynamicTop;
628+
totalMemory = _emscripten_get_heap_size()|0;
629+
if ((newDynamicTop|0) <= (totalMemory|0)) {
630+
HEAP32[DYNAMICTOP_PTR>>2] = newDynamicTop|0;
631+
} else {
632+
if ((_emscripten_resize_heap(newDynamicTop|0)|0) == 0) {
525633
___setErrNo({{{ cDefine('ENOMEM') }}});
526634
return -1;
527635
}
@@ -532,12 +640,12 @@ LibraryManager.library = {
532640

533641
brk__asm: true,
534642
brk__sig: ['ii'],
643+
brk__deps: ['__setErrNo', 'emscripten_get_heap_size', 'emscripten_resize_heap'],
535644
brk: function(newDynamicTop) {
536645
newDynamicTop = newDynamicTop|0;
537-
var oldDynamicTop = 0;
538646
var totalMemory = 0;
539647
#if USE_PTHREADS
540-
totalMemory = getTotalMemory()|0;
648+
totalMemory = _emscripten_get_heap_size()|0;
541649
// Asking to increase dynamic top to a too high value? In pthreads builds we cannot
542650
// enlarge memory, so this needs to fail.
543651
if ((newDynamicTop|0) < 0 | (newDynamicTop|0) > (totalMemory|0)) {
@@ -558,13 +666,12 @@ LibraryManager.library = {
558666
return -1;
559667
}
560668

561-
oldDynamicTop = HEAP32[DYNAMICTOP_PTR>>2]|0;
562-
HEAP32[DYNAMICTOP_PTR>>2] = newDynamicTop;
563-
totalMemory = getTotalMemory()|0;
564-
if ((newDynamicTop|0) > (totalMemory|0)) {
565-
if ((enlargeMemory()|0) == 0) {
669+
totalMemory = _emscripten_get_heap_size()|0;
670+
if ((newDynamicTop|0) <= (totalMemory|0)) {
671+
HEAP32[DYNAMICTOP_PTR>>2] = newDynamicTop|0;
672+
} else {
673+
if ((_emscripten_resize_heap(newDynamicTop|0)|0) == 0) {
566674
___setErrNo({{{ cDefine('ENOMEM') }}});
567-
HEAP32[DYNAMICTOP_PTR>>2] = oldDynamicTop;
568675
return -1;
569676
}
570677
}

src/preamble.js

Lines changed: 0 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,6 @@ function stackTrace() {
831831
var PAGE_SIZE = 16384;
832832
var WASM_PAGE_SIZE = {{{ WASM_PAGE_SIZE }}};
833833
var ASMJS_PAGE_SIZE = {{{ ASMJS_PAGE_SIZE }}};
834-
var MIN_TOTAL_MEMORY = 16777216;
835834

836835
function alignUp(x, multiple) {
837836
if (x % multiple > 0) {
@@ -959,110 +958,6 @@ if (!Module['reallocBuffer']) Module['reallocBuffer'] = function(size) {
959958
#endif // ALLOW_MEMORY_GROWTH
960959
#endif // WASM == 0
961960

962-
function enlargeMemory() {
963-
#if USE_PTHREADS
964-
abort('Cannot enlarge memory arrays, since compiling with pthreads support enabled (-s USE_PTHREADS=1).');
965-
#else
966-
#if ALLOW_MEMORY_GROWTH == 0
967-
#if ABORTING_MALLOC
968-
abortOnCannotGrowMemory();
969-
#else
970-
return false; // malloc will report failure
971-
#endif
972-
#else
973-
// TOTAL_MEMORY is the current size of the actual array, and DYNAMICTOP is the new top.
974-
#if ASSERTIONS
975-
assert(HEAP32[DYNAMICTOP_PTR>>2] > TOTAL_MEMORY); // This function should only ever be called after the ceiling of the dynamic heap has already been bumped to exceed the current total size of the asm.js heap.
976-
#endif
977-
978-
#if EMSCRIPTEN_TRACING
979-
// Report old layout one last time
980-
_emscripten_trace_report_memory_layout();
981-
#endif
982-
983-
var PAGE_MULTIPLE = {{{ getPageSize() }}};
984-
var LIMIT = 2147483648 - PAGE_MULTIPLE; // We can do one page short of 2GB as theoretical maximum.
985-
986-
if (HEAP32[DYNAMICTOP_PTR>>2] > LIMIT) {
987-
#if ASSERTIONS
988-
err('Cannot enlarge memory, asked to go up to ' + HEAP32[DYNAMICTOP_PTR>>2] + ' bytes, but the limit is ' + LIMIT + ' bytes!');
989-
#endif
990-
return false;
991-
}
992-
993-
var OLD_TOTAL_MEMORY = TOTAL_MEMORY;
994-
TOTAL_MEMORY = Math.max(TOTAL_MEMORY, MIN_TOTAL_MEMORY); // So the loop below will not be infinite, and minimum asm.js memory size is 16MB.
995-
996-
while (TOTAL_MEMORY < HEAP32[DYNAMICTOP_PTR>>2]) { // Keep incrementing the heap size as long as it's less than what is requested.
997-
if (TOTAL_MEMORY <= 536870912) {
998-
TOTAL_MEMORY = alignUp(2 * TOTAL_MEMORY, PAGE_MULTIPLE); // Simple heuristic: double until 1GB...
999-
} else {
1000-
// ..., but after that, add smaller increments towards 2GB, which we cannot reach
1001-
TOTAL_MEMORY = Math.min(alignUp((3 * TOTAL_MEMORY + 2147483648) / 4, PAGE_MULTIPLE), LIMIT);
1002-
#if ASSERTIONS
1003-
if (TOTAL_MEMORY === OLD_TOTAL_MEMORY) {
1004-
warnOnce('Cannot ask for more memory since we reached the practical limit in browsers (which is just below 2GB), so the request would have failed. Requesting only ' + TOTAL_MEMORY);
1005-
}
1006-
#endif
1007-
}
1008-
}
1009-
1010-
#if WASM_MEM_MAX != -1
1011-
// A limit was set for how much we can grow. We should not exceed that
1012-
// (the wasm binary specifies it, so if we tried, we'd fail anyhow). That is,
1013-
// if we are at say 64MB, and the max is 100MB, then we should *not* try to
1014-
// grow 64->128MB which is the default behavior (doubling), as 128MB will
1015-
// fail because of the max limit. Instead, we should only try to grow
1016-
// 64->100MB in this example, which has a chance of succeeding (but may
1017-
// still fail for another reason, of actually running out of memory).
1018-
TOTAL_MEMORY = Math.min(TOTAL_MEMORY, {{{ WASM_MEM_MAX }}});
1019-
if (TOTAL_MEMORY == OLD_TOTAL_MEMORY) {
1020-
#if ASSERTIONS
1021-
err('Failed to grow the heap from ' + OLD_TOTAL_MEMORY + ', as we reached the WASM_MEM_MAX limit (' + {{{ WASM_MEM_MAX }}} + ') set during compilation');
1022-
#endif
1023-
// restore the state to before this call, we failed
1024-
TOTAL_MEMORY = OLD_TOTAL_MEMORY;
1025-
return false;
1026-
}
1027-
#endif
1028-
1029-
#if ASSERTIONS
1030-
var start = Date.now();
1031-
#endif
1032-
1033-
var replacement = Module['reallocBuffer'](TOTAL_MEMORY);
1034-
if (!replacement || replacement.byteLength != TOTAL_MEMORY) {
1035-
#if ASSERTIONS
1036-
err('Failed to grow the heap from ' + OLD_TOTAL_MEMORY + ' bytes to ' + TOTAL_MEMORY + ' bytes, not enough memory!');
1037-
if (replacement) {
1038-
err('Expected to get back a buffer of size ' + TOTAL_MEMORY + ' bytes, but instead got back a buffer of size ' + replacement.byteLength);
1039-
}
1040-
#endif
1041-
// restore the state to before this call, we failed
1042-
TOTAL_MEMORY = OLD_TOTAL_MEMORY;
1043-
return false;
1044-
}
1045-
1046-
// everything worked
1047-
1048-
updateGlobalBuffer(replacement);
1049-
updateGlobalBufferViews();
1050-
1051-
#if ASSERTIONS && !WASM
1052-
err('Warning: Enlarging memory arrays, this is not fast! ' + [OLD_TOTAL_MEMORY, TOTAL_MEMORY]);
1053-
#endif
1054-
1055-
#if EMSCRIPTEN_TRACING
1056-
_emscripten_trace_js_log_message("Emscripten", "Enlarging memory arrays from " + OLD_TOTAL_MEMORY + " to " + TOTAL_MEMORY);
1057-
// And now report the new layout
1058-
_emscripten_trace_report_memory_layout();
1059-
#endif
1060-
1061-
return true;
1062-
#endif // ALLOW_MEMORY_GROWTH
1063-
#endif // USE_PTHREADS
1064-
}
1065-
1066961
#if ALLOW_MEMORY_GROWTH
1067962
var byteLength;
1068963
try {
@@ -1226,10 +1121,6 @@ HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE;
12261121
}
12271122
#endif
12281123

1229-
function getTotalMemory() {
1230-
return TOTAL_MEMORY;
1231-
}
1232-
12331124
// Endianness check (note: assumes compiler arch was little-endian)
12341125
#if STACK_OVERFLOW_CHECK
12351126
#if USE_PTHREADS

src/settings.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,14 @@ var PROFILING_FUNCS = 0;
688688
// may be slightly misleading, as this is for any JS library element, and not
689689
// just functions. For example, you can include the Browser object by adding
690690
// "$Browser" to this list.
691-
var DEFAULT_LIBRARY_FUNCS_TO_INCLUDE = ['memcpy', 'memset', 'malloc', 'free'];
691+
var DEFAULT_LIBRARY_FUNCS_TO_INCLUDE = [
692+
'memcpy',
693+
'memset',
694+
'malloc',
695+
'free',
696+
'emscripten_get_heap_size', // Used by dynamicAlloc() and -s FETCH=1
697+
'emscripten_resize_heap' // Used by dynamicAlloc() and -s FETCH=1
698+
];
692699

693700
// This list is also used to determine auto-exporting of library dependencies
694701
// (i.e., functions that might be dependencies of JS library functions, that if

0 commit comments

Comments
 (0)