-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Always, no, never... forget to check your references #4060
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Always, no, never... forget to check your references #4060
Conversation
I still need to update the tests and add a new test, but @rjmccall does this look like the right approach here? [cc @dabrahams and @jckarter with whom I spoke about this before) |
auto weakField = reinterpret_cast<WeakReference *>(fieldData); | ||
auto strongValue = swift_weakLoadStrong(weakField); | ||
fieldData = reinterpret_cast<OpaqueValue *>(strongValue); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this create a directness inconsistency? That is, doesn't reflect() expect to get a T*, not a T-that-happens-to-be-a-pointer?
Yeah, it stores an existential at a given out address. I think this was working because I was setting a weak property that happened to also be a global, i.e.: public class Person {
weak var parent: Person?
let x = 0xAABBCCDDEE
}
let p = Person()
let p2 = Person()
p.parent = p2
let child = Swift._reflect(p)[0].1.value
print(child) works, but public class Person {
weak var parent: Person?
let x = 0xAABBCCDDEE
}
let p = Person()
p.parent = Person() // <-- Not a global
let child = _reflect(p)[0].1.value
print(child) does not. |
Hah, @rjmccall points out that |
I think the indirectness is correct. The actual return does the right assignment here: new (outString) String(getFieldName(Clas->getDescription()->Class.FieldNames, i));
// 'owner' is consumed by this call.
new (outMirror) Mirror(reflect(owner, fieldData, fieldType.getType())); And the implementation of the subscript operation itself looks to be correct in the debugger to me. |
Lots of comments made in person:
|
Thanks John. I'm going to just address the weak case in this pull request and reconcile all of the other reference storage kinds in a a follow-up pull request to break up the patch a little bit. |
Sigh. Just found another crash with structs in |
@swift-ci Please test |
@swift-ci Please smoke test |
1 similar comment
@swift-ci Please smoke test |
Wha? Why is this a void function on Linux? |
@swift-ci Please smoke test |
@swift-ci please smoke test. |
for weak semantics, that is! 94a9c51 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
Some of these return void * on platforms with Objective-C interop, but drops the return value on those without, such as on Linux.
@swift-ci Please smoke test |
@swift-ci Please smoke test. |
All tests passed, looks like an infrastructural issue with the packaging step. I'll merge now. |
for weak semantics, that is!
94a9c51 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 normal codegen
methods.
When the runtime function swift_ClassMirror_subscript gets the offset
of one of its stored properties, it immediately packages it into the
rather ad-hoc existential container, known as just
Mirror
in theruntime. 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
by calling
swift_weakLoadStrong
before putting it into the Mirrorcontainer, which also clears the lower bits.
rdar://problem/27475034