digitalmars.D - Question about garbage collection specification
- rsw0x (6/6) Jun 13 2015 http://dlang.org/garbage.html
- ketmar (9/17) Jun 13 2015 'cause D is not another fashionable scripting language where you have to...
- rsw0x (4/29) Jun 13 2015 There's not even a warning on them that they're violating the
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (2/5) Jun 13 2015 https://github.com/D-Programming-Language/phobos/pull/3411
- ketmar (5/7) Jun 13 2015 i believe that if one needs to do such things, he is knowledgeable enoug...
- deadalnix (6/15) Jun 13 2015 I haven't read something that ridiculous in a while. Even if
- ketmar (2/3) Jun 13 2015 you're welcome.=
- deadalnix (4/10) Jun 13 2015 That seems like an arbitrary limitation. This will create an
- Steven Schveighoffer (12/24) Jun 13 2015 void *x = new int;
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (13/25) Jun 14 2015 I see David Nadlinger already said so in the PR, but that's how I
- Paulo Pinto (8/35) Jun 14 2015 Wouldn't it make sense to do so?
- rsw0x (5/45) Jun 14 2015 But a pointer can already point to a one byte aligned part of an
- rsw0x (4/53) Jun 14 2015 Woops, replied to the wrong person. My bad.
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (3/14) Jun 14 2015 Definitely, but I don't see how it could reasonably be added to
- Steven Schveighoffer (7/24) Jun 15 2015 We can create new types of pointers, remove void * from the language,
- ketmar (3/8) Jun 15 2015 i'm dreaming of making unions that contains GC objects invalid. it simpl...
- Steven Schveighoffer (12/32) Jun 15 2015 Huh? Of course it can!
- Dmitry Olshansky (6/12) Jun 15 2015 AFAIK the restriction was that pointers _themselves_ have to be stored
- Steven Schveighoffer (7/19) Jun 15 2015 That doesn't make sense. Why would you want to do this?
- Dmitry Olshansky (12/31) Jun 15 2015 What exactly? Storing pointer at misaligned memory location - no good
- Steven Schveighoffer (19/52) Jun 15 2015 Right, and that's already assumed in (and would be ignored by) the
- deadalnix (10/33) Jun 15 2015 I think you miread it.
- rsw0x (5/19) Jun 15 2015 this doesn't make any sense, it's referring to an object p (of
- Alex Parrill (7/11) Jun 15 2015 `p` is assumed to be a pointer. `cast(int) p` gets the integer
- Steven Schveighoffer (16/29) Jun 15 2015 Where? In the GC document? I don't think that document is correct in
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (17/25) Jun 15 2015 It doesn't need to, the undefined behaviour comes from the
- Steven Schveighoffer (9/22) Jun 15 2015 That is clearly not the case in the documentation. 'p' maintains a
http://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?
Jun 13 2015
On Sat, 13 Jun 2015 11:32:18 +0000, rsw0x wrote:http://dlang.org/garbage.html =20 Do not take advantage of alignment of pointers to store bit flags in the low order bits: p =3D cast(void*)(cast(int)p | 1); // error: undefined behavior =20 if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?'cause D is not another fashionable scripting language where you have to=20 eat what you got. one can avoid using GC in his code, or intermix GC with=20 other allocators, or rewrite the whole GC or the whole runtime. writing=20 stupid boilerplate code for tagged pointers and nan boxing is simply=20 tedious, it belongs to library. in other words: you can use `DirEntries` and `remove` to kill all files=20 in your home directory, but it's not the only use for that functions, so=20 they should not be removed from Phobos as "useless" or "dangerous".=
Jun 13 2015
On Saturday, 13 June 2015 at 12:26:49 UTC, ketmar wrote:On Sat, 13 Jun 2015 11:32:18 +0000, rsw0x wrote:There's not even a warning on them that they're violating the garbage collector specification, don't you think that's a little important?http://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?'cause D is not another fashionable scripting language where you have to eat what you got. one can avoid using GC in his code, or intermix GC with other allocators, or rewrite the whole GC or the whole runtime. writing stupid boilerplate code for tagged pointers and nan boxing is simply tedious, it belongs to library. in other words: you can use `DirEntries` and `remove` to kill all files in your home directory, but it's not the only use for that functions, so they should not be removed from Phobos as "useless" or "dangerous".
Jun 13 2015
On Saturday, 13 June 2015 at 12:28:15 UTC, rsw0x wrote:There's not even a warning on them that they're violating the garbage collector specification, don't you think that's a little important?https://github.com/D-Programming-Language/phobos/pull/3411
Jun 13 2015
On Sat, 13 Jun 2015 12:28:13 +0000, rsw0x wrote:There's not even a warning on them that they're violating the garbage collector specification, don't you think that's a little important?i believe that if one needs to do such things, he is knowledgeable enough=20 to foresee the possible consequences. this is not what casual programmer=20 does, so one is expected to know some internals. yet warning may be helpful too, Marc submitted a PR for that. ;-)=
Jun 13 2015
On Saturday, 13 June 2015 at 12:26:49 UTC, ketmar wrote:'cause D is not another fashionable scripting language where you have to eat what you got. one can avoid using GC in his code, or intermix GC with other allocators, or rewrite the whole GC or the whole runtime. writing stupid boilerplate code for tagged pointers and nan boxing is simply tedious, it belongs to library.I haven't read something that ridiculous in a while. Even if you'd be right, OP has a point in the fact that this should not be present in the standard lib without some big red sign. Hopefully, This will work just fine with the GC. The GC spec is needlessly restrictive.
Jun 13 2015
On Sat, 13 Jun 2015 22:09:52 +0000, deadalnix wrote:I haven't read something that ridiculous in a while.you're welcome.=
Jun 13 2015
On Saturday, 13 June 2015 at 11:32:20 UTC, rsw0x wrote:http://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?That seems like an arbitrary limitation. This will create an interior pointer, which the GC needs to recognize anyway. The doc need to be updated.
Jun 13 2015
On 6/13/15 6:07 PM, deadalnix wrote:On Saturday, 13 June 2015 at 11:32:20 UTC, rsw0x wrote:void *x = new int; ptr += 1; Is this illegal? If not, then why is the above illegal? If so, thousands of lines of code are in violation -- any kind of serialization library for example. It's exactly the same thing. We can probably change taggedPointer to do this instead, if it's such a big deal. We can change it to a void pointer, and only cast it to T* when retrieving the real pointer. But it seems kind of silly to outlaw the obvious implementation. I think we should revert the warning and fix the docs. -Stevehttp://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?That seems like an arbitrary limitation. This will create an interior pointer, which the GC needs to recognize anyway. The doc need to be updated.
Jun 13 2015
On Saturday, 13 June 2015 at 22:07:26 UTC, deadalnix wrote:On Saturday, 13 June 2015 at 11:32:20 UTC, rsw0x wrote:I see David Nadlinger already said so in the PR, but that's how I understand it: AFAIU the purpose of this restriction is to allow the GC to take advantage of alignment: a pointer with the lowest bit set cannot point to a 4-byte aligned struct, for example. The GC doc [1] mentions alignment several times, among them: "Do not misalign pointers if those pointers may point into the GC heap" As for arbitrary pointer arithmetic being allowed, I guess that's because the language doesn't distinguish between GC and non-GC pointers. And note that it is un- safe anyway. [1] http://dlang.org/garbage.htmlhttp://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?That seems like an arbitrary limitation. This will create an interior pointer, which the GC needs to recognize anyway. The doc need to be updated.
Jun 14 2015
On Sunday, 14 June 2015 at 11:03:00 UTC, Marc Schütz wrote:On Saturday, 13 June 2015 at 22:07:26 UTC, deadalnix wrote:Wouldn't it make sense to do so? Active Oberon, Modula-3 and .NET make such difference in their pointer types. I would imagine it could help in terms of what is possible for GC improvements. -- PauloOn Saturday, 13 June 2015 at 11:32:20 UTC, rsw0x wrote:I see David Nadlinger already said so in the PR, but that's how I understand it: AFAIU the purpose of this restriction is to allow the GC to take advantage of alignment: a pointer with the lowest bit set cannot point to a 4-byte aligned struct, for example. The GC doc [1] mentions alignment several times, among them: "Do not misalign pointers if those pointers may point into the GC heap" As for arbitrary pointer arithmetic being allowed, I guess that's because the language doesn't distinguish between GC and non-GC pointers. And note that it is un- safe anyway. [1] http://dlang.org/garbage.htmlhttp://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?That seems like an arbitrary limitation. This will create an interior pointer, which the GC needs to recognize anyway. The doc need to be updated.
Jun 14 2015
On Sunday, 14 June 2015 at 11:36:59 UTC, Paulo Pinto wrote:On Sunday, 14 June 2015 at 11:03:00 UTC, Marc Schütz wrote:But a pointer can already point to a one byte aligned part of an object and keep it alive because internal pointers must be supported. The only alignment enforced is that pointers must be aligned. This is an arbitrary restriction.On Saturday, 13 June 2015 at 22:07:26 UTC, deadalnix wrote:Wouldn't it make sense to do so? Active Oberon, Modula-3 and .NET make such difference in their pointer types. I would imagine it could help in terms of what is possible for GC improvements. -- PauloOn Saturday, 13 June 2015 at 11:32:20 UTC, rsw0x wrote:I see David Nadlinger already said so in the PR, but that's how I understand it: AFAIU the purpose of this restriction is to allow the GC to take advantage of alignment: a pointer with the lowest bit set cannot point to a 4-byte aligned struct, for example. The GC doc [1] mentions alignment several times, among them: "Do not misalign pointers if those pointers may point into the GC heap" As for arbitrary pointer arithmetic being allowed, I guess that's because the language doesn't distinguish between GC and non-GC pointers. And note that it is un- safe anyway. [1] http://dlang.org/garbage.htmlhttp://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?That seems like an arbitrary limitation. This will create an interior pointer, which the GC needs to recognize anyway. The doc need to be updated.
Jun 14 2015
On Sunday, 14 June 2015 at 11:57:35 UTC, rsw0x wrote:On Sunday, 14 June 2015 at 11:36:59 UTC, Paulo Pinto wrote:Woops, replied to the wrong person. My bad. And yes, you're right that the GC could improve if we went towards "d pointers" like Go did.On Sunday, 14 June 2015 at 11:03:00 UTC, Marc Schütz wrote:But a pointer can already point to a one byte aligned part of an object and keep it alive because internal pointers must be supported. The only alignment enforced is that pointers must be aligned. This is an arbitrary restriction.On Saturday, 13 June 2015 at 22:07:26 UTC, deadalnix wrote:Wouldn't it make sense to do so? Active Oberon, Modula-3 and .NET make such difference in their pointer types. I would imagine it could help in terms of what is possible for GC improvements. -- PauloOn Saturday, 13 June 2015 at 11:32:20 UTC, rsw0x wrote:I see David Nadlinger already said so in the PR, but that's how I understand it: AFAIU the purpose of this restriction is to allow the GC to take advantage of alignment: a pointer with the lowest bit set cannot point to a 4-byte aligned struct, for example. The GC doc [1] mentions alignment several times, among them: "Do not misalign pointers if those pointers may point into the GC heap" As for arbitrary pointer arithmetic being allowed, I guess that's because the language doesn't distinguish between GC and non-GC pointers. And note that it is un- safe anyway. [1] http://dlang.org/garbage.htmlhttp://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?That seems like an arbitrary limitation. This will create an interior pointer, which the GC needs to recognize anyway. The doc need to be updated.
Jun 14 2015
On Sunday, 14 June 2015 at 11:36:59 UTC, Paulo Pinto wrote:On Sunday, 14 June 2015 at 11:03:00 UTC, Marc Schütz wrote:Definitely, but I don't see how it could reasonably be added to the language now.As for arbitrary pointer arithmetic being allowed, I guess that's because the language doesn't distinguish between GC and non-GC pointers. And note that it is un- safe anyway. [1] http://dlang.org/garbage.htmlWouldn't it make sense to do so? Active Oberon, Modula-3 and .NET make such difference in their pointer types. I would imagine it could help in terms of what is possible for GC improvements.
Jun 14 2015
On 6/14/15 8:44 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>" wrote:On Sunday, 14 June 2015 at 11:36:59 UTC, Paulo Pinto wrote:We can create new types of pointers, remove void * from the language, and get rid of unions, and yes, *ONLY THEN* we can have a GC that takes advantage of this. These are painful, massively breaking changes. It's not going to happen. -SteveOn Sunday, 14 June 2015 at 11:03:00 UTC, Marc Schütz wrote:Definitely, but I don't see how it could reasonably be added to the language now.As for arbitrary pointer arithmetic being allowed, I guess that's because the language doesn't distinguish between GC and non-GC pointers. And note that it is un- safe anyway. [1] http://dlang.org/garbage.htmlWouldn't it make sense to do so? Active Oberon, Modula-3 and .NET make such difference in their pointer types. I would imagine it could help in terms of what is possible for GC improvements.
Jun 15 2015
On Mon, 15 Jun 2015 08:01:58 -0400, Steven Schveighoffer wrote:We can create new types of pointers, remove void * from the language, and get rid of unions, and yes, *ONLY THEN* we can have a GC that takes advantage of this. =20 These are painful, massively breaking changes. It's not going to happen.i'm dreaming of making unions that contains GC objects invalid. it simply=20 begs for troubles!=
Jun 15 2015
On 6/14/15 7:02 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>" wrote:On Saturday, 13 June 2015 at 22:07:26 UTC, deadalnix wrote:Huh? Of course it can! struct S { ubyte[4] arr; int x; } auto s = new S; auto p = &s.arr[1]; // points at an S in memory. I don't see how GC can take any advantage of this. -SteveOn Saturday, 13 June 2015 at 11:32:20 UTC, rsw0x wrote:I see David Nadlinger already said so in the PR, but that's how I understand it: AFAIU the purpose of this restriction is to allow the GC to take advantage of alignment: a pointer with the lowest bit set cannot point to a 4-byte aligned struct, for example.http://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?That seems like an arbitrary limitation. This will create an interior pointer, which the GC needs to recognize anyway. The doc need to be updated.
Jun 15 2015
On 13-Jun-2015 14:32, rsw0x wrote:http://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?AFAIK the restriction was that pointers _themselves_ have to be stored at word-aligned addresses. This allows GC to scan memory cheaper w/o considering if some misaligned address may contain a pointer. -- Dmitry Olshansky
Jun 15 2015
On 6/15/15 8:08 AM, Dmitry Olshansky wrote:On 13-Jun-2015 14:32, rsw0x wrote:That doesn't make sense. Why would you want to do this? The only rational thing I can think of is that you wouldn't want to store the result in an *actual* int pointer (lest it be used thinking it was valid without masking out the lower bits). But the example is storing it in a void *... -Stevehttp://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?AFAIK the restriction was that pointers _themselves_ have to be stored at word-aligned addresses. This allows GC to scan memory cheaper w/o considering if some misaligned address may contain a pointer.
Jun 15 2015
On 15-Jun-2015 15:49, Steven Schveighoffer wrote:On 6/15/15 8:08 AM, Dmitry Olshansky wrote:What exactly? Storing pointer at misaligned memory location - no good reason whatsoever. As in how it may happen - explicitly tightly packed structs with align(1) might end up doing this. From http://dlang.org/phobos/core_memory.html which seems to be more recent: Implementations are free to assume that GC pointers are only stored on word boundaries. Unaligned pointers may be ignored entirely.On 13-Jun-2015 14:32, rsw0x wrote:That doesn't make sense. Why would you want to do this?http://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?AFAIK the restriction was that pointers _themselves_ have to be stored at word-aligned addresses. This allows GC to scan memory cheaper w/o considering if some misaligned address may contain a pointer.The only rational thing I can think of is that you wouldn't want to store the result in an *actual* int pointer (lest it be used thinking it was valid without masking out the lower bits). But the example is storing it in a void *...The example doesn't show what memory location that p refers to thus it's not possible to say if it's valid. -- Dmitry Olshansky
Jun 15 2015
On 6/15/15 11:18 AM, Dmitry Olshansky wrote:On 15-Jun-2015 15:49, Steven Schveighoffer wrote:Right, and that's already assumed in (and would be ignored by) the current GC. What's NOT assumed (and I have no idea how we could make this assumption) is that interior pointers that point at parts of a larger struct/type/etc aren't valid GC pointers, and so the GC can ignore those too. For example: void *p = &someGCInt; p++; // equivalent to p = cast(void *)(cast(size_t)p | 1); The documentation above implies that if p is the only pointer to someGCInt, the GC may collect it. I think this is not possible for us to claim, even if we wanted to, given D's type system.On 6/15/15 8:08 AM, Dmitry Olshansky wrote:What exactly? Storing pointer at misaligned memory location - no good reason whatsoever. As in how it may happen - explicitly tightly packed structs with align(1) might end up doing this. From http://dlang.org/phobos/core_memory.html which seems to be more recent: Implementations are free to assume that GC pointers are only stored on word boundaries. Unaligned pointers may be ignored entirely.On 13-Jun-2015 14:32, rsw0x wrote:That doesn't make sense. Why would you want to do this?http://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?AFAIK the restriction was that pointers _themselves_ have to be stored at word-aligned addresses. This allows GC to scan memory cheaper w/o considering if some misaligned address may contain a pointer.The whole premise (as stated in the doc right before the example) is that you know the low order bits are 0 :) this is the complete basis of std.bitmanip.taggedPtr. It's quite genius I think, and the fact that it works with GC (and IMO, any possible GC you could create for D) without issue is awesome. We should not be attaching a scarlet comment to the docs to warn people away from it. -SteveThe only rational thing I can think of is that you wouldn't want to store the result in an *actual* int pointer (lest it be used thinking it was valid without masking out the lower bits). But the example is storing it in a void *...The example doesn't show what memory location that p refers to thus it's not possible to say if it's valid.
Jun 15 2015
On Monday, 15 June 2015 at 12:49:25 UTC, Steven Schveighoffer wrote:On 6/15/15 8:08 AM, Dmitry Olshansky wrote:I think you miread it. The memory the pointer points to can be misaligned. The memory the pointer is in must be aligned. Note that the second is mandatory is various hardware architecture to begin with, so it is not like it is a big constraint. It allow the GC to scan faster. It is all good. The first one do not make any sense as GC need to support interior pointers anyway.On 13-Jun-2015 14:32, rsw0x wrote:That doesn't make sense. Why would you want to do this? The only rational thing I can think of is that you wouldn't want to store the result in an *actual* int pointer (lest it be used thinking it was valid without masking out the lower bits). But the example is storing it in a void *... -Stevehttp://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?AFAIK the restriction was that pointers _themselves_ have to be stored at word-aligned addresses. This allows GC to scan memory cheaper w/o considering if some misaligned address may contain a pointer.
Jun 15 2015
On Monday, 15 June 2015 at 12:08:31 UTC, Dmitry Olshansky wrote:On 13-Jun-2015 14:32, rsw0x wrote:this doesn't make any sense, it's referring to an object p (of void*), not the location of p. It's setting the lsb of p to 1 and claiming it's undefined behavior, when it's clearly not. Unless I misunderstand it.http://dlang.org/garbage.html Do not take advantage of alignment of pointers to store bit flags in the low order bits: p = cast(void*)(cast(int)p | 1); // error: undefined behavior if this restriction is actually imposed - why does std.bitmanip.tagged{ClassRef,Pointer} even exist?AFAIK the restriction was that pointers _themselves_ have to be stored at word-aligned addresses. This allows GC to scan memory cheaper w/o considering if some misaligned address may contain a pointer.
Jun 15 2015
On Monday, 15 June 2015 at 15:33:41 UTC, rsw0x wrote:this doesn't make any sense, it's referring to an object p (of void*), not the location of p. It's setting the lsb of p to 1 and claiming it's undefined behavior, when it's clearly not. Unless I misunderstand it.`p` is assumed to be a pointer. `cast(int) p` gets the integer representation of the pointer (though it should be `uintptr_t` but whatever). It then does an integer bitwise or, then converts the result back to a pointer. It's undefined behavior in D because the spec just said so (regardless of its defined behavior in C).
Jun 15 2015
On 6/15/15 11:49 AM, Alex Parrill wrote:On Monday, 15 June 2015 at 15:33:41 UTC, rsw0x wrote:Where? In the GC document? I don't think that document is correct in this regard. Undefined behavior is something different than implementation defined behavior, which is what this is. The spec says (http://dlang.org/type.html): "Casting pointers to non-pointers and vice versa is allowed in D, however, do not do this for any pointers that point to data allocated by the garbage collector." How can the compiler POSSIBLY know whether a pointer points at GC data in order to make it undefined behavior? I don't see any justification for any of these restrictions. The "to allow maximum flexibility" justification needs more explanation, what possible feature could you implement given this restriction? It even allows using unions to do exactly the same thing. There is just no way this cannot be allowed. -Stevethis doesn't make any sense, it's referring to an object p (of void*), not the location of p. It's setting the lsb of p to 1 and claiming it's undefined behavior, when it's clearly not. Unless I misunderstand it.`p` is assumed to be a pointer. `cast(int) p` gets the integer representation of the pointer (though it should be `uintptr_t` but whatever). It then does an integer bitwise or, then converts the result back to a pointer. It's undefined behavior in D because the spec just said so (regardless of its defined behavior in C).
Jun 15 2015
On Monday, 15 June 2015 at 16:16:28 UTC, Steven Schveighoffer wrote:How can the compiler POSSIBLY know whether a pointer points at GC data in order to make it undefined behavior?It doesn't need to, the undefined behaviour comes from the unfulfilled expectations of the GC. For example, a "sufficiently advanced GC" with enough knowledge of types, including of local vars, could by chance run just at the moment when the only instance of the address is stored in an int variable, and disregard that variable because it's not a pointer. It is of course unlikely that GCs will ever get as much knowledge about local variables, or even unnamed temporaries...I don't see any justification for any of these restrictions. The "to allow maximum flexibility" justification needs more explanation, what possible feature could you implement given this restriction? It even allows using unions to do exactly the same thing. There is just no way this cannot be allowed.For unions, an advanced GC would know the type and would make sure to treat them conservatively. The restrictions are for the other cases where the types are references. The GC needs to rely on them being pointer if it wants to move them, for example. But I think you are right that the current restrictions are too strong. After some thoughts, I can't really see any realistic problem with tagged pointers.
Jun 15 2015
On 6/15/15 12:37 PM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>" wrote:On Monday, 15 June 2015 at 16:16:28 UTC, Steven Schveighoffer wrote:That is clearly not the case in the documentation. 'p' maintains a pointer to the data the entire time, before and after it's augmented. I'm perfectly OK changing the documentation to say "do not use integral types as the sole pointer to GC data." I can see how that may cause issues with the GC that has more advanced type information.How can the compiler POSSIBLY know whether a pointer points at GC data in order to make it undefined behavior?It doesn't need to, the undefined behaviour comes from the unfulfilled expectations of the GC. For example, a "sufficiently advanced GC" with enough knowledge of types, including of local vars, could by chance run just at the moment when the only instance of the address is stored in an int variable, and disregard that variable because it's not a pointer. It is of course unlikely that GCs will ever get as much knowledge about local variables, or even unnamed temporaries...But I think you are right that the current restrictions are too strong. After some thoughts, I can't really see any realistic problem with tagged pointers.Thanks for the consideration. -Steve
Jun 15 2015