[M3devel] (Not so) small bug report
Rodney M. Bates
rodney_bates at lcwb.coop
Sat Jul 26 19:07:13 CEST 2014
This bug is not exactly small.
The compiler assumes allocated space is zeroed, and doesn't generate
any initialization code for fields with an implicit or explicit initial
value of binary zeros. This is in m3front/src/types/ObjectType.m3:773 and :814
But RTAllocator.GetUntracedObj calls CStdlib.malloc to get the space, which,
according to my Harbison & Steele, does not initialize to anything. For
untraced REF and untraced REF ARRAY, it calls calloc, which does zero the
allocated area, so it looks like this affects only untraced OBJECT.
No doubt it is an accident that my small test case got memory that happened
to be zero anyway.
Pm3 calls CStdlib.malloc, but then zeros the result, in all 3 untraced cases.
On 07/26/2014 11:04 AM, Rodney M. Bates wrote:
> I can't reproduce this with cm3, AMD64_LINUX. The ASSERT does not fail,
> and I get:
> Breakpoint 1, P (el=11) at ../src/Main.m3:34
> 34 <*ASSERT nd.ns = 0 *>
> Current language: auto; currently Modula-3
> (m3gdb) p nd.ns
> $1 = 0
> The only things I did were to declare Elem and TStamp as CARDINAL,
> and put the allocator and ASSERT in a procedure, with el passed in.
> On 07/26/2014 06:20 AM, mika at async.caltech.edu wrote:
>> Hi m3devel,
>> So I realized that the reason my program runs slowly is not that there
>> are a lot of range checks, etc.
>> (BTW, changing M3_FRONT_FLAGS in cm3.cfg did manage to turn off these
>> checks as far as I can see, thanks!)
>> The problem is that the garbage collector involves procedure calls
>> whenever loading references. This is no good if you are running a tight
>> inner loop that chases pointers all over the heap.
>> My attempt at fixing this is to change the code to use UNTRACED REF for this
>> particular chunk, with DISPOSE. It's a small, simple part of the code, so this
>> is a good use case for the UNSAFE Modula-3 features.
>> I found a bug, though:
>> Node = UNTRACED ROOT OBJECT
>> id : Elem;
>> np : CARDINAL := 0;
>> pred : UNTRACED REF ARRAY OF Node;
>> ns : CARDINAL := 0;
>> succ : UNTRACED REF ARRAY OF Node;
>> sDly : UNTRACED REF ARRAY OF TStamp;
>> when : TStamp; (* max of all fanins observed *)
>> whch : Node; (* which fanin was critical *)
>> gen : CARDINAL := 0; (* generation of cnt *)
>> cnt : CARDINAL; (* how many fanins are left *)
>> nd := NEW(Node,
>> id := el,
>> pred := NEW(UNTRACED REF ARRAY OF Node, 1),
>> succ := NEW(UNTRACED REF ARRAY OF Node, 1),
>> sDly := NEW(UNTRACED REF ARRAY OF TStamp, 1),
>> cnt := 0);
>> <*ASSERT nd.ns = 0 *>
>> That ASSERT fails.
>> The code works on PM3 (FreeBSD4), as expected. (It works fine with
>> everything being traced, and I haven't changed any code at all, no DISPOSE
>> yet, so there "can't" be a bug in my code, at least not an unsafe one.)
>> Basically I think the implied initializers (from the :=... in the type definition)
>> aren't being run for UNTRACED ROOT OBJECTs.
rodney.m.bates at acm.org
More information about the M3devel