@@ -8019,7 +8019,7 @@ export class Compiler extends DiagnosticEmitter {
8019
8019
let expr = expression
8020
8020
? module . precomputeExpression (
8021
8021
this . compileExpression ( < Expression > expression , elementType ,
8022
- Constraints . CONV_IMPLICIT
8022
+ Constraints . CONV_IMPLICIT | Constraints . WILL_RETAIN
8023
8023
)
8024
8024
)
8025
8025
: this . makeZero ( elementType ) ;
@@ -8125,7 +8125,9 @@ export class Compiler extends DiagnosticEmitter {
8125
8125
let valueExpr = values [ i ] ;
8126
8126
if ( isManaged ) {
8127
8127
// value = __retain(value)
8128
- valueExpr = this . makeRetain ( valueExpr ) ;
8128
+ if ( ! this . skippedAutoreleases . has ( valueExpr ) ) {
8129
+ valueExpr = this . makeRetain ( valueExpr ) ;
8130
+ }
8129
8131
}
8130
8132
// store<T>(tempData, value, immOffset)
8131
8133
stmts . push (
@@ -8146,10 +8148,10 @@ export class Compiler extends DiagnosticEmitter {
8146
8148
this . currentType = arrayType ;
8147
8149
var expr = module . flatten ( stmts , nativeArrayType ) ;
8148
8150
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 ) {
8152
8152
this . skippedAutoreleases . add ( expr ) ;
8153
+ } else {
8154
+ expr = this . makeAutorelease ( expr , arrayType , this . currentFlow ) ;
8153
8155
}
8154
8156
}
8155
8157
return expr ;
@@ -8162,6 +8164,7 @@ export class Compiler extends DiagnosticEmitter {
8162
8164
constraints : Constraints
8163
8165
) : ExpressionRef {
8164
8166
var module = this . module ;
8167
+ var flow = this . currentFlow ;
8165
8168
var program = this . program ;
8166
8169
8167
8170
// make sure this method is only called with a valid contextualType
@@ -8170,79 +8173,146 @@ export class Compiler extends DiagnosticEmitter {
8170
8173
var arrayType = arrayInstance . type ;
8171
8174
var elementType = assert ( arrayInstance . getTypeArgumentsTo ( program . fixedArrayPrototype ) ) [ 0 ] ;
8172
8175
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
8174
8180
var expressions = expression . elementExpressions ;
8175
8181
var length = expressions . length ;
8176
8182
var values = new Array < ExpressionRef > ( length ) ;
8177
8183
var nativeElementType = elementType . toNativeType ( ) ;
8184
+ var isStatic = true ;
8178
8185
for ( let i = 0 ; i < length ; ++ i ) {
8179
8186
let expression = expressions [ i ] ;
8180
8187
let expr : ExpressionRef ;
8181
8188
if ( expression ) {
8182
8189
expr = module . precomputeExpression (
8183
8190
this . compileExpression ( < Expression > expression , elementType ,
8184
- Constraints . CONV_IMPLICIT
8191
+ Constraints . CONV_IMPLICIT | Constraints . WILL_RETAIN
8185
8192
)
8186
8193
) ;
8187
8194
if ( getExpressionId ( expr ) == ExpressionId . Const ) {
8188
8195
assert ( getExpressionType ( expr ) == nativeElementType ) ;
8189
8196
} 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 ;
8196
8198
}
8197
8199
} else {
8198
8200
expr = this . makeZero ( elementType ) ;
8199
8201
}
8200
8202
values [ i ] = expr ;
8201
8203
}
8202
8204
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 ;
8206
8207
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 ) ;
8220
8211
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 ) ) ;
8237
8220
if ( constraints & Constraints . WILL_RETAIN ) {
8238
8221
this . skippedAutoreleases . add ( expr ) ;
8239
8222
} 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
+ }
8241
8249
}
8250
+ this . currentType = arrayType ;
8251
+ return expr ;
8242
8252
}
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
+ ) ;
8243
8263
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
+ }
8245
8314
}
8315
+ return expr ;
8246
8316
}
8247
8317
8248
8318
private compileObjectLiteral ( expression : ObjectLiteralExpression , contextualType : Type ) : ExpressionRef {
0 commit comments