mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04: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;
|
||||
|
||||
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.GeneratorContext;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
|
@ -11,7 +14,7 @@ import org.teavm.model.ValueType;
|
|||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class ObjectNativeGenerator implements Generator {
|
||||
public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
||||
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) {
|
||||
writer.append(context.getParameterName(0)).append(".$id = $rt_nextId();").newLine();
|
||||
}
|
||||
|
@ -50,6 +65,13 @@ public class ObjectNativeGenerator implements Generator {
|
|||
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) {
|
||||
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("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;
|
||||
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
import org.teavm.javascript.ni.Rename;
|
||||
import org.teavm.javascript.ni.Superclass;
|
||||
|
@ -20,6 +21,7 @@ public class TObject {
|
|||
|
||||
@GeneratedBy(ObjectNativeGenerator.class)
|
||||
@Rename("getClass")
|
||||
@PluggableDependency(ObjectNativeGenerator.class)
|
||||
public native final TClass<?> getClass0();
|
||||
|
||||
@Override
|
||||
|
@ -31,6 +33,7 @@ public class TObject {
|
|||
|
||||
@Override
|
||||
@GeneratedBy(ObjectNativeGenerator.class)
|
||||
@PluggableDependency(ObjectNativeGenerator.class)
|
||||
protected native TObject clone();
|
||||
|
||||
@Rename("notify")
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package org.teavm.codegen;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
@ -13,6 +15,7 @@ import java.util.concurrent.CountDownLatch;
|
|||
public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
|
||||
private Mapper<T, R> innerMapper;
|
||||
private ConcurrentMap<T, Wrapper<R>> cache = new ConcurrentHashMap<>();
|
||||
private List<KeyListener<T>> keyListeners = new ArrayList<>();
|
||||
|
||||
private static class Wrapper<S> {
|
||||
volatile S value;
|
||||
|
@ -33,6 +36,9 @@ public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
|
|||
wrapper.value = innerMapper.map(preimage);
|
||||
wrapper.latch.countDown();
|
||||
wrapper.latch = null;
|
||||
for (KeyListener<T> listener : keyListeners) {
|
||||
listener.keyAdded(preimage);
|
||||
}
|
||||
} else {
|
||||
CountDownLatch latch = oldWrapper.latch;
|
||||
try {
|
||||
|
@ -52,4 +58,12 @@ public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
|
|||
public Collection<T> getCachedPreimages() {
|
||||
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.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.KeyListener;
|
||||
import org.teavm.codegen.Mapper;
|
||||
import org.teavm.model.*;
|
||||
|
||||
|
@ -54,6 +58,11 @@ public class DependencyChecker {
|
|||
return createFieldNode(preimage);
|
||||
}
|
||||
});
|
||||
methodCache.addKeyListener(new KeyListener<MethodReference>() {
|
||||
@Override public void keyAdded(MethodReference key) {
|
||||
activateDependencyPlugin(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public DependencyNode createNode() {
|
||||
|
@ -198,4 +207,28 @@ public class DependencyChecker {
|
|||
}
|
||||
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