What does ".island" suffix in symbol name mean?

During my analysis of the binary size changes after compiling Swift source code, I discovered symbols with the ".island" suffix. I couldn't find meaningful information about this suffix through my search, so I decided to reach out for assistance.

While comparing the changes in binary size after modifying specific code, I noticed a significant increase (from 33MB to 520MB). Upon analyzing the symbols of the enlarged binary using the nm command, I found the following pattern:

0000000000034e98 t _$s12{SomeSymbol}WOb
0000000007b1538c t _$s12{SomeSymbol}WOb.island
000000000f716284 t _$s12{SomeSymbol}WOb.island2
0000000017301164 t _$s12{SomeSymbol}WOb.island3

When I output the symbols of the binary using nm, I noticed many symbols with the same name but different ".island", ".island2", ".island3" suffixes. Disassembling the binary showed that functions with these suffixes simply delegate calls sequentially: x.island3 -> x.island2 -> x.island1 -> x.

It appears that these symbols serve as delegates for function calls, but I would like to understand why such duplicated functions with these suffixes are generated. Could someone help me to provide some insights on this matter?

2 Likes

Those are probably branch islands, which would be generated by the linker when it places the destination of a jump instruction in the machine code too far away to be reached by that single jump instruction. They're probably a symptom rather than a cause of whatever's causing your code size to increase so much. What sort of change did you make that caused this increase?

7 Likes

In the binary code, a struct with complex properties and used quite frequently had the CowBox macro applied. After removing this macro, the binary size increased significantly.

I suspect this is because the initializer of the struct differs depending on whether the CowBox macro is applied. Interestingly, the larger binary contains the symbol "outlined init with copy of A" for the struct (A), whereas the original binary does not.

Additionally, there is a significant difference in the number of function symbols with "outlined init with copy of", "outlined init with take of", and similar prefixes ("outlined..."), aside from those with the "island" suffix. The count increased from 1,570 to 2,633.

1 Like

Removing the CowBox is probably leading to the entire struct contents being passed around directly by value, which would account for all of those changes (and probably why CowBox is being used in the first place).

3 Likes

As you mentioned, I understand that changing the struct's property from a value type to a reference type (COW storage) can reduce the size, but I don't quite understand why the difference is so significant. Therefore, I would like to understand the exact reason for this difference (e.g., the struct is used frequently as a function parameter or return value / many other structs hold this struct as a property, etc.).

1 Like

Really appreciated for the detailed explaination but I don't know much about this field, so could you please advise me on what aspects I should look into to better understand this issue?

1 Like

Ahh… interesting! Could you share any more details about the struct that was migrated to CowBox? What does MemoryLayout return for size (and stride)? What is the memory footprint of one struct instance?

My expectation when building the CowBox macro was engineers were focused on optimizing memory as a primary goal. A secondary goal (if a struct was copied many many times) was optimizing CPU. The honest truth is I did not think to rigorously test for binary size optimizations. I would not have expected engineers would see any kind of stat-sig reduction in binary size from migrating to CowBox… but a legit 90 percent reduction in binary size with very complex structs is awesome.

I would appreciate any more details you might have about how this struct is built and how this struct is called. It would be great if I could repro these binary size reductions in a test project. Thanks!