Skip to content

Commit 5b4866a

Browse files
committed
non-static support
1 parent 2b95f87 commit 5b4866a

16 files changed

+1374
-1051
lines changed

src/compiler.ts

Lines changed: 117 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8019,7 +8019,7 @@ export class Compiler extends DiagnosticEmitter {
80198019
let expr = expression
80208020
? module.precomputeExpression(
80218021
this.compileExpression(<Expression>expression, elementType,
8022-
Constraints.CONV_IMPLICIT
8022+
Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN
80238023
)
80248024
)
80258025
: this.makeZero(elementType);
@@ -8125,7 +8125,9 @@ export class Compiler extends DiagnosticEmitter {
81258125
let valueExpr = values[i];
81268126
if (isManaged) {
81278127
// value = __retain(value)
8128-
valueExpr = this.makeRetain(valueExpr);
8128+
if (!this.skippedAutoreleases.has(valueExpr)) {
8129+
valueExpr = this.makeRetain(valueExpr);
8130+
}
81298131
}
81308132
// store<T>(tempData, value, immOffset)
81318133
stmts.push(
@@ -8146,10 +8148,10 @@ export class Compiler extends DiagnosticEmitter {
81468148
this.currentType = arrayType;
81478149
var expr = module.flatten(stmts, nativeArrayType);
81488150
if (arrayType.isManaged) {
8149-
if (!(constraints & Constraints.WILL_RETAIN)) {
8150-
expr = this.makeAutorelease(expr, arrayType, this.currentFlow);
8151-
} else {
8151+
if (constraints & Constraints.WILL_RETAIN) {
81528152
this.skippedAutoreleases.add(expr);
8153+
} else {
8154+
expr = this.makeAutorelease(expr, arrayType, this.currentFlow);
81538155
}
81548156
}
81558157
return expr;
@@ -8162,6 +8164,7 @@ export class Compiler extends DiagnosticEmitter {
81628164
constraints: Constraints
81638165
): ExpressionRef {
81648166
var module = this.module;
8167+
var flow = this.currentFlow;
81658168
var program = this.program;
81668169

81678170
// make sure this method is only called with a valid contextualType
@@ -8170,79 +8173,146 @@ export class Compiler extends DiagnosticEmitter {
81708173
var arrayType = arrayInstance.type;
81718174
var elementType = assert(arrayInstance.getTypeArgumentsTo(program.fixedArrayPrototype))[0];
81728175

8173-
// compile value expressions and assert that all are compile-time constants
8176+
// block those here so compiling expressions doesn't conflict
8177+
var tempThis = flow.getTempLocal(this.options.usizeType);
8178+
8179+
// compile value expressions and check if all are compile-time constants
81748180
var expressions = expression.elementExpressions;
81758181
var length = expressions.length;
81768182
var values = new Array<ExpressionRef>(length);
81778183
var nativeElementType = elementType.toNativeType();
8184+
var isStatic = true;
81788185
for (let i = 0; i < length; ++i) {
81798186
let expression = expressions[i];
81808187
let expr: ExpressionRef;
81818188
if (expression) {
81828189
expr = module.precomputeExpression(
81838190
this.compileExpression(<Expression>expression, elementType,
8184-
Constraints.CONV_IMPLICIT
8191+
Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN
81858192
)
81868193
);
81878194
if (getExpressionId(expr) == ExpressionId.Const) {
81888195
assert(getExpressionType(expr) == nativeElementType);
81898196
} else {
8190-
this.error(
8191-
DiagnosticCode.Expression_must_be_a_compile_time_constant,
8192-
expression.range
8193-
);
8194-
this.currentType = arrayType;
8195-
return module.unreachable();
8197+
isStatic = false;
81968198
}
81978199
} else {
81988200
expr = this.makeZero(elementType);
81998201
}
82008202
values[i] = expr;
82018203
}
82028204

8203-
// make a static memory segment
8204-
var bufferSegment = this.addStaticBuffer(elementType, values, arrayInstance.id);
8205-
var bufferAddress = i64_add(bufferSegment.offset, i64_new(program.runtimeHeaderSize));
8205+
var isWasm64 = this.options.isWasm64;
8206+
var bufferSize = values.length << elementType.alignLog2;
82068207

8207-
// return the static buffer directly if assigned to a global
8208-
if (constraints & Constraints.PREFER_STATIC) {
8209-
let expr = this.options.isWasm64
8210-
? module.i64(i64_low(bufferAddress), i64_high(bufferAddress))
8211-
: module.i32(i64_low(bufferAddress));
8212-
if (constraints & Constraints.WILL_RETAIN) {
8213-
this.skippedAutoreleases.add(expr);
8214-
} else {
8215-
// not necessary since this is static data anyway
8216-
// expr = this.makeAutorelease(expr, arrayType, flow);
8217-
}
8218-
this.currentType = arrayType;
8219-
return expr;
8208+
// if the array is static, make a static arraybuffer segment
8209+
if (isStatic) {
8210+
flow.freeTempLocal(tempThis);
82208211

8221-
// otherwise allocate a new chunk of memory and return a copy of the buffer
8222-
} else {
8223-
let isWasm64 = this.options.isWasm64;
8224-
let size = values.length << elementType.alignLog2;
8225-
let expr = this.makeRetain(
8226-
this.makeCallDirect(program.allocBufferInstance, [
8227-
isWasm64
8228-
? module.i64(size)
8229-
: module.i32(size),
8230-
module.i32(arrayInstance.id),
8231-
isWasm64
8232-
? module.i64(i64_low(bufferAddress), i64_high(bufferAddress))
8233-
: module.i32(i64_low(bufferAddress))
8234-
], expression)
8235-
);
8236-
if (arrayType.isManaged) {
8212+
let bufferSegment = this.addStaticBuffer(elementType, values, arrayInstance.id);
8213+
let bufferAddress = i64_add(bufferSegment.offset, i64_new(program.runtimeHeaderSize));
8214+
8215+
// return the static buffer directly if assigned to a global
8216+
if (constraints & Constraints.PREFER_STATIC) {
8217+
let expr = this.options.isWasm64
8218+
? module.i64(i64_low(bufferAddress), i64_high(bufferAddress))
8219+
: module.i32(i64_low(bufferAddress));
82378220
if (constraints & Constraints.WILL_RETAIN) {
82388221
this.skippedAutoreleases.add(expr);
82398222
} else {
8240-
expr = this.makeAutorelease(expr, arrayType);
8223+
// not necessary since this is static data anyway
8224+
// expr = this.makeAutorelease(expr, arrayType, flow);
8225+
}
8226+
this.currentType = arrayType;
8227+
return expr;
8228+
8229+
// otherwise allocate a new chunk of memory and return a copy of the buffer
8230+
} else {
8231+
// __allocBuffer(bufferSize, id, buffer)
8232+
let expr = this.makeRetain(
8233+
this.makeCallDirect(program.allocBufferInstance, [
8234+
isWasm64
8235+
? module.i64(bufferSize)
8236+
: module.i32(bufferSize),
8237+
module.i32(arrayInstance.id),
8238+
isWasm64
8239+
? module.i64(i64_low(bufferAddress), i64_high(bufferAddress))
8240+
: module.i32(i64_low(bufferAddress))
8241+
], expression)
8242+
);
8243+
if (arrayType.isManaged) {
8244+
if (constraints & Constraints.WILL_RETAIN) {
8245+
this.skippedAutoreleases.add(expr);
8246+
} else {
8247+
expr = this.makeAutorelease(expr, arrayType);
8248+
}
82418249
}
8250+
this.currentType = arrayType;
8251+
return expr;
82428252
}
8253+
}
8254+
8255+
// otherwise compile an explicit instantiation with indexed sets
8256+
var setter = arrayInstance.lookupOverload(OperatorKind.INDEXED_SET, true);
8257+
if (!setter) {
8258+
flow.freeTempLocal(tempThis);
8259+
this.error(
8260+
DiagnosticCode.Index_signature_in_type_0_only_permits_reading,
8261+
expression.range, arrayInstance.internalName
8262+
);
82438263
this.currentType = arrayType;
8244-
return expr;
8264+
return module.unreachable();
8265+
}
8266+
var nativeArrayType = arrayType.toNativeType();
8267+
8268+
var stmts = new Array<ExpressionRef>();
8269+
// tempThis = __allocBuffer(bufferSize, classId)
8270+
stmts.push(
8271+
module.local_set(tempThis.index,
8272+
this.makeRetain(
8273+
this.makeCallDirect(program.allocBufferInstance, [
8274+
isWasm64
8275+
? module.i64(bufferSize)
8276+
: module.i32(bufferSize),
8277+
module.i32(arrayInstance.id)
8278+
], expression)
8279+
)
8280+
)
8281+
);
8282+
var isManaged = elementType.isManaged;
8283+
for (let i = 0, alignLog2 = elementType.alignLog2; i < length; ++i) {
8284+
let valueExpr = values[i];
8285+
if (isManaged) {
8286+
// value = __retain(value)
8287+
if (!this.skippedAutoreleases.has(valueExpr)) {
8288+
valueExpr = this.makeRetain(valueExpr);
8289+
}
8290+
}
8291+
// store<T>(tempThis, value, immOffset)
8292+
stmts.push(
8293+
module.store(elementType.byteSize,
8294+
module.local_get(tempThis.index, nativeArrayType),
8295+
valueExpr,
8296+
nativeElementType,
8297+
i << alignLog2
8298+
)
8299+
);
8300+
}
8301+
// -> tempThis
8302+
stmts.push(
8303+
module.local_get(tempThis.index, nativeArrayType)
8304+
);
8305+
flow.freeTempLocal(tempThis);
8306+
this.currentType = arrayType;
8307+
var expr = module.flatten(stmts, nativeArrayType);
8308+
if (arrayType.isManaged) {
8309+
if (constraints & Constraints.WILL_RETAIN) {
8310+
this.skippedAutoreleases.add(expr);
8311+
} else {
8312+
expr = this.makeAutorelease(expr, arrayType, this.currentFlow);
8313+
}
82458314
}
8315+
return expr;
82468316
}
82478317

82488318
private compileObjectLiteral(expression: ObjectLiteralExpression, contextualType: Type): ExpressionRef {

std/assembly/fixedarray.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,18 @@ export class FixedArray<T> {
145145
toString(): string {
146146
return this.join();
147147
}
148+
149+
// RT integration
150+
151+
@unsafe private __visit_impl(cookie: u32): void {
152+
if (isManaged<T>()) {
153+
let cur = changetype<usize>(this);
154+
let end = cur + changetype<BLOCK>(changetype<usize>(this) - BLOCK_OVERHEAD).rtSize;
155+
while (cur < end) {
156+
let val = load<usize>(cur);
157+
if (val) __visit(val, cookie);
158+
cur += sizeof<usize>();
159+
}
160+
}
161+
}
148162
}

tests/compiler/infer-array.untouched.wat

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,7 +1704,6 @@
17041704
(local $2 f32)
17051705
(local $3 i32)
17061706
(local $4 i32)
1707-
(local $5 i32)
17081707
global.get $~lib/heap/__heap_base
17091708
i32.const 15
17101709
i32.add
@@ -1939,8 +1938,6 @@
19391938
i32.const 576
19401939
call $~lib/rt/__allocArray
19411940
call $~lib/rt/stub/__retain
1942-
local.tee $3
1943-
call $~lib/rt/stub/__retain
19441941
i32.store
19451942
local.get $4
19461943
i32.const 1
@@ -1949,15 +1946,9 @@
19491946
i32.const 608
19501947
call $~lib/rt/__allocArray
19511948
call $~lib/rt/stub/__retain
1952-
local.tee $5
1953-
call $~lib/rt/stub/__retain
19541949
i32.store offset=4
19551950
local.get $1
19561951
local.set $4
1957-
local.get $3
1958-
call $~lib/rt/stub/__release
1959-
local.get $5
1960-
call $~lib/rt/stub/__release
19611952
local.get $4
19621953
call $~lib/rt/stub/__release
19631954
local.get $1

tests/compiler/resolve-ternary.optimized.wat

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2606,33 +2606,35 @@
26062606
end
26072607
)
26082608
(func $~lib/rt/__visit_members (; 35 ;) (param $0 i32)
2609-
block $switch$1$default
2610-
block $switch$1$case$4
2611-
block $switch$1$case$2
2612-
local.get $0
2613-
i32.const 8
2614-
i32.sub
2615-
i32.load
2616-
br_table $switch$1$case$2 $switch$1$case$2 $switch$1$case$4 $switch$1$case$2 $switch$1$case$2 $switch$1$case$2 $switch$1$default
2609+
block $folding-inner0
2610+
block $switch$1$default
2611+
block $switch$1$case$4
2612+
block $switch$1$case$2
2613+
local.get $0
2614+
i32.const 8
2615+
i32.sub
2616+
i32.load
2617+
br_table $switch$1$case$2 $switch$1$case$2 $switch$1$case$4 $folding-inner0 $folding-inner0 $folding-inner0 $switch$1$default
2618+
end
2619+
return
26172620
end
2618-
return
2619-
end
2620-
local.get $0
2621-
i32.load
2622-
local.tee $0
2623-
if
26242621
local.get $0
2625-
i32.const 1524
2626-
i32.ge_u
2622+
i32.load
2623+
local.tee $0
26272624
if
26282625
local.get $0
2629-
i32.const 16
2630-
i32.sub
2631-
call $~lib/rt/pure/decrement
2626+
i32.const 1524
2627+
i32.ge_u
2628+
if
2629+
local.get $0
2630+
i32.const 16
2631+
i32.sub
2632+
call $~lib/rt/pure/decrement
2633+
end
26322634
end
2635+
return
26332636
end
2634-
return
2637+
unreachable
26352638
end
2636-
unreachable
26372639
)
26382640
)

0 commit comments

Comments
 (0)