diff --git a/uppsrc/Core/Heap.h b/uppsrc/Core/Heap.h index 6bfcb88ed..79851cee3 100644 --- a/uppsrc/Core/Heap.h +++ b/uppsrc/Core/Heap.h @@ -12,7 +12,7 @@ void MemoryFree48(void *ptr); void MemoryFreeThread(); void MemoryCheck(); int MemoryUsedKb(); - +int MemoryUsedKbMax(); void MemoryLimitKb(int kb); size_t GetMemoryBlockSize(void *ptr); diff --git a/uppsrc/Core/HeapImp.h b/uppsrc/Core/HeapImp.h index e0e613d21..3c43e81d6 100644 --- a/uppsrc/Core/HeapImp.h +++ b/uppsrc/Core/HeapImp.h @@ -1,4 +1,4 @@ -void OutOfMemoryPanic(size_t size); +void OutOfMemoryPanic(); void *SysAllocRaw(size_t size, size_t reqsize); void SysFreeRaw(void *ptr, size_t size); @@ -387,6 +387,7 @@ struct Heap : BlkHeap { static size_t sys_size; // blocks allocated directly from system (included in big too) static size_t sys_count; static size_t huge_chunks; // 32MB master pages + static size_t huge_4KB_count_max; // peak huge memory allocated #ifdef HEAPDBG static void DbgFreeFillK(void *ptr, int k); diff --git a/uppsrc/Core/Vcont.h b/uppsrc/Core/Vcont.h index 28dbd52cf..de0c20a6e 100644 --- a/uppsrc/Core/Vcont.h +++ b/uppsrc/Core/Vcont.h @@ -39,6 +39,36 @@ inline void DeepCopyConstruct(T *t, const S *s, const S *end) { template class Buffer : Moveable< Buffer > { T *ptr; + + void Malloc(size_t size) { + if(std::is_trivially_destructible::value) + ptr = (T *)MemoryAlloc(size * sizeof(T)); + else { + void *p = MemoryAlloc(size * sizeof(T) + 16); + *(size_t *)p = size; + ptr = (T *)((byte *)p + 16); + } + } + void New(size_t size) { + Malloc(size); + Construct(ptr, ptr + size); + } + void New(size_t size, const T& in) { + Malloc(size); + DeepCopyConstructFill(ptr, ptr + size, in); + } + void Free() { + if(ptr) { + if(std::is_trivially_destructible::value) + MemoryFree(ptr); + else { + void *p = (byte *)ptr - 16; + size_t size = *(size_t *)p; + Destroy(ptr, ptr + size); + MemoryFree(p); + } + } + } public: operator T*() { return ptr; } @@ -48,22 +78,22 @@ public: T *Get() { return ptr; } const T *Get() const { return ptr; } - void Alloc(size_t size) { Clear(); ptr = new T[size]; } - void Alloc(size_t size, const T& in) { Clear(); ptr = new T[size]; Fill(ptr, ptr + size, in); } + void Alloc(size_t size) { Clear(); New(size); } + void Alloc(size_t size, const T& in) { Clear(); New(size, in); } - void Clear() { if(ptr) delete[] ptr; ptr = NULL; } + void Clear() { Free(); ptr = NULL; } bool IsEmpty() const { return ptr == NULL; } Buffer() { ptr = NULL; } - Buffer(size_t size) { ptr = new T[size]; } - Buffer(size_t size, const T& init) { ptr = new T[size]; Fill(ptr, ptr + size, init); } - ~Buffer() { if(ptr) delete[] ptr; } + Buffer(size_t size) { New(size); } + Buffer(size_t size, const T& init) { New(size, init); } + ~Buffer() { Free(); } void operator=(Buffer&& v) { if(&v != this) { Clear(); ptr = v.ptr; v.ptr = NULL; } } Buffer(Buffer&& v) { ptr = v.ptr; v.ptr = NULL; } - Buffer(size_t size, std::initializer_list init) : Buffer(size) { - T *t = ptr; for(const auto& i : init) new (t++) T(i); + Buffer(size_t size, std::initializer_list init) { + T *t = Malloc(size); for(const auto& i : init) new (t++) T(i); } Buffer(std::initializer_list init) : Buffer(init.size(), init) {} }; diff --git a/uppsrc/Core/heaputil.cpp b/uppsrc/Core/heaputil.cpp index f571caa8f..ebbf3121b 100644 --- a/uppsrc/Core/heaputil.cpp +++ b/uppsrc/Core/heaputil.cpp @@ -13,8 +13,7 @@ namespace Upp { void OutOfMemoryPanic(size_t size) { char h[200]; - sprintf(h, "Out of memory!\nRequested size: %lld B\nU++ allocated memory: %d KB", - (long long)size, MemoryUsedKb()); + sprintf(h, "Out of memory!\nnU++ allocated memory: %d KB", MemoryUsedKb()); Panic(h); } @@ -25,40 +24,34 @@ size_t Heap::big_count; size_t Heap::sys_size; size_t Heap::sys_count; size_t Heap::huge_chunks; +size_t Heap::huge_4KB_count_max; int MemoryUsedKb() { return int(4 * (Heap::huge_4KB_count - Heap::free_4KB)); } -int sKBLimit = INT_MAX; - -void MemoryLimitKb(int kb) +int MemoryUsedKbMax() { - sKBLimit = kb; + return int(4 * Heap::huge_4KB_count_max); } -void DoPeakProfile(); - void *SysAllocRaw(size_t size, size_t reqsize) { void *ptr = NULL; - if(MemoryUsedKb() < sKBLimit) { - #ifdef PLATFORM_WIN32 - ptr = VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); - #elif PLATFORM_LINUX - ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); - if(ptr == MAP_FAILED) - ptr = NULL; - #else - ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); - if(ptr == MAP_FAILED) - ptr = NULL; - #endif - } +#ifdef PLATFORM_WIN32 + ptr = VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); +#elif PLATFORM_LINUX + ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if(ptr == MAP_FAILED) + ptr = NULL; +#else + ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); + if(ptr == MAP_FAILED) + ptr = NULL; +#endif if(!ptr) - OutOfMemoryPanic(size/*reqsize*/); - DoPeakProfile(); + OutOfMemoryPanic(size); return ptr; } @@ -196,6 +189,7 @@ String AsString(const MemoryProfile& mem) size_t asize = 0; int fcount = 0; size_t fsize = 0; + text << "Memory peak " << MemoryUsedKbMax() << "\n"; for(int i = 0; i < 1024; i++) if(mem.allocated[i]) { int sz = 4 * i; diff --git a/uppsrc/Core/hheap.cpp b/uppsrc/Core/hheap.cpp index daf93d68d..a381a4d03 100644 --- a/uppsrc/Core/hheap.cpp +++ b/uppsrc/Core/hheap.cpp @@ -30,6 +30,24 @@ EXITBLOCK { } #endif +int sKBLimit = INT_MAX; + +void MemoryLimitKb(int kb) +{ + sKBLimit = kb; +} + +static MemoryProfile *sPeak; + +MemoryProfile *PeakMemoryProfile() +{ + if(sPeak) + return sPeak; + sPeak = (MemoryProfile *)MemoryAllocPermanent(sizeof(MemoryProfile)); + memset((void *)sPeak, 0, sizeof(MemoryProfile)); + return NULL; +} + void *Heap::HugeAlloc(size_t count) // count in 4kb pages { ASSERT(count); @@ -40,6 +58,14 @@ void *Heap::HugeAlloc(size_t count) // count in 4kb pages #endif huge_4KB_count += count; + + if(huge_4KB_count > huge_4KB_count_max) { + huge_4KB_count_max = huge_4KB_count; + if(MemoryUsedKb() > sKBLimit) + Panic("MemoryLimitKb breached!"); + if(sPeak) + Make(*sPeak); + } if(!D::freelist[0]->next) { // initialization for(int i = 0; i < 2; i++) diff --git a/uppsrc/Core/sheap.cpp b/uppsrc/Core/sheap.cpp index bcc7e558e..d7457b601 100644 --- a/uppsrc/Core/sheap.cpp +++ b/uppsrc/Core/sheap.cpp @@ -465,23 +465,6 @@ MemoryProfile::MemoryProfile() ThreadHeap()->Make(*this); } -static MemoryProfile *sPeak; - -void DoPeakProfile() -{ - if(sPeak) - ThreadHeap()->Make(*sPeak); -} - -MemoryProfile *PeakMemoryProfile() -{ - if(sPeak) - return sPeak; - sPeak = (MemoryProfile *)MemoryAllocPermanent(sizeof(MemoryProfile)); - memset((void *)sPeak, 0, sizeof(MemoryProfile)); - return NULL; -} - #endif }