> On Jul 28, 2017, at 11:11 PM, John McCall via swift-dev <swift-dev@swift.org>
> wrote:
>> On Jul 28, 2017, at 10:38 PM, Andrew Trick <atr...@apple.com
>> <mailto:atr...@apple.com>> wrote:
>>> On Jul 28, 2017, at 3:15 PM, John McCall <rjmcc...@apple.com
>>> <mailto:rjmcc...@apple.com>> wrote:
>>>> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev
>>>> <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:
>>>>
>>>>
>>>>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev <swift-dev@swift.org
>>>>> <mailto: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.
>>
>> My question was really, are we going to runtime-initialize the specialized
>> metadata and specialized witness tables in order to install the unique
>> identifier, rather than requiring a runtime call whenever we need the unique
>> ID. I think the answer is “yes”, we want to install the ID at initialization
>> time for fast type comparison, hashing and casting.
>
> Sorry, by "(unique) global data about the conformance" I meant that we would
> emit a global conformance descriptor in constant data for the conformance
> declaration. There would be one of these, no matter how many it was
> instantiated; it would therefore uniquely identify a possible generic
> conformance the same way that a nominal type descriptor uniquely identifies a
> possibly generic type. The reference to it would just be an ordinary symbol
> reference.
Naturally, eagerly emitting one of those has the same advantages and
disadvantages as eagerly emitting type metadata and everything else, and can be
solved in the same way.
John.
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev