wasm gc: support System.arrayCopy for special cases

This commit is contained in:
Alexey Andreev 2024-08-03 20:59:19 +02:00
parent 065aef581d
commit e61301576b
17 changed files with 405 additions and 14 deletions

View File

@ -20,6 +20,7 @@ import java.util.List;
import org.teavm.backend.wasm.gc.WasmGCDependencies;
import org.teavm.backend.wasm.generate.gc.WasmGCDeclarationsGenerator;
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGenerators;
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsics;
import org.teavm.backend.wasm.model.WasmModule;
import org.teavm.backend.wasm.render.WasmBinaryRenderer;
import org.teavm.backend.wasm.render.WasmBinaryStatsCollector;
@ -108,6 +109,7 @@ public class WasmGCTarget implements TeaVMTarget {
public void emit(ListableClassHolderSource classes, BuildTarget buildTarget, String outputName) throws IOException {
var module = new WasmModule();
var customGenerators = new WasmGCCustomGenerators();
var intrinsics = new WasmGCIntrinsics();
var declarationsGenerator = new WasmGCDeclarationsGenerator(
module,
classes,
@ -115,7 +117,8 @@ public class WasmGCTarget implements TeaVMTarget {
controller.getClassInitializerInfo(),
controller.getDependencyInfo(),
controller.getDiagnostics(),
customGenerators
customGenerators,
intrinsics
);
declarationsGenerator.setFriendlyToDebugger(controller.isFriendlyToDebugger());
var moduleGenerator = new WasmGCModuleGenerator(declarationsGenerator);
@ -156,4 +159,9 @@ public class WasmGCTarget implements TeaVMTarget {
output.write(data);
}
}
@Override
public boolean needsSystemArrayCopyOptimization() {
return false;
}
}

View File

@ -26,6 +26,7 @@ import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCSupertypeFunctionProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
import org.teavm.backend.wasm.generate.gc.methods.WasmGCCustomGeneratorProvider;
import org.teavm.backend.wasm.generate.gc.methods.WasmGCIntrinsicProvider;
import org.teavm.backend.wasm.generate.gc.methods.WasmGCMethodGenerator;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmModule;
@ -55,7 +56,8 @@ public class WasmGCDeclarationsGenerator {
ClassInitializerInfo classInitializerInfo,
DependencyInfo dependencyInfo,
Diagnostics diagnostics,
WasmGCCustomGeneratorProvider customGenerators
WasmGCCustomGeneratorProvider customGenerators,
WasmGCIntrinsicProvider intrinsics
) {
this.module = module;
hierarchy = new ClassHierarchy(classes);
@ -73,7 +75,8 @@ public class WasmGCDeclarationsGenerator {
names,
diagnostics,
returnTypes,
customGenerators
customGenerators,
intrinsics
);
var tags = new TagRegistry(classes, hierarchy);
var metadataRequirements = new ClassMetadataRequirements(dependencyInfo);

View File

@ -476,7 +476,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
private void fillClassFields(List<WasmStorageType> fields, String className) {
var classReader = classSource.get(className);
if (classReader.hasModifier(ElementModifier.INTERFACE)) {
if (classReader == null || classReader.hasModifier(ElementModifier.INTERFACE)) {
fillSimpleClassFields(fields, "java.lang.Object");
} else {
fillSimpleClassFields(fields, className);

View File

@ -29,6 +29,7 @@ import org.teavm.backend.wasm.model.WasmModule;
import org.teavm.backend.wasm.model.WasmTag;
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
import org.teavm.backend.wasm.runtime.WasmGCSupport;
import org.teavm.model.ClassHierarchy;
import org.teavm.model.ClassReaderSource;
import org.teavm.model.MethodReference;
import org.teavm.model.classes.VirtualTableProvider;
@ -42,9 +43,11 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
private WasmGCTypeMapper typeMapper;
private WasmFunctionTypes functionTypes;
private ClassReaderSource classes;
private ClassHierarchy hierarchy;
private BaseWasmFunctionRepository functions;
private WasmGCSupertypeFunctionProvider supertypeFunctions;
private WasmGCCustomGeneratorProvider customGenerators;
private WasmGCIntrinsicProvider intrinsics;
private WasmFunction npeMethod;
private WasmFunction aaiobeMethod;
private WasmFunction cceMethod;
@ -53,20 +56,23 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
public WasmGCGenerationContext(WasmModule module, VirtualTableProvider virtualTables,
WasmGCTypeMapper typeMapper, WasmFunctionTypes functionTypes, ClassReaderSource classes,
BaseWasmFunctionRepository functions, WasmGCSupertypeFunctionProvider supertypeFunctions,
WasmGCClassInfoProvider classInfoProvider, WasmGCStandardClasses standardClasses,
WasmGCStringProvider strings, WasmGCCustomGeneratorProvider customGenerators) {
ClassHierarchy hierarchy, BaseWasmFunctionRepository functions,
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics) {
this.module = module;
this.virtualTables = virtualTables;
this.typeMapper = typeMapper;
this.functionTypes = functionTypes;
this.classes = classes;
this.hierarchy = hierarchy;
this.functions = functions;
this.supertypeFunctions = supertypeFunctions;
this.classInfoProvider = classInfoProvider;
this.standardClasses = standardClasses;
this.strings = strings;
this.customGenerators = customGenerators;
this.intrinsics = intrinsics;
}
public WasmGCClassInfoProvider classInfoProvider() {
@ -118,6 +124,10 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
return classes;
}
public ClassHierarchy hierarchy() {
return hierarchy;
}
public WasmFunction npeMethod() {
if (npeMethod == null) {
npeMethod = functions().forStaticMethod(new MethodReference(WasmGCSupport.class, "npe",
@ -151,7 +161,15 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
return exceptionGlobal;
}
public WasmModule module() {
return module;
}
public WasmGCCustomGeneratorProvider customGenerators() {
return customGenerators;
}
public WasmGCIntrinsicProvider intrinsics() {
return intrinsics;
}
}

View File

@ -20,16 +20,22 @@ import org.teavm.ast.ArrayType;
import org.teavm.ast.BinaryExpr;
import org.teavm.ast.Expr;
import org.teavm.ast.InvocationExpr;
import org.teavm.ast.InvocationType;
import org.teavm.ast.QualificationExpr;
import org.teavm.ast.SubscriptExpr;
import org.teavm.ast.UnwrapArrayExpr;
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.gc.PreciseTypeInference;
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicContext;
import org.teavm.backend.wasm.model.WasmArray;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmFunctionType;
import org.teavm.backend.wasm.model.WasmLocal;
import org.teavm.backend.wasm.model.WasmModule;
import org.teavm.backend.wasm.model.WasmStructure;
import org.teavm.backend.wasm.model.WasmType;
import org.teavm.backend.wasm.model.expression.WasmArrayGet;
@ -39,6 +45,7 @@ import org.teavm.backend.wasm.model.expression.WasmBlock;
import org.teavm.backend.wasm.model.expression.WasmCall;
import org.teavm.backend.wasm.model.expression.WasmCallReference;
import org.teavm.backend.wasm.model.expression.WasmCast;
import org.teavm.backend.wasm.model.expression.WasmDrop;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
@ -55,6 +62,7 @@ import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
import org.teavm.backend.wasm.model.expression.WasmStructSet;
import org.teavm.backend.wasm.model.expression.WasmThrow;
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
import org.teavm.model.ClassHierarchy;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReference;
import org.teavm.model.TextLocation;
@ -400,6 +408,30 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
result = invocation(expr, null, false);
}
@Override
protected WasmExpression invocation(InvocationExpr expr, List<WasmExpression> resultConsumer, boolean willDrop) {
if (expr.getType() == InvocationType.SPECIAL || expr.getType() == InvocationType.STATIC) {
var intrinsic = context.intrinsics().get(expr.getMethod());
if (intrinsic != null) {
var resultExpr = intrinsic.apply(expr, intrinsicContext);
if (resultConsumer != null) {
if (willDrop) {
var drop = new WasmDrop(resultExpr);
drop.setLocation(expr.getLocation());
resultConsumer.add(drop);
} else {
resultConsumer.add(resultExpr);
}
result = null;
return null;
} else {
return resultExpr;
}
}
}
return super.invocation(expr, resultConsumer, willDrop);
}
@Override
protected WasmExpression mapFirstArgumentForCall(WasmExpression argument, WasmFunction function,
MethodReference method) {
@ -480,4 +512,42 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
public void generateThrow(List<WasmExpression> target, TextLocation location) {
}
}
private WasmGCIntrinsicContext intrinsicContext = new WasmGCIntrinsicContext() {
@Override
public WasmExpression generate(Expr expr) {
accept(expr);
return result;
}
@Override
public WasmModule module() {
return context.module();
}
@Override
public WasmFunctionTypes functionTypes() {
return context.functionTypes();
}
@Override
public PreciseTypeInference types() {
return types;
}
@Override
public BaseWasmFunctionRepository functions() {
return context.functions();
}
@Override
public ClassHierarchy hierarchy() {
return context.hierarchy();
}
@Override
public WasmGCTypeMapper typeMapper() {
return context.typeMapper();
}
};
}

View File

@ -0,0 +1,23 @@
/*
* Copyright 2024 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.backend.wasm.generate.gc.methods;
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsic;
import org.teavm.model.MethodReference;
public interface WasmGCIntrinsicProvider {
WasmGCIntrinsic get(MethodReference method);
}

View File

@ -67,6 +67,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
private Diagnostics diagnostics;
private WasmGCTypeMapper typeMapper;
private WasmGCCustomGeneratorProvider customGenerators;
private WasmGCIntrinsicProvider intrinsics;
private Queue<Runnable> queue = new ArrayDeque<>();
private Map<MethodReference, WasmFunction> staticMethods = new HashMap<>();
private Map<MethodReference, WasmFunction> instanceMethods = new HashMap<>();
@ -89,7 +90,8 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
NameProvider names,
Diagnostics diagnostics,
WasmGCMethodReturnTypes returnTypes,
WasmGCCustomGeneratorProvider customGenerators
WasmGCCustomGeneratorProvider customGenerators,
WasmGCIntrinsicProvider intrinsics
) {
this.module = module;
this.hierarchy = hierarchy;
@ -101,6 +103,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
this.diagnostics = diagnostics;
this.returnTypes = returnTypes;
this.customGenerators = customGenerators;
this.intrinsics = intrinsics;
}
public void setTypeMapper(WasmGCTypeMapper typeMapper) {
@ -292,12 +295,14 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
typeMapper,
functionTypes,
classes,
hierarchy,
this,
supertypeFunctions,
classInfoProvider,
standardClasses,
strings,
customGenerators
customGenerators,
intrinsics
);
}
return context;
@ -324,5 +329,10 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
public WasmFunctionTypes functionTypes() {
return functionTypes;
}
@Override
public WasmGCTypeMapper typeMapper() {
return typeMapper;
}
};
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2024 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.backend.wasm.generators.gc;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmLocal;
import org.teavm.backend.wasm.model.WasmType;
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
public class SystemDoArrayCopyGenerator implements WasmGCCustomGenerator {
@Override
public void apply(MethodReference method, WasmFunction function, WasmGCCustomGeneratorContext context) {
function.add(new WasmLocal(context.typeMapper().mapType(ValueType.object("java.lang.Object"))));
function.add(new WasmLocal(WasmType.INT32));
function.add(new WasmLocal(context.typeMapper().mapType(ValueType.object("java.lang.Object"))));
function.add(new WasmLocal(WasmType.INT32));
function.add(new WasmLocal(WasmType.INT32));
function.getBody().add(new WasmUnreachable());
}
}

View File

@ -16,10 +16,13 @@
package org.teavm.backend.wasm.generators.gc;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
import org.teavm.backend.wasm.model.WasmModule;
public interface WasmGCCustomGeneratorContext {
WasmModule module();
WasmFunctionTypes functionTypes();
WasmGCTypeMapper typeMapper();
}

View File

@ -26,6 +26,7 @@ public class WasmGCCustomGenerators implements WasmGCCustomGeneratorProvider {
public WasmGCCustomGenerators() {
fillStringPool();
fillSystem();
}
private void fillStringPool() {
@ -35,6 +36,14 @@ public class WasmGCCustomGenerators implements WasmGCCustomGeneratorProvider {
);
}
private void fillSystem() {
generators.put(
new MethodReference(System.class, "doArrayCopy", Object.class, int.class, Object.class,
int.class, int.class, void.class),
new SystemDoArrayCopyGenerator()
);
}
@Override
public WasmGCCustomGenerator get(MethodReference method) {
return generators.get(method);

View File

@ -0,0 +1,103 @@
/*
* Copyright 2024 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.backend.wasm.intrinsics.gc;
import org.teavm.ast.InvocationExpr;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.model.WasmArray;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmStructure;
import org.teavm.backend.wasm.model.WasmType;
import org.teavm.backend.wasm.model.expression.WasmArrayCopy;
import org.teavm.backend.wasm.model.expression.WasmCall;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmStructGet;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
public class SystemArrayCopyIntrinsic implements WasmGCIntrinsic {
private WasmFunction defaultFunction;
@Override
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
var result = tryGenerateSpecialCase(invocation, context);
if (result == null) {
var function = getDefaultFunction(context);
result = new WasmCall(function, context.generate(invocation.getArguments().get(0)),
context.generate(invocation.getArguments().get(1)),
context.generate(invocation.getArguments().get(2)),
context.generate(invocation.getArguments().get(3)),
context.generate(invocation.getArguments().get(4)));
}
return result;
}
private WasmExpression tryGenerateSpecialCase(InvocationExpr invocation, WasmGCIntrinsicContext context) {
var sourceArray = invocation.getArguments().get(0);
var targetArray = invocation.getArguments().get(2);
if (sourceArray.getVariableIndex() < 0 || targetArray.getVariableIndex() < 0) {
return null;
}
var sourceType = context.types().typeOf(sourceArray.getVariableIndex());
if (sourceType == null || !(sourceType.valueType instanceof ValueType.Array)) {
return null;
}
var targetType = context.types().typeOf(targetArray.getVariableIndex());
if (targetType == null || !(targetType.valueType instanceof ValueType.Array)) {
return null;
}
var sourceItemType = ((ValueType.Array) sourceType.valueType).getItemType();
var targetItemType = ((ValueType.Array) targetType.valueType).getItemType();
if (sourceItemType != targetItemType
|| !context.hierarchy().isSuperType(targetItemType, sourceItemType, false)) {
return null;
}
var wasmTargetArrayType = (WasmType.CompositeReference) context.typeMapper().mapType(
ValueType.arrayOf(targetItemType));
var wasmTargetArrayStruct = (WasmStructure) wasmTargetArrayType.composite;
var wasmTargetArrayWrapper = context.generate(invocation.getArguments().get(2));
var wasmTargetArray = new WasmStructGet(wasmTargetArrayStruct, wasmTargetArrayWrapper,
WasmGCClassInfoProvider.ARRAY_DATA_FIELD_OFFSET);
var wasmTargetIndex = context.generate(invocation.getArguments().get(3));
var wasmSourceArrayType = (WasmType.CompositeReference) context.typeMapper().mapType(
ValueType.arrayOf(sourceItemType));
var wasmSourceArrayStruct = (WasmStructure) wasmSourceArrayType.composite;
var wasmSourceArrayWrapper = context.generate(invocation.getArguments().get(0));
var wasmSourceArray = new WasmStructGet(wasmSourceArrayStruct, wasmSourceArrayWrapper,
WasmGCClassInfoProvider.ARRAY_DATA_FIELD_OFFSET);
var wasmSourceIndex = context.generate(invocation.getArguments().get(1));
var wasmSize = context.generate(invocation.getArguments().get(4));
var wasmTargetArrayTypeRef = (WasmType.CompositeReference) wasmTargetArrayStruct.getFields()
.get(WasmGCClassInfoProvider.ARRAY_DATA_FIELD_OFFSET).asUnpackedType();
var wasmSourceArrayTypeRef = (WasmType.CompositeReference) wasmSourceArrayStruct.getFields()
.get(WasmGCClassInfoProvider.ARRAY_DATA_FIELD_OFFSET).asUnpackedType();
return new WasmArrayCopy((WasmArray) wasmTargetArrayTypeRef.composite, wasmTargetArray, wasmTargetIndex,
(WasmArray) wasmSourceArrayTypeRef.composite, wasmSourceArray, wasmSourceIndex, wasmSize);
}
private WasmFunction getDefaultFunction(WasmGCIntrinsicContext manager) {
if (defaultFunction == null) {
defaultFunction = manager.functions().forStaticMethod(new MethodReference(System.class,
"arraycopy", Object.class, int.class, Object.class, int.class, int.class, void.class));
}
return defaultFunction;
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright 2024 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.backend.wasm.intrinsics.gc;
import org.teavm.ast.InvocationExpr;
import org.teavm.backend.wasm.model.expression.WasmExpression;
public interface WasmGCIntrinsic {
WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context);
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2024 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.backend.wasm.intrinsics.gc;
import org.teavm.ast.Expr;
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.gc.PreciseTypeInference;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
import org.teavm.backend.wasm.model.WasmModule;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.model.ClassHierarchy;
public interface WasmGCIntrinsicContext {
WasmExpression generate(Expr expr);
WasmModule module();
WasmFunctionTypes functionTypes();
PreciseTypeInference types();
BaseWasmFunctionRepository functions();
ClassHierarchy hierarchy();
WasmGCTypeMapper typeMapper();
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2024 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.backend.wasm.intrinsics.gc;
import java.util.HashMap;
import java.util.Map;
import org.teavm.backend.wasm.generate.gc.methods.WasmGCIntrinsicProvider;
import org.teavm.model.MethodReference;
public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
private Map<MethodReference, WasmGCIntrinsic> intrinsics = new HashMap<>();
public WasmGCIntrinsics() {
fillSystem();
}
private void fillSystem() {
intrinsics.put(new MethodReference(System.class, "arraycopy", Object.class, int.class, Object.class,
int.class, int.class, void.class), new SystemArrayCopyIntrinsic());
}
@Override
public WasmGCIntrinsic get(MethodReference method) {
return intrinsics.get(method);
}
}

View File

@ -487,24 +487,24 @@ public abstract class BaseTypeInference<T> {
@Override
public void visit(InvokeInstruction insn) {
if (insn.getInstance() != null) {
push(insn.getInstance(), ValueType.object(reference.getClassName()));
push(insn.getInstance(), ValueType.object(insn.getMethod().getClassName()));
}
for (var i = 0; i < insn.getArguments().size(); ++i) {
push(insn.getArguments().get(i), reference.parameterType(i));
push(insn.getArguments().get(i), insn.getMethod().parameterType(i));
}
}
@Override
public void visit(GetFieldInstruction insn) {
if (insn.getInstance() != null) {
push(insn.getInstance(), ValueType.object(reference.getClassName()));
push(insn.getInstance(), ValueType.object(insn.getField().getClassName()));
}
}
@Override
public void visit(PutFieldInstruction insn) {
if (insn.getInstance() != null) {
push(insn.getInstance(), ValueType.object(reference.getClassName()));
push(insn.getInstance(), ValueType.object(insn.getField().getClassName()));
}
push(insn.getValue(), insn.getFieldType());
}

View File

@ -823,7 +823,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
optimizations.add(new ClassInitElimination());
optimizations.add(new UnreachableBasicBlockElimination());
optimizations.add(new UnusedVariableElimination());
if (target.needsSystemArrayCopyOptimization()) {
optimizations.add(new SystemArrayCopyOptimization());
}
return optimizations;
}

View File

@ -66,4 +66,8 @@ public interface TeaVMTarget {
default Collection<? extends MethodReference> getInitializerMethods() {
return null;
}
default boolean needsSystemArrayCopyOptimization() {
return true;
}
}