diff --git a/sdk/lib/rtl/heap.c b/sdk/lib/rtl/heap.c index ad4f6a1513d..a50c96759e6 100644 --- a/sdk/lib/rtl/heap.c +++ b/sdk/lib/rtl/heap.c @@ -702,10 +702,12 @@ RtlpFindAndCommitPages(PHEAP Heap, if(UcrDescriptor->Address == Segment->LastValidEntry) { FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY; + Segment->LastEntryInSegment = FirstEntry; } else { FirstEntry->Flags = 0; + Segment->LastEntryInSegment = Segment->FirstEntry; /* Update field of next entry */ ASSERT((FirstEntry + FirstEntry->Size)->PreviousSize == 0); (FirstEntry + FirstEntry->Size)->PreviousSize = FirstEntry->Size; @@ -720,6 +722,7 @@ RtlpFindAndCommitPages(PHEAP Heap, else { FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY; + Segment->LastEntryInSegment = FirstEntry; } /* We're done */ @@ -841,6 +844,7 @@ RtlpDeCommitFreeBlock(PHEAP Heap, FreeEntry->Flags = HEAP_ENTRY_LAST_ENTRY; FreeEntry->Size = (USHORT)PrecedingSize; Heap->TotalFreeSize += PrecedingSize; + Segment->LastEntryInSegment = FreeEntry; /* Insert it into the free list */ RtlpInsertFreeBlockHelper(Heap, FreeEntry, PrecedingSize, FALSE); @@ -849,6 +853,13 @@ RtlpDeCommitFreeBlock(PHEAP Heap, { /* Adjust preceding in use entry */ PrecedingInUseEntry->Flags |= HEAP_ENTRY_LAST_ENTRY; + Segment->LastEntryInSegment = PrecedingInUseEntry; + } + else if ((ULONG_PTR)Segment->LastEntryInSegment >= DecommitBase && + (ULONG_PTR)Segment->LastEntryInSegment < DecommitBase + DecommitSize) + { + /* Invalidate last entry */ + Segment->LastEntryInSegment = Segment->FirstEntry; } /* Now the next one */ @@ -933,6 +944,9 @@ RtlpInitializeHeapSegment(IN OUT PHEAP Heap, RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY) HeapEntry, (SegmentCommit >> HEAP_ENTRY_SHIFT) - Segment->Entry.Size); } + /* Always point to a valid entry */ + Segment->LastEntryInSegment = Segment->FirstEntry; + /* Initialise the Heap Segment UnCommitted Range information */ Segment->NumberOfUnCommittedPages = (ULONG)((SegmentReserve - SegmentCommit) >> PAGE_SHIFT); Segment->NumberOfUnCommittedRanges = 0; @@ -984,6 +998,7 @@ RtlpCoalesceFreeBlocks (PHEAP Heap, BOOLEAN Remove) { PHEAP_FREE_ENTRY CurrentEntry, NextEntry; + UCHAR SegmentOffset; /* Get the previous entry */ CurrentEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry - FreeEntry->PreviousSize); @@ -1022,6 +1037,12 @@ RtlpCoalesceFreeBlocks (PHEAP Heap, { ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize); } + else + { + SegmentOffset = FreeEntry->SegmentOffset; + ASSERT(SegmentOffset < HEAP_SEGMENTS); + Heap->Segments[SegmentOffset]->LastEntryInSegment = FreeEntry; + } } /* Check the next block if it exists */ @@ -1057,6 +1078,12 @@ RtlpCoalesceFreeBlocks (PHEAP Heap, { ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize); } + else + { + SegmentOffset = FreeEntry->SegmentOffset; + ASSERT(SegmentOffset < HEAP_SEGMENTS); + Heap->Segments[SegmentOffset]->LastEntryInSegment = FreeEntry; + } } } return FreeEntry; @@ -1637,6 +1664,7 @@ RtlpSplitEntry(PHEAP Heap, UCHAR FreeFlags, EntryFlags = HEAP_ENTRY_BUSY; PHEAP_ENTRY InUseEntry; SIZE_T FreeSize; + UCHAR SegmentOffset; /* Add extra flags in case of settable user value feature is requested, or there is a tag (small or normal) or there is a request to @@ -1748,6 +1776,12 @@ RtlpSplitEntry(PHEAP Heap, /* Reset flags of the free entry */ FreeFlags = 0; + if (SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY) + { + SegmentOffset = SplitBlock->SegmentOffset; + ASSERT(SegmentOffset < HEAP_SEGMENTS); + Heap->Segments[SegmentOffset]->LastEntryInSegment = SplitBlock; + } } } @@ -2311,6 +2345,7 @@ RtlpGrowBlockInPlace (IN PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, UnusedEntry, FollowingEntry; SIZE_T FreeSize, PrevSize, TailPart, AddedSize = 0; PHEAP_ENTRY_EXTRA OldExtra, NewExtra; + UCHAR SegmentOffset; /* We can't grow beyond specified threshold */ if (Index > Heap->VirtualMemoryThreshold) @@ -2407,9 +2442,17 @@ RtlpGrowBlockInPlace (IN PHEAP Heap, InUseEntry->Flags |= RememberFlags & HEAP_ENTRY_LAST_ENTRY; /* Either update previous size of the next entry or mark it as a last - entry in the segment*/ + entry in the segment */ if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY)) + { (InUseEntry + InUseEntry->Size)->PreviousSize = InUseEntry->Size; + } + else + { + SegmentOffset = InUseEntry->SegmentOffset; + ASSERT(SegmentOffset < HEAP_SEGMENTS); + Heap->Segments[SegmentOffset]->LastEntryInSegment = InUseEntry; + } } else { @@ -2422,6 +2465,10 @@ RtlpGrowBlockInPlace (IN PHEAP Heap, /* Update the following block or set the last entry in the segment */ if (RememberFlags & HEAP_ENTRY_LAST_ENTRY) { + SegmentOffset = UnusedEntry->SegmentOffset; + ASSERT(SegmentOffset < HEAP_SEGMENTS); + Heap->Segments[SegmentOffset]->LastEntryInSegment = UnusedEntry; + /* Set flags and size */ UnusedEntry->Flags = RememberFlags; UnusedEntry->Size = (USHORT)FreeSize; @@ -2468,7 +2515,15 @@ RtlpGrowBlockInPlace (IN PHEAP Heap, UnusedEntry->Size = (USHORT)FreeSize; if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY)) + { ((PHEAP_ENTRY)UnusedEntry + FreeSize)->PreviousSize = (USHORT)FreeSize; + } + else + { + SegmentOffset = UnusedEntry->SegmentOffset; + ASSERT(SegmentOffset < HEAP_SEGMENTS); + Heap->Segments[SegmentOffset]->LastEntryInSegment = UnusedEntry; + } /* Insert it back and update total size */ RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE); diff --git a/sdk/lib/rtl/heap.h b/sdk/lib/rtl/heap.h index 8fb9bc7ae0d..aef68e5edcd 100644 --- a/sdk/lib/rtl/heap.h +++ b/sdk/lib/rtl/heap.h @@ -217,7 +217,8 @@ typedef struct _HEAP_LIST_LOOKUP ULONG NumberOfUnCommittedRanges; \ USHORT SegmentAllocatorBackTraceIndex; \ USHORT Reserved; \ - LIST_ENTRY UCRSegmentList + LIST_ENTRY UCRSegmentList; \ + PVOID LastEntryInSegment //FIXME: non-Vista typedef struct _HEAP {