[ABI] Use mangled names for associated type witnesses.

Rather than storing associated type metadata access functions in
witness tables, initially store a pointer to a mangled type name.
On first access, demangle that type name and replace the witness
table entry with the resulting type metadata.

This reduces the code size of protocol conformances, because we no
longer need to create associated type metadata access functions for
every associated type, and the mangled names are much smaller (and
sharable). The same code size improvements apply to defaulted
associated types for resilient protocols, although those are more
rare. Witness tables themselves are slightly smaller, because we
don’t need separate private entries in them to act as caches.

On the caller side, associated type metadata is always produced via
a call to swift_getAssociatedTypeWitness(), which handles the demangling
and caching behavior.

In all, this reduces the size of the standard library by ~70k. There
are additional code-size wins that are possible with follow-on work:

* We can stop emitting type metadata access functions for non-resilient
types that have constant metadata (like `Int`), because they’re only
currently used as associated type metadata access functions.
* We can stop emitting separate associated type reflection metadata,
because the reflection infrastructure can use these mangled names
directly.
This commit is contained in:
Doug Gregor
2018-09-21 17:15:15 -07:00
parent 98b84734ba
commit b531b3923f
13 changed files with 192 additions and 229 deletions

View File

@@ -222,7 +222,8 @@ llvm::Constant *IRGenModule::getAddrOfStringForTypeRef(StringRef str) {
}
llvm::Constant *IRGenModule::getAddrOfStringForTypeRef(
const SymbolicMangling &mangling) {
const SymbolicMangling &mangling,
unsigned alignment) {
// Create a symbol name for the symbolic mangling. This is used as the
// uniquing key both for ODR coalescing and within this TU.
IRGenMangler mangler;
@@ -230,9 +231,12 @@ llvm::Constant *IRGenModule::getAddrOfStringForTypeRef(
mangler.mangleSymbolNameForSymbolicMangling(mangling);
// See if we emitted the constant already.
// FIXME: Make sure the existing variable has enough alignment. Otherwise,
// replace it.
auto &entry = StringsForTypeRef[symbolName];
if (entry.second)
if (entry.second && entry.first->getAlignment() >= alignment) {
return entry.second;
}
ConstantInitBuilder B(*this);
auto S = B.beginStruct();
@@ -284,7 +288,7 @@ llvm::Constant *IRGenModule::getAddrOfStringForTypeRef(
nullptr,
symbolName);
var->setVisibility(llvm::GlobalValue::HiddenVisibility);
var->setAlignment(1);
var->setAlignment(alignment);
setTrueConstGlobal(var);
var->setSection(getReflectionTypeRefSectionName());