-- Copyright (C) 1986 by Xerox Corporation. All rights reserved. -- BucketAllocImpl.mesa -- MEW 2-Mar-86 12:39:45 DIRECTORY BucketAlloc, Heap; BucketAllocImpl: MONITOR IMPORTS Heap EXPORTS BucketAlloc = BEGIN BucketRec: TYPE = RECORD [ first: LONG POINTER TO LONG POINTER, size: CARDINAL, info: BucketAlloc.BucketInfo]; BucketSeq: TYPE = RECORD [SEQUENCE length: CARDINAL OF BucketRec]; BigNode: TYPE = LONG POINTER TO BigNodeRec; BigNodeRec: TYPE = RECORD [size: CARDINAL, ptr: LONG POINTER, next: BigNode]; bigList: BigNode ¬ NIL; zone: UNCOUNTED ZONE; b: LONG POINTER TO BucketSeq; Initialize: PUBLIC ENTRY PROCEDURE [ z: UNCOUNTED ZONE, buckets: LONG DESCRIPTOR FOR ARRAY OF BucketAlloc.BucketInfo] = BEGIN zone ¬ z; b ¬ z.NEW[BucketSeq [LENGTH[buckets]]]; FOR i: CARDINAL IN [0..LENGTH[buckets]) DO b[i] ¬ [first: NIL, size: 0, info: buckets[i]]; IF buckets[i].nodeSize < SIZE[LONG POINTER] THEN b[i].info.nodeSize ¬ SIZE[LONG POINTER]; FOR j: CARDINAL IN [0..buckets[i].initialBucketSize) DO p: LONG POINTER TO LONG POINTER; p ¬ Heap.MakeNode[z, buckets[i].nodeSize]; p­ ¬ b[i].first; b[i].first ¬ p; ENDLOOP; b[i].size ¬ buckets[i].initialBucketSize; ENDLOOP; -- Now Sort These FOR i: CARDINAL IN [1..LENGTH[buckets]) DO current: BucketRec = b[i]; FOR j: CARDINAL DECREASING IN [0..i - 1] DO IF current.info.nodeSize >= b[j].info.nodeSize THEN { b[j + 1] ¬ current; EXIT}; b[j + 1] ¬ b[j]; ENDLOOP ENDLOOP; END; Reset: PUBLIC PROCEDURE = BEGIN FOR i: CARDINAL IN [0..b.length) DO IF b[i].size > b[i].info.initialBucketSize THEN FOR j: CARDINAL IN [0..(b[i].info.initialBucketSize - b[i].size)) DO ptr: LONG POINTER TO LONG POINTER ¬ b[i].first; b[i].first ¬ ptr­; zone.FREE[@ptr]; ENDLOOP ELSE FOR j: CARDINAL IN [b[i].size..b[i].info.initialBucketSize) DO p: LONG POINTER TO LONG POINTER; p ¬ Heap.MakeNode[zone, b[i].info.nodeSize]; p­ ¬ b[i].first; b[i].first ¬ p; ENDLOOP; b[i].size ¬ b[i].info.initialBucketSize; ENDLOOP END; Destroy: PUBLIC PROCEDURE = BEGIN FOR i: CARDINAL IN [0..b.length) DO p, next: LONG POINTER TO LONG POINTER; FOR p ¬ b[i].first, next WHILE p # NIL DO next ¬ p­; zone.FREE[@p]; ENDLOOP; ENDLOOP END; Alloc: PUBLIC PROCEDURE [size: CARDINAL] RETURNS [p: LONG POINTER] = BEGIN bucket: LONG POINTER TO BucketRec ¬ FindBucket[size]; IF bucket.info.nodeSize < size THEN { -- bigger than the biggest bucket big: BigNode ¬ zone.NEW[BigNodeRec]; p ¬ Heap.MakeNode[zone, size]; big­ ¬ [size: size, ptr: p, next: bigList]; bigList ¬ big; RETURN[p]}; IF bucket.first # NIL THEN { p ¬ bucket.first; bucket.first ¬ bucket.first­; bucket.size ¬ bucket.size - 1; RETURN[p]} ELSE RETURN[Heap.MakeNode[zone, bucket.info.nodeSize]] END; Free: PUBLIC PROCEDURE [p: LONG POINTER TO LONG POINTER, size: CARDINAL] = BEGIN bucket: LONG POINTER TO BucketRec ¬ FindBucket[size]; IF bucket.info.nodeSize < size THEN { -- bigger than the biggest bucket big: BigNode; FOR big ¬ bigList, big.next WHILE big # NIL DO IF big.ptr = p­ THEN { IF big # bigList THEN ERROR; -- ASSERT big = bigList bigList ¬ big.next; Heap.FreeNode[zone, p­]; p­ ¬ NIL; zone.FREE[@big]; RETURN}; IF big.next.ptr = p­ THEN { big.next ¬ big.next.next; Heap.FreeNode[zone, p­]; p­ ¬ NIL; zone.FREE[@big]; RETURN} ENDLOOP; }; IF bucket.size >= bucket.info.maxBucketSize THEN { Heap.FreeNode[zone, p­]; p­ ¬ NIL; RETURN} ELSE { LOOPHOLE[p­, LONG POINTER TO LONG POINTER]­ ¬ bucket.first; bucket.first ¬ LOOPHOLE[p­, LONG POINTER TO LONG POINTER]; bucket.size ¬ bucket.size + 1} END; FindBucket: PROCEDURE [size: CARDINAL] RETURNS [l: LONG POINTER TO BucketRec ¬ NIL] = BEGIN low, high, mid: CARDINAL; IF b[0].info.nodeSize >= size THEN RETURN[@b[0]]; IF b[b.length - 1].info.nodeSize <= size THEN RETURN[@b[b.length - 1]]; low ¬ 0; high ¬ b.length - 1; FOR mid ¬ (low + high) / 2, (low + high) / 2 WHILE high >= low DO IF b[mid].info.nodeSize = size THEN RETURN[@b[mid]]; IF b[mid].info.nodeSize > size THEN { IF b[mid - 1].info.nodeSize = size THEN RETURN[@b[mid - 1]]; IF b[mid - 1].info.nodeSize < size THEN RETURN[@b[mid]]; high ¬ mid - 1} ELSE { IF b[mid + 1].info.nodeSize >= size THEN RETURN[@b[mid + 1]]; low ¬ mid + 1} ENDLOOP; END; END..