00001
00002
00003
00004
00005
00006
00007
00008 enum { UNIT_SIZE=12, N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4,
00009 N_INDEXES=N1+N2+N3+N4 };
00010
00011 #pragma pack(1)
00012 struct BLK_NODE {
00013 DWORD Stamp;
00014 BLK_NODE* next;
00015 BOOL avail() const { return (next != NULL); }
00016 void link(BLK_NODE* p) { p->next=next; next=p; }
00017 void unlink() { next=next->next; }
00018 void* remove() {
00019 BLK_NODE* p=next; unlink();
00020 Stamp--; return p;
00021 }
00022 inline void insert(void* pv,int NU);
00023 } BList[N_INDEXES];
00024 struct MEM_BLK: public BLK_NODE { DWORD NU; } _PACK_ATTR;
00025 #pragma pack()
00026
00027 static BYTE Indx2Units[N_INDEXES], Units2Indx[128];
00028 static DWORD GlueCount, SubAllocatorSize=0;
00029 static BYTE* HeapStart, * pText, * UnitsStart, * LoUnit, * HiUnit;
00030
00031 inline void PrefetchData(void* Addr)
00032 {
00033 #if defined(_USE_PREFETCHING)
00034 BYTE PrefetchByte = *(volatile BYTE*) Addr;
00035 #endif
00036 }
00037 inline void BLK_NODE::insert(void* pv,int NU) {
00038 MEM_BLK* p=(MEM_BLK*) pv; link(p);
00039 p->Stamp=~0UL; p->NU=NU;
00040 Stamp++;
00041 }
00042 inline UINT U2B(UINT NU) { return 8*NU+4*NU; }
00043 inline void SplitBlock(void* pv,UINT OldIndx,UINT NewIndx)
00044 {
00045 UINT i, k, UDiff=Indx2Units[OldIndx]-Indx2Units[NewIndx];
00046 BYTE* p=((BYTE*) pv)+U2B(Indx2Units[NewIndx]);
00047 if (Indx2Units[i=Units2Indx[UDiff-1]] != UDiff) {
00048 k=Indx2Units[--i]; BList[i].insert(p,k);
00049 p += U2B(k); UDiff -= k;
00050 }
00051 BList[Units2Indx[UDiff-1]].insert(p,UDiff);
00052 }
00053 DWORD _STDCALL GetUsedMemory()
00054 {
00055 DWORD i, RetVal=SubAllocatorSize-(HiUnit-LoUnit)-(UnitsStart-pText);
00056 for (i=0;i < N_INDEXES;i++)
00057 RetVal -= UNIT_SIZE*Indx2Units[i]*BList[i].Stamp;
00058 return RetVal;
00059 }
00060 void _STDCALL StopSubAllocator() {
00061 if ( SubAllocatorSize ) {
00062 SubAllocatorSize=0; delete[] HeapStart;
00063 }
00064 }
00065 BOOL _STDCALL StartSubAllocator(UINT SASize)
00066 {
00067 DWORD t=SASize << 19U;
00068 if (SubAllocatorSize == t) return TRUE;
00069 StopSubAllocator();
00070 if ((HeapStart=new BYTE[t]) == NULL) return FALSE;
00071 SubAllocatorSize=t; return TRUE;
00072 }
00073 static inline void InitSubAllocator()
00074 {
00075 memset(BList,0,sizeof(BList));
00076 HiUnit=(pText=HeapStart)+SubAllocatorSize;
00077 UINT Diff=UNIT_SIZE*(SubAllocatorSize/8/UNIT_SIZE*7);
00078 LoUnit=UnitsStart=HiUnit-Diff; GlueCount=0;
00079 }
00080 static void GlueFreeBlocks()
00081 {
00082 UINT i, k, sz;
00083 MEM_BLK s0, * p, * p0, * p1;
00084 if (LoUnit != HiUnit) *LoUnit=0;
00085 for (i=0, (p0=&s0)->next=NULL;i < N_INDEXES;i++)
00086 while ( BList[i].avail() ) {
00087 p=(MEM_BLK*) BList[i].remove();
00088 if ( !p->NU ) continue;
00089 while ((p1=p+p->NU)->Stamp == ~0UL) {
00090 p->NU += p1->NU; p1->NU=0;
00091 }
00092 p0->link(p); p0=p;
00093 }
00094 while ( s0.avail() ) {
00095 p=(MEM_BLK*) s0.remove(); sz=p->NU;
00096 if ( !sz ) continue;
00097 for ( ;sz > 128;sz -= 128, p += 128)
00098 BList[N_INDEXES-1].insert(p,128);
00099 if (Indx2Units[i=Units2Indx[sz-1]] != sz) {
00100 k=sz-Indx2Units[--i]; BList[k-1].insert(p+(sz-k),k);
00101 }
00102 BList[i].insert(p,Indx2Units[i]);
00103 }
00104 GlueCount=1 << 13;
00105 }
00106 static void* _STDCALL AllocUnitsRare(UINT indx)
00107 {
00108 UINT i=indx;
00109 if ( !GlueCount ) {
00110 GlueFreeBlocks();
00111 if ( BList[i].avail() ) return BList[i].remove();
00112 }
00113 do {
00114 if (++i == N_INDEXES) {
00115 GlueCount--; i=U2B(Indx2Units[indx]);
00116 return (UnitsStart-pText > i)?(UnitsStart -= i):(NULL);
00117 }
00118 } while ( !BList[i].avail() );
00119 void* RetVal=BList[i].remove(); SplitBlock(RetVal,i,indx);
00120 return RetVal;
00121 }
00122 inline void* AllocUnits(UINT NU)
00123 {
00124 UINT indx=Units2Indx[NU-1];
00125 if ( BList[indx].avail() ) return BList[indx].remove();
00126 void* RetVal=LoUnit; LoUnit += U2B(Indx2Units[indx]);
00127 if (LoUnit <= HiUnit) return RetVal;
00128 LoUnit -= U2B(Indx2Units[indx]); return AllocUnitsRare(indx);
00129 }
00130 inline void* AllocContext()
00131 {
00132 if (HiUnit != LoUnit) return (HiUnit -= UNIT_SIZE);
00133 else if ( BList->avail() ) return BList->remove();
00134 else return AllocUnitsRare(0);
00135 }
00136 inline void UnitsCpy(void* Dest,void* Src,UINT NU)
00137 {
00138 DWORD* p1=(DWORD*) Dest, * p2=(DWORD*) Src;
00139 do {
00140 p1[0]=p2[0]; p1[1]=p2[1];
00141 p1[2]=p2[2];
00142 p1 += 3; p2 += 3;
00143 } while ( --NU );
00144 }
00145 inline void* ExpandUnits(void* OldPtr,UINT OldNU)
00146 {
00147 UINT i0=Units2Indx[OldNU-1], i1=Units2Indx[OldNU-1+1];
00148 if (i0 == i1) return OldPtr;
00149 void* ptr=AllocUnits(OldNU+1);
00150 if ( ptr ) {
00151 UnitsCpy(ptr,OldPtr,OldNU); BList[i0].insert(OldPtr,OldNU);
00152 }
00153 return ptr;
00154 }
00155 inline void* ShrinkUnits(void* OldPtr,UINT OldNU,UINT NewNU)
00156 {
00157 UINT i0=Units2Indx[OldNU-1], i1=Units2Indx[NewNU-1];
00158 if (i0 == i1) return OldPtr;
00159 if ( BList[i1].avail() ) {
00160 void* ptr=BList[i1].remove(); UnitsCpy(ptr,OldPtr,NewNU);
00161 BList[i0].insert(OldPtr,Indx2Units[i0]);
00162 return ptr;
00163 } else {
00164 SplitBlock(OldPtr,i0,i1); return OldPtr;
00165 }
00166 }
00167 inline void FreeUnits(void* ptr,UINT NU) {
00168 UINT indx=Units2Indx[NU-1];
00169 BList[indx].insert(ptr,Indx2Units[indx]);
00170 }
00171 inline void SpecialFreeUnit(void* ptr)
00172 {
00173 if ((BYTE*) ptr != UnitsStart) BList->insert(ptr,1);
00174 else { *(DWORD*) ptr=~0UL; UnitsStart += UNIT_SIZE; }
00175 }
00176 inline void* MoveUnitsUp(void* OldPtr,UINT NU)
00177 {
00178 UINT indx=Units2Indx[NU-1];
00179 if ((BYTE*) OldPtr > UnitsStart+16*1024 || (BLK_NODE*) OldPtr > BList[indx].next)
00180 return OldPtr;
00181 void* ptr=BList[indx].remove();
00182 UnitsCpy(ptr,OldPtr,NU); NU=Indx2Units[indx];
00183 if ((BYTE*) OldPtr != UnitsStart) BList[indx].insert(OldPtr,NU);
00184 else UnitsStart += U2B(NU);
00185 return ptr;
00186 }
00187 static inline void ExpandTextArea()
00188 {
00189 BLK_NODE* p;
00190 UINT Count[N_INDEXES]; memset(Count,0,sizeof(Count));
00191 while ((p=(BLK_NODE*) UnitsStart)->Stamp == ~0UL) {
00192 MEM_BLK* pm=(MEM_BLK*) p; UnitsStart=(BYTE*) (pm+pm->NU);
00193 Count[Units2Indx[pm->NU-1]]++; pm->Stamp=0;
00194 }
00195 for (UINT i=0;i < N_INDEXES;i++)
00196 for (p=BList+i;Count[i] != 0;p=p->next)
00197 while ( !p->next->Stamp ) {
00198 p->unlink(); BList[i].Stamp--;
00199 if ( !--Count[i] ) break;
00200 }
00201 }