Skip to content

Commit 4c60e03

Browse files
authored
Merge pull request swiftlang#79882 from slavapestov/sizeof-constraint
Sema: Optimize Constraint layout to save 24 bytes
2 parents 9560b86 + 6d90d16 commit 4c60e03

File tree

7 files changed

+176
-152
lines changed

7 files changed

+176
-152
lines changed

include/swift/Sema/Constraint.h

+47-52
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,8 @@ class Constraint final : public llvm::ilist_node<Constraint>,
336336
private llvm::TrailingObjects<Constraint,
337337
TypeVariableType *,
338338
ConstraintFix *,
339+
DeclContext *,
340+
ContextualTypeInfo,
339341
OverloadChoice> {
340342
friend TrailingObjects;
341343

@@ -345,9 +347,17 @@ class Constraint final : public llvm::ilist_node<Constraint>,
345347
/// The kind of restriction placed on this constraint.
346348
ConversionRestrictionKind Restriction : 8;
347349

348-
/// Whether we have a fix.
350+
/// The number of type variables referenced by this constraint.
351+
///
352+
/// The type variables themselves are tail-allocated.
353+
unsigned NumTypeVariables : 11;
354+
355+
/// Whether we have a tail-allocated fix.
349356
unsigned HasFix : 1;
350357

358+
/// Whether we have a tail-allocated DeclContext.
359+
unsigned HasDeclContext : 1;
360+
351361
/// Whether the \c Restriction field is valid.
352362
unsigned HasRestriction : 1;
353363

@@ -375,14 +385,19 @@ class Constraint final : public llvm::ilist_node<Constraint>,
375385
/// the rest of the constraint system. Currently only applies to conjunctions.
376386
unsigned IsIsolated : 1;
377387

378-
/// The number of type variables referenced by this constraint.
379-
///
380-
/// The type variables themselves are tail-allocated.
381-
unsigned NumTypeVariables : 11;
382-
383388
/// The kind of function reference, for member references.
384389
unsigned TheFunctionRefInfo : 3;
385390

391+
/// The trailing closure matching for an applicable function constraint,
392+
/// if any. 0 = None, 1 = Forward, 2 = Backward.
393+
unsigned trailingClosureMatching : 2;
394+
395+
/// For a SyntacticElement constraint, identify whether the result of this
396+
/// node is unused.
397+
unsigned isDiscarded : 1;
398+
399+
// 22 bits remaining
400+
386401
union {
387402
struct {
388403
/// The first type.
@@ -414,29 +429,19 @@ class Constraint final : public llvm::ilist_node<Constraint>,
414429
/// Used for ValueWitness constraints.
415430
ValueDecl *Ref;
416431
} Member;
417-
418-
/// The DC in which the use appears.
419-
DeclContext *UseDC;
420432
} Member;
421433

422434
/// The set of constraints for a disjunction.
423435
ArrayRef<Constraint *> Nested;
424436

425437
struct {
426-
/// The first type
438+
/// The first type.
427439
Type First;
428-
429-
/// The DC in which the use appears.
430-
DeclContext *UseDC;
431440
} Overload;
432441

433442
struct {
434443
/// The node itself.
435444
ASTNode Element;
436-
/// Contextual information associated with the element (if any).
437-
ContextualTypeInfo Context;
438-
/// Identifies whether result of this node is unused.
439-
bool IsDiscarded;
440445
} SyntacticElement;
441446

442447
struct {
@@ -447,11 +452,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
447452
/// The type being called, primarily a function type, but could
448453
/// be a metatype, a tuple or a nominal type.
449454
Type Callee;
450-
/// The trailing closure matching for an applicable function constraint,
451-
/// if any. 0 = None, 1 = Forward, 2 = Backward.
452-
unsigned TrailingClosureMatching : 2;
453-
/// The declaration context in which the application appears.
454-
DeclContext *UseDC;
455455
} Apply;
456456
};
457457

@@ -527,6 +527,14 @@ class Constraint final : public llvm::ilist_node<Constraint>,
527527
return HasFix ? 1 : 0;
528528
}
529529

530+
size_t numTrailingObjects(OverloadToken<DeclContext *>) const {
531+
return HasDeclContext ? 1 : 0;
532+
}
533+
534+
size_t numTrailingObjects(OverloadToken<ContextualTypeInfo>) const {
535+
return Kind == ConstraintKind::SyntacticElement ? 1 : 0;
536+
}
537+
530538
size_t numTrailingObjects(OverloadToken<OverloadChoice>) const {
531539
return Kind == ConstraintKind::BindOverload ? 1 : 0;
532540
}
@@ -604,15 +612,15 @@ class Constraint final : public llvm::ilist_node<Constraint>,
604612
DeclContext *useDC, ConstraintLocator *locator);
605613

606614
static Constraint *createSyntacticElement(ConstraintSystem &cs,
607-
ASTNode node,
608-
ConstraintLocator *locator,
609-
bool isDiscarded = false);
615+
ASTNode node,
616+
ConstraintLocator *locator,
617+
bool isDiscarded = false);
610618

611619
static Constraint *createSyntacticElement(ConstraintSystem &cs,
612-
ASTNode node,
613-
ContextualTypeInfo context,
614-
ConstraintLocator *locator,
615-
bool isDiscarded = false);
620+
ASTNode node,
621+
ContextualTypeInfo context,
622+
ConstraintLocator *locator,
623+
bool isDiscarded = false);
616624

617625
/// Determine the kind of constraint.
618626
ConstraintKind getKind() const { return Kind; }
@@ -864,24 +872,10 @@ class Constraint final : public llvm::ilist_node<Constraint>,
864872

865873
/// Retrieve the overload choice for an overload-binding constraint.
866874
OverloadChoice getOverloadChoice() const {
867-
assert(Kind == ConstraintKind::BindOverload);
875+
ASSERT(Kind == ConstraintKind::BindOverload);
868876
return *getTrailingObjects<OverloadChoice>();
869877
}
870878

871-
/// Retrieve the DC in which the overload was used.
872-
DeclContext *getOverloadUseDC() const {
873-
assert(Kind == ConstraintKind::BindOverload);
874-
return Overload.UseDC;
875-
}
876-
877-
/// Retrieve the DC in which the member was used.
878-
DeclContext *getMemberUseDC() const {
879-
assert(Kind == ConstraintKind::ValueMember ||
880-
Kind == ConstraintKind::UnresolvedValueMember ||
881-
Kind == ConstraintKind::ValueWitness);
882-
return Member.UseDC;
883-
}
884-
885879
FunctionType *getAppliedFunctionType() const {
886880
assert(Kind == ConstraintKind::ApplicableFunction);
887881
return Apply.AppliedFn;
@@ -892,24 +886,25 @@ class Constraint final : public llvm::ilist_node<Constraint>,
892886
return Apply.Callee;
893887
}
894888

895-
DeclContext *getApplicationDC() const {
896-
assert(Kind == ConstraintKind::ApplicableFunction);
897-
return Apply.UseDC;
898-
}
899-
900889
ASTNode getSyntacticElement() const {
901890
assert(Kind == ConstraintKind::SyntacticElement);
902891
return SyntacticElement.Element;
903892
}
904893

905894
ContextualTypeInfo getElementContext() const {
906-
assert(Kind == ConstraintKind::SyntacticElement);
907-
return SyntacticElement.Context;
895+
ASSERT(Kind == ConstraintKind::SyntacticElement);
896+
return *getTrailingObjects<ContextualTypeInfo>();
908897
}
909898

910899
bool isDiscardedElement() const {
911900
assert(Kind == ConstraintKind::SyntacticElement);
912-
return SyntacticElement.IsDiscarded;
901+
return isDiscarded;
902+
}
903+
904+
/// Retrieve the DC in which the overload was used.
905+
DeclContext *getDeclContext() const {
906+
ASSERT(HasDeclContext);
907+
return *getTrailingObjects<DeclContext *>();
913908
}
914909

915910
/// For an applicable function constraint, retrieve the trailing closure

include/swift/Sema/ConstraintSolverStats.def

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# error #define CS_STATISTIC(Name, Description) before including
1919
#endif
2020

21+
CS_STATISTIC(ASTBytesAllocated, "bytes allocated in solver arena")
2122
CS_STATISTIC(NumTypeVariablesBound, "# of type variables bound")
2223
CS_STATISTIC(NumTypeVariableBindings, "# of type variable bindings attempted")
2324
CS_STATISTIC(NumDisjunctions, "# of disjunctions explored")

lib/AST/ASTContext.cpp

+22-29
Original file line numberDiff line numberDiff line change
@@ -575,12 +575,6 @@ struct ASTContext::Implementation {
575575
/// The set of function types.
576576
llvm::FoldingSet<FunctionType> FunctionTypes;
577577

578-
/// The set of normal protocol conformances.
579-
llvm::FoldingSet<NormalProtocolConformance> NormalConformances;
580-
581-
// The set of self protocol conformances.
582-
llvm::DenseMap<ProtocolDecl*, SelfProtocolConformance*> SelfConformances;
583-
584578
/// The set of specialized protocol conformances.
585579
llvm::FoldingSet<SpecializedProtocolConformance> SpecializedConformances;
586580

@@ -597,9 +591,6 @@ struct ASTContext::Implementation {
597591
/// The set of substitution maps (uniqued by their storage).
598592
llvm::FoldingSet<SubstitutionMap::Storage> SubstitutionMaps;
599593

600-
/// The set of unique AvailabilityContexts (uniqued by their storage).
601-
llvm::FoldingSet<AvailabilityContext::Storage> AvailabilityContexts;
602-
603594
~Arena() {
604595
for (auto &conformance : SpecializedConformances)
605596
conformance.~SpecializedProtocolConformance();
@@ -613,11 +604,6 @@ struct ASTContext::Implementation {
613604
#if SWIFT_COMPILER_IS_MSVC
614605
#pragma warning (default: 4189)
615606
#endif
616-
617-
// Call the normal conformance destructors last since they could be
618-
// referenced by the other conformance types.
619-
for (auto &conformance : NormalConformances)
620-
conformance.~NormalProtocolConformance();
621607
}
622608

623609
size_t getTotalMemory() const;
@@ -645,6 +631,11 @@ struct ASTContext::Implementation {
645631
AutoDiffDerivativeFunctionIdentifiers;
646632

647633
llvm::FoldingSet<GenericSignatureImpl> GenericSignatures;
634+
llvm::FoldingSet<NormalProtocolConformance> NormalConformances;
635+
llvm::DenseMap<ProtocolDecl*, SelfProtocolConformance*> SelfConformances;
636+
637+
/// The set of unique AvailabilityContexts (uniqued by their storage).
638+
llvm::FoldingSet<AvailabilityContext::Storage> AvailabilityContexts;
648639

649640
/// A cache of information about whether particular nominal types
650641
/// are representable in a foreign language.
@@ -720,6 +711,9 @@ ASTContext::Implementation::Implementation()
720711
: IdentifierTable(Allocator),
721712
IntrinsicScratchContext(new llvm::LLVMContext()) {}
722713
ASTContext::Implementation::~Implementation() {
714+
for (auto &conformance : NormalConformances)
715+
conformance.~NormalProtocolConformance();
716+
723717
for (auto &cleanup : Cleanups)
724718
cleanup();
725719
}
@@ -889,6 +883,9 @@ void ASTContext::Implementation::dump(llvm::raw_ostream &os) const {
889883
SIZE_AND_BYTES(SILMoveOnlyWrappedTypes);
890884
SIZE_AND_BYTES(BuiltinIntegerTypes);
891885
SIZE_AND_BYTES(OpenedElementEnvironments);
886+
SIZE(NormalConformances);
887+
SIZE(SelfConformances);
888+
SIZE(AvailabilityContexts);
892889
SIZE_AND_BYTES(ForeignRepresentableCache);
893890
SIZE(SearchPathsSet);
894891

@@ -2912,15 +2909,14 @@ ASTContext::getNormalConformance(Type conformingType,
29122909

29132910
// Did we already record the normal conformance?
29142911
void *insertPos;
2915-
auto &normalConformances =
2916-
getImpl().getArena(AllocationArena::Permanent).NormalConformances;
2912+
auto &normalConformances = getImpl().NormalConformances;
29172913
if (auto result = normalConformances.FindNodeOrInsertPos(id, insertPos))
29182914
return result;
29192915

29202916
// Build a new normal protocol conformance.
2921-
auto result = new (*this, AllocationArena::Permanent)
2922-
NormalProtocolConformance(conformingType, protocol, loc, dc, state,
2923-
options, preconcurrencyLoc);
2917+
auto result = new (*this) NormalProtocolConformance(
2918+
conformingType, protocol, loc, dc, state,
2919+
options, preconcurrencyLoc);
29242920
normalConformances.InsertNode(result, insertPos);
29252921

29262922
return result;
@@ -2929,12 +2925,11 @@ ASTContext::getNormalConformance(Type conformingType,
29292925
/// Produce a self-conformance for the given protocol.
29302926
SelfProtocolConformance *
29312927
ASTContext::getSelfConformance(ProtocolDecl *protocol) {
2932-
auto &selfConformances =
2933-
getImpl().getArena(AllocationArena::Permanent).SelfConformances;
2928+
auto &selfConformances = getImpl().SelfConformances;
29342929
auto &entry = selfConformances[protocol];
29352930
if (!entry) {
2936-
entry = new (*this, AllocationArena::Permanent)
2937-
SelfProtocolConformance(protocol->getDeclaredExistentialType());
2931+
entry = new (*this) SelfProtocolConformance(
2932+
protocol->getDeclaredExistentialType());
29382933
}
29392934
return entry;
29402935
}
@@ -3274,6 +3269,9 @@ size_t ASTContext::getTotalMemory() const {
32743269
// getImpl().GenericSignatures ?
32753270
// getImpl().CompoundNames ?
32763271
// getImpl().IntegerTypes ?
3272+
// getImpl().NormalConformances ?
3273+
// getImpl().SelfConformances ?
3274+
// getImpl().AvailabilityContexts
32773275
getImpl().Permanent.getTotalMemory();
32783276

32793277
Size += getSolverMemory();
@@ -3315,7 +3313,6 @@ size_t ASTContext::Implementation::Arena::getTotalMemory() const {
33153313
// FunctionTypes ?
33163314
// UnboundGenericTypes ?
33173315
// BoundGenericTypes ?
3318-
// NormalConformances ?
33193316
// SpecializedConformances ?
33203317
// InheritedConformances ?
33213318
// BuiltinConformances ?
@@ -3360,14 +3357,11 @@ void ASTContext::Implementation::Arena::dump(llvm::raw_ostream &os) const {
33603357
SIZE_AND_BYTES(OpaqueArchetypeEnvironments);
33613358
SIZE_AND_BYTES(OpenedExistentialEnvironments);
33623359
SIZE(FunctionTypes);
3363-
SIZE(NormalConformances);
3364-
SIZE(SelfConformances);
33653360
SIZE(SpecializedConformances);
33663361
SIZE(InheritedConformances);
33673362
SIZE_AND_BYTES(BuiltinConformances);
33683363
SIZE(PackConformances);
33693364
SIZE(SubstitutionMaps);
3370-
SIZE(AvailabilityContexts);
33713365

33723366
#undef SIZE
33733367
#undef SIZE_AND_BYTES
@@ -5720,8 +5714,7 @@ const AvailabilityContext::Storage *AvailabilityContext::Storage::get(
57205714
AvailabilityContext::Storage::Profile(id, platformRange, isDeprecated,
57215715
domainInfos);
57225716

5723-
auto &foldingSet =
5724-
ctx.getImpl().getArena(AllocationArena::Permanent).AvailabilityContexts;
5717+
auto &foldingSet = ctx.getImpl().AvailabilityContexts;
57255718
void *insertPos;
57265719
auto *existing = foldingSet.FindNodeOrInsertPos(id, insertPos);
57275720
if (existing)

lib/Sema/CSSimplify.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -13118,7 +13118,7 @@ bool ConstraintSystem::simplifyAppliedOverloadsImpl(
1311813118
// Determine the type that this choice will have.
1311913119
Type choiceType = getEffectiveOverloadType(
1312013120
constraint->getLocator(), choice, /*allowMembers=*/true,
13121-
constraint->getOverloadUseDC());
13121+
constraint->getDeclContext());
1312213122
if (!choiceType) {
1312313123
hasUnhandledConstraints = true;
1312413124
return true;
@@ -16364,7 +16364,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
1636416364
return simplifyApplicableFnConstraint(
1636516365
constraint.getAppliedFunctionType(), constraint.getCalleeType(),
1636616366
constraint.getTrailingClosureMatching(),
16367-
constraint.getApplicationDC(), /*flags=*/std::nullopt,
16367+
constraint.getDeclContext(), /*flags=*/std::nullopt,
1636816368
constraint.getLocator());
1636916369

1637016370
case ConstraintKind::DynamicCallableApplicableFunction:
@@ -16411,7 +16411,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
1641116411

1641216412
resolveOverload(constraint.getLocator(), constraint.getFirstType(),
1641316413
constraint.getOverloadChoice(),
16414-
constraint.getOverloadUseDC());
16414+
constraint.getDeclContext());
1641516415
return SolutionKind::Solved;
1641616416

1641716417
case ConstraintKind::SubclassOf:
@@ -16458,7 +16458,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
1645816458
case ConstraintKind::UnresolvedValueMember:
1645916459
return simplifyMemberConstraint(
1646016460
constraint.getKind(), constraint.getFirstType(), constraint.getMember(),
16461-
constraint.getSecondType(), constraint.getMemberUseDC(),
16461+
constraint.getSecondType(), constraint.getDeclContext(),
1646216462
constraint.getFunctionRefInfo(),
1646316463
/*outerAlternatives=*/{},
1646416464
/*flags*/ std::nullopt, constraint.getLocator());
@@ -16467,7 +16467,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
1646716467
return simplifyValueWitnessConstraint(
1646816468
constraint.getKind(), constraint.getFirstType(),
1646916469
constraint.getRequirement(), constraint.getSecondType(),
16470-
constraint.getMemberUseDC(), constraint.getFunctionRefInfo(),
16470+
constraint.getDeclContext(), constraint.getFunctionRefInfo(),
1647116471
/*flags*/ std::nullopt, constraint.getLocator());
1647216472

1647316473
case ConstraintKind::Defaultable:

0 commit comments

Comments
 (0)