@@ -555,25 +555,92 @@ def include_and_export(name):
555
555
settings .EXPORTED_RUNTIME_METHODS += ['ExitStatus' ]
556
556
557
557
558
+ def set_initial_memory ():
559
+ user_specified_initial_heap = 'INITIAL_HEAP' in user_settings
560
+
561
+ # INITIAL_HEAP cannot be used when the memory object is created in JS: we don't know
562
+ # the size of static data here and thus the total initial memory size.
563
+ if settings .IMPORTED_MEMORY :
564
+ if user_specified_initial_heap :
565
+ # Some of these could (and should) be implemented.
566
+ exit_with_error ('INITIAL_HEAP is currently not compatible with IMPORTED_MEMORY (which is enabled indirectly via SHARED_MEMORY, RELOCATABLE, ASYNCIFY_LAZY_LOAD_CODE)' )
567
+ # The default for imported memory is to fall back to INITIAL_MEMORY.
568
+ settings .INITIAL_HEAP = - 1
569
+
570
+ if not user_specified_initial_heap :
571
+ # For backwards compatibility, we will only use INITIAL_HEAP by default when the user
572
+ # specified neither INITIAL_MEMORY nor MAXIMUM_MEMORY. Both place an upper bounds on
573
+ # the overall initial linear memory (stack + static data + heap), and we do not know
574
+ # the size of static data at this stage. Setting any non-zero initial heap value in
575
+ # this scenario would risk pushing users over the limit they have set.
576
+ user_specified_initial = settings .INITIAL_MEMORY != - 1
577
+ user_specified_maximum = 'MAXIMUM_MEMORY' in user_settings or 'WASM_MEM_MAX' in user_settings or 'BINARYEN_MEM_MAX' in user_settings
578
+ if user_specified_initial or user_specified_maximum :
579
+ settings .INITIAL_HEAP = - 1
580
+
581
+ # Apply the default if we are going with INITIAL_MEMORY.
582
+ if settings .INITIAL_HEAP == - 1 and settings .INITIAL_MEMORY == - 1 :
583
+ default_setting ('INITIAL_MEMORY' , 16 * 1024 * 1024 )
584
+
585
+ def check_memory_setting (setting ):
586
+ if settings [setting ] % webassembly .WASM_PAGE_SIZE != 0 :
587
+ exit_with_error (f'{ setting } must be a multiple of WebAssembly page size (64KiB), was { settings [setting ]} ' )
588
+ if settings [setting ] >= 2 ** 53 :
589
+ exit_with_error (f'{ setting } must be smaller than 2^53 bytes due to JS Numbers (doubles) being used to hold pointer addresses in JS side' )
590
+
591
+ # Due to the aforementioned lack of knowledge about the static data size, we delegate
592
+ # checking the overall consistency of these settings to wasm-ld.
593
+ if settings .INITIAL_HEAP != - 1 :
594
+ check_memory_setting ('INITIAL_HEAP' )
595
+
596
+ if settings .INITIAL_MEMORY != - 1 :
597
+ check_memory_setting ('INITIAL_MEMORY' )
598
+ if settings .INITIAL_MEMORY < settings .STACK_SIZE :
599
+ exit_with_error (f'INITIAL_MEMORY must be larger than STACK_SIZE, was { settings .INITIAL_MEMORY } (STACK_SIZE={ settings .STACK_SIZE } )' )
600
+
601
+ check_memory_setting ('MAXIMUM_MEMORY' )
602
+ if settings .MEMORY_GROWTH_LINEAR_STEP != - 1 :
603
+ check_memory_setting ('MEMORY_GROWTH_LINEAR_STEP' )
604
+
605
+
606
+ # Set an upper estimate of what MAXIMUM_MEMORY should be. Take note that this value
607
+ # may not be precise, and is only an upper bound of the exact value calculated later
608
+ # by the linker.
558
609
def set_max_memory ():
559
- # When memory growth is disallowed set MAXIMUM_MEMORY equal to INITIAL_MEMORY
610
+ # With INITIAL_HEAP, we only know the lower bound on initial memory size.
611
+ initial_memory_known = settings .INITIAL_MEMORY != - 1
612
+
560
613
if not settings .ALLOW_MEMORY_GROWTH :
561
614
if 'MAXIMUM_MEMORY' in user_settings :
562
615
diagnostics .warning ('unused-command-line-argument' , 'MAXIMUM_MEMORY is only meaningful with ALLOW_MEMORY_GROWTH' )
563
- settings .MAXIMUM_MEMORY = settings .INITIAL_MEMORY
616
+ # Optimization: lower the default maximum memory to initial memory if possible.
617
+ if initial_memory_known :
618
+ settings .MAXIMUM_MEMORY = settings .INITIAL_MEMORY
564
619
620
+ # Automaticaly up the default maximum when the user requested a large minimum.
565
621
if 'MAXIMUM_MEMORY' not in user_settings :
566
- if settings .ALLOW_MEMORY_GROWTH and settings .INITIAL_MEMORY > 2 * 1024 * 1024 * 1024 :
622
+ if settings .ALLOW_MEMORY_GROWTH :
623
+ if any ([settings .INITIAL_HEAP != - 1 and settings .INITIAL_HEAP >= 2 * 1024 * 1024 * 1024 ,
624
+ initial_memory_known and settings .INITIAL_MEMORY > 2 * 1024 * 1024 * 1024 ]):
567
625
settings .MAXIMUM_MEMORY = 4 * 1024 * 1024 * 1024
568
626
569
627
# INITIAL_MEMORY sets a lower bound for MAXIMUM_MEMORY
570
- if settings .INITIAL_MEMORY > settings .MAXIMUM_MEMORY :
628
+ if initial_memory_known and settings .INITIAL_MEMORY > settings .MAXIMUM_MEMORY :
571
629
settings .MAXIMUM_MEMORY = settings .INITIAL_MEMORY
572
630
573
- if settings .MAXIMUM_MEMORY < settings .INITIAL_MEMORY :
631
+ # A similar check for INITIAL_HEAP would not be precise and so is delegated to wasm-ld.
632
+ if initial_memory_known and settings .MAXIMUM_MEMORY < settings .INITIAL_MEMORY :
574
633
exit_with_error ('MAXIMUM_MEMORY cannot be less than INITIAL_MEMORY' )
575
634
576
635
636
+ def inc_initial_memory (delta ):
637
+ # Both INITIAL_HEAP and INITIAL_MEMORY can be set at the same time. Increment both.
638
+ if settings .INITIAL_HEAP != - 1 :
639
+ settings .INITIAL_HEAP += delta
640
+ if settings .INITIAL_MEMORY != - 1 :
641
+ settings .INITIAL_MEMORY += delta
642
+
643
+
577
644
def check_browser_versions ():
578
645
# Map of setting all VM version settings to the minimum version
579
646
# we support.
@@ -1362,18 +1429,10 @@ def phase_linker_setup(options, state, newargs):
1362
1429
'removeRunDependency' ,
1363
1430
]
1364
1431
1365
- def check_memory_setting (setting ):
1366
- if settings [setting ] % webassembly .WASM_PAGE_SIZE != 0 :
1367
- exit_with_error (f'{ setting } must be a multiple of WebAssembly page size (64KiB), was { settings [setting ]} ' )
1368
- if settings [setting ] >= 2 ** 53 :
1369
- exit_with_error (f'{ setting } must be smaller than 2^53 bytes due to JS Numbers (doubles) being used to hold pointer addresses in JS side' )
1432
+ if settings .SHARED_MEMORY or settings .RELOCATABLE or settings .ASYNCIFY_LAZY_LOAD_CODE :
1433
+ settings .IMPORTED_MEMORY = 1
1370
1434
1371
- check_memory_setting ('INITIAL_MEMORY' )
1372
- check_memory_setting ('MAXIMUM_MEMORY' )
1373
- if settings .INITIAL_MEMORY < settings .STACK_SIZE :
1374
- exit_with_error (f'INITIAL_MEMORY must be larger than STACK_SIZE, was { settings .INITIAL_MEMORY } (STACK_SIZE={ settings .STACK_SIZE } )' )
1375
- if settings .MEMORY_GROWTH_LINEAR_STEP != - 1 :
1376
- check_memory_setting ('MEMORY_GROWTH_LINEAR_STEP' )
1435
+ set_initial_memory ()
1377
1436
1378
1437
if settings .EXPORT_ES6 :
1379
1438
if not settings .MODULARIZE :
@@ -1433,9 +1492,6 @@ def check_memory_setting(setting):
1433
1492
(options .shell_path == DEFAULT_SHELL_HTML or options .shell_path == utils .path_from_root ('src/shell_minimal.html' )):
1434
1493
exit_with_error (f'Due to collision in variable name "Module", the shell file "{ options .shell_path } " is not compatible with build options "-sMODULARIZE -sEXPORT_NAME=Module". Either provide your own shell file, change the name of the export to something else to avoid the name collision. (see https://github.com/emscripten-core/emscripten/issues/7950 for details)' )
1435
1494
1436
- if settings .SHARED_MEMORY or settings .RELOCATABLE or settings .ASYNCIFY_LAZY_LOAD_CODE :
1437
- settings .IMPORTED_MEMORY = 1
1438
-
1439
1495
if settings .WASM_BIGINT :
1440
1496
settings .LEGALIZE_JS_FFI = 0
1441
1497
@@ -1496,9 +1552,9 @@ def check_memory_setting(setting):
1496
1552
# These values are designed be an over-estimate of the actual requirements and
1497
1553
# are based on experimentation with different tests/programs under asan and
1498
1554
# lsan.
1499
- settings . INITIAL_MEMORY += 50 * 1024 * 1024
1555
+ inc_initial_memory ( 50 * 1024 * 1024 )
1500
1556
if settings .PTHREADS :
1501
- settings . INITIAL_MEMORY += 50 * 1024 * 1024
1557
+ inc_initial_memory ( 50 * 1024 * 1024 )
1502
1558
1503
1559
if settings .USE_OFFSET_CONVERTER :
1504
1560
if settings .WASM2JS :
@@ -1541,22 +1597,23 @@ def check_memory_setting(setting):
1541
1597
if 'GLOBAL_BASE' in user_settings :
1542
1598
exit_with_error ("ASan does not support custom GLOBAL_BASE" )
1543
1599
1544
- # Increase the TOTAL_MEMORY and shift GLOBAL_BASE to account for
1600
+ # Increase the INITIAL_MEMORY and shift GLOBAL_BASE to account for
1545
1601
# the ASan shadow region which starts at address zero.
1546
1602
# The shadow region is 1/8th the size of the total memory and is
1547
1603
# itself part of the total memory.
1548
1604
# We use the following variables in this calculation:
1549
1605
# - user_mem : memory usable/visible by the user program.
1550
1606
# - shadow_size : memory used by asan for shadow memory.
1551
1607
# - total_mem : the sum of the above. this is the size of the wasm memory (and must be aligned to WASM_PAGE_SIZE)
1552
- user_mem = settings .INITIAL_MEMORY
1553
- if settings .ALLOW_MEMORY_GROWTH :
1554
- user_mem = settings .MAXIMUM_MEMORY
1608
+ user_mem = settings .MAXIMUM_MEMORY
1609
+ if not settings .ALLOW_MEMORY_GROWTH and settings . INITIAL_MEMORY != - 1 :
1610
+ user_mem = settings .INITIAL_MEMORY
1555
1611
1556
1612
# Given the know value of user memory size we can work backwards
1557
1613
# to find the total memory and the shadow size based on the fact
1558
1614
# that the user memory is 7/8ths of the total memory.
1559
1615
# (i.e. user_mem == total_mem * 7 / 8
1616
+ # TODO-Bug?: this does not look to handle 4GB MAXIMUM_MEMORY correctly.
1560
1617
total_mem = user_mem * 8 / 7
1561
1618
1562
1619
# But we might need to re-align to wasm page size
@@ -1569,10 +1626,12 @@ def check_memory_setting(setting):
1569
1626
# We don't need to worry about alignment here. wasm-ld will take care of that.
1570
1627
settings .GLOBAL_BASE = shadow_size
1571
1628
1572
- if not settings .ALLOW_MEMORY_GROWTH :
1573
- settings .INITIAL_MEMORY = total_mem
1574
- else :
1575
- settings .INITIAL_MEMORY += align_to_wasm_page_boundary (shadow_size )
1629
+ # Adjust INITIAL_MEMORY (if needed) to account for the shifted global base.
1630
+ if settings .INITIAL_MEMORY != - 1 :
1631
+ if settings .ALLOW_MEMORY_GROWTH :
1632
+ settings .INITIAL_MEMORY += align_to_wasm_page_boundary (shadow_size )
1633
+ else :
1634
+ settings .INITIAL_MEMORY = total_mem
1576
1635
1577
1636
if settings .SAFE_HEAP :
1578
1637
# SAFE_HEAP instruments ASan's shadow memory accesses.
0 commit comments