c8c0fd4ca3
This patch compresses the second part of the bytecode prelude which contains the source file name, function name, source-line-number mapping and cell closure information. This part of the prelude now begins with a single varible length unsigned integer which encodes 2 numbers, being the byte-size of the following 2 sections in the header: the "source info section" and the "closure section". After decoding this variable unsigned integer it's possible to skip over one or both of these sections very easily. This scheme saves about 2 bytes for most functions compared to the original format: one in the case that there are no closure cells, and one because padding was eliminated.
94 lines
2.3 KiB
Python
94 lines
2.3 KiB
Python
# test importing of .mpy files with native code (x64 only)
|
|
|
|
import sys, uio
|
|
|
|
try:
|
|
uio.IOBase
|
|
import uos
|
|
uos.mount
|
|
except (ImportError, AttributeError):
|
|
print("SKIP")
|
|
raise SystemExit
|
|
|
|
if not (sys.platform == 'linux' and sys.maxsize > 2 ** 32):
|
|
print("SKIP")
|
|
raise SystemExit
|
|
|
|
|
|
class UserFile(uio.IOBase):
|
|
def __init__(self, data):
|
|
self.data = data
|
|
self.pos = 0
|
|
def read(self):
|
|
return self.data
|
|
def readinto(self, buf):
|
|
n = 0
|
|
while n < len(buf) and self.pos < len(self.data):
|
|
buf[n] = self.data[self.pos]
|
|
n += 1
|
|
self.pos += 1
|
|
return n
|
|
def ioctl(self, req, arg):
|
|
return 0
|
|
|
|
|
|
class UserFS:
|
|
def __init__(self, files):
|
|
self.files = files
|
|
def mount(self, readonly, mksfs):
|
|
pass
|
|
def umount(self):
|
|
pass
|
|
def stat(self, path):
|
|
if path in self.files:
|
|
return (32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
|
raise OSError
|
|
def open(self, path, mode):
|
|
return UserFile(self.files[path])
|
|
|
|
|
|
# these are the test .mpy files
|
|
user_files = {
|
|
# bad architecture
|
|
'/mod0.mpy': b'M\x05\xff\x00\x10',
|
|
|
|
# test loading of viper and asm
|
|
'/mod1.mpy': (
|
|
b'M\x05\x0b\x1f\x20' # header
|
|
|
|
b'\x20' # n bytes, bytecode
|
|
b'\x00\x08\x00\x00\x00\x00' # prelude
|
|
b'\x51' # LOAD_CONST_NONE
|
|
b'\x63' # RETURN_VALUE
|
|
|
|
b'\x02m\x02m\x00\x02' # simple_name, source_file, n_obj, n_raw_code
|
|
|
|
b'\x22' # n bytes, viper code
|
|
b'\x00\x00\x00\x00\x00\x00' # dummy machine code
|
|
b'\x00\x00' # qstr0
|
|
b'\x01\x0c\x0aprint' # n_qstr, qstr0
|
|
b'\x00\x00\x00' # scope_flags, n_obj, n_raw_code
|
|
|
|
b'\x23' # n bytes, asm code
|
|
b'\x00\x00\x00\x00\x00\x00\x00\x00' # dummy machine code
|
|
b'\x00\x00\x00' # scope_flags, n_pos_args, type_sig
|
|
),
|
|
}
|
|
|
|
# create and mount a user filesystem
|
|
uos.mount(UserFS(user_files), '/userfs')
|
|
sys.path.append('/userfs')
|
|
|
|
# import .mpy files from the user filesystem
|
|
for i in range(len(user_files)):
|
|
mod = 'mod%u' % i
|
|
try:
|
|
__import__(mod)
|
|
print(mod, 'OK')
|
|
except ValueError as er:
|
|
print(mod, 'ValueError', er)
|
|
|
|
# unmount and undo path addition
|
|
uos.umount('/userfs')
|
|
sys.path.pop()
|