Obtaining aligned addresses and aligned spaces for objects

Ali Çehreli acehreli at yahoo.com
Wed Jun 29 10:29:07 PDT 2011


On Wed, 29 Jun 2011 10:47:39 -0400, Steven Schveighoffer wrote:

> On Wed, 29 Jun 2011 01:42:37 -0400, Ali Çehreli <acehreli at yahoo.com>
> wrote:
>> On a related note, why doesn't __traits(classInstanceSize, T) consider
>> the padding bytes? If I'm not mistaken struct sizes do include the
>> padding bytes. The following class has the very odd size of 17! Is that
>> by design?
> 
> Probably it's because classes are intended to occupy their own memory
> block, so the pad doesn't matter, you can't put two in the same block
> anyways.

You also say a block is 16 bytes below but the following program seems to 
be able to put objects at 24 byte intervals.

> 
> If you want to do it, I think it should be possible.

Actually I don't care. :) I am just trying to find out the right way of 
placing objects in memory. I am just trying to cover all aspects of it.

> But I don't think
> it would work great if you put two classes in the same block without
> significant compiler/GC changes.
> 
> That being said, given that all GC blocks are at least 16-byte aligned,
> the same should hold true for any class instance.

I am able to place class objects at 24 byte intervals with the following 
program, which indicates that some objects straddle block boundaries. Is 
that fine? Is the following method sufficient. Am I doing things 
unnecessarily complicated?

import std.stdio;
import core.memory;
import std.conv;

class C
{
    char c;

    this(char c)
    {
        this.c = c;
    }
}

T * alignedAddress(T)(T * candidate)
{
    return cast(T*)((cast(size_t)candidate + T.alignof - 1)
                    / T.alignof * T.alignof);
}

void * alignedAddress(T)(void * candidate)
{
    return alignedAddress(cast(T*)candidate);
}

size_t alignedSpace(T)()
{
    static if (is (T == class)) {
        size_t size = __traits(classInstanceSize, T);
    } else {
        size_t size = T.sizeof;
    }

    return cast(size_t)alignedAddress(cast(T*)size);
}

void main()
{
    size_t size = __traits(classInstanceSize, C);
    size_t alignedSize = alignedSpace!C();

    writeln("instance size: ", size);
    writeln("alignment    : ", C.alignof);
    writeln("aligned size : ", alignedSize);

    /* Inputs to use to make objects */
    string inputs = "hello world";

    /* Raw memory */
    void * chunk = GC.calloc(inputs.length * alignedSize);

    C[] variables;

    /* Make objects */
    foreach (i, c; inputs) {
        void * candidateAddress = chunk + (i * alignedSize);

        /* I don't think anymore that I need to call alignedAddress()
         * below. Still... */
        void * objectAddress = alignedAddress!C(candidateAddress);

        writefln("candidate: %s   addr: %s",
                 candidateAddress, objectAddress);

        variables ~= emplace!C(objectAddress[0..size], c);
        /*
         * It might make more sense to pass
         * objectAddress[0..alignedSize] above, but I can't. (Please
         * see http://d.puremagic.com/issues/show_bug.cgi?id=6204 )
         */
    }

    /* Use the objects */
    foreach (v; variables) {
        writeln(v.c, '.');
    }
}

Here is an output:

instance size: 17
alignment    : 8
aligned size : 24
candidate: 7F11467A2E00   addr: 7F11467A2E00
candidate: 7F11467A2E18   addr: 7F11467A2E18
candidate: 7F11467A2E30   addr: 7F11467A2E30
candidate: 7F11467A2E48   addr: 7F11467A2E48
candidate: 7F11467A2E60   addr: 7F11467A2E60
candidate: 7F11467A2E78   addr: 7F11467A2E78
candidate: 7F11467A2E90   addr: 7F11467A2E90
candidate: 7F11467A2EA8   addr: 7F11467A2EA8
candidate: 7F11467A2EC0   addr: 7F11467A2EC0
candidate: 7F11467A2ED8   addr: 7F11467A2ED8
candidate: 7F11467A2EF0   addr: 7F11467A2EF0
h.
e.
l.
l.
o.
 .
w.
o.
r.
l.
d.

> 
> -Steve

Ali


More information about the Digitalmars-d-learn mailing list