Skip to content

Reduce memory footprint of the Swift compiler #401

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 10, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/swift/SIL/SILBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class SILArgument;
class SILBasicBlock :
public llvm::ilist_node<SILBasicBlock>, public SILAllocated<SILBasicBlock> {
friend class SILSuccessor;
friend class SILFunction;
public:
using InstListType = llvm::iplist<SILInstruction>;
private:
Expand Down
7 changes: 7 additions & 0 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ class SILInstruction : public ValueBase,public llvm::ilist_node<SILInstruction>{
: ValueBase(Kind, TypeList), ParentBB(0), Location(*DebugLoc) {}

public:
/// Instructions should be allocated using a dedicated instruction allocation
/// function from the ContextTy.
template <typename ContextTy>
void *operator new(size_t Bytes, const ContextTy &C,
size_t Alignment = alignof(ValueBase)) {
return C.allocateInst(Bytes, Alignment);
}

enum class MemoryBehavior {
None,
Expand Down
11 changes: 6 additions & 5 deletions include/swift/SIL/SILModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,12 +531,13 @@ class SILModule {
bool PrintASTDecls = true) const;

/// Allocate memory using the module's internal allocator.
void *allocate(unsigned Size, unsigned Align) const {
if (getASTContext().LangOpts.UseMalloc)
return AlignedAlloc(Size, Align);
void *allocate(unsigned Size, unsigned Align) const;

return BPA.Allocate(Size, Align);
}
/// Allocate memory for an instruction using the module's internal allocator.
void *allocateInst(unsigned Size, unsigned Align) const;

/// Deallocate memory of an instruction.
void deallocateInst(SILInstruction *I);

/// \brief Looks up the llvm intrinsic ID and type for the builtin function.
///
Expand Down
21 changes: 15 additions & 6 deletions lib/SIL/SILBasicBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,25 @@ SILBasicBlock::SILBasicBlock(SILFunction *parent, SILBasicBlock *afterBB)
}
}
SILBasicBlock::~SILBasicBlock() {
// Notify the delete handlers that the instructions in this block are
// being deleted.
for (auto I = begin(), E = end(); I != E; ++I) {
getModule().notifyDeleteHandlers(&*I);
}

// Invalidate all of the basic block arguments.
for (auto *Arg : BBArgList) {
getModule().notifyDeleteHandlers(Arg);
}

dropAllReferences();

// Notify the delete handlers that the instructions in this block are
// being deleted.
auto &M = getModule();
for (auto I = begin(), E = end(); I != E;) {
auto Inst = &*I;
++I;
M.notifyDeleteHandlers(Inst);
erase(Inst);
}

// iplist's destructor is going to destroy the InstList.
InstList.clearAndLeakNodesUnsafely();
}

int SILBasicBlock::getDebugID() {
Expand Down Expand Up @@ -86,7 +93,9 @@ void SILBasicBlock::remove(SILInstruction *I) {
void SILBasicBlock::erase(SILInstruction *I) {
// Notify the delete handlers that this instruction is going away.
getModule().notifyDeleteHandlers(&*I);
auto *F = getParent();
InstList.erase(I);
F->getModule().deallocateInst(I);
}

/// This method unlinks 'self' from the containing SILFunction and deletes it.
Expand Down
19 changes: 17 additions & 2 deletions lib/SIL/SILFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,29 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage,
}

SILFunction::~SILFunction() {
#ifndef NDEBUG
// If the function is recursive, a function_ref inst inside of the function
// will give the function a non-zero ref count triggering the assertion. Thus
// we drop all instruction references before we erase.
// We also need to drop all references if instructions are allocated using
// an allocator that may recycle freed memory.
dropAllReferences();

auto &M = getModule();
for (auto &BB : *this) {
for (auto I = BB.begin(), E = BB.end(); I != E;) {
auto Inst = &*I;
++I;
SILInstruction::destroy(Inst);
// TODO: It is only safe to directly deallocate an
// instruction if this BB is being removed in scope
// of destructing a SILFunction.
M.deallocateInst(Inst);
}
BB.InstList.clearAndLeakNodesUnsafely();
}

assert(RefCount == 0 &&
"Function cannot be deleted while function_ref's still exist");
#endif
}

void SILFunction::setDeclContext(Decl *D) {
Expand Down
48 changes: 24 additions & 24 deletions lib/SIL/SILInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ AllocExistentialBoxInst *AllocExistentialBoxInst::create(
SILType ConcreteLoweredType, ArrayRef<ProtocolConformance *> Conformances,
SILFunction *F) {
SILModule &Mod = F->getModule();
void *Buffer = Mod.allocate(sizeof(AllocExistentialBoxInst),
alignof(AllocExistentialBoxInst));
void *Buffer = Mod.allocateInst(sizeof(AllocExistentialBoxInst),
alignof(AllocExistentialBoxInst));
for (ProtocolConformance *C : Conformances)
declareWitnessTable(Mod, C);
return ::new (Buffer) AllocExistentialBoxInst(Loc,
Expand All @@ -143,7 +143,7 @@ BuiltinInst *BuiltinInst::create(SILDebugLocation *Loc, Identifier Name,
ArrayRef<Substitution> Substitutions,
ArrayRef<SILValue> Args,
SILFunction &F) {
void *Buffer = F.getModule().allocate(
void *Buffer = F.getModule().allocateInst(
sizeof(BuiltinInst)
+ decltype(Operands)::getExtraSize(Args.size())
+ sizeof(Substitution) * Substitutions.size(),
Expand Down Expand Up @@ -190,7 +190,7 @@ bool swift::doesApplyCalleeHaveSemantics(SILValue callee, StringRef semantics) {
}

void *swift::allocateApplyInst(SILFunction &F, size_t size, size_t alignment) {
return F.getModule().allocate(size, alignment);
return F.getModule().allocateInst(size, alignment);
}

PartialApplyInst::PartialApplyInst(SILDebugLocation *Loc, SILValue Callee,
Expand Down Expand Up @@ -276,14 +276,14 @@ static unsigned getWordsForBitWidth(unsigned bits) {

template<typename INST>
static void *allocateLiteralInstWithTextSize(SILFunction &F, unsigned length) {
return F.getModule().allocate(sizeof(INST) + length, alignof(INST));
return F.getModule().allocateInst(sizeof(INST) + length, alignof(INST));
}

template<typename INST>
static void *allocateLiteralInstWithBitSize(SILFunction &F, unsigned bits) {
unsigned words = getWordsForBitWidth(bits);
return F.getModule().allocate(sizeof(INST) + sizeof(llvm::integerPart)*words,
alignof(INST));
return F.getModule().allocateInst(
sizeof(INST) + sizeof(llvm::integerPart)*words, alignof(INST));
}

IntegerLiteralInst::IntegerLiteralInst(SILDebugLocation *Loc, SILType Ty,
Expand Down Expand Up @@ -409,7 +409,7 @@ AssignInst::AssignInst(SILDebugLocation *Loc, SILValue Src, SILValue Dest)
MarkFunctionEscapeInst *
MarkFunctionEscapeInst::create(SILDebugLocation *Loc,
ArrayRef<SILValue> Elements, SILFunction &F) {
void *Buffer = F.getModule().allocate(sizeof(MarkFunctionEscapeInst) +
void *Buffer = F.getModule().allocateInst(sizeof(MarkFunctionEscapeInst) +
decltype(Operands)::getExtraSize(Elements.size()),
alignof(MarkFunctionEscapeInst));
return ::new(Buffer) MarkFunctionEscapeInst(Loc, Elements);
Expand Down Expand Up @@ -452,7 +452,7 @@ UnconditionalCheckedCastAddrInst::UnconditionalCheckedCastAddrInst(

StructInst *StructInst::create(SILDebugLocation *Loc, SILType Ty,
ArrayRef<SILValue> Elements, SILFunction &F) {
void *Buffer = F.getModule().allocate(sizeof(StructInst) +
void *Buffer = F.getModule().allocateInst(sizeof(StructInst) +
decltype(Operands)::getExtraSize(Elements.size()),
alignof(StructInst));
return ::new(Buffer) StructInst(Loc, Ty, Elements);
Expand All @@ -466,7 +466,7 @@ StructInst::StructInst(SILDebugLocation *Loc, SILType Ty,

TupleInst *TupleInst::create(SILDebugLocation *Loc, SILType Ty,
ArrayRef<SILValue> Elements, SILFunction &F) {
void *Buffer = F.getModule().allocate(sizeof(TupleInst) +
void *Buffer = F.getModule().allocateInst(sizeof(TupleInst) +
decltype(Operands)::getExtraSize(Elements.size()),
alignof(TupleInst));
return ::new(Buffer) TupleInst(Loc, Ty, Elements);
Expand Down Expand Up @@ -669,7 +669,7 @@ BranchInst *BranchInst::create(SILDebugLocation *Loc, SILBasicBlock *DestBB,
BranchInst *BranchInst::create(SILDebugLocation *Loc,
SILBasicBlock *DestBB, ArrayRef<SILValue> Args,
SILFunction &F) {
void *Buffer = F.getModule().allocate(sizeof(BranchInst) +
void *Buffer = F.getModule().allocateInst(sizeof(BranchInst) +
decltype(Operands)::getExtraSize(Args.size()),
alignof(BranchInst));
return ::new (Buffer) BranchInst(Loc, DestBB, Args);
Expand Down Expand Up @@ -703,7 +703,7 @@ CondBranchInst::create(SILDebugLocation *Loc, SILValue Condition,
Args.append(TrueArgs.begin(), TrueArgs.end());
Args.append(FalseArgs.begin(), FalseArgs.end());

void *Buffer = F.getModule().allocate(sizeof(CondBranchInst) +
void *Buffer = F.getModule().allocateInst(sizeof(CondBranchInst) +
decltype(Operands)::getExtraSize(Args.size()),
alignof(CondBranchInst));
return ::new (Buffer) CondBranchInst(Loc, Condition, TrueBB, FalseBB, Args,
Expand Down Expand Up @@ -853,7 +853,7 @@ SwitchValueInst *SwitchValueInst::create(
size_t bufSize = sizeof(SwitchValueInst) +
decltype(Operands)::getExtraSize(Cases.size()) +
sizeof(SILSuccessor) * numSuccessors;
void *buf = F.getModule().allocate(bufSize, alignof(SwitchValueInst));
void *buf = F.getModule().allocateInst(bufSize, alignof(SwitchValueInst));
return ::new (buf) SwitchValueInst(Loc, Operand, DefaultBB, Cases, BBs);
}

Expand Down Expand Up @@ -901,7 +901,7 @@ SelectValueInst::create(SILDebugLocation *Loc, SILValue Operand, SILType Type,

size_t bufSize = sizeof(SelectValueInst) + decltype(Operands)::getExtraSize(
CaseValuesAndResults.size());
void *buf = F.getModule().allocate(bufSize, alignof(SelectValueInst));
void *buf = F.getModule().allocateInst(bufSize, alignof(SelectValueInst));
return ::new (buf)
SelectValueInst(Loc, Operand, Type, DefaultResult, CaseValuesAndResults);
}
Expand Down Expand Up @@ -942,7 +942,7 @@ SELECT_ENUM_INST *SelectEnumInstBase::createSelectEnum(
// and `CaseBBs.size() + (DefaultBB ? 1 : 0)` values.
unsigned numCases = CaseValues.size();

void *buf = F.getModule().allocate(
void *buf = F.getModule().allocateInst(
sizeof(SELECT_ENUM_INST) + sizeof(EnumElementDecl*) * numCases
+ TailAllocatedOperandList<1>::getExtraSize(numCases + (bool)DefaultValue),
alignof(SELECT_ENUM_INST));
Expand Down Expand Up @@ -1063,7 +1063,7 @@ SWITCH_ENUM_INST *SwitchEnumInstBase::createSwitchEnum(
unsigned numCases = CaseBBs.size();
unsigned numSuccessors = numCases + (DefaultBB ? 1 : 0);

void *buf = F.getModule().allocate(sizeof(SWITCH_ENUM_INST)
void *buf = F.getModule().allocateInst(sizeof(SWITCH_ENUM_INST)
+ sizeof(EnumElementDecl*) * numCases
+ sizeof(SILSuccessor) * numSuccessors,
alignof(SWITCH_ENUM_INST));
Expand Down Expand Up @@ -1129,8 +1129,8 @@ DynamicMethodBranchInst *
DynamicMethodBranchInst::create(SILDebugLocation *Loc, SILValue Operand,
SILDeclRef Member, SILBasicBlock *HasMethodBB,
SILBasicBlock *NoMethodBB, SILFunction &F) {
void *Buffer = F.getModule().allocate(sizeof(DynamicMethodBranchInst),
alignof(DynamicMethodBranchInst));
void *Buffer = F.getModule().allocateInst(sizeof(DynamicMethodBranchInst),
alignof(DynamicMethodBranchInst));
return ::new (Buffer)
DynamicMethodBranchInst(Loc, Operand, Member, HasMethodBB, NoMethodBB);
}
Expand Down Expand Up @@ -1172,7 +1172,7 @@ WitnessMethodInst::create(SILDebugLocation *Loc, CanType LookupType,
SILValue OpenedExistential, bool Volatile) {
SILModule &Mod = F->getModule();
void *Buffer =
Mod.allocate(sizeof(WitnessMethodInst), alignof(WitnessMethodInst));
Mod.allocateInst(sizeof(WitnessMethodInst), alignof(WitnessMethodInst));

declareWitnessTable(Mod, Conformance);
return ::new (Buffer) WitnessMethodInst(Loc, LookupType, Conformance, Member,
Expand All @@ -1184,8 +1184,8 @@ InitExistentialAddrInst *InitExistentialAddrInst::create(
SILType ConcreteLoweredType, ArrayRef<ProtocolConformance *> Conformances,
SILFunction *F) {
SILModule &Mod = F->getModule();
void *Buffer = Mod.allocate(sizeof(InitExistentialAddrInst),
alignof(InitExistentialAddrInst));
void *Buffer = Mod.allocateInst(sizeof(InitExistentialAddrInst),
alignof(InitExistentialAddrInst));
for (ProtocolConformance *C : Conformances)
declareWitnessTable(Mod, C);
return ::new (Buffer) InitExistentialAddrInst(Loc, Existential,
Expand All @@ -1200,8 +1200,8 @@ InitExistentialRefInst::create(SILDebugLocation *Loc, SILType ExistentialType,
ArrayRef<ProtocolConformance *> Conformances,
SILFunction *F) {
SILModule &Mod = F->getModule();
void *Buffer = Mod.allocate(sizeof(InitExistentialRefInst),
alignof(InitExistentialRefInst));
void *Buffer = Mod.allocateInst(sizeof(InitExistentialRefInst),
alignof(InitExistentialRefInst));
for (ProtocolConformance *C : Conformances) {
if (!C)
continue;
Expand Down Expand Up @@ -1235,7 +1235,7 @@ InitExistentialMetatypeInst *InitExistentialMetatypeInst::create(
unsigned size = sizeof(InitExistentialMetatypeInst);
size += conformances.size() * sizeof(ProtocolConformance *);

void *buffer = M.allocate(size, alignof(InitExistentialMetatypeInst));
void *buffer = M.allocateInst(size, alignof(InitExistentialMetatypeInst));
for (ProtocolConformance *conformance : conformances)
if (!M.lookUpWitnessTable(conformance, false).first)
declareWitnessTable(M, conformance);
Expand Down
15 changes: 15 additions & 0 deletions lib/SIL/SILModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,21 @@ SILModule::~SILModule() {
delete (SILTypeListUniquingType*)TypeListUniquing;
}

void *SILModule::allocate(unsigned Size, unsigned Align) const {
if (getASTContext().LangOpts.UseMalloc)
return AlignedAlloc(Size, Align);

return BPA.Allocate(Size, Align);
}

void *SILModule::allocateInst(unsigned Size, unsigned Align) const {
return AlignedAlloc(Size, Align);
}

void SILModule::deallocateInst(SILInstruction *I) {
AlignedFree(I);
}

SILWitnessTable *
SILModule::createWitnessTableDeclaration(ProtocolConformance *C,
SILLinkage linkage) {
Expand Down