[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:
parent
38ffc89c87
commit
ee9bbfa5e6
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue