Always, no, never... forget to check your references

for weak semantics, that is!

94a9c512b9 made some changes to loading
weak references by adding some information in the lower bits with
respect to locking. These bits need to be masked out when performing a
load, such as when we want to get the metadata pointer for a class
instance. This normally works fine when going through the normal weak
loading functions in the runtime.

When the runtime function swift_ClassMirror_subscript gets the offset of
one of its stored properties, it immediately packages it into the the
ad-hoc existential container, known as just `Mirror` in the runtime.
However, the weak reference isn't aligned! It has bit 1 set.  We weren't
loading the weak reference here as we would during normal SILGen, such
as with a weak_load instruction. Simulate that here and make the
reference strong before putting it into the Mirror container, which also
clears those lower bits.

rdar://problem/27475034

There are still a couple of other cases to handle, namely the
unowned(safe) and unowned(unsafe) reference kinds. There may be other
places where an unaligned pointer is problematic in the runtime, which
we should audit for correctness.

rdar://problem/27809991
This commit is contained in:
David Farler
2016-08-16 11:43:58 -07:00
parent 43fb605c7e
commit 10c44e1a3a
5 changed files with 259 additions and 18 deletions

View File

@@ -2414,8 +2414,10 @@ namespace {
NominalTypeDecl::StoredPropertyRange storedProperties){
SmallVector<FieldTypeInfo, 4> types;
for (VarDecl *prop : storedProperties) {
types.push_back(FieldTypeInfo(prop->getType()->getCanonicalType(),
/*indirect*/ false));
auto propertyType = prop->getType()->getCanonicalType();
types.push_back(FieldTypeInfo(propertyType,
/*indirect*/ false,
propertyType->is<WeakStorageType>()));
}
return getFieldTypeAccessorFn(IGM, type, types);
}
@@ -2431,7 +2433,7 @@ namespace {
auto caseType = elt.decl->getArgumentType()->getCanonicalType();
bool isIndirect = elt.decl->isIndirect()
|| elt.decl->getParentEnum()->isIndirect();
types.push_back(FieldTypeInfo(caseType, isIndirect));
types.push_back(FieldTypeInfo(caseType, isIndirect, /*weak*/ false));
}
return getFieldTypeAccessorFn(IGM, type, types);
}
@@ -2784,9 +2786,13 @@ irgen::emitFieldTypeAccessor(IRGenModule &IGM,
auto metadata = IGF.emitTypeMetadataRef(fieldTy);
auto fieldTypeInfo = fieldTypes[i];
// Mix in flag bits.
if (fieldTypes[i].isIndirect()) {
auto flags = FieldType().withIndirect(true);
if (fieldTypeInfo.hasFlags()) {
auto flags = FieldType()
.withIndirect(fieldTypeInfo.isIndirect())
.withWeak(fieldTypeInfo.isWeak());
auto metadataBits = IGF.Builder.CreatePtrToInt(metadata, IGF.IGM.SizeTy);
metadataBits = IGF.Builder.CreateOr(metadataBits,
llvm::ConstantInt::get(IGF.IGM.SizeTy, flags.getIntValue()));