| 104 | |
| 105 | |
| 106 | void SubAllocator::InitSubAllocator() |
| 107 | { |
| 108 | int i, k; |
| 109 | memset(FreeList,0,sizeof(FreeList)); |
| 110 | pText=HeapStart; |
| 111 | |
| 112 | // Original algorithm operates with 12 byte FIXED_UNIT_SIZE, but actual |
| 113 | // size of RARPPM_MEM_BLK and RARPPM_CONTEXT structures can exceed this value |
| 114 | // because of alignment and larger pointer fields size. |
| 115 | // So we define UNIT_SIZE for this larger size and adjust memory |
| 116 | // pointers accordingly. |
| 117 | |
| 118 | // Size2 is (HiUnit-LoUnit) memory area size to allocate as originally |
| 119 | // supposed by compression algorithm. It is 7/8 of total allocated size. |
| 120 | uint Size2=FIXED_UNIT_SIZE*(SubAllocatorSize/8/FIXED_UNIT_SIZE*7); |
| 121 | |
| 122 | // RealSize2 is the real adjusted size of (HiUnit-LoUnit) memory taking |
| 123 | // into account that our UNIT_SIZE can be larger than FIXED_UNIT_SIZE. |
| 124 | uint RealSize2=Size2/FIXED_UNIT_SIZE*UNIT_SIZE; |
| 125 | |
| 126 | // Size1 is the size of memory area from HeapStart to FakeUnitsStart |
| 127 | // as originally supposed by compression algorithm. This area can contain |
| 128 | // different data types, both single symbols and structures. |
| 129 | uint Size1=SubAllocatorSize-Size2; |
| 130 | |
| 131 | // Real size of this area. We correct it according to UNIT_SIZE vs |
| 132 | // FIXED_UNIT_SIZE difference. Also we add one more UNIT_SIZE |
| 133 | // to compensate a possible reminder from Size1/FIXED_UNIT_SIZE, |
| 134 | // which would be lost otherwise. We add UNIT_SIZE instead of |
| 135 | // this Size1%FIXED_UNIT_SIZE reminder, because it allows to align |
| 136 | // UnitsStart easily and adding more than reminder is ok for algorithm. |
| 137 | uint RealSize1=Size1/FIXED_UNIT_SIZE*UNIT_SIZE+UNIT_SIZE; |
| 138 | |
| 139 | // RealSize1 must be divided by UNIT_SIZE without a reminder, so UnitsStart |
| 140 | // is aligned to UNIT_SIZE. It is important for those architectures, |
| 141 | // where a proper memory alignment is mandatory. Since we produce RealSize1 |
| 142 | // multiplying by UNIT_SIZE, this condition is always true. So LoUnit, |
| 143 | // UnitsStart, HeapStart are properly aligned, |
| 144 | LoUnit=UnitsStart=HeapStart+RealSize1; |
| 145 | |
| 146 | // When we reach FakeUnitsStart, we restart the model. It is where |
| 147 | // the original algorithm expected to see UnitsStart. Real UnitsStart |
| 148 | // can have a larger value. |
| 149 | FakeUnitsStart=HeapStart+Size1; |
| 150 | |
| 151 | HiUnit=LoUnit+RealSize2; |
| 152 | for (i=0,k=1;i < N1 ;i++,k += 1) |
| 153 | Indx2Units[i]=k; |
| 154 | for (k++;i < N1+N2 ;i++,k += 2) |
| 155 | Indx2Units[i]=k; |
| 156 | for (k++;i < N1+N2+N3 ;i++,k += 3) |
| 157 | Indx2Units[i]=k; |
| 158 | for (k++;i < N1+N2+N3+N4;i++,k += 4) |
| 159 | Indx2Units[i]=k; |
| 160 | for (GlueCount=k=i=0;k < 128;k++) |
| 161 | { |
| 162 | i += (Indx2Units[i] < k+1); |
| 163 | Units2Indx[k]=i; |