Skip to content

Commit 31d5385

Browse files
Merge pull request #31420 from nate-chandler/generic-metadata-prespecialization-components/rdar61465515
[5.3] [metadata prespecialization] Zero trailing flags field.
2 parents b7bdca8 + 102e8a1 commit 31d5385

31 files changed

+1403
-50
lines changed

include/swift/ABI/Metadata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3373,6 +3373,7 @@ class TargetGenericMetadataPatternTrailingObjects :
33733373
/// class metadata.
33743374
///
33753375
/// See also: [pre-5.2-extra-data-zeroing]
3376+
/// See also: [pre-5.3-extra-data-zeroing]
33763377
const GenericMetadataPartialPattern *getExtraDataPattern() const {
33773378
assert(asSelf()->hasExtraDataPattern());
33783379
return this->template getTrailingObjects<GenericMetadataPartialPattern>();

lib/IRGen/ConstantBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ class ConstantAggregateBuilderBase
7777
addInt(IGM().Int32Ty, value);
7878
}
7979

80+
void addInt64(uint64_t value) { addInt(IGM().Int64Ty, value); }
81+
82+
void addSize(Size size) { addInt(IGM().SizeTy, size.getValue()); }
83+
8084
void addRelativeAddressOrNull(llvm::Constant *target) {
8185
if (target) {
8286
addRelativeAddress(target);

lib/IRGen/EnumMetadataVisitor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,13 @@ class EnumMetadataScanner : public EnumMetadataVisitor<Impl> {
9494
void addGenericWitnessTable(GenericRequirement requirement) { addPointer(); }
9595
void addPayloadSize() { addPointer(); }
9696
void noteStartOfTypeSpecificMembers() {}
97-
void addTrailingFlags() { addPointer(); }
97+
void addTrailingFlags() { addInt64(); }
9898

9999
private:
100100
void addPointer() {
101101
NextOffset += super::IGM.getPointerSize();
102102
}
103+
void addInt64() { NextOffset += Size(8); }
103104
};
104105

105106
} // end namespace irgen

lib/IRGen/GenMeta.cpp

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,6 +2317,7 @@ namespace {
23172317
asImpl().layoutHeader();
23182318

23192319
// See also: [pre-5.2-extra-data-zeroing]
2320+
// See also: [pre-5.3-extra-data-zeroing]
23202321
if (asImpl().hasExtraDataPattern()) {
23212322
asImpl().addExtraDataPattern();
23222323
}
@@ -3730,7 +3731,7 @@ namespace {
37303731
GenericMetadataPatternFlags getPatternFlags() {
37313732
auto flags = super::getPatternFlags();
37323733

3733-
if (IGM.shouldPrespecializeGenericMetadata()) {
3734+
if (hasTrailingFlags()) {
37343735
flags.setHasTrailingFlags(true);
37353736
}
37363737

@@ -3743,7 +3744,11 @@ namespace {
37433744
HasDependentVWT);
37443745
}
37453746

3746-
bool hasExtraDataPattern() {
3747+
bool hasTrailingFlags() {
3748+
return IGM.shouldPrespecializeGenericMetadata();
3749+
}
3750+
3751+
bool hasKnownFieldOffsets() {
37473752
auto &ti = IGM.getTypeInfo(getLoweredType());
37483753
if (!isa<FixedTypeInfo>(ti))
37493754
return false;
@@ -3754,19 +3759,31 @@ namespace {
37543759
return true;
37553760
}
37563761

3757-
/// Fill in a constant field offset vector if possible.
3762+
bool hasExtraDataPattern() {
3763+
return hasKnownFieldOffsets() || hasTrailingFlags();
3764+
}
3765+
3766+
/// If present, the extra data pattern consists of one or both of the
3767+
/// following:
3768+
///
3769+
/// - the field offset vector
3770+
/// - the trailing flags
37583771
PartialPattern buildExtraDataPattern() {
37593772
ConstantInitBuilder builder(IGM);
3760-
auto init = builder.beginArray(IGM.Int32Ty);
3773+
auto init = builder.beginStruct();
37613774

37623775
struct Scanner : StructMetadataScanner<Scanner> {
3776+
GenericStructMetadataBuilder &Outer;
37633777
SILType Type;
3764-
ConstantArrayBuilder &B;
3765-
Scanner(IRGenModule &IGM, StructDecl *target, SILType type,
3766-
ConstantArrayBuilder &B)
3767-
: StructMetadataScanner(IGM, target), Type(type), B(B) {}
3778+
ConstantStructBuilder &B;
3779+
Scanner(GenericStructMetadataBuilder &outer, IRGenModule &IGM, StructDecl *target, SILType type,
3780+
ConstantStructBuilder &B)
3781+
: StructMetadataScanner(IGM, target), Outer(outer), Type(type), B(B) {}
37683782

37693783
void addFieldOffset(VarDecl *field) {
3784+
if (!Outer.hasKnownFieldOffsets()) {
3785+
return;
3786+
}
37703787
auto offset = emitPhysicalStructMemberFixedOffset(IGM, Type, field);
37713788
if (offset) {
37723789
B.add(offset);
@@ -3782,22 +3799,28 @@ namespace {
37823799
void noteEndOfFieldOffsets() {
37833800
B.addAlignmentPadding(IGM.getPointerAlignment());
37843801
}
3802+
3803+
void addTrailingFlags() { B.addInt64(0); }
37853804
};
3786-
Scanner(IGM, Target, getLoweredType(), init).layout();
3787-
Size vectorSize = init.getNextOffsetFromGlobal();
3805+
Scanner(*this, IGM, Target, getLoweredType(), init).layout();
3806+
Size structSize = init.getNextOffsetFromGlobal();
37883807

37893808
auto global = init.finishAndCreateGlobal("", IGM.getPointerAlignment(),
37903809
/*constant*/ true);
37913810

37923811
auto &layout = IGM.getMetadataLayout(Target);
3812+
3813+
bool offsetUpToTrailingFlags = hasTrailingFlags() && !hasKnownFieldOffsets();
3814+
Size zeroingStart = IGM.getOffsetOfStructTypeSpecificMetadataMembers();
3815+
Offset zeroingEnd = offsetUpToTrailingFlags
3816+
? layout.getTrailingFlagsOffset()
3817+
: layout.getFieldOffsetVectorOffset();
37933818
return { global,
3794-
layout.getFieldOffsetVectorOffset().getStatic()
3795-
- IGM.getOffsetOfStructTypeSpecificMetadataMembers(),
3796-
vectorSize };
3819+
zeroingEnd.getStatic()
3820+
- zeroingStart,
3821+
structSize };
37973822
}
37983823

3799-
void addTrailingFlags() { this->B.addInt(IGM.Int64Ty, 0); }
3800-
38013824
bool hasCompletionFunction() {
38023825
return !isa<FixedTypeInfo>(IGM.getTypeInfo(getLoweredType()));
38033826
}
@@ -4171,24 +4194,58 @@ namespace {
41714194
descriptor = emitPointerAuthSign(IGF, descriptor, authInfo);
41724195
}
41734196

4174-
auto metadata =
4197+
return
41754198
IGF.Builder.CreateCall(IGM.getAllocateGenericValueMetadataFn(),
41764199
{descriptor, arguments, templatePointer,
41774200
extraSizeV});
4201+
}
4202+
4203+
bool hasTrailingFlags() {
4204+
return IGM.shouldPrespecializeGenericMetadata();
4205+
}
4206+
4207+
bool hasKnownPayloadSize() {
4208+
auto &layout = IGM.getMetadataLayout(Target);
4209+
return layout.hasPayloadSizeOffset() && (bool)getConstantPayloadSize(IGM, Target);
4210+
}
4211+
4212+
bool hasExtraDataPattern() {
4213+
return hasKnownPayloadSize() || hasTrailingFlags();
4214+
}
4215+
4216+
/// If present, the extra data pattern consists of one or both of the
4217+
/// following:
4218+
///
4219+
/// - the payload-size
4220+
/// - the trailing flags
4221+
PartialPattern buildExtraDataPattern() {
4222+
ConstantInitBuilder builder(IGM);
4223+
auto init = builder.beginStruct();
4224+
4225+
auto &layout = IGM.getMetadataLayout(Target);
41784226

4179-
// Initialize the payload-size field if we have a constant value for it.
4180-
// This is so small that we just do it inline instead of bothering
4181-
// with a pattern.
41824227
if (layout.hasPayloadSizeOffset()) {
41834228
if (auto size = getConstantPayloadSize(IGM, Target)) {
4184-
auto offset = layout.getPayloadSizeOffset();
4185-
auto slot = IGF.emitAddressAtOffset(metadata, offset, IGM.SizeTy,
4186-
IGM.getPointerAlignment());
4187-
IGF.Builder.CreateStore(IGM.getSize(*size), slot);
4229+
init.addSize(*size);
41884230
}
41894231
}
4232+
if (hasTrailingFlags()) {
4233+
init.addInt64(0);
4234+
}
4235+
Size structSize = init.getNextOffsetFromGlobal();
41904236

4191-
return metadata;
4237+
auto global = init.finishAndCreateGlobal("", IGM.getPointerAlignment(),
4238+
/*constant*/ true);
4239+
4240+
bool offsetUpToTrailingFlags = hasTrailingFlags() && !hasKnownPayloadSize();
4241+
Size zeroingStart = IGM.getOffsetOfEnumTypeSpecificMetadataMembers();
4242+
Offset zeroingEnd = offsetUpToTrailingFlags
4243+
? layout.getTrailingFlagsOffset()
4244+
: layout.getPayloadSizeOffset();
4245+
return { global,
4246+
zeroingEnd.getStatic()
4247+
- zeroingStart,
4248+
structSize };
41924249
}
41934250

41944251
llvm::Constant *emitNominalTypeDescriptor() {
@@ -4198,7 +4255,7 @@ namespace {
41984255
GenericMetadataPatternFlags getPatternFlags() {
41994256
auto flags = super::getPatternFlags();
42004257

4201-
if (IGM.shouldPrespecializeGenericMetadata()) {
4258+
if (hasTrailingFlags()) {
42024259
flags.setHasTrailingFlags(true);
42034260
}
42044261

lib/IRGen/MetadataLayout.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,11 @@ EnumMetadataLayout::EnumMetadataLayout(IRGenModule &IGM, EnumDecl *decl)
543543
super::noteStartOfGenericRequirements();
544544
}
545545

546+
void addTrailingFlags() {
547+
Layout.TrailingFlagsOffset = getNextOffset();
548+
super::addTrailingFlags();
549+
}
550+
546551
void layout() {
547552
super::layout();
548553
Layout.TheSize = getMetadataSize();
@@ -558,6 +563,11 @@ EnumMetadataLayout::getPayloadSizeOffset() const {
558563
return Offset(PayloadSizeOffset.getStaticOffset());
559564
}
560565

566+
Offset EnumMetadataLayout::getTrailingFlagsOffset() const {
567+
assert(TrailingFlagsOffset.isStatic());
568+
return Offset(TrailingFlagsOffset.getStaticOffset());
569+
}
570+
561571
/********************************** STRUCTS ***********************************/
562572

563573
StructMetadataLayout::StructMetadataLayout(IRGenModule &IGM, StructDecl *decl)
@@ -594,6 +604,11 @@ StructMetadataLayout::StructMetadataLayout(IRGenModule &IGM, StructDecl *decl)
594604
super::noteEndOfFieldOffsets();
595605
}
596606

607+
void addTrailingFlags() {
608+
Layout.TrailingFlagsOffset = getNextOffset();
609+
super::addTrailingFlags();
610+
}
611+
597612
void layout() {
598613
super::layout();
599614
Layout.TheSize = getMetadataSize();
@@ -620,6 +635,11 @@ StructMetadataLayout::getFieldOffsetVectorOffset() const {
620635
return Offset(FieldOffsetVector.getStaticOffset());
621636
}
622637

638+
Offset
639+
StructMetadataLayout::getTrailingFlagsOffset() const {
640+
assert(TrailingFlagsOffset.isStatic());
641+
return Offset(TrailingFlagsOffset.getStaticOffset());
642+
}
623643
/****************************** FOREIGN CLASSES *******************************/
624644
ForeignClassMetadataLayout::ForeignClassMetadataLayout(IRGenModule &IGM,
625645
ClassDecl *theClass)

lib/IRGen/MetadataLayout.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ class ClassMetadataLayout : public NominalMetadataLayout {
284284
class EnumMetadataLayout : public NominalMetadataLayout {
285285
/// The offset of the payload size field, if there is one.
286286
StoredOffset PayloadSizeOffset;
287+
StoredOffset TrailingFlagsOffset;
287288

288289
// TODO: presumably it would be useful to store *something* here
289290
// for resilience.
@@ -301,6 +302,7 @@ class EnumMetadataLayout : public NominalMetadataLayout {
301302
}
302303

303304
Offset getPayloadSizeOffset() const;
305+
Offset getTrailingFlagsOffset() const;
304306

305307
static bool classof(const MetadataLayout *layout) {
306308
return layout->getKind() == Kind::Enum;
@@ -310,6 +312,7 @@ class EnumMetadataLayout : public NominalMetadataLayout {
310312
/// Layout for struct type metadata.
311313
class StructMetadataLayout : public NominalMetadataLayout {
312314
llvm::DenseMap<VarDecl*, StoredOffset> FieldOffsets;
315+
StoredOffset TrailingFlagsOffset;
313316

314317
/// The start of the field-offset vector.
315318
StoredOffset FieldOffsetVector;
@@ -338,6 +341,7 @@ class StructMetadataLayout : public NominalMetadataLayout {
338341
Size getStaticFieldOffset(VarDecl *field) const;
339342

340343
Offset getFieldOffsetVectorOffset() const;
344+
Offset getTrailingFlagsOffset() const;
341345

342346
static bool classof(const MetadataLayout *layout) {
343347
return layout->getKind() == Kind::Struct;

lib/IRGen/StructMetadataVisitor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,14 @@ class StructMetadataScanner : public StructMetadataVisitor<Impl> {
104104
NextOffset = NextOffset.roundUpToAlignment(super::IGM.getPointerAlignment());
105105
}
106106

107-
void addTrailingFlags() { addPointer(); }
107+
void addTrailingFlags() { addInt64(); }
108108

109109
private:
110110
void addPointer() {
111111
NextOffset += super::IGM.getPointerSize();
112112
}
113113
void addInt32() { NextOffset += Size(4); }
114+
void addInt64() { NextOffset += Size(8); }
114115
};
115116

116117
} // end namespace irgen

stdlib/public/runtime/Metadata.cpp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,18 @@ SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_END
436436
extern "C" void *_objc_empty_cache;
437437
#endif
438438

439+
template <>
440+
bool Metadata::isCanonicalStaticallySpecializedGenericMetadata() const {
441+
if (auto *metadata = dyn_cast<StructMetadata>(this))
442+
return metadata->isCanonicalStaticallySpecializedGenericMetadata();
443+
if (auto *metadata = dyn_cast<EnumMetadata>(this))
444+
return metadata->isCanonicalStaticallySpecializedGenericMetadata();
445+
if (auto *metadata = dyn_cast<ClassMetadata>(this))
446+
return metadata->isCanonicalStaticallySpecializedGenericMetadata();
447+
448+
return false;
449+
}
450+
439451
static void copyMetadataPattern(void **section,
440452
const GenericMetadataPartialPattern *pattern) {
441453
memcpy(section + pattern->OffsetInWords,
@@ -605,7 +617,10 @@ initializeValueMetadataFromPattern(ValueMetadata *metadata,
605617
auto extraDataPattern = pattern->getExtraDataPattern();
606618

607619
// Zero memory up to the offset.
608-
memset(metadataExtraData, 0, size_t(extraDataPattern->OffsetInWords));
620+
// [pre-5.3-extra-data-zeroing] Before Swift 5.3, the runtime did not
621+
// correctly zero the zero-prefix of the extra-data pattern.
622+
memset(metadataExtraData, 0,
623+
size_t(extraDataPattern->OffsetInWords) * sizeof(void *));
609624

610625
// Copy the pattern into the rest of the extra data.
611626
copyMetadataPattern(metadataExtraData, extraDataPattern);
@@ -648,6 +663,11 @@ swift::swift_allocateGenericValueMetadata(const ValueTypeDescriptor *description
648663

649664
auto bytes = (char*) cache.getAllocator().Allocate(totalSize, alignof(void*));
650665

666+
#ifndef NDEBUG
667+
// Fill the metadata record with garbage.
668+
memset(bytes, 0xAA, totalSize);
669+
#endif
670+
651671
auto addressPoint = bytes + sizeof(ValueMetadata::HeaderType);
652672
auto metadata = reinterpret_cast<ValueMetadata *>(addressPoint);
653673

@@ -672,6 +692,9 @@ swift::swift_getGenericMetadata(MetadataRequest request,
672692
arguments);
673693
auto result = cache.getOrInsert(key, request, description, arguments);
674694

695+
assert(
696+
!result.second.Value->isCanonicalStaticallySpecializedGenericMetadata());
697+
675698
return result.second;
676699
}
677700

@@ -5521,18 +5544,6 @@ bool Metadata::satisfiesClassConstraint() const {
55215544
return isAnyClass();
55225545
}
55235546

5524-
template <>
5525-
bool Metadata::isCanonicalStaticallySpecializedGenericMetadata() const {
5526-
if (auto *metadata = dyn_cast<StructMetadata>(this))
5527-
return metadata->isCanonicalStaticallySpecializedGenericMetadata();
5528-
if (auto *metadata = dyn_cast<EnumMetadata>(this))
5529-
return metadata->isCanonicalStaticallySpecializedGenericMetadata();
5530-
if (auto *metadata = dyn_cast<ClassMetadata>(this))
5531-
return metadata->isCanonicalStaticallySpecializedGenericMetadata();
5532-
5533-
return false;
5534-
}
5535-
55365547
#if !NDEBUG
55375548
static bool referencesAnonymousContext(Demangle::Node *node) {
55385549
if (node->getKind() == Demangle::Node::Kind::AnonymousContext)

test/IRGen/enum_future.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2660,7 +2660,7 @@ entry(%x : $*MyOptional):
26602660
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} internal %swift.type* @"$s11enum_future16DynamicSingletonOMi"(%swift.type_descriptor* %0, i8** %1, i8* %2) {{.*}} {
26612661
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
26622662
// CHECK: [[T:%T]] = load %swift.type*, %swift.type** [[T0]],
2663-
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_descriptor* %0, i8** %1, i8* %2, [[WORD]] {{4|8|16}})
2663+
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_descriptor* %0, i8** %1, i8* %2, [[WORD]] {{4|8|12|16}})
26642664
// CHECK-NEXT: ret %swift.type* [[METADATA]]
26652665

26662666
// CHECK-LABEL: define{{( protected)?}} internal swiftcc %swift.metadata_response @"$s11enum_future16DynamicSingletonOMr"

0 commit comments

Comments
 (0)