58
58
import org .teavm .backend .wasm .model .expression .WasmArrayLength ;
59
59
import org .teavm .backend .wasm .model .expression .WasmArrayNewDefault ;
60
60
import org .teavm .backend .wasm .model .expression .WasmArrayNewFixed ;
61
+ import org .teavm .backend .wasm .model .expression .WasmArraySet ;
61
62
import org .teavm .backend .wasm .model .expression .WasmBlock ;
62
63
import org .teavm .backend .wasm .model .expression .WasmCall ;
63
64
import org .teavm .backend .wasm .model .expression .WasmCallReference ;
@@ -169,15 +170,18 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
169
170
private int enumConstantsFunctionOffset = -1 ;
170
171
private int arrayLengthOffset = -1 ;
171
172
private int arrayGetOffset = -1 ;
173
+ private int arraySetOffset = -1 ;
172
174
private int arrayCopyOffset = -1 ;
173
175
private int cloneOffset = -1 ;
174
176
private int servicesOffset = -1 ;
175
177
private int throwableNativeOffset = -1 ;
176
178
private WasmStructure arrayVirtualTableStruct ;
177
179
private WasmFunction arrayGetObjectFunction ;
180
+ private WasmFunction arraySetObjectFunction ;
178
181
private WasmFunction arrayLengthObjectFunction ;
179
182
private WasmFunction arrayCopyObjectFunction ;
180
183
private WasmFunctionType arrayGetType ;
184
+ private WasmFunctionType arraySetType ;
181
185
private WasmFunctionType arrayLengthType ;
182
186
private WasmFunctionType arrayCopyType ;
183
187
private List <WasmFunction > multiArrayFunctions = new ArrayList <>();
@@ -943,6 +947,10 @@ private void applyArrayVirtualTable(WasmExpression[] entries, ValueType.Array ty
943
947
var getFunction = getArrayGetFunction (itemType );
944
948
entries [arrayGetOffset ] = new WasmFunctionReference (getFunction );
945
949
}
950
+ if (info .arraySet ()) {
951
+ var setFunction = getArraySetFunction (itemType );
952
+ entries [arraySetOffset ] = new WasmFunctionReference (setFunction );
953
+ }
946
954
if (info .arrayCopy ()) {
947
955
var copyFunction = getArrayCopyFunction (itemType );
948
956
entries [arrayCopyOffset ] = new WasmFunctionReference (copyFunction );
@@ -979,6 +987,11 @@ private void fillArrayVirtualTableMethods(ValueType type, List<WasmExpression> t
979
987
target .add (new WasmStructSet (structure , new WasmGetGlobal (global ), arrayGetOffset ,
980
988
new WasmFunctionReference (getFunction )));
981
989
}
990
+ if (info .arraySet ()) {
991
+ var setFunction = getArraySetFunction (itemType );
992
+ target .add (new WasmStructSet (structure , new WasmGetGlobal (global ), arraySetOffset ,
993
+ new WasmFunctionReference (setFunction )));
994
+ }
982
995
if (info .arrayCopy ()) {
983
996
var copyFunction = getArrayCopyFunction (itemType );
984
997
target .add (new WasmStructSet (structure , new WasmGetGlobal (global ), arrayCopyOffset ,
@@ -1054,8 +1067,7 @@ private WasmFunction getArrayGetObjectFunction() {
1054
1067
1055
1068
private WasmFunction generateArrayGetPrimitiveFunction (PrimitiveType type ) {
1056
1069
var function = new WasmFunction (getArrayGetType ());
1057
- function .setName (names .topLevel ("Array<" + names .suggestForType (ValueType .primitive (type ))
1058
- + ">::get" ));
1070
+ function .setName (names .topLevel ("Array<" + names .suggestForType (ValueType .primitive (type )) + ">::get" ));
1059
1071
module .functions .add (function );
1060
1072
function .setReferenced (true );
1061
1073
@@ -1123,13 +1135,120 @@ private WasmFunction generateArrayGetPrimitiveFunction(PrimitiveType type) {
1123
1135
return function ;
1124
1136
}
1125
1137
1138
+ private WasmFunction getArraySetFunction (ValueType itemType ) {
1139
+ if (itemType instanceof ValueType .Primitive ) {
1140
+ return generateArraySetPrimitiveFunction (((ValueType .Primitive ) itemType ).getKind ());
1141
+ }
1142
+ return getArraySetObjectFunction ();
1143
+ }
1144
+
1126
1145
private WasmFunction getArrayCopyFunction (ValueType itemType ) {
1127
1146
if (itemType instanceof ValueType .Primitive ) {
1128
1147
return createArrayCopyFunction (itemType );
1129
1148
}
1130
1149
return getArrayCopyObjectFunction ();
1131
1150
}
1132
1151
1152
+ private WasmFunction getArraySetObjectFunction () {
1153
+ if (arraySetObjectFunction == null ) {
1154
+ arraySetObjectFunction = new WasmFunction (getArraySetType ());
1155
+ arraySetObjectFunction .setName (names .topLevel ("Array<" + names .suggestForClass ("java.lang.Object" )
1156
+ + "::set" ));
1157
+ module .functions .add (arraySetObjectFunction );
1158
+ arraySetObjectFunction .setReferenced (true );
1159
+
1160
+ var arrayStruct = getClassInfo (ValueType .arrayOf (OBJECT_TYPE )).structure ;
1161
+ var arrayDataTypeRef = (WasmType .CompositeReference ) arrayStruct .getFields ()
1162
+ .get (ARRAY_DATA_FIELD_OFFSET ).getUnpackedType ();
1163
+ var arrayDataType = (WasmArray ) arrayDataTypeRef .composite ;
1164
+ var selfLocal = new WasmLocal (standardClasses .classClass ().getType (), "this" );
1165
+ var objectLocal = new WasmLocal (standardClasses .objectClass ().getType (), "object" );
1166
+ var indexLocal = new WasmLocal (WasmType .INT32 , "index" );
1167
+ var valueLocal = new WasmLocal (standardClasses .objectClass ().getType (), "value" );
1168
+ arraySetObjectFunction .add (selfLocal );
1169
+ arraySetObjectFunction .add (objectLocal );
1170
+ arraySetObjectFunction .add (indexLocal );
1171
+ arraySetObjectFunction .add (valueLocal );
1172
+
1173
+ var array = new WasmCast (new WasmGetLocal (objectLocal ), arrayStruct .getNonNullReference ());
1174
+ var arrayData = new WasmStructGet (arrayStruct , array , ARRAY_DATA_FIELD_OFFSET );
1175
+ var set = new WasmArraySet (arrayDataType , arrayData , new WasmGetLocal (indexLocal ),
1176
+ new WasmGetLocal (valueLocal ));
1177
+ arraySetObjectFunction .getBody ().add (set );
1178
+ }
1179
+ return arraySetObjectFunction ;
1180
+ }
1181
+
1182
+ private WasmFunction generateArraySetPrimitiveFunction (PrimitiveType type ) {
1183
+ var function = new WasmFunction (getArraySetType ());
1184
+ function .setName (names .topLevel ("Array<" + names .suggestForType (ValueType .primitive (type )) + ">::set" ));
1185
+ module .functions .add (function );
1186
+ function .setReferenced (true );
1187
+
1188
+ var arrayStruct = getClassInfo (ValueType .arrayOf (ValueType .primitive (type ))).structure ;
1189
+ var arrayDataTypeRef = (WasmType .CompositeReference ) arrayStruct .getFields ()
1190
+ .get (ARRAY_DATA_FIELD_OFFSET ).getUnpackedType ();
1191
+ var arrayDataType = (WasmArray ) arrayDataTypeRef .composite ;
1192
+ var classLocal = new WasmLocal (standardClasses .classClass ().getType (), "this" );
1193
+ var objectLocal = new WasmLocal (standardClasses .objectClass ().getType (), "object" );
1194
+ var indexLocal = new WasmLocal (WasmType .INT32 , "index" );
1195
+ var valueLocal = new WasmLocal (standardClasses .objectClass ().getType (), "value" );
1196
+ function .add (classLocal );
1197
+ function .add (objectLocal );
1198
+ function .add (indexLocal );
1199
+ function .add (valueLocal );
1200
+
1201
+ var array = new WasmCast (new WasmGetLocal (objectLocal ), arrayStruct .getNonNullReference ());
1202
+ var arrayData = new WasmStructGet (arrayStruct , array , ARRAY_DATA_FIELD_OFFSET );
1203
+ var set = new WasmArraySet (arrayDataType , arrayData , new WasmGetLocal (indexLocal ),
1204
+ new WasmGetLocal (valueLocal ));
1205
+ Class <?> primitiveType ;
1206
+ Class <?> wrapperType ;
1207
+ switch (type ) {
1208
+ case BOOLEAN :
1209
+ primitiveType = boolean .class ;
1210
+ wrapperType = Boolean .class ;
1211
+ break ;
1212
+ case BYTE :
1213
+ primitiveType = byte .class ;
1214
+ wrapperType = Byte .class ;
1215
+ break ;
1216
+ case SHORT :
1217
+ primitiveType = short .class ;
1218
+ wrapperType = Short .class ;
1219
+ break ;
1220
+ case CHARACTER :
1221
+ primitiveType = char .class ;
1222
+ wrapperType = Character .class ;
1223
+ break ;
1224
+ case INTEGER :
1225
+ primitiveType = int .class ;
1226
+ wrapperType = Integer .class ;
1227
+ break ;
1228
+ case LONG :
1229
+ primitiveType = long .class ;
1230
+ wrapperType = Long .class ;
1231
+ break ;
1232
+ case FLOAT :
1233
+ primitiveType = float .class ;
1234
+ wrapperType = Float .class ;
1235
+ break ;
1236
+ case DOUBLE :
1237
+ primitiveType = double .class ;
1238
+ wrapperType = Double .class ;
1239
+ break ;
1240
+ default :
1241
+ throw new IllegalArgumentException ();
1242
+ }
1243
+ var method = new MethodReference (wrapperType , primitiveType .getName () + "Value" , primitiveType );
1244
+ var unwrapFunction = functionProvider .forInstanceMethod (method );
1245
+ set .setValue (new WasmCast (set .getValue (), getClassInfo (ValueType .parse (wrapperType )).getType ()));
1246
+ set .setValue (new WasmCall (unwrapFunction , set .getValue ()));
1247
+ function .getBody ().add (set );
1248
+
1249
+ return function ;
1250
+ }
1251
+
1133
1252
private WasmFunction getArrayCopyObjectFunction () {
1134
1253
if (arrayCopyObjectFunction == null ) {
1135
1254
arrayCopyObjectFunction = createArrayCopyFunction (OBJECT_TYPE );
@@ -1180,6 +1299,14 @@ private WasmFunctionType getArrayGetType() {
1180
1299
return arrayGetType ;
1181
1300
}
1182
1301
1302
+ private WasmFunctionType getArraySetType () {
1303
+ if (arraySetType == null ) {
1304
+ arraySetType = functionTypes .of (null , standardClasses .classClass ().getType (),
1305
+ standardClasses .objectClass ().getType (), WasmType .INT32 , standardClasses .objectClass ().getType ());
1306
+ }
1307
+ return arraySetType ;
1308
+ }
1309
+
1183
1310
private WasmFunctionType getArrayLengthType () {
1184
1311
if (arrayLengthType == null ) {
1185
1312
arrayLengthType = functionTypes .of (WasmType .INT32 , standardClasses .classClass ().getType (),
@@ -1345,6 +1472,12 @@ public WasmStructure getArrayVirtualTableStructure() {
1345
1472
fields .add (new WasmField (arrayGetType .getReference ().asStorage (),
1346
1473
names .structureField ("@arrayGet" )));
1347
1474
}
1475
+ if (metadataRequirements .hasArraySet ()) {
1476
+ arraySetOffset = fields .size ();
1477
+ var arraySetType = getArraySetType ();
1478
+ fields .add (new WasmField (arraySetType .getReference ().asStorage (),
1479
+ names .structureField ("@arraySet" )));
1480
+ }
1348
1481
if (metadataRequirements .hasArrayCopy ()) {
1349
1482
arrayCopyOffset = fields .size ();
1350
1483
var arrayCopyType = getArrayCopyType ();
@@ -1371,6 +1504,12 @@ public int getArrayGetOffset() {
1371
1504
return arrayGetOffset ;
1372
1505
}
1373
1506
1507
+ @ Override
1508
+ public int getArraySetOffset () {
1509
+ initStructures ();
1510
+ return arraySetOffset ;
1511
+ }
1512
+
1374
1513
@ Override
1375
1514
public int getArrayCopyOffset () {
1376
1515
initStructures ();
@@ -1993,6 +2132,11 @@ private void fillArrayVirtualTableMethods(List<WasmExpression> target, WasmLocal
1993
2132
target .add (new WasmStructSet (structure , new WasmGetLocal (vt ), arrayGetOffset ,
1994
2133
new WasmFunctionReference (getFunction )));
1995
2134
}
2135
+ if (arraySetOffset >= 0 ) {
2136
+ var setFunction = getArraySetObjectFunction ();
2137
+ target .add (new WasmStructSet (structure , new WasmGetLocal (vt ), arraySetOffset ,
2138
+ new WasmFunctionReference (setFunction )));
2139
+ }
1996
2140
if (arrayCopyOffset >= 0 ) {
1997
2141
var copyFunction = getArrayCopyObjectFunction ();
1998
2142
target .add (new WasmStructSet (structure , new WasmGetLocal (vt ), arrayCopyOffset ,
0 commit comments