Skip to content

Commit 01c4134

Browse files
authored
Merge pull request shader-slang#417 from csyonghe/leakfix
Fix IR memory leaks.
2 parents 51cdcad + 4cf46e5 commit 01c4134

17 files changed

+282
-111
lines changed

slang.h

+1
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,7 @@ namespace slang
12371237
#include "source/slang/dxc-support.cpp"
12381238
#include "source/slang/emit.cpp"
12391239
#include "source/slang/ir.cpp"
1240+
#include "source/slang/memory_pool.cpp"
12401241
#include "source/slang/ir-legalize-types.cpp"
12411242
#include "source/slang/ir-ssa.cpp"
12421243
#include "source/slang/legalize-types.cpp"

source/core/smart-pointer.h

+14
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ namespace Slang
3535
referenceCount++;
3636
}
3737

38+
void decreaseReference()
39+
{
40+
--referenceCount;
41+
}
42+
3843
void releaseReference()
3944
{
4045
SLANG_ASSERT(referenceCount != 0);
@@ -192,6 +197,15 @@ namespace Slang
192197
return pointer;
193198
}
194199

200+
T* detach()
201+
{
202+
if (pointer)
203+
dynamic_cast<RefObject*>(pointer)->decreaseReference();
204+
auto rs = pointer;
205+
pointer = nullptr;
206+
return rs;
207+
}
208+
195209
private:
196210
T* pointer;
197211

source/slang/compiler.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ namespace Slang
179179
// This will only be valid/non-null after semantic
180180
// checking and IR generation are complete, so it
181181
// is not safe to use this field without testing for NULL.
182-
IRModule* irModule;
182+
RefPtr<IRModule> irModule;
183183
};
184184

185185
// A request to generate output in some target format
@@ -225,7 +225,7 @@ namespace Slang
225225
RefPtr<ModuleDecl> moduleDecl;
226226

227227
// The IR for the module
228-
IRModule* irModule = nullptr;
228+
RefPtr<IRModule> irModule = nullptr;
229229
};
230230

231231
class Session;
@@ -313,6 +313,8 @@ namespace Slang
313313
// Map from the logical name of a module to its definition
314314
Dictionary<Name*, RefPtr<LoadedModule>> mapNameToLoadedModules;
315315

316+
// The resulting specialized IR module for each entry point request
317+
List<RefPtr<IRModule>> compiledModules;
316318

317319
CompileRequest(Session* session);
318320

@@ -450,7 +452,6 @@ namespace Slang
450452

451453
Dictionary<int, RefPtr<Type>> builtinTypes;
452454
Dictionary<String, Decl*> magicDecls;
453-
List<RefPtr<Type>> canonicalTypes;
454455

455456
void initializeTypes();
456457

@@ -505,6 +506,7 @@ namespace Slang
505506
RefPtr<Scope> const& scope,
506507
String const& path,
507508
String const& source);
509+
~Session();
508510
};
509511

510512
}

source/slang/emit.cpp

+13-10
Original file line numberDiff line numberDiff line change
@@ -8084,17 +8084,17 @@ String emitEntryPoint(
80848084

80858085
EmitVisitor visitor(&context);
80868086

8087+
// We are going to create a fresh IR module that we will use to
8088+
// clone any code needed by the user's entry point.
8089+
IRSpecializationState* irSpecializationState = createIRSpecializationState(
8090+
entryPoint,
8091+
programLayout,
8092+
target,
8093+
targetRequest);
80878094
{
80888095
TypeLegalizationContext typeLegalizationContext;
80898096
typeLegalizationContext.session = entryPoint->compileRequest->mSession;
80908097

8091-
// We are going to create a fresh IR module that we will use to
8092-
// clone any code needed by the user's entry point.
8093-
IRSpecializationState* irSpecializationState = createIRSpecializationState(
8094-
entryPoint,
8095-
programLayout,
8096-
target,
8097-
targetRequest);
80988098
IRModule* irModule = getIRModule(irSpecializationState);
80998099

81008100
typeLegalizationContext.irModule = irModule;
@@ -8158,16 +8158,19 @@ String emitEntryPoint(
81588158
// TODO: do we want to emit directly from IR, or translate the
81598159
// IR back into AST for emission?
81608160
visitor.emitIRModule(&context, irModule);
8161+
8162+
// retain the specialized ir module, because the current
8163+
// GlobalGenericParamSubstitution implementation may reference ir objects
8164+
targetRequest->compileRequest->compiledModules.Add(irModule);
81618165
}
8166+
destroyIRSpecializationState(irSpecializationState);
81628167

81638168
String code = sharedContext.sb.ProduceString();
81648169
sharedContext.sb.Clear();
81658170

81668171
// Now that we've emitted the code for all the declaratiosn in the file,
81678172
// it is time to stich together the final output.
81688173

8169-
8170-
81718174
// There may be global-scope modifiers that we should emit now
81728175
visitor.emitGLSLPreprocessorDirectives(translationUnitSyntax);
81738176
String prefix = sharedContext.sb.ProduceString();
@@ -8189,7 +8192,7 @@ String emitEntryPoint(
81898192
finalResultBuilder << code;
81908193

81918194
String finalResult = finalResultBuilder.ProduceString();
8192-
8195+
81938196
return finalResult;
81948197
}
81958198

source/slang/ir-insts.h

+39-8
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ struct IRLayoutDecoration : IRDecoration
3333
enum { kDecorationOp = kIRDecorationOp_Layout };
3434

3535
RefPtr<Layout> layout;
36+
virtual void dispose() override
37+
{
38+
IRDecoration::dispose();
39+
layout = nullptr;
40+
}
3641
};
3742

3843
enum IRLoopControl
@@ -52,6 +57,11 @@ struct IRTargetSpecificDecoration : IRDecoration
5257
{
5358
// TODO: have a more structured representation of target specifiers
5459
String targetName;
60+
virtual void dispose()override
61+
{
62+
IRDecoration::dispose();
63+
targetName = String();
64+
}
5565
};
5666

5767
struct IRTargetDecoration : IRTargetSpecificDecoration
@@ -64,6 +74,11 @@ struct IRTargetIntrinsicDecoration : IRTargetSpecificDecoration
6474
enum { kDecorationOp = kIRDecorationOp_TargetIntrinsic };
6575

6676
String definition;
77+
virtual void dispose()override
78+
{
79+
IRTargetSpecificDecoration::dispose();
80+
definition = String();
81+
}
6782
};
6883

6984
//
@@ -73,6 +88,11 @@ struct IRTargetIntrinsicDecoration : IRTargetSpecificDecoration
7388
struct IRDeclRef : IRValue
7489
{
7590
DeclRef<Decl> declRef;
91+
virtual void dispose() override
92+
{
93+
IRValue::dispose();
94+
declRef = decltype(declRef)();
95+
}
7696
};
7797

7898
// An instruction that specializes another IR value
@@ -333,6 +353,13 @@ struct IRWitnessTable : IRGlobalValue
333353
RefPtr<GenericDecl> genericDecl;
334354
DeclRef<Decl> subTypeDeclRef, supTypeDeclRef;
335355
IRValueList<IRWitnessTableEntry> entries;
356+
virtual void dispose() override
357+
{
358+
IRGlobalValue::dispose();
359+
genericDecl = decltype(genericDecl)();
360+
subTypeDeclRef = decltype(subTypeDeclRef)();
361+
supTypeDeclRef = decltype(supTypeDeclRef)();
362+
}
336363
};
337364

338365
// An instruction that yields an undefined value.
@@ -610,22 +637,26 @@ struct IRBuilder
610637
UInt caseArgCount,
611638
IRValue* const* caseArgs);
612639

613-
614-
IRDecoration* addDecorationImpl(
615-
IRValue* value,
616-
UInt decorationSize,
617-
IRDecorationOp op);
618-
619640
template<typename T>
620641
T* addDecoration(IRValue* value, IRDecorationOp op)
621642
{
622-
return (T*) addDecorationImpl(value, sizeof(T), op);
643+
assert(getModule());
644+
auto decorationSize = sizeof(T);
645+
auto decoration = (T*)getModule()->memoryPool.allocZero(decorationSize);
646+
new(decoration)T();
647+
648+
decoration->op = op;
649+
650+
decoration->next = value->firstDecoration;
651+
value->firstDecoration = decoration;
652+
getModule()->irObjectsToFree.Add(decoration);
653+
return decoration;
623654
}
624655

625656
template<typename T>
626657
T* addDecoration(IRValue* value)
627658
{
628-
return (T*) addDecorationImpl(value, sizeof(T), IRDecorationOp(T::kDecorationOp));
659+
return addDecoration<T>(value, IRDecorationOp(T::kDecorationOp));
629660
}
630661

631662
IRHighLevelDeclDecoration* addHighLevelDeclDecoration(IRValue* value, Decl* decl);

0 commit comments

Comments
 (0)