Skip to content

Commit 4a6fe94

Browse files
authored
[Serialization] Do less work checking if a value can be deserialized. (swiftlang#9666)
Previously we recorded the canonical type of the declaration and made sure we could deserialize that, but that's a lot of extra work building up intermediate types that we mostly don't need. Instead, record smaller types that represent the possible points of failure--- right now, just the nominal types that are referenced by the value (function, variable/constant, subscript, or initializer). I chose to use types instead of declarations here because types can potentially encode more complicated constraints later (such as generic types checking that their arguments still conform). This gains us back 20% of type-checking time on a compile-time microbenchmark: `let _ = [1, 2]`. I expect the effect is less dramatic the more expressions you have, since we only need to deserialize things once.
1 parent 4a7dccd commit 4a6fe94

File tree

3 files changed

+128
-76
lines changed

3 files changed

+128
-76
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -855,12 +855,13 @@ namespace decls_block {
855855
CtorInitializerKindField, // initializer kind
856856
GenericEnvironmentIDField, // generic environment
857857
TypeIDField, // interface type
858-
TypeIDField, // canonical interface type
859858
DeclIDField, // overridden decl
860859
AccessibilityKindField, // accessibility
861860
BCFixed<1>, // requires a new vtable slot
862861
BCFixed<1>, // 'required' but overridden is not (used for recovery)
863-
BCArray<IdentifierIDField> // argument names
862+
BCVBR<5>, // number of parameter name components
863+
BCArray<IdentifierIDField> // name components,
864+
// followed by TypeID dependencies
864865
// Trailed by its generic parameters, if any, followed by the parameter
865866
// patterns.
866867
>;
@@ -876,7 +877,6 @@ namespace decls_block {
876877
BCFixed<1>, // HasNonPatternBindingInit?
877878
StorageKindField, // StorageKind
878879
TypeIDField, // interface type
879-
TypeIDField, // canonical interface type
880880
DeclIDField, // getter
881881
DeclIDField, // setter
882882
DeclIDField, // materializeForSet
@@ -886,7 +886,8 @@ namespace decls_block {
886886
DeclIDField, // didset
887887
DeclIDField, // overridden decl
888888
AccessibilityKindField, // accessibility
889-
AccessibilityKindField // setter accessibility, if applicable
889+
AccessibilityKindField, // setter accessibility, if applicable
890+
BCArray<TypeIDField> // dependencies
890891
>;
891892

892893
using ParamLayout = BCRecordLayout<
@@ -911,15 +912,16 @@ namespace decls_block {
911912
BCVBR<5>, // number of parameter patterns
912913
GenericEnvironmentIDField, // generic environment
913914
TypeIDField, // interface type
914-
TypeIDField, // canonical interface type
915915
DeclIDField, // operator decl
916916
DeclIDField, // overridden function
917917
DeclIDField, // AccessorStorageDecl
918-
BCFixed<1>, // name is compound?
918+
BCVBR<5>, // 0 for a simple name, otherwise the number of parameter name
919+
// components plus one
919920
AddressorKindField, // addressor kind
920921
AccessibilityKindField, // accessibility
921922
BCFixed<1>, // requires a new vtable slot
922-
BCArray<IdentifierIDField> // name components
923+
BCArray<IdentifierIDField> // name components,
924+
// followed by TypeID dependencies
923925
// The record is trailed by:
924926
// - its _silgen_name, if any
925927
// - its generic parameters, if any
@@ -984,7 +986,6 @@ namespace decls_block {
984986
StorageKindField, // StorageKind
985987
GenericEnvironmentIDField, // generic environment
986988
TypeIDField, // interface type
987-
TypeIDField, // canonical interface type
988989
DeclIDField, // getter
989990
DeclIDField, // setter
990991
DeclIDField, // materializeForSet
@@ -995,7 +996,9 @@ namespace decls_block {
995996
DeclIDField, // overridden decl
996997
AccessibilityKindField, // accessibility
997998
AccessibilityKindField, // setter accessibility, if applicable
998-
BCArray<IdentifierIDField> // name components
999+
BCVBR<5>, // number of parameter name components
1000+
BCArray<IdentifierIDField> // name components,
1001+
// followed by TypeID dependencies
9991002
// Trailed by:
10001003
// - generic parameters, if any
10011004
// - the indices pattern

lib/Serialization/Deserialization.cpp

Lines changed: 74 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,25 +2566,27 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
25662566
bool isImplicit, isObjC, hasStubImplementation, throws;
25672567
GenericEnvironmentID genericEnvID;
25682568
uint8_t storedInitKind, rawAccessLevel;
2569-
TypeID interfaceID, canonicalTypeID;
2569+
TypeID interfaceID;
25702570
DeclID overriddenID;
25712571
bool needsNewVTableEntry, firstTimeRequired;
2572-
ArrayRef<uint64_t> argNameIDs;
2572+
unsigned numArgNames;
2573+
ArrayRef<uint64_t> argNameAndDependencyIDs;
25732574

25742575
decls_block::ConstructorLayout::readRecord(scratch, contextID,
25752576
rawFailability, isImplicit,
25762577
isObjC, hasStubImplementation,
25772578
throws, storedInitKind,
25782579
genericEnvID, interfaceID,
2579-
canonicalTypeID, overriddenID,
2580+
overriddenID,
25802581
rawAccessLevel,
25812582
needsNewVTableEntry,
25822583
firstTimeRequired,
2583-
argNameIDs);
2584+
numArgNames,
2585+
argNameAndDependencyIDs);
25842586

25852587
// Resolve the name ids.
25862588
SmallVector<Identifier, 2> argNames;
2587-
for (auto argNameID : argNameIDs)
2589+
for (auto argNameID : argNameAndDependencyIDs.slice(0, numArgNames))
25882590
argNames.push_back(getIdentifier(argNameID));
25892591
DeclName name(ctx, ctx.Id_init, argNames);
25902592

@@ -2610,10 +2612,12 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
26102612
return llvm::make_error<OverrideError>(name, errorFlags);
26112613
}
26122614

2613-
auto canonicalType = getTypeChecked(canonicalTypeID);
2614-
if (!canonicalType) {
2615-
return llvm::make_error<TypeError>(
2616-
name, takeErrorInfo(canonicalType.takeError()), errorFlags);
2615+
for (auto dependencyID : argNameAndDependencyIDs.slice(numArgNames)) {
2616+
auto dependency = getTypeChecked(dependencyID);
2617+
if (!dependency) {
2618+
return llvm::make_error<TypeError>(
2619+
name, takeErrorInfo(dependency.takeError()), errorFlags);
2620+
}
26172621
}
26182622

26192623
auto parent = getDeclContext(contextID);
@@ -2690,18 +2694,20 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
26902694
DeclContextID contextID;
26912695
bool isImplicit, isObjC, isStatic, isLet, hasNonPatternBindingInit;
26922696
uint8_t storageKind, rawAccessLevel, rawSetterAccessLevel;
2693-
TypeID interfaceTypeID, canonicalTypeID;
2697+
TypeID interfaceTypeID;
26942698
DeclID getterID, setterID, materializeForSetID, willSetID, didSetID;
26952699
DeclID addressorID, mutableAddressorID, overriddenID;
2700+
ArrayRef<uint64_t> dependencyIDs;
26962701

26972702
decls_block::VarLayout::readRecord(scratch, nameID, contextID,
26982703
isImplicit, isObjC, isStatic, isLet,
26992704
hasNonPatternBindingInit, storageKind,
2700-
interfaceTypeID, canonicalTypeID,
2705+
interfaceTypeID,
27012706
getterID, setterID, materializeForSetID,
27022707
addressorID, mutableAddressorID,
27032708
willSetID, didSetID, overriddenID,
2704-
rawAccessLevel, rawSetterAccessLevel);
2709+
rawAccessLevel, rawSetterAccessLevel,
2710+
dependencyIDs);
27052711

27062712
Identifier name = getIdentifier(nameID);
27072713

@@ -2711,10 +2717,12 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
27112717
return llvm::make_error<OverrideError>(name);
27122718
}
27132719

2714-
auto canonicalType = getTypeChecked(canonicalTypeID);
2715-
if (!canonicalType) {
2716-
return llvm::make_error<TypeError>(
2717-
name, takeErrorInfo(canonicalType.takeError()));
2720+
for (TypeID dependencyID : dependencyIDs) {
2721+
auto dependency = getTypeChecked(dependencyID);
2722+
if (!dependency) {
2723+
return llvm::make_error<TypeError>(
2724+
name, takeErrorInfo(dependency.takeError()));
2725+
}
27182726
}
27192727

27202728
auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID);
@@ -2802,37 +2810,42 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
28022810
bool isStatic;
28032811
uint8_t rawStaticSpelling, rawAccessLevel, rawAddressorKind;
28042812
bool isObjC, isMutating, hasDynamicSelf, throws;
2805-
unsigned numParamPatterns;
2813+
unsigned numParamPatterns, numNameComponentsBiased;
28062814
GenericEnvironmentID genericEnvID;
2807-
TypeID interfaceTypeID, canonicalTypeID;
2815+
TypeID interfaceTypeID;
28082816
DeclID associatedDeclID;
28092817
DeclID overriddenID;
28102818
DeclID accessorStorageDeclID;
2811-
bool hasCompoundName, needsNewVTableEntry;
2812-
ArrayRef<uint64_t> nameIDs;
2819+
bool needsNewVTableEntry;
2820+
ArrayRef<uint64_t> nameAndDependencyIDs;
28132821

28142822
decls_block::FuncLayout::readRecord(scratch, contextID, isImplicit,
28152823
isStatic, rawStaticSpelling, isObjC,
28162824
isMutating, hasDynamicSelf, throws,
28172825
numParamPatterns, genericEnvID,
2818-
interfaceTypeID, canonicalTypeID,
2826+
interfaceTypeID,
28192827
associatedDeclID, overriddenID,
2820-
accessorStorageDeclID, hasCompoundName,
2828+
accessorStorageDeclID,
2829+
numNameComponentsBiased,
28212830
rawAddressorKind, rawAccessLevel,
2822-
needsNewVTableEntry, nameIDs);
2831+
needsNewVTableEntry,
2832+
nameAndDependencyIDs);
28232833

28242834
// Resolve the name ids.
2825-
SmallVector<Identifier, 2> names;
2826-
for (auto nameID : nameIDs)
2827-
names.push_back(getIdentifier(nameID));
2828-
2835+
Identifier baseName = getIdentifier(nameAndDependencyIDs.front());
28292836
DeclName name;
2830-
if (!names.empty()) {
2831-
if (hasCompoundName)
2832-
name = DeclName(ctx, names[0],
2833-
llvm::makeArrayRef(names.begin() + 1, names.end()));
2834-
else
2835-
name = DeclName(names[0]);
2837+
ArrayRef<uint64_t> dependencyIDs;
2838+
if (numNameComponentsBiased != 0) {
2839+
SmallVector<Identifier, 2> names;
2840+
for (auto nameID : nameAndDependencyIDs.slice(1,
2841+
numNameComponentsBiased-1)){
2842+
names.push_back(getIdentifier(nameID));
2843+
}
2844+
name = DeclName(ctx, baseName, names);
2845+
dependencyIDs = nameAndDependencyIDs.slice(numNameComponentsBiased);
2846+
} else {
2847+
name = baseName;
2848+
dependencyIDs = nameAndDependencyIDs.drop_front();
28362849
}
28372850

28382851
DeclDeserializationError::Flags errorFlags;
@@ -2845,10 +2858,12 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
28452858
return llvm::make_error<OverrideError>(name, errorFlags);
28462859
}
28472860

2848-
auto canonicalType = getTypeChecked(canonicalTypeID);
2849-
if (!canonicalType) {
2850-
return llvm::make_error<TypeError>(
2851-
name, takeErrorInfo(canonicalType.takeError()), errorFlags);
2861+
for (TypeID dependencyID : dependencyIDs) {
2862+
auto dependency = getTypeChecked(dependencyID);
2863+
if (!dependency) {
2864+
return llvm::make_error<TypeError>(
2865+
name, takeErrorInfo(dependency.takeError()), errorFlags);
2866+
}
28522867
}
28532868

28542869
auto DC = getDeclContext(contextID);
@@ -3355,28 +3370,29 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
33553370
DeclContextID contextID;
33563371
bool isImplicit, isObjC;
33573372
GenericEnvironmentID genericEnvID;
3358-
TypeID interfaceTypeID, canonicalTypeID;
3373+
TypeID interfaceTypeID;
33593374
DeclID getterID, setterID, materializeForSetID;
33603375
DeclID addressorID, mutableAddressorID, willSetID, didSetID;
33613376
DeclID overriddenID;
33623377
uint8_t rawAccessLevel, rawSetterAccessLevel;
33633378
uint8_t rawStorageKind;
3364-
ArrayRef<uint64_t> argNameIDs;
3379+
unsigned numArgNames;
3380+
ArrayRef<uint64_t> argNameAndDependencyIDs;
33653381

33663382
decls_block::SubscriptLayout::readRecord(scratch, contextID,
33673383
isImplicit, isObjC, rawStorageKind,
33683384
genericEnvID,
3369-
interfaceTypeID, canonicalTypeID,
3385+
interfaceTypeID,
33703386
getterID, setterID,
33713387
materializeForSetID,
33723388
addressorID, mutableAddressorID,
33733389
willSetID, didSetID,
33743390
overriddenID, rawAccessLevel,
3375-
rawSetterAccessLevel,
3376-
argNameIDs);
3391+
rawSetterAccessLevel, numArgNames,
3392+
argNameAndDependencyIDs);
33773393
// Resolve the name ids.
33783394
SmallVector<Identifier, 2> argNames;
3379-
for (auto argNameID : argNameIDs)
3395+
for (auto argNameID : argNameAndDependencyIDs.slice(0, numArgNames))
33803396
argNames.push_back(getIdentifier(argNameID));
33813397
DeclName name(ctx, ctx.Id_subscript, argNames);
33823398

@@ -3386,10 +3402,12 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
33863402
return llvm::make_error<OverrideError>(name);
33873403
}
33883404

3389-
auto canonicalType = getTypeChecked(canonicalTypeID);
3390-
if (!canonicalType) {
3391-
return llvm::make_error<TypeError>(
3392-
name, takeErrorInfo(canonicalType.takeError()));
3405+
for (TypeID dependencyID : argNameAndDependencyIDs.slice(numArgNames)) {
3406+
auto dependency = getTypeChecked(dependencyID);
3407+
if (!dependency) {
3408+
return llvm::make_error<TypeError>(
3409+
name, takeErrorInfo(dependency.takeError()));
3410+
}
33933411
}
33943412

33953413
auto parent = getDeclContext(contextID);
@@ -4379,8 +4397,15 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
43794397
decls_block::UnboundGenericTypeLayout::readRecord(scratch,
43804398
genericID, parentID);
43814399

4382-
auto genericDecl = cast<GenericTypeDecl>(getDecl(genericID));
4383-
typeOrOffset = UnboundGenericType::get(genericDecl, getType(parentID), ctx);
4400+
auto nominalOrError = getDeclChecked(genericID);
4401+
if (!nominalOrError)
4402+
return nominalOrError.takeError();
4403+
auto genericDecl = cast<GenericTypeDecl>(nominalOrError.get());
4404+
4405+
// FIXME: Check this?
4406+
auto parentTy = getType(parentID);
4407+
4408+
typeOrOffset = UnboundGenericType::get(genericDecl, parentTy, ctx);
43844409
break;
43854410
}
43864411

0 commit comments

Comments
 (0)