WASM: preparing to implement metadata API

This commit is contained in:
Alexey Andreev 2017-04-11 23:29:06 +03:00
parent 530fe1d277
commit f1da7a417e
28 changed files with 202 additions and 88 deletions

View File

@ -0,0 +1,23 @@
/*
* Copyright 2017 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;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsicFactory;
import org.teavm.vm.spi.TeaVMHostExtension;
public interface TeaVMWasmHost extends TeaVMHostExtension {
void add(WasmIntrinsicFactory intrinsicFactory);
}

View File

@ -25,6 +25,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import org.teavm.ast.decompilation.Decompiler;
import org.teavm.backend.wasm.binary.BinaryWriter;
@ -46,6 +47,8 @@ import org.teavm.backend.wasm.intrinsics.PlatformIntrinsic;
import org.teavm.backend.wasm.intrinsics.PlatformObjectIntrinsic;
import org.teavm.backend.wasm.intrinsics.ShadowStackIntrinsic;
import org.teavm.backend.wasm.intrinsics.StructureIntrinsic;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsicFactory;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsicFactoryContext;
import org.teavm.backend.wasm.intrinsics.WasmRuntimeIntrinsic;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmLocal;
@ -76,6 +79,7 @@ import org.teavm.backend.wasm.render.WasmCRenderer;
import org.teavm.backend.wasm.render.WasmRenderer;
import org.teavm.backend.wasm.transformation.IndirectCallTraceTransformation;
import org.teavm.backend.wasm.transformation.MemoryAccessTraceTransformation;
import org.teavm.common.ServiceRepository;
import org.teavm.dependency.ClassDependency;
import org.teavm.dependency.DependencyChecker;
import org.teavm.dependency.DependencyListener;
@ -89,6 +93,7 @@ import org.teavm.model.CallLocation;
import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource;
import org.teavm.model.ElementModifier;
import org.teavm.model.FieldReader;
import org.teavm.model.FieldReference;
@ -122,7 +127,7 @@ import org.teavm.vm.TeaVMTarget;
import org.teavm.vm.TeaVMTargetController;
import org.teavm.vm.spi.TeaVMHostExtension;
public class WasmTarget implements TeaVMTarget {
public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
private TeaVMTargetController controller;
private boolean debugging;
private boolean wastEmitted;
@ -132,6 +137,7 @@ public class WasmTarget implements TeaVMTarget {
private ClassInitializerTransformer classInitializerTransformer;
private ShadowStackTransformer shadowStackTransformer;
private WasmBinaryVersion version = WasmBinaryVersion.V_0x1;
private List<WasmIntrinsicFactory> additionalIntrinsics = new ArrayList<>();
@Override
public void setController(TeaVMTargetController controller) {
@ -142,9 +148,14 @@ public class WasmTarget implements TeaVMTarget {
clinitInsertionTransformer = new ClassInitializerInsertionTransformer(controller.getUnprocessedClassSource());
}
@Override
public void add(WasmIntrinsicFactory intrinsic) {
additionalIntrinsics.add(intrinsic);
}
@Override
public List<TeaVMHostExtension> getHostExtensions() {
return Collections.emptyList();
return Collections.singletonList(this);
}
@Override
@ -296,6 +307,12 @@ public class WasmTarget implements TeaVMTarget {
context.addIntrinsic(new PlatformClassIntrinsic());
context.addIntrinsic(new PlatformObjectIntrinsic(classGenerator));
context.addIntrinsic(new ClassIntrinsic());
IntrinsicFactoryContext intrinsicFactoryContext = new IntrinsicFactoryContext(classes);
for (WasmIntrinsicFactory additionalIntrinsicFactory : additionalIntrinsics) {
context.addIntrinsic(additionalIntrinsicFactory.create(intrinsicFactoryContext));
}
GCIntrinsic gcIntrinsic = new GCIntrinsic();
context.addIntrinsic(gcIntrinsic);
MutatorIntrinsic mutatorIntrinsic = new MutatorIntrinsic();
@ -379,6 +396,34 @@ public class WasmTarget implements TeaVMTarget {
}
}
private class IntrinsicFactoryContext implements WasmIntrinsicFactoryContext {
private ClassReaderSource classSource;
public IntrinsicFactoryContext(ClassReaderSource classSource) {
this.classSource = classSource;
}
@Override
public ClassReaderSource getClassSource() {
return classSource;
}
@Override
public ClassLoader getClassLoader() {
return controller.getClassLoader();
}
@Override
public ServiceRepository getServices() {
return controller.getServices();
}
@Override
public Properties getProperties() {
return controller.getProperties();
}
}
private String getBaseName(String name) {
int index = name.lastIndexOf('.');
return index < 0 ? name : name.substring(0, index);

View File

@ -1529,6 +1529,11 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
accept(expr);
return result;
}
@Override
public BinaryWriter getBinaryWriter() {
return binaryWriter;
}
};
private WasmLocal getTemporary(WasmType type) {

View File

@ -0,0 +1,21 @@
/*
* Copyright 2017 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;
@FunctionalInterface
public interface WasmIntrinsicFactory {
WasmIntrinsic create(WasmIntrinsicFactoryContext context);
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2017 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;
import java.util.Properties;
import org.teavm.common.ServiceRepository;
import org.teavm.model.ClassReaderSource;
public interface WasmIntrinsicFactoryContext {
ClassReaderSource getClassSource();
ClassLoader getClassLoader();
ServiceRepository getServices();
Properties getProperties();
}

View File

@ -16,8 +16,11 @@
package org.teavm.backend.wasm.intrinsics;
import org.teavm.ast.Expr;
import org.teavm.backend.wasm.binary.BinaryWriter;
import org.teavm.backend.wasm.model.expression.WasmExpression;
public interface WasmIntrinsicManager {
WasmExpression generate(Expr expr);
BinaryWriter getBinaryWriter();
}

View File

@ -15,10 +15,6 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface BooleanResource extends Resource {
boolean getValue();

View File

@ -15,10 +15,6 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface ByteResource extends Resource {
byte getValue();

View File

@ -15,9 +15,5 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface ClassResource extends Resource {
}

View File

@ -15,10 +15,6 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface DoubleResource extends Resource {
double getValue();

View File

@ -15,10 +15,6 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface FloatResource extends Resource {
float getValue();

View File

@ -15,10 +15,6 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface IntResource extends Resource {
int getValue();

View File

@ -15,11 +15,6 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
* @param <T>
*/
public interface ResourceArray<T extends Resource> extends Resource {
int size();

View File

@ -15,11 +15,6 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
* @param <T>
*/
public interface ResourceMap<T extends Resource> extends Resource {
boolean has(String key);

View File

@ -15,10 +15,6 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface ShortResource extends Resource {
short getValue();

View File

@ -15,9 +15,5 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface StaticFieldResource extends Resource {
}

View File

@ -15,10 +15,6 @@
*/
package org.teavm.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface StringResource extends Resource {
String getValue();

View File

@ -22,10 +22,6 @@ import org.teavm.model.FieldReference;
import org.teavm.model.ListableClassReaderSource;
import org.teavm.platform.metadata.*;
/**
*
* @author Alexey Andreev
*/
class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
private ListableClassReaderSource classSource;
private ClassLoader classLoader;

View File

@ -0,0 +1,55 @@
/*
* Copyright 2017 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.platform.plugin;
import java.util.Properties;
import org.teavm.ast.InvocationExpr;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsic;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsicManager;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.model.AnnotationReader;
import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource;
import org.teavm.model.MethodReference;
import org.teavm.platform.metadata.MetadataProvider;
public class MetadataIntrinsic implements WasmIntrinsic {
private ClassReaderSource classSource;
private ClassLoader classLoader;
private Properties properties;
public MetadataIntrinsic(ClassReaderSource classSource, ClassLoader classLoader, Properties properties) {
this.classSource = classSource;
this.classLoader = classLoader;
this.properties = properties;
}
@Override
public boolean isApplicable(MethodReference methodReference) {
ClassReader cls = classSource.get(methodReference.getClassName());
if (cls == null) {
return false;
}
AnnotationReader annot = cls.getAnnotations().get(MetadataProvider.class.getName());
return annot != null;
}
@Override
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
return null;
}
}

View File

@ -26,10 +26,6 @@ import org.teavm.platform.metadata.MetadataGenerator;
import org.teavm.platform.metadata.MetadataProvider;
import org.teavm.platform.metadata.Resource;
/**
*
* @author Alexey Andreev
*/
public class MetadataProviderNativeGenerator implements Generator {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {

View File

@ -20,10 +20,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author Alexey Andreev
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
@interface MetadataProviderRef {

View File

@ -15,16 +15,26 @@
*/
package org.teavm.platform.plugin;
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
import org.teavm.backend.wasm.TeaVMWasmHost;
import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin;
public class PlatformPlugin implements TeaVMPlugin {
@Override
public void install(TeaVMHost host) {
if (host.getExtension(TeaVMJavaScriptHost.class) != null) {
host.add(new MetadataProviderTransformer());
host.add(new ResourceTransformer());
host.add(new ResourceAccessorTransformer(host));
host.add(new ResourceAccessorDependencyListener());
}
TeaVMWasmHost wasmHost = host.getExtension(TeaVMWasmHost.class);
if (wasmHost != null) {
wasmHost.add(ctx -> new MetadataIntrinsic(ctx.getClassSource(), ctx.getClassLoader(), ctx.getProperties()));
}
host.add(new AsyncMethodProcessor());
host.add(new NewInstanceDependencySupport());
host.add(new ClassLookupDependencySupport());

View File

@ -17,10 +17,6 @@ package org.teavm.platform.plugin;
import org.teavm.platform.metadata.Resource;
/**
*
* @author Alexey Andreev
*/
final class ResourceAccessor {
private ResourceAccessor() {
}

View File

@ -20,10 +20,6 @@ import org.teavm.dependency.DependencyAgent;
import org.teavm.dependency.MethodDependency;
import org.teavm.model.CallLocation;
/**
*
* @author Alexey Andreev
*/
class ResourceAccessorDependencyListener extends AbstractDependencyListener {
@Override
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {

View File

@ -21,10 +21,6 @@ import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
class ResourceAccessorGenerator implements Generator {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {

View File

@ -23,10 +23,6 @@ import org.teavm.backend.javascript.spi.InjectorContext;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
/**
*
* @author Alexey Andreev
*/
class ResourceAccessorInjector implements Injector {
@Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {

View File

@ -25,10 +25,10 @@ import org.teavm.model.MethodHolder;
import org.teavm.vm.spi.TeaVMHost;
class ResourceAccessorTransformer implements ClassHolderTransformer {
private TeaVMJavaScriptHost vm;
private TeaVMJavaScriptHost jsHost;
public ResourceAccessorTransformer(TeaVMHost vm) {
this.vm = vm.getExtension(TeaVMJavaScriptHost.class);
this.jsHost = vm.getExtension(TeaVMJavaScriptHost.class);
}
@Override
@ -38,9 +38,9 @@ class ResourceAccessorTransformer implements ClassHolderTransformer {
for (MethodHolder method : cls.getMethods()) {
if (method.hasModifier(ElementModifier.NATIVE)) {
if (method.getName().equals("keys")) {
vm.add(method.getReference(), new ResourceAccessorGenerator());
jsHost.add(method.getReference(), new ResourceAccessorGenerator());
} else {
vm.add(method.getReference(), injector);
jsHost.add(method.getReference(), injector);
}
}
}

View File

@ -18,10 +18,6 @@ package org.teavm.platform.plugin;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*;
/**
*
* @author Alexey Andreev
*/
class ResourceTransformer implements ClassHolderTransformer {
@Override
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {