809
809
self.attrs['DISABLE_EXCEPTION_CATCHING'] = 1
810
810
self.attrs['RELOOP'] = 1
811
811
self.attrs['ALIASING_FUNCTION_POINTERS'] = 1
813
# Aside from these, -O3 also runs closure compiler and llvm lto
814
self.attrs['FORCE_ALIGNED_MEMORY'] = 1
815
self.attrs['DOUBLE_MODE'] = 0
816
self.attrs['PRECISE_I64_MATH'] = 0
817
if noisy: logging.warning('Applying some potentially unsafe optimizations! (Use -O2 if this fails.)')
819
813
def __getattr__(self, attr):
820
814
if attr in self.attrs:
1568
1562
chunkify = cache.chunkify
1571
memory_initializer_pattern = '/\* memory initializer \*/ allocate\(([\d,\.concat\(\)\[\]\\n ]+)"i8", ALLOC_NONE, ([\dRuntime\.GLOBAL_BASEH+]+)\)'
1565
memory_initializer_pattern = '/\* memory initializer \*/ allocate\(\[([\d, ]+)\], "i8", ALLOC_NONE, ([\d+Runtime\.GLOBAL_BASEH]+)\);'
1572
1566
no_memory_initializer_pattern = '/\* no memory initializer \*/'
1574
1568
memory_staticbump_pattern = 'STATICTOP = STATIC_BASE \+ (\d+);'
1652
1646
while x % by != 0: x += 1
1649
INITIALIZER_CHUNK_SIZE = 10240
1652
def collect_initializers(src):
1655
for init in re.finditer(JS.memory_initializer_pattern, src):
1656
contents = init.group(1).split(',')
1657
offset = sum([int(x) if x[0] != 'R' else 0 for x in init.group(2).split('+')])
1658
ret.append((offset, contents))
1659
assert offset > max_offset
1664
def split_initializer(contents):
1665
# 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
1668
maxx = JS.INITIALIZER_CHUNK_SIZE
1672
if i - start >= maxx or (i > start and i == l):
1673
#print >> sys.stderr, 'new', start, i-start
1674
ret.append((start, contents[start:i]))
1677
if contents[i] != '0':
1680
# look for a sequence of zeros
1682
while j < l and contents[j] == '0': j += 1
1683
if j-i > maxx/10 or j-start >= maxx:
1684
#print >> sys.stderr, 'skip', start, i-start, j-start
1685
ret.append((start, contents[start:i])) # skip over the zeros starting at i and ending at j
1691
def replace_initializers(src, inits):
1695
if not State.first: return ''
1696
# write out all the new initializers in place of the first old one
1699
offset, contents = init
1700
return '/* memory initializer */ allocate([%s], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE%s);' % (
1702
'' if offset == 0 else ('+%d' % offset)
1704
return '\n'.join(map(gen_init, inits))
1705
return re.sub(JS.memory_initializer_pattern, rep, src)
1708
def optimize_initializer(src):
1709
inits = JS.collect_initializers(src)
1710
if len(inits) == 0: return None
1711
assert len(inits) == 1
1713
offset, contents = init
1714
assert offset == 0 # offset 0, singleton
1715
if len(contents) <= JS.INITIALIZER_CHUNK_SIZE: return None
1716
return JS.replace_initializers(src, JS.split_initializer(contents))
1655
1718
# Compression of code and data for smaller downloads
1656
1719
class Compression: