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?

Reply via email to