> On Jul 28, 2017, at 3:15 PM, John McCall <rjmcc...@apple.com> wrote: > >> >> 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.
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. -Andy
_______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev