aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/js-optimizer.js27
-rw-r--r--tools/shared.py71
2 files changed, 88 insertions, 10 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index fa59dbec..6d65f3e7 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -3951,7 +3951,7 @@ function safeHeap(ast) {
return ['call', ['name', 'SAFE_HEAP_STORE'], [ptr, makeAsmCoercion(value, ASM_INT), ['num', 4], ['num', '0']]];
}
case 'HEAPF32': {
- return ['call', ['name', 'SAFE_HEAP_STORE'], [ptr, makeAsmCoercion(value, ASM_FLOAT), ['num', 4], ['num', '1']]];
+ return ['call', ['name', 'SAFE_HEAP_STORE'], [ptr, makeAsmCoercion(value, ASM_DOUBLE), ['num', 4], ['num', '1']]];
}
case 'HEAPF64': {
return ['call', ['name', 'SAFE_HEAP_STORE'], [ptr, makeAsmCoercion(value, ASM_DOUBLE), ['num', 8], ['num', '1']]];
@@ -3965,20 +3965,29 @@ function safeHeap(ast) {
var ptr = fixPtr(node[2], heap);
// SAFE_HEAP_LOAD(ptr, bytes, isFloat)
switch (heap) {
- case 'HEAP8': case 'HEAPU8': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0']]], ASM_INT);
+ case 'HEAP8': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0'], ['num', '0']]], ASM_INT);
}
- case 'HEAP16': case 'HEAPU16': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0']]], ASM_INT);
+ case 'HEAPU8': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0'], ['num', '1']]], ASM_INT);
}
- case 'HEAP32': case 'HEAPU32': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0']]], ASM_INT);
+ case 'HEAP16': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0'], ['num', '0']]], ASM_INT);
+ }
+ case 'HEAPU16': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0'], ['num', '1']]], ASM_INT);
+ }
+ case 'HEAP32': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0'], ['num', '0']]], ASM_INT);
+ }
+ case 'HEAPU32': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0'], ['num', '1']]], ASM_INT);
}
case 'HEAPF32': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '1']]], ASM_FLOAT);
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '1'], ['num', '0']]], ASM_DOUBLE);
}
case 'HEAPF64': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 8], ['num', '1']]], ASM_DOUBLE);
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 8], ['num', '1'], ['num', '0']]], ASM_DOUBLE);
}
default: throw 'bad heap ' + heap;
}
diff --git a/tools/shared.py b/tools/shared.py
index bb50350d..e05a5f7a 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -1568,7 +1568,7 @@ JCache = cache.JCache(Cache)
chunkify = cache.chunkify
class JS:
- memory_initializer_pattern = '/\* memory initializer \*/ allocate\(([\d,\.concat\(\)\[\]\\n ]+)"i8", ALLOC_NONE, ([\dRuntime\.GLOBAL_BASEH+]+)\)'
+ memory_initializer_pattern = '/\* memory initializer \*/ allocate\(\[([\d, ]+)\], "i8", ALLOC_NONE, ([\d+Runtime\.GLOBAL_BASEH]+)\);'
no_memory_initializer_pattern = '/\* no memory initializer \*/'
memory_staticbump_pattern = 'STATICTOP = STATIC_BASE \+ (\d+);'
@@ -1652,6 +1652,75 @@ class JS:
while x % by != 0: x += 1
return x
+ INITIALIZER_CHUNK_SIZE = 10240
+
+ @staticmethod
+ def collect_initializers(src):
+ ret = []
+ max_offset = -1
+ for init in re.finditer(JS.memory_initializer_pattern, src):
+ contents = init.group(1).split(',')
+ offset = sum([int(x) if x[0] != 'R' else 0 for x in init.group(2).split('+')])
+ ret.append((offset, contents))
+ assert offset > max_offset
+ max_offset = offset
+ return ret
+
+ @staticmethod
+ def split_initializer(contents):
+ # given a memory initializer (see memory_initializer_pattern), split it up into multiple initializers to avoid long runs of zeros or a single overly-large allocator
+ ret = []
+ l = len(contents)
+ maxx = JS.INITIALIZER_CHUNK_SIZE
+ i = 0
+ start = 0
+ while 1:
+ if i - start >= maxx or (i > start and i == l):
+ #print >> sys.stderr, 'new', start, i-start
+ ret.append((start, contents[start:i]))
+ start = i
+ if i == l: break
+ if contents[i] != '0':
+ i += 1
+ else:
+ # look for a sequence of zeros
+ j = i + 1
+ while j < l and contents[j] == '0': j += 1
+ if j-i > maxx/10 or j-start >= maxx:
+ #print >> sys.stderr, 'skip', start, i-start, j-start
+ ret.append((start, contents[start:i])) # skip over the zeros starting at i and ending at j
+ start = j
+ i = j
+ return ret
+
+ @staticmethod
+ def replace_initializers(src, inits):
+ class State:
+ first = True
+ def rep(m):
+ if not State.first: return ''
+ # write out all the new initializers in place of the first old one
+ State.first = False
+ def gen_init(init):
+ offset, contents = init
+ return '/* memory initializer */ allocate([%s], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE%s);' % (
+ ','.join(contents),
+ '' if offset == 0 else ('+%d' % offset)
+ )
+ return '\n'.join(map(gen_init, inits))
+ return re.sub(JS.memory_initializer_pattern, rep, src)
+
+ @staticmethod
+ def optimize_initializer(src):
+ inits = JS.collect_initializers(src)
+ if len(inits) == 0: return None
+ assert len(inits) == 1
+ init = inits[0]
+ offset, contents = init
+ assert offset == 0 # offset 0, singleton
+ if len(contents) <= JS.INITIALIZER_CHUNK_SIZE: return None
+ return JS.replace_initializers(src, JS.split_initializer(contents))
+
# Compression of code and data for smaller downloads
class Compression:
on = False