Skip to content

Commit 3866bd2

Browse files
authored
Merge pull request #13312 from slavapestov/class-resilience-part-3
Class resilience part 3
2 parents 0a6abb5 + 5dcc6b1 commit 3866bd2

14 files changed

+108
-149
lines changed

include/swift/Runtime/Metadata.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2869,16 +2869,11 @@ void swift_initStructMetadata_UniversalStrategy(size_t numFields,
28692869

28702870
/// Initialize the field offset vector for a dependent-layout class, using the
28712871
/// "Universal" layout strategy.
2872-
///
2873-
/// This will relocate the metadata if it doesn't have enough space
2874-
/// for its superclass. Note that swift_allocateGenericClassMetadata will
2875-
/// never produce a metadata that requires relocation.
28762872
SWIFT_RUNTIME_EXPORT
2877-
ClassMetadata *
2878-
swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
2879-
size_t numFields,
2880-
const TypeLayout * const *fieldTypes,
2881-
size_t *fieldOffsets);
2873+
void swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
2874+
size_t numFields,
2875+
const TypeLayout * const *fieldTypes,
2876+
size_t *fieldOffsets);
28822877

28832878
/// \brief Fetch a uniqued metadata for a metatype type.
28842879
SWIFT_RUNTIME_EXPORT

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -946,13 +946,13 @@ FUNCTION(GetExistentialMetadata,
946946
ATTRS(NoUnwind, ReadOnly))
947947

948948
// struct FieldInfo { size_t Size; size_t AlignMask; };
949-
// Metadata *swift_initClassMetadata_UniversalStrategy(Metadata *self,
950-
// size_t numFields,
951-
// TypeLayout * const *fieldTypes,
952-
// size_t *fieldOffsets);
949+
// void swift_initClassMetadata_UniversalStrategy(Metadata *self,
950+
// size_t numFields,
951+
// TypeLayout * const *fieldTypes,
952+
// size_t *fieldOffsets);
953953
FUNCTION(InitClassMetadataUniversal,
954954
swift_initClassMetadata_UniversalStrategy, DefaultCC,
955-
RETURNS(TypeMetadataPtrTy),
955+
RETURNS(VoidTy),
956956
ARGS(TypeMetadataPtrTy, SizeTy,
957957
Int8PtrPtrTy->getPointerTo(),
958958
SizeTy->getPointerTo()),

lib/IRGen/GenMeta.cpp

Lines changed: 23 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2758,8 +2758,6 @@ namespace {
27582758
struct FillOp {
27592759
CanType Type;
27602760
Optional<ProtocolConformanceRef> Conformance;
2761-
Size ToOffset;
2762-
bool IsRelative;
27632761
};
27642762

27652763
SmallVector<FillOp, 8> FillOps;
@@ -2836,7 +2834,10 @@ namespace {
28362834
// fill indexes are word-indexed.
28372835
Address metadataWords(IGF.Builder.CreateBitCast(metadataValue, IGM.Int8PtrPtrTy),
28382836
IGM.getPointerAlignment());
2839-
2837+
2838+
auto genericReqtOffset = IGM.getMetadataLayout(Target)
2839+
.getGenericRequirementsOffset(IGF);
2840+
28402841
for (auto &fillOp : FillOps) {
28412842
llvm::Value *value;
28422843
if (fillOp.Conformance) {
@@ -2846,20 +2847,12 @@ namespace {
28462847
}
28472848

28482849
auto dest = createPointerSizedGEP(IGF, metadataWords,
2849-
fillOp.ToOffset - AddressPoint);
2850-
2851-
// A far relative indirectable pointer.
2852-
if (fillOp.IsRelative) {
2853-
dest = IGF.Builder.CreateElementBitCast(dest,
2854-
IGM.FarRelativeAddressTy);
2855-
IGF.emitStoreOfRelativeIndirectablePointer(value, dest,
2856-
/*isFar*/ true);
2850+
genericReqtOffset.getStatic());
2851+
genericReqtOffset = genericReqtOffset.offsetBy(
2852+
IGF, IGM.getPointerSize());
28572853

2858-
// A direct pointer.
2859-
} else {
2860-
value = IGF.Builder.CreateBitCast(value, IGM.Int8PtrTy);
2861-
IGF.Builder.CreateStore(value, dest);
2862-
}
2854+
value = IGF.Builder.CreateBitCast(value, IGM.Int8PtrTy);
2855+
IGF.Builder.CreateStore(value, dest);
28632856
}
28642857

28652858
// Initialize the instantiated dependent value witness table, if we have
@@ -2894,12 +2887,6 @@ namespace {
28942887
return f;
28952888
}
28962889

2897-
void addFillOp(CanType type, Optional<ProtocolConformanceRef> conf,
2898-
bool isRelative) {
2899-
FillOps.push_back({type, conf, getNextOffsetFromTemplateHeader(),
2900-
isRelative });
2901-
}
2902-
29032890
public:
29042891
void createMetadataAccessFunction() {
29052892
(void) getGenericTypeMetadataAccessFunction(IGM, Target, ForDefinition);
@@ -2981,14 +2968,14 @@ namespace {
29812968

29822969
template <class... T>
29832970
void addGenericArgument(CanType type, T &&...args) {
2984-
addFillOp(type, None, /*relative*/ false);
2971+
FillOps.push_back({type, None});
29852972
super::addGenericArgument(type, std::forward<T>(args)...);
29862973
}
29872974

29882975
template <class... T>
29892976
void addGenericWitnessTable(CanType type, ProtocolConformanceRef conf,
29902977
T &&...args) {
2991-
addFillOp(type, conf, /*relative*/ false);
2978+
FillOps.push_back({type, conf});
29922979
super::addGenericWitnessTable(type, conf, std::forward<T>(args)...);
29932980
}
29942981

@@ -3021,11 +3008,10 @@ namespace {
30213008
};
30223009
} // end anonymous namespace
30233010

3024-
llvm::Value *
3025-
irgen::emitInitializeFieldOffsetVector(IRGenFunction &IGF,
3026-
SILType T,
3027-
llvm::Value *metadata,
3028-
llvm::Value *vwtable) {
3011+
void irgen::emitInitializeFieldOffsetVector(IRGenFunction &IGF,
3012+
SILType T,
3013+
llvm::Value *metadata,
3014+
llvm::Value *vwtable) {
30293015
auto *target = T.getNominalOrBoundGenericNominal();
30303016
llvm::Value *fieldVector
30313017
= emitAddressOfFieldOffsetVector(IGF, metadata, target)
@@ -3062,9 +3048,9 @@ irgen::emitInitializeFieldOffsetVector(IRGenFunction &IGF,
30623048

30633049
if (isa<ClassDecl>(target)) {
30643050
assert(vwtable == nullptr);
3065-
metadata = IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataUniversalFn(),
3066-
{metadata, numFields,
3067-
fields.getAddress(), fieldVector});
3051+
IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataUniversalFn(),
3052+
{metadata, numFields,
3053+
fields.getAddress(), fieldVector});
30683054
} else {
30693055
assert(isa<StructDecl>(target));
30703056
IGF.Builder.CreateCall(IGF.IGM.getInitStructMetadataUniversalFn(),
@@ -3074,8 +3060,6 @@ irgen::emitInitializeFieldOffsetVector(IRGenFunction &IGF,
30743060

30753061
IGF.Builder.CreateLifetimeEnd(fields,
30763062
IGF.IGM.getPointerSize() * storedProperties.size());
3077-
3078-
return metadata;
30793063
}
30803064

30813065
// Classes
@@ -3489,11 +3473,9 @@ namespace {
34893473
}
34903474

34913475
llvm::Value *emitFinishInitializationOfClassMetadata(IRGenFunction &IGF,
3492-
llvm::Value *metadata) {
3476+
llvm::Value *metadata) {
34933477
// We assume that we've already filled in the class's generic arguments.
34943478
// We need to:
3495-
// - relocate the metadata to accommodate the superclass,
3496-
// if something in our hierarchy is resilient to us;
34973479
// - fill out the subclass's field offset vector, if its layout
34983480
// wasn't fixed;
34993481
// - copy field offsets and generic arguments from higher in the
@@ -3508,9 +3490,9 @@ namespace {
35083490
if (doesClassMetadataRequireDynamicInitialization(IGF.IGM, Target)) {
35093491
auto classTy = Target->getDeclaredTypeInContext()->getCanonicalType();
35103492
auto loweredClassTy = IGF.IGM.getLoweredType(classTy);
3511-
metadata = emitInitializeFieldOffsetVector(IGF, loweredClassTy,
3512-
metadata,
3513-
/*vwtable=*/nullptr);
3493+
emitInitializeFieldOffsetVector(IGF, loweredClassTy,
3494+
metadata,
3495+
/*vwtable=*/nullptr);
35143496

35153497
// Realizing the class with the ObjC runtime will copy back to the
35163498
// field offset globals for us; but if ObjC interop is disabled, we
@@ -3742,9 +3724,7 @@ namespace {
37423724
IGF.Builder.CreateStore(superclassMetadata, superField);
37433725
}
37443726

3745-
metadata = emitFinishInitializationOfClassMetadata(IGF, metadata);
3746-
3747-
return metadata;
3727+
return emitFinishInitializationOfClassMetadata(IGF, metadata);
37483728
}
37493729
};
37503730

lib/IRGen/GenMeta.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,10 @@ namespace irgen {
255255

256256
/// \brief Initialize the field offset vector within the given class or struct
257257
/// metadata.
258-
llvm::Value *emitInitializeFieldOffsetVector(IRGenFunction &IGF,
259-
SILType T,
260-
llvm::Value *metadata,
261-
llvm::Value *vwtable);
258+
void emitInitializeFieldOffsetVector(IRGenFunction &IGF,
259+
SILType T,
260+
llvm::Value *metadata,
261+
llvm::Value *vwtable);
262262

263263
/// Adjustment indices for the address points of various metadata.
264264
/// Size is in words.

lib/IRGen/IRGen.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ class Offset {
484484
}
485485

486486
llvm::Value *getAsValue(IRGenFunction &IGF) const;
487-
Offset offsetBy(IRGenFunction &IGF, Offset other) const;
487+
Offset offsetBy(IRGenFunction &IGF, Size other) const;
488488
};
489489

490490
} // end namespace irgen

lib/IRGen/IRGenFunction.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,11 +394,12 @@ llvm::Value *Offset::getAsValue(IRGenFunction &IGF) const {
394394
}
395395
}
396396

397-
Offset Offset::offsetBy(IRGenFunction &IGF, Offset other) const {
398-
if (isStatic() && other.isStatic()) {
399-
return Offset(getStatic() + other.getStatic());
397+
Offset Offset::offsetBy(IRGenFunction &IGF, Size other) const {
398+
if (isStatic()) {
399+
return Offset(getStatic() + other);
400400
}
401-
return Offset(IGF.Builder.CreateAdd(getDynamic(), other.getDynamic()));
401+
auto otherVal = llvm::ConstantInt::get(IGF.IGM.SizeTy, other.getValue());
402+
return Offset(IGF.Builder.CreateAdd(getDynamic(), otherVal));
402403
}
403404

404405
Address IRGenFunction::emitAddressAtOffset(llvm::Value *base, Offset offset,

lib/IRGen/MetadataLayout.cpp

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ static llvm::Value *emitLoadOfGenericRequirement(IRGenFunction &IGF,
147147
llvm::Type *reqtTy) {
148148
auto offset =
149149
IGF.IGM.getMetadataLayout(decl).getGenericRequirementsOffset(IGF);
150-
offset = offset.offsetBy(IGF, Offset(reqtIndex * IGF.IGM.getPointerSize()));
150+
offset = offset.offsetBy(IGF, Size(reqtIndex * IGF.IGM.getPointerSize()));
151151

152152
auto slot = IGF.emitAddressAtOffset(metadata, offset, reqtTy,
153153
IGF.IGM.getPointerAlignment());
@@ -203,7 +203,7 @@ Address irgen::emitAddressOfFieldOffsetVector(IRGenFunction &IGF,
203203
/********************************** CLASSES ***********************************/
204204

205205
ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
206-
: NominalMetadataLayout(Kind::Class) {
206+
: NominalMetadataLayout(Kind::Class), NumImmediateMembers(0) {
207207

208208
struct Scanner : LayoutScanner<Scanner, ClassMetadataScanner> {
209209
using super = LayoutScanner;
@@ -228,9 +228,26 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
228228
super::noteStartOfGenericRequirements(forClass);
229229
}
230230

231+
void addGenericWitnessTable(CanType argType, ProtocolConformanceRef conf,
232+
ClassDecl *forClass) {
233+
if (forClass == Target) {
234+
Layout.NumImmediateMembers++;
235+
}
236+
super::addGenericWitnessTable(argType, conf, forClass);
237+
}
238+
239+
void addGenericArgument(CanType argType, ClassDecl *forClass) {
240+
if (forClass == Target) {
241+
Layout.NumImmediateMembers++;
242+
}
243+
super::addGenericArgument(argType, forClass);
244+
}
245+
231246
void addMethod(SILDeclRef fn) {
232-
if (fn.getDecl()->getDeclContext() == Target)
247+
if (fn.getDecl()->getDeclContext() == Target) {
248+
Layout.NumImmediateMembers++;
233249
Layout.MethodInfos.try_emplace(fn, getNextOffset());
250+
}
234251
super::addMethod(fn);
235252
}
236253

@@ -241,11 +258,21 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
241258
}
242259

243260
void addFieldOffset(VarDecl *field) {
244-
if (field->getDeclContext() == Target)
261+
if (field->getDeclContext() == Target) {
262+
Layout.NumImmediateMembers++;
245263
Layout.FieldOffsets.try_emplace(field, getNextOffset());
264+
}
246265
super::addFieldOffset(field);
247266
}
248267

268+
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
269+
if (placeholder->getDeclContext() == Target) {
270+
Layout.NumImmediateMembers +=
271+
placeholder->getNumberOfFieldOffsetVectorEntries();
272+
}
273+
super::addFieldOffsetPlaceholders(placeholder);
274+
}
275+
249276
void addVTableEntries(ClassDecl *forClass) {
250277
if (forClass == Target)
251278
Layout.VTableOffset = getNextOffset();

lib/IRGen/MetadataLayout.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ class ClassMetadataLayout : public NominalMetadataLayout {
168168
/// The start of the field-offset vector.
169169
StoredOffset FieldOffsetVector;
170170

171+
/// The number of members to add after superclass metadata.
172+
unsigned NumImmediateMembers;
173+
171174
const StoredMethodInfo &getStoredMethodInfo(SILDeclRef method) const {
172175
auto it = MethodInfos.find(method);
173176
assert(it != MethodInfos.end());
@@ -222,6 +225,13 @@ class ClassMetadataLayout : public NominalMetadataLayout {
222225

223226
Offset getFieldOffsetVectorOffset(IRGenFunction &IGF) const;
224227

228+
/// The number of members to add after superclass metadata. The size of
229+
/// this metadata is the superclass size plus the number of immediate
230+
/// members in the class itself.
231+
unsigned getNumImmediateMembers() const {
232+
return NumImmediateMembers;
233+
}
234+
225235
static bool classof(const MetadataLayout *layout) {
226236
return layout->getKind() == Kind::Class;
227237
}

0 commit comments

Comments
 (0)