diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/js-optimizer.js | 27 | ||||
-rw-r--r-- | tools/shared.py | 71 |
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 |