> On Jun 14, 2017, at 11:24 AM, Erik Eckstein via swift-dev
> <[email protected]> wrote:
>
> Hi,
>
> I’m about implementing statically initialized arrays. It’s about allocating
> storage for arrays in the data section rather than on the heap.
>
> Info: the array storage is a heap object. So in the following I’m using the
> general term “object” but the optimization will (probably) only handle array
> buffers.
>
> This optimization can be done for array literals containing only other
> literals as elements.
> Example:
>
> func createArray() -> [Int] {
> return [1, 2, 3]
> }
>
> The compiler can allocate the whole array buffer as a statically initialized
> global llvm-variable with a reference count of 2 to make it immortal.
I was thinking about this a little bit. IMO, we probably actually want a bit in
the header. The reason why is that even though setting the ref count to be
unbalanced makes an object immortal, retain/release will still modify the
reference count meaning that the statically initialized constant can not be in
read only memory. On the other hand, if we had a bit in the header, we could
use read only memory.
Michael
> It avoids heap allocations for array literals in cases stack-promotion can’t
> kick in. It also saves code size.
>
> What’s needed for this optimization?
>
> 1) An optimization pass (GlobalOpt) which detects such array literal
> initialization patterns and “outlines” those into a statically initialized
> global variable
> 2) A representation of statically initialized global variables in SIL
> 3) IRGen to create statically initialized objects as global llvm-variables
>
> ad 2) Changes in SIL:
>
> Currently a static initialized sil_global is represented by having a
> reference to a globalinit function which has to match a very specific pattern
> (e.g. must contain a single store to the global).
> This is somehow quirky and would get even more complicated for statically
> initialized objects.
>
> I’d like to change that so that the sil_global itself contains the
> initialization value.
> This part is not yet related to statically initialized objects. It just
> improves the representation of statically initialized global in general.
>
> @@ -1210,7 +1210,9 @@ Global Variables
> ::
>
> decl ::= sil-global-variable
> + static-initializer ::= '{' sil-instruction-def* '}'
> sil-global-variable ::= 'sil_global' sil-linkage identifier ':' sil-type
> + (static-initializer)?
>
> SIL representation of a global variable.
>
> @@ -1221,6 +1223,19 @@ SIL instructions. Prior to performing any access on
> the global, the
> Once a global's storage has been initialized, ``global_addr`` is used to
> project the value.
>
> +A global can also have a static initializer if it's initial value can be
> +composed of literals. The static initializer is represented as a list of
> +literal and aggregate instructions where the last instruction is the
> top-level
> +value of the static initializer::
> +
> + sil_global hidden @_T04test3varSiv : $Int {
> + %0 = integer_literal $Builtin.Int64, 27
> + %1 = struct $Int (%0 : $Builtin.Int64)
> + }
> +
> +In case a global has a static initializer, no ``alloc_global`` is needed
> before
> +it can be accessed.
> +
>
> Now to represent a statically initialized object, we need a new instruction.
> Note that this “instruction" can only appear in the initializer of a
> sil_global.
>
> +object
> +``````
> +::
> +
> + sil-instruction ::= 'object' sil-type '(' (sil-operand (','
> sil-operand)*)? ')'
> +
> + object $T (%a : $A, %b : $B, ...)
> + // $T must be a non-generic or bound generic reference type
> + // The first operands must match the stored properties of T
> + // Optionally there may be more elements, which are tail-allocated to T
> +
> +Constructs a statically initialized object. This instruction can only appear
> +as final instruction in a global variable static initializer list.
>
> Finally we need an instruction to use such a statically initialized global
> object.
>
> +global_object
> +`````````````
> +::
> +
> + sil-instruction ::= 'global_object' sil-global-name ':' sil-type
> +
> + %1 = global_object @v : $T
> + // @v must be a global variable with a static initialized object
> + // $T must be a reference type
> +
> +Creates a reference to the address of a global variable which has a static
> +initializer which is an object, i.e. the last instruction of the global's
> +static initializer list is an ``object`` instruction.
>
>
> ad 3) IRGen support
>
> Generating statically initialized globals is already done today for structs
> and tuples.
> What’s needed is the handling of objects.
> In addition to creating the global itself, we also need a runtime call to
> initialize the object header. In other words: the object is statically
> initialized, except the header.
>
> HeapObject *swift::swift_initImmortalObject(HeapMetadata const *metadata,
> HeapObject *object)
>
> There are 2 reasons for that: first, the object header format is not part of
> the ABI. And second, in case of a bound generic type (e.g. array buffers) the
> metadata is not statically available.
>
> One way to call this runtime function is dynamically at the global_object
> instruction whenever the metadata pointer is still null (via swift_once).
> Another possibility would be to call it in a global constructor.
>
> If you have any feedback, please let me know
>
> Thanks,
> Erik
> _______________________________________________
> swift-dev mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-dev
_______________________________________________
swift-dev mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-dev