konsoletyper 2015-02-21 13:04:09 +04:00
parent 123aac84fa
commit 34aeb6e3c9
6 changed files with 44 additions and 9 deletions

View File

@ -252,6 +252,10 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
if (methodRef == null) { if (methodRef == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
MethodReader methodReader = methodReaderCache.map(methodRef);
if (methodReader != null) {
methodRef = methodReader.getReference();
}
callGraph.getNode(methodRef); callGraph.getNode(methodRef);
boolean added = true; boolean added = true;
if (callLocation != null && callLocation.getMethod() != null) { if (callLocation != null && callLocation.getMethod() != null) {
@ -472,6 +476,12 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
return methodCache.getKnown(methodRef); return methodCache.getKnown(methodRef);
} }
@Override
public MethodDependency getMethodImplementation(MethodReference methodRef) {
MethodReader method = methodReaderCache.map(methodRef);
return method != null ? methodCache.getKnown(method.getReference()) : null;
}
public void processDependencies() { public void processDependencies() {
interrupted = false; interrupted = false;
int index = 0; int index = 0;

View File

@ -40,6 +40,8 @@ public interface DependencyInfo {
MethodDependencyInfo getMethod(MethodReference methodRef); MethodDependencyInfo getMethod(MethodReference methodRef);
MethodDependencyInfo getMethodImplementation(MethodReference methodRef);
ClassDependencyInfo getClass(String className); ClassDependencyInfo getClass(String className);
CallGraph getCallGraph(); CallGraph getCallGraph();

View File

@ -46,14 +46,15 @@ public class Decompiler {
private Set<MethodReference> methodsToPass = new HashSet<>(); private Set<MethodReference> methodsToPass = new HashSet<>();
private RegularMethodNodeCache regularMethodCache; private RegularMethodNodeCache regularMethodCache;
private Set<MethodReference> asyncMethods; private Set<MethodReference> asyncMethods;
private Set<MethodReference> asyncFamilyMethods; private Set<MethodReference> splitMethods = new HashSet<>();
public Decompiler(ClassHolderSource classSource, ClassLoader classLoader, Set<MethodReference> asyncMethods, public Decompiler(ClassHolderSource classSource, ClassLoader classLoader, Set<MethodReference> asyncMethods,
Set<MethodReference> asyncFamilyMethods) { Set<MethodReference> asyncFamilyMethods) {
this.classSource = classSource; this.classSource = classSource;
this.classLoader = classLoader; this.classLoader = classLoader;
this.asyncMethods = asyncMethods; this.asyncMethods = asyncMethods;
this.asyncFamilyMethods = asyncFamilyMethods; splitMethods.addAll(asyncMethods);
splitMethods.addAll(asyncFamilyMethods);
} }
public RegularMethodNodeCache getRegularMethodCache() { public RegularMethodNodeCache getRegularMethodCache() {
@ -199,10 +200,7 @@ public class Decompiler {
public AsyncMethodNode decompileAsync(MethodHolder method) { public AsyncMethodNode decompileAsync(MethodHolder method) {
AsyncMethodNode node = new AsyncMethodNode(method.getReference()); AsyncMethodNode node = new AsyncMethodNode(method.getReference());
Set<MethodReference> splitMethods = new HashSet<>(); AsyncProgramSplitter splitter = new AsyncProgramSplitter(classSource, splitMethods);
splitMethods.addAll(asyncMethods);
splitMethods.addAll(asyncFamilyMethods);
AsyncProgramSplitter splitter = new AsyncProgramSplitter(splitMethods);
splitter.split(method.getProgram()); splitter.split(method.getProgram());
for (int i = 0; i < splitter.size(); ++i) { for (int i = 0; i < splitter.size(); ++i) {
Integer input = null; Integer input = null;

View File

@ -28,9 +28,11 @@ import org.teavm.model.instructions.MonitorEnterInstruction;
public class AsyncProgramSplitter { public class AsyncProgramSplitter {
private List<Part> parts = new ArrayList<>(); private List<Part> parts = new ArrayList<>();
private Map<Long, Integer> partMap = new HashMap<>(); private Map<Long, Integer> partMap = new HashMap<>();
private ClassReaderSource classSource;
private Set<MethodReference> asyncMethods = new HashSet<>(); private Set<MethodReference> asyncMethods = new HashSet<>();
public AsyncProgramSplitter(Set<MethodReference> asyncMethods) { public AsyncProgramSplitter(ClassReaderSource classSource, Set<MethodReference> asyncMethods) {
this.classSource = classSource;
this.asyncMethods = asyncMethods; this.asyncMethods = asyncMethods;
} }
@ -62,7 +64,7 @@ public class AsyncProgramSplitter {
Integer receiver; Integer receiver;
if (insn instanceof InvokeInstruction) { if (insn instanceof InvokeInstruction) {
InvokeInstruction invoke = (InvokeInstruction)insn; InvokeInstruction invoke = (InvokeInstruction)insn;
if (!asyncMethods.contains(invoke.getMethod())) { if (!asyncMethods.contains(findRealMethod(invoke.getMethod()))) {
continue; continue;
} }
receiver = invoke.getReceiver() != null ? invoke.getReceiver().getIndex() : null; receiver = invoke.getReceiver() != null ? invoke.getReceiver().getIndex() : null;
@ -148,6 +150,25 @@ public class AsyncProgramSplitter {
partMap.clear(); partMap.clear();
} }
private MethodReference findRealMethod(MethodReference method) {
String clsName = method.getClassName();
while (clsName != null) {
ClassReader cls = classSource.get(clsName);
if (cls == null) {
break;
}
MethodReader methodReader = cls.getMethod(method.getDescriptor());
if (methodReader != null) {
return new MethodReference(clsName, method.getDescriptor());
}
clsName = cls.getParent();
if (clsName != null && clsName.equals(cls.getName())) {
break;
}
}
return method;
}
private Program createStubCopy(Program program) { private Program createStubCopy(Program program) {
Program copy = new Program(); Program copy = new Program();
for (int i = 0; i < program.basicBlockCount(); ++i) { for (int i = 0; i < program.basicBlockCount(); ++i) {

View File

@ -74,7 +74,8 @@ public class Devirtualization {
if (cls == null || !isAssignable(ref.getClassName(), cls)) { if (cls == null || !isAssignable(ref.getClassName(), cls)) {
continue; continue;
} }
MethodDependencyInfo methodDep = dependency.getMethod(new MethodReference(className, ref.getDescriptor())); MethodDependencyInfo methodDep = dependency.getMethodImplementation(new MethodReference(
className, ref.getDescriptor()));
if (methodDep != null) { if (methodDep != null) {
methods.add(methodDep.getReference()); methods.add(methodDep.getReference());
} }

View File

@ -558,6 +558,9 @@ function $rt_guardAsync(f, continuation) {
function TeaVMAsyncError(cause) { function TeaVMAsyncError(cause) {
this.message = "Async error occured"; this.message = "Async error occured";
this.cause = cause; this.cause = cause;
if (cause) {
this.$javaException = cause.$javaException;
}
} }
TeaVMAsyncError.prototype = new Error(); TeaVMAsyncError.prototype = new Error();
TeaVMAsyncError.prototype.constructor = TeaVMAsyncError; TeaVMAsyncError.prototype.constructor = TeaVMAsyncError;