www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Understanding GC memory ranges and roots

reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
I'm experimenting with an alternative GC implementation at

https://github.com/nordlow/phobos-next/blob/master/benchmarks/gc-benchmark/source/segregated_gc.d

I now wonder if the parameters passed by `GC.addRange` and 
`GC.addRoot` are the only memory entry blocks I need to implement 
to correctly scan the stack and static memory storage?

I doesn't seem like that because when I add prints to these 
functions the only call I get is

addRange(0x556d8d118ea0, 93200, nil)

Is this the stack or the static storage?
I'm guessing static storage because printing the address of the 
first variable in a function prints 0x7ffe094fa014 which is very 
different from 0x556d8d118ea0.

How do I catch both the stack and static storage?

And why am I not getting any calls to GC.addRoot()? When is 
GC.addRoot() supposed to be called and by who?
Jul 06 2020
next sibling parent Jacob Carlborg <doob me.com> writes:
On Monday, 6 July 2020 at 23:03:36 UTC, Per Nordlöw wrote:
 I'm experimenting with an alternative GC implementation at

 https://github.com/nordlow/phobos-next/blob/master/benchmarks/gc-benchmark/source/segregated_gc.d

 I now wonder if the parameters passed by `GC.addRange` and 
 `GC.addRoot` are the only memory entry blocks I need to 
 implement to correctly scan the stack and static memory storage?

 I doesn't seem like that because when I add prints to these 
 functions the only call I get is

 addRange(0x556d8d118ea0, 93200, nil)

 Is this the stack or the static storage?
 I'm guessing static storage because printing the address of the 
 first variable in a function prints 0x7ffe094fa014 which is 
 very different from 0x556d8d118ea0.

 How do I catch both the stack and static storage?

 And why am I not getting any calls to GC.addRoot()? When is 
 GC.addRoot() supposed to be called and by who?
The GC (at least the standard GC) works by scanning the roots. The roots are, IIRC, stack variables, global variables and TLS variables. Any memory that is reached through the roots is preserved, the rest of the memory (that has been allocated by the GC) is collected. `GC.addRoot` and `GC.addRange` are part of the user facing API. It's intended to be called by users. For example, if you allocate some GC memory and pass that to a C library. if you don't keep any references in the D code to that memory it will be collected, even though it might be used by the C library. In this case, `GC.addRoot` can be called to add additional roots to those mentioned above. I think you need to implemented acquiring the roots yourself. You can have a look at the current GC implementations. -- /Jacob Carlborg
Jul 07 2020
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/6/20 7:03 PM, Per Nordlöw wrote:
 I'm experimenting with an alternative GC implementation at
 
 https://github.com/nordlow/phobos-next/blob/master/benchmarks/gc-benchmark/so
rce/segregated_gc.d 
 
 
 I now wonder if the parameters passed by `GC.addRange` and `GC.addRoot` 
 are the only memory entry blocks I need to implement to correctly scan 
 the stack and static memory storage?
 
 I doesn't seem like that because when I add prints to these functions 
 the only call I get is
 
 addRange(0x556d8d118ea0, 93200, nil)
 
 Is this the stack or the static storage?
 I'm guessing static storage because printing the address of the first 
 variable in a function prints 0x7ffe094fa014 which is very different 
 from 0x556d8d118ea0.
 
addRoot and addRange are called when allocations happen outside the stack or static storage. This might be the global (non-TLS) storage? It could also be something else that the runtime uses (could be on the C heap).
 How do I catch both the stack and static storage?
The stack and Thread Local Storage (i.e. static storage) are scanned using a specialized interface. See here: https://github.com/dlang/druntime/blob/eb279cf69c2e56e38b865409226f22e1d2465e72/src/core/thread/threadbase.d#L1024-L1042
 And why am I not getting any calls to GC.addRoot()? When is GC.addRoot() 
 supposed to be called and by who?
 
If you are adding prints, you may as well throw an exception, catch it, and print the stack trace if you want to know who's calling what. -Steve
Jul 07 2020
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 07/07/2020 11:50 PM, Steven Schveighoffer wrote:
 If you are adding prints, you may as well throw an exception, catch it, 
 and print the stack trace if you want to know who's calling what.
You won't be able to new the Exception tho. It'll have to be malloc'd ext. In GC -> lock probably hit -> new -> wait on lock
Jul 07 2020
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/7/20 6:36 PM, rikki cattermole wrote:
 On 07/07/2020 11:50 PM, Steven Schveighoffer wrote:
 If you are adding prints, you may as well throw an exception, catch 
 it, and print the stack trace if you want to know who's calling what.
You won't be able to new the Exception tho. It'll have to be malloc'd ext.
there are ways to allocate them on the stack as well, or you can simply initialize a static exception. scope Exception ex = new Exception("nothing"); try { throw ex; } catch(Exception e) { // print stack trace }
 In GC -> lock probably hit -> new -> wait on lock
Not sure, possibly printing the stack trace may be a problem as well. But it does seem like it should be doable. -Steve
Jul 07 2020
prev sibling parent Atila Neves <atila.neves gmail.com> writes:
On Tuesday, 7 July 2020 at 22:36:35 UTC, rikki cattermole wrote:
 On 07/07/2020 11:50 PM, Steven Schveighoffer wrote:
 If you are adding prints, you may as well throw an exception, 
 catch it, and print the stack trace if you want to know who's 
 calling what.
You won't be able to new the Exception tho. It'll have to be malloc'd ext. In GC -> lock probably hit -> new -> wait on lock
-preview=dip1008
Jul 08 2020