Module mem = Begin External Routine lib$get_vm, lib$free_vm, lib$stop; Own LIST : Vector[33]; ! ! allocate 'n' words of memory ! Global Routine GETSPACE(n) = Begin Local p : Ref Vector, m, sts, k; ! no one should be allocating zero words If .n Eql 0 Then Return 0; ! compute the size in bytes m = .n * 8; ! we keep lists of blocks for sizes 1-32. for anything larger ! we just allocate the memory directly. If .n Gtru 32 Then Begin k = .m; p = 0; sts = lib$get_vm(k,p); If Not .sts Then lib$stop(.sts) End Else Begin ! take the next block from the list. if the list is empty then ! allocate 32 more blocks of that size and initialize a new list. p = .list[.n]; If .p Eqla 0 Then Begin k = .m * 32; sts = lib$get_vm(k,p); If Not .sts Then lib$stop(.sts); list[.n] = .p; ! first 30 Incr i From 1 To 30 Do Begin p[0] = .p + .m; p = .p + .m End; ! 31th p[0] = 0; ! 32nd p = .p + .m End Else list[.n] = .p[0] End; ! caller wants the memory block to be all zeros due to ! lazy programming ch$fill(0,.m,.p); Return .p End; ! ! duplicate a block of memory ! Global Routine DUPSPACE(p,n) = Begin Local s; s = GETSPACE(.n); ch$move(.n*8,.p,.s); Return .s End; ! ! release a block of memory ! ! notes: ! there is code which will allocate a block and then ! later release a portion of it back. this is ok ! because we do not place any headers in front of blocks ! and make it the responsibility of the caller to know ! the size of the block being released. Global Routine RELEASESPACE(p : Ref Vector,n) : Novalue = Begin Local k; If .n Eql 0 Then Return; ! lexemes uses the high order 32 bits of a word for information ! and the low 32 bits for the address. mask to only the address. p = .p<0,32,1>; If .p Eqla 0 Then Return; ! release big blocks back to the operating system If .n Gtr 32 Then Begin k = .n * 8; lib$free_vm(p,n) End Else ! otherwise place the block back on its list Begin p[0] = .list[.n]; list[.n] = .p End End; End Eludom