Skip to content

[ownership] On non-Darwin platforms, serialize the stdlib in OSSA form. #36025

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions include/swift/AST/SILOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,8 @@ class SILOptions {
bool VerifyExclusivity = false;

/// When building the stdlib with opts should we lower ownership after
/// serialization? Otherwise we do before. Only set to true on Darwin for now.
///
bool SerializeStdlibWithOwnershipWithOpts = false;
/// serialization? Otherwise we do before.
bool SerializeStdlibWithOwnershipWithOpts = true;

/// Calls to the replaced method inside of the replacement method will call
/// the previous implementation.
Expand Down
15 changes: 11 additions & 4 deletions include/swift/Serialization/SerializedSILLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class ModuleDecl;
class SILDeserializer;
class SILFunction;
class SILGlobalVariable;
class SILProperty;
class SILModule;
class SILVTable;
class SILWitnessTable;
Expand Down Expand Up @@ -69,10 +70,16 @@ class SerializedSILLoader {
SILDifferentiabilityWitness *
lookupDifferentiabilityWitness(SILDifferentiabilityWitnessKey key);

/// Invalidate the cached entries for deserialized SILFunctions.
void invalidateCaches();

bool invalidateFunction(SILFunction *F);
/// Invalidate the cached entries for deserialized state. Must be
/// called when erasing deserialized state in the SILModule.
void invalidateAllCaches();
bool invalidateFunction(SILFunction *f);
bool invalidateGlobalVariable(SILGlobalVariable *gv);
bool invalidateVTable(SILVTable *vt);
bool invalidateWitnessTable(SILWitnessTable *wt);
bool invalidateDefaultWitnessTable(SILDefaultWitnessTable *wt);
bool invalidateProperty(SILProperty *p);
bool invalidateDifferentiabilityWitness(SILDifferentiabilityWitness *w);

/// Deserialize all SILFunctions, VTables, and WitnessTables for
/// a given Module.
Expand Down
5 changes: 0 additions & 5 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1204,11 +1204,6 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
Args.hasArg(OPT_sil_stop_optzns_before_lowering_ownership);
if (const Arg *A = Args.getLastArg(OPT_external_pass_pipeline_filename))
Opts.ExternalPassPipelineFilename = A->getValue();
// If our triple is a darwin triple, lower ownership on the stdlib after we
// serialize.
if (Triple.isOSDarwin()) {
Opts.SerializeStdlibWithOwnershipWithOpts = true;
}

Opts.GenerateProfile |= Args.hasArg(OPT_profile_generate);
const Arg *ProfileUse = Args.getLastArg(OPT_profile_use);
Expand Down
10 changes: 6 additions & 4 deletions lib/SIL/IR/SILModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ SILModule::createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol,
void SILModule::deleteWitnessTable(SILWitnessTable *Wt) {
auto Conf = Wt->getConformance();
assert(lookUpWitnessTable(Conf, false) == Wt);
getSILLoader()->invalidateWitnessTable(Wt);
WitnessTableMap.erase(Conf);
witnessTables.erase(Wt);
}
Expand Down Expand Up @@ -474,7 +475,7 @@ bool SILModule::hasFunction(StringRef Name) {
}

void SILModule::invalidateSILLoaderCaches() {
getSILLoader()->invalidateCaches();
getSILLoader()->invalidateAllCaches();
}

SILFunction *SILModule::removeFromZombieList(StringRef Name) {
Expand Down Expand Up @@ -526,9 +527,10 @@ void SILModule::invalidateFunctionInSILCache(SILFunction *F) {
}

/// Erase a global SIL variable from the module.
void SILModule::eraseGlobalVariable(SILGlobalVariable *G) {
GlobalVariableMap.erase(G->getName());
getSILGlobalList().erase(G);
void SILModule::eraseGlobalVariable(SILGlobalVariable *gv) {
getSILLoader()->invalidateGlobalVariable(gv);
GlobalVariableMap.erase(gv->getName());
getSILGlobalList().erase(gv);
}

SILVTable *SILModule::lookUpVTable(const ClassDecl *C,
Expand Down
141 changes: 133 additions & 8 deletions lib/Serialization/DeserializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILProperty.h"
#include "swift/SIL/SILUndef.h"

#include "llvm/ADT/Statistic.h"
Expand Down Expand Up @@ -2937,11 +2938,11 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {

assert(VId <= GlobalVars.size() && "invalid GlobalVar ID");
auto &globalVarOrOffset = GlobalVars[VId-1];
if (globalVarOrOffset.isComplete())
return globalVarOrOffset;
if (globalVarOrOffset.isFullyDeserialized())
return globalVarOrOffset.get();

BCOffsetRAII restoreOffset(SILCursor);
if (llvm::Error Err = SILCursor.JumpToBit(globalVarOrOffset))
if (llvm::Error Err = SILCursor.JumpToBit(globalVarOrOffset.getOffset()))
MF->fatal(std::move(Err));
llvm::Expected<llvm::BitstreamEntry> maybeEntry =
SILCursor.advance(AF_DontPopBlockAtEnd);
Expand Down Expand Up @@ -2988,7 +2989,7 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
None,
dID ? cast<VarDecl>(MF->getDecl(dID)): nullptr);
v->setLet(IsLet);
globalVarOrOffset = v;
globalVarOrOffset.set(v, true /*isFullyDeserialized*/);
v->setDeclaration(IsDeclaration);

if (Callback)
Expand Down Expand Up @@ -3087,11 +3088,11 @@ SILVTable *SILDeserializer::readVTable(DeclID VId) {
assert(VId <= VTables.size() && "invalid VTable ID");
auto &vTableOrOffset = VTables[VId-1];

if (vTableOrOffset.isComplete())
return vTableOrOffset;
if (vTableOrOffset.isFullyDeserialized())
return vTableOrOffset.get();

BCOffsetRAII restoreOffset(SILCursor);
if (llvm::Error Err = SILCursor.JumpToBit(vTableOrOffset))
if (llvm::Error Err = SILCursor.JumpToBit(vTableOrOffset.getOffset()))
MF->fatal(std::move(Err));
llvm::Expected<llvm::BitstreamEntry> maybeEntry =
SILCursor.advance(AF_DontPopBlockAtEnd);
Expand Down Expand Up @@ -3188,7 +3189,7 @@ SILVTable *SILDeserializer::readVTable(DeclID VId) {
SILMod, theClass,
Serialized ? IsSerialized : IsNotSerialized,
vtableEntries);
vTableOrOffset = vT;
vTableOrOffset.set(vT, true /*isFullyDeserialized*/);

if (Callback) Callback->didDeserialize(MF->getAssociatedModule(), vT);
return vT;
Expand Down Expand Up @@ -3819,3 +3820,127 @@ bool SILDeserializer::invalidateFunction(SILFunction *F) {
}
return false;
}

// Invalidate all cached SILGlobalVariable.
void SILDeserializer::invalidateGlobalVariableCache() {
for (auto &entry : GlobalVars) {
if (entry.isDeserialized()) {
entry.reset();
}
}
}

// Invalidate a specific cached GlobalVariable.
bool SILDeserializer::invalidateGlobalVariable(SILGlobalVariable *gv) {
for (auto &entry : GlobalVars) {
if (entry.isDeserialized() && entry.get() == gv) {
entry.reset();
return true;
}
}

return false;
}

// Invalidate all cached SILVTable.
void SILDeserializer::invalidateVTableCache() {
for (auto &entry : VTables) {
if (entry.isDeserialized()) {
entry.reset();
}
}
}

// Invalidate a specific cached SILVTable.
bool SILDeserializer::invalidateVTable(SILVTable *v) {
for (auto &entry : VTables) {
if (entry.isDeserialized() && entry.get() == v) {
entry.reset();
return true;
}
}

return false;
}

// Invalidate all cached SILWitnessTable.
void SILDeserializer::invalidateWitnessTableCache() {
for (auto &entry : WitnessTables) {
if (entry.isDeserialized()) {
entry.reset();
}
}
}

// Invalidate a specific cached SILWitnessTable.
bool SILDeserializer::invalidateWitnessTable(SILWitnessTable *wt) {
for (auto &entry : WitnessTables) {
if (entry.isDeserialized() && entry.get() == wt) {
entry.reset();
return true;
}
}
return false;
}

// Invalidate all cached SILDefaultWitnessTable.
void SILDeserializer::invalidateDefaultWitnessTableCache() {
for (auto &entry : DefaultWitnessTables) {
if (entry.isDeserialized()) {
entry.reset();
}
}
}

// Invalidate a specific cached SILDefaultWitnessTable.
bool SILDeserializer::invalidateDefaultWitnessTable(
SILDefaultWitnessTable *wt) {
for (auto &entry : DefaultWitnessTables) {
if (entry.isDeserialized() && entry.get() == wt) {
entry.reset();
return true;
}
}
return false;
}

// Invalidate all cached SILProperty.
void SILDeserializer::invalidatePropertyCache() {
for (auto &entry : Properties) {
if (entry.isDeserialized()) {
entry.reset();
}
}
}

// Invalidate a specific cached SILProperty.
bool SILDeserializer::invalidateProperty(SILProperty *p) {
for (auto &entry : Properties) {
if (entry.isDeserialized() && entry.get() == p) {
entry.reset();
return true;
}
}
return false;
}

// Invalidate all cached SILDifferentiabilityWitness.
void SILDeserializer::invalidateDifferentiabilityWitnessCache() {
for (auto &entry : DifferentiabilityWitnesses) {
if (entry.isDeserialized()) {
entry.reset();
}
}
}

// Invalidate a specific cached SILDifferentiabilityWitness.
bool SILDeserializer::invalidateDifferentiabilityWitness(
SILDifferentiabilityWitness *w) {
for (auto &entry : DifferentiabilityWitnesses) {
if (entry.isDeserialized() && entry.get() == w) {
entry.reset();
return true;
}
}
return false;
}
71 changes: 67 additions & 4 deletions lib/Serialization/DeserializeSIL.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,24 @@ namespace swift {
using SerializedFuncTable =
llvm::OnDiskIterableChainedHashTable<FuncTableInfo>;

//-----
// Deserialization Caches
//
// NOTE: When adding more serialized tables to the deserializer,
// always add invalidate methods and make sure SILModule always
// invalidates the deserializer appropriately when it erases a
// value that we deserialized here. Otherwise, memory corruption
// may result.

std::unique_ptr<SerializedFuncTable> FuncTable;
MutableArrayRef<ModuleFile::PartiallySerialized<SILFunction*>> Funcs;

std::unique_ptr<SerializedFuncTable> VTableList;
MutableArrayRef<ModuleFile::Serialized<SILVTable*>> VTables;

std::unique_ptr<SerializedFuncTable> GlobalVarList;
MutableArrayRef<ModuleFile::Serialized<SILGlobalVariable*>> GlobalVars;
MutableArrayRef<ModuleFile::PartiallySerialized<SILGlobalVariable *>>
GlobalVars;

std::unique_ptr<SerializedFuncTable> VTableList;
MutableArrayRef<ModuleFile::PartiallySerialized<SILVTable *>> VTables;

std::unique_ptr<SerializedFuncTable> WitnessTableList;
MutableArrayRef<ModuleFile::PartiallySerialized<SILWitnessTable *>>
Expand All @@ -63,6 +73,12 @@ namespace swift {
ModuleFile::PartiallySerialized<SILDifferentiabilityWitness *>>
DifferentiabilityWitnesses;

//-----
// End Deserialization Caches
//
// Before adding a new cache here, please read the comment at the
// beginning of the deserialization cache section.

/// A declaration will only
llvm::DenseMap<NormalProtocolConformance *, SILWitnessTable *>
ConformanceToWitnessTableMap;
Expand Down Expand Up @@ -176,6 +192,53 @@ namespace swift {
/// Invalidate a specific cached SILFunction.
bool invalidateFunction(SILFunction *F);

/// Invalidate all cached SILGlobalVariable.
void invalidateGlobalVariableCache();

/// Invalidate a specific cached GlobalVariable.
bool invalidateGlobalVariable(SILGlobalVariable *gv);

/// Invalidate all cached SILVTable.
void invalidateVTableCache();

/// Invalidate a specific cached SILVTable.
bool invalidateVTable(SILVTable *v);

/// Invalidate all cached SILWitnessTable.
void invalidateWitnessTableCache();

/// Invalidate a specific cached SILWitnessTable.
bool invalidateWitnessTable(SILWitnessTable *v);

/// Invalidate all cached SILDefaultWitnessTable.
void invalidateDefaultWitnessTableCache();

/// Invalidate a specific cached SILDefaultWitnessTable.
bool invalidateDefaultWitnessTable(SILDefaultWitnessTable *v);

/// Invalidate all cached SILProperty.
void invalidatePropertyCache();

/// Invalidate a specific cached SILProperty.
bool invalidateProperty(SILProperty *v);

/// Invalidate all cached SILDifferentiabilityWitness.
void invalidateDifferentiabilityWitnessCache();

/// Invalidate a specific cached SILDifferentiabilityWitness.
bool invalidateDifferentiabilityWitness(SILDifferentiabilityWitness *v);

/// Invalidate all caches in this deserializer.
void invalidateAllCaches() {
invalidateFunctionCache();
invalidateGlobalVariableCache();
invalidateVTableCache();
invalidateWitnessTableCache();
invalidateDefaultWitnessTableCache();
invalidatePropertyCache();
invalidateDifferentiabilityWitnessCache();
}

/// Deserialize all SILFunctions, VTables, WitnessTables, and
/// DefaultWitnessTables inside the module, and add them to SILMod.
///
Expand Down
Loading