Skip to content

Commit 1ec68fe

Browse files
authored
Fix local confusion in generated implicit setters (#1102)
1 parent 930778c commit 1ec68fe

8 files changed

+3098
-18
lines changed

src/compiler.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,17 +1440,37 @@ export class Compiler extends DiagnosticEmitter {
14401440
var nativeThisType = this.options.nativeSizeType;
14411441
var nativeValueType = type.toNativeType();
14421442
var module = this.module;
1443-
var valueExpr = module.local_get(1, nativeValueType);
1443+
var valueExpr: ExpressionRef;
1444+
var varTypes: NativeType[] | null = null;
14441445
if (type.isManaged) {
1445-
valueExpr = this.makeReplace(
1446-
module.load(type.byteSize, false,
1447-
module.local_get(0, nativeThisType),
1448-
nativeValueType, instance.memoryOffset
1446+
// Can't use makeReplace here since there's no corresponding flow, so
1447+
// 0: this, 1: value, 2: oldValue (temp)
1448+
valueExpr = module.block(null, [
1449+
module.if(
1450+
module.binary(nativeValueType == NativeType.I64 ? BinaryOp.NeI64 : BinaryOp.NeI32,
1451+
// value != (oldValue = this.field)
1452+
module.local_get(1, nativeValueType),
1453+
module.local_tee(2,
1454+
module.load(type.byteSize, false,
1455+
module.local_get(0, nativeThisType),
1456+
nativeValueType, instance.memoryOffset
1457+
)
1458+
)
1459+
),
1460+
module.block(null, [
1461+
module.drop(
1462+
this.makeRetain(module.local_get(1, nativeValueType))
1463+
),
1464+
this.makeRelease(module.local_get(2, nativeValueType))
1465+
])
14491466
),
1450-
valueExpr
1451-
);
1467+
module.local_get(1, nativeValueType)
1468+
], nativeValueType);
1469+
varTypes = [ nativeValueType ];
1470+
} else {
1471+
valueExpr = module.local_get(1, nativeValueType);
14521472
}
1453-
instance.setterRef = module.addFunction(instance.internalSetterName, createType([ nativeThisType, nativeValueType ]), NativeType.None, null,
1473+
instance.setterRef = module.addFunction(instance.internalSetterName, createType([ nativeThisType, nativeValueType ]), NativeType.None, varTypes,
14541474
module.store(type.byteSize,
14551475
module.local_get(0, nativeThisType),
14561476
valueExpr,
@@ -6702,7 +6722,14 @@ export class Compiler extends DiagnosticEmitter {
67026722
}
67036723

67046724
/** Makes a replace, retaining the new expression's value and releasing the old expression's value, in this order. */
6705-
makeReplace(oldExpr: ExpressionRef, newExpr: ExpressionRef, alreadyRetained: bool = false): ExpressionRef {
6725+
makeReplace(
6726+
/** Old value being replaced. */
6727+
oldExpr: ExpressionRef,
6728+
/** New value being assigned. */
6729+
newExpr: ExpressionRef,
6730+
/** Whether the new value is already retained. */
6731+
alreadyRetained: bool = false,
6732+
): ExpressionRef {
67066733
var module = this.module;
67076734
var flow = this.currentFlow;
67086735
var nativeSizeType = this.options.nativeSizeType;

tests/compiler/extends-recursive.optimized.wat

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@
1212
i32.load
1313
)
1414
(func $extends-recursive/Parent#set:child (; 1 ;) (param $0 i32) (param $1 i32)
15-
(local $2 i32)
1615
local.get $0
17-
local.get $1
18-
local.tee $0
1916
i32.load
2017
drop
2118
local.get $0
19+
local.get $1
2220
i32.store
2321
)
2422
)

tests/compiler/extends-recursive.untouched.wat

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,21 @@
2121
nop
2222
)
2323
(func $extends-recursive/Parent#set:child (; 3 ;) (param $0 i32) (param $1 i32)
24+
(local $2 i32)
2425
local.get $0
2526
local.get $1
26-
local.tee $0
2727
local.get $0
2828
i32.load
29-
local.tee $1
29+
local.tee $2
3030
i32.ne
3131
if
32-
local.get $0
33-
call $~lib/rt/stub/__retain
34-
local.set $0
3532
local.get $1
33+
call $~lib/rt/stub/__retain
34+
drop
35+
local.get $2
3636
call $~lib/rt/stub/__release
3737
end
38-
local.get $0
38+
local.get $1
3939
i32.store
4040
)
4141
)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
exports.postInstantiate = function(instance) {
2+
const exports = instance.exports;
3+
4+
// using an integer value
5+
var basic = exports["Basic#constructor"](0, 123); // retain $0
6+
(() => {
7+
var val = exports["Basic#get:val"](basic);
8+
if (val != 123) throw Error("invalid value");
9+
exports["Basic#set:val"](basic, 42);
10+
val = exports["Basic#get:val"](basic);
11+
if (val != 42) throw Error("invalid value");
12+
})();
13+
14+
// using a managed value
15+
var managed = exports["Managed#constructor"](0, basic); // retain $1
16+
(() => {
17+
var foo = exports["Managed#get:foo"](managed); // retain $2
18+
if (foo != basic) throw Error("invalid value");
19+
exports.__release(foo); // release $2
20+
})();
21+
(() => {
22+
var foo = exports["Basic#constructor"](0, 321); // retain $3
23+
exports["Managed#set:foo"](managed, foo);
24+
exports.__release(foo); // release $3
25+
var expectedFoo = foo;
26+
foo = exports["Managed#get:foo"](managed); // retain $4
27+
if (foo != expectedFoo) throw Error("invalid value");
28+
exports.__release(foo); // releae $4
29+
})();
30+
31+
// combining both
32+
(() => {
33+
var foo = exports["Managed#get:foo"](managed); // retain $5
34+
var val = exports["Basic#get:val"](foo);
35+
if (val != 321) throw Error("invalid value");
36+
exports.__release(foo); // release $5
37+
})();
38+
39+
exports.__release(basic); // release $0
40+
exports.__release(managed); // release $1
41+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"asc_flags": [
3+
"--runtime full",
4+
"--use ASC_RTRACE=1"
5+
]
6+
}

0 commit comments

Comments
 (0)