Heaps.Mos 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. (* ported version of Minos to work with the ARM backend of the Fox Compiler Suite *)
  2. MODULE Heaps; (* originally called "MAU" *) (* Memory Allocation Unit; NW 15.12.2007*)
  3. (* These procedures must remain in this order!*)
  4. (*
  5. 001 2007-07-03 tt: Added this header and formatted Module
  6. 002 2007-09-04 tt: Added status info
  7. *)
  8. IMPORT SYSTEM, Board, Memory, Trace;
  9. CONST
  10. Initialize = Board.InitializeHeap;
  11. VAR
  12. heapStart : ADDRESS;
  13. heap : ADDRESS; (*origin of free space*)
  14. heapEnd : ADDRESS;
  15. PROCEDURE New*( VAR p: LONGINT; T: LONGINT ); (*1*)
  16. (*allocate record, add tag field of 1 word with offset -4*)
  17. VAR i, size: LONGINT;
  18. BEGIN
  19. p := heap + 4;
  20. SYSTEM.PUT( heap, T ); (*adr of type descriptor (tag) to tagfield of new record*)
  21. SYSTEM.GET( T, size ); (*obtain record size from type descriptor*)
  22. IF size MOD 4 # 0 THEN INC(size, 4 - size MOD 4) END;
  23. heap := p + size;
  24. (* Clear heap *)
  25. IF Initialize THEN Memory.Fill8(p, size, 0X) END;
  26. ASSERT(heap < heapEnd);
  27. ASSERT(heapStart <= heap);
  28. END New;
  29. PROCEDURE AllocH*(VAR a: LONGINT; len, elsize: LONGINT); (*2*)
  30. (*allocate open array on heap, prefix with size field of 1 word with offset -4*)
  31. VAR i, adr, size: LONGINT;
  32. BEGIN
  33. size := len * elsize + 4; adr := ADDRESSOF(a);
  34. SYSTEM.PUT(adr, heap - 12); (*address of array into descriptor*)
  35. SYSTEM.PUT(adr-4, len); (*length of array into descriptor*)
  36. SYSTEM.PUT(heap, size); (*size of block into header*)
  37. IF size MOD 4 # 0 THEN INC(size, 4 - size MOD 4) END;
  38. IF Initialize THEN Memory.Fill8(heap + 4, len * elsize, 0X) END;
  39. heap := heap + size;
  40. ASSERT(heap < heapEnd);
  41. ASSERT(heapStart <= heap);
  42. END AllocH;
  43. PROCEDURE AllocS*(VAR a: LONGINT; len, elsize: LONGINT); (*3*)
  44. (*allocate open array on stack*)
  45. VAR adr: LONGINT;
  46. BEGIN adr := ADDRESSOF(a); SYSTEM.SETSP(SYSTEM.SP() - len * elsize);
  47. SYSTEM.PUT(adr, SYSTEM.SP()); (*address of array into descriptor*)
  48. SYSTEM.PUT(adr-4, len) (*length of array into descriptor*)
  49. END AllocS;
  50. PROCEDURE Alloc*( VAR adr: LONGINT; size: LONGINT );
  51. (*allocate area from free space*)
  52. VAR
  53. i: LONGINT;
  54. BEGIN
  55. IF size MOD 4 # 0 THEN INC(size, 4 - size MOD 4) END;
  56. adr := heap;
  57. IF Initialize THEN Memory.Fill8(adr, size, 0X) END;
  58. (*INC (size, 4);*)
  59. (*SYSTEM.PUT (heap, size);*)
  60. heap := heap + size;
  61. ASSERT(heap < heapEnd);
  62. ASSERT(heapStart <= heap);
  63. END Alloc;
  64. PROCEDURE HeapSize*(): LONGINT;
  65. BEGIN
  66. RETURN heapEnd - heapStart
  67. END HeapSize;
  68. PROCEDURE Free*(): LONGINT;
  69. BEGIN
  70. RETURN heapEnd - heap
  71. END Free;
  72. (* PROCEDURES THAT ARE USED BY THE FOX COMPILER *)
  73. (** NewSys - Implementation of SYSTEM.NEW. **)
  74. PROCEDURE NewSys*(VAR pointer: ANY; size: SIZE; isRealtime: BOOLEAN);
  75. VAR
  76. pointerAsInteger: LONGINT;
  77. BEGIN
  78. Alloc(pointerAsInteger, size);
  79. pointer := SYSTEM.VAL(ANY, pointerAsInteger)
  80. END NewSys;
  81. (** NewRec - Implementation of NEW with a record.
  82. - this is essentially a wrapper that calls New(...) **)
  83. PROCEDURE NewRec*(VAR pointer: ANY; typeTag: ADDRESS; isRealtime: BOOLEAN);
  84. VAR
  85. pointerAsInteger: LONGINT;
  86. BEGIN
  87. New(pointerAsInteger, SYSTEM.VAL(LONGINT, typeTag));
  88. pointer := SYSTEM.VAL(ANY, pointerAsInteger)
  89. END NewRec;
  90. (** NewArr - Implementation of NEW with an array containing pointers. *)
  91. PROCEDURE NewArr*(VAR p: ANY; elemTag: ADDRESS; numElems, numDims: SIZE; isRealtime: BOOLEAN);
  92. VAR
  93. openArray: ARRAY 2 OF LONGINT;
  94. BEGIN
  95. AllocH(openArray[1], numElems * numDims, SYSTEM.GET32(elemTag));
  96. p := SYSTEM.VAL(ANY, openArray[1]);
  97. END NewArr;
  98. (* replacement for overcomplicated code emission -- at the cost of a slightly increased runtime cost *)
  99. PROCEDURE NewArray*(CONST a: ARRAY OF SIZE; tag: ADDRESS; staticElements, elementSize: SIZE; VAR dest: ANY);
  100. TYPE
  101. UnsafeArray= POINTER {UNSAFE,UNTRACED} TO UnsafeArrayDesc;
  102. UnsafeArrayDesc = RECORD
  103. header : ARRAY 3 OF ADDRESS;
  104. len: ARRAY 8 OF SIZE;
  105. END;
  106. VAR p: ANY; dim: SIZE;
  107. PROCEDURE GetSize(): SIZE;
  108. VAR i: SIZE; size: SIZE;
  109. BEGIN
  110. size := 1;
  111. FOR i := 0 TO dim-1 DO
  112. size := size * a[i];
  113. END;
  114. RETURN size*staticElements;
  115. END GetSize;
  116. PROCEDURE SetSizes(dest: UnsafeArray);
  117. VAR i: SIZE;
  118. BEGIN
  119. FOR i := 0 TO dim-1 DO
  120. dest.len[i] := a[dim-1-i];
  121. END;
  122. END SetSizes;
  123. BEGIN
  124. (* static elements is requred for this case : POINTER TO ARRAY OF ARRAY X OF RecordWithPointer *)
  125. dim := LEN( a,0 );
  126. IF tag = NIL THEN
  127. NewSys(p, GetSize() * elementSize + dim * SIZEOF(ADDRESS) + 3 *SIZEOF(ADDRESS) + (dim DIV 2) * 2 * SIZEOF(ADDRESS), FALSE);
  128. ELSE
  129. NewArr(p, tag, GetSize(), dim, FALSE);
  130. END;
  131. SetSizes(p);
  132. dest := p;
  133. END NewArray;
  134. PROCEDURE Show*();
  135. BEGIN
  136. Trace.String("Heap base : "); Trace.Hex( heapStart, -8 ); Trace.String("; heap "); Trace.Hex( heap, -8 ); Trace.String("; end "); Trace.Hex( heapEnd, -8 ); Trace.Ln;
  137. END Show;
  138. BEGIN
  139. (* Init heap, currently done manually *)
  140. heapStart := Board.HeapBase;
  141. heap := Board.HeapBase;
  142. heapEnd := Board.HeapEnd;
  143. END Heaps.