<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><b class="">Approved</b>. &nbsp;I’ll handle the merge with the pull request.<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 2, 2016, at 9:54 AM, Arnold Schwaighofer &lt;<a href="mailto:aschwaighofer@apple.com" class="">aschwaighofer@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><a href="https://github.com/apple/swift/pull/1159" class="">https://github.com/apple/swift/pull/1159</a><br class=""><br class="">Perform a dynamic method call if a class has objc ancestry in specula<br class="">tive devirt as fallback.<br class=""><br class="">If a class has an @objc ancestry this class can be dynamically overridden and<br class="">therefore we don't know the default case even if we see the full class<br class="">hierarchy.<br class=""><br class="">rdar://23228386<br class=""><br class="">Explanation:<br class=""><br class="">Before this change we would devirtualize a method call to static calls of the potential call targets without a fallback to a class method lookup if we believed to have the full class hierarchy e.g in WMO mode. But during runtime this assumption can be violated because an objective-c class can be dynamically extended and so we would end up calling through the wrong method.<br class=""><br class="">private class A : NSObject {<br class="">func foo() {...}<br class="">}<br class="">private class B : A { <br class="">override foo() {...}<br class="">}<br class=""><br class="">Before:<br class=""><br class="">callAnA(a : A) {<br class=""> if (a isa A) {<br class=""> &nbsp;A.foo(a)<br class=""> } else {<br class=""> &nbsp;B.foo(a)<br class=""> }<br class="">}<br class=""><br class="">After:<br class=""><br class="">callAnA(a : A) {<br class=""> if (a isa A) {<br class=""> &nbsp;A.foo(a)<br class=""> } else if (a isa B) {<br class=""> &nbsp;B.foo(a)<br class=""> } else a.foo(a) // call through class method table.<br class="">}<br class=""><br class="">Scope:<br class=""><br class="">The change only effects whether we emit a default case that calls through the class method table. Emitting the call through the class method table is always safe. This risk is low.<br class=""><br class="">Testing:<br class=""><br class="">There is a unit test testing the change, furthermore the change was tested in the project reported in rdar://23228386 and only with this change the test scenario in the project works.<br class=""><br class="">Reviewed by:<br class="">Roman, the author of the speculative virtualization pass, and Slava also took a look at it.</div></div></blockquote></div><br class=""></div></body></html>