> On Jun 15, 2017, at 10:52 AM, Arnold via swift-dev <swift-dev@swift.org> > wrote: > > > >> On Jun 14, 2017, at 2:56 PM, Dave Abrahams via swift-dev >> <swift-dev@swift.org> wrote: >> >> >>> on Wed Jun 14 2017, Erik Eckstein <swift-dev-AT-swift.org> 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. >> >> W00t! I'd like to do the same for String, i.e. encode the entire buffer >> in the data section. I was looking for Array example code to follow but >> couldn't find it. > > > We have support for constant string buffers as of PR 8701 and PR 8692. The > former PR shows the protocol that has to be implemented. > > (The implementation currently exposes the ref count ABI. This can/needs to be > fixed when we move to a stable abi by running an once initializer)
It would be reasonable to arrange for a specific bit pattern to be a guaranteed "do not reference-count this" pattern even under a stable ABI. We just have to be careful about picking it. If we didn't want to do that, the best solution would be an absolute symbol — although we'd have to use an entire word for the refcount, even on 64-bit. John. >>> 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. >> >> Why not 1 > > Mutation must force copying. > >>> 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 >> >> I just ask that you keep in mind that we'll eventually want the same >> capability for other types, and try to write the code to make that >> feasible. >> >> Thanks, >> >> -- >> -Dave >> >> _______________________________________________ >> 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 _______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev