-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Perform JS static allocations at compile time #7850
Changes from all commits
0bdd47b
e5bbc52
afc4c16
ae0bbb5
2e75cd8
4a62b1f
35282e2
30f2ff0
d6b4c00
387034f
b07a654
1c57b5d
fdda39a
de1ad42
8f7ce9c
ecedef6
0338565
6d62a03
a470a71
9d5c349
a07858f
214f936
afbac79
332849f
6d8a2c1
23ec68e
dccd4f1
c6e3ea3
c8aed5d
080820d
4b48ca9
9e44fd6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -527,6 +527,15 @@ def is_int(x): | |
return False | ||
|
||
|
||
def align_memory(addr): | ||
return (addr + 15) & -16 | ||
|
||
|
||
def align_static_bump(metadata): | ||
metadata['staticBump'] = align_memory(metadata['staticBump']) | ||
return metadata['staticBump'] | ||
|
||
|
||
def update_settings_glue(metadata): | ||
if shared.Settings.CYBERDWARF: | ||
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.append("cyberdwarf_Debugger") | ||
|
@@ -581,6 +590,14 @@ def read_proxied_function_signatures(asmConsts): | |
if not shared.Settings.WASM_BACKEND: | ||
shared.Settings.PROXIED_FUNCTION_SIGNATURES = read_proxied_function_signatures(metadata['asmConsts']) | ||
|
||
shared.Settings.STATIC_BUMP = align_static_bump(metadata) | ||
|
||
|
||
def apply_forwarded_data(forwarded_data): | ||
forwarded_json = json.loads(forwarded_data) | ||
# Be aware of JS static allocations | ||
shared.Settings.STATIC_BUMP = forwarded_json['STATIC_BUMP'] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. obviously STATIC_BUMP is preexisting, but it does seem odd to be setting global settings (which usually just come via command-line flags or a certain narrow set of ways to configure) based on this forwarded data. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually does this mean that STATIC_BUMP can now be demoted from a shared setting to something local to emscripten.py? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is slightly odd, yeah, we use Specifically here, this can't be a local var to the file since we do want to use it elsewhere (e.g. when we write the metadata we write this - although I didn't update all those places yet in this PR, to keep it small). |
||
|
||
|
||
def compile_settings(compiler_engine, libraries, temp_files): | ||
# Save settings to a file to work around v8 issue 1579 | ||
|
@@ -596,18 +613,53 @@ def compile_settings(compiler_engine, libraries, temp_files): | |
cwd=path_from_root('src'), env=env) | ||
assert '//FORWARDED_DATA:' in out, 'Did not receive forwarded data in pre output - process failed?' | ||
glue, forwarded_data = out.split('//FORWARDED_DATA:') | ||
|
||
apply_forwarded_data(forwarded_data) | ||
|
||
return glue, forwarded_data | ||
|
||
|
||
def apply_memory(pre, metadata): | ||
# Apply the statically-at-compile-time computed memory locations. | ||
# Note: if RELOCATABLE, then only relative sizes can be computed, and we don't | ||
# actually write out any absolute memory locations ({{{ STACK_BASE }}} | ||
# does not exist, etc.) | ||
|
||
# Memory layout: | ||
# * first the static globals | ||
global_start = shared.Settings.GLOBAL_BASE | ||
static_bump = shared.Settings.STATIC_BUMP | ||
# * then the stack (up on fastcomp, down on upstream) | ||
stack_low = align_memory(global_start + static_bump) | ||
stack_high = align_memory(stack_low + shared.Settings.TOTAL_STACK) | ||
if shared.Settings.WASM_BACKEND: | ||
stack_start = stack_high | ||
stack_max = stack_low | ||
else: | ||
stack_start = stack_low | ||
stack_max = stack_high | ||
# * then dynamic memory begins | ||
dynamic_start = align_memory(stack_high) | ||
|
||
# Write it all out | ||
pre = pre.replace('{{{ STATIC_BUMP }}}', str(static_bump)) | ||
pre = pre.replace('{{{ STACK_BASE }}}', str(stack_start)) | ||
pre = pre.replace('{{{ STACK_MAX }}}', str(stack_max)) | ||
pre = pre.replace('{{{ DYNAMIC_BASE }}}', str(dynamic_start)) | ||
|
||
logger.debug('global_start: %d stack_start: %d, stack_max: %d, dynamic_start: %d, static bump: %d', global_start, stack_start, stack_max, dynamic_start, static_bump) | ||
|
||
return pre | ||
|
||
|
||
def memory_and_global_initializers(pre, metadata, mem_init): | ||
global_initializers = ', '.join('{ func: function() { %s() } }' % i for i in metadata['initializers']) | ||
|
||
if shared.Settings.SIMD == 1: | ||
pre = open(path_from_root(os.path.join('src', 'ecmascript_simd.js'))).read() + '\n\n' + pre | ||
|
||
staticbump = metadata['staticBump'] | ||
while staticbump % 16 != 0: | ||
staticbump += 1 | ||
staticbump = shared.Settings.STATIC_BUMP | ||
|
||
pthread = '' | ||
if shared.Settings.USE_PTHREADS: | ||
pthread = 'if (!ENVIRONMENT_IS_PTHREAD)' | ||
|
@@ -621,8 +673,8 @@ def memory_and_global_initializers(pre, metadata, mem_init): | |
|
||
if shared.Settings.SIDE_MODULE: | ||
pre = pre.replace('GLOBAL_BASE', 'gb') | ||
if shared.Settings.SIDE_MODULE or shared.Settings.WASM: | ||
pre = pre.replace('{{{ STATIC_BUMP }}}', str(staticbump)) | ||
|
||
pre = apply_memory(pre, metadata) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is the new logic still correct for sidemodules and/or !WASM? I don't see any mentions of those. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Identical for wasm and !wasm. In a side module we wouldn't have STACK_BASE etc., as the location is determined at runtime anyhow (by the dynamic loader). So maybe it's a little odd we compute those even though they are not written out. I'll add a comment. |
||
|
||
return pre | ||
|
||
|
@@ -1887,16 +1939,15 @@ def emscript_wasm_backend(infile, outfile, memfile, libraries, compiler_engine, | |
|
||
global_initializers = ', '.join('{ func: function() { %s() } }' % i for i in metadata['initializers']) | ||
|
||
staticbump = metadata['staticBump'] | ||
while staticbump % 16 != 0: | ||
staticbump += 1 | ||
staticbump = shared.Settings.STATIC_BUMP | ||
|
||
pre = pre.replace('STATICTOP = STATIC_BASE + 0;', '''STATICTOP = STATIC_BASE + %d; | ||
/* global initializers */ %s __ATINIT__.push(%s); | ||
''' % (staticbump, | ||
'if (!ENVIRONMENT_IS_PTHREAD)' if shared.Settings.USE_PTHREADS else '', | ||
global_initializers)) | ||
|
||
pre = pre.replace('{{{ STATIC_BUMP }}}', str(staticbump)) | ||
pre = apply_memory(pre, metadata) | ||
|
||
# merge forwarded data | ||
shared.Settings.EXPORTED_FUNCTIONS = forwarded_json['EXPORTED_FUNCTIONS'] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,7 @@ var LibraryPThread = { | |
// mainThreadBlock: undefined, | ||
initMainThreadBlock: function() { | ||
if (ENVIRONMENT_IS_PTHREAD) return undefined; | ||
PThread.mainThreadBlock = allocate({{{ C_STRUCTS.pthread.__size__ }}}, "i32*", ALLOC_STATIC); | ||
PThread.mainThreadBlock = {{{ makeStaticAlloc(C_STRUCTS.pthread.__size__) }}}; | ||
|
||
for (var i = 0; i < {{{ C_STRUCTS.pthread.__size__ }}}/4; ++i) HEAPU32[PThread.mainThreadBlock/4+i] = 0; | ||
|
||
|
@@ -34,7 +34,7 @@ var LibraryPThread = { | |
{{{ makeSetValue('headPtr', 0, 'headPtr', 'i32') }}}; | ||
|
||
// Allocate memory for thread-local storage. | ||
var tlsMemory = allocate({{{ cDefine('PTHREAD_KEYS_MAX') }}} * 4, "i32*", ALLOC_STATIC); | ||
var tlsMemory = {{{ makeStaticAlloc(cDefine('PTHREAD_KEYS_MAX') * 4) }}}; | ||
for (var i = 0; i < {{{ cDefine('PTHREAD_KEYS_MAX') }}}; ++i) HEAPU32[tlsMemory/4+i] = 0; | ||
Atomics.store(HEAPU32, (PThread.mainThreadBlock + {{{ C_STRUCTS.pthread.tsd }}} ) >> 2, tlsMemory); // Init thread-local-storage memory array. | ||
Atomics.store(HEAPU32, (PThread.mainThreadBlock + {{{ C_STRUCTS.pthread.tid }}} ) >> 2, PThread.mainThreadBlock); // Main thread ID. | ||
|
@@ -54,7 +54,7 @@ var LibraryPThread = { | |
|
||
#if PTHREADS_PROFILING | ||
createProfilerBlock: function(pthreadPtr) { | ||
var profilerBlock = (pthreadPtr == PThread.mainThreadBlock) ? allocate({{{ C_STRUCTS.thread_profiler_block.__size__ }}}, "i32*", ALLOC_STATIC) : _malloc({{{ C_STRUCTS.thread_profiler_block.__size__ }}}); | ||
var profilerBlock = (pthreadPtr == PThread.mainThreadBlock) ? {{{ makeStaticAlloc(C_STRUCTS.thread_profiler_block.__size__) }}} : _malloc({{{ C_STRUCTS.thread_profiler_block.__size__ }}}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (it looks like the above three code blocks have historically overallocated 4x the number of bytes needed, but this change fixes that) |
||
Atomics.store(HEAPU32, (pthreadPtr + {{{ C_STRUCTS.pthread.profilerBlock }}} ) >> 2, profilerBlock); | ||
|
||
// Zero fill contents at startup. | ||
|
@@ -400,7 +400,6 @@ var LibraryPThread = { | |
#endif | ||
tempDoublePtr: tempDoublePtr, | ||
TOTAL_MEMORY: TOTAL_MEMORY, | ||
STATICTOP: STATICTOP, | ||
DYNAMIC_BASE: DYNAMIC_BASE, | ||
DYNAMICTOP_PTR: DYNAMICTOP_PTR, | ||
PthreadWorkerInit: PthreadWorkerInit | ||
|
@@ -529,7 +528,7 @@ var LibraryPThread = { | |
}, | ||
|
||
_num_logical_cores__deps: ['emscripten_force_num_logical_cores'], | ||
_num_logical_cores: '; if (ENVIRONMENT_IS_PTHREAD) __num_logical_cores = PthreadWorkerInit.__num_logical_cores; else { PthreadWorkerInit.__num_logical_cores = __num_logical_cores = allocate(1, "i32*", ALLOC_STATIC); HEAPU32[__num_logical_cores>>2] = navigator["hardwareConcurrency"] || ' + {{{ PTHREAD_HINT_NUM_CORES }}} + '; }', | ||
_num_logical_cores: '; if (ENVIRONMENT_IS_PTHREAD) __num_logical_cores = PthreadWorkerInit.__num_logical_cores; else { PthreadWorkerInit.__num_logical_cores = __num_logical_cores = {{{ makeStaticAlloc(4) }}}; HEAPU32[__num_logical_cores>>2] = navigator["hardwareConcurrency"] || ' + {{{ PTHREAD_HINT_NUM_CORES }}} + '; }', | ||
|
||
emscripten_has_threading_support: function() { | ||
return typeof SharedArrayBuffer !== 'undefined'; | ||
|
@@ -1031,7 +1030,7 @@ var LibraryPThread = { | |
}, | ||
|
||
// Stores the memory address that the main thread is waiting on, if any. | ||
_main_thread_futex_wait_address: '; if (ENVIRONMENT_IS_PTHREAD) __main_thread_futex_wait_address = PthreadWorkerInit.__main_thread_futex_wait_address; else PthreadWorkerInit.__main_thread_futex_wait_address = __main_thread_futex_wait_address = allocate(1, "i32*", ALLOC_STATIC)', | ||
_main_thread_futex_wait_address: '; if (ENVIRONMENT_IS_PTHREAD) __main_thread_futex_wait_address = PthreadWorkerInit.__main_thread_futex_wait_address; else PthreadWorkerInit.__main_thread_futex_wait_address = __main_thread_futex_wait_address = {{{ makeStaticAlloc(4) }}}', | ||
|
||
// Returns 0 on success, or one of the values -ETIMEDOUT, -EWOULDBLOCK or -EINVAL on error. | ||
emscripten_futex_wait__deps: ['_main_thread_futex_wait_address', 'emscripten_main_thread_process_queued_calls'], | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find hex literals more readable for bitwise operations but YMMV