@@ -233,6 +233,9 @@ static arraylist_t ccallable_list;
233
233
static htable_t fptr_to_id ;
234
234
void * native_functions ;
235
235
236
+ // table of struct field addresses to rewrite during saving
237
+ static htable_t field_replace ;
238
+
236
239
// array of definitions for the predefined function pointers
237
240
// (reverse of fptr_to_id)
238
241
// This is a manually constructed dual of the fvars array, which would be produced by codegen for Julia code, for C.
@@ -415,6 +418,13 @@ static void jl_serialize_module(jl_serializer_state *s, jl_module_t *m)
415
418
}
416
419
}
417
420
421
+ static jl_value_t * get_replaceable_field (jl_value_t * * addr )
422
+ {
423
+ jl_value_t * fld = (jl_value_t * )ptrhash_get (& field_replace , addr );
424
+ if (fld == HT_NOTFOUND )
425
+ return * addr ;
426
+ return fld ;
427
+ }
418
428
419
429
#define NBOX_C 1024
420
430
@@ -515,7 +525,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int recur
515
525
size_t i , np = t -> layout -> npointers ;
516
526
for (i = 0 ; i < np ; i ++ ) {
517
527
uint32_t ptr = jl_ptr_offset (t , i );
518
- jl_value_t * fld = (( jl_value_t * const * )data )[ptr ];
528
+ jl_value_t * fld = get_replaceable_field ( & (( jl_value_t * * )data )[ptr ]) ;
519
529
jl_serialize_value (s , fld );
520
530
}
521
531
}
@@ -944,7 +954,7 @@ static void jl_write_values(jl_serializer_state *s)
944
954
size_t np = t -> layout -> npointers ;
945
955
for (i = 0 ; i < np ; i ++ ) {
946
956
size_t offset = jl_ptr_offset (t , i ) * sizeof (jl_value_t * );
947
- jl_value_t * fld = * ( jl_value_t * * )& data [offset ];
957
+ jl_value_t * fld = get_replaceable_field (( jl_value_t * * )& data [offset ]) ;
948
958
if (fld != NULL ) {
949
959
arraylist_push (& s -> relocs_list , (void * )(uintptr_t )(offset + reloc_offset )); // relocation location
950
960
arraylist_push (& s -> relocs_list , (void * )backref_id (s , fld )); // relocation target
@@ -1527,7 +1537,7 @@ static void jl_prune_type_cache_linear(jl_svec_t *cache)
1527
1537
}
1528
1538
}
1529
1539
1530
- static jl_value_t * strip_codeinfo (jl_method_t * m , jl_value_t * ci_ , int isdef )
1540
+ static jl_value_t * strip_codeinfo_meta (jl_method_t * m , jl_value_t * ci_ , int orig )
1531
1541
{
1532
1542
jl_code_info_t * ci = NULL ;
1533
1543
JL_GC_PUSH1 (& ci );
@@ -1552,7 +1562,7 @@ static jl_value_t *strip_codeinfo(jl_method_t *m, jl_value_t *ci_, int isdef)
1552
1562
if (s != (jl_value_t * )jl_unused_sym )
1553
1563
jl_array_ptr_set (ci -> slotnames , i , questionsym );
1554
1564
}
1555
- if (isdef ) {
1565
+ if (orig ) {
1556
1566
m -> slot_syms = jl_compress_argnames (ci -> slotnames );
1557
1567
jl_gc_wb (m , m -> slot_syms );
1558
1568
}
@@ -1563,33 +1573,69 @@ static jl_value_t *strip_codeinfo(jl_method_t *m, jl_value_t *ci_, int isdef)
1563
1573
return ret ;
1564
1574
}
1565
1575
1576
+ static void record_field_change (jl_value_t * * addr , jl_value_t * newval )
1577
+ {
1578
+ ptrhash_put (& field_replace , (void * )addr , newval );
1579
+ }
1580
+
1566
1581
static void strip_specializations_ (jl_method_instance_t * mi )
1567
1582
{
1568
1583
assert (jl_is_method_instance (mi ));
1569
1584
jl_code_instance_t * codeinst = mi -> cache ;
1570
1585
while (codeinst ) {
1571
1586
if (codeinst -> inferred && codeinst -> inferred != jl_nothing ) {
1572
- codeinst -> inferred = strip_codeinfo (mi -> def .method , codeinst -> inferred , 0 );
1573
- jl_gc_wb (codeinst , codeinst -> inferred );
1587
+ if (jl_options .strip_ir ) {
1588
+ record_field_change (& codeinst -> inferred , jl_nothing );
1589
+ }
1590
+ else if (jl_options .strip_metadata ) {
1591
+ codeinst -> inferred = strip_codeinfo_meta (mi -> def .method , codeinst -> inferred , 0 );
1592
+ jl_gc_wb (codeinst , codeinst -> inferred );
1593
+ }
1574
1594
}
1575
1595
codeinst = jl_atomic_load_relaxed (& codeinst -> next );
1576
1596
}
1597
+ if (jl_options .strip_ir ) {
1598
+ record_field_change (& mi -> uninferred , NULL );
1599
+ }
1577
1600
}
1578
1601
1579
1602
static int strip_all_codeinfos__ (jl_typemap_entry_t * def , void * _env )
1580
1603
{
1581
1604
jl_method_t * m = def -> func .method ;
1582
1605
if (m -> source ) {
1583
- m -> source = strip_codeinfo (m , m -> source , 1 );
1584
- jl_gc_wb (m , m -> source );
1606
+ int stripped_ir = 0 ;
1607
+ if (jl_options .strip_ir ) {
1608
+ if (m -> unspecialized ) {
1609
+ jl_code_instance_t * unspec = jl_atomic_load_relaxed (& m -> unspecialized -> cache );
1610
+ if (unspec && jl_atomic_load_relaxed (& unspec -> invoke )) {
1611
+ // we have a generic compiled version, so can remove the IR
1612
+ record_field_change (& m -> source , jl_nothing );
1613
+ stripped_ir = 1 ;
1614
+ }
1615
+ }
1616
+ if (!stripped_ir ) {
1617
+ int mod_setting = jl_get_module_compile (m -> module );
1618
+ // if the method is declared not to be compiled, keep IR for interpreter
1619
+ if (!(mod_setting == JL_OPTIONS_COMPILE_OFF || mod_setting == JL_OPTIONS_COMPILE_MIN )) {
1620
+ record_field_change (& m -> source , jl_nothing );
1621
+ stripped_ir = 1 ;
1622
+ }
1623
+ }
1624
+ }
1625
+ if (jl_options .strip_metadata && !stripped_ir ) {
1626
+ m -> source = strip_codeinfo_meta (m , m -> source , 1 );
1627
+ jl_gc_wb (m , m -> source );
1628
+ }
1585
1629
}
1586
- jl_svec_t * specializations = def -> func . method -> specializations ;
1630
+ jl_svec_t * specializations = m -> specializations ;
1587
1631
size_t i , l = jl_svec_len (specializations );
1588
1632
for (i = 0 ; i < l ; i ++ ) {
1589
1633
jl_value_t * mi = jl_svecref (specializations , i );
1590
1634
if (mi != jl_nothing )
1591
1635
strip_specializations_ ((jl_method_instance_t * )mi );
1592
1636
}
1637
+ if (m -> unspecialized )
1638
+ strip_specializations_ (m -> unspecialized );
1593
1639
return 1 ;
1594
1640
}
1595
1641
@@ -1610,11 +1656,15 @@ static void jl_cleanup_serializer2(void);
1610
1656
1611
1657
static void jl_save_system_image_to_stream (ios_t * f ) JL_GC_DISABLED
1612
1658
{
1613
- if (jl_options .strip_metadata )
1614
- jl_strip_all_codeinfos ();
1615
1659
jl_gc_collect (JL_GC_FULL );
1616
1660
jl_gc_collect (JL_GC_INCREMENTAL ); // sweep finalizers
1617
1661
JL_TIMING (SYSIMG_DUMP );
1662
+
1663
+ htable_new (& field_replace , 10000 );
1664
+ // strip metadata and IR when requested
1665
+ if (jl_options .strip_metadata || jl_options .strip_ir )
1666
+ jl_strip_all_codeinfos ();
1667
+
1618
1668
int en = jl_gc_enable (0 );
1619
1669
jl_init_serializer2 (1 );
1620
1670
htable_reset (& backref_table , 250000 );
@@ -1759,6 +1809,7 @@ static void jl_save_system_image_to_stream(ios_t *f) JL_GC_DISABLED
1759
1809
arraylist_free (& ccallable_list );
1760
1810
arraylist_free (& s .relocs_list );
1761
1811
arraylist_free (& s .gctags_list );
1812
+ htable_free (& field_replace );
1762
1813
jl_cleanup_serializer2 ();
1763
1814
1764
1815
jl_gc_enable (en );
0 commit comments