mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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.c.TeaVMCHost;
|
||||||
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
||||||
import org.teavm.backend.wasm.TeaVMWasmHost;
|
import org.teavm.backend.wasm.TeaVMWasmHost;
|
||||||
|
import org.teavm.backend.wasm.gc.TeaVMWasmGCHost;
|
||||||
import org.teavm.classlib.ReflectionSupplier;
|
import org.teavm.classlib.ReflectionSupplier;
|
||||||
import org.teavm.classlib.impl.currency.CountriesGenerator;
|
import org.teavm.classlib.impl.currency.CountriesGenerator;
|
||||||
import org.teavm.classlib.impl.currency.CurrenciesGenerator;
|
import org.teavm.classlib.impl.currency.CurrenciesGenerator;
|
||||||
|
@ -94,6 +95,11 @@ public class JCLPlugin implements TeaVMPlugin {
|
||||||
if (wasmHost != null) {
|
if (wasmHost != null) {
|
||||||
wasmHost.add(new ServiceLoaderWasmSupport());
|
wasmHost.add(new ServiceLoaderWasmSupport());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var wasmGCHost = host.getExtension(TeaVMWasmGCHost.class);
|
||||||
|
if (wasmGCHost != null) {
|
||||||
|
wasmGCHost.addGeneratorFactory(new ServiceLoaderWasmGCSupport());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isBootstrap()) {
|
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;
|
package org.teavm.classlib.java.util;
|
||||||
|
|
||||||
|
import org.teavm.classlib.PlatformDetector;
|
||||||
import org.teavm.classlib.java.lang.*;
|
import org.teavm.classlib.java.lang.*;
|
||||||
import org.teavm.platform.PlatformClass;
|
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) {
|
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) {
|
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 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() {
|
public void reload() {
|
||||||
// Do nothing, services are bound at build time
|
// 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.gc.WasmGCDependencies;
|
||||||
import org.teavm.backend.wasm.generate.gc.WasmGCDeclarationsGenerator;
|
import org.teavm.backend.wasm.generate.gc.WasmGCDeclarationsGenerator;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCCustomTypeMapperFactory;
|
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.generators.gc.WasmGCCustomGenerators;
|
||||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicFactory;
|
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 List<WasmGCIntrinsicFactory> intrinsicFactories = new ArrayList<>();
|
||||||
private Map<MethodReference, WasmGCIntrinsic> customIntrinsics = new HashMap<>();
|
private Map<MethodReference, WasmGCIntrinsic> customIntrinsics = new HashMap<>();
|
||||||
private List<WasmGCCustomTypeMapperFactory> customTypeMapperFactories = new ArrayList<>();
|
private List<WasmGCCustomTypeMapperFactory> customTypeMapperFactories = new ArrayList<>();
|
||||||
|
private Map<MethodReference, WasmGCCustomGenerator> customCustomGenerators = new HashMap<>();
|
||||||
|
private List<WasmGCCustomGeneratorFactory> customGeneratorFactories = new ArrayList<>();
|
||||||
|
|
||||||
public void setObfuscated(boolean obfuscated) {
|
public void setObfuscated(boolean obfuscated) {
|
||||||
this.obfuscated = obfuscated;
|
this.obfuscated = obfuscated;
|
||||||
|
@ -81,6 +85,16 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
|
||||||
customIntrinsics.put(method, intrinsic);
|
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
|
@Override
|
||||||
public void addCustomTypeMapperFactory(WasmGCCustomTypeMapperFactory customTypeMapperFactory) {
|
public void addCustomTypeMapperFactory(WasmGCCustomTypeMapperFactory customTypeMapperFactory) {
|
||||||
customTypeMapperFactories.add(customTypeMapperFactory);
|
customTypeMapperFactories.add(customTypeMapperFactory);
|
||||||
|
@ -151,8 +165,9 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
|
||||||
@Override
|
@Override
|
||||||
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(classes, controller.getServices(),
|
||||||
var intrinsics = new WasmGCIntrinsics(classes, intrinsicFactories, customIntrinsics);
|
customGeneratorFactories, customCustomGenerators);
|
||||||
|
var intrinsics = new WasmGCIntrinsics(classes, controller.getServices(), intrinsicFactories, customIntrinsics);
|
||||||
var declarationsGenerator = new WasmGCDeclarationsGenerator(
|
var declarationsGenerator = new WasmGCDeclarationsGenerator(
|
||||||
module,
|
module,
|
||||||
classes,
|
classes,
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
package org.teavm.backend.wasm.gc;
|
package org.teavm.backend.wasm.gc;
|
||||||
|
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCCustomTypeMapperFactory;
|
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.WasmGCIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicFactory;
|
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicFactory;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
@ -26,5 +28,9 @@ public interface TeaVMWasmGCHost extends TeaVMHostExtension {
|
||||||
|
|
||||||
void addIntrinsic(MethodReference method, WasmGCIntrinsic intrinsic);
|
void addIntrinsic(MethodReference method, WasmGCIntrinsic intrinsic);
|
||||||
|
|
||||||
|
void addGeneratorFactory(WasmGCCustomGeneratorFactory factory);
|
||||||
|
|
||||||
|
void addGenerator(MethodReference method, WasmGCCustomGenerator generator);
|
||||||
|
|
||||||
void addCustomTypeMapperFactory(WasmGCCustomTypeMapperFactory customTypeMapperFactory);
|
void addCustomTypeMapperFactory(WasmGCCustomTypeMapperFactory customTypeMapperFactory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ public class WasmGCDeclarationsGenerator {
|
||||||
module,
|
module,
|
||||||
classes,
|
classes,
|
||||||
hierarchy,
|
hierarchy,
|
||||||
|
dependencyInfo,
|
||||||
functionTypes,
|
functionTypes,
|
||||||
tags,
|
tags,
|
||||||
metadataRequirements,
|
metadataRequirements,
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
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.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
||||||
|
import org.teavm.dependency.DependencyInfo;
|
||||||
import org.teavm.model.ClassHierarchy;
|
import org.teavm.model.ClassHierarchy;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
@ -143,6 +145,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
private int arrayLengthOffset = -1;
|
private int arrayLengthOffset = -1;
|
||||||
private int arrayGetOffset = -1;
|
private int arrayGetOffset = -1;
|
||||||
private int cloneOffset = -1;
|
private int cloneOffset = -1;
|
||||||
|
private int servicesOffset = -1;
|
||||||
private WasmStructure arrayVirtualTableStruct;
|
private WasmStructure arrayVirtualTableStruct;
|
||||||
private WasmFunction arrayGetObjectFunction;
|
private WasmFunction arrayGetObjectFunction;
|
||||||
private WasmFunction arrayLengthObjectFunction;
|
private WasmFunction arrayLengthObjectFunction;
|
||||||
|
@ -150,9 +153,10 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
private WasmFunctionType arrayLengthType;
|
private WasmFunctionType arrayLengthType;
|
||||||
private List<WasmStructure> nonInitializedStructures = new ArrayList<>();
|
private List<WasmStructure> nonInitializedStructures = new ArrayList<>();
|
||||||
private WasmArray objectArrayType;
|
private WasmArray objectArrayType;
|
||||||
|
private boolean hasLoadServices;
|
||||||
|
|
||||||
public WasmGCClassGenerator(WasmModule module, ClassReaderSource classSource,
|
public WasmGCClassGenerator(WasmModule module, ClassReaderSource classSource,
|
||||||
ClassHierarchy hierarchy,
|
ClassHierarchy hierarchy, DependencyInfo dependencyInfo,
|
||||||
WasmFunctionTypes functionTypes, TagRegistry tagRegistry,
|
WasmFunctionTypes functionTypes, TagRegistry tagRegistry,
|
||||||
ClassMetadataRequirements metadataRequirements, WasmGCVirtualTableProvider virtualTables,
|
ClassMetadataRequirements metadataRequirements, WasmGCVirtualTableProvider virtualTables,
|
||||||
BaseWasmFunctionRepository functionProvider, WasmGCNameProvider names,
|
BaseWasmFunctionRepository functionProvider, WasmGCNameProvider names,
|
||||||
|
@ -177,6 +181,12 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
typeMapper.setCustomTypeMappers(customTypeMapperFactories.stream()
|
typeMapper.setCustomTypeMappers(customTypeMapperFactories.stream()
|
||||||
.map(factory -> factory.createTypeMapper(customTypeMapperFactoryContext))
|
.map(factory -> factory.createTypeMapper(customTypeMapperFactoryContext))
|
||||||
.collect(Collectors.toList()));
|
.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() {
|
private WasmGCCustomTypeMapperFactoryContext customTypeMapperFactoryContext() {
|
||||||
|
@ -443,6 +453,12 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
return cloneOffset;
|
return cloneOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getServicesOffset() {
|
||||||
|
standardClasses.classClass().getStructure().init();
|
||||||
|
return servicesOffset;
|
||||||
|
}
|
||||||
|
|
||||||
private void initPrimitiveClass(WasmGCClassInfo classInfo, ValueType.Primitive type) {
|
private void initPrimitiveClass(WasmGCClassInfo classInfo, ValueType.Primitive type) {
|
||||||
classInfo.initializer = target -> {
|
classInfo.initializer = target -> {
|
||||||
int kind;
|
int kind;
|
||||||
|
@ -1152,6 +1168,11 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
cloneOffset = fields.size();
|
cloneOffset = fields.size();
|
||||||
fields.add(createClassField(functionTypes.of(standardClasses.objectClass().getType(),
|
fields.add(createClassField(functionTypes.of(standardClasses.objectClass().getType(),
|
||||||
standardClasses.objectClass().getType()).getReference().asStorage(), "clone"));
|
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()) {
|
if (metadataRequirements.hasEnumConstants()) {
|
||||||
enumConstantsFunctionOffset = fields.size();
|
enumConstantsFunctionOffset = fields.size();
|
||||||
var enumArrayType = getClassInfo(ValueType.arrayOf(ValueType.object("java.lang.Enum"))).getType();
|
var enumArrayType = getClassInfo(ValueType.arrayOf(ValueType.object("java.lang.Enum"))).getType();
|
||||||
|
|
|
@ -67,6 +67,8 @@ public interface WasmGCClassInfoProvider {
|
||||||
|
|
||||||
int getCloneOffset();
|
int getCloneOffset();
|
||||||
|
|
||||||
|
int getServicesOffset();
|
||||||
|
|
||||||
default WasmGCClassInfo getClassInfo(String name) {
|
default WasmGCClassInfo getClassInfo(String name) {
|
||||||
return getClassInfo(ValueType.object(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.BaseWasmFunctionRepository;
|
||||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
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.gc.PreciseValueType;
|
||||||
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
|
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
|
||||||
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
|
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
|
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
|
||||||
|
@ -269,6 +270,9 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
var localVar = ast.getVariables().get(i);
|
var localVar = ast.getVariables().get(i);
|
||||||
var representative = method.getProgram().variableAt(variableRepresentatives[i]);
|
var representative = method.getProgram().variableAt(variableRepresentatives[i]);
|
||||||
var inferredType = typeInference.typeOf(representative);
|
var inferredType = typeInference.typeOf(representative);
|
||||||
|
if (inferredType == null) {
|
||||||
|
inferredType = new PreciseValueType(ValueType.object("java.lang.Object"), false);
|
||||||
|
}
|
||||||
var type = !inferredType.isArrayUnwrap
|
var type = !inferredType.isArrayUnwrap
|
||||||
? typeMapper.mapType(inferredType.valueType)
|
? typeMapper.mapType(inferredType.valueType)
|
||||||
: classInfoProvider.getClassInfo(inferredType.valueType).getArray().getReference();
|
: 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.lang.reflect.Array;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.teavm.backend.wasm.generate.gc.methods.WasmGCCustomGeneratorProvider;
|
import org.teavm.backend.wasm.generate.gc.methods.WasmGCCustomGeneratorProvider;
|
||||||
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
||||||
|
import org.teavm.common.ServiceRepository;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
public class WasmGCCustomGenerators implements WasmGCCustomGeneratorProvider {
|
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();
|
fillClass();
|
||||||
fillStringPool();
|
fillStringPool();
|
||||||
fillSystem();
|
fillSystem();
|
||||||
fillArray();
|
fillArray();
|
||||||
|
for (var entry : generators.entrySet()) {
|
||||||
|
add(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillClass() {
|
private void fillClass() {
|
||||||
var classGenerators = new ClassGenerators();
|
var classGenerators = new ClassGenerators();
|
||||||
generators.put(new MethodReference(Class.class, "isAssignableFrom", Class.class, boolean.class),
|
add(new MethodReference(Class.class, "isAssignableFrom", Class.class, boolean.class), classGenerators);
|
||||||
classGenerators);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillStringPool() {
|
private void fillStringPool() {
|
||||||
generators.put(
|
add(new MethodReference(WasmGCSupport.class, "nextByte", byte.class), new WasmGCStringPoolGenerator());
|
||||||
new MethodReference(WasmGCSupport.class, "nextByte", byte.class),
|
|
||||||
new WasmGCStringPoolGenerator()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillSystem() {
|
private void fillSystem() {
|
||||||
generators.put(
|
add(
|
||||||
new MethodReference(System.class, "doArrayCopy", Object.class, int.class, Object.class,
|
new MethodReference(System.class, "doArrayCopy", Object.class, int.class, Object.class,
|
||||||
int.class, int.class, void.class),
|
int.class, int.class, void.class),
|
||||||
new SystemDoArrayCopyGenerator()
|
new SystemDoArrayCopyGenerator()
|
||||||
|
@ -55,12 +65,44 @@ public class WasmGCCustomGenerators implements WasmGCCustomGeneratorProvider {
|
||||||
|
|
||||||
private void fillArray() {
|
private void fillArray() {
|
||||||
var arrayGenerator = new ArrayGenerator();
|
var arrayGenerator = new ArrayGenerator();
|
||||||
generators.put(new MethodReference(Array.class, "newInstanceImpl", Class.class, int.class, Object.class),
|
add(new MethodReference(Array.class, "newInstanceImpl", Class.class, int.class, Object.class), arrayGenerator);
|
||||||
arrayGenerator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WasmGCCustomGenerator get(MethodReference method) {
|
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;
|
package org.teavm.backend.wasm.intrinsics.gc;
|
||||||
|
|
||||||
|
import org.teavm.common.ServiceRepository;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
|
||||||
public interface WasmGCIntrinsicFactoryContext {
|
public interface WasmGCIntrinsicFactoryContext {
|
||||||
ClassReaderSource classes();
|
ClassReaderSource classes();
|
||||||
|
|
||||||
|
ServiceRepository services();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Map;
|
||||||
import org.teavm.backend.wasm.WasmRuntime;
|
import org.teavm.backend.wasm.WasmRuntime;
|
||||||
import org.teavm.backend.wasm.generate.gc.methods.WasmGCIntrinsicProvider;
|
import org.teavm.backend.wasm.generate.gc.methods.WasmGCIntrinsicProvider;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
|
import org.teavm.common.ServiceRepository;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
@ -30,10 +31,12 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||||
private Map<MethodReference, IntrinsicContainer> intrinsics = new HashMap<>();
|
private Map<MethodReference, IntrinsicContainer> intrinsics = new HashMap<>();
|
||||||
private List<WasmGCIntrinsicFactory> factories;
|
private List<WasmGCIntrinsicFactory> factories;
|
||||||
private ClassReaderSource classes;
|
private ClassReaderSource classes;
|
||||||
|
private ServiceRepository services;
|
||||||
|
|
||||||
public WasmGCIntrinsics(ClassReaderSource classes, List<WasmGCIntrinsicFactory> factories,
|
public WasmGCIntrinsics(ClassReaderSource classes, ServiceRepository services,
|
||||||
Map<MethodReference, WasmGCIntrinsic> customIntrinsics) {
|
List<WasmGCIntrinsicFactory> factories, Map<MethodReference, WasmGCIntrinsic> customIntrinsics) {
|
||||||
this.classes = classes;
|
this.classes = classes;
|
||||||
|
this.services = services;
|
||||||
this.factories = List.copyOf(factories);
|
this.factories = List.copyOf(factories);
|
||||||
factories = List.copyOf(factories);
|
factories = List.copyOf(factories);
|
||||||
fillWasmRuntime();
|
fillWasmRuntime();
|
||||||
|
@ -179,5 +182,10 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||||
public ClassReaderSource classes() {
|
public ClassReaderSource classes() {
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServiceRepository services() {
|
||||||
|
return services;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user