Skip to content

Commit 03e5d31

Browse files
fixed implementation of Disposable (#83)
* added implementation of disposal for return op * added more test for disposable
1 parent d87090f commit 03e5d31

File tree

6 files changed

+132
-36
lines changed

6 files changed

+132
-36
lines changed

tsc/include/TypeScript/MLIRLogic/MLIRGenContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ struct GenContext
164164
ArrayRef<mlir::Value> callOperands;
165165
int *state;
166166
bool disableSpreadParams;
167+
const GenContext* parentBlockContext;
168+
bool isLoop;
169+
std::string loopLabel;
167170
};
168171

169172
struct ValueOrLogicalResult

tsc/lib/TypeScript/MLIRGen.cpp

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ enum class TypeProvided
112112
Yes
113113
};
114114

115+
enum class DisposeDepth
116+
{
117+
CurrentScope,
118+
LoopScope,
119+
FullStack
120+
};
121+
115122
typedef std::tuple<mlir::Type, mlir::Value, TypeProvided> TypeValueInitType;
116123
typedef std::function<TypeValueInitType(mlir::Location, const GenContext &)> TypeValueInitFuncType;
117124

@@ -1010,6 +1017,7 @@ class MLIRGenImpl
10101017

10111018
SymbolTableScopeT varScope(symbolTable);
10121019
GenContext genContextUsing(genContext);
1020+
genContextUsing.parentBlockContext = &genContext;
10131021

10141022
auto usingVars = std::make_unique<SmallVector<ts::VariableDeclarationDOM::TypePtr>>();
10151023
genContextUsing.usingVars = usingVars.get();
@@ -1061,21 +1069,38 @@ class MLIRGenImpl
10611069
}
10621070

10631071
// we need to call dispose for those which are in "using"
1064-
for (auto vi : *genContextUsing.usingVars)
1065-
{
1066-
auto varInTable = symbolTable.lookup(vi->getName());
1067-
auto callResult = mlirGenCallThisMethod(location, varInTable.first, SYMBOL_DISPOSE, undefined, {}, genContext);
1068-
EXIT_IF_FAILED(callResult);
1069-
}
1070-
1071-
genContextUsing.usingVars = nullptr;
1072+
EXIT_IF_FAILED(mlirGenDisposable(location, DisposeDepth::CurrentScope, {}, &genContextUsing));
10721073

10731074
// clear states to be able to run second time
10741075
clearState(blockAST->statements);
10751076

10761077
return mlir::success();
10771078
}
10781079

1080+
mlir::LogicalResult mlirGenDisposable(mlir::Location location, DisposeDepth disposeDepth, std::string loopLabel, const GenContext* genContext)
1081+
{
1082+
if (genContext->usingVars != nullptr)
1083+
{
1084+
for (auto vi : *genContext->usingVars)
1085+
{
1086+
auto varInTable = symbolTable.lookup(vi->getName());
1087+
auto callResult = mlirGenCallThisMethod(location, varInTable.first, SYMBOL_DISPOSE, undefined, {}, *genContext);
1088+
EXIT_IF_FAILED(callResult);
1089+
}
1090+
1091+
const_cast<GenContext *>(genContext)->usingVars = nullptr;
1092+
1093+
auto continueIntoDepth = disposeDepth == DisposeDepth::FullStack
1094+
|| disposeDepth == DisposeDepth::LoopScope && genContext->isLoop && genContext->loopLabel != loopLabel;
1095+
if (continueIntoDepth)
1096+
{
1097+
EXIT_IF_FAILED(mlirGenDisposable(location, disposeDepth, {}, genContext->parentBlockContext));
1098+
}
1099+
}
1100+
1101+
return mlir::success();
1102+
}
1103+
10791104
mlir::LogicalResult mlirGen(Statement statementAST, const GenContext &genContext)
10801105
{
10811106
auto kind = (SyntaxKind)statementAST;
@@ -5390,10 +5415,14 @@ class MLIRGenImpl
53905415
}
53915416

53925417
VALIDATE(expressionValue, location)
5393-
5418+
5419+
EXIT_IF_FAILED(mlirGenDisposable(location, DisposeDepth::FullStack, {}, &genContext));
5420+
53945421
return mlirGenReturnValue(location, expressionValue, false, genContext);
53955422
}
53965423

5424+
EXIT_IF_FAILED(mlirGenDisposable(location, DisposeDepth::FullStack, {}, &genContext));
5425+
53975426
builder.create<mlir_ts::ReturnOp>(location);
53985427
return mlir::success();
53995428
}
@@ -6102,6 +6131,9 @@ class MLIRGenImpl
61026131
label = "";
61036132
}
61046133

6134+
const_cast<GenContext &>(genContext).isLoop = true;
6135+
const_cast<GenContext &>(genContext).loopLabel = label;
6136+
61056137
/*auto *cond =*/builder.createBlock(&doWhileOp.getCond(), {}, types);
61066138
/*auto *body =*/builder.createBlock(&doWhileOp.getBody(), {}, types);
61076139

@@ -6143,6 +6175,9 @@ class MLIRGenImpl
61436175
label = "";
61446176
}
61456177

6178+
const_cast<GenContext &>(genContext).isLoop = true;
6179+
const_cast<GenContext &>(genContext).loopLabel = label;
6180+
61466181
/*auto *cond =*/builder.createBlock(&whileOp.getCond(), {}, types);
61476182
/*auto *body =*/builder.createBlock(&whileOp.getBody(), {}, types);
61486183

@@ -6219,6 +6254,9 @@ class MLIRGenImpl
62196254
label = "";
62206255
}
62216256

6257+
const_cast<GenContext &>(genContext).isLoop = true;
6258+
const_cast<GenContext &>(genContext).loopLabel = label;
6259+
62226260
/*auto *cond =*/builder.createBlock(&forOp.getCond(), {}, types);
62236261
/*auto *body =*/builder.createBlock(&forOp.getBody(), {}, types);
62246262
/*auto *incr =*/builder.createBlock(&forOp.getIncr(), {}, types);
@@ -6581,6 +6619,8 @@ class MLIRGenImpl
65816619

65826620
auto label = MLIRHelper::getName(continueStatementAST->label);
65836621

6622+
EXIT_IF_FAILED(mlirGenDisposable(location, DisposeDepth::LoopScope, label, &genContext));
6623+
65846624
builder.create<mlir_ts::ContinueOp>(location, builder.getStringAttr(label));
65856625
return mlir::success();
65866626
}
@@ -6591,6 +6631,8 @@ class MLIRGenImpl
65916631

65926632
auto label = MLIRHelper::getName(breakStatementAST->label);
65936633

6634+
EXIT_IF_FAILED(mlirGenDisposable(location, DisposeDepth::LoopScope, label, &genContext));
6635+
65946636
builder.create<mlir_ts::BreakOp>(location, builder.getStringAttr(label));
65956637
return mlir::success();
65966638
}

tsc/test/tester/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ add_test(NAME test-compile-00-decorators COMMAND test-runner "${PROJECT_SOURCE_D
287287
add_test(NAME test-compile-00-conditional-type COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00conditional_type.ts")
288288
add_test(NAME test-compile-00-disposable COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00disposable.ts")
289289
add_test(NAME test-compile-01-disposable COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/01disposable.ts")
290+
add_test(NAME test-compile-02-disposable COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/02disposable.ts")
290291
add_test(NAME test-compile-01-arguments COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/01arguments.ts")
291292
add_test(NAME test-compile-02-numbers COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/02numbers.ts")
292293
add_test(NAME test-compile-05-strings COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/05strings.ts")
@@ -567,6 +568,7 @@ add_test(NAME test-jit-00-decorators COMMAND test-runner -jit "${PROJECT_SOURCE_
567568
add_test(NAME test-jit-00-conditional-type COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00conditional_type.ts")
568569
add_test(NAME test-jit-00-disposable COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00disposable.ts")
569570
add_test(NAME test-jit-01-disposable COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/01disposable.ts")
571+
add_test(NAME test-jit-02-disposable COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/02disposable.ts")
570572
add_test(NAME test-jit-01-arguments COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/01arguments.ts")
571573
add_test(NAME test-jit-02-numbers COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/02numbers.ts")
572574
add_test(NAME test-jit-05-strings COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/05strings.ts")

tsc/test/tester/tests/00disposable.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
let called = false;
22

33
function main() {
4-
doSomeWork();
4+
doSomeWork1();
5+
6+
assert(called, "Disposable is not called");
7+
8+
called = false;
9+
10+
{
11+
using file = new TempFile(".some_temp_file");
12+
}
513

614
assert(called, "Disposable is not called");
715

@@ -12,14 +20,13 @@ interface Disposable {
1220
[Symbol.dispose](): void;
1321
}
1422

15-
function doSomeWork() {
23+
function doSomeWork1() {
1624
const file = new TempFile(".some_temp_file");
1725
try {
1826
// ...
1927
}
2028
finally {
2129
file[Symbol.dispose]();
22-
called = true;
2330
}
2431
}
2532

@@ -34,6 +41,7 @@ class TempFile implements Disposable {
3441
[Symbol.dispose]() {
3542
// Close the file and delete it.
3643
this.#handle = 0;
44+
called = true;
3745
print("dispose");
3846
}
3947
}

tsc/test/tester/tests/01disposable.ts

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,34 @@
1-
let called = false;
1+
let count = 0;
22

3-
function main()
4-
{
5-
{
6-
using file = new TempFile(".some_temp_file");
3+
function loggy(id: string) {
4+
print(`Creating ${id}`);
5+
return {
6+
[Symbol.dispose]() {
7+
print(`Disposing ${id}`);
8+
count++;
9+
}
710
}
8-
9-
assert(called, "Disposable is not called");
10-
print("done.");
1111
}
1212

13-
interface Disposable {
14-
[Symbol.dispose](): void;
13+
function func() {
14+
using a = loggy("a");
15+
using b = loggy("b");
16+
{
17+
using c = loggy("c");
18+
using d = loggy("d");
19+
}
20+
using e = loggy("e");
21+
return;
22+
// Unreachable.
23+
// Never created, never disposed.
24+
using f = loggy("f");
1525
}
1626

17-
class TempFile implements Disposable {
18-
#path: string;
19-
#handle: number;
20-
constructor(path: string) {
21-
this.#path = path;
22-
this.#handle = 1;
23-
}
24-
// other methods
25-
[Symbol.dispose]() {
26-
// Close the file and delete it.
27-
this.#handle = 0;
28-
print("dispose");
29-
called = true;
30-
}
27+
function main()
28+
{
29+
func();
30+
31+
assert(count == 5, "Not all 'dispose' called");
32+
33+
print("done.");
3134
}

tsc/test/tester/tests/02disposable.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
let count_created = 0;
2+
let count_disp = 0;
3+
function loggy(id: string) {
4+
print(`Creating ${id}`);
5+
count_created++;
6+
return {
7+
[Symbol.dispose]() {
8+
print(`Disposing ${id}`);
9+
count_disp++;
10+
}
11+
}
12+
}
13+
14+
function func(i = 0) {
15+
using a = loggy("a");
16+
cont1: while (i-- > 0)
17+
{
18+
using b = loggy("b");
19+
let j = 3;
20+
while (j-- > 0) {
21+
using c = loggy("c");
22+
continue cont1;
23+
}
24+
}
25+
26+
// Unreachable.
27+
// Never created, never disposed.
28+
using f = loggy("f");
29+
}
30+
31+
function main()
32+
{
33+
func(3);
34+
35+
assert(count_created == count_disp, "not equal create-dispose");
36+
37+
print("done.");
38+
}

0 commit comments

Comments
 (0)