From 0dc170dad212395562f5536a94d60656e4a7be33 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 26 Mar 2019 19:09:25 +0300 Subject: [PATCH] Fix bugs in C backend --- .../org/teavm/classlib/java/lang/TThread.java | 13 ++++ .../analysis/ClassInitializerAnalysis.java | 3 +- .../java/org/teavm/runtime/EventQueue.java | 2 +- .../main/java/org/teavm/runtime/Fiber.java | 4 + .../platform/plugin/MetadataCIntrinsic.java | 77 +++++++++++-------- .../teavm/platform/plugin/PlatformPlugin.java | 11 ++- samples/benchmark/CMakeLists.txt | 2 +- 7 files changed, 74 insertions(+), 38 deletions(-) diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java index 2e515174e..1245f6982 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java @@ -30,6 +30,7 @@ public class TThread extends TObject implements TRunnable { private static int activeCount = 1; private long id; private int priority; + private boolean daemon; private long timeSliceStart; private int yieldCount; private final Object finishedLock = new Object(); @@ -40,6 +41,10 @@ public class TThread extends TObject implements TRunnable { private boolean alive = true; TRunnable target; + static { + mainThread.setDaemon(true); + } + public TThread() { this(null, null); } @@ -107,6 +112,14 @@ public class TThread extends TObject implements TRunnable { return name; } + public final boolean isDaemon() { + return daemon; + } + + public final void setDaemon(boolean daemon) { + this.daemon = daemon; + } + public final void join(long millis, int nanos) throws InterruptedException { if (currentThread() == this) { return; diff --git a/core/src/main/java/org/teavm/model/analysis/ClassInitializerAnalysis.java b/core/src/main/java/org/teavm/model/analysis/ClassInitializerAnalysis.java index 2ca9143f3..6ad234198 100644 --- a/core/src/main/java/org/teavm/model/analysis/ClassInitializerAnalysis.java +++ b/core/src/main/java/org/teavm/model/analysis/ClassInitializerAnalysis.java @@ -28,6 +28,7 @@ import org.teavm.dependency.DependencyInfo; import org.teavm.dependency.MethodDependencyInfo; import org.teavm.dependency.ValueDependencyInfo; import org.teavm.interop.NoSideEffects; +import org.teavm.interop.StaticInit; import org.teavm.model.BasicBlockReader; import org.teavm.model.ClassHierarchy; import org.teavm.model.ClassReader; @@ -104,7 +105,7 @@ public class ClassInitializerAnalysis implements ClassInitializerInfo { ClassReader cls = classes.get(className); - if (cls == null) { + if (cls == null || cls.getAnnotations().get(StaticInit.class.getName()) != null) { classStatuses.put(className, STATIC); return; } diff --git a/core/src/main/java/org/teavm/runtime/EventQueue.java b/core/src/main/java/org/teavm/runtime/EventQueue.java index eb36ec316..c1a7711d0 100644 --- a/core/src/main/java/org/teavm/runtime/EventQueue.java +++ b/core/src/main/java/org/teavm/runtime/EventQueue.java @@ -69,7 +69,7 @@ public final class EventQueue { } } - static void stop() { + public static void stop() { finished = true; } diff --git a/core/src/main/java/org/teavm/runtime/Fiber.java b/core/src/main/java/org/teavm/runtime/Fiber.java index 9ba5a71c2..8cfcea40f 100644 --- a/core/src/main/java/org/teavm/runtime/Fiber.java +++ b/core/src/main/java/org/teavm/runtime/Fiber.java @@ -25,6 +25,7 @@ public class Fiber { public static final int STATE_RUNNING = 0; public static final int STATE_SUSPENDING = 1; public static final int STATE_RESUMING = 2; + private static int daemonCount = 1; private int[] intValues; private int intTop; @@ -221,6 +222,9 @@ public class Fiber { current = this; runner.run(); current = former; + if (!isSuspending() && Thread.currentThread().isDaemon() && --daemonCount == 0) { + EventQueue.stop(); + } } void resume() { diff --git a/platform/src/main/java/org/teavm/platform/plugin/MetadataCIntrinsic.java b/platform/src/main/java/org/teavm/platform/plugin/MetadataCIntrinsic.java index 28fc7584b..4cca48af0 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/MetadataCIntrinsic.java +++ b/platform/src/main/java/org/teavm/platform/plugin/MetadataCIntrinsic.java @@ -15,7 +15,9 @@ */ package org.teavm.platform.plugin; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Properties; import java.util.Set; import org.teavm.ast.InvocationExpr; @@ -36,52 +38,32 @@ class MetadataCIntrinsic implements Intrinsic { private CodeWriter structuresWriter; private CodeWriter staticFieldInitWriter; private DefaultMetadataGeneratorContext metadataContext; - private MethodReference constructorMethod; - private MethodReference targetMethod; - private MetadataGenerator generator; + private Map generatorMap = new HashMap<>(); - MetadataCIntrinsic(ClassReaderSource classSource, ClassLoader classLoader, + void init(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services, Properties properties, CodeWriter structuresWriter, - CodeWriter staticFieldInitWriter, MethodReference constructorMethod, MethodReference targetMethod, - MetadataGenerator generator) { + CodeWriter staticFieldInitWriter) { this.structuresWriter = structuresWriter; this.staticFieldInitWriter = staticFieldInitWriter; metadataContext = new DefaultMetadataGeneratorContext(classSource, classLoader, properties, services); - this.constructorMethod = constructorMethod; - this.targetMethod = targetMethod; - this.generator = generator; + } + + public void addGenerator(MethodReference constructor, MethodReference method, MetadataGenerator generator) { + generatorMap.put(constructor, new MethodGenerator(method, generator)); } @Override public boolean canHandle(MethodReference methodReference) { - return constructorMethod.equals(methodReference); + return generatorMap.containsKey(methodReference); } @Override public void apply(IntrinsicContext context, InvocationExpr invocation) { - writeInitializer(context, invocation); - context.writer().print(context.names().forMethod(invocation.getMethod())); + MethodGenerator generator = generatorMap.get(invocation.getMethod()); + generator.apply(context, invocation); } - private void writeInitializer(IntrinsicContext context, InvocationExpr invocation) { - MethodReference methodReference = invocation.getMethod(); - if (!writtenInitializers.add(methodReference)) { - return; - } - - String variableName = context.names().forMethod(methodReference); - staticFieldInitWriter.print("static ").printType(methodReference.getReturnType()).print(" ") - .print(variableName).print(" = "); - if (generator == null) { - staticFieldInitWriter.print("NULL"); - } else { - Resource resource = generator.generateMetadata(metadataContext, targetMethod); - writeValue(context, resource); - } - staticFieldInitWriter.println(";"); - } - - private void writeValue(IntrinsicContext context, Object value) { + void writeValue(IntrinsicContext context, Object value) { if (value == null) { staticFieldInitWriter.print("NULL"); } else if (value instanceof String) { @@ -269,4 +251,37 @@ class MetadataCIntrinsic implements Intrinsic { } return a; } + + class MethodGenerator { + private MethodReference targetMethod; + private MetadataGenerator generator; + + MethodGenerator(MethodReference targetMethod, MetadataGenerator generator) { + this.targetMethod = targetMethod; + this.generator = generator; + } + + public void apply(IntrinsicContext context, InvocationExpr invocation) { + writeInitializer(context, invocation); + context.writer().print(context.names().forMethod(invocation.getMethod())); + } + + private void writeInitializer(IntrinsicContext context, InvocationExpr invocation) { + MethodReference methodReference = invocation.getMethod(); + if (!writtenInitializers.add(methodReference)) { + return; + } + + String variableName = context.names().forMethod(methodReference); + staticFieldInitWriter.print("static ").printType(methodReference.getReturnType()).print(" ") + .print(variableName).print(" = "); + if (generator == null) { + staticFieldInitWriter.print("NULL"); + } else { + Resource resource = generator.generateMetadata(metadataContext, targetMethod); + writeValue(context, resource); + } + staticFieldInitWriter.println(";"); + } + } } diff --git a/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java b/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java index 6ac53603f..39d35b553 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java +++ b/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java @@ -48,8 +48,8 @@ public class PlatformPlugin implements TeaVMPlugin, MetadataRegistration { @Override public void install(TeaVMHost host) { + host.add(metadataTransformer); if (host.getExtension(TeaVMJavaScriptHost.class) != null) { - host.add(metadataTransformer); host.add(new ResourceTransformer()); host.add(new ResourceAccessorTransformer(host)); host.add(new ResourceAccessorDependencyListener()); @@ -101,11 +101,14 @@ public class PlatformPlugin implements TeaVMPlugin, MetadataRegistration { TeaVMCHost cHost = host.getExtension(TeaVMCHost.class); if (cHost != null) { - metadataGeneratorConsumers.add((constructor, method, generator) -> { - cHost.addIntrinsic(ctx -> new MetadataCIntrinsic(ctx.getClassSource(), ctx.getClassLoader(), + MetadataCIntrinsic metadataCIntrinsic = new MetadataCIntrinsic(); + cHost.addIntrinsic(ctx -> { + metadataCIntrinsic.init(ctx.getClassSource(), ctx.getClassLoader(), ctx.getServices(), ctx.getProperties(), ctx.getStructureCodeWriter(), - ctx.getStaticFieldsInitWriter(), constructor, method, generator)); + ctx.getStaticFieldsInitWriter()); + return metadataCIntrinsic; }); + metadataGeneratorConsumers.add(metadataCIntrinsic::addGenerator); cHost.addIntrinsic(ctx -> new ResourceReadCIntrinsic(ctx.getClassSource())); cHost.addIntrinsic(ctx -> new Intrinsic() { @Override diff --git a/samples/benchmark/CMakeLists.txt b/samples/benchmark/CMakeLists.txt index 9e18ce699..ccdd64bfa 100644 --- a/samples/benchmark/CMakeLists.txt +++ b/samples/benchmark/CMakeLists.txt @@ -20,4 +20,4 @@ link_directories(${GTK3_LIBRARY_DIRS}) add_definitions(${GTK3_CFLAGS_OTHER}) add_executable(teavm_benchmark target/generated/c/classes.c) -target_link_libraries(teavm_benchmark ${GTK3_LIBRARIES} m) \ No newline at end of file +target_link_libraries(teavm_benchmark ${GTK3_LIBRARIES} m rt) \ No newline at end of file