AST: GenericContexts store a GenericSignature instead of a GenericEnvironment

This eliminates the entire 'lazy generic environment' concept;
essentially, all generic environments are now lazy, and since
each signature has exactly one environment, their construction
no longer needs to be co-ordinated with deserialization.
This commit is contained in:
Slava Pestov
2019-09-05 18:16:38 -04:00
parent e027c82f37
commit 0405ab5ffc
11 changed files with 48 additions and 196 deletions

View File

@@ -68,7 +68,6 @@ namespace swift {
class InFlightDiagnostic;
class IterableDeclContext;
class LazyContextData;
class LazyGenericContextData;
class LazyIterableDeclContextData;
class LazyMemberLoader;
class LazyResolver;
@@ -817,15 +816,6 @@ public:
LazyContextData *getOrCreateLazyContextData(const DeclContext *decl,
LazyMemberLoader *lazyLoader);
/// Get the lazy function data for the given generic context.
///
/// \param lazyLoader If non-null, the lazy loader to use when creating the
/// function data. The pointer must either be null or be consistent
/// across all calls for the same \p func.
LazyGenericContextData *getOrCreateLazyGenericContextData(
const GenericContext *dc,
LazyMemberLoader *lazyLoader);
/// Get the lazy iterable context for the given iterable declaration context.
///
/// \param lazyLoader If non-null, the lazy loader to use when creating the

View File

@@ -1482,18 +1482,11 @@ public:
/// moves the trailing where clause into the generic parameter list.
TrailingWhereClause *TrailingWhere = nullptr;
/// The generic signature or environment of this declaration.
///
/// When this declaration stores only a signature, the generic
/// environment will be lazily loaded.
mutable llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
GenericSigOrEnv;
/// The generic signature of this declaration.
GenericSignature *GenericSig = nullptr;
};
class GenericContext : private _GenericContext, public DeclContext {
/// Lazily populate the generic environment.
GenericEnvironment *getLazyGenericEnvironmentSlow() const;
protected:
GenericContext(DeclContextKind Kind, DeclContext *Parent)
: _GenericContext(), DeclContext(Kind, Parent) { }
@@ -1542,18 +1535,12 @@ public:
/// Retrieve the generic requirements.
ArrayRef<Requirement> getGenericRequirements() const;
/// Set a lazy generic environment.
void setLazyGenericEnvironment(LazyMemberLoader *lazyLoader,
GenericSignature *genericSig,
uint64_t genericEnvData);
/// Whether this generic context has a lazily-created generic environment
/// that has not yet been constructed.
bool hasLazyGenericEnvironment() const;
/// Set the generic context of this context.
void setGenericEnvironment(GenericEnvironment *genericEnv);
/// Set the generic signature of this context.
void setGenericSignature(GenericSignature *genericSig);
/// Retrieve the position of any where clause for this context's
/// generic parameters.
SourceRange getGenericTrailingWhereClauseSourceRange() const;

View File

@@ -360,10 +360,6 @@ public:
/// of its parents.
GenericEnvironment *getGenericEnvironmentOfContext() const;
/// Whether the context has a generic environment that will be constructed
/// on first access (but has not yet been constructed).
bool contextHasLazyGenericEnvironment() const;
/// Map an interface type to a contextual type within this context.
Type mapTypeIntoContext(Type type) const;

View File

@@ -85,15 +85,8 @@ public:
LazyMemberLoader *loader;
};
/// Context data for generic contexts.
class LazyGenericContextData : public LazyContextData {
public:
/// The context data used for loading the generic environment.
uint64_t genericEnvData = 0;
};
/// Context data for iterable decl contexts.
class LazyIterableDeclContextData : public LazyGenericContextData {
class LazyIterableDeclContextData : public LazyContextData {
public:
/// The context data used for loading all of the members of the iterable
/// context.
@@ -145,10 +138,6 @@ public:
virtual Type loadAssociatedTypeDefault(const AssociatedTypeDecl *ATD,
uint64_t contextData) = 0;
/// Returns the generic environment.
virtual GenericEnvironment *loadGenericEnvironment(const DeclContext *decl,
uint64_t contextData) = 0;
/// Loads the requirement signature for a protocol.
virtual void
loadRequirementSignature(const ProtocolDecl *proto, uint64_t contextData,

View File

@@ -249,12 +249,6 @@ FRONTEND_STATISTIC(Sema, NumFunctionsTypechecked)
/// amount of work the GSB does analyzing type signatures.
FRONTEND_STATISTIC(Sema, NumGenericSignatureBuilders)
/// Number of lazy generic environments registered.
FRONTEND_STATISTIC(Sema, NumLazyGenericEnvironments)
/// Number of lazy generic environments deserialized.
FRONTEND_STATISTIC(Sema, NumLazyGenericEnvironmentsLoaded)
/// Number of lazy requirement signatures registered.
FRONTEND_STATISTIC(Sema, NumLazyRequirementSignatures)

View File

@@ -1970,10 +1970,10 @@ LazyContextData *ASTContext::getOrCreateLazyContextData(
assert(lazyLoader && "Queried lazy data for non-lazy iterable context");
if (isa<ProtocolDecl>(dc))
entry = Allocate<LazyProtocolData>();
else if (isa<NominalTypeDecl>(dc) || isa<ExtensionDecl>(dc))
else {
assert(isa<NominalTypeDecl>(dc) || isa<ExtensionDecl>(dc));
entry = Allocate<LazyIterableDeclContextData>();
else
entry = Allocate<LazyGenericContextData>();
}
entry->loader = lazyLoader;
return entry;
@@ -1992,13 +1992,6 @@ LazyIterableDeclContextData *ASTContext::getOrCreateLazyIterableContextData(
lazyLoader);
}
LazyGenericContextData *ASTContext::getOrCreateLazyGenericContextData(
const GenericContext *dc,
LazyMemberLoader *lazyLoader) {
return (LazyGenericContextData *)getOrCreateLazyContextData(dc,
lazyLoader);
}
bool ASTContext::hasDelayedConformanceErrors() const {
for (const auto &entry : getImpl().DelayedConformanceDiags) {
auto &diagnostics = entry.getSecond();

View File

@@ -66,10 +66,6 @@ using namespace swift;
#define DEBUG_TYPE "Serialization"
STATISTIC(NumLazyGenericEnvironments,
"# of lazily-deserialized generic environments known");
STATISTIC(NumLazyGenericEnvironmentsLoaded,
"# of lazily-deserialized generic environments loaded");
STATISTIC(NumLazyRequirementSignatures,
"# of lazily-deserialized requirement signatures known");
@@ -829,11 +825,8 @@ void GenericContext::setGenericParams(GenericParamList *params) {
}
GenericSignature *GenericContext::getGenericSignature() const {
if (auto genericEnv = GenericSigOrEnv.dyn_cast<GenericEnvironment *>())
return genericEnv->getGenericSignature();
if (auto genericSig = GenericSigOrEnv.dyn_cast<GenericSignature *>())
return genericSig;
if (GenericSig)
return GenericSig;
// The signature of a Protocol is trivial (Self: TheProtocol) so let's compute
// it.
@@ -842,81 +835,28 @@ GenericSignature *GenericContext::getGenericSignature() const {
auto self = PD->getSelfInterfaceType()->castTo<GenericTypeParamType>();
auto req =
Requirement(RequirementKind::Conformance, self, PD->getDeclaredType());
auto *genericSig = GenericSignature::get({self}, {req});
// Save it for next time.
const_cast<GenericContext *>(this)->GenericSigOrEnv = genericSig;
return genericSig;
const_cast<GenericContext *>(this)->GenericSig
= GenericSignature::get({self}, {req});
return GenericSig;
}
return nullptr;
}
GenericEnvironment *GenericContext::getGenericEnvironment() const {
// Fast case: we already have a generic environment.
if (auto genericEnv = GenericSigOrEnv.dyn_cast<GenericEnvironment *>())
return genericEnv;
// If we only have a generic signature, build the generic environment.
if (GenericSigOrEnv.dyn_cast<GenericSignature *>() || isa<ProtocolDecl>(this))
return getLazyGenericEnvironmentSlow();
if (auto *genericSig = getGenericSignature())
return genericSig->getGenericEnvironment();
return nullptr;
}
bool GenericContext::hasLazyGenericEnvironment() const {
return GenericSigOrEnv.dyn_cast<GenericSignature *>() != nullptr;
}
void GenericContext::setGenericEnvironment(GenericEnvironment *genericEnv) {
assert((GenericSigOrEnv.isNull() ||
getGenericSignature()->getCanonicalSignature() ==
genericEnv->getGenericSignature()->getCanonicalSignature()) &&
"set a generic environment with a different generic signature");
this->GenericSigOrEnv = genericEnv;
setGenericSignature(genericEnv ? genericEnv->getGenericSignature() : nullptr);
}
GenericEnvironment *
GenericContext::getLazyGenericEnvironmentSlow() const {
assert(GenericSigOrEnv.is<GenericSignature *>() &&
"not a lazily computed generic environment");
if (auto PD = dyn_cast<ProtocolDecl>(this)) {
// The signature of a Protocol is trivial (Self: TheProtocol) so let's
// compute it directly.
auto *genericEnv = getGenericSignature()->getGenericEnvironment();
const_cast<GenericContext *>(this)->setGenericEnvironment(genericEnv);
return genericEnv;
}
auto contextData = getASTContext().getOrCreateLazyGenericContextData(
this, nullptr);
auto *genericEnv = contextData->loader->loadGenericEnvironment(
this, contextData->genericEnvData);
const_cast<GenericContext *>(this)->setGenericEnvironment(genericEnv);
++NumLazyGenericEnvironmentsLoaded;
// FIXME: (transitional) increment the redundant "always-on" counter.
if (getASTContext().Stats)
getASTContext().Stats->getFrontendCounters().NumLazyGenericEnvironmentsLoaded++;
return genericEnv;
}
void GenericContext::setLazyGenericEnvironment(LazyMemberLoader *lazyLoader,
GenericSignature *genericSig,
uint64_t genericEnvData) {
assert(GenericSigOrEnv.isNull() && "already have a generic signature");
GenericSigOrEnv = genericSig;
auto contextData =
getASTContext().getOrCreateLazyGenericContextData(this, lazyLoader);
contextData->genericEnvData = genericEnvData;
++NumLazyGenericEnvironments;
// FIXME: (transitional) increment the redundant "always-on" counter.
if (getASTContext().Stats)
getASTContext().Stats->getFrontendCounters().NumLazyGenericEnvironments++;
void GenericContext::setGenericSignature(GenericSignature *genericSig) {
assert(GenericSig == nullptr && "Generic signature cannot be changed");
this->GenericSig = genericSig;
}
SourceRange GenericContext::getGenericTrailingWhereClauseSourceRange() const {

View File

@@ -175,17 +175,6 @@ GenericEnvironment *DeclContext::getGenericEnvironmentOfContext() const {
return nullptr;
}
bool DeclContext::contextHasLazyGenericEnvironment() const {
auto dc = this;
do {
if (auto decl = dc->getAsDecl())
if (auto GC = decl->getAsGenericContext())
return GC->hasLazyGenericEnvironment();
} while ((dc = dc->getParent()));
return false;
}
Type DeclContext::mapTypeIntoContext(Type type) const {
return GenericEnvironment::mapTypeIntoContext(
getGenericEnvironmentOfContext(), type);

View File

@@ -1243,12 +1243,6 @@ public:
llvm_unreachable("unimplemented for ClangImporter");
}
/// Returns the generic environment.
virtual GenericEnvironment *loadGenericEnvironment(const DeclContext *decl,
uint64_t contextData) override {
llvm_unreachable("unimplemented for ClangImporter");
}
void loadRequirementSignature(const ProtocolDecl *decl, uint64_t contextData,
SmallVectorImpl<Requirement> &reqs) override {
llvm_unreachable("unimplemented for ClangImporter");

View File

@@ -807,13 +807,6 @@ static void skipGenericRequirements(llvm::BitstreamCursor &Cursor) {
}
}
void ModuleFile::configureGenericEnvironment(
GenericContext *genericDecl, serialization::GenericSignatureID sigID) {
if (sigID == 0) return;
auto *genericSig = getGenericSignature(sigID);
genericDecl->setLazyGenericEnvironment(this, genericSig, sigID);
}
GenericSignature *ModuleFile::getGenericSignature(
serialization::GenericSignatureID ID) {
using namespace decls_block;
@@ -2196,13 +2189,13 @@ public:
DeclContextID contextID;
TypeID underlyingTypeID, interfaceTypeID;
bool isImplicit;
GenericSignatureID genericEnvID;
GenericSignatureID genericSigID;
uint8_t rawAccessLevel;
ArrayRef<uint64_t> dependencyIDs;
decls_block::TypeAliasLayout::readRecord(scratch, nameID, contextID,
underlyingTypeID, interfaceTypeID,
isImplicit, genericEnvID,
isImplicit, genericSigID,
rawAccessLevel, dependencyIDs);
Identifier name = MF.getIdentifier(nameID);
@@ -2225,7 +2218,7 @@ public:
SourceLoc(), genericParams, DC);
declOrOffset = alias;
MF.configureGenericEnvironment(alias, genericEnvID);
alias->setGenericSignature(MF.getGenericSignature(genericSigID));
alias->setUnderlyingType(MF.getType(underlyingTypeID));
@@ -2324,13 +2317,13 @@ public:
DeclContextID contextID;
bool isImplicit;
bool isObjC;
GenericSignatureID genericEnvID;
GenericSignatureID genericSigID;
uint8_t rawAccessLevel;
unsigned numConformances, numInheritedTypes;
ArrayRef<uint64_t> rawInheritedAndDependencyIDs;
decls_block::StructLayout::readRecord(scratch, nameID, contextID,
isImplicit, isObjC, genericEnvID,
isImplicit, isObjC, genericSigID,
rawAccessLevel,
numConformances, numInheritedTypes,
rawInheritedAndDependencyIDs);
@@ -2359,7 +2352,7 @@ public:
declOrOffset = theStruct;
// Read the generic environment.
MF.configureGenericEnvironment(theStruct, genericEnvID);
theStruct->setGenericSignature(MF.getGenericSignature(genericSigID));
if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
theStruct->setAccess(*accessLevel);
@@ -2391,7 +2384,7 @@ public:
DeclContextID contextID;
bool isIUO, isFailable;
bool isImplicit, isObjC, hasStubImplementation, throws;
GenericSignatureID genericEnvID;
GenericSignatureID genericSigID;
uint8_t storedInitKind, rawAccessLevel;
DeclID overriddenID;
bool needsNewVTableEntry, firstTimeRequired;
@@ -2402,7 +2395,7 @@ public:
isFailable, isIUO, isImplicit,
isObjC, hasStubImplementation,
throws, storedInitKind,
genericEnvID,
genericSigID,
overriddenID,
rawAccessLevel,
needsNewVTableEntry,
@@ -2461,7 +2454,7 @@ public:
genericParams, parent);
declOrOffset = ctor;
MF.configureGenericEnvironment(ctor, genericEnvID);
ctor->setGenericSignature(MF.getGenericSignature(genericSigID));
if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
ctor->setAccess(*accessLevel);
@@ -2750,7 +2743,7 @@ public:
uint8_t rawAccessorKind;
bool isObjC, hasForcedStaticDispatch, throws;
unsigned numNameComponentsBiased;
GenericSignatureID genericEnvID;
GenericSignatureID genericSigID;
TypeID resultInterfaceTypeID;
bool isIUO;
DeclID associatedDeclID;
@@ -2765,7 +2758,7 @@ public:
isStatic, rawStaticSpelling, isObjC,
rawMutModifier,
hasForcedStaticDispatch, throws,
genericEnvID,
genericSigID,
resultInterfaceTypeID,
isIUO,
associatedDeclID, overriddenID,
@@ -2779,7 +2772,7 @@ public:
isStatic, rawStaticSpelling, isObjC,
rawMutModifier,
hasForcedStaticDispatch, throws,
genericEnvID,
genericSigID,
resultInterfaceTypeID,
isIUO,
overriddenID,
@@ -2911,7 +2904,7 @@ public:
}
declOrOffset = fn;
MF.configureGenericEnvironment(fn, genericEnvID);
fn->setGenericSignature(MF.getGenericSignature(genericSigID));
if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
fn->setAccess(*accessLevel);
@@ -3295,7 +3288,7 @@ public:
DeclContextID contextID;
bool isImplicit, isObjC;
bool inheritsSuperclassInitializers;
GenericSignatureID genericEnvID;
GenericSignatureID genericSigID;
TypeID superclassID;
uint8_t rawAccessLevel;
unsigned numConformances, numInheritedTypes;
@@ -3303,7 +3296,7 @@ public:
decls_block::ClassLayout::readRecord(scratch, nameID, contextID,
isImplicit, isObjC,
inheritsSuperclassInitializers,
genericEnvID, superclassID,
genericSigID, superclassID,
rawAccessLevel, numConformances,
numInheritedTypes,
rawInheritedAndDependencyIDs);
@@ -3331,7 +3324,7 @@ public:
None, genericParams, DC);
declOrOffset = theClass;
MF.configureGenericEnvironment(theClass, genericEnvID);
theClass->setGenericSignature(MF.getGenericSignature(genericSigID));
if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
theClass->setAccess(*accessLevel);
@@ -3368,14 +3361,14 @@ public:
DeclContextID contextID;
bool isImplicit;
bool isObjC;
GenericSignatureID genericEnvID;
GenericSignatureID genericSigID;
TypeID rawTypeID;
uint8_t rawAccessLevel;
unsigned numConformances, numInherited;
ArrayRef<uint64_t> rawInheritedAndDependencyIDs;
decls_block::EnumLayout::readRecord(scratch, nameID, contextID,
isImplicit, isObjC, genericEnvID,
isImplicit, isObjC, genericSigID,
rawTypeID, rawAccessLevel,
numConformances, numInherited,
rawInheritedAndDependencyIDs);
@@ -3403,7 +3396,7 @@ public:
declOrOffset = theEnum;
MF.configureGenericEnvironment(theEnum, genericEnvID);
theEnum->setGenericSignature(MF.getGenericSignature(genericSigID));
if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
theEnum->setAccess(*accessLevel);
@@ -3518,7 +3511,7 @@ public:
StringRef blobData) {
DeclContextID contextID;
bool isImplicit, isObjC, isGetterMutating, isSetterMutating;
GenericSignatureID genericEnvID;
GenericSignatureID genericSigID;
TypeID elemInterfaceTypeID;
bool isIUO;
ModuleFile::AccessorRecord accessors;
@@ -3535,7 +3528,7 @@ public:
opaqueReadOwnership,
readImpl, writeImpl, readWriteImpl,
numAccessors,
genericEnvID,
genericSigID,
elemInterfaceTypeID,
isIUO,
overriddenID, rawAccessLevel,
@@ -3597,7 +3590,7 @@ public:
subscript->setIsSetterMutating(isSetterMutating);
declOrOffset = subscript;
MF.configureGenericEnvironment(subscript, genericEnvID);
subscript->setGenericSignature(MF.getGenericSignature(genericSigID));
subscript->setIndices(MF.readParameterList());
@@ -3642,13 +3635,13 @@ public:
DeclID extendedNominalID;
DeclContextID contextID;
bool isImplicit;
GenericSignatureID genericEnvID;
GenericSignatureID genericSigID;
unsigned numConformances, numInherited;
ArrayRef<uint64_t> inheritedAndDependencyIDs;
decls_block::ExtensionLayout::readRecord(scratch, extendedTypeID,
extendedNominalID, contextID,
isImplicit, genericEnvID,
isImplicit, genericSigID,
numConformances, numInherited,
inheritedAndDependencyIDs);
@@ -3682,7 +3675,7 @@ public:
outerParams = genericParams;
}
MF.configureGenericEnvironment(extension, genericEnvID);
extension->setGenericSignature(MF.getGenericSignature(genericSigID));
auto extendedType = MF.getType(extendedTypeID);
ctx.evaluator.cacheOutput(ExtendedTypeRequest{extension},
@@ -3726,11 +3719,11 @@ public:
StringRef blobData) {
DeclContextID contextID;
bool isImplicit, isObjC;
GenericSignatureID genericEnvID;
GenericSignatureID genericSigID;
decls_block::DestructorLayout::readRecord(scratch, contextID,
isImplicit, isObjC,
genericEnvID);
genericSigID);
DeclContext *DC = MF.getDeclContext(contextID);
if (declOrOffset.isComplete())
@@ -3742,7 +3735,7 @@ public:
if (auto bodyText = MF.maybeReadInlinableBodyText())
dtor->setBodyStringRepresentation(*bodyText);
MF.configureGenericEnvironment(dtor, genericEnvID);
dtor->setGenericSignature(MF.getGenericSignature(genericSigID));
dtor->setAccess(std::max(cast<ClassDecl>(DC)->getFormalAccess(),
AccessLevel::Internal));
@@ -5498,11 +5491,6 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
}
}
GenericEnvironment *ModuleFile::loadGenericEnvironment(const DeclContext *decl,
uint64_t contextData) {
return decl->getGenericSignatureOfContext()->getGenericEnvironment();
}
void ModuleFile::loadRequirementSignature(const ProtocolDecl *decl,
uint64_t contextData,
SmallVectorImpl<Requirement> &reqs) {

View File

@@ -554,11 +554,6 @@ private:
void readGenericRequirements(SmallVectorImpl<Requirement> &requirements,
llvm::BitstreamCursor &Cursor);
/// Set up a (potentially lazy) generic environment for the given type,
/// function or extension.
void configureGenericEnvironment(GenericContext *genericDecl,
serialization::GenericSignatureID envID);
/// Populates the protocol's default witness table.
///
/// Returns true if there is an error.
@@ -789,9 +784,6 @@ public:
virtual void finishNormalConformance(NormalProtocolConformance *conformance,
uint64_t contextData) override;
GenericEnvironment *loadGenericEnvironment(const DeclContext *decl,
uint64_t contextData) override;
void
loadRequirementSignature(const ProtocolDecl *proto, uint64_t contextData,
SmallVectorImpl<Requirement> &requirements) override;