> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev <swift-dev@swift.org> 
> wrote:
> 
> 
>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev <swift-dev@swift.org> 
>> wrote:
>> 
>> The Swift runtime currently maintains globally unique pointer identities for 
>> type metadata and protocol conformances. This makes checking type 
>> equivalence a trivial pointer equality comparison, but most operations on 
>> generic values do not really care about exact type identity and only need to 
>> invoke value or protocol witness methods or consult other data in the type 
>> metadata structure. I think it's worth reevaluating whether having globally 
>> unique type metadata objects is the correct design choice. Maintaining 
>> global uniqueness of metadata instances carries a number of costs. Any code 
>> that wants type metadata for an instance of a generic type, even a fully 
>> concrete one, must make a potentially expensive runtime call to get the 
>> canonical metadata instance. This also greatly complicates our ability to 
>> emit specializations of type metadata, value witness tables, or protocol 
>> witness tables for concrete instances of generic types, since 
>> specializations would need to be registered with the runtime as canonical 
>> metadata objects, and it would be difficult to do this lazily and still 
>> reliably favor specializations over more generic witnesses. The lack of 
>> witness table specializations leaves an obnoxious performance cliff for 
>> instances of generic types that end up inside existential containers or 
>> cross into unspecialized code. The runtime also obligates binaries to 
>> provide the canonical metadata for all of their public types, along with all 
>> the dependent value witnesses, class methods, and protocol witness tables, 
>> meaning a type abstraction can never be completely "zero-cost" across 
>> modules.
>> 
>> On the other hand, if type metadata did not need to be unique, then the 
>> compiler would be free to emit specialized type metadata and protocol 
>> witness tables for fully concrete non-concrete value types without 
>> consulting the runtime. This would let us avoid runtime calls to fetch 
>> metadata in specialized code, and would make it much easier for us to 
>> implement witness specialization. It would also give us the ability to 
>> potentially extend the "inlinable" concept to public fragile types, making 
>> it a client's responsibility to emit metadata for the type when needed and 
>> keeping the type from affecting its home module's ABI. This could 
>> significantly reduce the size and ABI surface area of the standard library, 
>> since the standard library contains a lot of generic lightweight adapter 
>> types for collections and other abstractions that are intended to be 
>> optimized away in most use cases.
>> 
>> There are of course benefits to globally unique metadata objects that we 
>> would lose if we gave up uniqueness. Operations that do check type identity, 
>> such as comparison, hashing, and dynamic casting, would have to perform more 
>> expensive checks, and nonunique metadata objects would need to carry 
>> additional information to enable those checks. It is likely that class 
>> objects would have to remain globally unique, if for no other reason than 
>> that the Objective-C runtime requires it on Apple platforms. Having multiple 
>> equivalent copies of type metadata has the potential to increase the working 
>> set of an app in some situations, although it's likely that redundant 
>> compiler-emitted copies of value type metadata would at least be able to 
>> live in constant pages mapped from disk instead of getting dynamically 
>> instantiated by the runtime like everything is today. There could also be 
>> subtle source-breaking behavior for code that bitcasts metatype values to 
>> integers or pointers and expects bit-level equality to indicate type 
>> equality. It's unlikely to me that giving up uniqueness would buy us any 
>> simplification to the runtime, since the runtime would still need to be able 
>> to instantiate metadata for unspecialized code, and we would still want to 
>> unique runtime-instantiated metadata objects as an optimization.
>> 
>> Overall, my intuition is that the tradeoffs come out in favor for nonunique 
>> metadata objects, but what do you all think? Is there anything I'm missing?
>> 
>> -Joe
> 
> In a premature proposal two years ago, we agreed to ditch unique protocol 
> conformances but install the canonical address as the first entry in each 
> specialized table.

This would be a reference to (unique) global data about the conformance, not a 
reference to some canonical version of the protocol witness table.  We do not 
rely on having a canonical protocol witness table.  The only reason we unique 
them (when we do need to instantiate) is because we don't want to track their 
lifetimes.

> That would mitigate the disadvantages that you pointed to. But, we would also 
> lose the ability to emit specialized metadata/conformances in constant pages. 
> How do you feel about that tradeoff?

Note that, per above, it's only specialized constant type metadata that we 
would lose.

I continue to feel that having to do structural equality tests on type metadata 
would be a huge loss.

John.
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to