[clang][Interp] Make sure we free() allocated InitMaps

They get allocated when calling initialize() on a primitive array. And
they get free'd when the array is fully initialized. However, when that
never happens, they get leaked. Fix that by calling the destructor of
global variables.

Differential Revision: https://reviews.llvm.org/D136826
This commit is contained in:
Timm Bäder 2022-10-27 11:32:31 +02:00
parent 38ffc89c87
commit ee9bbfa5e6
5 changed files with 26 additions and 3 deletions

View File

@ -39,6 +39,11 @@ static void ctorArrayTy(Block *, char *Ptr, bool, bool, bool, Descriptor *D) {
template <typename T>
static void dtorArrayTy(Block *, char *Ptr, Descriptor *D) {
InitMap *IM = *reinterpret_cast<InitMap **>(Ptr);
if (IM != (InitMap *)-1)
free(IM);
Ptr += sizeof(InitMap *);
for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
reinterpret_cast<T *>(Ptr)[I].~T();
}
@ -178,7 +183,7 @@ static BlockCtorFn getCtorArrayPrim(PrimType Type) {
}
static BlockDtorFn getDtorArrayPrim(PrimType Type) {
COMPOSITE_TYPE_SWITCH(Type, return dtorArrayTy<T>, return nullptr);
TYPE_SWITCH(Type, return dtorArrayTy<T>);
}
static BlockMoveFn getMoveArrayPrim(PrimType Type) {

View File

@ -73,6 +73,12 @@ public:
/*isActive=*/true, Desc);
}
// Invokes the Destructor.
void invokeDtor() {
if (Desc->DtorFn)
Desc->DtorFn(this, data(), Desc);
}
protected:
friend class Pointer;
friend class DeadBlock;

View File

@ -143,7 +143,7 @@ bool Pointer::isInitialized() const {
Descriptor *Desc = getFieldDesc();
assert(Desc);
if (Desc->isPrimitiveArray()) {
if (Pointee->IsStatic)
if (isStatic() && Base == 0)
return true;
// Primitive array field are stored in a bitset.
InitMap *Map = getInitMap();
@ -164,7 +164,11 @@ void Pointer::initialize() const {
assert(Desc);
if (Desc->isArray()) {
if (Desc->isPrimitiveArray() && !Pointee->IsStatic) {
if (Desc->isPrimitiveArray()) {
// Primitive global arrays don't have an initmap.
if (isStatic() && Base == 0)
return;
// Primitive array initializer.
InitMap *&Map = getInitMap();
if (Map == (InitMap *)-1)

View File

@ -64,6 +64,7 @@ unsigned Program::createGlobalString(const StringLiteral *S) {
unsigned Sz = Desc->getAllocSize();
auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true,
/*isExtern=*/false);
G->block()->invokeCtor();
Globals.push_back(G);
// Construct the string in storage.

View File

@ -47,6 +47,13 @@ public:
// here manually so they are properly freeing their resources.
for (auto RecordPair : Records)
RecordPair.second->~Record();
// Manually destroy all the blocks. They are almost all harmless,
// but primitive arrays might have an InitMap* heap allocated and
// that needs to be freed.
for (Global *G : Globals) {
G->block()->invokeDtor();
}
}
/// Marshals a native pointer to an ID for embedding in bytecode.