Most of the linker doesn't have to handle symbol names. The parts that do are close enough to the symbol table that they can get the name from there.
This deletes the boilerplate for tracking whether we have a name or name offset. It also reduces SymbolBody from 56 to 40 bytes on x86_64.
The performance results are more mixed than what I was expecting, but I think the patch is still worth it:
the gold plugin
master 0.389837796 patch 0.390047270
clang
master 0.669623963 patch 0.666252931
llvm-as
master 0.035799643 patch 0.035869600
the gold plugin fsds
master 0.417012576 patch 0.415979779
clang fsds
master 0.722732074 patch 0.719288980
llvm-as fsds
master 0.032511485 patch 0.032528634
scylla
master 4.915247943 patch 4.978490188
I'd define three functions instead of dispatching three ways in a single function.