@@ -78,6 +78,18 @@ class Config:
78
78
MP_BC_LOAD_ATTR = 0x1e
79
79
MP_BC_STORE_ATTR = 0x26
80
80
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
+
81
93
def make_opcode_format ():
82
94
def OC4 (a , b , c , d ):
83
95
return a | (b << 2 ) | (c << 4 ) | (d << 6 )
@@ -252,35 +264,50 @@ def freeze(self, parent_name):
252
264
i += 1
253
265
RawCode .escaped_names .add (self .escaped_name )
254
266
267
+ sizes = {"bytecode" : 0 , "strings" : 0 , "raw_code_overhead" : 0 , "const_table_overhead" : 0 , "string_overhead" : 0 , "number_overhead" : 0 }
255
268
# emit children first
256
269
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
+
258
274
259
275
# generate bytecode data
260
276
print ()
261
277
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 ))
262
279
print ('STATIC ' , end = '' )
263
280
if not config .MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE :
264
281
print ('const ' , end = '' )
265
282
print ('byte bytecode_data_%s[%u] = {' % (self .escaped_name , len (self .bytecode )))
283
+ sizes ["bytecode" ] += len (self .bytecode )
266
284
print (' ' , end = '' )
267
285
for i in range (self .ip2 ):
268
286
print (' 0x%02x,' % self .bytecode [i ], end = '' )
269
287
print ()
288
+ print (" // simple name" )
270
289
print (' ' , self .simple_name .qstr_id , '& 0xff,' , self .simple_name .qstr_id , '>> 8,' )
290
+ print (" // source file" )
271
291
print (' ' , self .source_file .qstr_id , '& 0xff,' , self .source_file .qstr_id , '>> 8,' )
292
+ print (" // code info" )
272
293
print (' ' , end = '' )
273
294
for i in range (self .ip2 + 4 , self .ip ):
274
295
print (' 0x%02x,' % self .bytecode [i ], end = '' )
275
296
print ()
297
+ print (" // bytecode" )
276
298
ip = self .ip
277
299
while ip < len (self .bytecode ):
278
300
f , sz = mp_opcode_format (self .bytecode , ip )
301
+ opcode = self .bytecode [ip ]
302
+ if opcode in opcode_names :
303
+ opcode = opcode_names [opcode ]
304
+ else :
305
+ opcode = '0x%02x' % opcode
279
306
if f == 1 :
280
307
qst = self ._unpack_qstr (ip + 1 ).qstr_id
281
- print (' ' , '0x%02x,' % self . bytecode [ ip ], qst , ' & 0xff,' , qst , ' >> 8,' )
308
+ print (' {}, {} & 0xff, {} >> 8,' . format ( opcode , qst , qst ) )
282
309
else :
283
- print (' ' , '' .join ('0x%02x, ' % self .bytecode [ip + i ] for i in range (sz )))
310
+ print (' {},{}' . format ( opcode , '' .join (' 0x%02x,' % self .bytecode [ip + i ] for i in range (1 , sz ) )))
284
311
ip += sz
285
312
print ('};' )
286
313
@@ -295,9 +322,12 @@ def freeze(self, parent_name):
295
322
obj_type = 'mp_type_str'
296
323
else :
297
324
obj_type = 'mp_type_bytes'
298
- print ('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"};'
325
+ print ('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"}; // %s '
299
326
% (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 )))
327
+ len (obj ), '' .join (('\\ x%02x' % b ) for b in obj ), obj ))
328
+ sizes ["strings" ] += len (obj )
329
+ sizes ["string_overhead" ] += 16
330
+
301
331
elif is_int_type (obj ):
302
332
if config .MICROPY_LONGINT_IMPL == config .MICROPY_LONGINT_IMPL_NONE :
303
333
# TODO check if we can actually fit this long-int into a small-int
@@ -321,14 +351,17 @@ def freeze(self, parent_name):
321
351
print ('STATIC const mp_obj_int_t %s = {{&mp_type_int}, '
322
352
'{.neg=%u, .fixed_dig=1, .alloc=%u, .len=%u, .dig=(uint%u_t[]){%s}}};'
323
353
% (obj_name , neg , ndigs , ndigs , bits_per_dig , digs ))
354
+ sizes ["number_overhead" ] += 16
324
355
elif type (obj ) is float :
325
356
print ('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B' )
326
357
print ('STATIC const mp_obj_float_t %s = {{&mp_type_float}, %.16g};'
327
358
% (obj_name , obj ))
328
359
print ('#endif' )
360
+ sizes ["number_overhead" ] += 8
329
361
elif type (obj ) is complex :
330
362
print ('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};'
331
363
% (obj_name , obj .real , obj .imag ))
364
+ sizes ["number_overhead" ] += 12
332
365
else :
333
366
raise FreezeError (self , 'freezing of object %r is not implemented' % (obj ,))
334
367
@@ -338,8 +371,10 @@ def freeze(self, parent_name):
338
371
print ('STATIC const mp_rom_obj_t const_table_data_%s[%u] = {'
339
372
% (self .escaped_name , const_table_len ))
340
373
for qst in self .qstrs :
374
+ sizes ["const_table_overhead" ] += 4
341
375
print (' MP_ROM_QSTR(%s),' % global_qstrs [qst ].qstr_id )
342
376
for i in range (len (self .objs )):
377
+ sizes ["const_table_overhead" ] += 4
343
378
if type (self .objs [i ]) is float :
344
379
print ('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B' )
345
380
print (' MP_ROM_PTR(&const_obj_%s_%u),' % (self .escaped_name , i ))
@@ -353,6 +388,7 @@ def freeze(self, parent_name):
353
388
else :
354
389
print (' MP_ROM_PTR(&const_obj_%s_%u),' % (self .escaped_name , i ))
355
390
for rc in self .raw_codes :
391
+ sizes ["const_table_overhead" ] += 4
356
392
print (' MP_ROM_PTR(&raw_code_%s),' % rc .escaped_name )
357
393
print ('};' )
358
394
@@ -376,6 +412,9 @@ def freeze(self, parent_name):
376
412
print (' #endif' )
377
413
print (' },' )
378
414
print ('};' )
415
+ sizes ["raw_code_overhead" ] += 16
416
+
417
+ return sizes
379
418
380
419
def read_uint (f ):
381
420
i = 0
@@ -467,6 +506,7 @@ def freeze_mpy(base_qstrs, raw_codes):
467
506
new [q .qstr_esc ] = (len (new ), q .qstr_esc , q .str )
468
507
new = sorted (new .values (), key = lambda x : x [0 ])
469
508
509
+ print ('#include "py/bc0.h"' )
470
510
print ('#include "py/mpconfig.h"' )
471
511
print ('#include "py/objint.h"' )
472
512
print ('#include "py/objstr.h"' )
@@ -523,27 +563,45 @@ def freeze_mpy(base_qstrs, raw_codes):
523
563
print (' %u, // allocated entries' % len (new ))
524
564
print (' %u, // used entries' % len (new ))
525
565
print (' {' )
566
+ qstr_size = {"metadata" : 0 , "data" : 0 }
526
567
for _ , _ , qstr in new :
568
+ qstr_size ["metadata" ] += config .MICROPY_QSTR_BYTES_IN_LEN + config .MICROPY_QSTR_BYTES_IN_HASH
569
+ qstr_size ["data" ] += len (qstr )
527
570
print (' %s,'
528
571
% qstrutil .make_bytes (config .MICROPY_QSTR_BYTES_IN_LEN , config .MICROPY_QSTR_BYTES_IN_HASH , qstr ))
529
572
print (' },' )
530
573
print ('};' )
531
574
575
+ sizes = {}
532
576
for rc in raw_codes :
533
- rc .freeze (rc .source_file .str .replace ('/' , '_' )[:- 3 ] + '_' )
577
+ sizes [ rc . source_file . str ] = rc .freeze (rc .source_file .str .replace ('/' , '_' )[:- 3 ] + '_' )
534
578
535
579
print ()
536
580
print ('const char mp_frozen_mpy_names[] = {' )
581
+ qstr_size ["filenames" ] = 1
537
582
for rc in raw_codes :
538
583
module_name = rc .source_file .str
539
584
print ('"%s\\ 0"' % module_name )
585
+ qstr_size ["filenames" ] += len (module_name ) + 1
540
586
print ('"\\ 0"};' )
541
587
542
588
print ('const mp_raw_code_t *const mp_frozen_mpy_content[] = {' )
543
589
for rc in raw_codes :
544
590
print (' &raw_code_%s,' % rc .escaped_name )
591
+ size = sizes [rc .source_file .str ]
592
+ print (' // Total size:' , sum (size .values ()))
593
+ for k in size :
594
+ print (" // {} {}" .format (k , size [k ]))
545
595
print ('};' )
546
596
597
+ print ()
598
+ print ('// Total size:' , sum ([sum (x .values ()) for x in sizes .values ()]) + sum (qstr_size .values ()))
599
+ for k in size :
600
+ total = sum ([x [k ] for x in sizes .values ()])
601
+ print ("// {} {}" .format (k , total ))
602
+ for k in qstr_size :
603
+ print ("// qstr {} {}" .format (k , qstr_size [k ]))
604
+
547
605
def main ():
548
606
import argparse
549
607
cmd_parser = argparse .ArgumentParser (description = 'A tool to work with MicroPython .mpy files.' )
0 commit comments