@@ -78,6 +78,18 @@ class Config:
7878MP_BC_LOAD_ATTR = 0x1e
7979MP_BC_STORE_ATTR = 0x26
8080
81+ # load opcode names
82+ opcode_names = {}
83+ with open ("../../py/bc0.h" ) as f :
84+ for line in f .readlines ():
85+ if line .startswith ("#define" ):
86+ s = line .split (maxsplit = 3 )
87+ if len (s ) < 3 :
88+ continue
89+ _ , name , value = s [:3 ]
90+ opcode = int (value .strip ("()" ), 0 )
91+ opcode_names [opcode ] = name
92+
8193def make_opcode_format ():
8294 def OC4 (a , b , c , d ):
8395 return a | (b << 2 ) | (c << 4 ) | (d << 6 )
@@ -252,35 +264,48 @@ def freeze(self, parent_name):
252264 i += 1
253265 RawCode .escaped_names .add (self .escaped_name )
254266
267+ sizes = {"bytecode" : 0 , "strings" : 0 , "raw_code_overhead" : 0 , "const_table_overhead" : 0 , "string_overhead" : 0 , "number_overhead" : 0 }
255268 # emit children first
256269 for rc in self .raw_codes :
257- rc .freeze (self .escaped_name + '_' )
270+ subsize = rc .freeze (self .escaped_name + '_' )
271+ for k in sizes :
272+ sizes [k ] += subsize [k ]
273+
258274
259275 # generate bytecode data
260276 print ()
261277 print ('// frozen bytecode for file %s, scope %s%s' % (self .source_file .str , parent_name , self .simple_name .str ))
278+ print ("// bytecode size" , len (self .bytecode ))
262279 print ('STATIC ' , end = '' )
263280 if not config .MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE :
264281 print ('const ' , end = '' )
265282 print ('byte bytecode_data_%s[%u] = {' % (self .escaped_name , len (self .bytecode )))
283+ sizes ["bytecode" ] += len (self .bytecode )
266284 print (' ' , end = '' )
267285 for i in range (self .ip2 ):
268286 print (' 0x%02x,' % self .bytecode [i ], end = '' )
269287 print ()
288+ print (" // simple name" )
270289 print (' ' , self .simple_name .qstr_id , '& 0xff,' , self .simple_name .qstr_id , '>> 8,' )
290+ print (" // source file" )
271291 print (' ' , self .source_file .qstr_id , '& 0xff,' , self .source_file .qstr_id , '>> 8,' )
272292 print (' ' , end = '' )
273293 for i in range (self .ip2 + 4 , self .ip ):
274- print ( ' 0x%02x,' % self .bytecode [i ], end = '' )
294+ opcode = self .bytecode [i ]
275295 print ()
276296 ip = self .ip
277297 while ip < len (self .bytecode ):
278298 f , sz = mp_opcode_format (self .bytecode , ip )
299+ opcode = self .bytecode [ip ]
300+ if opcode in opcode_names :
301+ opcode = opcode_names [opcode ]
302+ else :
303+ opcode = '0x%02x' % opcode
279304 if f == 1 :
280305 qst = self ._unpack_qstr (ip + 1 ).qstr_id
281- print (' ' , '0x%02x,' % self . bytecode [ ip ], qst , ' & 0xff,' , qst , ' >> 8,' )
306+ print (' {}, {} & 0xff, {} >> 8,' . format ( opcode , qst , qst ) )
282307 else :
283- print (' ' , '' .join ('0x%02x, ' % self .bytecode [ip + i ] for i in range (sz )))
308+ print (' {},{}' . format ( opcode , '' .join (' 0x%02x,' % self .bytecode [ip + i ] for i in range (1 , sz ) )))
284309 ip += sz
285310 print ('};' )
286311
@@ -295,9 +320,12 @@ def freeze(self, parent_name):
295320 obj_type = 'mp_type_str'
296321 else :
297322 obj_type = 'mp_type_bytes'
298- print ('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"};'
323+ print ('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"}; // %s '
299324 % (obj_name , obj_type , qstrutil .compute_hash (obj , config .MICROPY_QSTR_BYTES_IN_HASH ),
300- len (obj ), '' .join (('\\ x%02x' % b ) for b in obj )))
325+ len (obj ), '' .join (('\\ x%02x' % b ) for b in obj ), obj ))
326+ sizes ["strings" ] += len (obj )
327+ sizes ["string_overhead" ] += 16
328+
301329 elif is_int_type (obj ):
302330 if config .MICROPY_LONGINT_IMPL == config .MICROPY_LONGINT_IMPL_NONE :
303331 # TODO check if we can actually fit this long-int into a small-int
@@ -321,14 +349,17 @@ def freeze(self, parent_name):
321349 print ('STATIC const mp_obj_int_t %s = {{&mp_type_int}, '
322350 '{.neg=%u, .fixed_dig=1, .alloc=%u, .len=%u, .dig=(uint%u_t[]){%s}}};'
323351 % (obj_name , neg , ndigs , ndigs , bits_per_dig , digs ))
352+ sizes ["number_overhead" ] += 16
324353 elif type (obj ) is float :
325354 print ('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B' )
326355 print ('STATIC const mp_obj_float_t %s = {{&mp_type_float}, %.16g};'
327356 % (obj_name , obj ))
328357 print ('#endif' )
358+ sizes ["number_overhead" ] += 8
329359 elif type (obj ) is complex :
330360 print ('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};'
331361 % (obj_name , obj .real , obj .imag ))
362+ sizes ["number_overhead" ] += 12
332363 else :
333364 raise FreezeError (self , 'freezing of object %r is not implemented' % (obj ,))
334365
@@ -338,8 +369,10 @@ def freeze(self, parent_name):
338369 print ('STATIC const mp_rom_obj_t const_table_data_%s[%u] = {'
339370 % (self .escaped_name , const_table_len ))
340371 for qst in self .qstrs :
372+ sizes ["const_table_overhead" ] += 4
341373 print (' MP_ROM_QSTR(%s),' % global_qstrs [qst ].qstr_id )
342374 for i in range (len (self .objs )):
375+ sizes ["const_table_overhead" ] += 4
343376 if type (self .objs [i ]) is float :
344377 print ('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B' )
345378 print (' MP_ROM_PTR(&const_obj_%s_%u),' % (self .escaped_name , i ))
@@ -353,6 +386,7 @@ def freeze(self, parent_name):
353386 else :
354387 print (' MP_ROM_PTR(&const_obj_%s_%u),' % (self .escaped_name , i ))
355388 for rc in self .raw_codes :
389+ sizes ["const_table_overhead" ] += 4
356390 print (' MP_ROM_PTR(&raw_code_%s),' % rc .escaped_name )
357391 print ('};' )
358392
@@ -376,6 +410,9 @@ def freeze(self, parent_name):
376410 print (' #endif' )
377411 print (' },' )
378412 print ('};' )
413+ sizes ["raw_code_overhead" ] += 16
414+
415+ return sizes
379416
380417def read_uint (f ):
381418 i = 0
@@ -467,6 +504,7 @@ def freeze_mpy(base_qstrs, raw_codes):
467504 new [q .qstr_esc ] = (len (new ), q .qstr_esc , q .str )
468505 new = sorted (new .values (), key = lambda x : x [0 ])
469506
507+ print ('#include "py/bc0.h"' )
470508 print ('#include "py/mpconfig.h"' )
471509 print ('#include "py/objint.h"' )
472510 print ('#include "py/objstr.h"' )
@@ -523,27 +561,45 @@ def freeze_mpy(base_qstrs, raw_codes):
523561 print (' %u, // allocated entries' % len (new ))
524562 print (' %u, // used entries' % len (new ))
525563 print (' {' )
564+ qstr_size = {"metadata" : 0 , "data" : 0 }
526565 for _ , _ , qstr in new :
566+ qstr_size ["metadata" ] += config .MICROPY_QSTR_BYTES_IN_LEN + config .MICROPY_QSTR_BYTES_IN_HASH
567+ qstr_size ["data" ] += len (qstr )
527568 print (' %s,'
528569 % qstrutil .make_bytes (config .MICROPY_QSTR_BYTES_IN_LEN , config .MICROPY_QSTR_BYTES_IN_HASH , qstr ))
529570 print (' },' )
530571 print ('};' )
531572
573+ sizes = {}
532574 for rc in raw_codes :
533- rc .freeze (rc .source_file .str .replace ('/' , '_' )[:- 3 ] + '_' )
575+ sizes [ rc . source_file . str ] = rc .freeze (rc .source_file .str .replace ('/' , '_' )[:- 3 ] + '_' )
534576
535577 print ()
536578 print ('const char mp_frozen_mpy_names[] = {' )
579+ qstr_size ["filenames" ] = 1
537580 for rc in raw_codes :
538581 module_name = rc .source_file .str
539582 print ('"%s\\ 0"' % module_name )
583+ qstr_size ["filenames" ] += len (module_name ) + 1
540584 print ('"\\ 0"};' )
541585
542586 print ('const mp_raw_code_t *const mp_frozen_mpy_content[] = {' )
543587 for rc in raw_codes :
544588 print (' &raw_code_%s,' % rc .escaped_name )
589+ size = sizes [rc .source_file .str ]
590+ print (' // Total size:' , sum (size .values ()))
591+ for k in size :
592+ print (" // {} {}" .format (k , size [k ]))
545593 print ('};' )
546594
595+ print ()
596+ print ('// Total size:' , sum ([sum (x .values ()) for x in sizes .values ()]) + sum (qstr_size .values ()))
597+ for k in size :
598+ total = sum ([x [k ] for x in sizes .values ()])
599+ print ("// {} {}" .format (k , total ))
600+ for k in qstr_size :
601+ print ("// qstr {} {}" .format (k , qstr_size [k ]))
602+
547603def main ():
548604 import argparse
549605 cmd_parser = argparse .ArgumentParser (description = 'A tool to work with MicroPython .mpy files.' )
0 commit comments