Add support of new plugin interface to extensions

This commit is contained in:
Alexey Andreev 2014-12-11 19:20:39 +04:00
parent 316850bbb5
commit cd0664d695
21 changed files with 61 additions and 59 deletions

View File

@ -39,7 +39,6 @@ public class ClassLookupDependencySupport implements DependencyListener {
public void methodAchieved(final DependencyAgent agent, MethodDependency method) {
MethodReference ref = method.getReference();
if (ref.getClassName().equals("java.lang.Class") && ref.getName().equals("forNameImpl")) {
final DependencyStack stack = method.getStack();
allClasses.addConsumer(new DependencyConsumer() {
@Override public void consume(DependencyAgentType type) {
ClassReader cls = agent.getClassSource().get(type.getName());
@ -48,7 +47,7 @@ public class ClassLookupDependencySupport implements DependencyListener {
}
MethodReader initMethod = cls.getMethod(new MethodDescriptor("<clinit>", ValueType.VOID));
if (initMethod != null) {
agent.linkMethod(initMethod.getReference(), stack).use();
agent.linkMethod(initMethod.getReference(), null).use();
}
}
});

View File

@ -27,7 +27,7 @@ import org.teavm.model.ValueType;
*/
public class EnumDependencySupport implements DependencyListener {
private DependencyNode allEnums;
private volatile DependencyStack enumConstantsStack;
private boolean unlocked;
@Override
public void started(DependencyAgent agent) {
@ -41,11 +41,11 @@ public class EnumDependencySupport implements DependencyListener {
return;
}
allEnums.propagate(agent.getType(className));
if (enumConstantsStack != null) {
if (unlocked) {
MethodReader method = cls.getMethod(new MethodDescriptor("values",
ValueType.arrayOf(ValueType.object(cls.getName()))));
if (method != null) {
agent.linkMethod(method.getReference(), enumConstantsStack).use();
agent.linkMethod(method.getReference(), null).use();
}
}
}
@ -54,9 +54,9 @@ public class EnumDependencySupport implements DependencyListener {
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
if (method.getReference().getClassName().equals("java.lang.Class") &&
method.getReference().getName().equals("getEnumConstantsImpl")) {
unlocked = true;
allEnums.connect(method.getResult().getArrayItem());
method.getResult().propagate(agent.getType("[java.lang.Enum"));
enumConstantsStack = method.getStack();
for (String cls : agent.getAchievableClasses()) {
classAchieved(agent, cls);
}

View File

@ -15,6 +15,7 @@
*/
package org.teavm.classlib.impl;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.javascript.ni.PreserveOriginalName;
import org.teavm.model.*;

View File

@ -15,6 +15,7 @@
*/
package org.teavm.classlib.impl;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*;
import org.teavm.model.instructions.ConstructInstruction;
import org.teavm.model.instructions.ExitInstruction;

View File

@ -24,7 +24,6 @@ import org.teavm.model.*;
*/
public class NewInstanceDependencySupport implements DependencyListener {
private DependencyNode allClassesNode;
private DependencyStack newInstanceStack;
@Override
public void started(DependencyAgent agent) {
@ -50,7 +49,6 @@ public class NewInstanceDependencySupport implements DependencyListener {
public void methodAchieved(final DependencyAgent agent, MethodDependency method) {
MethodReader reader = method.getMethod();
if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) {
newInstanceStack = method.getStack();
allClassesNode.connect(method.getResult());
method.getResult().addConsumer(new DependencyConsumer() {
@Override public void consume(DependencyAgentType type) {
@ -62,7 +60,7 @@ public class NewInstanceDependencySupport implements DependencyListener {
private void attachConstructor(DependencyAgent checker, String type) {
MethodReference ref = new MethodReference(type, new MethodDescriptor("<init>", ValueType.VOID));
checker.linkMethod(ref, newInstanceStack).use();
checker.linkMethod(ref, null).use();
}
@Override

View File

@ -37,7 +37,6 @@ public class ServiceLoaderSupport implements Generator, DependencyListener {
private Map<String, List<String>> serviceMap = new HashMap<>();
private DependencyNode allClassesNode;
private ClassLoader classLoader;
private DependencyStack stack;
public ServiceLoaderSupport(ClassLoader classLoader) {
this.classLoader = classLoader;
@ -123,7 +122,6 @@ public class ServiceLoaderSupport implements Generator, DependencyListener {
MethodReference ref = method.getReference();
if (ref.getClassName().equals("java.util.ServiceLoader") && ref.getName().equals("loadServices")) {
method.getResult().propagate(agent.getType("[java.lang.Object"));
stack = method.getStack();
allClassesNode.connect(method.getResult().getArrayItem());
method.getResult().getArrayItem().addConsumer(new DependencyConsumer() {
@Override public void consume(DependencyAgentType type) {
@ -135,7 +133,7 @@ public class ServiceLoaderSupport implements Generator, DependencyListener {
private void initConstructor(DependencyAgent agent, String type) {
MethodReference ctor = new MethodReference(type, new MethodDescriptor("<init>", ValueType.VOID));
agent.linkMethod(ctor, stack).use();
agent.linkMethod(ctor, null).use();
}
@Override

View File

@ -206,7 +206,7 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
break;
case "newInstance":
agent.linkMethod(new MethodReference(InstantiationException.class.getName(), "<init>",
ValueType.VOID), graph.getStack()).use();
ValueType.VOID), null).use();
break;
}
}

View File

@ -85,7 +85,7 @@ public class ObjectNativeGenerator implements Generator, Injector, DependencyPlu
private void achieveGetClass(DependencyAgent agent, MethodDependency method) {
MethodReference initMethod = new MethodReference(Class.class, "createNew", Class.class);
agent.linkMethod(initMethod, method.getStack()).use();
agent.linkMethod(initMethod, null).use();
method.getResult().propagate(agent.getType("java.lang.Class"));
}

View File

@ -98,12 +98,12 @@ public class SystemNativeGenerator implements Generator, DependencyPlugin {
}
private void achieveSetErr(DependencyAgent agent, MethodDependency method) {
FieldDependency fieldDep = agent.linkField(new FieldReference("java.lang.System", "err"), method.getStack());
FieldDependency fieldDep = agent.linkField(new FieldReference("java.lang.System", "err"), null);
method.getVariable(1).connect(fieldDep.getValue());
}
private void achieveSetOut(DependencyAgent agent, MethodDependency method) {
FieldDependency fieldDep = agent.linkField(new FieldReference("java.lang.System", "out"), method.getStack());
FieldDependency fieldDep = agent.linkField(new FieldReference("java.lang.System", "out"), null);
method.getVariable(1).connect(fieldDep.getValue());
}
}

View File

@ -83,7 +83,7 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
@Override public void consume(DependencyAgentType type) {
if (!type.getName().startsWith("[")) {
MethodReference cons = new MethodReference(IllegalArgumentException.class, "<init>", void.class);
agent.linkMethod(cons, method.getStack()).use();
agent.linkMethod(cons, null).use();
}
}
});
@ -136,7 +136,7 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
String wrapper = "java.lang." + primitiveWrappers[i];
MethodReference methodRef = new MethodReference(wrapper, "valueOf",
primitiveTypes[i], ValueType.object(wrapper));
agent.linkMethod(methodRef, method.getStack()).use();
agent.linkMethod(methodRef, null).use();
method.getResult().propagate(agent.getType("java.lang." + primitiveWrappers[i]));
}
}

View File

@ -16,6 +16,7 @@
package org.teavm.classlib.java.util;
import java.io.IOException;
import java.util.TimerTask;
import org.teavm.codegen.SourceWriter;
import org.teavm.dependency.DependencyAgent;
import org.teavm.dependency.DependencyPlugin;
@ -23,21 +24,20 @@ import org.teavm.dependency.MethodDependency;
import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
/**
*
* @author Alexey Andreev
*/
public class TimerNativeGenerator implements Generator, DependencyPlugin {
private static final MethodReference performOnceRef = new MethodReference("java.util.TimerTask",
"performOnce", ValueType.VOID);
private static final MethodReference performOnceRef = new MethodReference(TimerTask.class,
"performOnce", void.class);
@Override
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
switch (method.getReference().getName()) {
case "scheduleOnce": {
MethodDependency performMethod = agent.linkMethod(performOnceRef, method.getStack());
MethodDependency performMethod = agent.linkMethod(performOnceRef, null);
performMethod.use();
method.getVariable(1).connect(performMethod.getVariable(1));
break;

View File

@ -69,7 +69,7 @@ public class EntryPointGenerator extends AbstractRendererListener implements Dep
@Override
public void started(DependencyAgent agent) {
for (String className : classesToLoad) {
agent.linkClass(className, DependencyStack.ROOT).initClass(DependencyStack.ROOT);
agent.linkClass(className, null).initClass(null);
}
}

View File

@ -15,6 +15,7 @@
*/
package org.teavm.html4j;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*;
import org.teavm.model.instructions.*;
@ -31,12 +32,11 @@ public class JCLHacks implements ClassHolderTransformer {
}
private void installThreadMethods(ClassHolder cls) {
cls.addMethod(createMethodThrowingSecurityException(new MethodDescriptor("setName",
ValueType.object("java.lang.String"), ValueType.VOID), false));
cls.addMethod(createMethodThrowingSecurityException(new MethodDescriptor("start",
ValueType.VOID), false));
cls.addMethod(createMethodThrowingSecurityException(new MethodDescriptor("setName", String.class, void.class),
false));
cls.addMethod(createMethodThrowingSecurityException(new MethodDescriptor("start", void.class), false));
cls.addMethod(createMethodThrowingSecurityException(new MethodDescriptor("setDaemon",
ValueType.BOOLEAN, ValueType.VOID), false));
boolean.class, void.class), false));
cls.addMethod(createThreadSleep());
}
@ -59,7 +59,7 @@ public class JCLHacks implements ClassHolderTransformer {
InvokeInstruction invoke = new InvokeInstruction();
invoke.setType(InvocationType.SPECIAL);
invoke.setInstance(var);
invoke.setMethod(new MethodReference("java.lang.SecurityException", "<init>", ValueType.VOID));
invoke.setMethod(new MethodReference(SecurityException.class, "<init>", void.class));
block.getInstructions().add(invoke);
RaiseInstruction raise = new RaiseInstruction();
raise.setException(var);

View File

@ -80,16 +80,16 @@ public class JavaScriptBodyDependency implements DependencyListener {
}
private void includeDefaultDependencies(DependencyAgent agent) {
agent.linkMethod(JavaScriptConvGenerator.fromJsMethod, DependencyStack.ROOT).use();
agent.linkMethod(JavaScriptConvGenerator.toJsMethod, DependencyStack.ROOT).use();
agent.linkMethod(JavaScriptConvGenerator.intValueMethod, DependencyStack.ROOT).use();
agent.linkMethod(JavaScriptConvGenerator.valueOfIntMethod, DependencyStack.ROOT).use();
agent.linkMethod(JavaScriptConvGenerator.booleanValueMethod, DependencyStack.ROOT).use();
agent.linkMethod(JavaScriptConvGenerator.valueOfBooleanMethod, DependencyStack.ROOT).use();
agent.linkMethod(JavaScriptConvGenerator.doubleValueMethod, DependencyStack.ROOT).use();
agent.linkMethod(JavaScriptConvGenerator.valueOfDoubleMethod, DependencyStack.ROOT).use();
agent.linkMethod(JavaScriptConvGenerator.charValueMethod, DependencyStack.ROOT).use();
agent.linkMethod(JavaScriptConvGenerator.valueOfCharMethod, DependencyStack.ROOT).use();
agent.linkMethod(JavaScriptConvGenerator.fromJsMethod, null).use();
agent.linkMethod(JavaScriptConvGenerator.toJsMethod, null).use();
agent.linkMethod(JavaScriptConvGenerator.intValueMethod, null).use();
agent.linkMethod(JavaScriptConvGenerator.valueOfIntMethod, null).use();
agent.linkMethod(JavaScriptConvGenerator.booleanValueMethod, null).use();
agent.linkMethod(JavaScriptConvGenerator.valueOfBooleanMethod, null).use();
agent.linkMethod(JavaScriptConvGenerator.doubleValueMethod, null).use();
agent.linkMethod(JavaScriptConvGenerator.valueOfDoubleMethod, null).use();
agent.linkMethod(JavaScriptConvGenerator.charValueMethod, null).use();
agent.linkMethod(JavaScriptConvGenerator.valueOfCharMethod, null).use();
}
@Override
@ -134,7 +134,7 @@ public class JavaScriptBodyDependency implements DependencyListener {
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
MethodReader reader = findMethod(agent.getClassSource(), fqn, desc);
MethodReference ref = reader != null ? reader.getReference() : new MethodReference(fqn, desc);
MethodDependency methodDep = agent.linkMethod(ref, caller.getStack());
MethodDependency methodDep = agent.linkMethod(ref, null);
if (!methodDep.isMissing()) {
if (reader.hasModifier(ElementModifier.STATIC) || reader.hasModifier(ElementModifier.FINAL)) {
methodDep.use();
@ -166,7 +166,7 @@ public class JavaScriptBodyDependency implements DependencyListener {
return;
}
MethodReference methodRef = new MethodReference(type.getName(), superMethod.getDescriptor());
MethodDependency method = agent.linkMethod(methodRef, caller.getStack());
MethodDependency method = agent.linkMethod(methodRef, new CallLocation(caller.getReference()));
method.use();
for (int i = 0; i < method.getParameterCount(); ++i) {
allClassesNode.connect(method.getVariable(i));

View File

@ -16,6 +16,7 @@
package org.teavm.html4j;
import net.java.html.js.JavaScriptBody;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.model.*;

View File

@ -138,7 +138,7 @@ public class JSNativeGenerator implements Injector, DependencyPlugin {
ClassReader cls = agent.getClassSource().get(type);
if (cls != null) {
for (MethodReader method : cls.getMethods()) {
agent.linkMethod(method.getReference(), caller.getStack()).use();
agent.linkMethod(method.getReference(), null).use();
}
}
}

View File

@ -32,7 +32,7 @@ class JSObjectClassTransformer implements ClassHolderTransformer {
processor.processClass(cls);
for (MethodHolder method : cls.getMethods()) {
if (method.getProgram() != null) {
processor.processProgram(method.getProgram());
processor.processProgram(method);
}
}
}

View File

@ -67,8 +67,8 @@ class JavascriptNativeProcessor {
}
}
public void processProgram(Program program) {
this.program = program;
public void processProgram(MethodHolder methodToProcess) {
program = methodToProcess.getProgram();
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
List<Instruction> instructions = block.getInstructions();
@ -83,6 +83,7 @@ class JavascriptNativeProcessor {
}
replacement.clear();
MethodReader method = getMethod(invoke.getMethod());
CallLocation callLocation = new CallLocation(methodToProcess.getReference(), insn.getLocation());
if (method.getAnnotations().get(JSProperty.class.getName()) != null) {
if (isProperGetter(method.getDescriptor())) {
String propertyName;
@ -96,7 +97,7 @@ class JavascriptNativeProcessor {
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
addPropertyGet(propertyName, invoke.getInstance(), result);
if (result != null) {
result = unwrap(insn.getLocation(), result, method.getResultType());
result = unwrap(callLocation, result, method.getResultType());
copyVar(result, invoke.getReceiver());
}
} else if (isProperSetter(method.getDescriptor())) {
@ -107,11 +108,11 @@ class JavascriptNativeProcessor {
} else {
propertyName = cutPrefix(method.getName(), 3);
}
Variable wrapped = wrapArgument(insn.getLocation(), invoke.getArguments().get(0),
Variable wrapped = wrapArgument(callLocation, invoke.getArguments().get(0),
method.parameterType(0));
addPropertySet(propertyName, invoke.getInstance(), wrapped);
} else {
diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript property declaration");
continue;
}
@ -121,7 +122,7 @@ class JavascriptNativeProcessor {
addIndexerGet(invoke.getInstance(), wrap(invoke.getArguments().get(0),
method.parameterType(0)), result);
if (result != null) {
result = unwrap(insn.getLocation(), result, method.getResultType());
result = unwrap(callLocation, result, method.getResultType());
copyVar(result, invoke.getReceiver());
}
} else if (isProperSetIndexer(method.getDescriptor())) {
@ -129,7 +130,7 @@ class JavascriptNativeProcessor {
Variable value = wrap(invoke.getArguments().get(1), method.parameterType(1));
addIndexerSet(invoke.getInstance(), index, value);
} else {
diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript indexer declaration");
continue;
}
@ -139,7 +140,7 @@ class JavascriptNativeProcessor {
boolean isConstructor = false;
if (constructorAnnot != null) {
if (!isSupportedType(method.getResultType())) {
diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript constructor declaration");
continue;
}
@ -147,7 +148,7 @@ class JavascriptNativeProcessor {
name = nameVal != null ? constructorAnnot.getValue("value").getString() : "";
if (name.isEmpty()) {
if (!method.getName().startsWith("new") || method.getName().length() == 3) {
diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
"declared as a native JavaScript constructor, but its name does " +
"not satisfy conventions");
continue;
@ -164,14 +165,14 @@ class JavascriptNativeProcessor {
}
}
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) {
diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript method declaration");
continue;
}
}
for (ValueType arg : method.getParameterTypes()) {
if (!isSupportedType(arg)) {
diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript method or constructor declaration");
continue;
}
@ -187,13 +188,13 @@ class JavascriptNativeProcessor {
newInvoke.getArguments().add(invoke.getInstance());
newInvoke.getArguments().add(addStringWrap(addString(name)));
for (int k = 0; k < invoke.getArguments().size(); ++k) {
Variable arg = wrapArgument(insn.getLocation(), invoke.getArguments().get(k),
Variable arg = wrapArgument(callLocation, invoke.getArguments().get(k),
method.parameterType(k));
newInvoke.getArguments().add(arg);
}
replacement.add(newInvoke);
if (result != null) {
result = unwrap(insn.getLocation(), result, method.getResultType());
result = unwrap(callLocation, result, method.getResultType());
copyVar(result, invoke.getReceiver());
}
}
@ -268,7 +269,7 @@ class JavascriptNativeProcessor {
return var;
}
private Variable unwrap(InstructionLocation location, Variable var, ValueType type) {
private Variable unwrap(CallLocation location, Variable var, ValueType type) {
if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive)type).getKind()) {
case BOOLEAN:
@ -320,7 +321,7 @@ class JavascriptNativeProcessor {
return result;
}
private Variable wrapArgument(InstructionLocation location, Variable var, ValueType type) {
private Variable wrapArgument(CallLocation location, Variable var, ValueType type) {
if (type instanceof ValueType.Object) {
String className = ((ValueType.Object)type).getClassName();
ClassReader cls = classSource.get(className);
@ -331,7 +332,7 @@ class JavascriptNativeProcessor {
return wrap(var, type);
}
private Variable wrapFunctor(InstructionLocation location, Variable var, ClassReader type) {
private Variable wrapFunctor(CallLocation location, Variable var, ClassReader type) {
if (!type.hasModifier(ElementModifier.INTERFACE) || type.getMethods().size() != 1) {
diagnostics.error(location, "Wrong functor: " + type.getName());
return var;

View File

@ -15,6 +15,7 @@
*/
package org.teavm.platform.plugin;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.model.*;
import org.teavm.platform.metadata.MetadataProvider;

View File

@ -15,6 +15,7 @@
*/
package org.teavm.platform.plugin;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*;
import org.teavm.vm.spi.TeaVMHost;

View File

@ -15,6 +15,7 @@
*/
package org.teavm.platform.plugin;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*;
/**