Refuse from CallStack for complete CallGraph

This commit is contained in:
Alexey Andreev 2014-11-23 22:34:12 +03:00
parent e736cf09d7
commit 30781bb16e
30 changed files with 714 additions and 296 deletions

View File

@ -0,0 +1,41 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.callgraph;
import java.util.Collection;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReference;
/**
* <p>Root object for traversing through call graph. Graph does not represent polymorphic calls.
* Instead, it generated multiple call sites for one location.</p>
*
* @author Alexey Andreev
*/
public interface CallGraph {
/**
* <p>Get node corresponding to the specific method.</p>
*
* @param method a method to lookup node for.
* @return the node that corresponds to the specified method or <code>null</code>, if this method is never
* called.
*/
CallGraphNode getNode(MethodReference method);
Collection<? extends FieldAccessSite> getFieldAccess(FieldReference reference);
Collection<? extends ClassAccessSite> getClassAccess(String className);
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.callgraph;
import java.util.Collection;
import org.teavm.model.MethodReference;
/**
* Represents a method with information about what methods does it call and what method do call the method.
* @author Alexey Andreev
*/
public interface CallGraphNode {
/*
* Returns reference to entire call graph.
*/
CallGraph getGraph();
/**
* Returns the method that this node represents.
*/
MethodReference getMethod();
/**
* Returns immutable collection of all call sites that are in the method.
*/
Collection<? extends CallSite> getCallSites();
/**
* Returns immutable collection of all call sites that call this method.
*/
Collection<? extends CallSite> getCallerCallSites();
Collection<? extends FieldAccessSite> getFieldAccessSites();
Collection<? extends ClassAccessSite> getClassAccessSites();
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.callgraph;
import org.teavm.model.InstructionLocation;
/**
* <p>Call site that represents exact place in the code that calls a method.</p>.
* @author Alexey Andreev
*/
public interface CallSite {
/**
* <p>Gets location of the call site</p>.
*
* @return location of the call site or <code>null</code> if no debug information found for this call site.
*/
InstructionLocation getLocation();
/**
* <p>Gets a method that this call site invokes.</p>
*/
CallGraphNode getCallee();
/**
* <p>Gets a method that contains this call site.</p>
*/
CallGraphNode getCaller();
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.callgraph;
import org.teavm.model.InstructionLocation;
/**
*
* @author Alexey Andreev
*/
public interface ClassAccessSite {
InstructionLocation getLocation();
CallGraphNode getCallee();
String getClassName();
}

View File

@ -0,0 +1,72 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.callgraph;
import java.util.*;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class DefaultCallGraph implements CallGraph {
private Map<MethodReference, DefaultCallGraphNode> nodes = new HashMap<>();
private Map<FieldReference, Set<DefaultFieldAccessSite>> fieldAccessSites = new HashMap<>();
private Map<String, Set<DefaultClassAccessSite>> classAccessSites = new HashMap<>();
@Override
public DefaultCallGraphNode getNode(MethodReference method) {
DefaultCallGraphNode node = nodes.get(method);
if (node == null) {
node = new DefaultCallGraphNode(this);
nodes.put(method, node);
}
return nodes.get(method);
}
@Override
public Collection<DefaultFieldAccessSite> getFieldAccess(FieldReference reference) {
Set<DefaultFieldAccessSite> resultSet = fieldAccessSites.get(reference);
return resultSet != null ? Collections.unmodifiableSet(resultSet) :
Collections.<DefaultFieldAccessSite>emptySet();
}
void addFieldAccess(DefaultFieldAccessSite accessSite) {
Set<DefaultFieldAccessSite> sites = fieldAccessSites.get(accessSite.getField());
if (sites == null) {
sites = new HashSet<>();
fieldAccessSites.put(accessSite.getField(), sites);
}
sites.add(accessSite);
}
@Override
public Collection<DefaultClassAccessSite> getClassAccess(String className) {
Set<DefaultClassAccessSite> resultSet = classAccessSites.get(className);
return resultSet != null ? Collections.unmodifiableSet(resultSet) :
Collections.<DefaultClassAccessSite>emptySet();
}
void addClassAccess(DefaultClassAccessSite accessSite) {
Set<DefaultClassAccessSite> sites = classAccessSites.get(accessSite.getClassName());
if (sites == null) {
sites = new HashSet<>();
classAccessSites.put(accessSite.getClassName(), sites);
}
sites.add(accessSite);
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.callgraph;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.teavm.model.FieldReference;
import org.teavm.model.InstructionLocation;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class DefaultCallGraphNode implements CallGraphNode {
private DefaultCallGraph graph;
private MethodReference method;
private Set<DefaultCallSite> callSites;
private transient Set<DefaultCallSite> safeCallSites;
private List<DefaultCallSite> callerCallSites;
private transient List<DefaultCallSite> safeCallersCallSites;
private Set<DefaultFieldAccessSite> fieldAccessSites;
private transient Set<DefaultFieldAccessSite> safeFieldAccessSites;
private Set<DefaultClassAccessSite> classAccessSites;
private transient Set<DefaultClassAccessSite> safeClassAccessSites;
DefaultCallGraphNode(DefaultCallGraph graph) {
this.graph = graph;
}
@Override
public DefaultCallGraph getGraph() {
return graph;
}
@Override
public MethodReference getMethod() {
return method;
}
@Override
public Collection<DefaultCallSite> getCallSites() {
if (safeCallSites == null) {
safeCallSites = Collections.unmodifiableSet(callSites);
}
return safeCallSites;
}
@Override
public Collection<DefaultCallSite> getCallerCallSites() {
if (safeCallersCallSites == null) {
safeCallersCallSites = Collections.unmodifiableList(callerCallSites);
}
return safeCallersCallSites;
}
public void addCallSite(MethodReference method, InstructionLocation location) {
DefaultCallGraphNode callee = graph.getNode(method);
DefaultCallSite callSite = new DefaultCallSite(location, callee, this);
if (callSites.add(callSite)) {
callee.callerCallSites.add(callSite);
}
}
public void addCallSite(MethodReference method) {
addCallSite(method, null);
}
@Override
public Collection<DefaultFieldAccessSite> getFieldAccessSites() {
if (safeFieldAccessSites == null) {
safeFieldAccessSites = Collections.unmodifiableSet(fieldAccessSites);
}
return safeFieldAccessSites;
}
public void addFieldAccess(FieldReference field, InstructionLocation location) {
DefaultFieldAccessSite site = new DefaultFieldAccessSite(location, this, field);
if (fieldAccessSites.add(site)) {
graph.addFieldAccess(site);
}
}
@Override
public Collection<? extends ClassAccessSite> getClassAccessSites() {
if (safeClassAccessSites == null) {
safeClassAccessSites = Collections.unmodifiableSet(classAccessSites);
}
return safeClassAccessSites;
}
public void addClassAccess(String className, InstructionLocation location) {
DefaultClassAccessSite site = new DefaultClassAccessSite(location, this, className);
if (classAccessSites.add(site)) {
graph.addClassAccess(site);
}
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.callgraph;
import java.util.Objects;
import org.teavm.model.InstructionLocation;
/**
*
* @author Alexey Andreev
*/
public class DefaultCallSite implements CallSite {
private InstructionLocation location;
private DefaultCallGraphNode callee;
private DefaultCallGraphNode caller;
DefaultCallSite(InstructionLocation location, DefaultCallGraphNode callee, DefaultCallGraphNode caller) {
this.location = location;
this.callee = callee;
this.caller = caller;
}
@Override
public InstructionLocation getLocation() {
return location;
}
@Override
public DefaultCallGraphNode getCallee() {
return callee;
}
@Override
public DefaultCallGraphNode getCaller() {
return caller;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof DefaultCallSite)) {
return false;
}
DefaultCallSite other = (DefaultCallSite)obj;
return Objects.equals(callee.getMethod(), other.callee.getMethod()) &&
Objects.equals(location, other.location);
}
@Override
public int hashCode() {
return Objects.hash(callee.getMethod(), location);
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.callgraph;
import org.teavm.model.InstructionLocation;
/**
*
* @author Alexey Andreev
*/
public class DefaultClassAccessSite implements ClassAccessSite {
private InstructionLocation location;
private CallGraphNode callee;
private String className;
DefaultClassAccessSite(InstructionLocation location, CallGraphNode callee, String className) {
this.location = location;
this.callee = callee;
this.className = className;
}
@Override
public InstructionLocation getLocation() {
return location;
}
@Override
public CallGraphNode getCallee() {
return callee;
}
@Override
public String getClassName() {
return className;
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.callgraph;
import java.util.Objects;
import org.teavm.model.FieldReference;
import org.teavm.model.InstructionLocation;
/**
*
* @author Alexey Andreev
*/
public class DefaultFieldAccessSite implements FieldAccessSite {
private InstructionLocation location;
private CallGraphNode callee;
private FieldReference field;
DefaultFieldAccessSite(InstructionLocation location, CallGraphNode callee, FieldReference field) {
this.location = location;
this.callee = callee;
this.field = field;
}
@Override
public InstructionLocation getLocation() {
return null;
}
@Override
public CallGraphNode getCallee() {
return null;
}
@Override
public FieldReference getField() {
return null;
}
@Override
public int hashCode() {
return Objects.hash(location, callee, field);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof DefaultFieldAccessSite)) {
return false;
}
DefaultFieldAccessSite other = (DefaultFieldAccessSite)obj;
return Objects.equals(location, other.location) && Objects.equals(callee, other.callee) &&
Objects.equals(field, other.field);
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.callgraph;
import org.teavm.model.FieldReference;
import org.teavm.model.InstructionLocation;
/**
*
* @author Alexey Andreev
*/
public interface FieldAccessSite {
InstructionLocation getLocation();
CallGraphNode getCallee();
FieldReference getField();
}

View File

@ -16,6 +16,8 @@
package org.teavm.dependency; package org.teavm.dependency;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
import org.teavm.model.InstructionLocation;
import org.teavm.model.MethodReference;
/** /**
* *
@ -24,13 +26,11 @@ import org.teavm.model.ClassReader;
public class ClassDependency implements ClassDependencyInfo { public class ClassDependency implements ClassDependencyInfo {
private DependencyChecker checker; private DependencyChecker checker;
private String className; private String className;
private DependencyStack stack;
private ClassReader classReader; private ClassReader classReader;
ClassDependency(DependencyChecker checker, String className, DependencyStack stack, ClassReader classReader) { ClassDependency(DependencyChecker checker, String className, ClassReader classReader) {
this.checker = checker; this.checker = checker;
this.className = className; this.className = className;
this.stack = stack;
this.classReader = classReader; this.classReader = classReader;
} }
@ -48,14 +48,9 @@ public class ClassDependency implements ClassDependencyInfo {
return classReader; return classReader;
} }
@Override public void initClass(MethodReference caller, InstructionLocation location) {
public DependencyStack getStack() {
return stack;
}
public void initClass(DependencyStack stack) {
if (!isMissing()) { if (!isMissing()) {
checker.initClass(this, stack); checker.initClass(this, caller, location);
} }
} }
} }

View File

@ -23,6 +23,4 @@ public interface ClassDependencyInfo {
String getClassName(); String getClassName();
boolean isMissing(); boolean isMissing();
DependencyStack getStack();
} }

View File

@ -16,10 +16,8 @@
package org.teavm.dependency; package org.teavm.dependency;
import org.teavm.common.ServiceRepository; import org.teavm.common.ServiceRepository;
import org.teavm.model.ClassHolder; import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.Diagnostics; import org.teavm.model.*;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReference;
/** /**
* *
@ -34,11 +32,11 @@ public interface DependencyAgent extends DependencyInfo, ServiceRepository {
void submitClass(ClassHolder cls); void submitClass(ClassHolder cls);
MethodDependency linkMethod(MethodReference methodRef, DependencyStack stack); MethodDependency linkMethod(MethodReference methodRef, MethodReference caller, InstructionLocation location);
ClassDependency linkClass(String className, final DependencyStack stack); ClassDependency linkClass(String className, MethodReference caller, InstructionLocation location);
FieldDependency linkField(FieldReference fieldRef, DependencyStack stack); FieldDependency linkField(FieldReference fieldRef, MethodReference caller, InstructionLocation location);
Diagnostics getDiagnostics(); Diagnostics getDiagnostics();
} }

View File

@ -17,8 +17,11 @@ package org.teavm.dependency;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import org.teavm.callgraph.CallGraph;
import org.teavm.callgraph.DefaultCallGraph;
import org.teavm.common.*; import org.teavm.common.*;
import org.teavm.common.CachedMapper.KeyListener; import org.teavm.common.CachedMapper.KeyListener;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.util.ModelUtils; import org.teavm.model.util.ModelUtils;
@ -33,9 +36,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
private ClassLoader classLoader; private ClassLoader classLoader;
private Mapper<MethodReference, MethodReader> methodReaderCache; private Mapper<MethodReference, MethodReader> methodReaderCache;
private Mapper<FieldReference, FieldReader> fieldReaderCache; private Mapper<FieldReference, FieldReader> fieldReaderCache;
private Map<MethodReference, DependencyStack> stacks = new HashMap<>();
private Map<FieldReference, DependencyStack> fieldStacks = new HashMap<>();
private Map<String, DependencyStack> classStacks = new HashMap<>();
private CachedMapper<MethodReference, MethodDependency> methodCache; private CachedMapper<MethodReference, MethodDependency> methodCache;
private CachedMapper<FieldReference, FieldDependency> fieldCache; private CachedMapper<FieldReference, FieldDependency> fieldCache;
private CachedMapper<String, ClassDependency> classCache; private CachedMapper<String, ClassDependency> classCache;
@ -51,6 +51,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
private DependencyCheckerInterruptor interruptor; private DependencyCheckerInterruptor interruptor;
private boolean interrupted; private boolean interrupted;
private Diagnostics diagnostics; private Diagnostics diagnostics;
private DefaultCallGraph callGraph = new DefaultCallGraph();
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services, public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
Diagnostics diagnostics) { Diagnostics diagnostics) {
@ -72,26 +73,24 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
@Override public MethodDependency map(MethodReference preimage) { @Override public MethodDependency map(MethodReference preimage) {
MethodReader method = methodReaderCache.map(preimage); MethodReader method = methodReaderCache.map(preimage);
if (method != null && !method.getReference().equals(preimage)) { if (method != null && !method.getReference().equals(preimage)) {
stacks.put(method.getReference(), stacks.get(preimage));
return methodCache.map(method.getReference()); return methodCache.map(method.getReference());
} }
return createMethodDep(preimage, method, stacks.get(preimage)); return createMethodDep(preimage, method);
} }
}); });
fieldCache = new CachedMapper<>(new Mapper<FieldReference, FieldDependency>() { fieldCache = new CachedMapper<>(new Mapper<FieldReference, FieldDependency>() {
@Override public FieldDependency map(FieldReference preimage) { @Override public FieldDependency map(FieldReference preimage) {
FieldReader field = fieldReaderCache.map(preimage); FieldReader field = fieldReaderCache.map(preimage);
if (field != null && !field.getReference().equals(preimage)) { if (field != null && !field.getReference().equals(preimage)) {
fieldStacks.put(field.getReference(), fieldStacks.get(preimage));
return fieldCache.map(field.getReference()); return fieldCache.map(field.getReference());
} }
return createFieldNode(preimage, field, fieldStacks.get(preimage)); return createFieldNode(preimage, field);
} }
}); });
classCache = new CachedMapper<>(new Mapper<String, ClassDependency>() { classCache = new CachedMapper<>(new Mapper<String, ClassDependency>() {
@Override public ClassDependency map(String preimage) { @Override public ClassDependency map(String preimage) {
return createClassDependency(preimage, classStacks.get(preimage)); return createClassDependency(preimage);
} }
}); });
methodCache.addKeyListener(new KeyListener<MethodReference>() { methodCache.addKeyListener(new KeyListener<MethodReference>() {
@ -167,7 +166,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
@Override @Override
public String generateClassName() { public String generateClassName() {
return "$$tmp$$.TempClass" + classNameSuffix++; return "$$teavm_generated_class$$" + classNameSuffix++;
} }
@Override @Override
@ -189,7 +188,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
if (parameters.length + 1 != argumentTypes.length) { if (parameters.length + 1 != argumentTypes.length) {
throw new IllegalArgumentException("argumentTypes length does not match the number of method's arguments"); throw new IllegalArgumentException("argumentTypes length does not match the number of method's arguments");
} }
MethodDependency method = linkMethod(methodRef, DependencyStack.ROOT); MethodDependency method = linkMethod(methodRef, null, null);
method.use(); method.use();
DependencyNode[] varNodes = method.getVariables(); DependencyNode[] varNodes = method.getVariables();
varNodes[0].propagate(getType(methodRef.getClassName())); varNodes[0].propagate(getType(methodRef.getClassName()));
@ -218,7 +217,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
@Override @Override
public ClassDependency linkClass(String className, DependencyStack stack) { public ClassDependency linkClass(String className, DependencyStack stack) {
classStacks.put(className, stack);
return classCache.map(className); return classCache.map(className);
} }
@ -239,21 +237,26 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
} }
@Override @Override
public MethodDependency linkMethod(MethodReference methodRef, DependencyStack stack) { public MethodDependency linkMethod(MethodReference methodRef, MethodReference caller,
InstructionLocation location) {
if (methodRef == null) { if (methodRef == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
stacks.put(methodRef, stack); callGraph.addNode(methodRef);
if (caller != null) {
callGraph.addNode(caller);
callGraph.getNode(caller).addCallSite(methodRef, location);
}
return methodCache.map(methodRef); return methodCache.map(methodRef);
} }
void initClass(ClassDependency cls, final DependencyStack stack) { void initClass(ClassDependency cls, final MethodReference caller, final InstructionLocation location) {
ClassReader reader = cls.getClassReader(); ClassReader reader = cls.getClassReader();
final MethodReader method = reader.getMethod(new MethodDescriptor("<clinit>", void.class)); final MethodReader method = reader.getMethod(new MethodDescriptor("<clinit>", void.class));
if (method != null) { if (method != null) {
tasks.add(new Runnable() { tasks.add(new Runnable() {
@Override public void run() { @Override public void run() {
linkMethod(method.getReference(), stack).use(); linkMethod(method.getReference(), caller, location).use();
} }
}); });
} }
@ -373,7 +376,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
} }
@Override @Override
public FieldDependency linkField(FieldReference fieldRef, DependencyStack stack) { public FieldDependency linkField(FieldReference fieldRef, MethodReference caller, InstructionLocation location) {
fieldStacks.put(fieldRef, stack); fieldStacks.put(fieldRef, stack);
return fieldCache.map(fieldRef); return fieldCache.map(fieldRef);
} }
@ -434,25 +437,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
return methodCache.getKnown(methodRef); return methodCache.getKnown(methodRef);
} }
public DependencyViolations getViolations() {
if (dependencyViolations == null) {
dependencyViolations = new DependencyViolations(missingMethods, missingClasses, missingFields);
}
return dependencyViolations;
}
public void checkForViolations() {
getViolations().checkForViolations();
}
public boolean hasViolations() {
return getViolations().hasSevereViolations();
}
public void showViolations(Appendable sb) throws IOException {
getViolations().showViolations(sb);
}
public void processDependencies() { public void processDependencies() {
interrupted = false; interrupted = false;
int index = 0; int index = 0;
@ -477,4 +461,8 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
public Diagnostics getDiagnostics() { public Diagnostics getDiagnostics() {
return diagnostics; return diagnostics;
} }
public CallGraph getCallGraph() {
return callGraph;
}
} }

View File

@ -22,6 +22,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import org.teavm.common.CachedMapper; import org.teavm.common.CachedMapper;
import org.teavm.common.Mapper; import org.teavm.common.Mapper;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.util.ModelUtils; import org.teavm.model.util.ModelUtils;

View File

@ -18,6 +18,7 @@ package org.teavm.dependency;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.teavm.callgraph.DefaultCallGraphNode;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.instructions.*; import org.teavm.model.instructions.*;
import org.teavm.model.util.ListingBuilder; import org.teavm.model.util.ListingBuilder;
@ -31,7 +32,8 @@ class DependencyGraphBuilder {
private DependencyNode[] nodes; private DependencyNode[] nodes;
private DependencyNode resultNode; private DependencyNode resultNode;
private ProgramReader program; private ProgramReader program;
private DependencyStack callerStack; private DefaultCallGraphNode caller;
private InstructionLocation currentLocation;
private ExceptionConsumer currentExceptionConsumer; private ExceptionConsumer currentExceptionConsumer;
public DependencyGraphBuilder(DependencyChecker dependencyChecker) { public DependencyGraphBuilder(DependencyChecker dependencyChecker) {
@ -50,7 +52,6 @@ class DependencyGraphBuilder {
} }
resultNode = dep.getResult(); resultNode = dep.getResult();
nodes = dep.getVariables(); nodes = dep.getVariables();
callerStack = new DependencyStack(method.getReference(), dep.getStack());
for (int i = 0; i < program.basicBlockCount(); ++i) { for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlockReader block = program.basicBlockAt(i); BasicBlockReader block = program.basicBlockAt(i);
currentExceptionConsumer = createExceptionConsumer(dep, block); currentExceptionConsumer = createExceptionConsumer(dep, block);
@ -62,7 +63,7 @@ class DependencyGraphBuilder {
} }
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
if (tryCatch.getExceptionType() != null) { if (tryCatch.getExceptionType() != null) {
dependencyChecker.linkClass(tryCatch.getExceptionType(), callerStack); dependencyChecker.linkClass(tryCatch.getExceptionType(), caller.getMethod(), null);
} }
} }
} }
@ -116,20 +117,23 @@ class DependencyGraphBuilder {
private final DependencyChecker checker; private final DependencyChecker checker;
private final DependencyNode[] parameters; private final DependencyNode[] parameters;
private final DependencyNode result; private final DependencyNode result;
private final DependencyStack stack; private final DefaultCallGraphNode caller;
private final InstructionLocation location;
private final Set<MethodReference> knownMethods = new HashSet<>(); private final Set<MethodReference> knownMethods = new HashSet<>();
private ExceptionConsumer exceptionConsumer; private ExceptionConsumer exceptionConsumer;
public VirtualCallConsumer(DependencyNode node, ClassReader filterClass, public VirtualCallConsumer(DependencyNode node, ClassReader filterClass,
MethodDescriptor methodDesc, DependencyChecker checker, DependencyNode[] parameters, MethodDescriptor methodDesc, DependencyChecker checker, DependencyNode[] parameters,
DependencyNode result, DependencyStack stack, ExceptionConsumer exceptionConsumer) { DependencyNode result, DefaultCallGraphNode caller, InstructionLocation location,
ExceptionConsumer exceptionConsumer) {
this.node = node; this.node = node;
this.filterClass = filterClass; this.filterClass = filterClass;
this.methodDesc = methodDesc; this.methodDesc = methodDesc;
this.checker = checker; this.checker = checker;
this.parameters = parameters; this.parameters = parameters;
this.result = result; this.result = result;
this.stack = stack; this.caller = caller;
this.location = location;
this.exceptionConsumer = exceptionConsumer; this.exceptionConsumer = exceptionConsumer;
} }
@ -147,7 +151,7 @@ class DependencyGraphBuilder {
return; return;
} }
MethodReference methodRef = new MethodReference(className, methodDesc); MethodReference methodRef = new MethodReference(className, methodDesc);
MethodDependency methodDep = checker.linkMethod(methodRef, stack); MethodDependency methodDep = checker.linkMethod(methodRef, caller.getMethod(), location);
if (!methodDep.isMissing() && knownMethods.add(methodRef)) { if (!methodDep.isMissing() && knownMethods.add(methodRef)) {
methodDep.use(); methodDep.use();
DependencyNode[] targetParams = methodDep.getVariables(); DependencyNode[] targetParams = methodDep.getVariables();
@ -185,7 +189,7 @@ class DependencyGraphBuilder {
private InstructionReader reader = new InstructionReader() { private InstructionReader reader = new InstructionReader() {
@Override @Override
public void location(InstructionLocation location) { public void location(InstructionLocation location) {
callerStack = new DependencyStack(callerStack.getMethod(), location, callerStack.getCause()); currentLocation = location;
} }
@Override @Override
@ -200,7 +204,7 @@ class DependencyGraphBuilder {
} }
if (cst instanceof ValueType.Object) { if (cst instanceof ValueType.Object) {
final String className = ((ValueType.Object)cst).getClassName(); final String className = ((ValueType.Object)cst).getClassName();
dependencyChecker.linkClass(className, callerStack); dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
} }
} }
@ -228,7 +232,7 @@ class DependencyGraphBuilder {
public void stringConstant(VariableReader receiver, String cst) { public void stringConstant(VariableReader receiver, String cst) {
nodes[receiver.getIndex()].propagate(dependencyChecker.getType("java.lang.String")); nodes[receiver.getIndex()].propagate(dependencyChecker.getType("java.lang.String"));
MethodDependency method = dependencyChecker.linkMethod(new MethodReference(String.class, MethodDependency method = dependencyChecker.linkMethod(new MethodReference(String.class,
"<init>", char[].class, void.class), callerStack); "<init>", char[].class, void.class), caller.getMethod(), currentLocation);
method.use(); method.use();
} }
@ -316,7 +320,7 @@ class DependencyGraphBuilder {
nodes[receiver.getIndex()].propagate(dependencyChecker.getType("[" + itemType)); nodes[receiver.getIndex()].propagate(dependencyChecker.getType("[" + itemType));
String className = extractClassName(itemType); String className = extractClassName(itemType);
if (className != null) { if (className != null) {
dependencyChecker.linkClass(className, callerStack); dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
} }
} }
@ -338,7 +342,7 @@ class DependencyGraphBuilder {
nodes[receiver.getIndex()].propagate(dependencyChecker.getType(sb.toString())); nodes[receiver.getIndex()].propagate(dependencyChecker.getType(sb.toString()));
String className = extractClassName(itemType); String className = extractClassName(itemType);
if (className != null) { if (className != null) {
dependencyChecker.linkClass(className, callerStack); dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
} }
} }
@ -350,7 +354,7 @@ class DependencyGraphBuilder {
@Override @Override
public void getField(VariableReader receiver, VariableReader instance, FieldReference field, public void getField(VariableReader receiver, VariableReader instance, FieldReference field,
ValueType fieldType) { ValueType fieldType) {
FieldDependency fieldDep = dependencyChecker.linkField(field, callerStack); FieldDependency fieldDep = dependencyChecker.linkField(field, caller.getMethod(), currentLocation);
DependencyNode receiverNode = nodes[receiver.getIndex()]; DependencyNode receiverNode = nodes[receiver.getIndex()];
fieldDep.getValue().connect(receiverNode); fieldDep.getValue().connect(receiverNode);
initClass(field.getClassName()); initClass(field.getClassName());
@ -358,7 +362,7 @@ class DependencyGraphBuilder {
@Override @Override
public void putField(VariableReader instance, FieldReference field, VariableReader value) { public void putField(VariableReader instance, FieldReference field, VariableReader value) {
FieldDependency fieldDep = dependencyChecker.linkField(field, callerStack); FieldDependency fieldDep = dependencyChecker.linkField(field, caller.getMethod(), currentLocation);
DependencyNode valueNode = nodes[value.getIndex()]; DependencyNode valueNode = nodes[value.getIndex()];
valueNode.connect(fieldDep.getValue()); valueNode.connect(fieldDep.getValue());
initClass(field.getClassName()); initClass(field.getClassName());
@ -420,7 +424,7 @@ class DependencyGraphBuilder {
private void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method, private void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method,
List<? extends VariableReader> arguments) { List<? extends VariableReader> arguments) {
MethodDependency methodDep = dependencyChecker.linkMethod(method, callerStack); MethodDependency methodDep = dependencyChecker.linkMethod(method, caller.getMethod(), currentLocation);
if (methodDep.isMissing()) { if (methodDep.isMissing()) {
return; return;
} }
@ -441,7 +445,7 @@ class DependencyGraphBuilder {
private void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method, private void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method,
List<? extends VariableReader> arguments) { List<? extends VariableReader> arguments) {
MethodDependency methodDep = dependencyChecker.linkMethod(method, callerStack); MethodDependency methodDep = dependencyChecker.linkMethod(method, caller.getMethod(), currentLocation);
if (methodDep.isMissing()) { if (methodDep.isMissing()) {
return; return;
} }
@ -453,7 +457,7 @@ class DependencyGraphBuilder {
DependencyConsumer listener = new VirtualCallConsumer(nodes[instance.getIndex()], DependencyConsumer listener = new VirtualCallConsumer(nodes[instance.getIndex()],
dependencyChecker.getClassSource().get(methodDep.getMethod().getOwnerName()), dependencyChecker.getClassSource().get(methodDep.getMethod().getOwnerName()),
method.getDescriptor(), dependencyChecker, actualArgs, method.getDescriptor(), dependencyChecker, actualArgs,
receiver != null ? nodes[receiver.getIndex()] : null, callerStack, receiver != null ? nodes[receiver.getIndex()] : null, caller, currentLocation,
currentExceptionConsumer); currentExceptionConsumer);
nodes[instance.getIndex()].addConsumer(listener); nodes[instance.getIndex()].addConsumer(listener);
} }
@ -462,13 +466,14 @@ class DependencyGraphBuilder {
public void isInstance(VariableReader receiver, VariableReader value, final ValueType type) { public void isInstance(VariableReader receiver, VariableReader value, final ValueType type) {
String className = extractClassName(type); String className = extractClassName(type);
if (className != null) { if (className != null) {
dependencyChecker.linkClass(className, callerStack); dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
} }
} }
@Override @Override
public void initClass(final String className) { public void initClass(final String className) {
dependencyChecker.linkClass(className, callerStack).initClass(callerStack); dependencyChecker.linkClass(className, caller.getMethod(), currentLocation)
.initClass(caller.getMethod(), currentLocation);
} }
@Override @Override
@ -476,8 +481,8 @@ class DependencyGraphBuilder {
DependencyNode valueNode = nodes[value.getIndex()]; DependencyNode valueNode = nodes[value.getIndex()];
DependencyNode receiverNode = nodes[receiver.getIndex()]; DependencyNode receiverNode = nodes[receiver.getIndex()];
valueNode.connect(receiverNode); valueNode.connect(receiverNode);
dependencyChecker.linkMethod(new MethodReference("java.lang.NullPointerException", dependencyChecker.linkMethod(new MethodReference(NullPointerException.class, "<init>", void.class),
"<init>", ValueType.VOID), callerStack).use(); caller.getMethod(), currentLocation).use();
currentExceptionConsumer.consume(dependencyChecker.getType("java.lang.NullPointerException")); currentExceptionConsumer.consume(dependencyChecker.getType("java.lang.NullPointerException"));
} }
}; };

View File

@ -1,85 +0,0 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.dependency;
import org.teavm.model.InstructionLocation;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class DependencyStack {
public static final DependencyStack ROOT = new DependencyStack();
private MethodReference method;
private DependencyStack cause;
private InstructionLocation location;
private DependencyStack() {
}
public DependencyStack(MethodReference method) {
this(method, ROOT);
}
public DependencyStack(MethodReference method, InstructionLocation location) {
this(method, location, ROOT);
}
public DependencyStack(MethodReference method, DependencyStack cause) {
this(method, null, cause);
}
public DependencyStack(MethodReference method, InstructionLocation location, DependencyStack cause) {
if (method == null || cause == null) {
throw new IllegalArgumentException("Arguments must not be null");
}
this.method = method;
this.location = location;
this.cause = cause;
}
public MethodReference getMethod() {
return method;
}
public DependencyStack getCause() {
return cause;
}
public InstructionLocation getLocation() {
return location;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
DependencyStack stack = this;
while (true) {
if (stack.method == null) {
sb.append(" used by ROOT\n");
break;
} else {
sb.append(" used by " + stack.method);
if (stack.location != null) {
sb.append(" : ").append(stack.location.getLine());
}
stack = stack.cause;
}
}
return sb.toString();
}
}

View File

@ -1,102 +0,0 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.dependency;
import java.io.IOException;
import java.util.*;
/**
*
* @author Alexey Andreev
*/
public class DependencyViolations {
private final Set<MethodDependencyInfo> missingMethods;
private final Set<ClassDependencyInfo> missingClasses;
private final Set<FieldDependencyInfo> missingFields;
DependencyViolations(Collection<? extends MethodDependencyInfo> missingMethods,
Collection<? extends ClassDependencyInfo> missingClasses,
Collection<? extends FieldDependencyInfo> missingFields) {
this.missingMethods = Collections.unmodifiableSet(new HashSet<>(missingMethods));
this.missingClasses = Collections.unmodifiableSet(new HashSet<>(missingClasses));
this.missingFields = Collections.unmodifiableSet(new HashSet<>(missingFields));
}
public Set<MethodDependencyInfo> getMissingMethods() {
return missingMethods;
}
public Set<ClassDependencyInfo> getMissingClasses() {
return missingClasses;
}
public Set<FieldDependencyInfo> getMissingFields() {
return missingFields;
}
public boolean hasSevereViolations() {
return !missingMethods.isEmpty() || !missingClasses.isEmpty() || !missingFields.isEmpty();
}
public void checkForViolations() {
if (!hasSevereViolations()) {
return;
}
StringBuilder sb = new StringBuilder();
try {
showViolations(sb);
} catch (IOException e) {
throw new AssertionError("StringBuilder should not throw IOException");
}
throw new IllegalStateException(sb.toString());
}
public void showViolations(Appendable sb) throws IOException {
List<String> items = new ArrayList<>();
Map<String, DependencyStack> stackMap = new HashMap<>();
for (ClassDependencyInfo cls : missingClasses) {
stackMap.put(cls.getClassName(), cls.getStack());
items.add(cls.getClassName());
}
for (MethodDependencyInfo method : missingMethods) {
stackMap.put(method.getReference().toString(), method.getStack());
items.add(method.getReference().toString());
}
for (FieldDependencyInfo field : missingFields) {
stackMap.put(field.getReference().toString(), field.getStack());
items.add(field.getReference().toString());
}
Collections.sort(items);
sb.append("Can't compile due to the following violations:\n");
for (String item : items) {
sb.append("Missing ").append(item).append("\n");
DependencyStack stack = stackMap.get(item);
if (stack == null) {
sb.append(" at unknown location\n");
} else {
while (stack.getMethod() != null) {
sb.append(" at ").append(stack.getMethod().toString());
if (stack.getLocation() != null) {
sb.append(":").append(String.valueOf(stack.getLocation().getLine()));
}
sb.append("\n");
stack = stack.getCause();
}
}
sb.append('\n');
}
}
}

View File

@ -27,6 +27,4 @@ public interface FieldDependencyInfo {
FieldReference getReference(); FieldReference getReference();
boolean isMissing(); boolean isMissing();
DependencyStack getStack();
} }

View File

@ -39,6 +39,4 @@ public interface MethodDependencyInfo {
boolean isUsed(); boolean isUsed();
boolean isMissing(); boolean isMissing();
DependencyStack getStack();
} }

View File

@ -13,26 +13,24 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.dependency; package org.teavm.diagnostics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.teavm.model.Diagnostics;
import org.teavm.model.InstructionLocation; import org.teavm.model.InstructionLocation;
import org.teavm.vm.DiagnosticsProblem; import org.teavm.model.MethodReference;
import org.teavm.vm.DiagnosticsProblemSeverity;
/** /**
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
class DependencyDiagnostics implements Diagnostics { class DependencyDiagnostics implements Diagnostics {
private List<DiagnosticsProblem> problems = new ArrayList<>(); private List<Problem> problems = new ArrayList<>();
private List<DiagnosticsProblem> severeProblems = new ArrayList<>(); private List<Problem> severeProblems = new ArrayList<>();
@Override @Override
public void error(InstructionLocation location, String error) { public void error(MethodReference method, InstructionLocation location, String error, Object[] params) {
DiagnosticsProblem violation = new DiagnosticsProblem(DiagnosticsProblemSeverity.ERROR, location, error); Problem violation = new Problem(ProblemSeverity.ERROR, location, error);
problems.add(violation); problems.add(violation);
severeProblems.add(violation); severeProblems.add(violation);
} }
@ -44,7 +42,7 @@ class DependencyDiagnostics implements Diagnostics {
@Override @Override
public void warning(InstructionLocation location, String error) { public void warning(InstructionLocation location, String error) {
DiagnosticsProblem violation = new DiagnosticsProblem(DiagnosticsProblemSeverity.WARNING, location, error); Problem violation = new Problem(ProblemSeverity.WARNING, location, error);
problems.add(violation); problems.add(violation);
} }
@ -53,11 +51,11 @@ class DependencyDiagnostics implements Diagnostics {
warning(null, error); warning(null, error);
} }
public List<DiagnosticsProblem> getProblems() { public List<Problem> getProblems() {
return problems; return problems;
} }
public List<DiagnosticsProblem> getSevereProblems() { public List<Problem> getSevereProblems() {
return severeProblems; return severeProblems;
} }
} }

View File

@ -13,19 +13,16 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.model; package org.teavm.diagnostics;
import org.teavm.model.CallLocation;
/** /**
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public interface Diagnostics { public interface Diagnostics {
void error(InstructionLocation location, String error); void error(CallLocation location, String error, Object... params);
void error(String error); void warning(CallLocation location, String error, Object... params);
void warning(InstructionLocation location, String error);
void warning(String error);
} }

View File

@ -13,30 +13,33 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.vm; package org.teavm.diagnostics;
import org.teavm.model.InstructionLocation; import java.util.Arrays;
import org.teavm.model.CallLocation;
/** /**
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public class DiagnosticsProblem { public class Problem {
private DiagnosticsProblemSeverity severity; private ProblemSeverity severity;
private InstructionLocation location; private CallLocation location;
private String text; private String text;
private Object[] params;
public DiagnosticsProblem(DiagnosticsProblemSeverity severity, InstructionLocation location, String text) { public Problem(ProblemSeverity severity, CallLocation location, String text, Object[] params) {
this.severity = severity; this.severity = severity;
this.location = location; this.location = location;
this.text = text; this.text = text;
this.params = Arrays.copyOf(params, params.length);
} }
public DiagnosticsProblemSeverity getSeverity() { public ProblemSeverity getSeverity() {
return severity; return severity;
} }
public InstructionLocation getLocation() { public CallLocation getLocation() {
return location; return location;
} }

View File

@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.vm; package org.teavm.diagnostics;
/** /**
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public enum DiagnosticsProblemSeverity { public enum ProblemSeverity {
ERROR, ERROR,
WARNING WARNING
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.javascript; package org.teavm.javascript;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.instructions.InvocationType; import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction; import org.teavm.model.instructions.InvokeInstruction;

View File

@ -0,0 +1,57 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.model;
import java.util.Objects;
/**
*
* @author Alexey Andreev
*/
public class CallLocation {
private MethodReference method;
private InstructionLocation sourceLocation;
public CallLocation(MethodReference method, InstructionLocation sourceLocation) {
this.method = method;
this.sourceLocation = sourceLocation;
}
public MethodReference getMethod() {
return method;
}
public InstructionLocation getSourceLocation() {
return sourceLocation;
}
@Override
public int hashCode() {
return Objects.hash(method, sourceLocation);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof CallLocation)) {
return false;
}
CallLocation other = (CallLocation)obj;
return Objects.equals(method, other.method) && Objects.equals(sourceLocation, other.sourceLocation);
}
}

View File

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

View File

@ -20,6 +20,7 @@ import java.util.Set;
import org.teavm.dependency.ClassDependencyInfo; import org.teavm.dependency.ClassDependencyInfo;
import org.teavm.dependency.FieldDependencyInfo; import org.teavm.dependency.FieldDependencyInfo;
import org.teavm.dependency.MethodDependencyInfo; import org.teavm.dependency.MethodDependencyInfo;
import org.teavm.diagnostics.Problem;
/** /**
* *
@ -32,9 +33,9 @@ public interface Violations {
Set<FieldDependencyInfo> getMissingFields(); Set<FieldDependencyInfo> getMissingFields();
List<DiagnosticsProblem> getDiagnosticsProblems(); List<Problem> getDiagnosticsProblems();
List<DiagnosticsProblem> getSevereDiagnosticsProblems(); List<Problem> getSevereDiagnosticsProblems();
boolean hasSevereViolations(); boolean hasSevereViolations();

View File

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

View File

@ -16,6 +16,7 @@
package org.teavm.jso.plugin; package org.teavm.jso.plugin;
import java.util.*; import java.util.*;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.javascript.ni.PreserveOriginalName; import org.teavm.javascript.ni.PreserveOriginalName;
import org.teavm.jso.*; import org.teavm.jso.*;
import org.teavm.model.*; import org.teavm.model.*;