Skip to content

Commit

Permalink
AST: Have SubstitutionMaps manage the memory for the conformance array
Browse files Browse the repository at this point in the history
  • Loading branch information
slavapestov committed Jan 18, 2017
1 parent 6a926d1 commit 24b2531
Show file tree
Hide file tree
Showing 11 changed files with 45 additions and 77 deletions.
4 changes: 2 additions & 2 deletions include/swift/AST/SubstitutionMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class SubstitutionMap {
using ParentType = std::pair<CanType, AssociatedTypeDecl *>;

llvm::DenseMap<SubstitutableType *, Type> subMap;
llvm::DenseMap<TypeBase *, ArrayRef<ProtocolConformanceRef>> conformanceMap;
llvm::DenseMap<TypeBase *, SmallVector<ProtocolConformanceRef, 1>> conformanceMap;
llvm::DenseMap<TypeBase *, SmallVector<ParentType, 1>> parentMap;

Optional<ProtocolConformanceRef>
Expand All @@ -66,7 +66,7 @@ class SubstitutionMap {

void addSubstitution(CanSubstitutableType type, Type replacement);

void addConformances(CanType type, ArrayRef<ProtocolConformanceRef> conformances);
void addConformance(CanType type, ProtocolConformanceRef conformance);

void addParent(CanType type, CanType parent,
AssociatedTypeDecl *assocType);
Expand Down
3 changes: 2 additions & 1 deletion lib/AST/GenericEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,8 @@ getSubstitutionMap(ModuleDecl *mod,
// Record the replacement type and its conformances.
if (auto *archetype = contextTy->getAs<ArchetypeType>()) {
result.addSubstitution(CanArchetypeType(archetype), sub.getReplacement());
result.addConformances(CanType(archetype), sub.getConformances());
for (auto conformance : sub.getConformances())
result.addConformance(CanType(archetype), conformance);
continue;
}

Expand Down
6 changes: 3 additions & 3 deletions lib/AST/GenericSignature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,11 +313,11 @@ GenericSignature::getSubstitutionMap(ArrayRef<Substitution> subs,
subs = subs.slice(1);

auto canTy = depTy->getCanonicalType();
if (isa<SubstitutableType>(canTy)) {
if (isa<SubstitutableType>(canTy))
result.addSubstitution(cast<SubstitutableType>(canTy),
sub.getReplacement());
}
result.addConformances(canTy, sub.getConformances());
for (auto conformance : sub.getConformances())
result.addConformance(canTy, conformance);
}

for (auto reqt : getRequirements()) {
Expand Down
23 changes: 5 additions & 18 deletions lib/AST/SubstitutionMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,8 @@ addSubstitution(CanSubstitutableType type, Type replacement) {
}

void SubstitutionMap::
addConformances(CanType type, ArrayRef<ProtocolConformanceRef> conformances) {
if (conformances.empty())
return;

auto result = conformanceMap.insert(
std::make_pair(type.getPointer(), conformances));
assert(result.second ||
result.first->getSecond().size() == conformances.size());
(void) result;
addConformance(CanType type, ProtocolConformanceRef conformance) {
conformanceMap[type.getPointer()].push_back(conformance);
}

ArrayRef<ProtocolConformanceRef> SubstitutionMap::
Expand Down Expand Up @@ -172,8 +165,6 @@ SubstitutionMap::getOverrideSubstitutions(const ClassDecl *baseClass,

// Map the innermost generic parameters of the derived function to
// the base.
auto &ctx = baseClass->getASTContext();

auto baseParams = baseSig->getInnermostGenericParams();
if (baseParams.back()->getDepth() >= minDepth) {
assert(derivedSig);
Expand Down Expand Up @@ -203,21 +194,17 @@ SubstitutionMap::getOverrideSubstitutions(const ClassDecl *baseClass,
auto canTy = t->getCanonicalType();

if (isRootedInInnermostParameter(t)) {
auto conformances =
ctx.AllocateUninitialized<ProtocolConformanceRef>(
reqs.size());
for (unsigned i = 0, e = reqs.size(); i < e; i++) {
auto reqt = reqs[i];
assert(reqt.getKind() == RequirementKind::Conformance);
auto *proto = reqt.getSecondType()
->castTo<ProtocolType>()->getDecl();
if (derivedSubs)
conformances[i] = *derivedSubs->lookupConformance(canTy, proto);
subMap.addConformance(canTy, *derivedSubs->lookupConformance(
canTy, proto));
else
conformances[i] = ProtocolConformanceRef(proto);
subMap.addConformance(canTy, ProtocolConformanceRef(proto));
}

subMap.addConformances(canTy, conformances);
}

return false;
Expand Down
4 changes: 1 addition & 3 deletions lib/SILGen/SILGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1776,9 +1776,7 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance,
specialized = ctx.getSpecializedConformance(concreteTy, conformance,
concreteSubs);

SmallVector<ProtocolConformanceRef, 1> conformances;
conformances.push_back(ProtocolConformanceRef(specialized));
reqtSubs.addConformances(selfTy, ctx.AllocateCopy(conformances));
reqtSubs.addConformance(selfTy, ProtocolConformanceRef(specialized));

auto input = reqtOrigTy->getInput().subst(reqtSubs)->getCanonicalType();
auto result = reqtOrigTy->getResult().subst(reqtSubs)->getCanonicalType();
Expand Down
26 changes: 11 additions & 15 deletions lib/SILGen/SILGenPoly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2456,18 +2456,6 @@ buildThunkSignature(SILGenFunction &gen,
[&](Type depTy, ArrayRef<Requirement> reqs) -> bool {
auto canTy = depTy->getCanonicalType();

// Add abstract conformances.
auto conformances =
ctx.AllocateUninitialized<ProtocolConformanceRef>(
reqs.size());
for (unsigned i = 0, e = reqs.size(); i < e; i++) {
auto reqt = reqs[i];
assert(reqt.getKind() == RequirementKind::Conformance);
auto *proto = reqt.getSecondType()
->castTo<ProtocolType>()->getDecl();
conformances[i] = ProtocolConformanceRef(proto);
}

ArchetypeType *oldArchetype;
// The opened existential archetype maps to the new generic parameter's
// archetype.
Expand All @@ -2484,11 +2472,19 @@ buildThunkSignature(SILGenFunction &gen,

if (isa<SubstitutableType>(canTy)) {
interfaceSubs.addSubstitution(cast<SubstitutableType>(canTy),
oldArchetype);
oldArchetype);
}

contextSubs.addConformances(CanType(oldArchetype), conformances);
interfaceSubs.addConformances(canTy, conformances);
// Add abstract conformances.
for (unsigned i = 0, e = reqs.size(); i < e; i++) {
auto reqt = reqs[i];
assert(reqt.getKind() == RequirementKind::Conformance);
auto *proto = reqt.getSecondType()
->castTo<ProtocolType>()->getDecl();
auto conformance = ProtocolConformanceRef(proto);
contextSubs.addConformance(CanType(oldArchetype), conformance);
interfaceSubs.addConformance(canTy, conformance);
}

return false;
});
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ SILCombiner::createApplyWithConcreteType(FullApplySite AI,
} else {
SubstitutionMap Subs;
Subs.addSubstitution(CanArchetypeType(OpenedArchetype), ConcreteType);
Subs.addConformances(CanType(OpenedArchetype), Conformance);
Subs.addConformance(CanType(OpenedArchetype), Conformance);
NewSubstCalleeType = SubstCalleeType.subst(AI.getModule(), Subs);
}

Expand Down
10 changes: 7 additions & 3 deletions lib/SILOptimizer/Utils/Devirtualize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,9 @@ getSubstitutionsForCallee(SILModule &M,
subMap.addSubstitution(cast<SubstitutableType>(canTy),
sub.getReplacement());
}
subMap.addConformances(canTy, sub.getConformances());

for (auto conformance : sub.getConformances())
subMap.addConformance(canTy, conformance);
}
assert(origSubs.empty());
}
Expand Down Expand Up @@ -849,7 +851,8 @@ static void getWitnessMethodSubstitutions(
auto gp = cast<GenericTypeParamType>(witnessThunkSig->getGenericParams()
.front()->getCanonicalType());
subMap.addSubstitution(gp, origSubs.front().getReplacement());
subMap.addConformances(gp, origSubs.front().getConformances());
for (auto conformance : origSubs.front().getConformances())
subMap.addConformance(gp, conformance);

// For default witnesses, innermost generic parameters are always at
// depth 1.
Expand Down Expand Up @@ -916,7 +919,8 @@ static void getWitnessMethodSubstitutions(
subMap.addSubstitution(cast<SubstitutableType>(canTy),
sub.getReplacement());
}
subMap.addConformances(canTy, sub.getConformances());
for (auto conformance : sub.getConformances())
subMap.addConformance(canTy, conformance);
}
assert(subs.empty() && "Did not consume all substitutions");
}
Expand Down
20 changes: 2 additions & 18 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1445,26 +1445,11 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
}

// Capture the conformances needed for the substitution map.
CanType currentType;
SmallVector<ProtocolConformanceRef, 4> currentConformances;
auto flushConformances = [&] {
subMap.addConformances(currentType,
TC.Context.AllocateCopy(currentConformances));
currentConformances.clear();
};

for (const auto &req : genericSig->getRequirements()) {
// If we're on to a new dependent type, flush the conformances gathered
// thus far.
CanType canFirstType = req.getFirstType()->getCanonicalType();
if (canFirstType != currentType) {
if (currentType) flushConformances();
currentType = canFirstType;
}

switch (req.getKind()) {
case RequirementKind::Conformance: {
// Get the conformance and record it.
auto origType = req.getFirstType()->getCanonicalType();
auto firstType = req.getFirstType().subst(subMap);
auto protoType = req.getSecondType()->castTo<ProtocolType>();
auto conformance =
Expand All @@ -1481,7 +1466,7 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
return;
}

currentConformances.push_back(*conformance);
subMap.addConformance(origType, *conformance);
break;
}
case RequirementKind::Superclass: {
Expand Down Expand Up @@ -1514,7 +1499,6 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
}
}
}
if (currentType) flushConformances();

// Compute the substitutions.
SmallVector<Substitution, 4> substitutions;
Expand Down
18 changes: 9 additions & 9 deletions lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1009,11 +1009,11 @@ RequirementEnvironment::RequirementEnvironment(
{
SmallVector<ProtocolConformanceRef, 1> conformances;
if (specialized)
conformances.push_back(ProtocolConformanceRef(specialized));
reqToSyntheticEnvMap.addConformance(
selfType, ProtocolConformanceRef(specialized));
else
conformances.push_back(ProtocolConformanceRef(proto));
reqToSyntheticEnvMap.addConformances(selfType,
ctx.AllocateCopy(conformances));
reqToSyntheticEnvMap.addConformance(
selfType, ProtocolConformanceRef(proto));
}

// Construct an archetype builder by collecting the constraints from the
Expand Down Expand Up @@ -1067,11 +1067,11 @@ RequirementEnvironment::RequirementEnvironment(
if (auto archetypeType
= reqEnv->mapTypeIntoContext(genericParam)->getAs<ArchetypeType>()) {
// Add substitutions.
SmallVector<ProtocolConformanceRef, 1> conformances;
for (auto proto : archetypeType->getConformsTo())
conformances.push_back(ProtocolConformanceRef(proto));
reqToSyntheticEnvMap.addConformances(genericParam->getCanonicalType(),
ctx.AllocateCopy(conformances));
for (auto proto : archetypeType->getConformsTo()) {
reqToSyntheticEnvMap.addConformance(
genericParam->getCanonicalType(),
ProtocolConformanceRef(proto));
}
}
}

Expand Down
6 changes: 2 additions & 4 deletions lib/Serialization/Deserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4335,12 +4335,10 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
reqToSyntheticMap.addSubstitution(canonicalGP, concreteTy);

if (unsigned numConformances = *rawIDIter++) {
SmallVector<ProtocolConformanceRef, 2> conformances;
while (numConformances--) {
conformances.push_back(readConformance(DeclTypeCursor));
reqToSyntheticMap.addConformance(
canonicalGP, readConformance(DeclTypeCursor));
}
reqToSyntheticMap.addConformances(canonicalGP,
ctx.AllocateCopy(conformances));
}
}
}
Expand Down

0 comments on commit 24b2531

Please sign in to comment.