From ade00cc984ec046a1d42c4db186437ec46a455f0 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 26 Feb 2019 00:10:07 +0300 Subject: [PATCH] C backend: fix bugs --- .../java/org/teavm/backend/c/CTarget.java | 12 +++++++++--- .../backend/c/generate/ClassGenerator.java | 6 ++++++ .../backend/c/generate/GenerationContext.java | 11 +++++++++-- .../backend/c/generators/ArrayGenerator.java | 19 ++++++++++++++----- .../c/generators/GeneratorContext.java | 3 +++ .../org/teavm/backend/wasm/WasmTarget.java | 2 +- .../model/classes/VirtualTableProvider.java | 15 ++++++++++----- core/src/main/java/org/teavm/vm/TeaVM.java | 5 +++++ .../org/teavm/vm/TeaVMTargetController.java | 3 +++ .../java/org/teavm/platform/Platform.java | 1 + .../platform/plugin/PlatformGenerator.java | 3 +++ 11 files changed, 64 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/org/teavm/backend/c/CTarget.java b/core/src/main/java/org/teavm/backend/c/CTarget.java index 575ec5a5f..f45eadde2 100644 --- a/core/src/main/java/org/teavm/backend/c/CTarget.java +++ b/core/src/main/java/org/teavm/backend/c/CTarget.java @@ -108,6 +108,9 @@ import org.teavm.vm.TeaVMTargetController; import org.teavm.vm.spi.TeaVMHostExtension; public class CTarget implements TeaVMTarget, TeaVMCHost { + private static final Set VIRTUAL_METHODS = new HashSet<>(Arrays.asList( + new MethodReference(Object.class, "clone", Object.class) + )); private TeaVMTargetController controller; private ClassInitializerInsertionTransformer clinitInsertionTransformer; private ClassInitializerEliminator classInitializerEliminator; @@ -146,6 +149,8 @@ public class CTarget implements TeaVMTarget, TeaVMCHost { clinitInsertionTransformer = new ClassInitializerInsertionTransformer(controller.getUnprocessedClassSource()); nullCheckInsertion = new NullCheckInsertion(characteristics); nullCheckTransformation = new NullCheckTransformation(); + + controller.addVirtualMethods(VIRTUAL_METHODS::contains); } @Override @@ -243,8 +248,9 @@ public class CTarget implements TeaVMTarget, TeaVMCHost { List generators = new ArrayList<>(); generators.add(new ArrayGenerator()); - GenerationContext context = new GenerationContext(vtableProvider, characteristics, stringPool, nameProvider, - controller.getDiagnostics(), classes, intrinsics, generators); + GenerationContext context = new GenerationContext(vtableProvider, characteristics, + controller.getDependencyInfo(), stringPool, nameProvider, controller.getDiagnostics(), classes, + intrinsics, generators); BufferedCodeWriter codeWriter = new BufferedCodeWriter(); copyResource(codeWriter, "runtime.c"); @@ -362,7 +368,7 @@ public class CTarget implements TeaVMTarget, TeaVMCHost { } } - return new VirtualTableProvider(classes, virtualMethods); + return new VirtualTableProvider(classes, virtualMethods, controller::isVirtual); } private void generateSpecialFunctions(GenerationContext context, CodeWriter writer) { diff --git a/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java b/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java index 7c3a63246..878da78d7 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java +++ b/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java @@ -28,6 +28,7 @@ import org.teavm.ast.decompilation.Decompiler; import org.teavm.backend.c.generators.Generator; import org.teavm.backend.c.generators.GeneratorContext; import org.teavm.backend.lowlevel.generate.ClassGeneratorUtil; +import org.teavm.dependency.DependencyInfo; import org.teavm.diagnostics.Diagnostics; import org.teavm.interop.Address; import org.teavm.interop.DelegateTo; @@ -672,6 +673,11 @@ public class ClassGenerator { return context.getClassSource(); } + @Override + public DependencyInfo getDependencies() { + return context.getDependencies(); + } + @Override public String getParameterName(int index) { return index == 0 ? "_this_" : "local_" + index; diff --git a/core/src/main/java/org/teavm/backend/c/generate/GenerationContext.java b/core/src/main/java/org/teavm/backend/c/generate/GenerationContext.java index 3b2572518..821456274 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/GenerationContext.java +++ b/core/src/main/java/org/teavm/backend/c/generate/GenerationContext.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Map; import org.teavm.backend.c.generators.Generator; import org.teavm.backend.c.intrinsic.Intrinsic; +import org.teavm.dependency.DependencyInfo; import org.teavm.diagnostics.Diagnostics; import org.teavm.model.ClassReaderSource; import org.teavm.model.MethodReference; @@ -30,6 +31,7 @@ import org.teavm.model.lowlevel.Characteristics; public class GenerationContext { private VirtualTableProvider virtualTableProvider; private Characteristics characteristics; + private DependencyInfo dependencies; private StringPool stringPool; private NameProvider names; private Diagnostics diagnostics; @@ -39,10 +41,11 @@ public class GenerationContext { private Map intrinsicCache = new HashMap<>(); public GenerationContext(VirtualTableProvider virtualTableProvider, Characteristics characteristics, - StringPool stringPool, NameProvider names, Diagnostics diagnostics, ClassReaderSource classSource, - List intrinsics, List generators) { + DependencyInfo dependencies, StringPool stringPool, NameProvider names, Diagnostics diagnostics, + ClassReaderSource classSource, List intrinsics, List generators) { this.virtualTableProvider = virtualTableProvider; this.characteristics = characteristics; + this.dependencies = dependencies; this.stringPool = stringPool; this.names = names; this.diagnostics = diagnostics; @@ -63,6 +66,10 @@ public class GenerationContext { return characteristics; } + public DependencyInfo getDependencies() { + return dependencies; + } + public StringPool getStringPool() { return stringPool; } diff --git a/core/src/main/java/org/teavm/backend/c/generators/ArrayGenerator.java b/core/src/main/java/org/teavm/backend/c/generators/ArrayGenerator.java index 0b8986109..40644e428 100644 --- a/core/src/main/java/org/teavm/backend/c/generators/ArrayGenerator.java +++ b/core/src/main/java/org/teavm/backend/c/generators/ArrayGenerator.java @@ -16,8 +16,12 @@ package org.teavm.backend.c.generators; import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import org.teavm.backend.c.generate.CodeWriter; -import org.teavm.model.ClassReader; +import org.teavm.dependency.MethodDependencyInfo; +import org.teavm.dependency.ValueDependencyInfo; import org.teavm.model.FieldReference; import org.teavm.model.MethodReference; import org.teavm.model.ValueType; @@ -69,14 +73,19 @@ public class ArrayGenerator implements Generator { writer.println("switch ((flags >> " + RuntimeClass.PRIMITIVE_SHIFT + ") & " + RuntimeClass.PRIMITIVE_MASK + ") {").indent(); + MethodDependencyInfo dependency = context.getDependencies().getMethod(new MethodReference(Array.class, + "getImpl", Object.class, int.class, Object.class)); + ValueDependencyInfo arrayDependency = dependency.getVariable(1); + Set types = new HashSet<>(Arrays.asList(arrayDependency.getTypes())); for (int i = 0; i < primitiveWrappers.length; ++i) { + String typeName = ValueType.arrayOf(primitiveTypes[i]).toString(); + if (!types.contains(typeName)) { + continue; + } + String wrapper = "java.lang." + primitiveWrappers[i]; MethodReference methodRef = new MethodReference(wrapper, "valueOf", primitiveTypes[i], ValueType.object(wrapper)); - ClassReader cls = context.getClassSource().get(methodRef.getClassName()); - if (cls == null || cls.getMethod(methodRef.getDescriptor()) == null) { - continue; - } String type = CodeWriter.strictTypeAsString(primitiveTypes[i]); writer.println("case " + primitives[i] + ":").indent(); diff --git a/core/src/main/java/org/teavm/backend/c/generators/GeneratorContext.java b/core/src/main/java/org/teavm/backend/c/generators/GeneratorContext.java index 2f4853750..fcdd003e1 100644 --- a/core/src/main/java/org/teavm/backend/c/generators/GeneratorContext.java +++ b/core/src/main/java/org/teavm/backend/c/generators/GeneratorContext.java @@ -16,6 +16,7 @@ package org.teavm.backend.c.generators; import org.teavm.backend.c.generate.NameProvider; +import org.teavm.dependency.DependencyInfo; import org.teavm.diagnostics.Diagnostics; import org.teavm.model.ClassReaderSource; @@ -26,5 +27,7 @@ public interface GeneratorContext { ClassReaderSource getClassSource(); + DependencyInfo getDependencies(); + String getParameterName(int index); } diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java index 477dc9899..edbe79d66 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java @@ -794,7 +794,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost { } } - return new VirtualTableProvider(classes, virtualMethods); + return new VirtualTableProvider(classes, virtualMethods, controller::isVirtual); } @Override diff --git a/core/src/main/java/org/teavm/model/classes/VirtualTableProvider.java b/core/src/main/java/org/teavm/model/classes/VirtualTableProvider.java index 3f8778797..e4f853133 100644 --- a/core/src/main/java/org/teavm/model/classes/VirtualTableProvider.java +++ b/core/src/main/java/org/teavm/model/classes/VirtualTableProvider.java @@ -21,6 +21,7 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import java.util.function.Predicate; import org.teavm.model.ClassReader; import org.teavm.model.ClassReaderSource; import org.teavm.model.ElementModifier; @@ -35,7 +36,8 @@ public class VirtualTableProvider { private Map virtualTables = new LinkedHashMap<>(); private InterfaceToClassMapping interfaceMapping; - public VirtualTableProvider(ListableClassReaderSource classSource, Set virtualMethods) { + public VirtualTableProvider(ListableClassReaderSource classSource, Set virtualMethods, + Predicate methodCalledVirtually) { this.classSource = classSource; interfaceMapping = new InterfaceToClassMapping(classSource); @@ -50,11 +52,11 @@ public class VirtualTableProvider { } for (String className : classNames) { - fillClass(className); + fillClass(className, methodCalledVirtually); } } - private void fillClass(String className) { + private void fillClass(String className, Predicate methodCalledVirtually) { if (virtualTables.containsKey(className)) { return; } @@ -66,7 +68,7 @@ public class VirtualTableProvider { return; } if (cls.getParent() != null) { - fillClass(cls.getParent()); + fillClass(cls.getParent(), methodCalledVirtually); VirtualTable parentTable = virtualTables.get(cls.getParent()); for (VirtualTableEntry parentEntry : parentTable.entries.values()) { VirtualTableEntry entry = new VirtualTableEntry(table, parentEntry.getMethod(), @@ -84,6 +86,9 @@ public class VirtualTableProvider { MethodReference implementationRef = implementation != null ? implementation.getReference() : null; + if (implementationRef != null && !methodCalledVirtually.test(implementationRef)) { + implementationRef = null; + } table.entries.put(method, new VirtualTableEntry(table, method, implementationRef, table.entries.size())); } @@ -95,7 +100,7 @@ public class VirtualTableProvider { continue; } VirtualTableEntry entry = table.entries.get(method.getDescriptor()); - if (entry != null) { + if (entry != null && methodCalledVirtually.test(method.getReference())) { entry.implementor = method.getReference(); } } diff --git a/core/src/main/java/org/teavm/vm/TeaVM.java b/core/src/main/java/org/teavm/vm/TeaVM.java index c01562371..2b5286806 100644 --- a/core/src/main/java/org/teavm/vm/TeaVM.java +++ b/core/src/main/java/org/teavm/vm/TeaVM.java @@ -812,6 +812,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository { + compileProgressReportStart; return progressListener.progressReached(progress); } + + @Override + public void addVirtualMethods(Predicate methods) { + TeaVM.this.addVirtualMethods(methods); + } }; class PostProcessingClassHolderSource implements ListableClassHolderSource { diff --git a/core/src/main/java/org/teavm/vm/TeaVMTargetController.java b/core/src/main/java/org/teavm/vm/TeaVMTargetController.java index 9572f21af..c37bd1467 100644 --- a/core/src/main/java/org/teavm/vm/TeaVMTargetController.java +++ b/core/src/main/java/org/teavm/vm/TeaVMTargetController.java @@ -18,6 +18,7 @@ package org.teavm.vm; import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.function.Predicate; import org.teavm.cache.CacheStatus; import org.teavm.common.ServiceRepository; import org.teavm.dependency.DependencyInfo; @@ -51,4 +52,6 @@ public interface TeaVMTargetController { boolean isVirtual(MethodReference method); TeaVMProgressFeedback reportProgress(int progress); + + void addVirtualMethods(Predicate methods); } diff --git a/platform/src/main/java/org/teavm/platform/Platform.java b/platform/src/main/java/org/teavm/platform/Platform.java index 1c6781de9..9e395a59f 100644 --- a/platform/src/main/java/org/teavm/platform/Platform.java +++ b/platform/src/main/java/org/teavm/platform/Platform.java @@ -226,6 +226,7 @@ public final class Platform { } @Unmanaged + @PluggableDependency(PlatformGenerator.class) public static String getName(PlatformClass cls) { return cls.getMetadata().getName(); } diff --git a/platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java b/platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java index 42b687dfa..676fb3c34 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java +++ b/platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java @@ -59,6 +59,9 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin case "getEnumConstants": method.getResult().propagate(agent.getType("[Ljava/lang/Enum;")); break; + case "getName": + method.getResult().propagate(agent.getType("java.lang.String")); + break; } }