aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-06-25 17:49:28 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-07-03 15:31:03 -0700
commit20e81c40735a5c98672900d3793f1cc8452b2471 (patch)
treec7e5c4badba7e3aa6b7d28c4bdd7233a3b7954b3
parent8bd809c849bdce4533c0062010e0c88fc1b0d467 (diff)
begin work on memory relocation
-rw-r--r--emlink.py31
-rw-r--r--src/parseTools.js7
-rwxr-xr-xtests/runner.py2
-rw-r--r--tools/js-optimizer.js2
-rw-r--r--tools/shared.py8
5 files changed, 43 insertions, 7 deletions
diff --git a/emlink.py b/emlink.py
index cb1bcc25..06ef0062 100644
--- a/emlink.py
+++ b/emlink.py
@@ -12,7 +12,7 @@ Note that the output file can be used as a main module, so you can link multiple
side modules into a main module that way.
'''
-import os, subprocess, sys
+import os, subprocess, sys, re
from tools import shared
from tools import js_optimizer
@@ -36,6 +36,19 @@ class AsmModule():
self.end_funcs = self.js.rfind(js_optimizer.end_funcs_marker)
self.end_asm = self.js.rfind(js_optimizer.end_asm_marker)
+ self.pre = self.js[:self.start_asm]
+
+ # heap initializer
+ mem_init = re.search(shared.JS.memory_initializer_pattern, self.pre)
+ if mem_init:
+ self.mem_init_full_js = mem_init.group(0)
+ self.mem_init_js = mem_init.groups(0)[0][:-2]
+ self.mem_init_size = self.mem_init_js.count(',') + self.mem_init_js.count('concat') # XXX add testing for large and small ones
+ else:
+ self.mem_init_js = ''
+ self.mem_init_size = 0
+ #print >> sys.stderr, self.mem_init_js
+
# imports
self.imports_js = self.js[self.start_asm:self.start_funcs]
self.imports = [m.group(0) for m in js_optimizer.import_sig.finditer(self.imports_js)]
@@ -54,9 +67,14 @@ class AsmModule():
def relocate_into(self, main):
# heap initializer TODO
+ concat = '.concat(' if main.mem_init_js and self.mem_init_js else ''
+ end = ')' if main.mem_init_js and self.mem_init_js else ''
+ allocation = main.mem_init_js + concat + self.mem_init_js + end
+ if allocation:
+ full_allocation = '/* memory initializer */ allocate(' + allocation + ', "i8", ALLOC_NONE, Runtime.GLOBAL_BASE)'
+ main.pre = re.sub(shared.JS.memory_initializer_pattern if main.mem_init_js else shared.JS.no_memory_initializer_pattern, full_allocation, main.pre, count=1)
# global initializers TODO
- shared.JS.memory_initializer_pattern
# imports
main_imports = set(main.imports)
@@ -72,7 +90,12 @@ class AsmModule():
rep += '_'
replacements[func] = rep
- temp = shared.Building.js_optimizer(self.filename, ['asm', 'relocate'], extra_info={ 'replacements': replacements })
+ temp = shared.Building.js_optimizer(self.filename, ['asm', 'relocate'], extra_info={
+ 'replacements': replacements,
+ 'fBase': 0,
+ 'hBase': shared.JS.align(main.mem_init_size, 8)
+ })
+ #print >> sys.stderr, 'relocated side into', temp
relocated_funcs = AsmModule(temp)
shared.try_delete(temp)
main.extra_funcs_js = relocated_funcs.funcs_js.replace(js_optimizer.start_funcs_marker, '\n')
@@ -83,7 +106,7 @@ class AsmModule():
def write(self, out):
f = open(out, 'w')
- f.write(self.js[:self.start_asm])
+ f.write(self.pre)
f.write(self.imports_js)
f.write(self.funcs_js)
f.write(self.extra_funcs_js)
diff --git a/src/parseTools.js b/src/parseTools.js
index 6bc0b7ea..2b143697 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -492,7 +492,9 @@ function makeGlobalUse(ident) {
UNINDEXABLE_GLOBALS[ident] = 1;
return ident;
}
- return (Runtime.GLOBAL_BASE + index).toString();
+ var ret = (Runtime.GLOBAL_BASE + index).toString();
+ if (SIDE_MODULE) ret = '(H_BASE+' + ret + ')';
+ return ret;
}
return ident;
}
@@ -1627,6 +1629,9 @@ function makePointer(slab, pos, allocator, type, ptr, finalMemoryInitialization)
// writing out into memory, without a normal allocation. We put all of these into a single big chunk.
assert(typeof slab == 'object');
assert(slab.length % QUANTUM_SIZE == 0, slab.length); // must be aligned already
+ if (SIDE_MODULE && typeof ptr == 'string') {
+ ptr = parseInt(ptr.substring(ptr.indexOf('+'), ptr.length-1)); // parse into (H_BASE+X)
+ }
var offset = ptr - Runtime.GLOBAL_BASE;
for (var i = 0; i < slab.length; i++) {
memoryInitialization[offset + i] = slab[i];
diff --git a/tests/runner.py b/tests/runner.py
index 9afc36d3..7a8ccf6f 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -10611,6 +10611,7 @@ f.close()
def test_static_link(self):
def test(main, side, first=True):
+ #t = main ; main = side ; side = t
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(main)
open(os.path.join(self.get_dir(), 'side.cpp'), 'w').write(side)
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'side.cpp'), '-o', 'side.js', '-s', 'SIDE_MODULE=1', '-O2']).communicate()
@@ -10621,6 +10622,7 @@ f.close()
out = run_js('together.js', engine=SPIDERMONKEY_ENGINE, stderr=PIPE, full_output=True)
self.assertContained('side says 11.', out)
self.validate_asmjs(out)
+ #if first: test(side, main, False) # test reverse order
test('''
#include <stdio.h>
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 85171a02..f382496f 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -2760,7 +2760,7 @@ function relocate(ast) {
} else if (node[2][1] == 'H_BASE') {
base = hBase;
}
- if (base) {
+ if (base !== null) {
var other = node[3];
if (other[0] == 'num') {
other[1] += base;
diff --git a/tools/shared.py b/tools/shared.py
index bc1177b2..1d70fcab 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -1352,10 +1352,16 @@ chunkify = cache.chunkify
class JS:
memory_initializer_pattern = '/\* memory initializer \*/ allocate\(([\d,\.concat\(\)\[\]\\n ]+)"i8", ALLOC_NONE, Runtime\.GLOBAL_BASE\)'
+ no_memory_initializer_pattern = '/\* no memory initializer \*/'
@staticmethod
def to_nice_ident(ident): # limited version of the JS function toNiceIdent
- return ident.replace('%', '$').replace('@', '_');
+ return ident.replace('%', '$').replace('@', '_')
+
+ @staticmethod
+ def align(x, by):
+ while x % by != 0: x += 1
+ return x
# Compression of code and data for smaller downloads
class Compression: