void ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) { SUPPORTS_DAC; g_gcDacGlobals->n_heaps.EnumMem(); DacEnumMemoryRegion(g_gcDacGlobals->g_heaps.GetAddr(), sizeof(TADDR) * *g_gcDacGlobals->n_heaps); g_gcDacGlobals->gc_structures_invalid_cnt.EnumMem(); g_gcDacGlobals->g_heaps.EnumMem(); for (int i=0; i < *g_gcDacGlobals->n_heaps; i++) { DPTR(dac_gc_heap) pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, i); size_t gen_table_size = g_gcDacGlobals->generation_size * (*g_gcDacGlobals->max_gen + 1); DacEnumMemoryRegion(dac_cast<TADDR>(pHeap), sizeof(dac_gc_heap)); DacEnumMemoryRegion(dac_cast<TADDR>(pHeap->finalize_queue), sizeof(dac_finalize_queue)); DacEnumMemoryRegion(dac_cast<TADDR>(pHeap->generation_table), gen_table_size); // enumerating the generations from max (which is normally gen2) to max+1 gives you // the segment list for all the normal segements plus the large heap segment (max+1) // this is the convention in the GC so it is repeated here for (ULONG i = *g_gcDacGlobals->max_gen; i <= *g_gcDacGlobals->max_gen +1; i++) { DPTR(dac_heap_segment) seg = ServerGenerationTableIndex(pHeap, i)->start_segment; while (seg) { DacEnumMemoryRegion(PTR_HOST_TO_TADDR(seg), sizeof(dac_heap_segment)); seg = seg->next; } } } }
HRESULT ClrDataAccess::GetServerAllocData(unsigned int count, struct DacpGenerationAllocData *data, unsigned int *pNeeded) { unsigned int heaps = (unsigned int)GCHeapCount(); if (pNeeded) *pNeeded = heaps; if (data) { if (count > heaps) count = heaps; for (unsigned int n=0; n < heaps; n++) { DPTR(dac_gc_heap) pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, n); for (int i=0;i<NUMBERGENERATIONS;i++) { dac_generation generation = *ServerGenerationTableIndex(pHeap, i); data[n].allocData[i].allocBytes = (CLRDATA_ADDRESS)(ULONG_PTR) generation.allocation_context.alloc_bytes; data[n].allocData[i].allocBytesLoh = (CLRDATA_ADDRESS)(ULONG_PTR) generation.allocation_context.alloc_bytes_loh; } } } return S_OK; }
HRESULT ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapDetails *detailsData) { if (!heapAddr) { // PREfix. return E_INVALIDARG; } DPTR(dac_gc_heap) pHeap = __DPtr<dac_gc_heap>(TO_TADDR(heapAddr)); int i; //get global information first detailsData->heapAddr = heapAddr; detailsData->lowest_address = PTR_CDADDR(g_lowest_address); detailsData->highest_address = PTR_CDADDR(g_highest_address); detailsData->card_table = PTR_CDADDR(g_card_table); // now get information specific to this heap (server mode gives us several heaps; we're getting // information about only one of them. detailsData->alloc_allocated = (CLRDATA_ADDRESS)pHeap->alloc_allocated; detailsData->ephemeral_heap_segment = (CLRDATA_ADDRESS)dac_cast<TADDR>(pHeap->ephemeral_heap_segment); // get bounds for the different generations for (i=0; i<NUMBERGENERATIONS; i++) { DPTR(dac_generation) generation = ServerGenerationTableIndex(pHeap, i); detailsData->generation_table[i].start_segment = (CLRDATA_ADDRESS)dac_cast<TADDR>(generation->start_segment); detailsData->generation_table[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR)generation->allocation_start; DPTR(gc_alloc_context) alloc_context = dac_cast<TADDR>(generation) + offsetof(dac_generation, allocation_context); detailsData->generation_table[i].allocContextPtr = (CLRDATA_ADDRESS)(ULONG_PTR) alloc_context->alloc_ptr; detailsData->generation_table[i].allocContextLimit = (CLRDATA_ADDRESS)(ULONG_PTR) alloc_context->alloc_limit; } DPTR(dac_finalize_queue) fq = pHeap->finalize_queue; DPTR(uint8_t*) pFillPointerArray= dac_cast<TADDR>(fq) + offsetof(dac_finalize_queue, m_FillPointers); for(i=0; i<(NUMBERGENERATIONS+dac_finalize_queue::ExtraSegCount); i++) { detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS) pFillPointerArray[i]; } return S_OK; }
HRESULT ClrDataAccess::ServerOomData(CLRDATA_ADDRESS addr, DacpOomData *oomData) { DPTR(dac_gc_heap) pHeap = __DPtr<dac_gc_heap>(TO_TADDR(addr)); oom_history pOOMInfo = pHeap->oom_info; oomData->reason = pOOMInfo.reason; oomData->alloc_size = pOOMInfo.alloc_size; oomData->available_pagefile_mb = pOOMInfo.available_pagefile_mb; oomData->gc_index = pOOMInfo.gc_index; oomData->fgm = pOOMInfo.fgm; oomData->size = pOOMInfo.size; oomData->loh_p = pOOMInfo.loh_p; return S_OK; }
HRESULT ClrDataAccess::ServerGCHeapAnalyzeData(CLRDATA_ADDRESS heapAddr, DacpGcHeapAnalyzeData *analyzeData) { if (!heapAddr) { // PREfix. return E_INVALIDARG; } DPTR(dac_gc_heap) pHeap = __DPtr<dac_gc_heap>(TO_TADDR(heapAddr)); analyzeData->heapAddr = heapAddr; analyzeData->internal_root_array = (CLRDATA_ADDRESS)pHeap->internal_root_array; analyzeData->internal_root_array_index = (size_t)pHeap->internal_root_array_index; analyzeData->heap_analyze_success = (BOOL)pHeap->heap_analyze_success; return S_OK; }
void DisposeClonedShape (Shape* const shape) { ASSERT_INITIALISED #if WITH_LAME_THINGS == 1 // Memory validation PASSERT(_::alValidate(shape)) PASSERT(_::alGet(shape)->allocated) shape->~Shape(); _::alGet(shape)->allocated = false; if (--_::allocations == 0) Reset(); #else // !WITH_LAME_THINGS DPTR(_DNOTNULL(shape))->~Shape(); DDELARR(reinterpret_cast<util_ui8* const>(shape)); #endif // WITH_LAME_THINGS }
HRESULT DacHeapWalker::InitHeapDataSvr(HeapData *&pHeaps, size_t &pCount) { // Scrape basic heap details int heaps = *g_gcDacGlobals->n_heaps; pCount = heaps; pHeaps = new (nothrow) HeapData[heaps]; if (pHeaps == NULL) return E_OUTOFMEMORY; for (int i = 0; i < heaps; ++i) { // Basic heap info. DPTR(dac_gc_heap) heap = HeapTableIndex(g_gcDacGlobals->g_heaps, i); dac_generation gen0 = *ServerGenerationTableIndex(heap, 0); dac_generation gen1 = *ServerGenerationTableIndex(heap, 1); dac_generation gen2 = *ServerGenerationTableIndex(heap, 2); dac_generation loh = *ServerGenerationTableIndex(heap, 3); pHeaps[i].YoungestGenPtr = (CORDB_ADDRESS)gen0.allocation_context.alloc_ptr; pHeaps[i].YoungestGenLimit = (CORDB_ADDRESS)gen0.allocation_context.alloc_limit; pHeaps[i].Gen0Start = (CORDB_ADDRESS)gen0.allocation_start; pHeaps[i].Gen0End = (CORDB_ADDRESS)heap->alloc_allocated; pHeaps[i].Gen1Start = (CORDB_ADDRESS)gen1.allocation_start; // Segments int count = GetSegmentCount(loh.start_segment); count += GetSegmentCount(gen2.start_segment); pHeaps[i].SegmentCount = count; pHeaps[i].Segments = new (nothrow) SegmentData[count]; if (pHeaps[i].Segments == NULL) return E_OUTOFMEMORY; // Small object heap segments DPTR(dac_heap_segment) seg = gen2.start_segment; int j = 0; for (; seg && (j < count); ++j) { pHeaps[i].Segments[j].Start = (CORDB_ADDRESS)seg->mem; if (seg.GetAddr() == heap->ephemeral_heap_segment.GetAddr()) { pHeaps[i].Segments[j].End = (CORDB_ADDRESS)heap->alloc_allocated; pHeaps[i].EphemeralSegment = j; pHeaps[i].Segments[j].Generation = 1; } else { pHeaps[i].Segments[j].End = (CORDB_ADDRESS)seg->allocated; pHeaps[i].Segments[j].Generation = 2; } seg = seg->next; } // Large object heap segments seg = loh.start_segment; for (; seg && (j < count); ++j) { pHeaps[i].Segments[j].Generation = 3; pHeaps[i].Segments[j].Start = (CORDB_ADDRESS)seg->mem; pHeaps[i].Segments[j].End = (CORDB_ADDRESS)seg->allocated; seg = seg->next; } } return S_OK; }