Store memory initialization in string literal if requested

With “--memory-init-file 0 -s MEM_INIT_METHOD=2” on the command line, the
generated JavaScript file will contain a string literal representing the
initial content of the memory buffer.

The MEM_INIT_METHOD defaults to 0 but gets set to 1 if --memory-init-file is
being used.  Setting it to 1 without --memory-init-file will cause an error.
That way, we can use the setting in the postamble, without too many changes
in other places.

Since memory is initialized to all zero, trailing zeros can be omitted.
This change affects the file-based initialization as well.
This commit is contained in:
Martin von Gagern 2015-05-28 20:51:34 +02:00
Родитель 92094e41a6
Коммит 8f44c9f77a
5 изменённых файлов: 46 добавлений и 10 удалений

20
emcc
Просмотреть файл

@ -1289,6 +1289,10 @@ try:
# Emscripten
logging.debug('LLVM => JS')
extra_args = [] if not js_libraries else ['--libraries', ','.join(map(os.path.abspath, js_libraries))]
if memory_init_file:
shared.Settings.MEM_INIT_METHOD = 1
elif shared.Settings.MEM_INIT_METHOD == 1:
shared.Settings.MEM_INIT_METHOD = 0
final = shared.Building.emscripten(final, append_ext=False, extra_args=extra_args)
if DEBUG: save_intermediate('original')
@ -1340,14 +1344,26 @@ try:
js_transform_tempfiles = [final]
if memory_init_file:
if memory_init_file or shared.Settings.MEM_INIT_METHOD == 2:
memfile = target + '.mem'
shared.try_delete(memfile)
def repl(m):
# handle chunking of the memory initializer
s = m.groups(0)[0]
if len(s) == 0 and not shared.Settings.EMTERPRETIFY: return m.group(0) # emterpreter must have a mem init file; otherwise, don't emit 0-size ones
open(memfile, 'wb').write(''.join(map(lambda x: chr(int(x or '0')), s.split(','))))
membytes = [int(x or '0') for x in s.split(',')]
if not shared.Settings.EMTERPRETIFY:
while membytes and membytes[-1] == 0:
membytes.pop()
if not membytes:
return '';
membytes = ''.join(map(chr, membytes))
if not memory_init_file:
s = repr(membytes)
hex_to_octal = lambda x: '\\%o' % int(x.group(1), 16)
s = re.sub(r'\\x([0-1][0-9A-Fa-f])(?:(?=[^0-9])|$)', hex_to_octal, s)
return 'var memoryInitializer = %s;' % s
open(memfile, 'wb').write(membytes)
if DEBUG:
# Copy into temp dir as well, so can be run there too
shared.safe_copy(memfile, os.path.join(shared.get_emscripten_temp_dir(), os.path.basename(memfile)))

Просмотреть файл

@ -1,6 +1,16 @@
// === Auto-generated postamble setup entry stuff ===
#if MEM_INIT_METHOD == 2
#if USE_PTHREADS
if (memoryInitializer && !ENVIRONMENT_IS_PTHREAD) (function(s) {
#else
if (memoryInitializer) (function(s) {
#endif
for (var i = 0; i < s.length; ++i) HEAPU8[STATIC_BASE + i] = s.charCodeAt(i);
})(memoryInitializer);
#else
#if MEM_INIT_METHOD == 1
#if USE_PTHREADS
if (memoryInitializer && !ENVIRONMENT_IS_PTHREAD) {
#else
@ -52,6 +62,8 @@ if (memoryInitializer) {
}
}
}
#endif
#endif
function ExitStatus(status) {
this.name = "ExitStatus";

Просмотреть файл

@ -35,6 +35,11 @@ var INVOKE_RUN = 1; // Whether we will run the main() function. Disable if you e
// can do with Module.callMain(), with an optional parameter of commandline args).
var NO_EXIT_RUNTIME = 0; // If set, the runtime is not quit when main() completes (allowing code to
// run afterwards, for example from the browser main event loop).
var MEM_INIT_METHOD = 0; // How to represent the initial memory content.
// 0: keep array literal representing the initial memory data
// 1: create a *.mem file containing the binary data of the initial memory;
// use the --memory-init-file command line switch to select this method
// 2: embed a string literal representing that initial memory data
var TOTAL_STACK = 5*1024*1024; // The total stack size. There is no way to enlarge the stack, so this
// value must be large enough for the program's requirements. If
// assertions are on, we will assert on not exceeding this, otherwise,

Просмотреть файл

@ -62,6 +62,14 @@ class RunnerCore(unittest.TestCase):
def is_emterpreter(self):
return False
def uses_memory_init_file(self):
if self.emcc_args is None:
return None
elif '--memory-init-file' in self.emcc_args:
return int(self.emcc_args[self.emcc_args.index('--memory-init-file')+1])
else:
return ('-O2' in self.emcc_args or '-O3' in self.emcc_args or '-Oz' in self.emcc_args) and not Settings.SIDE_MODULE
def setUp(self):
Settings.reset()
self.banned_js_engines = []
@ -252,16 +260,10 @@ class RunnerCore(unittest.TestCase):
output_processor(open(filename + '.o.js').read())
if self.emcc_args is not None:
if '--memory-init-file' in self.emcc_args:
memory_init_file = int(self.emcc_args[self.emcc_args.index('--memory-init-file')+1])
else:
memory_init_file = ('-O2' in self.emcc_args or '-O3' in self.emcc_args or '-Oz' in self.emcc_args) and not Settings.SIDE_MODULE
src = open(filename + '.o.js').read()
if memory_init_file:
if self.uses_memory_init_file():
# side memory init file, or an empty one in the js
assert ('/* memory initializer */' not in src) or ('/* memory initializer */ allocate([]' in src)
else:
assert 'memory initializer */' in src or '/*' not in src # memory initializer comment, or cleaned-up source with no comments
def validate_asmjs(self, err):
if 'uccessfully compiled asm.js code' in err and 'asm.js link error' not in err:

Просмотреть файл

@ -4549,7 +4549,7 @@ def process(filename):
try_delete(mem_file)
self.do_run(src, ('size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\n5 bytes to dev/null: 5\nok.\n \ntexte\n', 'size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\ntexte\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\n5 bytes to dev/null: 5\nok.\n'),
post_build=post, extra_emscripten_args=['-H', 'libc/fcntl.h'])
if '-O2' in self.emcc_args:
if self.uses_memory_init_file():
assert os.path.exists(mem_file)
def test_files_m(self):
@ -7387,6 +7387,7 @@ asm2f = make_run("asm2f", compiler=CLANG, emcc_args=["-Oz", "-s", "PRECISE_F32=1
asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "-s", "SAFE_HEAP=1"])
asm1i = make_run("asm1i", compiler=CLANG, emcc_args=["-O1", '-s', 'EMTERPRETIFY=1'])
asm3i = make_run("asm3i", compiler=CLANG, emcc_args=["-O3", '-s', 'EMTERPRETIFY=1'])
asm2m = make_run("asm2m", compiler=CLANG, emcc_args=["-O2", "--memory-init-file", "0", "-s", "MEM_INIT_METHOD=2"])
# Legacy test modes -
asm2nn = make_run("asm2nn", compiler=CLANG, emcc_args=["-O2"], env={"EMCC_NATIVE_OPTIMIZER": "0"})