On Saturday, 15 November 2014 at 03:41:56 UTC, Steven
Schveighoffer wrote:
On 11/14/14 8:56 PM, IgorStepanov wrote:
On Friday, 14 November 2014 at 23:49:00 UTC, ketmar via
Digitalmars-d
wrote:
On Fri, 14 Nov 2014 23:23:17 +0000
IgorStepanov via Digitalmars-d <[email protected]>
wrote:
What does the NO_INTERIOR flag?
it stops GC to acknowledge pointers inside allocated area as
anchors.
i.e. if there is no pointer to the head (first address) of
allocated
memory, it is assumed to be garbage.
this way we have much less "false pointers", and GC not doing
pointer->block conversions.
for buckets we certainly has "head pointer" and can't have
pointers to
bucket elements without "head pointer". so it's safe to tell
GC that it
shouldn't do unnecessary work.
In other words, if buckets array will contain only uint-s
there is no
reason to mark buckets with NO_INTERIOR?
In case ketmar's reply doesn't drive it home...
NO_INTERIOR means that the GC should NOT consider pointers to a
block as valid references if those pointers don't point to the
HEAD of the block. In other words, they point to the interior.
An example
int * x = new int;
*x = 5;
byte *b = cast(byte *)x;
b++; // b is now an interior pointer, yet x is not.
If we had marked x's block as NO_INTERIOR, we are fine as long
as x remains. If we set x to null, there is a danger that the
block is collected, and now b is dangling.
Now, this isn't a whole lot more efficient, you still have to
look up what b points at and see that it has the flag set. BUT,
where it DOES help is if you had some size_t somewhere on a
stack, that happens to be the same value as b, the GC may think
it's a pointer, but correctly not keep the block alive just for
that "false pointer". The larger the block, the more helpful
NO_INTERIOR is.
-Steve
Thanks for explanations. I undersood that now. However I have got
a strange bug with NO_INTERIOR.
I have the following function:
static Bucket[] newBuckets(in size_t len) @trusted pure nothrow
{
Bucket[] ret = new Bucket[len];
if (!__ctfe)
{
GC.setAttr(ret.ptr, GC.BlkAttr.NO_INTERIOR);
}
return ret;
}
The Bucket declaration has a two uint fields and one of those has
a explicit initializer:
private enum uint EmptyBucket = uint.max;
static struct Bucket
{
uint depth;
uint index = EmptyBucket;
@property bool occupied() const
{
return index != EmptyBucket;
}
}
I call this function for creating new bucket array (in init()
function, at first value inserting and at rehashing).
I don't create a copy, slice, I don't get a array pointer. Before
array creating and rehashing I use buckets only for access by
index. However I have got a error, when `index` field initializes
with some strange value when newBuckets argument is very big.
(buckets.length is big value). When I comment a
GC.setAttr(ret.ptr, GC.BlkAttr.NO_INTERIOR); line, code start
works fine.
Do I any fundamental error in this code?
May be Bucket[] ret = new Bucket[len]; ret.ptr is not base
pointer?