Skip to content

Commit 3554da1

Browse files
committed
AST: Redo FunctionType canonicalization and profiling
Use the parameter list instead of the input type.
1 parent de697dc commit 3554da1

File tree

3 files changed

+116
-77
lines changed

3 files changed

+116
-77
lines changed

include/swift/AST/Types.h

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2982,10 +2982,6 @@ class AnyFunctionType : public TypeBase {
29822982
return getExtInfo().throws();
29832983
}
29842984

2985-
/// Determine whether the given function input type is one of the
2986-
/// canonical forms.
2987-
static bool isCanonicalFunctionInputType(Type input);
2988-
29892985
/// Returns a new function type exactly like this one but with the ExtInfo
29902986
/// replaced.
29912987
AnyFunctionType *withExtInfo(ExtInfo info) const;
@@ -3035,6 +3031,7 @@ inline AnyFunctionType::CanYield AnyFunctionType::Yield::getCanonical() const {
30353031
/// For example:
30363032
/// let x : (Float, Int) -> Int
30373033
class FunctionType final : public AnyFunctionType,
3034+
public llvm::FoldingSetNode,
30383035
private llvm::TrailingObjects<FunctionType, AnyFunctionType::Param> {
30393036
friend TrailingObjects;
30403037

@@ -3049,17 +3046,26 @@ class FunctionType final : public AnyFunctionType,
30493046
ArrayRef<Param> getParams() const {
30503047
return {getTrailingObjects<Param>(), getNumParams()};
30513048
}
3052-
3049+
3050+
void Profile(llvm::FoldingSetNodeID &ID) {
3051+
Profile(ID, getParams(), getResult(), getExtInfo());
3052+
}
3053+
static void Profile(llvm::FoldingSetNodeID &ID,
3054+
ArrayRef<Param> params,
3055+
Type result,
3056+
ExtInfo info);
3057+
30533058
// Implement isa/cast/dyncast/etc.
30543059
static bool classof(const TypeBase *T) {
30553060
return T->getKind() == TypeKind::Function;
30563061
}
30573062

30583063
private:
30593064
FunctionType(ArrayRef<Param> params,
3060-
Type Input, Type Result,
3061-
RecursiveTypeProperties properties,
3062-
ExtInfo Info);
3065+
Type input, Type result,
3066+
ExtInfo info,
3067+
const ASTContext *ctx,
3068+
RecursiveTypeProperties properties);
30633069
};
30643070
BEGIN_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType)
30653071
static CanFunctionType get(CanParamArrayRef params, CanType result,
@@ -3137,12 +3143,12 @@ class GenericFunctionType final : public AnyFunctionType,
31373143
FunctionType *substGenericArgs(SubstitutionMap subs);
31383144

31393145
void Profile(llvm::FoldingSetNodeID &ID) {
3140-
Profile(ID, getGenericSignature(), getInput(), getResult(),
3146+
Profile(ID, getGenericSignature(), getParams(), getResult(),
31413147
getExtInfo());
31423148
}
31433149
static void Profile(llvm::FoldingSetNodeID &ID,
31443150
GenericSignature *sig,
3145-
Type input,
3151+
ArrayRef<Param> params,
31463152
Type result,
31473153
ExtInfo info);
31483154

lib/AST/ASTContext.cpp

Lines changed: 100 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,6 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
299299
llvm::DenseMap<std::pair<Type,char>, MetatypeType*> MetatypeTypes;
300300
llvm::DenseMap<std::pair<Type,char>,
301301
ExistentialMetatypeType*> ExistentialMetatypeTypes;
302-
llvm::DenseMap<std::pair<Type,std::pair<Type,unsigned>>, FunctionType*>
303-
FunctionTypes;
304302
llvm::DenseMap<Type, ArraySliceType*> ArraySliceTypes;
305303
llvm::DenseMap<std::pair<Type, Type>, DictionaryType *> DictionaryTypes;
306304
llvm::DenseMap<Type, OptionalType*> OptionalTypes;
@@ -320,6 +318,9 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
320318
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
321319
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
322320

321+
/// The set of function types.
322+
llvm::FoldingSet<FunctionType> FunctionTypes;
323+
323324
/// The set of normal protocol conformances.
324325
llvm::FoldingSet<NormalProtocolConformance> NormalConformances;
325326

@@ -2103,7 +2104,6 @@ size_t ASTContext::Implementation::Arena::getTotalMemory() const {
21032104
// TupleTypes ?
21042105
llvm::capacity_in_bytes(MetatypeTypes) +
21052106
llvm::capacity_in_bytes(ExistentialMetatypeTypes) +
2106-
llvm::capacity_in_bytes(FunctionTypes) +
21072107
llvm::capacity_in_bytes(ArraySliceTypes) +
21082108
llvm::capacity_in_bytes(DictionaryTypes) +
21092109
llvm::capacity_in_bytes(OptionalTypes) +
@@ -2113,6 +2113,7 @@ size_t ASTContext::Implementation::Arena::getTotalMemory() const {
21132113
llvm::capacity_in_bytes(InOutTypes) +
21142114
llvm::capacity_in_bytes(DependentMemberTypes) +
21152115
llvm::capacity_in_bytes(DynamicSelfTypes);
2116+
// FunctionTypes ?
21162117
// EnumTypes ?
21172118
// StructTypes ?
21182119
// ClassTypes ?
@@ -3606,37 +3607,66 @@ DynamicSelfType *DynamicSelfType::get(Type selfType, const ASTContext &ctx) {
36063607
return result;
36073608
}
36083609

3609-
static RecursiveTypeProperties getFunctionRecursiveProperties(Type Input,
3610-
Type Result) {
3611-
// assert(!Input->hasLValueType()
3612-
// && "function should not take lvalues directly as parameters");
3613-
3614-
auto properties = Input->getRecursiveProperties()
3615-
| Result->getRecursiveProperties();
3610+
static RecursiveTypeProperties
3611+
getFunctionRecursiveProperties(ArrayRef<AnyFunctionType::Param> params,
3612+
Type result) {
3613+
RecursiveTypeProperties properties;
3614+
for (auto param : params)
3615+
properties |= param.getPlainType()->getRecursiveProperties();
3616+
properties |= result->getRecursiveProperties();
36163617
properties &= ~RecursiveTypeProperties::IsLValue;
36173618
return properties;
36183619
}
36193620

3621+
static bool
3622+
isFunctionTypeCanonical(ArrayRef<AnyFunctionType::Param> params,
3623+
Type result) {
3624+
for (auto param : params) {
3625+
if (!param.getPlainType()->isCanonical())
3626+
return false;
3627+
}
3628+
3629+
return result->isCanonical();
3630+
}
3631+
36203632
// For now, generic function types cannot be dependent (in fact,
36213633
// they erase dependence) or contain type variables, and they're
36223634
// always materializable.
36233635
static RecursiveTypeProperties
3624-
getGenericFunctionRecursiveProperties(Type Input, Type Result) {
3625-
// assert(!Input->hasLValueType()
3626-
// && "function should not take lvalues directly as parameters");
3627-
3636+
getGenericFunctionRecursiveProperties(ArrayRef<AnyFunctionType::Param> params,
3637+
Type result) {
36283638
static_assert(RecursiveTypeProperties::BitWidth == 10,
36293639
"revisit this if you add new recursive type properties");
36303640
RecursiveTypeProperties properties;
3631-
if (Input->getRecursiveProperties().hasError())
3632-
properties |= RecursiveTypeProperties::HasError;
3633-
if (Result->getRecursiveProperties().hasDynamicSelf())
3641+
3642+
for (auto param : params) {
3643+
if (param.getPlainType()->getRecursiveProperties().hasError())
3644+
properties |= RecursiveTypeProperties::HasError;
3645+
}
3646+
3647+
if (result->getRecursiveProperties().hasDynamicSelf())
36343648
properties |= RecursiveTypeProperties::HasDynamicSelf;
3635-
if (Result->getRecursiveProperties().hasError())
3649+
if (result->getRecursiveProperties().hasError())
36363650
properties |= RecursiveTypeProperties::HasError;
3651+
36373652
return properties;
36383653
}
36393654

3655+
static bool
3656+
isGenericFunctionTypeCanonical(GenericSignature *sig,
3657+
ArrayRef<AnyFunctionType::Param> params,
3658+
Type result) {
3659+
if (!sig->isCanonical())
3660+
return false;
3661+
3662+
for (auto param : params) {
3663+
if (!sig->isCanonicalTypeInContext(param.getPlainType()))
3664+
return false;
3665+
}
3666+
3667+
return sig->isCanonicalTypeInContext(result);
3668+
}
3669+
36403670
AnyFunctionType *AnyFunctionType::withExtInfo(ExtInfo info) const {
36413671
if (isa<FunctionType>(this))
36423672
return FunctionType::get(getParams(), getResult(), info,
@@ -3742,62 +3772,79 @@ void AnyFunctionType::relabelParams(MutableArrayRef<Param> params,
37423772
}
37433773
}
37443774

3775+
static void profileParams(llvm::FoldingSetNodeID &ID,
3776+
ArrayRef<AnyFunctionType::Param> params) {
3777+
ID.AddInteger(params.size());
3778+
for (auto param : params) {
3779+
ID.AddPointer(param.getLabel().get());
3780+
ID.AddPointer(param.getPlainType().getPointer());
3781+
ID.AddInteger(param.getParameterFlags().toRaw());
3782+
}
3783+
}
3784+
3785+
void FunctionType::Profile(llvm::FoldingSetNodeID &ID,
3786+
ArrayRef<AnyFunctionType::Param> params,
3787+
Type result,
3788+
ExtInfo info) {
3789+
profileParams(ID, params);
3790+
ID.AddPointer(result.getPointer());
3791+
ID.AddInteger(info.getFuncAttrKey());
3792+
}
3793+
37453794
FunctionType *FunctionType::get(ArrayRef<AnyFunctionType::Param> params,
37463795
Type result, ExtInfo info,
37473796
bool canonicalVararg) {
37483797
auto input = composeInput(result->getASTContext(), params, canonicalVararg);
3749-
auto properties = getFunctionRecursiveProperties(input, result);
3798+
auto properties = getFunctionRecursiveProperties(params, result);
37503799
auto arena = getArena(properties);
3751-
uint16_t attrKey = info.getFuncAttrKey();
37523800

3753-
const ASTContext &C = input->getASTContext();
3801+
llvm::FoldingSetNodeID id;
3802+
FunctionType::Profile(id, params, result, info);
37543803

3755-
FunctionType *&Entry
3756-
= C.getImpl().getArena(arena).FunctionTypes[{input, {result, attrKey} }];
3757-
if (Entry) return Entry;
3758-
3759-
void *mem = C.Allocate(sizeof(FunctionType) +
3760-
sizeof(AnyFunctionType::Param) * params.size(),
3761-
alignof(FunctionType), arena);
3762-
return Entry = new (mem) FunctionType(params, input, result,
3763-
properties, info);
3804+
const ASTContext &ctx = result->getASTContext();
3805+
3806+
// Do we already have this generic function type?
3807+
void *insertPos;
3808+
if (auto funcTy =
3809+
ctx.getImpl().getArena(arena).FunctionTypes.FindNodeOrInsertPos(id, insertPos)) {
3810+
return funcTy;
3811+
}
3812+
3813+
void *mem = ctx.Allocate(sizeof(FunctionType) +
3814+
sizeof(AnyFunctionType::Param) * params.size(),
3815+
alignof(FunctionType), arena);
3816+
3817+
bool isCanonical = isFunctionTypeCanonical(params, result);
3818+
auto funcTy = new (mem) FunctionType(params, input, result, info,
3819+
isCanonical ? &ctx : nullptr,
3820+
properties);
3821+
ctx.getImpl().getArena(arena).FunctionTypes.InsertNode(funcTy, insertPos);
3822+
return funcTy;
37643823
}
37653824

37663825
// If the input and result types are canonical, then so is the result.
37673826
FunctionType::FunctionType(ArrayRef<AnyFunctionType::Param> params,
37683827
Type input, Type output,
3769-
RecursiveTypeProperties properties,
3770-
ExtInfo Info)
3771-
: AnyFunctionType(TypeKind::Function,
3772-
(isCanonicalFunctionInputType(input) &&
3773-
output->isCanonical())
3774-
? &input->getASTContext()
3775-
: nullptr,
3776-
input, output, properties, params.size(), Info) {
3828+
ExtInfo info,
3829+
const ASTContext *ctx,
3830+
RecursiveTypeProperties properties)
3831+
: AnyFunctionType(TypeKind::Function, ctx,
3832+
input, output, properties, params.size(), info) {
37773833
std::uninitialized_copy(params.begin(), params.end(),
37783834
getTrailingObjects<AnyFunctionType::Param>());
37793835
}
37803836

37813837
void GenericFunctionType::Profile(llvm::FoldingSetNodeID &ID,
37823838
GenericSignature *sig,
3783-
Type input,
3839+
ArrayRef<AnyFunctionType::Param> params,
37843840
Type result,
37853841
ExtInfo info) {
37863842
ID.AddPointer(sig);
3787-
ID.AddPointer(input.getPointer());
3843+
profileParams(ID, params);
37883844
ID.AddPointer(result.getPointer());
37893845
ID.AddInteger(info.getFuncAttrKey());
37903846
}
37913847

3792-
/// If this is a ParenType, unwrap it to produce the underlying type.
3793-
/// Otherwise, return \c type.
3794-
static Type unwrapParenType(Type type) {
3795-
if (auto parenTy = dyn_cast<ParenType>(type.getPointer()))
3796-
return parenTy->getUnderlyingType();
3797-
3798-
return type;
3799-
}
3800-
38013848
GenericFunctionType *GenericFunctionType::get(GenericSignature *sig,
38023849
ArrayRef<Param> params,
38033850
Type result,
@@ -3806,10 +3853,10 @@ GenericFunctionType *GenericFunctionType::get(GenericSignature *sig,
38063853
assert(sig && "no generic signature for generic function type?!");
38073854

38083855
auto input = composeInput(result->getASTContext(), params, canonicalVararg);
3809-
assert(!input->hasTypeVariable() && !result->hasTypeVariable());
3856+
assert(!result->hasTypeVariable());
38103857

38113858
llvm::FoldingSetNodeID id;
3812-
GenericFunctionType::Profile(id, sig, input, result, info);
3859+
GenericFunctionType::Profile(id, sig, params, result, info);
38133860

38143861
const ASTContext &ctx = input->getASTContext();
38153862

@@ -3824,10 +3871,7 @@ GenericFunctionType *GenericFunctionType::get(GenericSignature *sig,
38243871
// it's canonical. Unfortunately, isCanonicalTypeInContext can cause
38253872
// new GenericFunctionTypes to be created and thus invalidate our insertion
38263873
// point.
3827-
bool isCanonical = sig->isCanonical()
3828-
&& isCanonicalFunctionInputType(input)
3829-
&& sig->isCanonicalTypeInContext(unwrapParenType(input))
3830-
&& sig->isCanonicalTypeInContext(result);
3874+
bool isCanonical = isGenericFunctionTypeCanonical(sig, params, result);
38313875

38323876
if (auto funcTy
38333877
= ctx.getImpl().GenericFunctionTypes.FindNodeOrInsertPos(id, insertPos)) {
@@ -3838,7 +3882,7 @@ GenericFunctionType *GenericFunctionType::get(GenericSignature *sig,
38383882
sizeof(AnyFunctionType::Param) * params.size(),
38393883
alignof(GenericFunctionType));
38403884

3841-
auto properties = getGenericFunctionRecursiveProperties(input, result);
3885+
auto properties = getGenericFunctionRecursiveProperties(params, result);
38423886
auto funcTy = new (mem) GenericFunctionType(sig, params, input, result, info,
38433887
isCanonical ? &ctx : nullptr,
38443888
properties);

lib/AST/Type.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2680,17 +2680,6 @@ Type ProtocolCompositionType::get(const ASTContext &C,
26802680
return build(C, CanTypes, HasExplicitAnyObject);
26812681
}
26822682

2683-
bool AnyFunctionType::isCanonicalFunctionInputType(Type input) {
2684-
// Canonically, we should have a tuple type or parenthesized type.
2685-
if (auto tupleTy = dyn_cast<TupleType>(input.getPointer()))
2686-
return tupleTy->isCanonical();
2687-
if (auto parenTy = dyn_cast<ParenType>(input.getPointer()))
2688-
return parenTy->getUnderlyingType()->isCanonical();
2689-
2690-
// FIXME: Still required for the constraint solver.
2691-
return isa<TypeVariableType>(input.getPointer());
2692-
}
2693-
26942683
FunctionType *
26952684
GenericFunctionType::substGenericArgs(SubstitutionMap subs) {
26962685
auto substFn = Type(this).subst(subs)->castTo<AnyFunctionType>();

0 commit comments

Comments
 (0)