digitalmars.D - Class Instance allocations
- bearophile (70/70) Jan 11 2010 This page says "The pointer returned from new() must be to memory aligne...
- Justin Johansson (10/97) Jan 13 2010 I understand your quandary.
- Robert Jacques (3/12) Jan 13 2010 If I recall correctly, doubles require 8-byte alignment. So you object
- Justin Johansson (4/22) Jan 13 2010 Instances of my Foo class require 17 bytes so therefore all objects
- Simen kjaeraas (9/14) Jan 13 2010 If a member of your class requires n-byte alignment, your class will
- bearophile (6/10) Jan 13 2010 And no one has given me such answers yet.
- bearophile (2/3) Jan 13 2010 I hope to be wrong :-)
- =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= (3/6) Jan 13 2010 I think the GC has a 16 byte minimum allocation block, I believe I read
- Steven Schveighoffer (25/36) Jan 14 2010 It depends on the architecture/register. On most chips, if you load a
- bearophile (5/11) Jan 14 2010 I think it may also be a matter of tag bits added to pointers by the mar...
- Sean Kelly (2/9) Jan 14 2010 It does. So every block returned from the GC will be 16 byte aligned.
This page says "The pointer returned from new() must be to memory aligned to the default alignment. This is 8 on win32 systems.": http://www.digitalmars.com/d/2.0/memory.html Is that true? Is this required by the tag bits added by the GC scans? Does std.c.stdlib.malloc always return aligned to 8 on Windows? Below in the same page, in the Mark/Release section: class Foo { ... new(size_t sz) { void *p; p = &buffer[bufindex]; bufindex += sz; if (bufindex > buffer.length) throw new OutOfMemory; return p; } ... If sz is not a multiple of 8 then new() can return a pointer not aligned to 8: import std.outofmemory: OutOfMemoryException; import std.gc: addRange, removeRange; import std.c.stdlib: malloc, free; import std.c.stdio: printf; class Foo { static void[] buffer; static int bufIndex; static const int bufSize = 100; int x; //********** static this() { void* p = malloc(bufSize); if (!p) throw new OutOfMemoryException; addRange(p, p + bufSize); buffer = p[0 .. bufSize]; } static ~this() { if (buffer.length) { removeRange(buffer.ptr); free(buffer.ptr); buffer = null; } } new(size_t sz) { void* p = &buffer[bufIndex]; bufIndex += sz; if (bufIndex > buffer.length) throw new OutOfMemoryException; printf("%d %d\n", cast(size_t)p, cast(size_t)p % 8); // ****** return p; } delete(void* p) { assert(0); } static int mark() { return bufIndex; } static void release(int i) { bufIndex = i; } } void main() { int m = Foo.mark(); Foo f1 = new Foo; // allocate Foo f2 = new Foo; // allocate Foo.release(m); // deallocate f1 and f2 } Output, f2 reference is now always aligned to 4 bytes: 1382368 0 1382380 4 So, does the new() in this class (that has that extra "x" field) need to be fixed to be sure the pointers it returns are aligned to 8? The Foo class in the Mark/Release section has some other little bugs, that I think I have fixed here. D docs need something like the Andrei's book machinery, where D code snippets are actually run (Python docs too run their snippets). Bye, bearophile
Jan 11 2010
I understand your quandary. For me "Win32" == "32 bits" == "4 bytes" == "sizeof(ubiquitous machine register)". So why on earth, since Visual Studio 2001 (and before?), was the default alignment set to 8 bytes for the M$ C/C++ compiler code generation option? This I just do not understand (so, of course, enlightenment is welcome). Beers for the New Years, Justin Johansson bearophile wrote:This page says "The pointer returned from new() must be to memory aligned to the default alignment. This is 8 on win32 systems.": http://www.digitalmars.com/d/2.0/memory.html Is that true? Is this required by the tag bits added by the GC scans? Does std.c.stdlib.malloc always return aligned to 8 on Windows? Below in the same page, in the Mark/Release section: class Foo { ... new(size_t sz) { void *p; p = &buffer[bufindex]; bufindex += sz; if (bufindex > buffer.length) throw new OutOfMemory; return p; } ... If sz is not a multiple of 8 then new() can return a pointer not aligned to 8: import std.outofmemory: OutOfMemoryException; import std.gc: addRange, removeRange; import std.c.stdlib: malloc, free; import std.c.stdio: printf; class Foo { static void[] buffer; static int bufIndex; static const int bufSize = 100; int x; //********** static this() { void* p = malloc(bufSize); if (!p) throw new OutOfMemoryException; addRange(p, p + bufSize); buffer = p[0 .. bufSize]; } static ~this() { if (buffer.length) { removeRange(buffer.ptr); free(buffer.ptr); buffer = null; } } new(size_t sz) { void* p = &buffer[bufIndex]; bufIndex += sz; if (bufIndex > buffer.length) throw new OutOfMemoryException; printf("%d %d\n", cast(size_t)p, cast(size_t)p % 8); // ****** return p; } delete(void* p) { assert(0); } static int mark() { return bufIndex; } static void release(int i) { bufIndex = i; } } void main() { int m = Foo.mark(); Foo f1 = new Foo; // allocate Foo f2 = new Foo; // allocate Foo.release(m); // deallocate f1 and f2 } Output, f2 reference is now always aligned to 4 bytes: 1382368 0 1382380 4 So, does the new() in this class (that has that extra "x" field) need to be fixed to be sure the pointers it returns are aligned to 8? The Foo class in the Mark/Release section has some other little bugs, that I think I have fixed here. D docs need something like the Andrei's book machinery, where D code snippets are actually run (Python docs too run their snippets). Bye, bearophile
Jan 13 2010
On Wed, 13 Jan 2010 10:29:35 -0500, Justin Johansson <no spam.com> wrote:I understand your quandary. For me "Win32" == "32 bits" == "4 bytes" == "sizeof(ubiquitous machine register)". So why on earth, since Visual Studio 2001 (and before?), was the default alignment set to 8 bytes for the M$ C/C++ compiler code generation option? This I just do not understand (so, of course, enlightenment is welcome). Beers for the New Years, Justin JohanssonIf I recall correctly, doubles require 8-byte alignment. So you object therefore must require 8-byte alignment.
Jan 13 2010
Robert Jacques wrote:On Wed, 13 Jan 2010 10:29:35 -0500, Justin Johansson <no spam.com> wrote:Instances of my Foo class require 17 bytes so therefore all objects require 17 byte alignment. But for my Bar class it's 42. ???I understand your quandary. For me "Win32" == "32 bits" == "4 bytes" == "sizeof(ubiquitous machine register)". So why on earth, since Visual Studio 2001 (and before?), was the default alignment set to 8 bytes for the M$ C/C++ compiler code generation option? This I just do not understand (so, of course, enlightenment is welcome). Beers for the New Years, Justin JohanssonIf I recall correctly, doubles require 8-byte alignment. So you object therefore must require 8-byte alignment.
Jan 13 2010
Justin Johansson <no spam.com> wrote:If a member of your class requires n-byte alignment, your class will require (k*n)-byte alignment (where k is a positive integer), to ensure the member has its required alignment. Example: doubles require 8-byte alignment. You create class foo { double bar; }. If your foo is offset by 2 bytes from an 8-byte border, so is bar, and thus its alignment is broken. -- SimenIf I recall correctly, doubles require 8-byte alignment. So you object therefore must require 8-byte alignment.Instances of my Foo class require 17 bytes so therefore all objects require 17 byte alignment. But for my Bar class it's 42. ???
Jan 13 2010
Justin Johansson:So why on earth, since Visual Studio 2001 (and before?), was the default alignment set to 8 bytes for the M$ C/C++ compiler code generation option?Maybe because for compatibility reasons they can't require a 16 bytes alignment (as OS X does, I think) as SSE registers appreciate.And no one has given me such answers yet. And currently the D GC seems to always return aligned to 16 bytes (even chunks of memory smaller than 16 bytes). Bye, bearophileIs that true? Is this required by the tag bits added by the GC scans? Does std.c.stdlib.malloc always return aligned to 8 on Windows?<<
Jan 13 2010
bearophile:And currently the D GC seems to always return aligned to 16 bytes (even chunks of memory smaller than 16 bytes).<I hope to be wrong :-)
Jan 13 2010
On 01/13/2010 06:18 PM, bearophile wrote:bearophile:I think the GC has a 16 byte minimum allocation block, I believe I read it somewhere around here.And currently the D GC seems to always return aligned to 16 bytes (even chunks of memory smaller than 16 bytes).<I hope to be wrong :-)
Jan 13 2010
On Wed, 13 Jan 2010 12:16:30 -0500, bearophile <bearophileHUGS lycos.com> wrote:Justin Johansson:It depends on the architecture/register. On most chips, if you load a register from a segment of memory, that memory has to be n-byte aligned where n is the number of bytes for the register. But there are exceptions. I'm not sure if SSE register requires alignment. Typically on systems that do not support loading from a byte-aligned memory segment will throw a bus error if you try to do it.So why on earth, since Visual Studio 2001 (and before?), was the default alignment set to 8 bytes for the M$ C/C++ compiler code generation option?Maybe because for compatibility reasons they can't require a 16 bytes alignment (as OS X does, I think) as SSE registers appreciate.I would guess that pointers on a 32-bit architecture need to be 4-byte aligned, otherwise, a struct like this: struct S { int *x; int *y; } would have to be minimum of 16 bytes! I think the reason the allocator must return 8-byte aligned memory is because the allocator doesn't know what you're going to put in there, so it must handle the worst case scenario (doubles). BTW, 16 bytes is the minimum size the GC returns, and I think it's a somewhat arbitrary decision. The minimum you could possibly return is 8 bytes, and it becomes a judgement call that depends on other factors if you want to increase the minimum size (less overhead per block vs. more wasted space). -SteveAnd no one has given me such answers yet. And currently the D GC seems to always return aligned to 16 bytes (even chunks of memory smaller than 16 bytes).Is that true? Is this required by the tag bits added by the GC scans? Does std.c.stdlib.malloc always return aligned to 8 on Windows?<<
Jan 14 2010
Steven Schveighoffer:I'm not sure if SSE register requires alignment. Typically on systems that do not support loading from a byte-aligned memory segment will throw a bus error if you try to do it.I think SSE registers require 8 byte alignment, but some of their operations are faster with data aligned on 16 bytes. In future this 16 byte alignment requirement will probably be slowly dropped (already partially dropped in core i7). At that point the 16 byte alignment of the D GC can become overkill.I think the reason the allocator must return 8-byte aligned memory is because the allocator doesn't know what you're going to put in there, so it must handle the worst case scenario (doubles).I think it may also be a matter of tag bits added to pointers by the mark phase of the GC. I think two bits may suffice, so I don't know why the alignment to 8. Anyway, the new() method in the class I've shown at the top of this thread is wrong then, because sometimes it returns aligned to 4. It needs some extra machinery to fix this. Bye, bearophile
Jan 14 2010
Pelle MÃ¥nsson Wrote:On 01/13/2010 06:18 PM, bearophile wrote:It does. So every block returned from the GC will be 16 byte aligned.bearophile:I think the GC has a 16 byte minimum allocation block, I believe I read it somewhere around here.And currently the D GC seems to always return aligned to 16 bytes (even chunks of memory smaller than 16 bytes).<I hope to be wrong :-)
Jan 14 2010