Don't finalize scope objects without dtors and monitor (#2516)

The dtors can be checked at compile-time; insert a runtime check for the
monitor before finalizing the stack-allocated class object via druntime
call.

See issue #2515.
This commit is contained in:
Martin Kinkelin 2018-01-26 18:38:16 +01:00 committed by GitHub
parent 1da088330d
commit 6367d98d3a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 143 additions and 2 deletions

View file

@ -21,6 +21,7 @@
#include "gen/llvmhelpers.h"
#include "gen/logger.h"
#include "gen/nested.h"
#include "gen/optimizer.h"
#include "gen/rttibuilder.h"
#include "gen/runtime.h"
#include "gen/structs.h"
@ -193,6 +194,50 @@ void DtoFinalizeClass(Loc &loc, LLValue *inst) {
////////////////////////////////////////////////////////////////////////////////
void DtoFinalizeScopeClass(Loc &loc, LLValue *inst, ClassDeclaration *cd) {
if (!isOptimizationEnabled()) {
DtoFinalizeClass(loc, inst);
return;
}
assert(cd);
// As of 2.077, the front-end doesn't emit the implicit delete() for C++
// classes, so this code assumes D classes.
assert(!cd->isCPPclass());
bool hasDtor = false;
for (; cd; cd = cd->baseClass) {
if (cd->dtor) {
hasDtor = true;
break;
}
}
if (hasDtor) {
DtoFinalizeClass(loc, inst);
return;
}
// no dtors => only finalize (via druntime call) if monitor is set,
// see https://github.com/ldc-developers/ldc/issues/2515
llvm::BasicBlock *ifbb = gIR->insertBB("if");
llvm::BasicBlock *endbb = gIR->insertBBAfter(ifbb, "endif");
const auto monitor = DtoLoad(DtoGEPi(inst, 0, 1), ".monitor");
const auto hasMonitor =
gIR->ir->CreateICmp(llvm::CmpInst::ICMP_NE, monitor,
getNullValue(monitor->getType()), ".hasMonitor");
llvm::BranchInst::Create(ifbb, endbb, hasMonitor, gIR->scopebb());
gIR->scope() = IRScope(ifbb);
DtoFinalizeClass(loc, inst);
gIR->ir->CreateBr(endbb);
gIR->scope() = IRScope(endbb);
}
////////////////////////////////////////////////////////////////////////////////
DValue *DtoCastClass(Loc &loc, DValue *val, Type *_to) {
IF_LOG Logger::println("DtoCastClass(%s, %s)", val->type->toChars(),
_to->toChars());