mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-21 01:00:54 +08:00
wasm gc: implement ServiceLoader
This commit is contained in:
parent
36f7ec36f3
commit
55ac5d0321
@ -22,6 +22,7 @@ import java.util.ServiceLoader;
|
||||
import org.teavm.backend.c.TeaVMCHost;
|
||||
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
||||
import org.teavm.backend.wasm.TeaVMWasmHost;
|
||||
import org.teavm.backend.wasm.gc.TeaVMWasmGCHost;
|
||||
import org.teavm.classlib.ReflectionSupplier;
|
||||
import org.teavm.classlib.impl.currency.CountriesGenerator;
|
||||
import org.teavm.classlib.impl.currency.CurrenciesGenerator;
|
||||
@ -94,6 +95,11 @@ public class JCLPlugin implements TeaVMPlugin {
|
||||
if (wasmHost != null) {
|
||||
wasmHost.add(new ServiceLoaderWasmSupport());
|
||||
}
|
||||
|
||||
var wasmGCHost = host.getExtension(TeaVMWasmGCHost.class);
|
||||
if (wasmGCHost != null) {
|
||||
wasmGCHost.addGeneratorFactory(new ServiceLoaderWasmGCSupport());
|
||||
}
|
||||
}
|
||||
|
||||
if (!isBootstrap()) {
|
||||
|
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 2021 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.classlib.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.ServiceLoader;
|
||||
import org.teavm.backend.wasm.generate.TemporaryVariablePool;
|
||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||
import org.teavm.backend.wasm.generate.gc.methods.WasmGCGenerationUtil;
|
||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGenerator;
|
||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGeneratorContext;
|
||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGeneratorFactory;
|
||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGeneratorFactoryContext;
|
||||
import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmGlobal;
|
||||
import org.teavm.backend.wasm.model.WasmLocal;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
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.WasmExpression;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmNullBranch;
|
||||
import org.teavm.backend.wasm.model.expression.WasmNullCondition;
|
||||
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
public class ServiceLoaderWasmGCSupport implements WasmGCCustomGeneratorFactory {
|
||||
static final MethodDescriptor INIT_METHOD = new MethodDescriptor("<init>", ValueType.VOID);
|
||||
|
||||
@Override
|
||||
public WasmGCCustomGenerator createGenerator(MethodReference methodRef,
|
||||
WasmGCCustomGeneratorFactoryContext context) {
|
||||
if (methodRef.getClassName().equals(ServiceLoader.class.getName())
|
||||
&& methodRef.getName().equals("loadServices")) {
|
||||
return new ServiceLoaderIntrinsic(context.services().getService(ServiceLoaderInformation.class));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static class ServiceLoaderIntrinsic implements WasmGCCustomGenerator {
|
||||
private ServiceLoaderInformation information;
|
||||
|
||||
ServiceLoaderIntrinsic(ServiceLoaderInformation information) {
|
||||
this.information = information;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(MethodReference method, WasmFunction function, WasmGCCustomGeneratorContext context) {
|
||||
var initializer = generateInitializer(context);
|
||||
var emptyInitializer = generateEmptyInitializer(context);
|
||||
var arrayType = (WasmType.Reference) context.typeMapper().mapType(ValueType.parse(Object[].class));
|
||||
var servicesFunctionType = context.functionTypes().of(arrayType);
|
||||
var classLocal = new WasmLocal(context.typeMapper().mapType(ValueType.parse(Class.class)));
|
||||
function.add(classLocal);
|
||||
|
||||
var classStruct = context.classInfoProvider().getClassInfo("java.lang.Class").getStructure();
|
||||
|
||||
var initializerGlobalName = context.names().topLevel("teavm@initializeServicesRef");
|
||||
var global = new WasmGlobal(initializerGlobalName, initializer.getType().getReference(),
|
||||
new WasmFunctionReference(initializer));
|
||||
context.module().globals.add(global);
|
||||
initializer.getBody().add(0, new WasmSetGlobal(global, new WasmFunctionReference(emptyInitializer)));
|
||||
|
||||
function.getBody().add(new WasmCallReference(new WasmGetGlobal(global), initializer.getType()));
|
||||
|
||||
var block = new WasmBlock(false);
|
||||
var servicesFunctionRef = new WasmStructGet(classStruct, new WasmGetLocal(classLocal),
|
||||
context.classInfoProvider().getServicesOffset());
|
||||
var nullCheckedRef = new WasmNullBranch(WasmNullCondition.NULL, servicesFunctionRef, block);
|
||||
var getServices = new WasmCallReference(nullCheckedRef, servicesFunctionType);
|
||||
block.getBody().add(new WasmReturn(getServices));
|
||||
function.getBody().add(block);
|
||||
|
||||
function.getBody().add(new WasmNullConstant(arrayType));
|
||||
}
|
||||
|
||||
private WasmFunction generateInitializer(WasmGCCustomGeneratorContext context) {
|
||||
var function = new WasmFunction(context.functionTypes().of(null));
|
||||
function.setReferenced(true);
|
||||
function.setName(context.names().topLevel("teavm@initializeServices"));
|
||||
context.module().functions.add(function);
|
||||
|
||||
var serviceTypes = information.serviceTypes();
|
||||
var classStruct = context.classInfoProvider().getClassInfo("java.lang.Class").getStructure();
|
||||
var fieldIndex = context.classInfoProvider().getServicesOffset();
|
||||
|
||||
for (var serviceType : serviceTypes) {
|
||||
var implementations = information.serviceImplementations(serviceType);
|
||||
var providerFunction = generateServiceProvider(context, serviceType, implementations);
|
||||
var classInfo = context.classInfoProvider().getClassInfo(serviceType);
|
||||
var classRef = new WasmGetGlobal(classInfo.getPointer());
|
||||
var providerRef = new WasmFunctionReference(providerFunction);
|
||||
function.getBody().add(new WasmStructSet(classStruct, classRef, fieldIndex, providerRef));
|
||||
}
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
private WasmFunction generateServiceProvider(WasmGCCustomGeneratorContext context,
|
||||
String interfaceName, Collection<? extends String> implementations) {
|
||||
var functionType = context.functionTypes().of(context.typeMapper().mapType(
|
||||
ValueType.parse(Object[].class)));
|
||||
var function = new WasmFunction(functionType);
|
||||
function.setName(context.names().topLevel(context.names().suggestForClass(interfaceName) + "@services"));
|
||||
function.setReferenced(true);
|
||||
context.module().functions.add(function);
|
||||
var tempVars = new TemporaryVariablePool(function);
|
||||
var util = new WasmGCGenerationUtil(context.classInfoProvider(), tempVars);
|
||||
var block = new WasmBlock(false);
|
||||
block.setType(context.typeMapper().mapType(ValueType.parse(Object[].class)));
|
||||
util.allocateArrayWithElements(ValueType.parse(Object.class), () -> {
|
||||
var items = new ArrayList<WasmExpression>();
|
||||
for (var implementationName : implementations) {
|
||||
items.add(instantiateService(context, function, implementationName));
|
||||
}
|
||||
return items;
|
||||
}, null, null, function.getBody());
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
private WasmExpression instantiateService(WasmGCCustomGeneratorContext context,
|
||||
WasmFunction function, String implementationName) {
|
||||
var implementationInfo = context.classInfoProvider().getClassInfo(implementationName);
|
||||
var block = new WasmBlock(false);
|
||||
block.setType(context.typeMapper().mapType(ValueType.parse(Object.class)));
|
||||
var tmpVar = new WasmLocal(implementationInfo.getType());
|
||||
function.add(tmpVar);
|
||||
var structNew = new WasmSetLocal(tmpVar, new WasmStructNewDefault(
|
||||
implementationInfo.getStructure()));
|
||||
block.getBody().add(structNew);
|
||||
|
||||
var initClassField = new WasmStructSet(implementationInfo.getStructure(), new WasmGetLocal(tmpVar),
|
||||
WasmGCClassInfoProvider.CLASS_FIELD_OFFSET, new WasmGetGlobal(implementationInfo.getPointer()));
|
||||
block.getBody().add(initClassField);
|
||||
|
||||
var constructor = context.functions().forInstanceMethod(
|
||||
new MethodReference(implementationName, INIT_METHOD));
|
||||
block.getBody().add(new WasmCall(constructor, new WasmGetLocal(tmpVar)));
|
||||
block.getBody().add(new WasmGetLocal(tmpVar));
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
private WasmFunction generateEmptyInitializer(WasmGCCustomGeneratorContext context) {
|
||||
var function = new WasmFunction(context.functionTypes().of(null));
|
||||
function.setReferenced(true);
|
||||
function.setName(context.names().topLevel("teavm@emptyServicesInitializer"));
|
||||
context.module().functions.add(function);
|
||||
function.getBody().add(new WasmReturn());
|
||||
return function;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.teavm.classlib.java.util;
|
||||
|
||||
import org.teavm.classlib.PlatformDetector;
|
||||
import org.teavm.classlib.java.lang.*;
|
||||
import org.teavm.platform.PlatformClass;
|
||||
|
||||
@ -45,7 +46,9 @@ public final class TServiceLoader<S> extends TObject implements TIterable<S> {
|
||||
}
|
||||
|
||||
public static <S> TServiceLoader<S> load(TClass<S> service) {
|
||||
return new TServiceLoader<>(doLoadServices(service.getPlatformClass()));
|
||||
return new TServiceLoader<>(PlatformDetector.isWebAssemblyGC()
|
||||
? doLoadServices(service)
|
||||
: doLoadServices(service.getPlatformClass()));
|
||||
}
|
||||
|
||||
public static <S> TServiceLoader<S> load(TClass<S> service, @SuppressWarnings("unused") TClassLoader loader) {
|
||||
@ -66,6 +69,16 @@ public final class TServiceLoader<S> extends TObject implements TIterable<S> {
|
||||
|
||||
private static native Object[] loadServices(PlatformClass cls);
|
||||
|
||||
private static Object[] doLoadServices(TClass<?> cls) {
|
||||
Object[] result = loadServices(cls);
|
||||
if (result == null) {
|
||||
result = new Object[0];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static native Object[] loadServices(TClass<?> cls);
|
||||
|
||||
public void reload() {
|
||||
// Do nothing, services are bound at build time
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ import org.teavm.backend.wasm.gc.TeaVMWasmGCHost;
|
||||
import org.teavm.backend.wasm.gc.WasmGCDependencies;
|
||||
import org.teavm.backend.wasm.generate.gc.WasmGCDeclarationsGenerator;
|
||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCCustomTypeMapperFactory;
|
||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGenerator;
|
||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGeneratorFactory;
|
||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGenerators;
|
||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsic;
|
||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicFactory;
|
||||
@ -62,6 +64,8 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
|
||||
private List<WasmGCIntrinsicFactory> intrinsicFactories = new ArrayList<>();
|
||||
private Map<MethodReference, WasmGCIntrinsic> customIntrinsics = new HashMap<>();
|
||||
private List<WasmGCCustomTypeMapperFactory> customTypeMapperFactories = new ArrayList<>();
|
||||
private Map<MethodReference, WasmGCCustomGenerator> customCustomGenerators = new HashMap<>();
|
||||
private List<WasmGCCustomGeneratorFactory> customGeneratorFactories = new ArrayList<>();
|
||||
|
||||
public void setObfuscated(boolean obfuscated) {
|
||||
this.obfuscated = obfuscated;
|
||||
@ -81,6 +85,16 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
|
||||
customIntrinsics.put(method, intrinsic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGeneratorFactory(WasmGCCustomGeneratorFactory factory) {
|
||||
customGeneratorFactories.add(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGenerator(MethodReference method, WasmGCCustomGenerator generator) {
|
||||
customCustomGenerators.put(method, generator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCustomTypeMapperFactory(WasmGCCustomTypeMapperFactory customTypeMapperFactory) {
|
||||
customTypeMapperFactories.add(customTypeMapperFactory);
|
||||
@ -151,8 +165,9 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
|
||||
@Override
|
||||
public void emit(ListableClassHolderSource classes, BuildTarget buildTarget, String outputName) throws IOException {
|
||||
var module = new WasmModule();
|
||||
var customGenerators = new WasmGCCustomGenerators();
|
||||
var intrinsics = new WasmGCIntrinsics(classes, intrinsicFactories, customIntrinsics);
|
||||
var customGenerators = new WasmGCCustomGenerators(classes, controller.getServices(),
|
||||
customGeneratorFactories, customCustomGenerators);
|
||||
var intrinsics = new WasmGCIntrinsics(classes, controller.getServices(), intrinsicFactories, customIntrinsics);
|
||||
var declarationsGenerator = new WasmGCDeclarationsGenerator(
|
||||
module,
|
||||
classes,
|
||||
|
@ -16,6 +16,8 @@
|
||||
package org.teavm.backend.wasm.gc;
|
||||
|
||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCCustomTypeMapperFactory;
|
||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGenerator;
|
||||
import org.teavm.backend.wasm.generators.gc.WasmGCCustomGeneratorFactory;
|
||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsic;
|
||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicFactory;
|
||||
import org.teavm.model.MethodReference;
|
||||
@ -26,5 +28,9 @@ public interface TeaVMWasmGCHost extends TeaVMHostExtension {
|
||||
|
||||
void addIntrinsic(MethodReference method, WasmGCIntrinsic intrinsic);
|
||||
|
||||
void addGeneratorFactory(WasmGCCustomGeneratorFactory factory);
|
||||
|
||||
void addGenerator(MethodReference method, WasmGCCustomGenerator generator);
|
||||
|
||||
void addCustomTypeMapperFactory(WasmGCCustomTypeMapperFactory customTypeMapperFactory);
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ public class WasmGCDeclarationsGenerator {
|
||||
module,
|
||||
classes,
|
||||
hierarchy,
|
||||
dependencyInfo,
|
||||
functionTypes,
|
||||
tags,
|
||||
metadataRequirements,
|
||||
|
@ -24,6 +24,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||
@ -75,6 +76,7 @@ import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
||||
import org.teavm.dependency.DependencyInfo;
|
||||
import org.teavm.model.ClassHierarchy;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
@ -143,6 +145,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||
private int arrayLengthOffset = -1;
|
||||
private int arrayGetOffset = -1;
|
||||
private int cloneOffset = -1;
|
||||
private int servicesOffset = -1;
|
||||
private WasmStructure arrayVirtualTableStruct;
|
||||
private WasmFunction arrayGetObjectFunction;
|
||||
private WasmFunction arrayLengthObjectFunction;
|
||||
@ -150,9 +153,10 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||
private WasmFunctionType arrayLengthType;
|
||||
private List<WasmStructure> nonInitializedStructures = new ArrayList<>();
|
||||
private WasmArray objectArrayType;
|
||||
private boolean hasLoadServices;
|
||||
|
||||
public WasmGCClassGenerator(WasmModule module, ClassReaderSource classSource,
|
||||
ClassHierarchy hierarchy,
|
||||
ClassHierarchy hierarchy, DependencyInfo dependencyInfo,
|
||||
WasmFunctionTypes functionTypes, TagRegistry tagRegistry,
|
||||
ClassMetadataRequirements metadataRequirements, WasmGCVirtualTableProvider virtualTables,
|
||||
BaseWasmFunctionRepository functionProvider, WasmGCNameProvider names,
|
||||
@ -177,6 +181,12 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||
typeMapper.setCustomTypeMappers(customTypeMapperFactories.stream()
|
||||
.map(factory -> factory.createTypeMapper(customTypeMapperFactoryContext))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
var loadServicesMethod = dependencyInfo.getMethod(new MethodReference(ServiceLoader.class, "loadServices",
|
||||
Class.class, Object[].class));
|
||||
if (loadServicesMethod != null && loadServicesMethod.isUsed()) {
|
||||
hasLoadServices = true;
|
||||
}
|
||||
}
|
||||
|
||||
private WasmGCCustomTypeMapperFactoryContext customTypeMapperFactoryContext() {
|
||||
@ -443,6 +453,12 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||
return cloneOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServicesOffset() {
|
||||
standardClasses.classClass().getStructure().init();
|
||||
return servicesOffset;
|
||||
}
|
||||
|
||||
private void initPrimitiveClass(WasmGCClassInfo classInfo, ValueType.Primitive type) {
|
||||
classInfo.initializer = target -> {
|
||||
int kind;
|
||||
@ -1152,6 +1168,11 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||
cloneOffset = fields.size();
|
||||
fields.add(createClassField(functionTypes.of(standardClasses.objectClass().getType(),
|
||||
standardClasses.objectClass().getType()).getReference().asStorage(), "clone"));
|
||||
if (hasLoadServices) {
|
||||
servicesOffset = fields.size();
|
||||
var serviceFunctionType = functionTypes.of(getClassInfo(ValueType.parse(Object[].class)).getType());
|
||||
fields.add(createClassField(serviceFunctionType.getReference().asStorage(), "services"));
|
||||
}
|
||||
if (metadataRequirements.hasEnumConstants()) {
|
||||
enumConstantsFunctionOffset = fields.size();
|
||||
var enumArrayType = getClassInfo(ValueType.arrayOf(ValueType.object("java.lang.Enum"))).getType();
|
||||
|
@ -67,6 +67,8 @@ public interface WasmGCClassInfoProvider {
|
||||
|
||||
int getCloneOffset();
|
||||
|
||||
int getServicesOffset();
|
||||
|
||||
default WasmGCClassInfo getClassInfo(String name) {
|
||||
return getClassInfo(ValueType.object(name));
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import org.teavm.ast.decompilation.Decompiler;
|
||||
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.PreciseValueType;
|
||||
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
|
||||
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
|
||||
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
|
||||
@ -269,6 +270,9 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||
var localVar = ast.getVariables().get(i);
|
||||
var representative = method.getProgram().variableAt(variableRepresentatives[i]);
|
||||
var inferredType = typeInference.typeOf(representative);
|
||||
if (inferredType == null) {
|
||||
inferredType = new PreciseValueType(ValueType.object("java.lang.Object"), false);
|
||||
}
|
||||
var type = !inferredType.isArrayUnwrap
|
||||
? typeMapper.mapType(inferredType.valueType)
|
||||
: classInfoProvider.getClassInfo(inferredType.valueType).getArray().getReference();
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.model.MethodReference;
|
||||
|
||||
public interface WasmGCCustomGeneratorFactory {
|
||||
WasmGCCustomGenerator createGenerator(MethodReference methodRef, WasmGCCustomGeneratorFactoryContext context);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2024 konsoletyper.
|
||||
*
|
||||
* 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.common.ServiceRepository;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
|
||||
public interface WasmGCCustomGeneratorFactoryContext {
|
||||
ClassReaderSource classes();
|
||||
|
||||
ServiceRepository services();
|
||||
}
|
@ -17,36 +17,46 @@ package org.teavm.backend.wasm.generators.gc;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.teavm.backend.wasm.generate.gc.methods.WasmGCCustomGeneratorProvider;
|
||||
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
||||
import org.teavm.common.ServiceRepository;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
public class WasmGCCustomGenerators implements WasmGCCustomGeneratorProvider {
|
||||
private Map<MethodReference, WasmGCCustomGenerator> generators = new HashMap<>();
|
||||
private List<WasmGCCustomGeneratorFactory> factories;
|
||||
private Map<MethodReference, Container> generators = new HashMap<>();
|
||||
private ClassReaderSource classes;
|
||||
private ServiceRepository services;
|
||||
|
||||
public WasmGCCustomGenerators() {
|
||||
public WasmGCCustomGenerators(ClassReaderSource classes, ServiceRepository services,
|
||||
List<WasmGCCustomGeneratorFactory> factories,
|
||||
Map<MethodReference, WasmGCCustomGenerator> generators) {
|
||||
this.factories = List.copyOf(factories);
|
||||
this.classes = classes;
|
||||
this.services = services;
|
||||
fillClass();
|
||||
fillStringPool();
|
||||
fillSystem();
|
||||
fillArray();
|
||||
for (var entry : generators.entrySet()) {
|
||||
add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void fillClass() {
|
||||
var classGenerators = new ClassGenerators();
|
||||
generators.put(new MethodReference(Class.class, "isAssignableFrom", Class.class, boolean.class),
|
||||
classGenerators);
|
||||
add(new MethodReference(Class.class, "isAssignableFrom", Class.class, boolean.class), classGenerators);
|
||||
}
|
||||
|
||||
private void fillStringPool() {
|
||||
generators.put(
|
||||
new MethodReference(WasmGCSupport.class, "nextByte", byte.class),
|
||||
new WasmGCStringPoolGenerator()
|
||||
);
|
||||
add(new MethodReference(WasmGCSupport.class, "nextByte", byte.class), new WasmGCStringPoolGenerator());
|
||||
}
|
||||
|
||||
private void fillSystem() {
|
||||
generators.put(
|
||||
add(
|
||||
new MethodReference(System.class, "doArrayCopy", Object.class, int.class, Object.class,
|
||||
int.class, int.class, void.class),
|
||||
new SystemDoArrayCopyGenerator()
|
||||
@ -55,12 +65,44 @@ public class WasmGCCustomGenerators implements WasmGCCustomGeneratorProvider {
|
||||
|
||||
private void fillArray() {
|
||||
var arrayGenerator = new ArrayGenerator();
|
||||
generators.put(new MethodReference(Array.class, "newInstanceImpl", Class.class, int.class, Object.class),
|
||||
arrayGenerator);
|
||||
add(new MethodReference(Array.class, "newInstanceImpl", Class.class, int.class, Object.class), arrayGenerator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmGCCustomGenerator get(MethodReference method) {
|
||||
return generators.get(method);
|
||||
var result = generators.get(method);
|
||||
if (result == null) {
|
||||
WasmGCCustomGenerator generator = null;
|
||||
for (var factory : factories) {
|
||||
generator = factory.createGenerator(method, factoryContext);
|
||||
}
|
||||
result = new Container(generator);
|
||||
generators.put(method, result);
|
||||
}
|
||||
return result.generator;
|
||||
}
|
||||
|
||||
private void add(MethodReference method, WasmGCCustomGenerator generator) {
|
||||
generators.put(method, new Container(generator));
|
||||
}
|
||||
|
||||
private static class Container {
|
||||
final WasmGCCustomGenerator generator;
|
||||
|
||||
Container(WasmGCCustomGenerator generator) {
|
||||
this.generator = generator;
|
||||
}
|
||||
}
|
||||
|
||||
private WasmGCCustomGeneratorFactoryContext factoryContext = new WasmGCCustomGeneratorFactoryContext() {
|
||||
@Override
|
||||
public ClassReaderSource classes() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceRepository services() {
|
||||
return services;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -15,8 +15,11 @@
|
||||
*/
|
||||
package org.teavm.backend.wasm.intrinsics.gc;
|
||||
|
||||
import org.teavm.common.ServiceRepository;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
|
||||
public interface WasmGCIntrinsicFactoryContext {
|
||||
ClassReaderSource classes();
|
||||
|
||||
ServiceRepository services();
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import java.util.Map;
|
||||
import org.teavm.backend.wasm.WasmRuntime;
|
||||
import org.teavm.backend.wasm.generate.gc.methods.WasmGCIntrinsicProvider;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||
import org.teavm.common.ServiceRepository;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
@ -30,10 +31,12 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||
private Map<MethodReference, IntrinsicContainer> intrinsics = new HashMap<>();
|
||||
private List<WasmGCIntrinsicFactory> factories;
|
||||
private ClassReaderSource classes;
|
||||
private ServiceRepository services;
|
||||
|
||||
public WasmGCIntrinsics(ClassReaderSource classes, List<WasmGCIntrinsicFactory> factories,
|
||||
Map<MethodReference, WasmGCIntrinsic> customIntrinsics) {
|
||||
public WasmGCIntrinsics(ClassReaderSource classes, ServiceRepository services,
|
||||
List<WasmGCIntrinsicFactory> factories, Map<MethodReference, WasmGCIntrinsic> customIntrinsics) {
|
||||
this.classes = classes;
|
||||
this.services = services;
|
||||
this.factories = List.copyOf(factories);
|
||||
factories = List.copyOf(factories);
|
||||
fillWasmRuntime();
|
||||
@ -179,5 +182,10 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||
public ClassReaderSource classes() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceRepository services() {
|
||||
return services;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user