runtime/src/common/RTHeap.m3


Copyright (C) 1994, Digital Equipment Corp.

UNSAFE MODULE RTHeap;

IMPORT RTType, RTMisc;
If r is a traced reference, GetDataAdr returns the address of r^'s data bytes. If r is a traced object, GetDataAdr returns the address of r's data record's bytes. It is a checked runtime error if r is NIL. Note that the address can subsequently change unless object mobility is disabled using RTCollector.

PROCEDURE GetDataAdr (r: REFANY): ADDRESS =
  VAR def := RTType.Get(TYPECODE(r));
  BEGIN
    IF r = NIL THEN
      Die (); <*ASSERT FALSE*>
    ELSIF def.defaultMethods # NIL THEN
      RETURN LOOPHOLE(r, ADDRESS) + ADRSIZE(ADDRESS);
    ELSIF def.nDimensions # 0 THEN
      RETURN LOOPHOLE(r, UNTRACED REF ADDRESS)^;
    ELSE
      RETURN LOOPHOLE(r, ADDRESS);
    END;
  END GetDataAdr;
If r is a traced reference, GetDataSize returns the number of r^'s data bytes. If r is a traced object, GetDataSize returns the number of r's data record's bytes. It is a checked runtime error if r is NIL.

PROCEDURE GetDataSize (r: REFANY): CARDINAL =
  VAR
    def := RTType.Get(TYPECODE(r));
    sizes: UNTRACED REF INTEGER;
    n: INTEGER;
  BEGIN
    IF r = NIL THEN
      Die (); <*ASSERT FALSE*>
    ELSIF def.defaultMethods # NIL THEN
      RETURN def.dataSize - BYTESIZE(ADDRESS);
    ELSIF def.nDimensions = 0 THEN
      RETURN def.dataSize;
    ELSE (* an open array *)
      n := 1;
      sizes := LOOPHOLE(r, ADDRESS) + ADRSIZE(ADDRESS);
      FOR i := 0 TO def.nDimensions - 1 DO
        n := n * sizes^;
        INC(sizes, ADRSIZE(INTEGER));
      END;
      RETURN n * def.elementSize;
    END;
  END GetDataSize;
If r is a traced reference to an open array, GetArrayShape returns in s[0 .. n-1] the size of each dimension of the n-dimensional open array r^. If s is too large, the extra elements are ignored; if it's too small, the extra sizes are discarded. It is a checked runtime error if r is NIL. If r is not a reference to an open array, s is unchanged.

PROCEDURE GetArrayShape (r: REFANY; VAR s: ARRAY OF INTEGER) =
  VAR
    def := RTType.Get(TYPECODE(r));
    sizes: UNTRACED REF INTEGER := LOOPHOLE(r, ADDRESS) + ADRSIZE(ADDRESS);
  BEGIN
    FOR i := 0 TO MIN(NUMBER(s), def.nDimensions) - 1 DO
      s[i] := sizes^;
      INC(sizes, ADRSIZE(sizes^));
    END;
  END GetArrayShape;

PROCEDURE Die () =
  BEGIN
    RTMisc.FatalError (NIL, 0, "NIL ref passed to RTHeap.GetData");
  END Die;

BEGIN
END RTHeap.