7
7
compileCall as compileBuiltinCall ,
8
8
compileAllocate ,
9
9
compileAbort ,
10
- compileIterateRoots
10
+ compileIterateRoots ,
11
+ ensureGCHook
11
12
} from "./builtins" ;
12
13
13
14
import {
@@ -6226,53 +6227,51 @@ export class Compiler extends DiagnosticEmitter {
6226
6227
/** Ensures that the specified string exists in static memory and returns a pointer to it. */
6227
6228
ensureStaticString ( stringValue : string ) : ExpressionRef {
6228
6229
var program = this . program ;
6229
- var module = this . module ;
6230
- var options = this . options ;
6231
- var stringSegments = this . stringSegments ;
6232
- var needsGCHeader = program . hasGC ;
6230
+ var hasGC = program . hasGC ;
6231
+ var gcHeaderSize = program . gcHeaderSize ;
6233
6232
6233
+ var stringInstance = assert ( program . stringInstance ) ;
6234
6234
var stringSegment : MemorySegment ;
6235
- var stringOffset : I64 ;
6236
- if ( ! stringSegments . has ( stringValue ) ) {
6237
- let stringLength = stringValue . length ;
6238
- let stringSize = 4 + stringLength * 2 ;
6239
- let offset = 0 ;
6240
- let gcHeaderSize = program . gcHeaderSize ;
6241
- if ( needsGCHeader ) {
6242
- stringSize += gcHeaderSize ;
6243
- offset += gcHeaderSize ;
6244
- }
6245
- let stringBuffer = new Uint8Array ( stringSize ) ;
6246
- stringBuffer [ offset ] = stringLength & 0xff ;
6247
- stringBuffer [ offset + 1 ] = ( stringLength >>> 8 ) & 0xff ;
6248
- stringBuffer [ offset + 2 ] = ( stringLength >>> 16 ) & 0xff ;
6249
- stringBuffer [ offset + 3 ] = ( stringLength >>> 24 ) & 0xff ;
6250
- for ( let i = 0 ; i < stringLength ; ++ i ) {
6251
- stringBuffer [ offset + 4 + i * 2 ] = stringValue . charCodeAt ( i ) & 0xff ;
6252
- stringBuffer [ offset + 5 + i * 2 ] = ( stringValue . charCodeAt ( i ) >>> 8 ) & 0xff ;
6253
- }
6254
- stringSegment = this . addMemorySegment ( stringBuffer , options . usizeType . byteSize ) ;
6255
- stringSegments . set ( stringValue , stringSegment ) ;
6256
- if ( needsGCHeader ) {
6257
- stringOffset = i64_add ( stringSegment . offset , i64_new ( gcHeaderSize , 0 ) ) ;
6235
+
6236
+ // if the string already exists, reuse it
6237
+ var segments = this . stringSegments ;
6238
+ if ( segments . has ( stringValue ) ) {
6239
+ stringSegment = < MemorySegment > segments . get ( stringValue ) ;
6240
+
6241
+ // otherwise create it
6242
+ } else {
6243
+ let length = stringValue . length ;
6244
+ let headerSize = ( stringInstance . currentMemoryOffset + 1 ) & ~ 1 ;
6245
+ let totalSize = headerSize + length * 2 ;
6246
+
6247
+ let buf : Uint8Array ;
6248
+ let pos : u32 ;
6249
+
6250
+ if ( hasGC ) {
6251
+ buf = new Uint8Array ( gcHeaderSize + totalSize ) ;
6252
+ pos = gcHeaderSize ;
6253
+ writeI32 ( ensureGCHook ( this , stringInstance ) , buf , program . gcHookOffset ) ;
6258
6254
} else {
6259
- stringOffset = stringSegment . offset ;
6255
+ buf = new Uint8Array ( totalSize ) ;
6256
+ pos = 0 ;
6260
6257
}
6261
- } else {
6262
- stringSegment = < MemorySegment > stringSegments . get ( stringValue ) ;
6263
- stringOffset = stringSegment . offset ;
6264
- }
6265
- if ( program . typesLookup . has ( "string" ) ) {
6266
- let stringType = < Type > program . typesLookup . get ( "string" ) ;
6267
- this . currentType = stringType ;
6268
- } else {
6269
- this . currentType = options . usizeType ;
6258
+ writeI32 ( length , buf , pos + stringInstance . offsetof ( "length" ) ) ;
6259
+ pos += headerSize ;
6260
+ for ( let i = 0 ; i < length ; ++ i ) {
6261
+ writeI16 ( stringValue . charCodeAt ( i ) , buf , pos + ( i << 1 ) ) ;
6262
+ }
6263
+ stringSegment = this . addMemorySegment ( buf ) ;
6264
+ segments . set ( stringValue , stringSegment ) ;
6270
6265
}
6271
- if ( options . isWasm64 ) {
6272
- return module . createI64 ( i64_low ( stringOffset ) , i64_high ( stringOffset ) ) ;
6266
+ var stringOffset = stringSegment . offset ;
6267
+ if ( hasGC ) stringOffset = i64_add ( stringOffset , i64_new ( gcHeaderSize ) ) ;
6268
+
6269
+ this . currentType = stringInstance . type ;
6270
+ if ( this . options . isWasm64 ) {
6271
+ return this . module . createI64 ( i64_low ( stringOffset ) , i64_high ( stringOffset ) ) ;
6273
6272
} else {
6274
- assert ( i64_is_i32 ( stringOffset ) ) ;
6275
- return module . createI32 ( i64_low ( stringOffset ) ) ;
6273
+ assert ( i64_is_u32 ( stringOffset ) ) ;
6274
+ return this . module . createI32 ( i64_low ( stringOffset ) ) ;
6276
6275
}
6277
6276
}
6278
6277
@@ -6282,52 +6281,32 @@ export class Compiler extends DiagnosticEmitter {
6282
6281
6283
6282
/** Ensures that the specified array exists in static memory and returns a pointer to it. */
6284
6283
ensureStaticArray ( elementType : Type , values : ExpressionRef [ ] ) : ExpressionRef {
6284
+ var program = this . program ;
6285
+ var hasGC = program . hasGC ;
6286
+ var gcHeaderSize = program . gcHeaderSize ;
6287
+
6285
6288
var length = values . length ;
6286
6289
var byteSize = elementType . byteSize ;
6287
6290
var byteLength = length * byteSize ;
6288
6291
var usizeTypeSize = this . options . usizeType . byteSize ;
6289
6292
6290
- // determine the size of the Array header
6291
- var arrayHeaderSize = ( usizeTypeSize + 4 + 7 ) & ~ 7 ; // .buffer_ + .length_ + alignment
6292
- var arrayTotalSize = arrayHeaderSize ;
6293
-
6294
- // determine the size of the ArrayBuffer
6295
- var bufferHeaderSize = ( 4 + 7 ) & ~ 7 ; // .byteLength + alignment
6296
- var bufferTotalSize = 1 << ( 32 - clz ( byteLength + bufferHeaderSize - 1 ) ) ; // see internals
6297
-
6298
- var program = this . program ;
6299
- var needsGC = program . hasGC ;
6300
- var gcHeaderSize = program . gcHeaderSize ;
6301
-
6302
- var offset = 0 ;
6303
- if ( needsGC ) {
6304
- offset += gcHeaderSize ; // start writing after GC header
6305
- arrayTotalSize += gcHeaderSize ;
6306
- bufferTotalSize += gcHeaderSize ;
6307
- }
6308
-
6309
- // create a compound segment holding both the the Array header and the ArrayBuffer
6310
- var buffer = new Uint8Array ( arrayHeaderSize + bufferTotalSize ) ;
6311
- var segment = this . addMemorySegment ( buffer ) ;
6312
-
6313
- // write the Array header first
6314
- if ( usizeTypeSize == 8 ) {
6315
- writeI64 ( i64_add ( segment . offset , i64_new ( arrayHeaderSize ) ) , buffer , offset ) ; // .buffer_
6316
- offset += 8 ;
6293
+ var buf : Uint8Array ;
6294
+ var pos : u32 ;
6295
+
6296
+ // create the backing ArrayBuffer segment
6297
+ var bufferInstance = assert ( program . arrayBufferInstance ) ;
6298
+ var bufferHeaderSize = ( bufferInstance . currentMemoryOffset + 7 ) & ~ 7 ;
6299
+ var bufferTotalSize = 1 << ( 32 - clz ( bufferHeaderSize + byteLength - 1 ) ) ;
6300
+ if ( hasGC ) {
6301
+ buf = new Uint8Array ( gcHeaderSize + bufferTotalSize ) ;
6302
+ pos = gcHeaderSize ;
6303
+ writeI32 ( ensureGCHook ( this , bufferInstance ) , buf , program . gcHookOffset ) ;
6317
6304
} else {
6318
- assert ( i64_is_u32 ( segment . offset ) ) ;
6319
- writeI32 ( i64_low ( segment . offset ) + arrayHeaderSize , buffer , offset ) ; // .buffer_
6320
- offset += 4 ;
6305
+ buf = new Uint8Array ( bufferTotalSize ) ;
6306
+ pos = 0 ;
6321
6307
}
6322
- writeI32 ( length , buffer , offset ) ; // .length_
6323
- offset += 4 ;
6324
- assert ( ( ( offset + 7 ) & ~ 7 ) == arrayTotalSize ) ; // incl. GC header if applicable
6325
-
6326
- // append the ArrayBuffer
6327
- offset = arrayTotalSize ;
6328
- if ( needsGC ) offset += gcHeaderSize ;
6329
- writeI32 ( byteLength , buffer , offset ) ; // .byteLength
6330
- offset += bufferHeaderSize ; // align
6308
+ writeI32 ( byteLength , buf , pos + bufferInstance . offsetof ( "byteLength" ) ) ;
6309
+ pos += bufferHeaderSize ;
6331
6310
var nativeType = elementType . toNativeType ( ) ;
6332
6311
switch ( nativeType ) {
6333
6312
case NativeType . I32 : {
@@ -6337,8 +6316,8 @@ export class Compiler extends DiagnosticEmitter {
6337
6316
let value = values [ i ] ;
6338
6317
assert ( getExpressionType ( value ) == nativeType ) ;
6339
6318
assert ( getExpressionId ( value ) == ExpressionId . Const ) ;
6340
- writeI8 ( getConstValueI32 ( value ) , buffer , offset ) ;
6341
- offset += 1 ;
6319
+ writeI8 ( getConstValueI32 ( value ) , buf , pos ) ;
6320
+ pos += 1 ;
6342
6321
}
6343
6322
break ;
6344
6323
}
@@ -6347,8 +6326,8 @@ export class Compiler extends DiagnosticEmitter {
6347
6326
let value = values [ i ] ;
6348
6327
assert ( getExpressionType ( value ) == nativeType ) ;
6349
6328
assert ( getExpressionId ( value ) == ExpressionId . Const ) ;
6350
- writeI16 ( getConstValueI32 ( value ) , buffer , offset ) ;
6351
- offset += 2 ;
6329
+ writeI16 ( getConstValueI32 ( value ) , buf , pos ) ;
6330
+ pos += 2 ;
6352
6331
}
6353
6332
break ;
6354
6333
}
@@ -6357,8 +6336,8 @@ export class Compiler extends DiagnosticEmitter {
6357
6336
let value = values [ i ] ;
6358
6337
assert ( getExpressionType ( value ) == nativeType ) ;
6359
6338
assert ( getExpressionId ( value ) == ExpressionId . Const ) ;
6360
- writeI32 ( getConstValueI32 ( value ) , buffer , offset ) ;
6361
- offset += 4 ;
6339
+ writeI32 ( getConstValueI32 ( value ) , buf , pos ) ;
6340
+ pos += 4 ;
6362
6341
}
6363
6342
break ;
6364
6343
}
@@ -6371,8 +6350,8 @@ export class Compiler extends DiagnosticEmitter {
6371
6350
let value = values [ i ] ;
6372
6351
assert ( getExpressionType ( value ) == nativeType ) ;
6373
6352
assert ( getExpressionId ( value ) == ExpressionId . Const ) ;
6374
- writeI64 ( i64_new ( getConstValueI64Low ( value ) , getConstValueI64High ( value ) ) , buffer , offset ) ;
6375
- offset += 8 ;
6353
+ writeI64 ( i64_new ( getConstValueI64Low ( value ) , getConstValueI64High ( value ) ) , buf , pos ) ;
6354
+ pos += 8 ;
6376
6355
}
6377
6356
break ;
6378
6357
}
@@ -6381,8 +6360,8 @@ export class Compiler extends DiagnosticEmitter {
6381
6360
let value = values [ i ] ;
6382
6361
assert ( getExpressionType ( value ) == nativeType ) ;
6383
6362
assert ( getExpressionId ( value ) == ExpressionId . Const ) ;
6384
- writeF32 ( getConstValueF32 ( value ) , buffer , offset ) ;
6385
- offset += 4 ;
6363
+ writeF32 ( getConstValueF32 ( value ) , buf , pos ) ;
6364
+ pos += 4 ;
6386
6365
}
6387
6366
break ;
6388
6367
}
@@ -6391,35 +6370,43 @@ export class Compiler extends DiagnosticEmitter {
6391
6370
let value = values [ i ] ;
6392
6371
assert ( getExpressionType ( value ) == nativeType ) ;
6393
6372
assert ( getExpressionId ( value ) == ExpressionId . Const ) ;
6394
- writeF64 ( getConstValueF64 ( value ) , buffer , offset ) ;
6395
- offset += 8 ;
6373
+ writeF64 ( getConstValueF64 ( value ) , buf , pos ) ;
6374
+ pos += 8 ;
6396
6375
}
6397
6376
break ;
6398
6377
}
6399
6378
default : assert ( false ) ;
6400
6379
}
6401
- assert ( offset <= arrayTotalSize + bufferTotalSize ) ; // might have empty trailing space
6402
-
6403
- var arrayPrototype = this . program . arrayPrototype ;
6404
- if ( arrayPrototype ) {
6405
- let arrayInstance = this . resolver . resolveClass ( arrayPrototype , [ elementType ] , null , ReportMode . REPORT ) ;
6406
- if ( ! arrayInstance ) {
6407
- this . currentType = this . options . usizeType ;
6408
- return this . module . createUnreachable ( ) ;
6409
- }
6410
- this . currentType = arrayInstance . type ;
6380
+ var bufferSegment = this . addMemorySegment ( buf ) ;
6381
+ var bufferOffset = bufferSegment . offset ;
6382
+ if ( hasGC ) bufferOffset = i64_add ( bufferOffset , i64_new ( gcHeaderSize ) ) ;
6383
+
6384
+ // create the Array segment and return a pointer to it
6385
+ var arrayPrototype = assert ( program . arrayPrototype ) ;
6386
+ var arrayInstance = assert ( this . resolver . resolveClass ( arrayPrototype , [ elementType ] ) ) ;
6387
+ var arrayHeaderSize = ( arrayInstance . currentMemoryOffset + 7 ) & ~ 7 ;
6388
+ if ( hasGC ) {
6389
+ buf = new Uint8Array ( gcHeaderSize + arrayHeaderSize ) ;
6390
+ pos = gcHeaderSize ;
6391
+ writeI32 ( ensureGCHook ( this , arrayInstance ) , buf , program . gcHookOffset ) ;
6411
6392
} else {
6412
- this . currentType = this . options . usizeType ;
6393
+ buf = new Uint8Array ( arrayHeaderSize ) ;
6394
+ pos = 0 ;
6413
6395
}
6414
-
6415
- // return a pointer at the array header (skip GC header if present)
6416
- var address = segment . offset ;
6417
- if ( needsGC ) address = i64_add ( address , i64_new ( gcHeaderSize , 0 ) ) ;
6396
+ var arraySegment = this . addMemorySegment ( buf ) ;
6397
+ var arrayOffset = arraySegment . offset ;
6398
+ if ( hasGC ) arrayOffset = i64_add ( arrayOffset , i64_new ( gcHeaderSize ) ) ;
6399
+ this . currentType = arrayInstance . type ;
6418
6400
if ( usizeTypeSize == 8 ) {
6419
- return this . module . createI64 ( i64_low ( address ) , i64_high ( address ) ) ;
6401
+ writeI64 ( bufferOffset , buf , pos + arrayInstance . offsetof ( "buffer_" ) ) ;
6402
+ writeI32 ( length , buf , pos + arrayInstance . offsetof ( "length_" ) ) ;
6403
+ return this . module . createI64 ( i64_low ( arrayOffset ) , i64_high ( arrayOffset ) ) ;
6420
6404
} else {
6421
- assert ( i64_is_u32 ( address ) ) ;
6422
- return this . module . createI32 ( i64_low ( address ) ) ;
6405
+ assert ( i64_is_u32 ( bufferOffset ) ) ;
6406
+ writeI32 ( i64_low ( bufferOffset ) , buf , pos + arrayInstance . offsetof ( "buffer_" ) ) ;
6407
+ writeI32 ( length , buf , pos + arrayInstance . offsetof ( "length_" ) ) ;
6408
+ assert ( i64_is_u32 ( arrayOffset ) ) ;
6409
+ return this . module . createI32 ( i64_low ( arrayOffset ) ) ;
6423
6410
}
6424
6411
}
6425
6412
@@ -6433,17 +6420,20 @@ export class Compiler extends DiagnosticEmitter {
6433
6420
6434
6421
// find out whether all elements are constant (array is static)
6435
6422
var length = expressions . length ;
6436
- var values = new Array < ExpressionRef > ( length ) ;
6423
+ var compiledValues = new Array < ExpressionRef > ( length ) ;
6424
+ var constantValues = new Array < ExpressionRef > ( length ) ;
6437
6425
var nativeElementType = elementType . toNativeType ( ) ;
6438
6426
var isStatic = true ;
6439
6427
for ( let i = 0 ; i < length ; ++ i ) {
6440
- values [ i ] = expressions [ i ]
6428
+ let expr = expressions [ i ]
6441
6429
? this . compileExpression ( < Expression > expressions [ i ] , elementType , ConversionKind . IMPLICIT , WrapMode . NONE )
6442
6430
: elementType . toNativeZero ( module ) ;
6431
+ compiledValues [ i ] = expr ;
6443
6432
if ( isStatic ) {
6444
- let expr = module . precomputeExpression ( values [ i ] ) ;
6433
+ expr = module . precomputeExpression ( compiledValues [ i ] ) ;
6445
6434
if ( getExpressionId ( expr ) == ExpressionId . Const ) {
6446
6435
assert ( getExpressionType ( expr ) == nativeElementType ) ;
6436
+ constantValues [ i ] = expr ;
6447
6437
} else {
6448
6438
if ( isConst ) {
6449
6439
this . warning (
@@ -6457,7 +6447,7 @@ export class Compiler extends DiagnosticEmitter {
6457
6447
}
6458
6448
6459
6449
// make a static array if possible
6460
- if ( isStatic ) return this . ensureStaticArray ( elementType , values ) ;
6450
+ if ( isStatic ) return this . ensureStaticArray ( elementType , constantValues ) ;
6461
6451
6462
6452
// otherwise obtain the array type
6463
6453
var arrayPrototype = assert ( this . program . arrayPrototype ) ;
@@ -6491,7 +6481,7 @@ export class Compiler extends DiagnosticEmitter {
6491
6481
stmts [ index ++ ] = this . makeCallDirect ( setter , [
6492
6482
module . createGetLocal ( tempLocal . index , nativeArrayType ) , // this
6493
6483
module . createI32 ( i ) ,
6494
- values [ i ]
6484
+ compiledValues [ i ]
6495
6485
] ) ;
6496
6486
}
6497
6487
assert ( index + 1 == stmts . length ) ;
0 commit comments