[M3devel] explanation of CheckLoadTracedRef?

Tony Hosking hosking at cs.purdue.edu
Mon Apr 20 06:55:13 CEST 2009


On 20 Apr 2009, at 13:47, Jay wrote:

>
>
> - What does CheckLoadTracedRef and co. do?

It makes sure that when loading a reference from the heap we make sure  
that reference is black (i.e., not gray).  The invariant is that  
mutator threads should never be exposed to pointers to old space while  
the incrememtal collector is executing.

> - Can the compiler be smarter?

It's tricky.  We'd like to eliminate two checks on the same field.    
So long as we can ensure that no GC flip occurs between the first  
check and the second then yes.  If not then we must keep both checks.

> Easily/effectively?
> I'm just reading code to understand the object model..
> and I see like this:
> b.F1(1); (* line 60 *)
> b.F2(2);
>
>
>
> .stabn 68,0,60,LM17-LFBB2 (",60," means line 60)
> LM17:
> movl _MM_Main+584, %esi
> testl %esi, %esi
> je L13
> testb $64, -2(%esi)
> je L13
> movl %esi, (%esp)
> call _RTHooks__CheckLoadTracedRef
> L13:
> movl (%esi), %eax
> movl (%eax), %ebx
> movl $1, 4(%esp)
> movl %esi, (%esp)
> call *%ebx
> .stabn 68,0,61,LM18-LFBB2 (",61," means line 61)
> LM18:
> movl _MM_Main+584, %ebx
> testl %ebx, %ebx
> je L14
> testb $64, -2(%ebx)
> je L14
> movl %ebx, (%esp)
> call _RTHooks__CheckLoadTracedRef
> L14:
> movl (%ebx), %eax
> movl 4(%eax), %esi
> movl $2, 4(%esp)
> movl %ebx, (%esp)
> call *%esi
>
>
> Does one really need to "check" pointers so often?
> You know, like twice in a row?
> Granted, there is a call in between.
> I understand, that one call could have done "anything".
>
>
> Ok, here is another case cm3 -O, cm3cg -O3, no intervening function  
> call, still two checks:
>
>
> T3 = OBJECT
> a: INTEGER;
> END;
>
>
> c := NEW(T3);
>
>
> RTIO.PutInt(c.a + c.a);
>
>
> .stabn 68,0,63,LM20-LFBB2
> LM20:
> movl _MM_Main+588, %esi
> testl %esi, %esi
> je L15
> testb $64, -2(%esi)
> je L15
> movl %esi, (%esp)
> call _RTHooks__CheckLoadTracedRef
> L15:
> movl _MM_Main+588, %ebx
> testl %ebx, %ebx
> je L16
> testb $64, -2(%ebx)
> je L16
> movl %ebx, (%esp)
> call _RTHooks__CheckLoadTracedRef
> L16:
> movl $0, 4(%esp)
> movl 4(%ebx), %eax
> addl 4(%esi), %eax
> movl %eax, (%esp)
> call _RTIO__PutInt
>
>
> I'm of two minds on optimizing though.
> Do it. Don't it.
>
> I don't like debugging optimize code.
> Nor do I want to waste time having the compiler make the code less  
> debuggable.
> But when I look at the code and how bad the code quality is, and  
> that it could be substantially
> better without sacrificing debuging...
>
>
> This example is somewhat contrived, but the code seems like 33% waste.
> Eventually that much bloat is going to cost in terms of I/O in the  
> assembly, linker,
> paging it in at runtime, and even a little extra to run it.

It would be useful to see what the overhead actually is.  You can do  
this by changing Host.doIncGC to FALSE instead of TRUE in m3front.   
There is a flag that will do this: -NoIncGC.  I forget how we actually  
pass those flags to the front-end from m3build.  I think something like:

M3Option("-NoIncGC")


> "Now that I understand things somewhat better.."
> How bad/unportable was it the previous way, the VM-synchronized way?

Not compatible with system threading.

> Can the checks only be generated for calls to extern functions?

Huh?  Not pertinent.

> When I write C wrappers, am I missing checks?
> (I can check, maybe the checks are generated).
> Are they missing sometimes with regard to X Windows?

You should *never* access a field in the heap in C code!   All  
accesses to traced fields in the heap must take place in Modula-3.   
Otherwise things will break!  C wrappers should not do anything other  
than forward calls to C library calls.  They should not perform heap  
accesses.

> I think I understand just barely some of what is going on.
> That writes through pointers need to be checked.

Yes, writes of references to traced fields in the heap need the checks  
too for generational GC.

> Because objects can move around.
> But moving objects doesn't update the references, but instead
> marks pages as different? (In the VM-synchronized world,
> moving an object would mark its original page invalid, triggering
> a page fault upon subsequent access, which is handled by referencing
> the new location and maybe updating the old pointer).

I think you are confusing incremental and incremental GC.

>
>
>
> ??? Something like that ???
>
>
> - Jay




More information about the M3devel mailing list