Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-31 Thread John McCall via swift-dev

> On Jul 31, 2017, at 12:13 PM, Joe Groff  wrote:
> 
> 
>> On Jul 30, 2017, at 7:55 PM, John McCall via swift-dev > > wrote:
>> 
>>> On Jul 30, 2017, at 9:08 PM, Slava Pestov >> > wrote:
 On Jul 30, 2017, at 5:47 PM, John McCall > wrote:
> On Jul 29, 2017, at 7:35 PM, Slava Pestov  > wrote:
>> On Jul 29, 2017, at 12:53 PM, John McCall via swift-dev 
>> > wrote:
>>> On Jul 29, 2017, at 12:48 AM, Andrew Trick >> > wrote:
 On Jul 28, 2017, at 8:13 PM, John McCall > wrote:
> On Jul 28, 2017, at 11:11 PM, John McCall via swift-dev 
> > wrote:
>> On Jul 28, 2017, at 10:38 PM, Andrew Trick > > wrote:
>>> On Jul 28, 2017, at 3:15 PM, John McCall >> > wrote:
 On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
 > wrote:
 
 
> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
> > 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-31 Thread Joe Groff via swift-dev

> On Jul 31, 2017, at 9:21 AM, Erik Eckstein  wrote:
> 
> Would it be possible that whenever a specialized class is instantiated and 
> the metadata already exists with a generic vtable, it just overwrites the 
> vtable pointer in the metadata with the specialized version?
> I didn’t think that through, but maybe the same could be done for witness 
> tables?

Sure, we could redirect tables at runtime. It would require more runtime 
infrastructure, though we can't really get around uniquing vtables for classes, 
so that might be unavoidable.

-Joe
___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-31 Thread Jordan Rose via swift-dev


> On Jul 29, 2017, at 13:20, Chris Lattner  wrote:
> 
> 
>> On Jul 28, 2017, at 3:59 PM, Jordan Rose via swift-dev > > wrote:
>> 
 So generic code to instantiate type metadata would have to construct these 
 mangled strings eagerly?
>>> 
>>> We already do exactly that for the ObjC runtime name of generic class 
>>> instantiations, for what it's worth, but it could conceivably be lazy as 
>>> well, at the cost of making the comparison yet more expensive. There aren't 
>>> that many runtime operations that need to do type comparison, though—the 
>>> ones I can think of are casting and the equality/hashing operations on 
>>> Any.Type—so how important is efficient type comparison?
>> 
>> I'm still strongly against any feature that relies on type names being 
>> present at runtime. I think we should be able to omit those for both code 
>> size and secrecy reasons when the type isn't an @objc class or protocol.
> 
> Out of curiosity, is there something that strongly motivates this?  Aren’t 
> code obfuscation tools good enough for the few people who care?
> 
> Actually achieving “secrecy” would require revising the mangling scheme and 
> making lots of other changes to the runtime metadata.  This would be very 
> complicated and expensive, and almost no one cares AFAIK.

I've got a pile of secrecy-related Radars that says it's at least worth 
thinking about. I don't think it matters for public symbols but for non-public 
ones C people are used to being able to use names freely, even if Objective-C 
people know they can show up in the runtime metadata.

(We've also gotten complains that there aren't good code obfuscation tools for 
Swift, since we don't have a preprocessor. That's a separable issue, though.)

Jordan

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


Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-31 Thread Erik Eckstein via swift-dev
Would it be possible that whenever a specialized class is instantiated and the 
metadata already exists with a generic vtable, it just overwrites the vtable 
pointer in the metadata with the specialized version?
I didn’t think that through, but maybe the same could be done for witness 
tables?

> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  
> 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
> ___
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev

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


Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-31 Thread Joe Groff via swift-dev

> On Jul 30, 2017, at 7:55 PM, John McCall via swift-dev  
> wrote:
> 
>> On Jul 30, 2017, at 9:08 PM, Slava Pestov > > wrote:
>>> On Jul 30, 2017, at 5:47 PM, John McCall >> > wrote:
 On Jul 29, 2017, at 7:35 PM, Slava Pestov > wrote:
> On Jul 29, 2017, at 12:53 PM, John McCall via swift-dev 
> > wrote:
>> On Jul 29, 2017, at 12:48 AM, Andrew Trick > > wrote:
>>> On Jul 28, 2017, at 8:13 PM, John McCall >> > wrote:
 On Jul 28, 2017, at 11:11 PM, John McCall via swift-dev 
 > wrote:
> On Jul 28, 2017, at 10:38 PM, Andrew Trick  > wrote:
>> On Jul 28, 2017, at 3:15 PM, John McCall > > wrote:
>>> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
>>> > wrote:
>>> 
>>> 
 On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
 > 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 
 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-30 Thread John McCall via swift-dev
> On Jul 30, 2017, at 9:08 PM, Slava Pestov  wrote:
>> On Jul 30, 2017, at 5:47 PM, John McCall > > wrote:
>>> On Jul 29, 2017, at 7:35 PM, Slava Pestov >> > wrote:
 On Jul 29, 2017, at 12:53 PM, John McCall via swift-dev 
 > wrote:
> On Jul 29, 2017, at 12:48 AM, Andrew Trick  > wrote:
>> On Jul 28, 2017, at 8:13 PM, John McCall > > wrote:
>>> On Jul 28, 2017, at 11:11 PM, John McCall via swift-dev 
>>> > wrote:
 On Jul 28, 2017, at 10:38 PM, Andrew Trick > wrote:
> On Jul 28, 2017, at 3:15 PM, John McCall  > wrote:
>> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
>> > wrote:
>> 
>> 
>>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
>>> > 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-30 Thread Slava Pestov via swift-dev

> On Jul 30, 2017, at 5:47 PM, John McCall  wrote:
> 
>> On Jul 29, 2017, at 7:35 PM, Slava Pestov > > wrote:
>>> On Jul 29, 2017, at 12:53 PM, John McCall via swift-dev 
>>> > wrote:
 On Jul 29, 2017, at 12:48 AM, Andrew Trick > wrote:
> On Jul 28, 2017, at 8:13 PM, John McCall  > wrote:
>> On Jul 28, 2017, at 11:11 PM, John McCall via swift-dev 
>> > wrote:
>>> On Jul 28, 2017, at 10:38 PM, Andrew Trick >> > wrote:
 On Jul 28, 2017, at 3:15 PM, John McCall > wrote:
> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
> > wrote:
> 
> 
>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
>> > 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-29 Thread Slava Pestov via swift-dev

> On Jul 28, 2017, at 4:07 PM, Jordan Rose via swift-dev  
> wrote:
> 
> My point is we can't use our usual mangling in the string, because that 
> contains type names.
> 

We could invent a ‘mangling’ format (either using the existing demangler with a 
special flag or something else) where types inside the module are encoded as a 
pointer to a nominal type descriptor or something.

This would be useful for remote reflection as well, for secrecy and efficiency 
reasons.

Also being able to build metadata from a mangling will allow the standard 
library’s Mirror type to use the reflection metadata, instead of a ‘field type 
accessor’ which is emitted by IRGen for each value type, saving on code size.

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


Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-29 Thread Slava Pestov via swift-dev

> On Jul 29, 2017, at 12:53 PM, John McCall via swift-dev  
> wrote:
> 
>> On Jul 29, 2017, at 12:48 AM, Andrew Trick > > wrote:
>>> On Jul 28, 2017, at 8:13 PM, John McCall >> > wrote:
 On Jul 28, 2017, at 11:11 PM, John McCall via swift-dev 
 > wrote:
> On Jul 28, 2017, at 10:38 PM, Andrew Trick  > wrote:
>> On Jul 28, 2017, at 3:15 PM, John McCall > > wrote:
>>> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
>>> > wrote:
>>> 
>>> 
 On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
 > 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-29 Thread John McCall via swift-dev
> On Jul 29, 2017, at 4:33 PM, Chris Lattner  wrote:
>> On Jul 29, 2017, at 1:32 PM, John McCall  wrote:
>> 
>>> On Jul 29, 2017, at 4:24 PM, Chris Lattner via swift-dev 
>>>  wrote:
>>> 
>>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  
>>> wrote:
 
 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?
>>> 
>>> I think your proposal makes sense, particularly when we start caring about 
>>> metadata/conformances for non-nominal types, which don’t have a declaration 
>>> location.  They are a bit over the horizon right now, but we need to 
>>> support making tuples conform to protocols someday.  Eliminating the 
>>> requirement for them to be uniquely emitted across the entire program would 
>>> make that much simpler, because otherwise you’re in the land of weak 
>>> symbols or something.
>> 
>> Not really, because the conformance is presumably still declared somewhere 
>> in Swift and therefore has a natural unique definition point even if the 
>> type doesn’t.
> 
> Ok, so you’re suggesting that the stdlib would have the “automatically 
> provided” conditional conformances for things like equatable, then each 
> module that actually uses one gets a specialization?

Well, presumably the stdlib's generic conformance would actually be usable 
itself, but yes, other modules could of course emit specialized witness tables 
if they want.

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


Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-29 Thread Chris Lattner via swift-dev

> On Jul 29, 2017, at 1:32 PM, John McCall  wrote:
> 
>> On Jul 29, 2017, at 4:24 PM, Chris Lattner via swift-dev 
>>  wrote:
>> 
>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  
>> wrote:
>>> 
>>> 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?
>> 
>> I think your proposal makes sense, particularly when we start caring about 
>> metadata/conformances for non-nominal types, which don’t have a declaration 
>> location.  They are a bit over the horizon right now, but we need to support 
>> making tuples conform to protocols someday.  Eliminating the requirement for 
>> them to be uniquely emitted across the entire program would make that much 
>> simpler, because otherwise you’re in the land of weak symbols or something.
> 
> Not really, because the conformance is presumably still declared somewhere in 
> Swift and therefore has a natural unique definition point even if the type 
> doesn’t.

Ok, so you’re suggesting that the stdlib would have the “automatically 
provided” conditional conformances for things like equatable, then each module 
that actually uses one gets a specialization?

-Chris

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


Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-29 Thread Chris Lattner via swift-dev
On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  
wrote:
> 
> 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?

I think your proposal makes sense, particularly when we start caring about 
metadata/conformances for non-nominal types, which don’t have a declaration 
location.  They are a bit over the horizon right now, but we need to support 
making tuples conform to protocols someday.  Eliminating the requirement for 
them to be uniquely emitted across the entire program would make that much 
simpler, because otherwise you’re in the land of weak symbols or something.

-Chris

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


Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-29 Thread Chris Lattner via swift-dev

> On Jul 28, 2017, at 3:59 PM, Jordan Rose via swift-dev  
> wrote:
> 
>>> So generic code to instantiate type metadata would have to construct these 
>>> mangled strings eagerly?
>> 
>> We already do exactly that for the ObjC runtime name of generic class 
>> instantiations, for what it's worth, but it could conceivably be lazy as 
>> well, at the cost of making the comparison yet more expensive. There aren't 
>> that many runtime operations that need to do type comparison, though—the 
>> ones I can think of are casting and the equality/hashing operations on 
>> Any.Type—so how important is efficient type comparison?
> 
> I'm still strongly against any feature that relies on type names being 
> present at runtime. I think we should be able to omit those for both code 
> size and secrecy reasons when the type isn't an @objc class or protocol.

Out of curiosity, is there something that strongly motivates this?  Aren’t code 
obfuscation tools good enough for the few people who care?

Actually achieving “secrecy” would require revising the mangling scheme and 
making lots of other changes to the runtime metadata.  This would be very 
complicated and expensive, and almost no one cares AFAIK.

-Chris

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


Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-29 Thread John McCall via swift-dev
> On Jul 29, 2017, at 12:48 AM, Andrew Trick  wrote:
>> On Jul 28, 2017, at 8:13 PM, John McCall > > wrote:
>>> On Jul 28, 2017, at 11:11 PM, John McCall via swift-dev 
>>> > wrote:
 On Jul 28, 2017, at 10:38 PM, Andrew Trick > wrote:
> On Jul 28, 2017, at 3:15 PM, John McCall  > wrote:
>> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
>> > wrote:
>> 
>> 
>>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
>>> > 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 
>>> 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread Andrew Trick via swift-dev

> On Jul 28, 2017, at 8:13 PM, John McCall  wrote:
> 
>> On Jul 28, 2017, at 11:11 PM, John McCall via swift-dev > > wrote:
>>> On Jul 28, 2017, at 10:38 PM, Andrew Trick >> > wrote:
 On Jul 28, 2017, at 3:15 PM, John McCall > wrote:
> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
> > wrote:
> 
> 
>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
>> > 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread John McCall via swift-dev
> On Jul 28, 2017, at 11:11 PM, John McCall via swift-dev  
> wrote:
>> On Jul 28, 2017, at 10:38 PM, Andrew Trick > > wrote:
>>> On Jul 28, 2017, at 3:15 PM, John McCall >> > wrote:
 On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
 > wrote:
 
 
> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  > 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread Andrew Trick via swift-dev

> On Jul 28, 2017, at 3:15 PM, John McCall  wrote:
> 
>> 
>> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
>>  wrote:
>> 
>> 
>>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  
>>> 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread Jonathan Hull via swift-dev
Is there a way to split the difference?

You would still have a repository of canonical metadata, but you could have 
another non-unique structure which can be used for most cases without having to 
go get the canonical version.  You could use the non-unique structure to lookup 
the canonical version when desired, and the structure would contain enough 
information to create a canonical version lazily the first time it is needed.  

That way, you could just use the non-unique structures… but they could be 
exchanged for a unique/canonical version (or one can be created) when that 
really is needed.

I am a bit out of my depth here, so hopefully this makes at least a little 
sense...

Thanks,
Jon


> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  
> 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
> ___
> 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread Joe Groff via swift-dev

> On Jul 28, 2017, at 3:54 PM, John McCall  wrote:
> 
>> On Jul 28, 2017, at 6:34 PM, Joe Groff  wrote:
>>> On Jul 28, 2017, at 3:30 PM, John McCall  wrote:
 On Jul 28, 2017, at 6:24 PM, Joe Groff  wrote:
> On Jul 28, 2017, at 3:15 PM, John McCall  wrote:
> 
> 
>> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
>>  wrote:
>> 
>> 
>>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
>>>  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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread Jordan Rose via swift-dev


> On Jul 28, 2017, at 16:03, Joe Groff  wrote:
> 
> 
>> On Jul 28, 2017, at 3:59 PM, Jordan Rose > > wrote:
>> 
>> 
>> 
>>> On Jul 28, 2017, at 15:35, Joe Groff via swift-dev >> > wrote:
>>> 
 
 On Jul 28, 2017, at 3:30 PM, John McCall > wrote:
 
> On Jul 28, 2017, at 6:24 PM, Joe Groff  > wrote:
>> On Jul 28, 2017, at 3:15 PM, John McCall > > wrote:
>> 
>> 
>>> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
>>> > wrote:
>>> 
>>> 
 On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
 > 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread Joe Groff via swift-dev

> On Jul 28, 2017, at 3:59 PM, Jordan Rose  wrote:
> 
> 
> 
>> On Jul 28, 2017, at 15:35, Joe Groff via swift-dev > > wrote:
>> 
>>> 
>>> On Jul 28, 2017, at 3:30 PM, John McCall >> > wrote:
>>> 
 On Jul 28, 2017, at 6:24 PM, Joe Groff > wrote:
> On Jul 28, 2017, at 3:15 PM, John McCall  > wrote:
> 
> 
>> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
>> > wrote:
>> 
>> 
>>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
>>> > 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread John McCall via swift-dev
> On Jul 28, 2017, at 6:34 PM, Joe Groff  wrote:
>> On Jul 28, 2017, at 3:30 PM, John McCall  wrote:
>>> On Jul 28, 2017, at 6:24 PM, Joe Groff  wrote:
 On Jul 28, 2017, at 3:15 PM, John McCall  wrote:
 
 
> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
>  wrote:
> 
> 
>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev 
>>  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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread John McCall via swift-dev
> On Jul 28, 2017, at 6:24 PM, Joe Groff  wrote:
>> On Jul 28, 2017, at 3:15 PM, John McCall  wrote:
>> 
>> 
>>> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev 
>>>  wrote:
>>> 
>>> 
 On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  
 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread John McCall via swift-dev

> On Jul 28, 2017, at 6:02 PM, Andrew Trick via swift-dev  
> wrote:
> 
> 
>> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  
>> 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 

Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread Andrew Trick via swift-dev

> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  
> 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. 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?

-Andy

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


Re: [swift-dev] Reconsidering the global uniqueness of type metadata and protocol conformance instances

2017-07-28 Thread Michael Ilseman via swift-dev

> On Jul 28, 2017, at 2:20 PM, Joe Groff via swift-dev  
> 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,

This seems pretty compelling

> and it would be difficult to do this lazily and still reliably favor 
> specializations over more generic witnesses.

What do you mean by doing this lazily and favoring the specializations?

> 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.
> 

Do you have some examples here to illustrate? E.g. if I pass an instance of 
concrete type to something taking a T:Hashable, how does that currently work vs 
how it would work with this change? Would this mean that I can just pass off a 
function pointer to the hashing function? Do I need some kind of id scheme if 
the callee might want to cast or do something else with it?

> 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.

How do you think this will work? Do you think we will want a way to go from a 
non-unique type metadata to some kind of canonical, uniqued type metadata? 
Would it make sense to key this off of a mangled name?

> 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.

This sounds very niche, and I don’t think we have promised any kind of 
stability or compatibility in that area.

> 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