Fix bugs in C backend

This commit is contained in:
Alexey Andreev 2019-03-26 19:09:25 +03:00
parent 9a6da19a24
commit 0dc170dad2
7 changed files with 74 additions and 38 deletions

View File

@ -30,6 +30,7 @@ public class TThread extends TObject implements TRunnable {
private static int activeCount = 1; private static int activeCount = 1;
private long id; private long id;
private int priority; private int priority;
private boolean daemon;
private long timeSliceStart; private long timeSliceStart;
private int yieldCount; private int yieldCount;
private final Object finishedLock = new Object(); private final Object finishedLock = new Object();
@ -40,6 +41,10 @@ public class TThread extends TObject implements TRunnable {
private boolean alive = true; private boolean alive = true;
TRunnable target; TRunnable target;
static {
mainThread.setDaemon(true);
}
public TThread() { public TThread() {
this(null, null); this(null, null);
} }
@ -107,6 +112,14 @@ public class TThread extends TObject implements TRunnable {
return name; 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 { public final void join(long millis, int nanos) throws InterruptedException {
if (currentThread() == this) { if (currentThread() == this) {
return; return;

View File

@ -28,6 +28,7 @@ import org.teavm.dependency.DependencyInfo;
import org.teavm.dependency.MethodDependencyInfo; import org.teavm.dependency.MethodDependencyInfo;
import org.teavm.dependency.ValueDependencyInfo; import org.teavm.dependency.ValueDependencyInfo;
import org.teavm.interop.NoSideEffects; import org.teavm.interop.NoSideEffects;
import org.teavm.interop.StaticInit;
import org.teavm.model.BasicBlockReader; import org.teavm.model.BasicBlockReader;
import org.teavm.model.ClassHierarchy; import org.teavm.model.ClassHierarchy;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
@ -104,7 +105,7 @@ public class ClassInitializerAnalysis implements ClassInitializerInfo {
ClassReader cls = classes.get(className); ClassReader cls = classes.get(className);
if (cls == null) { if (cls == null || cls.getAnnotations().get(StaticInit.class.getName()) != null) {
classStatuses.put(className, STATIC); classStatuses.put(className, STATIC);
return; return;
} }

View File

@ -69,7 +69,7 @@ public final class EventQueue {
} }
} }
static void stop() { public static void stop() {
finished = true; finished = true;
} }

View File

@ -25,6 +25,7 @@ public class Fiber {
public static final int STATE_RUNNING = 0; public static final int STATE_RUNNING = 0;
public static final int STATE_SUSPENDING = 1; public static final int STATE_SUSPENDING = 1;
public static final int STATE_RESUMING = 2; public static final int STATE_RESUMING = 2;
private static int daemonCount = 1;
private int[] intValues; private int[] intValues;
private int intTop; private int intTop;
@ -221,6 +222,9 @@ public class Fiber {
current = this; current = this;
runner.run(); runner.run();
current = former; current = former;
if (!isSuspending() && Thread.currentThread().isDaemon() && --daemonCount == 0) {
EventQueue.stop();
}
} }
void resume() { void resume() {

View File

@ -15,7 +15,9 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import org.teavm.ast.InvocationExpr; import org.teavm.ast.InvocationExpr;
@ -36,52 +38,32 @@ class MetadataCIntrinsic implements Intrinsic {
private CodeWriter structuresWriter; private CodeWriter structuresWriter;
private CodeWriter staticFieldInitWriter; private CodeWriter staticFieldInitWriter;
private DefaultMetadataGeneratorContext metadataContext; private DefaultMetadataGeneratorContext metadataContext;
private MethodReference constructorMethod; private Map<MethodReference, MethodGenerator> generatorMap = new HashMap<>();
private MethodReference targetMethod;
private MetadataGenerator generator;
MetadataCIntrinsic(ClassReaderSource classSource, ClassLoader classLoader, void init(ClassReaderSource classSource, ClassLoader classLoader,
ServiceRepository services, Properties properties, CodeWriter structuresWriter, ServiceRepository services, Properties properties, CodeWriter structuresWriter,
CodeWriter staticFieldInitWriter, MethodReference constructorMethod, MethodReference targetMethod, CodeWriter staticFieldInitWriter) {
MetadataGenerator generator) {
this.structuresWriter = structuresWriter; this.structuresWriter = structuresWriter;
this.staticFieldInitWriter = staticFieldInitWriter; this.staticFieldInitWriter = staticFieldInitWriter;
metadataContext = new DefaultMetadataGeneratorContext(classSource, classLoader, properties, services); 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 @Override
public boolean canHandle(MethodReference methodReference) { public boolean canHandle(MethodReference methodReference) {
return constructorMethod.equals(methodReference); return generatorMap.containsKey(methodReference);
} }
@Override @Override
public void apply(IntrinsicContext context, InvocationExpr invocation) { public void apply(IntrinsicContext context, InvocationExpr invocation) {
writeInitializer(context, invocation); MethodGenerator generator = generatorMap.get(invocation.getMethod());
context.writer().print(context.names().forMethod(invocation.getMethod())); generator.apply(context, invocation);
} }
private void writeInitializer(IntrinsicContext context, InvocationExpr invocation) { void writeValue(IntrinsicContext context, Object value) {
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) {
if (value == null) { if (value == null) {
staticFieldInitWriter.print("NULL"); staticFieldInitWriter.print("NULL");
} else if (value instanceof String) { } else if (value instanceof String) {
@ -269,4 +251,37 @@ class MetadataCIntrinsic implements Intrinsic {
} }
return a; 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(";");
}
}
} }

View File

@ -48,8 +48,8 @@ public class PlatformPlugin implements TeaVMPlugin, MetadataRegistration {
@Override @Override
public void install(TeaVMHost host) { public void install(TeaVMHost host) {
host.add(metadataTransformer);
if (host.getExtension(TeaVMJavaScriptHost.class) != null) { if (host.getExtension(TeaVMJavaScriptHost.class) != null) {
host.add(metadataTransformer);
host.add(new ResourceTransformer()); host.add(new ResourceTransformer());
host.add(new ResourceAccessorTransformer(host)); host.add(new ResourceAccessorTransformer(host));
host.add(new ResourceAccessorDependencyListener()); host.add(new ResourceAccessorDependencyListener());
@ -101,11 +101,14 @@ public class PlatformPlugin implements TeaVMPlugin, MetadataRegistration {
TeaVMCHost cHost = host.getExtension(TeaVMCHost.class); TeaVMCHost cHost = host.getExtension(TeaVMCHost.class);
if (cHost != null) { if (cHost != null) {
metadataGeneratorConsumers.add((constructor, method, generator) -> { MetadataCIntrinsic metadataCIntrinsic = new MetadataCIntrinsic();
cHost.addIntrinsic(ctx -> new MetadataCIntrinsic(ctx.getClassSource(), ctx.getClassLoader(), cHost.addIntrinsic(ctx -> {
metadataCIntrinsic.init(ctx.getClassSource(), ctx.getClassLoader(),
ctx.getServices(), ctx.getProperties(), ctx.getStructureCodeWriter(), 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 ResourceReadCIntrinsic(ctx.getClassSource()));
cHost.addIntrinsic(ctx -> new Intrinsic() { cHost.addIntrinsic(ctx -> new Intrinsic() {
@Override @Override

View File

@ -20,4 +20,4 @@ link_directories(${GTK3_LIBRARY_DIRS})
add_definitions(${GTK3_CFLAGS_OTHER}) add_definitions(${GTK3_CFLAGS_OTHER})
add_executable(teavm_benchmark target/generated/c/classes.c) add_executable(teavm_benchmark target/generated/c/classes.c)
target_link_libraries(teavm_benchmark ${GTK3_LIBRARIES} m) target_link_libraries(teavm_benchmark ${GTK3_LIBRARIES} m rt)