mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: support System.arrayCopy for special cases
This commit is contained in:
parent
065aef581d
commit
e61301576b
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,4 +66,8 @@ public interface TeaVMTarget {
|
|||
default Collection<? extends MethodReference> getInitializerMethods() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default boolean needsSystemArrayCopyOptimization() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user