-- Copyright (C) 1986 by Xerox Corporation. All rights reserved.
-- CHeapImpl.mesa
-- NFS 3-Mar-86 11:10:55
-- C Library storage allocation/deallocation procedures.
DIRECTORY
CHeap USING [BytePointer],
CRuntime USING [GetHeap, SetHeap, StopIfUserAborted],
CString USING [ToBytePointer, ToWordPointer],
Environment USING [bytesPerWord, Word, wordsPerPage],
Heap USING [Create, Error],
Inline USING [DBITAND, LongCOPY],
SpecialCRuntime USING [heapSize];
CHeapImpl: PROGRAM
IMPORTS CRuntime, CString, Heap, Inline, SpecialCRuntime EXPORTS CHeap =
{
BytePointer: TYPE = CHeap.BytePointer;
GetHeap: PUBLIC PROCEDURE RETURNS [UNCOUNTED ZONE] = {
z: UNCOUNTED ZONE;
CRuntime.StopIfUserAborted[];
z ← CRuntime.GetHeap[];
IF z = NIL THEN {
z ← Heap.Create[
initial: SpecialCRuntime.heapSize, increment: SpecialCRuntime.heapSize,
largeNodeThreshold:
INTEGER[SpecialCRuntime.heapSize] * Environment.wordsPerPage];
CRuntime.SetHeap[z];
};
RETURN[z];
};
WordsForBytes: PROCEDURE [nBytes: CARDINAL] RETURNS [nWords: CARDINAL] = INLINE {
RETURN[(nBytes + Environment.bytesPerWord - 1) / Environment.bytesPerWord]; };
malloc: PUBLIC PROCEDURE [size: CARDINAL] RETURNS [ptr: BytePointer] = {
ENABLE Heap.Error => {ptr.pointer ← NIL; CONTINUE; };
z: UNCOUNTED ZONE ← GetHeap[];
ptr ← CString.ToBytePointer[MakeNode[z: z, n: WordsForBytes[size]]];
};
calloc: PUBLIC PROCEDURE [nelem, elsize: CARDINAL] RETURNS [ptr: BytePointer] = {
ENABLE Heap.Error => {ptr.pointer ← NIL; CONTINUE; };
z: UNCOUNTED ZONE;
wptr: LONG POINTER;
nWords: CARDINAL = WordsForBytes[nelem * elsize];
IF nWords = 0 THEN {ptr.pointer ← NIL; RETURN};
z ← GetHeap[];
wptr ← MakeNode[z: z, n: nWords];
LOOPHOLE[wptr, LONG POINTER TO Environment.Word]↑ ← 0;
Inline.LongCOPY[
from: wptr, nwords: nWords - 1,
to: LOOPHOLE[wptr, LONG ORDERED POINTER] + 1];
ptr ← CString.ToBytePointer[wptr];
};
realloc: PUBLIC PROCEDURE [ptr: BytePointer, size: CARDINAL]
RETURNS [nptr: BytePointer] = {
ENABLE Heap.Error => {nptr.pointer ← NIL; CONTINUE; };
z: UNCOUNTED ZONE;
oldSize: CARDINAL;
newSize: CARDINAL = WordsForBytes[size];
wptr: LONG POINTER ←
IF IsBytePtr[ptr.pointer] THEN CString.ToWordPointer[ptr] ELSE ptr.pointer;
wnptr: LONG POINTER;
z ← GetHeap[];
oldSize ← GetNodeSize[wptr, z];
IF newSize <= oldSize THEN RETURN[ptr];
wnptr ← MakeNode[z: z, n: newSize];
Inline.LongCOPY[from: wptr, nwords: oldSize, to: wnptr];
FreeNode[z: z, p: wptr];
nptr ← CString.ToBytePointer[wnptr];
};
GetNodeSize: PROCEDURE [
ptr: LONG POINTER, z: UNCOUNTED ZONE]
RETURNS [size: CARDINAL] = {
node: NodeHandle ← ptr - SIZE[CARDINAL];
RETURN[node.length];
};
free: PUBLIC PROCEDURE [ptr: BytePointer] RETURNS [INTEGER ← 0] = {
z: UNCOUNTED ZONE;
wptr: LONG POINTER ←
IF IsBytePtr[ptr.pointer] THEN CString.ToWordPointer[ptr] ELSE ptr.pointer;
z ← GetHeap[];
FreeNode[z: z, p: wptr];
};
IsBytePtr: PROCEDURE [ptr: LONG UNSPECIFIED] RETURNS [BOOLEAN] = INLINE {
hiBit: LONG CARDINAL = 20000000000B; RETURN[Inline.DBITAND[ptr, hiBit] # 0]; };
SetHeap: PUBLIC PROCEDURE [z: UNCOUNTED ZONE] RETURNS [INTEGER ← 0] = {
CRuntime.SetHeap[z]; };
NodeObject: TYPE = RECORD [
body: SEQUENCE length: CARDINAL OF WORD];
NodeHandle: TYPE = LONG POINTER TO NodeObject;
FreeNode: PROC[z: UNCOUNTED ZONE, p: LONG POINTER]={
node: NodeHandle ← p - SIZE[CARDINAL];
z.FREE[@node];
};
MakeNode: PROC[z: UNCOUNTED ZONE, n: CARDINAL] RETURNS [p: LONG POINTER]={
node: NodeHandle;
node ← z.NEW[NodeObject[n]];
RETURN[@node[0]];
};
}.