mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Dependency plugin support added
This commit is contained in:
parent
59358dcd8d
commit
91a50605bc
|
@ -1,6 +1,9 @@
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
|
import org.teavm.dependency.DependencyChecker;
|
||||||
|
import org.teavm.dependency.DependencyPlugin;
|
||||||
|
import org.teavm.dependency.MethodGraph;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
import org.teavm.javascript.ni.GeneratorContext;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
@ -11,7 +14,7 @@ import org.teavm.model.ValueType;
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
*/
|
*/
|
||||||
public class ObjectNativeGenerator implements Generator {
|
public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
||||||
switch (methodRef.getDescriptor().getName()) {
|
switch (methodRef.getDescriptor().getName()) {
|
||||||
|
@ -33,6 +36,18 @@ public class ObjectNativeGenerator implements Generator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void methodAchieved(DependencyChecker checker, MethodReference method) {
|
||||||
|
switch (method.getDescriptor().getName()) {
|
||||||
|
case "clone":
|
||||||
|
achieveClone(checker, method);
|
||||||
|
break;
|
||||||
|
case "getClass":
|
||||||
|
achieveGetClass(checker);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void generateInit(GeneratorContext context, SourceWriter writer) {
|
private void generateInit(GeneratorContext context, SourceWriter writer) {
|
||||||
writer.append(context.getParameterName(0)).append(".$id = $rt_nextId();").newLine();
|
writer.append(context.getParameterName(0)).append(".$id = $rt_nextId();").newLine();
|
||||||
}
|
}
|
||||||
|
@ -50,6 +65,13 @@ public class ObjectNativeGenerator implements Generator {
|
||||||
writer.append("return cls;").newLine();
|
writer.append("return cls;").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void achieveGetClass(DependencyChecker checker) {
|
||||||
|
String classClass = "java.lang.Class";
|
||||||
|
MethodReference method = new MethodReference(classClass, new MethodDescriptor("createNew",
|
||||||
|
ValueType.object(classClass)));
|
||||||
|
checker.addEntryPoint(method);
|
||||||
|
}
|
||||||
|
|
||||||
private void generateHashCode(GeneratorContext context, SourceWriter writer) {
|
private void generateHashCode(GeneratorContext context, SourceWriter writer) {
|
||||||
writer.append("return ").append(context.getParameterName(0)).append(".$id;").newLine();
|
writer.append("return ").append(context.getParameterName(0)).append(".$id;").newLine();
|
||||||
}
|
}
|
||||||
|
@ -67,4 +89,9 @@ public class ObjectNativeGenerator implements Generator {
|
||||||
writer.append("copy[field] = obj[field];").newLine().outdent().append("}").newLine();
|
writer.append("copy[field] = obj[field];").newLine().outdent().append("}").newLine();
|
||||||
writer.append("return copy;").newLine();
|
writer.append("return copy;").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void achieveClone(DependencyChecker checker, MethodReference method) {
|
||||||
|
MethodGraph graph = checker.attachMethodGraph(method);
|
||||||
|
graph.getVariableNode(0).connect(graph.getResultNode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import org.teavm.dependency.PluggableDependency;
|
||||||
import org.teavm.javascript.ni.GeneratedBy;
|
import org.teavm.javascript.ni.GeneratedBy;
|
||||||
import org.teavm.javascript.ni.Rename;
|
import org.teavm.javascript.ni.Rename;
|
||||||
import org.teavm.javascript.ni.Superclass;
|
import org.teavm.javascript.ni.Superclass;
|
||||||
|
@ -20,6 +21,7 @@ public class TObject {
|
||||||
|
|
||||||
@GeneratedBy(ObjectNativeGenerator.class)
|
@GeneratedBy(ObjectNativeGenerator.class)
|
||||||
@Rename("getClass")
|
@Rename("getClass")
|
||||||
|
@PluggableDependency(ObjectNativeGenerator.class)
|
||||||
public native final TClass<?> getClass0();
|
public native final TClass<?> getClass0();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,6 +33,7 @@ public class TObject {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@GeneratedBy(ObjectNativeGenerator.class)
|
@GeneratedBy(ObjectNativeGenerator.class)
|
||||||
|
@PluggableDependency(ObjectNativeGenerator.class)
|
||||||
protected native TObject clone();
|
protected native TObject clone();
|
||||||
|
|
||||||
@Rename("notify")
|
@Rename("notify")
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package org.teavm.codegen;
|
package org.teavm.codegen;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
@ -13,6 +15,7 @@ import java.util.concurrent.CountDownLatch;
|
||||||
public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
|
public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
|
||||||
private Mapper<T, R> innerMapper;
|
private Mapper<T, R> innerMapper;
|
||||||
private ConcurrentMap<T, Wrapper<R>> cache = new ConcurrentHashMap<>();
|
private ConcurrentMap<T, Wrapper<R>> cache = new ConcurrentHashMap<>();
|
||||||
|
private List<KeyListener<T>> keyListeners = new ArrayList<>();
|
||||||
|
|
||||||
private static class Wrapper<S> {
|
private static class Wrapper<S> {
|
||||||
volatile S value;
|
volatile S value;
|
||||||
|
@ -33,6 +36,9 @@ public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
|
||||||
wrapper.value = innerMapper.map(preimage);
|
wrapper.value = innerMapper.map(preimage);
|
||||||
wrapper.latch.countDown();
|
wrapper.latch.countDown();
|
||||||
wrapper.latch = null;
|
wrapper.latch = null;
|
||||||
|
for (KeyListener<T> listener : keyListeners) {
|
||||||
|
listener.keyAdded(preimage);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
CountDownLatch latch = oldWrapper.latch;
|
CountDownLatch latch = oldWrapper.latch;
|
||||||
try {
|
try {
|
||||||
|
@ -52,4 +58,12 @@ public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
|
||||||
public Collection<T> getCachedPreimages() {
|
public Collection<T> getCachedPreimages() {
|
||||||
return new HashSet<>(cache.keySet());
|
return new HashSet<>(cache.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addKeyListener(KeyListener<T> listener) {
|
||||||
|
keyListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface KeyListener<S> {
|
||||||
|
void keyAdded(S key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,12 @@ package org.teavm.dependency;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.teavm.codegen.ConcurrentCachedMapper;
|
import org.teavm.codegen.ConcurrentCachedMapper;
|
||||||
|
import org.teavm.codegen.ConcurrentCachedMapper.KeyListener;
|
||||||
import org.teavm.codegen.Mapper;
|
import org.teavm.codegen.Mapper;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
|
|
||||||
|
@ -54,6 +58,11 @@ public class DependencyChecker {
|
||||||
return createFieldNode(preimage);
|
return createFieldNode(preimage);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
methodCache.addKeyListener(new KeyListener<MethodReference>() {
|
||||||
|
@Override public void keyAdded(MethodReference key) {
|
||||||
|
activateDependencyPlugin(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DependencyNode createNode() {
|
public DependencyNode createNode() {
|
||||||
|
@ -198,4 +207,28 @@ public class DependencyChecker {
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void activateDependencyPlugin(MethodReference methodRef) {
|
||||||
|
ClassHolder cls = classSource.getClassHolder(methodRef.getClassName());
|
||||||
|
MethodHolder method = cls.getMethod(methodRef.getDescriptor());
|
||||||
|
AnnotationHolder depAnnot = method.getAnnotations().get(PluggableDependency.class.getName());
|
||||||
|
if (depAnnot == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ValueType depType = depAnnot.getValues().get("value").getJavaClass();
|
||||||
|
String depClassName = ((ValueType.Object)depType).getClassName();
|
||||||
|
Class<?> depClass;
|
||||||
|
try {
|
||||||
|
depClass = Class.forName(depClassName);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException("Dependency plugin not found: " + depClassName, e);
|
||||||
|
}
|
||||||
|
DependencyPlugin plugin;
|
||||||
|
try {
|
||||||
|
plugin = (DependencyPlugin)depClass.newInstance();
|
||||||
|
} catch (IllegalAccessException | InstantiationException e) {
|
||||||
|
throw new RuntimeException("Can't instantiate dependency plugin " + depClassName, e);
|
||||||
|
}
|
||||||
|
plugin.methodAchieved(this, methodRef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.teavm.dependency;
|
||||||
|
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public interface DependencyPlugin {
|
||||||
|
void methodAchieved(DependencyChecker checker, MethodReference method);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package org.teavm.dependency;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface PluggableDependency {
|
||||||
|
Class<? extends DependencyPlugin> value();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user