Re: [swift-dev] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-17 Thread Michael Gottesman via swift-dev

> On Oct 17, 2016, at 12:01 PM, Michael Gottesman  wrote:
> 
> 
>> On Oct 17, 2016, at 11:53 AM, Michael Gottesman via swift-dev 
>> > wrote:
>> 
>> 
>>> On Oct 17, 2016, at 10:00 AM, Joe Groff >> > wrote:
>>> 
>>> 
 On Oct 17, 2016, at 9:57 AM, Michael Gottesman > wrote:
 
 
> On Oct 17, 2016, at 9:42 AM, Joe Groff via swift-dev  > wrote:
> 
> 
>> On Oct 16, 2016, at 1:10 PM, Dave Abrahams via swift-dev 
>> > wrote:
>> 
>> 
>> on Thu Oct 13 2016, Joe Groff > > wrote:
>> 
 On Oct 13, 2016, at 1:18 PM, Greg Parker > wrote:
 
 
> On Oct 13, 2016, at 10:46 AM, John McCall via swift-dev 
> > wrote:
> 
>>> 
>> On Oct 13, 2016, at 9:04 AM, Joe Groff via swift-dev 
>> > wrote:
>> 
>>> On Mar 1, 2016, at 1:33 PM, Joe Groff via swift-dev 
>>> > wrote:
>>> 
>>> In swift_retain/release, we have an early-exit check to pass
>>> through a nil pointer. Since we're already burning branch, I'm
>>> thinking we could pass through not only zero but negative pointer
>>> values too on 64-bit systems, since negative pointers are never
>>> valid userspace pointers on our 64-bit targets. This would give
>>> us room for tagged-pointer-like optimizations, for instance to
>>> avoid allocations for tiny closure contexts.
>> 
>> I'd like to resurrect this thread as we look to locking down the
>> ABI. There were portability concerns about doing this unilaterally
>> for all 64-bit targets, but AFAICT it should be safe for x86-64
>> and Apple AArch64 targets. The x86-64 ABI limits the userland
>> address space, per section 3.3.2:
>> 
>> Although the AMD64 architecture uses 64-bit pointers,
>> implementations are only required to handle 48-bit
>> addresses. Therefore, conforming processes may only use addresses
>> from 0x  to 0x7fff .
>> 
>> Apple's ARM64 platforms always enable the top-byte-ignore
>> architectural feature, restricting the available address space to
>> the low 56 bits of the full 64-bit address space in
>> practice. Therefore, "negative" values should never be valid
>> user-space references to Swift-refcountable objects. Taking
>> advantage of this fact would enable us to optimize small closure
>> contexts, Error objects, and, if we move to a reference-counted
>> COW model for existentials, small `Any` values, which need to be
>> refcountable for ABI reasons but don't semantically promise a
>> unique identity like class instances do.
> 
> This makes sense to me.  if (x <= 0) return; should be just as cheap 
> as is (x == 0) return;
 
 Conversely, I wanted to try to remove such nil checks. Currently
 they look haphazard: some functions have them and some do not.
 
 Allowing ABI space for tagged pointer objects is a much bigger
 problem than the check in swift_retain/release. For example, all
 vtable and witness table dispatch sites to AnyObject or any other
 type that might someday have a tagged pointer subclass would need to
 compile in a fallback path now. You can't dereference a tagged
 pointer to get its class pointer.
>>> 
>>> True. I don't think we'd want to use this optimization for class
>>> types; I was specifically thinking of other things for which we use
>>> nullable refcounted representations, particularly closure
>>> contexts. The ABI for function types requires the context to be
>>> refcountable by swift_retain/release, but it doesn't necessarily have
>>> to be a valid pointer, if the closure formation site and invocation
>>> function agree on a tagged-pointer representation. 
>> 
>> Well, but we'd like to take advantage of the same kind of optimization
>> for the small string optimization.  It doesn't seem like this should be
>> handled differently just because the string buffer is a class instance
>> and not a closure context.
> 
> String is a struct, and small strings don't have to be modeled as class 
> instances. An enum { case Big(StringStorage), Small(Int63) } or similar 
> layout should be able to take advantage of 

Re: [swift-dev] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-17 Thread Michael Gottesman via swift-dev

> On Oct 17, 2016, at 11:53 AM, Michael Gottesman via swift-dev 
>  wrote:
> 
> 
>> On Oct 17, 2016, at 10:00 AM, Joe Groff > > wrote:
>> 
>> 
>>> On Oct 17, 2016, at 9:57 AM, Michael Gottesman >> > wrote:
>>> 
>>> 
 On Oct 17, 2016, at 9:42 AM, Joe Groff via swift-dev > wrote:
 
 
> On Oct 16, 2016, at 1:10 PM, Dave Abrahams via swift-dev 
> > wrote:
> 
> 
> on Thu Oct 13 2016, Joe Groff  > wrote:
> 
>>> On Oct 13, 2016, at 1:18 PM, Greg Parker >> > wrote:
>>> 
>>> 
 On Oct 13, 2016, at 10:46 AM, John McCall via swift-dev 
 > wrote:
 
>> 
> On Oct 13, 2016, at 9:04 AM, Joe Groff via swift-dev 
> > wrote:
> 
>> On Mar 1, 2016, at 1:33 PM, Joe Groff via swift-dev 
>> > wrote:
>> 
>> In swift_retain/release, we have an early-exit check to pass
>> through a nil pointer. Since we're already burning branch, I'm
>> thinking we could pass through not only zero but negative pointer
>> values too on 64-bit systems, since negative pointers are never
>> valid userspace pointers on our 64-bit targets. This would give
>> us room for tagged-pointer-like optimizations, for instance to
>> avoid allocations for tiny closure contexts.
> 
> I'd like to resurrect this thread as we look to locking down the
> ABI. There were portability concerns about doing this unilaterally
> for all 64-bit targets, but AFAICT it should be safe for x86-64
> and Apple AArch64 targets. The x86-64 ABI limits the userland
> address space, per section 3.3.2:
> 
> Although the AMD64 architecture uses 64-bit pointers,
> implementations are only required to handle 48-bit
> addresses. Therefore, conforming processes may only use addresses
> from 0x  to 0x7fff .
> 
> Apple's ARM64 platforms always enable the top-byte-ignore
> architectural feature, restricting the available address space to
> the low 56 bits of the full 64-bit address space in
> practice. Therefore, "negative" values should never be valid
> user-space references to Swift-refcountable objects. Taking
> advantage of this fact would enable us to optimize small closure
> contexts, Error objects, and, if we move to a reference-counted
> COW model for existentials, small `Any` values, which need to be
> refcountable for ABI reasons but don't semantically promise a
> unique identity like class instances do.
 
 This makes sense to me.  if (x <= 0) return; should be just as cheap 
 as is (x == 0) return;
>>> 
>>> Conversely, I wanted to try to remove such nil checks. Currently
>>> they look haphazard: some functions have them and some do not.
>>> 
>>> Allowing ABI space for tagged pointer objects is a much bigger
>>> problem than the check in swift_retain/release. For example, all
>>> vtable and witness table dispatch sites to AnyObject or any other
>>> type that might someday have a tagged pointer subclass would need to
>>> compile in a fallback path now. You can't dereference a tagged
>>> pointer to get its class pointer.
>> 
>> True. I don't think we'd want to use this optimization for class
>> types; I was specifically thinking of other things for which we use
>> nullable refcounted representations, particularly closure
>> contexts. The ABI for function types requires the context to be
>> refcountable by swift_retain/release, but it doesn't necessarily have
>> to be a valid pointer, if the closure formation site and invocation
>> function agree on a tagged-pointer representation. 
> 
> Well, but we'd like to take advantage of the same kind of optimization
> for the small string optimization.  It doesn't seem like this should be
> handled differently just because the string buffer is a class instance
> and not a closure context.
 
 String is a struct, and small strings don't have to be modeled as class 
 instances. An enum { case Big(StringStorage), Small(Int63) } or similar 
 layout should be able to take advantage of swift_retain/release ignoring 
 negative values too.
>>> 
>>> I need to catch up on this thread, but there is an important thing to 
>>> remember. If you use an enum like this there are a few potential issues:
>>> 

Re: [swift-dev] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-17 Thread Dave Abrahams via swift-dev

on Mon Oct 17 2016, Joe Groff  wrote:

>> On Oct 16, 2016, at 1:10 PM, Dave Abrahams via swift-dev 
>>  wrote:
>> 
>> 
>> on Thu Oct 13 2016, Joe Groff  wrote:
>> 
>
 On Oct 13, 2016, at 1:18 PM, Greg Parker  wrote:
 
 
> On Oct 13, 2016, at 10:46 AM, John McCall via swift-dev 
>  wrote:
> 
>>> 
>> On Oct 13, 2016, at 9:04 AM, Joe Groff via swift-dev 
>>  wrote:
>> 
>>> On Mar 1, 2016, at 1:33 PM, Joe Groff via swift-dev 
>>>  wrote:
>>> 
>>> In swift_retain/release, we have an early-exit check to pass
>>> through a nil pointer. Since we're already burning branch, I'm
>>> thinking we could pass through not only zero but negative pointer
>>> values too on 64-bit systems, since negative pointers are never
>>> valid userspace pointers on our 64-bit targets. This would give
>>> us room for tagged-pointer-like optimizations, for instance to
>>> avoid allocations for tiny closure contexts.
>> 
>> I'd like to resurrect this thread as we look to locking down the
>> ABI. There were portability concerns about doing this unilaterally
>> for all 64-bit targets, but AFAICT it should be safe for x86-64
>> and Apple AArch64 targets. The x86-64 ABI limits the userland
>> address space, per section 3.3.2:
>> 
>> Although the AMD64 architecture uses 64-bit pointers,
>> implementations are only required to handle 48-bit
>> addresses. Therefore, conforming processes may only use addresses
>> from 0x  to 0x7fff .
>> 
>> Apple's ARM64 platforms always enable the top-byte-ignore
>> architectural feature, restricting the available address space to
>> the low 56 bits of the full 64-bit address space in
>> practice. Therefore, "negative" values should never be valid
>> user-space references to Swift-refcountable objects. Taking
>> advantage of this fact would enable us to optimize small closure
>> contexts, Error objects, and, if we move to a reference-counted
>> COW model for existentials, small `Any` values, which need to be
>> refcountable for ABI reasons but don't semantically promise a
>> unique identity like class instances do.
> 
> This makes sense to me.  if (x <= 0) return; should be just as cheap as 
> is (x == 0) return;
 
 Conversely, I wanted to try to remove such nil checks. Currently
 they look haphazard: some functions have them and some do not.
 
 Allowing ABI space for tagged pointer objects is a much bigger
 problem than the check in swift_retain/release. For example, all
 vtable and witness table dispatch sites to AnyObject or any other
 type that might someday have a tagged pointer subclass would need to
 compile in a fallback path now. You can't dereference a tagged
 pointer to get its class pointer.
>>> 
>>> True. I don't think we'd want to use this optimization for class
>>> types; I was specifically thinking of other things for which we use
>>> nullable refcounted representations, particularly closure
>>> contexts. The ABI for function types requires the context to be
>>> refcountable by swift_retain/release, but it doesn't necessarily have
>>> to be a valid pointer, if the closure formation site and invocation
>>> function agree on a tagged-pointer representation. 
>> 
>> Well, but we'd like to take advantage of the same kind of optimization
>> for the small string optimization.  It doesn't seem like this should be
>> handled differently just because the string buffer is a class instance
>> and not a closure context.
>
> String is a struct, and small strings don't have to be modeled as
> class instances. An enum { case Big(StringStorage), Small(Int63) } or
> similar layout should be able to take advantage of
> swift_retain/release ignoring negative values too.

That would be nice.  Historically I've had to bypass enums either
because the codegen or the optimizer wasn't smart enough.

We *had* wanted to use some of the same tagged pointer representations
as Cocoa does for NSString, and if we give up layout to the enum codegen
machinery we won't get that.  That would be a very minor
performance win, though, so it probably doesn't matter.

>
> -Joe
>
>>> We could also do interesting things with enums; if one payload type is
>>> a class reference and the rest are trivial, we could lay the enum out
>>> in such a way that we can use swift_retain/release on it by setting
>>> the high bit when tagging the trivial representations, saving us the
>>> need to emit a switch. We wouldn't actually dereference the pointer
>>> representation without checking it first.
>>> 
>>> I know we've discussed taking the nil check out of
>>> swift_retain/release, and possibly having separate variants that do
>>> include the null check for when we know we're working with
>>> Optionals. How 

Re: [swift-dev] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-17 Thread Michael Gottesman via swift-dev

> On Oct 17, 2016, at 9:42 AM, Joe Groff via swift-dev  
> wrote:
> 
> 
>> On Oct 16, 2016, at 1:10 PM, Dave Abrahams via swift-dev 
>>  wrote:
>> 
>> 
>> on Thu Oct 13 2016, Joe Groff  wrote:
>> 
 On Oct 13, 2016, at 1:18 PM, Greg Parker  wrote:
 
 
> On Oct 13, 2016, at 10:46 AM, John McCall via swift-dev 
>  wrote:
> 
>>> 
>> On Oct 13, 2016, at 9:04 AM, Joe Groff via swift-dev 
>>  wrote:
>> 
>>> On Mar 1, 2016, at 1:33 PM, Joe Groff via swift-dev 
>>>  wrote:
>>> 
>>> In swift_retain/release, we have an early-exit check to pass
>>> through a nil pointer. Since we're already burning branch, I'm
>>> thinking we could pass through not only zero but negative pointer
>>> values too on 64-bit systems, since negative pointers are never
>>> valid userspace pointers on our 64-bit targets. This would give
>>> us room for tagged-pointer-like optimizations, for instance to
>>> avoid allocations for tiny closure contexts.
>> 
>> I'd like to resurrect this thread as we look to locking down the
>> ABI. There were portability concerns about doing this unilaterally
>> for all 64-bit targets, but AFAICT it should be safe for x86-64
>> and Apple AArch64 targets. The x86-64 ABI limits the userland
>> address space, per section 3.3.2:
>> 
>> Although the AMD64 architecture uses 64-bit pointers,
>> implementations are only required to handle 48-bit
>> addresses. Therefore, conforming processes may only use addresses
>> from 0x  to 0x7fff .
>> 
>> Apple's ARM64 platforms always enable the top-byte-ignore
>> architectural feature, restricting the available address space to
>> the low 56 bits of the full 64-bit address space in
>> practice. Therefore, "negative" values should never be valid
>> user-space references to Swift-refcountable objects. Taking
>> advantage of this fact would enable us to optimize small closure
>> contexts, Error objects, and, if we move to a reference-counted
>> COW model for existentials, small `Any` values, which need to be
>> refcountable for ABI reasons but don't semantically promise a
>> unique identity like class instances do.
> 
> This makes sense to me.  if (x <= 0) return; should be just as cheap as 
> is (x == 0) return;
 
 Conversely, I wanted to try to remove such nil checks. Currently
 they look haphazard: some functions have them and some do not.
 
 Allowing ABI space for tagged pointer objects is a much bigger
 problem than the check in swift_retain/release. For example, all
 vtable and witness table dispatch sites to AnyObject or any other
 type that might someday have a tagged pointer subclass would need to
 compile in a fallback path now. You can't dereference a tagged
 pointer to get its class pointer.
>>> 
>>> True. I don't think we'd want to use this optimization for class
>>> types; I was specifically thinking of other things for which we use
>>> nullable refcounted representations, particularly closure
>>> contexts. The ABI for function types requires the context to be
>>> refcountable by swift_retain/release, but it doesn't necessarily have
>>> to be a valid pointer, if the closure formation site and invocation
>>> function agree on a tagged-pointer representation. 
>> 
>> Well, but we'd like to take advantage of the same kind of optimization
>> for the small string optimization.  It doesn't seem like this should be
>> handled differently just because the string buffer is a class instance
>> and not a closure context.
> 
> String is a struct, and small strings don't have to be modeled as class 
> instances. An enum { case Big(StringStorage), Small(Int63) } or similar 
> layout should be able to take advantage of swift_retain/release ignoring 
> negative values too.

I need to catch up on this thread, but there is an important thing to remember. 
If you use an enum like this there are a few potential issues:

1. In the implementation, you will /not/ want to use the enum internally. This 
would prevent the optimizer from eliminating all of the Small Case reference 
counting operations. This means you would rewrap the internal value when you 
return one and when you enter into an internal implementation code path try to 
immediately switch to a specialized small case path if you can.
2. {Retain,Release}Values will be created outside. We are talking about some 
ways of fixing this from a code-size perspective by using a value witness, but 
in the present this may cause additional code-size increase.



> 
> -Joe
> 
>>> We could also do interesting things with enums; if one payload type is
>>> a class reference and the rest are trivial, we could lay the enum out
>>> in such a way that we can use swift_retain/release on 

Re: [swift-dev] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-17 Thread Joe Groff via swift-dev

> On Oct 16, 2016, at 1:10 PM, Dave Abrahams via swift-dev 
>  wrote:
> 
> 
> on Thu Oct 13 2016, Joe Groff  wrote:
> 
>>> On Oct 13, 2016, at 1:18 PM, Greg Parker  wrote:
>>> 
>>> 
 On Oct 13, 2016, at 10:46 AM, John McCall via swift-dev 
  wrote:
 
>> 
> On Oct 13, 2016, at 9:04 AM, Joe Groff via swift-dev 
>  wrote:
> 
>> On Mar 1, 2016, at 1:33 PM, Joe Groff via swift-dev 
>>  wrote:
>> 
>> In swift_retain/release, we have an early-exit check to pass
>> through a nil pointer. Since we're already burning branch, I'm
>> thinking we could pass through not only zero but negative pointer
>> values too on 64-bit systems, since negative pointers are never
>> valid userspace pointers on our 64-bit targets. This would give
>> us room for tagged-pointer-like optimizations, for instance to
>> avoid allocations for tiny closure contexts.
> 
> I'd like to resurrect this thread as we look to locking down the
> ABI. There were portability concerns about doing this unilaterally
> for all 64-bit targets, but AFAICT it should be safe for x86-64
> and Apple AArch64 targets. The x86-64 ABI limits the userland
> address space, per section 3.3.2:
> 
> Although the AMD64 architecture uses 64-bit pointers,
> implementations are only required to handle 48-bit
> addresses. Therefore, conforming processes may only use addresses
> from 0x  to 0x7fff .
> 
> Apple's ARM64 platforms always enable the top-byte-ignore
> architectural feature, restricting the available address space to
> the low 56 bits of the full 64-bit address space in
> practice. Therefore, "negative" values should never be valid
> user-space references to Swift-refcountable objects. Taking
> advantage of this fact would enable us to optimize small closure
> contexts, Error objects, and, if we move to a reference-counted
> COW model for existentials, small `Any` values, which need to be
> refcountable for ABI reasons but don't semantically promise a
> unique identity like class instances do.
 
 This makes sense to me.  if (x <= 0) return; should be just as cheap as is 
 (x == 0) return;
>>> 
>>> Conversely, I wanted to try to remove such nil checks. Currently
>>> they look haphazard: some functions have them and some do not.
>>> 
>>> Allowing ABI space for tagged pointer objects is a much bigger
>>> problem than the check in swift_retain/release. For example, all
>>> vtable and witness table dispatch sites to AnyObject or any other
>>> type that might someday have a tagged pointer subclass would need to
>>> compile in a fallback path now. You can't dereference a tagged
>>> pointer to get its class pointer.
>> 
>> True. I don't think we'd want to use this optimization for class
>> types; I was specifically thinking of other things for which we use
>> nullable refcounted representations, particularly closure
>> contexts. The ABI for function types requires the context to be
>> refcountable by swift_retain/release, but it doesn't necessarily have
>> to be a valid pointer, if the closure formation site and invocation
>> function agree on a tagged-pointer representation. 
> 
> Well, but we'd like to take advantage of the same kind of optimization
> for the small string optimization.  It doesn't seem like this should be
> handled differently just because the string buffer is a class instance
> and not a closure context.

String is a struct, and small strings don't have to be modeled as class 
instances. An enum { case Big(StringStorage), Small(Int63) } or similar layout 
should be able to take advantage of swift_retain/release ignoring negative 
values too.

-Joe

>> We could also do interesting things with enums; if one payload type is
>> a class reference and the rest are trivial, we could lay the enum out
>> in such a way that we can use swift_retain/release on it by setting
>> the high bit when tagging the trivial representations, saving us the
>> need to emit a switch. We wouldn't actually dereference the pointer
>> representation without checking it first.
>> 
>> I know we've discussed taking the nil check out of
>> swift_retain/release, and possibly having separate variants that do
>> include the null check for when we know we're working with
>> Optionals. How much of difference would that really make, though? I'd
>> expect it to be a fairly easily predictable branch, since most objects
>> are likely to be nonnull in practice.
>> 
>> -Joe
>> ___
>> swift-dev mailing list
>> swift-dev@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-dev
> 
> -- 
> -Dave
> 
> ___
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-13 Thread Alexis via swift-dev


> On Oct 13, 2016, at 5:14 PM, Joe Groff  wrote:
> 
> 
>> On Oct 13, 2016, at 2:04 PM, Alexis  wrote:
>> 
>> Correct me if I’m wrong, but aren’t all kernel addresses negative on x64 and 
>> AArch64? Would this then mean any attempt to use Swift in kernel-space 
>> requires a distinct ABI?
> 
> That's correct, but we'd likely already have to have a separate "kernel" ABI 
> due to our assumptions about spare bits in pointers. It also seems unlikely 
> to me that kernel developers would want to use our refcounting scheme as is.

True, but the types being discussed here seem to mostly be language features 
that are implicitly falling back to reference counting when escape analysis 
fails. And specifically the tagging you’re proposing is for the cases where 
some special analysis passes and we can avoid the ref-counting machinery, 
right? Sounds like exactly the things they want. Although perhaps if they want 
to always avoid the ref-counting machinery, then we can actually have more 
aggressive pointer tagging tricks in the kernel ABI. 

Well, as long as we’re aware that this is more complexity we’re adopting, seems 
fine.

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


Re: [swift-dev] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-13 Thread John McCall via swift-dev

> On Oct 13, 2016, at 2:14 PM, Joe Groff via swift-dev  
> wrote:
> 
> 
>> On Oct 13, 2016, at 2:04 PM, Alexis  wrote:
>> 
>> Correct me if I’m wrong, but aren’t all kernel addresses negative on x64 and 
>> AArch64? Would this then mean any attempt to use Swift in kernel-space 
>> requires a distinct ABI?
> 
> That's correct, but we'd likely already have to have a separate "kernel" ABI 
> due to our assumptions about spare bits in pointers.

This is exactly my thinking.

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


Re: [swift-dev] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-13 Thread Alexis via swift-dev
Correct me if I’m wrong, but aren’t all kernel addresses negative on x64 and 
AArch64? Would this then mean any attempt to use Swift in kernel-space requires 
a distinct ABI?

> On Oct 13, 2016, at 12:04 PM, Joe Groff via swift-dev  
> wrote:
> 
> 
>> On Mar 1, 2016, at 1:33 PM, Joe Groff via swift-dev > > wrote:
>> 
>> In swift_retain/release, we have an early-exit check to pass through a nil 
>> pointer. Since we're already burning branch, I'm thinking we could pass 
>> through not only zero but negative pointer values too on 64-bit systems, 
>> since negative pointers are never valid userspace pointers on our 64-bit 
>> targets. This would give us room for tagged-pointer-like optimizations, for 
>> instance to avoid allocations for tiny closure contexts.
> 
> I'd like to resurrect this thread as we look to locking down the ABI. There 
> were portability concerns about doing this unilaterally for all 64-bit 
> targets, but AFAICT it should be safe for x86-64 and Apple AArch64 targets. 
> The x86-64 ABI limits the userland address space, per section 3.3.2:
> 
> Although the AMD64 architecture uses 64-bit pointers, implementations are 
> only required to handle 48-bit addresses. Therefore, conforming processes may 
> only use addresses from 0x  to 0x7fff .
> 
> Apple's ARM64 platforms always enable the top-byte-ignore architectural 
> feature, restricting the available address space to the low 56 bits of the 
> full 64-bit address space in practice. Therefore, "negative" values should 
> never be valid user-space references to Swift-refcountable objects. Taking 
> advantage of this fact would enable us to optimize small closure contexts, 
> Error objects, and, if we move to a reference-counted COW model for 
> existentials, small `Any` values, which need to be refcountable for ABI 
> reasons but don't semantically promise a unique identity like class instances 
> do.
> 
> -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] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-13 Thread Joe Groff via swift-dev

> On Oct 13, 2016, at 1:18 PM, Greg Parker  wrote:
> 
> 
>> On Oct 13, 2016, at 10:46 AM, John McCall via swift-dev 
>>  wrote:
>> 
>>> On Oct 13, 2016, at 9:04 AM, Joe Groff via swift-dev  
>>> wrote:
>>> 
 On Mar 1, 2016, at 1:33 PM, Joe Groff via swift-dev  
 wrote:
 
 In swift_retain/release, we have an early-exit check to pass through a nil 
 pointer. Since we're already burning branch, I'm thinking we could pass 
 through not only zero but negative pointer values too on 64-bit systems, 
 since negative pointers are never valid userspace pointers on our 64-bit 
 targets. This would give us room for tagged-pointer-like optimizations, 
 for instance to avoid allocations for tiny closure contexts.
>>> 
>>> I'd like to resurrect this thread as we look to locking down the ABI. There 
>>> were portability concerns about doing this unilaterally for all 64-bit 
>>> targets, but AFAICT it should be safe for x86-64 and Apple AArch64 targets. 
>>> The x86-64 ABI limits the userland address space, per section 3.3.2:
>>> 
>>> Although the AMD64 architecture uses 64-bit pointers, implementations are 
>>> only required to handle 48-bit addresses. Therefore, conforming processes 
>>> may only use addresses from 0x  to 0x7fff .
>>> 
>>> Apple's ARM64 platforms always enable the top-byte-ignore architectural 
>>> feature, restricting the available address space to the low 56 bits of the 
>>> full 64-bit address space in practice. Therefore, "negative" values should 
>>> never be valid user-space references to Swift-refcountable objects. Taking 
>>> advantage of this fact would enable us to optimize small closure contexts, 
>>> Error objects, and, if we move to a reference-counted COW model for 
>>> existentials, small `Any` values, which need to be refcountable for ABI 
>>> reasons but don't semantically promise a unique identity like class 
>>> instances do.
>> 
>> This makes sense to me.  if (x <= 0) return; should be just as cheap as is 
>> (x == 0) return;
> 
> Conversely, I wanted to try to remove such nil checks. Currently they look 
> haphazard: some functions have them and some do not.
> 
> Allowing ABI space for tagged pointer objects is a much bigger problem than 
> the check in swift_retain/release. For example, all vtable and witness table 
> dispatch sites to AnyObject or any other type that might someday have a 
> tagged pointer subclass would need to compile in a fallback path now. You 
> can't dereference a tagged pointer to get its class pointer. 

True. I don't think we'd want to use this optimization for class types; I was 
specifically thinking of other things for which we use nullable refcounted 
representations, particularly closure contexts. The ABI for function types 
requires the context to be refcountable by swift_retain/release, but it doesn't 
necessarily have to be a valid pointer, if the closure formation site and 
invocation function agree on a tagged-pointer representation. We could also do 
interesting things with enums; if one payload type is a class reference and the 
rest are trivial, we could lay the enum out in such a way that we can use 
swift_retain/release on it by setting the high bit when tagging the trivial 
representations, saving us the need to emit a switch. We wouldn't actually 
dereference the pointer representation without checking it first.

I know we've discussed taking the nil check out of swift_retain/release, and 
possibly having separate variants that do include the null check for when we 
know we're working with Optionals. How much of difference would that really 
make, though? I'd expect it to be a fairly easily predictable branch, since 
most objects are likely to be nonnull in practice.

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


Re: [swift-dev] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-13 Thread Greg Parker via swift-dev

> On Oct 13, 2016, at 10:46 AM, John McCall via swift-dev  
> wrote:
> 
>> On Oct 13, 2016, at 9:04 AM, Joe Groff via swift-dev > > wrote:
>> 
>>> On Mar 1, 2016, at 1:33 PM, Joe Groff via swift-dev >> > wrote:
>>> 
>>> In swift_retain/release, we have an early-exit check to pass through a nil 
>>> pointer. Since we're already burning branch, I'm thinking we could pass 
>>> through not only zero but negative pointer values too on 64-bit systems, 
>>> since negative pointers are never valid userspace pointers on our 64-bit 
>>> targets. This would give us room for tagged-pointer-like optimizations, for 
>>> instance to avoid allocations for tiny closure contexts.
>> 
>> I'd like to resurrect this thread as we look to locking down the ABI. There 
>> were portability concerns about doing this unilaterally for all 64-bit 
>> targets, but AFAICT it should be safe for x86-64 and Apple AArch64 targets. 
>> The x86-64 ABI limits the userland address space, per section 3.3.2:
>> 
>> Although the AMD64 architecture uses 64-bit pointers, implementations are 
>> only required to handle 48-bit addresses. Therefore, conforming processes 
>> may only use addresses from 0x  to 0x7fff .
>> 
>> Apple's ARM64 platforms always enable the top-byte-ignore architectural 
>> feature, restricting the available address space to the low 56 bits of the 
>> full 64-bit address space in practice. Therefore, "negative" values should 
>> never be valid user-space references to Swift-refcountable objects. Taking 
>> advantage of this fact would enable us to optimize small closure contexts, 
>> Error objects, and, if we move to a reference-counted COW model for 
>> existentials, small `Any` values, which need to be refcountable for ABI 
>> reasons but don't semantically promise a unique identity like class 
>> instances do.
> 
> This makes sense to me.  if (x <= 0) return; should be just as cheap as is (x 
> == 0) return;

Conversely, I wanted to try to remove such nil checks. Currently they look 
haphazard: some functions have them and some do not.

Allowing ABI space for tagged pointer objects is a much bigger problem than the 
check in swift_retain/release. For example, all vtable and witness table 
dispatch sites to AnyObject or any other type that might someday have a tagged 
pointer subclass would need to compile in a fallback path now. You can't 
dereference a tagged pointer to get its class pointer. 


-- 
Greg Parker gpar...@apple.com  Runtime 
Wrangler


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


Re: [swift-dev] Having 64-bit swift_retain/release ignore all negative pointer values

2016-10-13 Thread Joe Groff via swift-dev

> On Mar 1, 2016, at 1:33 PM, Joe Groff via swift-dev  
> wrote:
> 
> In swift_retain/release, we have an early-exit check to pass through a nil 
> pointer. Since we're already burning branch, I'm thinking we could pass 
> through not only zero but negative pointer values too on 64-bit systems, 
> since negative pointers are never valid userspace pointers on our 64-bit 
> targets. This would give us room for tagged-pointer-like optimizations, for 
> instance to avoid allocations for tiny closure contexts.

I'd like to resurrect this thread as we look to locking down the ABI. There 
were portability concerns about doing this unilaterally for all 64-bit targets, 
but AFAICT it should be safe for x86-64 and Apple AArch64 targets. The x86-64 
ABI limits the userland address space, per section 3.3.2:

Although the AMD64 architecture uses 64-bit pointers, implementations are only 
required to handle 48-bit addresses. Therefore, conforming processes may only 
use addresses from 0x  to 0x7fff .

Apple's ARM64 platforms always enable the top-byte-ignore architectural 
feature, restricting the available address space to the low 56 bits of the full 
64-bit address space in practice. Therefore, "negative" values should never be 
valid user-space references to Swift-refcountable objects. Taking advantage of 
this fact would enable us to optimize small closure contexts, Error objects, 
and, if we move to a reference-counted COW model for existentials, small `Any` 
values, which need to be refcountable for ABI reasons but don't semantically 
promise a unique identity like class instances do.

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