Statically-emitted or statically-allocated objects with new refcounting


(Joe Groff) #1

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

-Joe


(Greg Parker) #2

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

···

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler


(Greg Parker) #3

Oh wait, you *don't* want to use what stack-allocated objects use. They get deinited without being deallocated, and I assume you want neither deinit nor dealloc. Let me work this out.

···

On Mar 14, 2017, at 1:34 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler


(Jordan Rose) #4

Wouldn’t it be okay to just emit it with an unbalanced retain?

Jordan

···

On Mar 14, 2017, at 13:52, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 1:34 PM, Greg Parker via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

Oh wait, you *don't* want to use what stack-allocated objects use. They get deinited without being deallocated, and I assume you want neither deinit nor dealloc. Let me work this out.


(John McCall) #5

It's better if there's some way to make an object completely ref-count inert. Often, the compiler only sees one side of a retain/release pair, like when you return a constant NSString — you know locally that you're retaining a constant string, but you're returning it to some context that has no idea what it's getting. If the object is just unbalanced-retained, you have to preserve the retain or else the caller might release it. (That's true even if the imbalance is quite large — no fair crashing the program but only after a function's been called 2^19 times! Imagine reproducing that...) Making the object completely inert means you can just unconditionally say "hey, I know R/R are no-ops on this value" and delete them as a peephole.

John.

···

On Mar 14, 2017, at 5:08 PM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 13:52, Greg Parker via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On Mar 14, 2017, at 1:34 PM, Greg Parker via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

Oh wait, you *don't* want to use what stack-allocated objects use. They get deinited without being deallocated, and I assume you want neither deinit nor dealloc. Let me work this out.

Wouldn’t it be okay to just emit it with an unbalanced retain?


(Greg Parker) #6

That's right. Unbalanced retain is the solution today. I expect a truly inert solution soon.

···

On Mar 14, 2017, at 2:16 PM, John McCall <rjmccall@apple.com> wrote:

On Mar 14, 2017, at 5:08 PM, Jordan Rose via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On Mar 14, 2017, at 13:52, Greg Parker via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On Mar 14, 2017, at 1:34 PM, Greg Parker via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

Oh wait, you *don't* want to use what stack-allocated objects use. They get deinited without being deallocated, and I assume you want neither deinit nor dealloc. Let me work this out.

Wouldn’t it be okay to just emit it with an unbalanced retain?

It's better if there's some way to make an object completely ref-count inert. Often, the compiler only sees one side of a retain/release pair, like when you return a constant NSString — you know locally that you're retaining a constant string, but you're returning it to some context that has no idea what it's getting. If the object is just unbalanced-retained, you have to preserve the retain or else the caller might release it. (That's true even if the imbalance is quite large — no fair crashing the program but only after a function's been called 2^19 times! Imagine reproducing that...) Making the object completely inert means you can just unconditionally say "hey, I know R/R are no-ops on this value" and delete them as a peephole.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler


(Joe Groff) #7

Cool. Do you think we'd be able to avoid atomic barriers on inert objects, or would that unfairly impact freeable objects?

-Joe

···

On Mar 14, 2017, at 3:53 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 2:16 PM, John McCall <rjmccall@apple.com> wrote:

On Mar 14, 2017, at 5:08 PM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 13:52, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 1:34 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

Oh wait, you *don't* want to use what stack-allocated objects use. They get deinited without being deallocated, and I assume you want neither deinit nor dealloc. Let me work this out.

Wouldn’t it be okay to just emit it with an unbalanced retain?

It's better if there's some way to make an object completely ref-count inert. Often, the compiler only sees one side of a retain/release pair, like when you return a constant NSString — you know locally that you're retaining a constant string, but you're returning it to some context that has no idea what it's getting. If the object is just unbalanced-retained, you have to preserve the retain or else the caller might release it. (That's true even if the imbalance is quite large — no fair crashing the program but only after a function's been called 2^19 times! Imagine reproducing that...) Making the object completely inert means you can just unconditionally say "hey, I know R/R are no-ops on this value" and delete them as a peephole.

That's right. Unbalanced retain is the solution today. I expect a truly inert solution soon.


(John McCall) #8

Greg is the right person to answer this for certain, but retain and release use a load + exchange pattern, and inertness will presumably be testable based purely on the initial load.

John.

···

On Mar 16, 2017, at 4:23 PM, Joe Groff <jgroff@apple.com> wrote:

On Mar 14, 2017, at 3:53 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 2:16 PM, John McCall <rjmccall@apple.com> wrote:

On Mar 14, 2017, at 5:08 PM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 13:52, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 1:34 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

Oh wait, you *don't* want to use what stack-allocated objects use. They get deinited without being deallocated, and I assume you want neither deinit nor dealloc. Let me work this out.

Wouldn’t it be okay to just emit it with an unbalanced retain?

It's better if there's some way to make an object completely ref-count inert. Often, the compiler only sees one side of a retain/release pair, like when you return a constant NSString — you know locally that you're retaining a constant string, but you're returning it to some context that has no idea what it's getting. If the object is just unbalanced-retained, you have to preserve the retain or else the caller might release it. (That's true even if the imbalance is quite large — no fair crashing the program but only after a function's been called 2^19 times! Imagine reproducing that...) Making the object completely inert means you can just unconditionally say "hey, I know R/R are no-ops on this value" and delete them as a peephole.

That's right. Unbalanced retain is the solution today. I expect a truly inert solution soon.

Cool. Do you think we'd be able to avoid atomic barriers on inert objects, or would that unfairly impact freeable objects?


(Greg Parker) #9

Oops, dropped my reply somewhere. Yes, that's correct. The only barriers are the store-release in swift_release and the matching acquire before deinit. Truly inert objects would perform neither of those. They would perform the load and then shortcut out at the "this object is unusual" bit test before the incremented store.

You can initialize your objects with a refcount field of `uintptr_t(1)` for now. That's the same value used for newly-allocated objects. Note that the `1` is not the strong retain count.

Is this going in the compiler's codegen somewhere? We should have a test and a big comment in RefCount.h for the dependency, assuming it can't be easily handled automatically at build time, because these values will certainly change in the future.

···

On Mar 16, 2017, at 7:35 PM, John McCall <rjmccall@apple.com> wrote:

On Mar 16, 2017, at 4:23 PM, Joe Groff <jgroff@apple.com> wrote:

On Mar 14, 2017, at 3:53 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 2:16 PM, John McCall <rjmccall@apple.com> wrote:

On Mar 14, 2017, at 5:08 PM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 13:52, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 1:34 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

Oh wait, you *don't* want to use what stack-allocated objects use. They get deinited without being deallocated, and I assume you want neither deinit nor dealloc. Let me work this out.

Wouldn’t it be okay to just emit it with an unbalanced retain?

It's better if there's some way to make an object completely ref-count inert. Often, the compiler only sees one side of a retain/release pair, like when you return a constant NSString — you know locally that you're retaining a constant string, but you're returning it to some context that has no idea what it's getting. If the object is just unbalanced-retained, you have to preserve the retain or else the caller might release it. (That's true even if the imbalance is quite large — no fair crashing the program but only after a function's been called 2^19 times! Imagine reproducing that...) Making the object completely inert means you can just unconditionally say "hey, I know R/R are no-ops on this value" and delete them as a peephole.

That's right. Unbalanced retain is the solution today. I expect a truly inert solution soon.

Cool. Do you think we'd be able to avoid atomic barriers on inert objects, or would that unfairly impact freeable objects?

Greg is the right person to answer this for certain, but retain and release use a load + exchange pattern, and inertness will presumably be testable based purely on the initial load.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler


(Joe Groff) #10

It might at some point, but I was thinking of using this in the runtime for now. We already have a few statically-emitted objects for the empty containers that could benefit from this, but they could presumably use API from RefCount.h to grab a constexpr bit pattern with which to initialize themselves.

-Joe

···

On Mar 16, 2017, at 9:02 PM, Greg Parker <gparker@apple.com> wrote:

On Mar 16, 2017, at 7:35 PM, John McCall <rjmccall@apple.com> wrote:

On Mar 16, 2017, at 4:23 PM, Joe Groff <jgroff@apple.com> wrote:

On Mar 14, 2017, at 3:53 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 2:16 PM, John McCall <rjmccall@apple.com> wrote:

On Mar 14, 2017, at 5:08 PM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 13:52, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 1:34 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

Oh wait, you *don't* want to use what stack-allocated objects use. They get deinited without being deallocated, and I assume you want neither deinit nor dealloc. Let me work this out.

Wouldn’t it be okay to just emit it with an unbalanced retain?

It's better if there's some way to make an object completely ref-count inert. Often, the compiler only sees one side of a retain/release pair, like when you return a constant NSString — you know locally that you're retaining a constant string, but you're returning it to some context that has no idea what it's getting. If the object is just unbalanced-retained, you have to preserve the retain or else the caller might release it. (That's true even if the imbalance is quite large — no fair crashing the program but only after a function's been called 2^19 times! Imagine reproducing that...) Making the object completely inert means you can just unconditionally say "hey, I know R/R are no-ops on this value" and delete them as a peephole.

That's right. Unbalanced retain is the solution today. I expect a truly inert solution soon.

Cool. Do you think we'd be able to avoid atomic barriers on inert objects, or would that unfairly impact freeable objects?

Greg is the right person to answer this for certain, but retain and release use a load + exchange pattern, and inertness will presumably be testable based purely on the initial load.

Oops, dropped my reply somewhere. Yes, that's correct. The only barriers are the store-release in swift_release and the matching acquire before deinit. Truly inert objects would perform neither of those. They would perform the load and then shortcut out at the "this object is unusual" bit test before the incremented store.

You can initialize your objects with a refcount field of `uintptr_t(1)` for now. That's the same value used for newly-allocated objects. Note that the `1` is not the strong retain count.

Is this going in the compiler's codegen somewhere? We should have a test and a big comment in RefCount.h for the dependency, assuming it can't be easily handled automatically at build time, because these values will certainly change in the future.


(Greg Parker) #11

Good: we already support that usage. Struct HeapObject has a constexpr initializer that sets the refcounts to that value. See stdlib/public/stubs/GlobalObjects.cpp for some similar uses.

(But wait, objects for empty containers are already in GlobalObjects.cpp. Are you adding more such objects?)

···

On Mar 17, 2017, at 8:19 AM, Joe Groff <jgroff@apple.com> wrote:

On Mar 16, 2017, at 9:02 PM, Greg Parker <gparker@apple.com> wrote:

On Mar 16, 2017, at 7:35 PM, John McCall <rjmccall@apple.com> wrote:

On Mar 16, 2017, at 4:23 PM, Joe Groff <jgroff@apple.com> wrote:

On Mar 14, 2017, at 3:53 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 2:16 PM, John McCall <rjmccall@apple.com> wrote:

On Mar 14, 2017, at 5:08 PM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 13:52, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 1:34 PM, Greg Parker via swift-dev <swift-dev@swift.org> wrote:

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

Oh wait, you *don't* want to use what stack-allocated objects use. They get deinited without being deallocated, and I assume you want neither deinit nor dealloc. Let me work this out.

Wouldn’t it be okay to just emit it with an unbalanced retain?

It's better if there's some way to make an object completely ref-count inert. Often, the compiler only sees one side of a retain/release pair, like when you return a constant NSString — you know locally that you're retaining a constant string, but you're returning it to some context that has no idea what it's getting. If the object is just unbalanced-retained, you have to preserve the retain or else the caller might release it. (That's true even if the imbalance is quite large — no fair crashing the program but only after a function's been called 2^19 times! Imagine reproducing that...) Making the object completely inert means you can just unconditionally say "hey, I know R/R are no-ops on this value" and delete them as a peephole.

That's right. Unbalanced retain is the solution today. I expect a truly inert solution soon.

Cool. Do you think we'd be able to avoid atomic barriers on inert objects, or would that unfairly impact freeable objects?

Greg is the right person to answer this for certain, but retain and release use a load + exchange pattern, and inertness will presumably be testable based purely on the initial load.

Oops, dropped my reply somewhere. Yes, that's correct. The only barriers are the store-release in swift_release and the matching acquire before deinit. Truly inert objects would perform neither of those. They would perform the load and then shortcut out at the "this object is unusual" bit test before the incremented store.

You can initialize your objects with a refcount field of `uintptr_t(1)` for now. That's the same value used for newly-allocated objects. Note that the `1` is not the strong retain count.

Is this going in the compiler's codegen somewhere? We should have a test and a big comment in RefCount.h for the dependency, assuming it can't be easily handled automatically at build time, because these values will certainly change in the future.

It might at some point, but I was thinking of using this in the runtime for now. We already have a few statically-emitted objects for the empty containers that could benefit from this, but they could presumably use API from RefCount.h to grab a constexpr bit pattern with which to initialize themselves.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler


(Joe Groff) #12

I was considering it as a possibility for statically emitting literal key path objects as part of Foundation's recent language proposal (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170313/033998.html). Even for this case, I don't think I'd have the compiler statically emit the bit pattern, but have accesses to the object go through a runtime call that lazily reifies it. (That way, if we change the object format, we can also still reallocate the older compiler-emitted format.)

-Joe

···

On Mar 17, 2017, at 4:04 PM, Greg Parker <gparker@apple.com> wrote:

On Mar 17, 2017, at 8:19 AM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

On Mar 16, 2017, at 9:02 PM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Mar 16, 2017, at 7:35 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Mar 16, 2017, at 4:23 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

On Mar 14, 2017, at 3:53 PM, Greg Parker via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On Mar 14, 2017, at 2:16 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Mar 14, 2017, at 5:08 PM, Jordan Rose via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On Mar 14, 2017, at 13:52, Greg Parker via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On Mar 14, 2017, at 1:34 PM, Greg Parker via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On Mar 14, 2017, at 12:43 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

Hey Greg, what are the correct refcounting bits now to set in a global statically-emitted heap object that shouldn't ever be released?

For now use the same thing that stack-allocated objects use. I forget what the bit pattern is exactly. (I assume you are not in strictly read-only memory and can tolerate writes to the refcount word. We don't yet have an implementation for immortal read-only objects.)

Oh wait, you *don't* want to use what stack-allocated objects use. They get deinited without being deallocated, and I assume you want neither deinit nor dealloc. Let me work this out.

Wouldn’t it be okay to just emit it with an unbalanced retain?

It's better if there's some way to make an object completely ref-count inert. Often, the compiler only sees one side of a retain/release pair, like when you return a constant NSString — you know locally that you're retaining a constant string, but you're returning it to some context that has no idea what it's getting. If the object is just unbalanced-retained, you have to preserve the retain or else the caller might release it. (That's true even if the imbalance is quite large — no fair crashing the program but only after a function's been called 2^19 times! Imagine reproducing that...) Making the object completely inert means you can just unconditionally say "hey, I know R/R are no-ops on this value" and delete them as a peephole.

That's right. Unbalanced retain is the solution today. I expect a truly inert solution soon.

Cool. Do you think we'd be able to avoid atomic barriers on inert objects, or would that unfairly impact freeable objects?

Greg is the right person to answer this for certain, but retain and release use a load + exchange pattern, and inertness will presumably be testable based purely on the initial load.

Oops, dropped my reply somewhere. Yes, that's correct. The only barriers are the store-release in swift_release and the matching acquire before deinit. Truly inert objects would perform neither of those. They would perform the load and then shortcut out at the "this object is unusual" bit test before the incremented store.

You can initialize your objects with a refcount field of `uintptr_t(1)` for now. That's the same value used for newly-allocated objects. Note that the `1` is not the strong retain count.

Is this going in the compiler's codegen somewhere? We should have a test and a big comment in RefCount.h for the dependency, assuming it can't be easily handled automatically at build time, because these values will certainly change in the future.

It might at some point, but I was thinking of using this in the runtime for now. We already have a few statically-emitted objects for the empty containers that could benefit from this, but they could presumably use API from RefCount.h to grab a constexpr bit pattern with which to initialize themselves.

Good: we already support that usage. Struct HeapObject has a constexpr initializer that sets the refcounts to that value. See stdlib/public/stubs/GlobalObjects.cpp for some similar uses.

(But wait, objects for empty containers are already in GlobalObjects.cpp. Are you adding more such objects?)


(Greg Parker) #13

The stable ABI will have affordances for statically-emitted objects. For now you can use the machinery in GlobalObjects.cpp. When the stable ABI progresses we'll find all uses of that code and update them.

One likely possibility is that we emit some bit pattern directly, but also emit enough metadata so that the runtime could find all such objects at launch time. (For example on Mach-O the objects could all be emitted into the same section.) That way we get high performance now but preserve the ability to rewrite the objects in the future, on the assumption that such ABI evolution will be rare. The Objective-C runtime uses this technique in several places.

···

On Mar 17, 2017, at 4:07 PM, Joe Groff <jgroff@apple.com> wrote:

On Mar 17, 2017, at 4:04 PM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Mar 17, 2017, at 8:19 AM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

It might at some point, but I was thinking of using this in the runtime for now. We already have a few statically-emitted objects for the empty containers that could benefit from this, but they could presumably use API from RefCount.h to grab a constexpr bit pattern with which to initialize themselves.

Good: we already support that usage. Struct HeapObject has a constexpr initializer that sets the refcounts to that value. See stdlib/public/stubs/GlobalObjects.cpp for some similar uses.

(But wait, objects for empty containers are already in GlobalObjects.cpp. Are you adding more such objects?)

I was considering it as a possibility for statically emitting literal key path objects as part of Foundation's recent language proposal (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170313/033998.html). Even for this case, I don't think I'd have the compiler statically emit the bit pattern, but have accesses to the object go through a runtime call that lazily reifies it. (That way, if we change the object format, we can also still reallocate the older compiler-emitted format.)

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler