mirror of
https://github.com/python/cpython.git
synced 2025-07-19 01:05:26 +00:00
bpo-45850: Implement deep-freeze on Windows (#29648)
Implement changes to build with deep-frozen modules on Windows. Note that we now require Python 3.10 as the "bootstrap" or "host" Python. This causes a modest startup speed (around 7%) on Windows.
This commit is contained in:
parent
4d6c0c0cce
commit
1037ca5a8e
9 changed files with 500 additions and 24 deletions
|
@ -1,13 +1,16 @@
|
|||
import argparse
|
||||
import ast
|
||||
import builtins
|
||||
import collections
|
||||
import contextlib
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import time
|
||||
import types
|
||||
import typing
|
||||
|
||||
import umarshal
|
||||
|
||||
verbose = False
|
||||
|
||||
|
||||
|
@ -55,7 +58,8 @@ def get_localsplus_counts(code: types.CodeType,
|
|||
nplaincellvars += 1
|
||||
elif kind & CO_FAST_FREE:
|
||||
nfreevars += 1
|
||||
assert nlocals == len(code.co_varnames) == code.co_nlocals
|
||||
assert nlocals == len(code.co_varnames) == code.co_nlocals, \
|
||||
(nlocals, len(code.co_varnames), code.co_nlocals)
|
||||
assert ncellvars == len(code.co_cellvars)
|
||||
assert nfreevars == len(code.co_freevars)
|
||||
assert len(names) == nlocals + nplaincellvars + nfreevars
|
||||
|
@ -274,14 +278,7 @@ class Printer:
|
|||
self.write(item + ",")
|
||||
return f"& {name}._object.ob_base.ob_base"
|
||||
|
||||
def generate_int(self, name: str, i: int) -> str:
|
||||
maxint = sys.maxsize
|
||||
if maxint == 2**31 - 1:
|
||||
digit = 2**15
|
||||
elif maxint == 2**63 - 1:
|
||||
digit = 2**30
|
||||
else:
|
||||
assert False, f"What int size is this system?!? {maxint=}"
|
||||
def _generate_int_for_bits(self, name: str, i: int, digit: int) -> None:
|
||||
sign = -1 if i < 0 else 0 if i == 0 else +1
|
||||
i = abs(i)
|
||||
digits: list[int] = []
|
||||
|
@ -298,6 +295,20 @@ class Printer:
|
|||
if digits:
|
||||
ds = ", ".join(map(str, digits))
|
||||
self.write(f".ob_digit = {{ {ds} }},")
|
||||
|
||||
def generate_int(self, name: str, i: int) -> str:
|
||||
if abs(i) < 2**15:
|
||||
self._generate_int_for_bits(name, i, 2**15)
|
||||
else:
|
||||
connective = "if"
|
||||
for bits_in_digit in 15, 30:
|
||||
self.write(f"#{connective} PYLONG_BITS_IN_DIGIT == {bits_in_digit}")
|
||||
self._generate_int_for_bits(name, i, 2**bits_in_digit)
|
||||
connective = "elif"
|
||||
self.write("#else")
|
||||
self.write('#error "PYLONG_BITS_IN_DIGIT should be 15 or 30"')
|
||||
self.write("#endif")
|
||||
# If neither clause applies, it won't compile
|
||||
return f"& {name}.ob_base.ob_base"
|
||||
|
||||
def generate_float(self, name: str, x: float) -> str:
|
||||
|
@ -326,7 +337,7 @@ class Printer:
|
|||
return self.cache[key]
|
||||
self.misses += 1
|
||||
match obj:
|
||||
case types.CodeType() as code:
|
||||
case types.CodeType() | umarshal.Code() as code:
|
||||
val = self.generate_code(name, code)
|
||||
case tuple(t):
|
||||
val = self.generate_tuple(name, t)
|
||||
|
@ -367,8 +378,31 @@ _Py_get_%%NAME%%_toplevel(void)
|
|||
}
|
||||
"""
|
||||
|
||||
FROZEN_COMMENT = "/* Auto-generated by Programs/_freeze_module.c */"
|
||||
|
||||
FROZEN_DATA_LINE = r"\s*(\d+,\s*)+\s*"
|
||||
|
||||
|
||||
def is_frozen_header(source: str) -> bool:
|
||||
return source.startswith(FROZEN_COMMENT)
|
||||
|
||||
|
||||
def decode_frozen_data(source: str) -> types.CodeType:
|
||||
lines = source.splitlines()
|
||||
while lines and re.match(FROZEN_DATA_LINE, lines[0]) is None:
|
||||
del lines[0]
|
||||
while lines and re.match(FROZEN_DATA_LINE, lines[-1]) is None:
|
||||
del lines[-1]
|
||||
values: tuple[int, ...] = ast.literal_eval("".join(lines))
|
||||
data = bytes(values)
|
||||
return umarshal.loads(data)
|
||||
|
||||
|
||||
def generate(source: str, filename: str, modname: str, file: typing.TextIO) -> None:
|
||||
code = compile(source, filename, "exec")
|
||||
if is_frozen_header(source):
|
||||
code = decode_frozen_data(source)
|
||||
else:
|
||||
code = compile(source, filename, "exec")
|
||||
printer = Printer(file)
|
||||
printer.generate("toplevel", code)
|
||||
printer.write("")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue