| 1019 | } |
| 1020 | |
| 1021 | void BFGC::SweepSpan(tcmalloc_obj::Span* span, int expectedStartPage) |
| 1022 | { |
| 1023 | if ((gBfRtDbgFlags & BfRtFlags_ObjectHasDebugFlags) == 0) |
| 1024 | return; |
| 1025 | |
| 1026 | if (span->location != tcmalloc_obj::Span::IN_USE) |
| 1027 | return; |
| 1028 | |
| 1029 | if (span->start != expectedStartPage) |
| 1030 | { |
| 1031 | // This check covers when a new multi-page span is being put into place |
| 1032 | // and we catch after the first block, and it also catches the case |
| 1033 | // when the allocator splits a span and the pagemap can hold a reference |
| 1034 | // to a span that no longer covers that location. |
| 1035 | // For both of these cases we ignore the span. Remember, the worst case |
| 1036 | // here is that we'll miss a sweep of an object, which would just delay it's |
| 1037 | // cleanup until next GC cycle. Because the GC is the sole freer of spans, |
| 1038 | // there can never be a case where we find a valid span and then the span |
| 1039 | // changes sizeclass or location before we can scan the memory it points to. |
| 1040 | // |
| 1041 | // This also covers the case where a page spans over a radix map section and |
| 1042 | // we catch it on an outer loop again |
| 1043 | return; |
| 1044 | } |
| 1045 | |
| 1046 | intptr pageSize = (intptr)1<<kPageShift; |
| 1047 | intptr spanSize = pageSize * span->length; |
| 1048 | void* spanStart = (void*)((intptr)span->start << kPageShift); |
| 1049 | void* spanEnd = (void*)((intptr)spanStart + spanSize); |
| 1050 | void* spanPtr = spanStart; |
| 1051 | |
| 1052 | BF_LOGASSERT((spanStart >= tcmalloc_obj::PageHeap::sAddressStart) && (spanEnd <= tcmalloc_obj::PageHeap::sAddressEnd)); |
| 1053 | |
| 1054 | intptr elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass); |
| 1055 | if (elementSize == 0) |
| 1056 | elementSize = spanSize; |
| 1057 | BF_LOGASSERT(elementSize >= sizeof(bf::System::Object)); |
| 1058 | |
| 1059 | while (spanPtr <= (uint8*)spanEnd - elementSize) |
| 1060 | { |
| 1061 | //objCheckCount++; |
| 1062 | |
| 1063 | bf::System::Object* obj = (bf::System::Object*)spanPtr; |
| 1064 | |
| 1065 | #ifdef TARGET_TYPE |
| 1066 | if ((obj->mAllocCheckPtr != 0) && (obj->mBFVData->mType == TARGET_TYPE)) |
| 1067 | { |
| 1068 | //sweepFoundCount++; |
| 1069 | } |
| 1070 | #endif |
| 1071 | // Mark 0 means 'just allocated'. 'deleteMarkId' is the last one. 'invalidMarkId' should be impossible because we'd either be deleted or marked as leaked before |
| 1072 | |
| 1073 | int deleteMarkId = mCurMarkId - 1; |
| 1074 | if (deleteMarkId == 0) |
| 1075 | deleteMarkId = 3; |
| 1076 | |
| 1077 | int invalidMarkId = deleteMarkId - 1; |
| 1078 | if (invalidMarkId == 0) |
nothing calls this directly
no test coverage detected