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.gc.WasmGCDependencies;
|
||||||
import org.teavm.backend.wasm.generate.gc.WasmGCDeclarationsGenerator;
|
import org.teavm.backend.wasm.generate.gc.WasmGCDeclarationsGenerator;
|
||||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGenerators;
|
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.model.WasmModule;
|
||||||
import org.teavm.backend.wasm.render.WasmBinaryRenderer;
|
import org.teavm.backend.wasm.render.WasmBinaryRenderer;
|
||||||
import org.teavm.backend.wasm.render.WasmBinaryStatsCollector;
|
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 {
|
public void emit(ListableClassHolderSource classes, BuildTarget buildTarget, String outputName) throws IOException {
|
||||||
var module = new WasmModule();
|
var module = new WasmModule();
|
||||||
var customGenerators = new WasmGCCustomGenerators();
|
var customGenerators = new WasmGCCustomGenerators();
|
||||||
|
var intrinsics = new WasmGCIntrinsics();
|
||||||
var declarationsGenerator = new WasmGCDeclarationsGenerator(
|
var declarationsGenerator = new WasmGCDeclarationsGenerator(
|
||||||
module,
|
module,
|
||||||
classes,
|
classes,
|
||||||
|
@ -115,7 +117,8 @@ public class WasmGCTarget implements TeaVMTarget {
|
||||||
controller.getClassInitializerInfo(),
|
controller.getClassInitializerInfo(),
|
||||||
controller.getDependencyInfo(),
|
controller.getDependencyInfo(),
|
||||||
controller.getDiagnostics(),
|
controller.getDiagnostics(),
|
||||||
customGenerators
|
customGenerators,
|
||||||
|
intrinsics
|
||||||
);
|
);
|
||||||
declarationsGenerator.setFriendlyToDebugger(controller.isFriendlyToDebugger());
|
declarationsGenerator.setFriendlyToDebugger(controller.isFriendlyToDebugger());
|
||||||
var moduleGenerator = new WasmGCModuleGenerator(declarationsGenerator);
|
var moduleGenerator = new WasmGCModuleGenerator(declarationsGenerator);
|
||||||
|
@ -156,4 +159,9 @@ public class WasmGCTarget implements TeaVMTarget {
|
||||||
output.write(data);
|
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.WasmGCSupertypeFunctionProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
|
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.WasmGCCustomGeneratorProvider;
|
||||||
|
import org.teavm.backend.wasm.generate.gc.methods.WasmGCIntrinsicProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.methods.WasmGCMethodGenerator;
|
import org.teavm.backend.wasm.generate.gc.methods.WasmGCMethodGenerator;
|
||||||
import org.teavm.backend.wasm.model.WasmFunction;
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
import org.teavm.backend.wasm.model.WasmModule;
|
import org.teavm.backend.wasm.model.WasmModule;
|
||||||
|
@ -55,7 +56,8 @@ public class WasmGCDeclarationsGenerator {
|
||||||
ClassInitializerInfo classInitializerInfo,
|
ClassInitializerInfo classInitializerInfo,
|
||||||
DependencyInfo dependencyInfo,
|
DependencyInfo dependencyInfo,
|
||||||
Diagnostics diagnostics,
|
Diagnostics diagnostics,
|
||||||
WasmGCCustomGeneratorProvider customGenerators
|
WasmGCCustomGeneratorProvider customGenerators,
|
||||||
|
WasmGCIntrinsicProvider intrinsics
|
||||||
) {
|
) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
hierarchy = new ClassHierarchy(classes);
|
hierarchy = new ClassHierarchy(classes);
|
||||||
|
@ -73,7 +75,8 @@ public class WasmGCDeclarationsGenerator {
|
||||||
names,
|
names,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
returnTypes,
|
returnTypes,
|
||||||
customGenerators
|
customGenerators,
|
||||||
|
intrinsics
|
||||||
);
|
);
|
||||||
var tags = new TagRegistry(classes, hierarchy);
|
var tags = new TagRegistry(classes, hierarchy);
|
||||||
var metadataRequirements = new ClassMetadataRequirements(dependencyInfo);
|
var metadataRequirements = new ClassMetadataRequirements(dependencyInfo);
|
||||||
|
|
|
@ -476,7 +476,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
|
|
||||||
private void fillClassFields(List<WasmStorageType> fields, String className) {
|
private void fillClassFields(List<WasmStorageType> fields, String className) {
|
||||||
var classReader = classSource.get(className);
|
var classReader = classSource.get(className);
|
||||||
if (classReader.hasModifier(ElementModifier.INTERFACE)) {
|
if (classReader == null || classReader.hasModifier(ElementModifier.INTERFACE)) {
|
||||||
fillSimpleClassFields(fields, "java.lang.Object");
|
fillSimpleClassFields(fields, "java.lang.Object");
|
||||||
} else {
|
} else {
|
||||||
fillSimpleClassFields(fields, className);
|
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.WasmTag;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||||
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
||||||
|
import org.teavm.model.ClassHierarchy;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.classes.VirtualTableProvider;
|
import org.teavm.model.classes.VirtualTableProvider;
|
||||||
|
@ -42,9 +43,11 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||||
private WasmGCTypeMapper typeMapper;
|
private WasmGCTypeMapper typeMapper;
|
||||||
private WasmFunctionTypes functionTypes;
|
private WasmFunctionTypes functionTypes;
|
||||||
private ClassReaderSource classes;
|
private ClassReaderSource classes;
|
||||||
|
private ClassHierarchy hierarchy;
|
||||||
private BaseWasmFunctionRepository functions;
|
private BaseWasmFunctionRepository functions;
|
||||||
private WasmGCSupertypeFunctionProvider supertypeFunctions;
|
private WasmGCSupertypeFunctionProvider supertypeFunctions;
|
||||||
private WasmGCCustomGeneratorProvider customGenerators;
|
private WasmGCCustomGeneratorProvider customGenerators;
|
||||||
|
private WasmGCIntrinsicProvider intrinsics;
|
||||||
private WasmFunction npeMethod;
|
private WasmFunction npeMethod;
|
||||||
private WasmFunction aaiobeMethod;
|
private WasmFunction aaiobeMethod;
|
||||||
private WasmFunction cceMethod;
|
private WasmFunction cceMethod;
|
||||||
|
@ -53,20 +56,23 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||||
|
|
||||||
public WasmGCGenerationContext(WasmModule module, VirtualTableProvider virtualTables,
|
public WasmGCGenerationContext(WasmModule module, VirtualTableProvider virtualTables,
|
||||||
WasmGCTypeMapper typeMapper, WasmFunctionTypes functionTypes, ClassReaderSource classes,
|
WasmGCTypeMapper typeMapper, WasmFunctionTypes functionTypes, ClassReaderSource classes,
|
||||||
BaseWasmFunctionRepository functions, WasmGCSupertypeFunctionProvider supertypeFunctions,
|
ClassHierarchy hierarchy, BaseWasmFunctionRepository functions,
|
||||||
WasmGCClassInfoProvider classInfoProvider, WasmGCStandardClasses standardClasses,
|
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
|
||||||
WasmGCStringProvider strings, WasmGCCustomGeneratorProvider customGenerators) {
|
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
|
||||||
|
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.virtualTables = virtualTables;
|
this.virtualTables = virtualTables;
|
||||||
this.typeMapper = typeMapper;
|
this.typeMapper = typeMapper;
|
||||||
this.functionTypes = functionTypes;
|
this.functionTypes = functionTypes;
|
||||||
this.classes = classes;
|
this.classes = classes;
|
||||||
|
this.hierarchy = hierarchy;
|
||||||
this.functions = functions;
|
this.functions = functions;
|
||||||
this.supertypeFunctions = supertypeFunctions;
|
this.supertypeFunctions = supertypeFunctions;
|
||||||
this.classInfoProvider = classInfoProvider;
|
this.classInfoProvider = classInfoProvider;
|
||||||
this.standardClasses = standardClasses;
|
this.standardClasses = standardClasses;
|
||||||
this.strings = strings;
|
this.strings = strings;
|
||||||
this.customGenerators = customGenerators;
|
this.customGenerators = customGenerators;
|
||||||
|
this.intrinsics = intrinsics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmGCClassInfoProvider classInfoProvider() {
|
public WasmGCClassInfoProvider classInfoProvider() {
|
||||||
|
@ -118,6 +124,10 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ClassHierarchy hierarchy() {
|
||||||
|
return hierarchy;
|
||||||
|
}
|
||||||
|
|
||||||
public WasmFunction npeMethod() {
|
public WasmFunction npeMethod() {
|
||||||
if (npeMethod == null) {
|
if (npeMethod == null) {
|
||||||
npeMethod = functions().forStaticMethod(new MethodReference(WasmGCSupport.class, "npe",
|
npeMethod = functions().forStaticMethod(new MethodReference(WasmGCSupport.class, "npe",
|
||||||
|
@ -151,7 +161,15 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||||
return exceptionGlobal;
|
return exceptionGlobal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmModule module() {
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
public WasmGCCustomGeneratorProvider customGenerators() {
|
public WasmGCCustomGeneratorProvider customGenerators() {
|
||||||
return 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.BinaryExpr;
|
||||||
import org.teavm.ast.Expr;
|
import org.teavm.ast.Expr;
|
||||||
import org.teavm.ast.InvocationExpr;
|
import org.teavm.ast.InvocationExpr;
|
||||||
|
import org.teavm.ast.InvocationType;
|
||||||
import org.teavm.ast.QualificationExpr;
|
import org.teavm.ast.QualificationExpr;
|
||||||
import org.teavm.ast.SubscriptExpr;
|
import org.teavm.ast.SubscriptExpr;
|
||||||
import org.teavm.ast.UnwrapArrayExpr;
|
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.gc.PreciseTypeInference;
|
||||||
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor;
|
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.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.WasmArray;
|
||||||
import org.teavm.backend.wasm.model.WasmFunction;
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
import org.teavm.backend.wasm.model.WasmFunctionType;
|
import org.teavm.backend.wasm.model.WasmFunctionType;
|
||||||
import org.teavm.backend.wasm.model.WasmLocal;
|
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.WasmStructure;
|
||||||
import org.teavm.backend.wasm.model.WasmType;
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmArrayGet;
|
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.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
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.WasmExpression;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
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.WasmStructSet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||||
|
import org.teavm.model.ClassHierarchy;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
|
@ -400,6 +408,30 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
result = invocation(expr, null, false);
|
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
|
@Override
|
||||||
protected WasmExpression mapFirstArgumentForCall(WasmExpression argument, WasmFunction function,
|
protected WasmExpression mapFirstArgumentForCall(WasmExpression argument, WasmFunction function,
|
||||||
MethodReference method) {
|
MethodReference method) {
|
||||||
|
@ -480,4 +512,42 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
public void generateThrow(List<WasmExpression> target, TextLocation location) {
|
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 Diagnostics diagnostics;
|
||||||
private WasmGCTypeMapper typeMapper;
|
private WasmGCTypeMapper typeMapper;
|
||||||
private WasmGCCustomGeneratorProvider customGenerators;
|
private WasmGCCustomGeneratorProvider customGenerators;
|
||||||
|
private WasmGCIntrinsicProvider intrinsics;
|
||||||
private Queue<Runnable> queue = new ArrayDeque<>();
|
private Queue<Runnable> queue = new ArrayDeque<>();
|
||||||
private Map<MethodReference, WasmFunction> staticMethods = new HashMap<>();
|
private Map<MethodReference, WasmFunction> staticMethods = new HashMap<>();
|
||||||
private Map<MethodReference, WasmFunction> instanceMethods = new HashMap<>();
|
private Map<MethodReference, WasmFunction> instanceMethods = new HashMap<>();
|
||||||
|
@ -89,7 +90,8 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
NameProvider names,
|
NameProvider names,
|
||||||
Diagnostics diagnostics,
|
Diagnostics diagnostics,
|
||||||
WasmGCMethodReturnTypes returnTypes,
|
WasmGCMethodReturnTypes returnTypes,
|
||||||
WasmGCCustomGeneratorProvider customGenerators
|
WasmGCCustomGeneratorProvider customGenerators,
|
||||||
|
WasmGCIntrinsicProvider intrinsics
|
||||||
) {
|
) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.hierarchy = hierarchy;
|
this.hierarchy = hierarchy;
|
||||||
|
@ -101,6 +103,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
this.returnTypes = returnTypes;
|
this.returnTypes = returnTypes;
|
||||||
this.customGenerators = customGenerators;
|
this.customGenerators = customGenerators;
|
||||||
|
this.intrinsics = intrinsics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTypeMapper(WasmGCTypeMapper typeMapper) {
|
public void setTypeMapper(WasmGCTypeMapper typeMapper) {
|
||||||
|
@ -292,12 +295,14 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
typeMapper,
|
typeMapper,
|
||||||
functionTypes,
|
functionTypes,
|
||||||
classes,
|
classes,
|
||||||
|
hierarchy,
|
||||||
this,
|
this,
|
||||||
supertypeFunctions,
|
supertypeFunctions,
|
||||||
classInfoProvider,
|
classInfoProvider,
|
||||||
standardClasses,
|
standardClasses,
|
||||||
strings,
|
strings,
|
||||||
customGenerators
|
customGenerators,
|
||||||
|
intrinsics
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
|
@ -324,5 +329,10 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
public WasmFunctionTypes functionTypes() {
|
public WasmFunctionTypes functionTypes() {
|
||||||
return 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;
|
package org.teavm.backend.wasm.generators.gc;
|
||||||
|
|
||||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||||
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
|
||||||
import org.teavm.backend.wasm.model.WasmModule;
|
import org.teavm.backend.wasm.model.WasmModule;
|
||||||
|
|
||||||
public interface WasmGCCustomGeneratorContext {
|
public interface WasmGCCustomGeneratorContext {
|
||||||
WasmModule module();
|
WasmModule module();
|
||||||
|
|
||||||
WasmFunctionTypes functionTypes();
|
WasmFunctionTypes functionTypes();
|
||||||
|
|
||||||
|
WasmGCTypeMapper typeMapper();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ public class WasmGCCustomGenerators implements WasmGCCustomGeneratorProvider {
|
||||||
|
|
||||||
public WasmGCCustomGenerators() {
|
public WasmGCCustomGenerators() {
|
||||||
fillStringPool();
|
fillStringPool();
|
||||||
|
fillSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillStringPool() {
|
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
|
@Override
|
||||||
public WasmGCCustomGenerator get(MethodReference method) {
|
public WasmGCCustomGenerator get(MethodReference method) {
|
||||||
return generators.get(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
|
@Override
|
||||||
public void visit(InvokeInstruction insn) {
|
public void visit(InvokeInstruction insn) {
|
||||||
if (insn.getInstance() != null) {
|
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) {
|
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
|
@Override
|
||||||
public void visit(GetFieldInstruction insn) {
|
public void visit(GetFieldInstruction insn) {
|
||||||
if (insn.getInstance() != null) {
|
if (insn.getInstance() != null) {
|
||||||
push(insn.getInstance(), ValueType.object(reference.getClassName()));
|
push(insn.getInstance(), ValueType.object(insn.getField().getClassName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PutFieldInstruction insn) {
|
public void visit(PutFieldInstruction insn) {
|
||||||
if (insn.getInstance() != null) {
|
if (insn.getInstance() != null) {
|
||||||
push(insn.getInstance(), ValueType.object(reference.getClassName()));
|
push(insn.getInstance(), ValueType.object(insn.getField().getClassName()));
|
||||||
}
|
}
|
||||||
push(insn.getValue(), insn.getFieldType());
|
push(insn.getValue(), insn.getFieldType());
|
||||||
}
|
}
|
||||||
|
|
|
@ -823,7 +823,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
optimizations.add(new ClassInitElimination());
|
optimizations.add(new ClassInitElimination());
|
||||||
optimizations.add(new UnreachableBasicBlockElimination());
|
optimizations.add(new UnreachableBasicBlockElimination());
|
||||||
optimizations.add(new UnusedVariableElimination());
|
optimizations.add(new UnusedVariableElimination());
|
||||||
|
if (target.needsSystemArrayCopyOptimization()) {
|
||||||
optimizations.add(new SystemArrayCopyOptimization());
|
optimizations.add(new SystemArrayCopyOptimization());
|
||||||
|
}
|
||||||
return optimizations;
|
return optimizations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,4 +66,8 @@ public interface TeaVMTarget {
|
||||||
default Collection<? extends MethodReference> getInitializerMethods() {
|
default Collection<? extends MethodReference> getInitializerMethods() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default boolean needsSystemArrayCopyOptimization() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user