Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

V 0.7.1

	deleted:    .#d.txt
	modified:   examples/kilim/examples/HttpFileServer.java
	modified:   src/kilim/Mailbox.java
	modified:   src/kilim/analysis/AsmDetector.java
	modified:   src/kilim/analysis/BasicBlock.java
	modified:   src/kilim/analysis/CallWeaver.java
	modified:   src/kilim/analysis/ClassFlow.java
	modified:   src/kilim/analysis/ClassWeaver.java
	modified:   src/kilim/analysis/Detector.java
	modified:   src/kilim/analysis/FileLister.java
	modified:   src/kilim/analysis/Frame.java
	modified:   src/kilim/analysis/MethodFlow.java
	modified:   src/kilim/analysis/MethodWeaver.java
	modified:   src/kilim/analysis/TypeDesc.java
	modified:   src/kilim/analysis/Value.java
	modified:   src/kilim/http/HttpSession.java
	new file:   src/kilim/mirrors/ClassMirror.java
	new file:   src/kilim/mirrors/ClassMirrorNotFoundException.java
	new file:   src/kilim/mirrors/FieldMirror.java
	new file:   src/kilim/mirrors/MemberMirror.java
	new file:   src/kilim/mirrors/MethodMirror.java
	new file:   src/kilim/mirrors/Mirrors.java
	new file:   src/kilim/mirrors/RuntimeClassMirrors.java
	modified:   src/kilim/nio/EndPoint.java
	modified:   src/kilim/tools/DumpClass.java
	modified:   src/kilim/tools/FlowAnalyzer.java
	modified:   src/kilim/tools/Weaver.java
	modified:   test/kilim/test/Base.java
	modified:   test/kilim/test/TestInvalidPausables.java
  • Loading branch information...
commit aa68747588afe97cfd22381e5ed1d672c2228a21 1 parent 4bb92e3
@sriram-srinivasan sriram-srinivasan authored
Showing with 652 additions and 221 deletions.
  1. +0 −1  .#d.txt
  2. +20 −12 examples/kilim/examples/HttpFileServer.java
  3. +9 −6 src/kilim/Mailbox.java
  4. +4 −3 src/kilim/analysis/AsmDetector.java
  5. +18 −8 src/kilim/analysis/BasicBlock.java
  6. +0 −1  src/kilim/analysis/CallWeaver.java
  7. +99 −69 src/kilim/analysis/ClassFlow.java
  8. +9 −4 src/kilim/analysis/ClassWeaver.java
  9. +114 −23 src/kilim/analysis/Detector.java
  10. +4 −0 src/kilim/analysis/FileLister.java
  11. +3 −0  src/kilim/analysis/Frame.java
  12. +28 −15 src/kilim/analysis/MethodFlow.java
  13. +8 −6 src/kilim/analysis/MethodWeaver.java
  14. +6 −42 src/kilim/analysis/TypeDesc.java
  15. +2 −1  src/kilim/analysis/Value.java
  16. +7 −8 src/kilim/http/HttpSession.java
  17. +17 −0 src/kilim/mirrors/ClassMirror.java
  18. +14 −0 src/kilim/mirrors/ClassMirrorNotFoundException.java
  19. +7 −0 src/kilim/mirrors/FieldMirror.java
  20. +5 −0 src/kilim/mirrors/MemberMirror.java
  21. +14 −0 src/kilim/mirrors/MethodMirror.java
  22. +22 −0 src/kilim/mirrors/Mirrors.java
  23. +187 −0 src/kilim/mirrors/RuntimeClassMirrors.java
  24. +2 −0  src/kilim/nio/EndPoint.java
  25. +2 −1  src/kilim/tools/DumpClass.java
  26. +9 −7 src/kilim/tools/FlowAnalyzer.java
  27. +34 −8 src/kilim/tools/Weaver.java
  28. +6 −5 test/kilim/test/Base.java
  29. +2 −1  test/kilim/test/TestInvalidPausables.java
View
1  .#d.txt
View
32 examples/kilim/examples/HttpFileServer.java
@@ -50,6 +50,7 @@ public static void main(String[] args) throws IOException {
// create a listener on port 7262. An instance of HttpFileServer is created upon
// every new socket connection to this port.
new HttpServer(7262, HttpFileServer.class);
+ System.out.println("HttpFileServer listening on http://localhost:7262");
}
public static void usage() {
@@ -98,10 +99,15 @@ private File urlToPath(HttpRequest req) {
}
public boolean check(HttpResponse resp, File file) throws IOException, Pausable {
- if (!file.exists())
- problem(file, resp, HttpResponse.ST_NOT_FOUND, "File Not Found");
- else if (!file.canRead()) {
- problem(file, resp, HttpResponse.ST_FORBIDDEN, "Unable to read file");
+ byte[] status = HttpResponse.ST_OK;
+ String msg = "";
+
+ if (!file.exists()) {
+ status = HttpResponse.ST_NOT_FOUND;
+ msg = "File Not Found: " + file.getName();
+ } else if (!file.canRead()) {
+ status = HttpResponse.ST_FORBIDDEN;
+ msg = "Unable to read file " + file.getName();
} else {
try {
String path = file.getCanonicalPath();
@@ -109,14 +115,15 @@ else if (!file.canRead()) {
throw new SecurityException();
}
} catch (Exception e) {
- problem(file, resp, HttpResponse.ST_FORBIDDEN, "Error: " + e.getMessage());
+ status = HttpResponse.ST_FORBIDDEN;
+ msg = "Error retrieving " + file.getName() + ":<br>" + e.getMessage();
}
}
- if (resp.status == HttpResponse.ST_OK) {
- return true;
- } else {
- super.sendResponse(resp);
+ if (status != HttpResponse.ST_OK) {
+ problem(file, resp, status, msg);
return false;
+ } else {
+ return true;
}
}
@@ -154,7 +161,7 @@ public void sendDirectory(HttpResponse resp, File file, boolean headOnly) throws
p.print(relDir);
p.print("</title></head><body ");
p.print("><h2>Index of ");
- p.print(relDir);
+ p.print(relDir.equals(".") ? "/" : relDir);
p.print("</h2>");
String names[] = file.list();
if (names == null) {
@@ -171,7 +178,7 @@ public void sendDirectory(HttpResponse resp, File file, boolean headOnly) throws
p.print("</a><br>");
}
}
- p.print("</body>");
+ p.print("</body></html>");
p.flush();
super.sendResponse(resp);
}
@@ -186,7 +193,8 @@ private String getRelPath(File file) throws IOException {
if (!path.startsWith(baseDirectoryName)) {
throw new SecurityException();
}
- return path.substring(baseDirectoryName.length()); // include the "/"
+ path = path.substring(baseDirectoryName.length()); // include the "/"
+ return (path.length() == 0) ? "." : path;
}
public static HashMap<String, String> mimeTypes = new HashMap<String, String>();
View
15 src/kilim/Mailbox.java
@@ -77,8 +77,7 @@ public T get(EventSubscriber eo) {
int n = numMsgs;
if (n > 0) {
int ic = icons;
- msg = msgs[ic];
- msgs[ic] = null;
+ msg = msgs[ic]; msgs[ic]=null;
icons = (ic + 1) % msgs.length;
numMsgs = n - 1;
@@ -180,7 +179,7 @@ public T get() throws Pausable{
public T get(long timeoutMillis) throws Pausable {
final Task t = Task.getCurrentTask();
T msg = get(t);
- long begin = System.currentTimeMillis();
+ long end = System.currentTimeMillis() + timeoutMillis;
while (msg == null) {
TimerTask tt = new TimerTask() {
public void run() {
@@ -191,10 +190,14 @@ public void run() {
Task.timer.schedule(tt, timeoutMillis);
Task.pause(this);
tt.cancel();
- if (System.currentTimeMillis() - begin > timeoutMillis) {
+
+ msg = get(t);
+
+ timeoutMillis = end - System.currentTimeMillis();
+ if (timeoutMillis <= 0) {
+ removeMsgAvailableListener(t);
break;
}
- msg = get(t);
}
return msg;
}
@@ -235,7 +238,7 @@ public synchronized void removeSpaceAvailableListener(EventSubscriber spcSub) {
public synchronized void addMsgAvailableListener(EventSubscriber msgSub) {
- if (sink != null) {
+ if (sink != null && sink != msgSub) {
throw new AssertionError(
"Error: A mailbox can not be shared by two consumers. New = "
+ msgSub + ", Old = " + sink);
View
7 src/kilim/analysis/AsmDetector.java
@@ -16,7 +16,7 @@
public class AsmDetector {
static HashMap<String, ClassCache> classCacheMap= new HashMap<String, ClassCache>();
public static int getPausableStatus(String className, String methodName,
- String desc)
+ String desc, Detector detector)
{
try {
ClassCache classCache = classCacheMap.get(className);
@@ -30,7 +30,7 @@ public static int getPausableStatus(String className, String methodName,
if (status == Detector.METHOD_NOT_FOUND) {
// check super classes
for (String superName: classCache.superClasses) {
- status = Detector.getPausableStatus(superName, methodName, desc);
+ status = detector.getPausableStatus(superName, methodName, desc);
if (status != Detector.METHOD_NOT_FOUND)
break;
}
@@ -64,7 +64,7 @@ private static ClassCache cache(String className, ClassNode cn) {
return classCache;
}
public static void main(String[] args) {
- AsmDetector.getPausableStatus("com/sleepycat/je/Database", "putInternal", "Lcom/sleepycat/je/Transaction;Lcom/sleepycat/je/DatabaseEntry;Lcom/sleepycat/je/DatabaseEntry;Lcom/sleepycat/je/dbi/PutMode;Lkilim/Fiber;)Lcom/sleepycat/je/OperationStatus;)V");
+ AsmDetector.getPausableStatus("com/sleepycat/je/Database", "putInternal", "Lcom/sleepycat/je/Transaction;Lcom/sleepycat/je/DatabaseEntry;Lcom/sleepycat/je/DatabaseEntry;Lcom/sleepycat/je/dbi/PutMode;Lkilim/Fiber;)Lcom/sleepycat/je/OperationStatus;)V", Detector.DEFAULT);
}
static class ClassCache {
@@ -86,6 +86,7 @@ public int getPausableStatus(String methodName, String desc) {
return Detector.METHOD_NOT_FOUND;
}
}
+ @Override
public String toString() {
return className + "\nPausable Methods: " + pausableMethods + "\nOthers:" + otherMethods;
}
View
26 src/kilim/analysis/BasicBlock.java
@@ -4,8 +4,6 @@
* specified in the file "License"
*/
package kilim.analysis;
-import kilim.*;
-
import static kilim.Constants.D_ARRAY_BOOLEAN;
import static kilim.Constants.D_ARRAY_BYTE;
import static kilim.Constants.D_ARRAY_CHAR;
@@ -25,8 +23,8 @@
import static kilim.Constants.D_RETURN_ADDRESS;
import static kilim.Constants.D_SHORT;
import static kilim.Constants.D_VOID;
-import static kilim.Constants.THROWABLE_CLASS;
import static kilim.Constants.TASK_CLASS;
+import static kilim.Constants.THROWABLE_CLASS;
import static org.objectweb.asm.Opcodes.*;
import java.util.ArrayList;
@@ -37,6 +35,8 @@
import java.util.List;
import java.util.Stack;
+import kilim.KilimException;
+
import org.objectweb.asm.Label;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
@@ -220,6 +220,10 @@ public BasicBlock(MethodFlow aflow, Label aStartLabel) {
successors = new ArrayList<BasicBlock>(2);
}
+ Detector detector() {
+ return flow.detector();
+ }
+
/**
* Absorb as many instructions until the next label or the next transfer of
* control instruction. In the first pass we may end up creating many many
@@ -232,6 +236,7 @@ public BasicBlock(MethodFlow aflow, Label aStartLabel) {
* 3. A pausable method is treated like a labeled instruction, and is
* given a label if there isn't one already. Constraint 2 applies.
*/
+ @SuppressWarnings("unchecked")
int initialize(int pos) {
AbstractInsnNode ain;
startPos = pos;
@@ -318,7 +323,7 @@ int initialize(int pos) {
case TABLESWITCH:
case LOOKUPSWITCH:
Label defaultLabel;
- List otherLabels;
+ List<Label> otherLabels;
if (opcode == TABLESWITCH) {
defaultLabel = ((TableSwitchInsnNode) ain).dflt;
otherLabels = ((TableSwitchInsnNode) ain).labels;
@@ -326,7 +331,7 @@ int initialize(int pos) {
defaultLabel = ((LookupSwitchInsnNode) ain).dflt;
otherLabels = ((LookupSwitchInsnNode) ain).labels;
}
- for (Iterator it = otherLabels.iterator(); it.hasNext();) {
+ for (Iterator<Label> it = otherLabels.iterator(); it.hasNext();) {
l = (Label) it.next();
addSuccessor(flow.getOrCreateBasicBlock(l));
}
@@ -355,6 +360,9 @@ int initialize(int pos) {
break;
default:
+ if (opcode >= 26 && opcode <= 45)
+ throw new IllegalStateException("instruction variants not expected here");
+
break;
}
@@ -476,6 +484,7 @@ void interpret() {
frame.push(Value.make(startPos, D_RETURN_ADDRESS));
}
String componentType = null;
+ @SuppressWarnings("unused")
boolean canThrowException = false;
boolean propagateFrame = true;
int i = 0;
@@ -1078,16 +1087,16 @@ void interpret() {
}
}
-
+ /*
private boolean checkReceiverType(Value v, MethodInsnNode min) {
String t = v.getTypeDesc();
if (t == D_NULL) {
return true;
}
t = TypeDesc.getInternalName(t);
- return Detector.getPausableStatus(t, min.name, min.desc) != Detector.METHOD_NOT_FOUND;
+ return detector().getPausableStatus(t, min.name, min.desc) != Detector.METHOD_NOT_FOUND;
}
-
+ */
public boolean isCatchHandler() {
return caughtExceptionType != null;
}
@@ -1402,6 +1411,7 @@ BasicBlock getFollowingBlock() {
return flow.getBasicBlock(l);
}
+ @Override
public String toString() {
StringBuffer sb = new StringBuffer(200);
sb.append("\n========== BB #").append(id).append("[").append(System.identityHashCode(this)).append("]\n");
View
1  src/kilim/analysis/CallWeaver.java
@@ -297,7 +297,6 @@ int getNumBottom() {
*/
void genRewind(MethodVisitor mv) {
Frame f = bb.startFrame;
- Usage u = bb.usage;
// The last parameter to the method is fiber, but the original
// code doesn't know that and will use up that slot as it
View
168 src/kilim/analysis/ClassFlow.java
@@ -4,6 +4,7 @@
* specified in the file "License"
*/
package kilim.analysis;
+
import kilim.*;
import java.io.IOException;
@@ -12,38 +13,47 @@
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
/**
- * This class reads a .class file (or stream), wraps each method with a MethodFlow
- * object and optionally analyzes it.
+ * This class reads a .class file (or stream), wraps each method with a MethodFlow object and optionally analyzes it.
*
*/
public class ClassFlow extends ClassNode {
ArrayList<MethodFlow> methodFlows;
- ClassReader cr;
- String classDesc;
+ ClassReader cr;
+ String classDesc;
/**
- * true if any of the methods contained in the class file is pausable.
- * ClassWeaver uses it later to avoid weaving if isPausable isn't true.
+ * true if any of the methods contained in the class file is pausable. ClassWeaver uses it later to avoid weaving if
+ * isPausable isn't true.
*/
- private boolean isPausable;
+ private boolean isPausable;
/**
* true if the .class being read is already woven.
*/
- public boolean isWoven = false;
-
- public ClassFlow(InputStream is) throws IOException {
+ public boolean isWoven = false;
+ private Detector detector;
+
+ public ClassFlow(InputStream is, Detector detector) throws IOException {
cr = new ClassReader(is);
+ this.detector = detector;
}
-
- public ClassFlow(String aClassName) throws IOException {
+
+ public ClassFlow(String aClassName, Detector detector) throws IOException {
cr = new ClassReader(aClassName);
+ this.detector = detector;
}
-
- @SuppressWarnings({"unchecked"})
+
+ public ClassFlow(byte[] data, Detector detector) {
+ cr = new ClassReader(data);
+ this.detector = detector;
+ }
+
+ @Override
+ @SuppressWarnings( { "unchecked" })
public MethodVisitor visitMethod(
final int access,
final String name,
@@ -52,83 +62,103 @@ public MethodVisitor visitMethod(
final String[] exceptions)
{
MethodFlow mn = new MethodFlow( this, access, name, desc, signature,
- exceptions);
+ exceptions, detector);
super.methods.add(mn);
return mn;
}
-
- public ArrayList<MethodFlow> getMethodFlows(){
- assert (methodFlows != null): "ClassFlow.analyze not called";
+
+ public ArrayList<MethodFlow> getMethodFlows() {
+ assert (methodFlows != null) : "ClassFlow.analyze not called";
return methodFlows;
}
public ArrayList<MethodFlow> analyze(boolean forceAnalysis) throws KilimException {
-// cr.accept(this, ClassReader.SKIP_DEBUG);
- cr.accept(this, false);
- for (Object o: this.fields) {
- FieldNode fn = (FieldNode)o;
- if (fn.name.equals(Constants.WOVEN_FIELD)) {
- isWoven = true; break;
- }
- }
- if (isWoven && !forceAnalysis)
- return new ArrayList<MethodFlow>(); // This is a hack.
-
- cr = null; // We don't need this any more.
- classDesc = TypeDesc.getInterned("L" + name + ';');
- ArrayList<MethodFlow> flows = new ArrayList<MethodFlow>(methods.size());
- String msg = "";
- for (Object o: methods) {
- try {
- MethodFlow mf = (MethodFlow)o;
- if (mf.isBridge()) {
- MethodFlow mmf = getOrigWithSameSig(mf);
- if (mmf != null)
- mf.setPausable(mmf.isPausable());
+ // cr.accept(this, ClassReader.SKIP_DEBUG);
+
+ Detector save = Detector.setDetector(detector);
+ try {
+
+ cr.accept(this, false);
+ for (Object o : this.fields) {
+ FieldNode fn = (FieldNode) o;
+ if (fn.name.equals(Constants.WOVEN_FIELD)) {
+ isWoven = true;
+ break;
}
- mf.verifyPausables();
- if (mf.isPausable()) isPausable = true;
- if ((mf.isPausable() || forceAnalysis) && (!mf.isAbstract())) {
- mf.analyze();
+ }
+ if (isWoven && !forceAnalysis)
+ return new ArrayList<MethodFlow>(); // This is a hack.
+
+
+ cr = null; // We don't need this any more.
+ classDesc = TypeDesc.getInterned("L" + name + ';');
+ ArrayList<MethodFlow> flows = new ArrayList<MethodFlow>(methods.size());
+ String msg = "";
+ for (Object o : methods) {
+ try {
+ MethodFlow mf = (MethodFlow) o;
+ if (mf.isBridge()) {
+ MethodFlow mmf = getOrigWithSameSig(mf);
+ if (mmf != null)
+ mf.setPausable(mmf.isPausable());
+ }
+ mf.verifyPausables();
+ if (mf.isPausable())
+ isPausable = true;
+ if ((mf.isPausable() || forceAnalysis) && (!mf.isAbstract())) {
+ mf.analyze();
+ }
+ flows.add(mf);
+ } catch (KilimException ke) {
+ msg = msg + ke.getMessage() + "\n-------------------------------------------------\n";
}
- flows.add(mf);
- } catch (KilimException ke) {
- msg = msg + ke.getMessage() + "\n-------------------------------------------------\n";
}
+ if (msg.length() > 0) {
+ throw new KilimException(msg);
+ }
+ methodFlows = flows;
+ return flows;
+
+ } finally {
+ Detector.setDetector(save);
}
- if (msg.length() > 0) {
- throw new KilimException(msg);
- }
- methodFlows = flows;
- return flows;
}
-
+
private MethodFlow getOrigWithSameSig(MethodFlow bridgeMethod) {
- for (Object o:methods) {
- MethodFlow mf = (MethodFlow)o;
- if (mf == bridgeMethod) continue;
+ for (Object o : methods) {
+ MethodFlow mf = (MethodFlow) o;
+ if (mf == bridgeMethod)
+ continue;
if (mf.name.equals(bridgeMethod.name)) {
- String mfArgs = mf.desc.substring(0,mf.desc.indexOf(')'));
- String bmArgs = bridgeMethod.desc.substring(0,bridgeMethod.desc.indexOf(')'));
- if (mfArgs.equals(bmArgs)) return mf;
+ String mfArgs = mf.desc.substring(0, mf.desc.indexOf(')'));
+ String bmArgs = bridgeMethod.desc.substring(0, bridgeMethod.desc.indexOf(')'));
+ if (mfArgs.equals(bmArgs))
+ return mf;
}
}
return null;
-// throw new AssertionError("Bridge method found, but original method does not exist\nBridge method:" +
-// this.name + "::" + bridgeMethod.name + bridgeMethod.desc);
+ // throw new AssertionError("Bridge method found, but original method does not exist\nBridge method:" +
+ // this.name + "::" + bridgeMethod.name + bridgeMethod.desc);
+ }
+
+ public String getClassDescriptor() {
+ return classDesc;
+ }
+
+ public String getClassName() {
+ return super.name.replace('/', '.');
}
-
- public String getClassDescriptor() { return classDesc; }
-
- public String getClassName() { return super.name.replace('/', '.');}
public boolean isPausable() {
getMethodFlows(); // check analyze has been run.
return isPausable;
}
-
-
- boolean isInterface() {
- return (this.access & Constants.ACC_INTERFACE) != 0;
+
+ boolean isInterface() {
+ return (this.access & Opcodes.ACC_INTERFACE) != 0;
+ }
+
+ public Detector detector() {
+ return detector;
}
}
View
13 src/kilim/analysis/ClassWeaver.java
@@ -31,13 +31,18 @@
List<ClassInfo> classInfoList = new LinkedList<ClassInfo>();
static HashSet<String> stateClasses = new HashSet<String>();
- public ClassWeaver(InputStream is) throws IOException {
- classFlow = new ClassFlow(is);
+ public ClassWeaver(byte[] data, Detector detector) {
+ classFlow = new ClassFlow(data, detector);
weave();
}
- public ClassWeaver(String className) throws IOException {
- classFlow = new ClassFlow(className);
+ public ClassWeaver(InputStream is, Detector detector) throws IOException {
+ classFlow = new ClassFlow(is, detector);
+ weave();
+ }
+
+ public ClassWeaver(String className, Detector detector) throws IOException {
+ classFlow = new ClassFlow(className, detector);
weave();
}
View
137 src/kilim/analysis/Detector.java
@@ -4,13 +4,17 @@
* specified in the file "License"
*/
package kilim.analysis;
-import java.lang.reflect.Method;
+import static kilim.Constants.D_OBJECT;
+
+import java.util.ArrayList;
import kilim.Constants;
import kilim.NotPausable;
import kilim.Pausable;
-
-import org.objectweb.asm.Type;
+import kilim.mirrors.ClassMirror;
+import kilim.mirrors.ClassMirrorNotFoundException;
+import kilim.mirrors.MethodMirror;
+import kilim.mirrors.Mirrors;
/**
* Utility class to check if a method has been marked pausable
*
@@ -24,7 +28,22 @@
static final String[] STANDARD_DONT_CHECK_LIST = {
"java.", "javax." };
- public static boolean isPausable(String className, String methodName,
+ public static final Detector DEFAULT = new Detector(Mirrors.getRuntimeMirrors());
+
+ private final Mirrors mirrors;
+
+ public Detector(Mirrors mirrors) {
+ this.mirrors = mirrors;
+
+ NOT_PAUSABLE = mirrors.mirror(NotPausable.class);
+ PAUSABLE = mirrors.mirror(Pausable.class);
+ OBJECT = mirrors.mirror(Object.class);
+
+ }
+
+ ClassMirror NOT_PAUSABLE, PAUSABLE, OBJECT;
+
+ public boolean isPausable(String className, String methodName,
String desc) {
return getPausableStatus(className, methodName, desc) == PAUSABLE_METHOD_FOUND;
}
@@ -33,7 +52,7 @@ public static boolean isPausable(String className, String methodName,
* @return one of METHOD_NOT_FOUND, PAUSABLE_METHOD_FOUND, METHOD_NOT_PAUSABLE
*/
- public static int getPausableStatus(String className, String methodName,
+ public int getPausableStatus(String className, String methodName,
String desc)
{
int ret = METHOD_NOT_FOUND;
@@ -42,34 +61,34 @@ public static int getPausableStatus(String className, String methodName,
}
className = className.replace('/', '.');
try {
- Class cl = Class.forName(className);
- Method m = findMethod(cl, methodName, desc);
+ ClassMirror cl = mirrors.classForName(className);
+ MethodMirror m = findMethod(cl, methodName, desc);
if (m != null) {
- for (Class c: m.getExceptionTypes()) {
- if (NotPausable.class.isAssignableFrom(c)) {
+ for (ClassMirror c: m.getExceptionTypes()) {
+ if (NOT_PAUSABLE.isAssignableFrom(c)) {
return METHOD_NOT_PAUSABLE;
}
- if (Pausable.class.isAssignableFrom(c)) {
+ if (PAUSABLE.isAssignableFrom(c)) {
return PAUSABLE_METHOD_FOUND;
}
}
return METHOD_NOT_PAUSABLE;
}
- } catch (ClassNotFoundException ignore) {
+ } catch (ClassMirrorNotFoundException ignore) {
} catch (VerifyError ve) {
- return AsmDetector.getPausableStatus(className, methodName, desc);
+ return AsmDetector.getPausableStatus(className, methodName, desc, this);
}
return ret;
}
- public static Method findMethod(Class cl, String methodName, String desc) {
+ private MethodMirror findMethod(ClassMirror cl, String methodName, String desc) {
if (cl == null) return null;
- Method m = findMethodInHierarchy(cl, methodName, desc);
+ MethodMirror m = findMethodInHierarchy(cl, methodName, desc);
if (m == null) {
- cl = Object.class;
- for (Method om : cl.getDeclaredMethods()) {
- if (om.getName().equals(methodName) && Type.getMethodDescriptor(om).equals(desc)) {
+ cl = mirrors.mirror(Object.class);
+ for (MethodMirror om : cl.getDeclaredMethods()) {
+ if (om.getName().equals(methodName) && om.getMethodDescriptor().equals(desc)) {
return om;
}
}
@@ -77,24 +96,24 @@ public static Method findMethod(Class cl, String methodName, String desc) {
return m;
}
- public static Method findMethodInHierarchy(Class cl, String methodName,
+ private MethodMirror findMethodInHierarchy(ClassMirror cl, String methodName,
String desc) {
if (cl == null) return null;
- for (Method om : cl.getDeclaredMethods()) {
- if (om.getName().equals(methodName) && Type.getMethodDescriptor(om).equals(desc)) {
+ for (MethodMirror om : cl.getDeclaredMethods()) {
+ if (om.getName().equals(methodName) && om.getMethodDescriptor().equals(desc)) {
if (om.isBridge()) continue;
return om;
}
}
- if (cl == Object.class)
+ if (OBJECT.equals(cl))
return null;
- Method m = findMethodInHierarchy(cl.getSuperclass(), methodName, desc);
+ MethodMirror m = findMethodInHierarchy(cl.getSuperclass(), methodName, desc);
if (m != null)
return m;
- for (Class ifcl : cl.getInterfaces()) {
+ for (ClassMirror ifcl : cl.getInterfaces()) {
m = findMethodInHierarchy(ifcl, methodName, desc);
if (m != null)
return m;
@@ -103,6 +122,8 @@ public static Method findMethodInHierarchy(Class cl, String methodName,
}
public static String D_FIBER_ = Constants.D_FIBER + ")";
+
+ @SuppressWarnings("unused")
private static String statusToStr(int st) {
switch (st) {
case METHOD_NOT_FOUND : return "not found";
@@ -111,4 +132,74 @@ private static String statusToStr(int st) {
default: throw new AssertionError("Unknown status");
}
}
+
+
+ static private final ThreadLocal<Detector> DETECTOR = new ThreadLocal<Detector>();
+
+ static Detector getDetector() {
+ Detector d = DETECTOR.get();
+ if (d == null) return Detector.DEFAULT;
+ return d;
+}
+
+ static Detector setDetector(Detector d) {
+ Detector res = DETECTOR.get();
+ DETECTOR.set(d);
+ return res;
+ }
+
+ public String commonSuperType(String oa, String ob) throws ClassMirrorNotFoundException {
+ String a = toClassName(oa);
+ String b = toClassName(ob);
+
+ try {
+ ClassMirror ca = mirrors.classForName(a);
+ ClassMirror cb = mirrors.classForName(b);
+ if (ca.isAssignableFrom(cb)) return oa;
+ if (cb.isAssignableFrom(ca)) return ob;
+ if (ca.isInterface() && cb.isInterface()) {
+ return D_OBJECT; // This is what the java bytecode verifier does
+ }
+ } catch (ClassMirrorNotFoundException e) {
+ // try to see if the below works...
+ }
+
+ ArrayList<String> sca = getSuperClasses(a);
+ ArrayList<String> scb = getSuperClasses(b);
+ int lasta = sca.size()-1;
+ int lastb = scb.size()-1;
+ do {
+ if (sca.get(lasta).equals(scb.get(lastb))) {
+ lasta--;
+ lastb--;
+ } else {
+ break;
+ }
+ } while (lasta >= 0 && lastb >= 0);
+ return toDesc(sca.get(lasta+1));
+ }
+
+
+ public ArrayList<String> getSuperClasses(String cc) throws ClassMirrorNotFoundException {
+ ClassMirror c = mirrors.classForName(cc);
+ ArrayList<String> ret = new ArrayList<String>(3);
+ while (c != null) {
+ ret.add(c.getName());
+ c = c.getSuperclass();
+ }
+ return ret;
+
+ }
+
+ private static String toDesc(String name) {
+ return (name.equals(JAVA_LANG_OBJECT)) ?
+ D_OBJECT : "L" + name.replace('.', '/') + ';';
+ }
+
+ private static String toClassName(String s) {
+ return s.replace('/','.').substring(1,s.length()-1);
+ }
+
+ static String JAVA_LANG_OBJECT = "java.lang.Object";
+
}
View
4 src/kilim/analysis/FileLister.java
@@ -60,6 +60,7 @@ public FileLister(String dirOrJarName) throws IOException {
final File file;
DirEntry(File f) {file = f;}
+ @Override
public String getFileName() {
try {
return file.getCanonicalPath();
@@ -67,6 +68,7 @@ public String getFileName() {
return null;
}
+ @Override
public InputStream getInputStream() throws IOException {
return new BufferedInputStream(new FileInputStream(file));
}
@@ -119,10 +121,12 @@ public void remove() {
private final JarEntry jarEntry;
JEntry(JarEntry j) {jarEntry = j;}
+ @Override
public String getFileName() {
return jarEntry.getName();
}
+ @Override
public InputStream getInputStream() throws IOException {
return jarFile.getInputStream(jarEntry);
}
View
3  src/kilim/analysis/Frame.java
@@ -246,6 +246,7 @@ void clearStack() {
stacklen = 0;
}
+ @Override
public boolean equals(Object other) {
Frame that = (Frame)other;
for (int i = 0; i < locals.length; i++) {
@@ -257,6 +258,7 @@ public boolean equals(Object other) {
return true;
}
+ @Override
public int hashCode() {
int hash = 0;
for (int i = 0; i < this.locals.length;i++) hash ^= this.locals[i].hashCode();
@@ -264,6 +266,7 @@ public int hashCode() {
return hash;
}
+ @Override
public String toString() {
StringBuffer sb = new StringBuffer(100);
int numDefined = 0;
View
43 src/kilim/analysis/MethodFlow.java
@@ -5,13 +5,11 @@
*/
package kilim.analysis;
-import kilim.*;
-
+import static kilim.Constants.NOT_PAUSABLE_CLASS;
+import static kilim.Constants.PAUSABLE_CLASS;
import static kilim.analysis.BasicBlock.COALESCED;
import static kilim.analysis.BasicBlock.ENQUEUED;
import static kilim.analysis.BasicBlock.INLINE_CHECKED;
-import static kilim.Constants.PAUSABLE_CLASS;
-import static kilim.Constants.NOT_PAUSABLE_CLASS;
import static org.objectweb.asm.Opcodes.ACC_STATIC;
import static org.objectweb.asm.Opcodes.ACC_VOLATILE;
import static org.objectweb.asm.Opcodes.JSR;
@@ -24,10 +22,13 @@
import java.util.List;
import java.util.PriorityQueue;
+import kilim.KilimException;
+
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.LineNumberNode;
@@ -42,6 +43,7 @@
*/
public class MethodFlow extends MethodNode {
+
/**
* The classFlow to which this methodFlow belongs
*/
@@ -81,15 +83,19 @@
private List<MethodInsnNode> pausableMethods = new LinkedList<MethodInsnNode>();
+ private final Detector detector;
+
public MethodFlow(
ClassFlow classFlow,
final int access,
final String name,
final String desc,
final String signature,
- final String[] exceptions) {
+ final String[] exceptions,
+ final Detector detector) {
super(access, name, desc, signature, exceptions);
this.classFlow = classFlow;
+ this.detector = detector;
int numInstructions = instructions.size();
posToLabelMap = new ArrayList<Label>(numInstructions);
for (int i = numInstructions - 1 ; i >= 0; i--) {
@@ -149,7 +155,7 @@ public void verifyPausables() throws KilimException {
}
private void checkStatus(String superClassName, String methodName, String desc) throws KilimException {
- int status = Detector.getPausableStatus(superClassName, methodName, desc);
+ int status = detector.getPausableStatus(superClassName, methodName, desc);
if ((status == Detector.PAUSABLE_METHOD_FOUND && !hasPausableAnnotation)) {
throw new KilimException("Base class method is pausable, derived class is not: " +
"\nBase class = " + superClassName +
@@ -193,9 +199,9 @@ public void visitMethodInsn(int opcode, String owner, String name, String desc)
// method call sites. If the class is already woven, we don't need this
// functionality.
if (!classFlow.isWoven) {
- int methodStatus = Detector.getPausableStatus(owner, name, desc);
+ int methodStatus = detector.getPausableStatus(owner, name, desc);
if (methodStatus == Detector.METHOD_NOT_FOUND) {
- throw new KilimException("Check classpath. Method " + owner + name + desc + " could not be located");
+ throw new KilimException("Check classpath. Method " + owner + "." + name + desc + " could not be located");
} else if (methodStatus == Detector.PAUSABLE_METHOD_FOUND) {
MethodInsnNode min = (MethodInsnNode)instructions.get(instructions.size()-1);
pausableMethods.add(min);
@@ -245,6 +251,7 @@ boolean isPausableMethodInsn(MethodInsnNode min) {
return pausableMethods.contains(min);
}
+ @Override
public String toString() {
ArrayList<BasicBlock> ret = getBasicBlocks();
Collections.sort(ret);
@@ -255,15 +262,16 @@ public BBList getBasicBlocks() {
return basicBlocks;
}
+ @SuppressWarnings("unchecked")
private void assignCatchHandlers() {
- ArrayList tcbs = (ArrayList) tryCatchBlocks;
+ ArrayList<TryCatchBlockNode> tcbs = (ArrayList<TryCatchBlockNode>) tryCatchBlocks;
/// aargh. I'd love to create an array of Handler objects, but generics
// doesn't care for it.
if (tcbs.size() == 0) return;
ArrayList<Handler> handlers= new ArrayList<Handler>(tcbs.size());
for (int i = 0; i < tcbs.size(); i++) {
- TryCatchBlockNode tcb = (TryCatchBlockNode)tcbs.get(i);
+ TryCatchBlockNode tcb = tcbs.get(i);
handlers.add(new Handler(
getLabelPosition(tcb.start),
getLabelPosition(tcb.end) - 1, // end is inclusive
@@ -459,7 +467,7 @@ public void accept(final MethodVisitor mv) {
? 0
: visibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
- List l = visibleParameterAnnotations[i];
+ List<?> l = visibleParameterAnnotations[i];
if (l == null) {
continue;
}
@@ -472,7 +480,7 @@ public void accept(final MethodVisitor mv) {
? 0
: invisibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
- List l = invisibleParameterAnnotations[i];
+ List<?> l = invisibleParameterAnnotations[i];
if (l == null) {
continue;
}
@@ -542,9 +550,9 @@ public static void acceptAnnotation(final AnnotationVisitor av, final String nam
} else if (value instanceof AnnotationNode) {
AnnotationNode an = (AnnotationNode) value;
an.accept(av.visitAnnotation(name, an.desc));
- } else if (value instanceof List) {
+ } else if (value instanceof List<?>) {
AnnotationVisitor v = av.visitArray(name);
- List array = (List) value;
+ List<?> array = (List<?>) value;
for (int j = 0; j < array.size(); ++j) {
acceptAnnotation(v, null, array.get(j));
}
@@ -555,7 +563,7 @@ public static void acceptAnnotation(final AnnotationVisitor av, final String nam
}
public boolean isAbstract() {
- return ((this.access & Constants.ACC_ABSTRACT) != 0);
+ return ((this.access & Opcodes.ACC_ABSTRACT) != 0);
}
public boolean isStatic() {
return ((this.access & ACC_STATIC) != 0);
@@ -565,6 +573,11 @@ public boolean isBridge() {
return ((this.access & ACC_VOLATILE) != 0);
}
+ public Detector detector() {
+ return this.classFlow.detector();
+}
+
+
}
View
14 src/kilim/analysis/MethodWeaver.java
@@ -5,8 +5,6 @@
*/
package kilim.analysis;
-import kilim.*;
-
import static kilim.Constants.D_FIBER;
import static kilim.Constants.D_INT;
import static kilim.Constants.D_VOID;
@@ -26,6 +24,8 @@
import java.util.ArrayList;
import java.util.List;
+import kilim.Constants;
+
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
@@ -124,7 +124,7 @@ private void visitAttrs(MethodVisitor mv) {
n = mf.visibleParameterAnnotations == null ? 0
: mf.visibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
- List l = mf.visibleParameterAnnotations[i];
+ List<?> l = mf.visibleParameterAnnotations[i];
if (l == null) {
continue;
}
@@ -136,7 +136,7 @@ private void visitAttrs(MethodVisitor mv) {
n = mf.invisibleParameterAnnotations == null ? 0
: mf.invisibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
- List l = mf.invisibleParameterAnnotations[i];
+ List<?> l = mf.invisibleParameterAnnotations[i];
if (l == null) {
continue;
}
@@ -181,7 +181,7 @@ private void visitInstructions(MethodVisitor mv) {
for (BasicBlock bb : mf.getBasicBlocks()) {
int from = bb.startPos;
- if (bb.isPausable()) {
+ if (bb.isPausable() && bb.startFrame != null) {
genPausableMethod(mv, bb);
from = bb.startPos + 1; // first instruction is consumed
} else if (bb.isCatchHandler()) {
@@ -217,10 +217,12 @@ private void visitInstructions(MethodVisitor mv) {
if (cwList == null) {
cwList = new ArrayList<CallWeaver>(callWeavers.size());
}
+ if (!cwList.contains(cw)) {
cwList.add(cw);
}
}
}
+ }
return cwList;
}
@@ -281,7 +283,7 @@ void genGetCurrentTask(MethodVisitor mv, BasicBlock bb) {
private void createCallWeavers() {
MethodFlow mf = methodFlow;
for (BasicBlock bb : mf.getBasicBlocks()) {
- if (!bb.isPausable()) continue;
+ if (!bb.isPausable() || bb.startFrame==null) continue;
// No prelude needed for Task.getCurrentTask().
if (bb.isGetCurrentTask()) continue;
CallWeaver cw = new CallWeaver(this, bb);
View
48 src/kilim/analysis/TypeDesc.java
@@ -19,10 +19,10 @@
import static kilim.Constants.D_UNDEFINED;
import java.lang.reflect.Field;
-import java.util.ArrayList;
import java.util.HashMap;
import kilim.Constants;
+import kilim.mirrors.ClassMirrorNotFoundException;
import org.objectweb.asm.Type;
@@ -56,7 +56,7 @@ static boolean isDoubleWord(String desc) {
}
public static String getInterned(String desc) {
- String ret = (String)knownTypes.get(desc);
+ String ret = knownTypes.get(desc);
if (ret == null) {
switch (desc.charAt(0)) {
case 'L':
@@ -205,9 +205,6 @@ public static String mergeType(String a, String b) throws IncompatibleTypesExcep
throw new IncompatibleTypesException("" + a + "," + b);
}
- private static String toClassName(String s) {
- return s.replace('/','.').substring(1,s.length()-1);
- }
static String JAVA_LANG_OBJECT = "java.lang.Object";
// public for testing purposes
@@ -216,46 +213,13 @@ public static String commonSuperType(String oa, String ob) {
if (oa == D_OBJECT || ob == D_OBJECT) return D_OBJECT;
if (oa.equals(ob)) return oa;
- String a = toClassName(oa);
- String b = toClassName(ob);
- Class ca = Class.forName(a);
- Class cb = Class.forName(b);
- if (ca.isAssignableFrom(cb)) return oa;
- if (cb.isAssignableFrom(ca)) return ob;
- if (ca.isInterface() && cb.isInterface()) {
- return D_OBJECT; // This is what the java bytecode verifier does
- }
- ArrayList<String> sca = getSuperClasses(ca);
- ArrayList<String> scb = getSuperClasses(cb);
- int lasta = sca.size()-1;
- int lastb = scb.size()-1;
- do {
- if (sca.get(lasta).equals(scb.get(lastb))) {
- lasta--;
- lastb--;
- } else {
- break;
- }
- } while (lasta >= 0 && lastb >= 0);
- return toDesc(sca.get(lasta+1));
- } catch (ClassNotFoundException cnfe) {
- throw new InternalError(cnfe.getMessage());
- }
- }
+ String lub = Detector.getDetector().commonSuperType(oa, ob);
- private static ArrayList<String> getSuperClasses(Class c) {
- ArrayList<String> ret = new ArrayList<String>(3);
- while (c != null) {
- ret.add(c.getName());
- c = c.getSuperclass();
- }
- return ret;
+ return lub;
+ } catch (ClassMirrorNotFoundException cnfe) {
+ throw new InternalError(cnfe.getMessage());
}
-
- private static String toDesc(String name) {
- return (name.equals(JAVA_LANG_OBJECT)) ?
- D_OBJECT : "L" + name.replace('.', '/') + ';';
}
public static boolean isIntType(String typeDesc) {
View
3  src/kilim/analysis/Value.java
@@ -130,9 +130,9 @@ public boolean equals(Object obj) {
if (sites[i] != other.sites[i]) {
return false;
}
+ }
return true;
}
- }
return false;
}
@@ -161,6 +161,7 @@ public boolean isCategory1() {
return category() == 1;
}
+ @Override
public String toString() {
if (numSites == 0 && typeDesc == D_UNDEFINED) return "undef";
StringBuffer sb = new StringBuffer(40);
View
15 src/kilim/http/HttpSession.java
@@ -51,25 +51,24 @@ public void sendResponse(HttpResponse resp) throws IOException, Pausable {
resp.reuse();
}
- static byte[] pre = "<html><body><h1>".getBytes();
- static byte[] post = "</h1></body></html>".getBytes();
+ static byte[] pre = "<html><body><p>".getBytes();
+ static byte[] post = "</body></html>".getBytes();
/**
* Send an error page to the client.
*
- * @param resp
- * The response object.
- * @param statusCode
- * @param string
+ * @param resp The response object.
+ * @param statusCode See HttpResponse.ST*
+ * @param htmlMsg The body of the message that gives more detail.
* @throws IOException
* @throws Pausable
*/
- public void problem(HttpResponse resp, byte[] statusCode, String string) throws IOException, Pausable {
+ public void problem(HttpResponse resp, byte[] statusCode, String htmlMsg) throws IOException, Pausable {
resp.status = statusCode;
resp.setContentType("text/html");
OutputStream os = resp.getOutputStream();
os.write(pre);
- os.write(string.getBytes());
+ os.write(htmlMsg.getBytes());
os.write(post);
sendResponse(resp);
}
View
17 src/kilim/mirrors/ClassMirror.java
@@ -0,0 +1,17 @@
+package kilim.mirrors;
+
+public abstract class ClassMirror {
+
+ public abstract MethodMirror[] getDeclaredMethods();
+
+ public abstract boolean isAssignableFrom(ClassMirror c);
+
+ public abstract ClassMirror getSuperclass();
+
+ public abstract ClassMirror[] getInterfaces();
+
+ public abstract boolean isInterface();
+
+ public abstract String getName();
+
+}
View
14 src/kilim/mirrors/ClassMirrorNotFoundException.java
@@ -0,0 +1,14 @@
+package kilim.mirrors;
+
+public class ClassMirrorNotFoundException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5147833200948234264L;
+
+ public ClassMirrorNotFoundException(Throwable cause) {
+ super(cause);
+ }
+
+}
View
7 src/kilim/mirrors/FieldMirror.java
@@ -0,0 +1,7 @@
+package kilim.mirrors;
+
+public interface FieldMirror extends MemberMirror {
+
+ public ClassMirror getType();
+
+}
View
5 src/kilim/mirrors/MemberMirror.java
@@ -0,0 +1,5 @@
+package kilim.mirrors;
+
+public interface MemberMirror {
+ public abstract String getName();
+}
View
14 src/kilim/mirrors/MethodMirror.java
@@ -0,0 +1,14 @@
+package kilim.mirrors;
+
+
+
+public interface MethodMirror extends MemberMirror {
+
+ /** @see org.objectweb.asm.Type#getMethodDescriptor(java.lang.reflect.Method) */
+ public abstract String getMethodDescriptor();
+
+ public abstract ClassMirror[] getExceptionTypes() ;
+
+ public abstract boolean isBridge();
+
+}
View
22 src/kilim/mirrors/Mirrors.java
@@ -0,0 +1,22 @@
+package kilim.mirrors;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+
+public abstract class Mirrors {
+
+ abstract public ClassMirror classForName(String className)
+ throws ClassMirrorNotFoundException;
+
+ public abstract ClassMirror mirror(Class<?> clazz);
+ public abstract MethodMirror mirror(Method mth) ;
+ public abstract MemberMirror mirror(Member member) ;
+ public abstract FieldMirror mirror(Field member) ;
+
+ public static Mirrors getRuntimeMirrors() {
+ return new RuntimeClassMirrors();
+ }
+
+}
View
187 src/kilim/mirrors/RuntimeClassMirrors.java
@@ -0,0 +1,187 @@
+package kilim.mirrors;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+import org.objectweb.asm.Type;
+
+class RuntimeClassMirrors extends Mirrors {
+
+ static class RuntimeMemberMirror implements MemberMirror {
+
+ private final Member member;
+
+ public RuntimeMemberMirror(Member member) {
+ this.member = member;
+ }
+
+ public String getName() {
+ return member.getName();
+ }
+
+ }
+
+ static class RuntimeFieldMirror extends RuntimeMemberMirror implements FieldMirror {
+
+ final private Field field;
+
+ public RuntimeFieldMirror(Field field) {
+ super(field);
+ this.field = field;
+ }
+
+ public static FieldMirror forField(Field member) {
+ if (member == null) return null;
+ else return new RuntimeFieldMirror(member);
+ }
+
+ public ClassMirror getType() {
+ return RuntimeClassMirror.forClass(field.getType());
+ }
+ }
+
+ static class RuntimeMethodMirror extends RuntimeMemberMirror implements MethodMirror {
+
+ private final Method method;
+
+ public RuntimeMethodMirror(Method method) {
+ super(method);
+ this.method = method;
+ }
+
+ static MethodMirror forMethod(Method method) {
+ if (method==null) return null;
+ else return new RuntimeMethodMirror(method);
+ }
+
+ public static MethodMirror[] forMethods(Method[] declaredMethods) {
+ MethodMirror[] result = new MethodMirror[declaredMethods.length];
+ for (int i = 0; i < declaredMethods.length; i++) {
+ result[i] = RuntimeMethodMirror.forMethod(declaredMethods[i]);
+ }
+ return result;
+ }
+
+ public ClassMirror[] getExceptionTypes() {
+ return RuntimeClassMirror.forClasses(method.getExceptionTypes());
+ }
+
+ public String getMethodDescriptor() {
+ return Type.getMethodDescriptor(method);
+ }
+
+ public boolean isBridge() {
+ return method.isBridge();
+ }
+
+ }
+
+ static class RuntimeClassMirror extends ClassMirror {
+
+ private final Class<?> clazz;
+
+ public RuntimeClassMirror(Class<?> clazz) {
+ if (clazz == null) throw new NullPointerException();
+ this.clazz = clazz;
+ }
+
+ @Override
+ public String getName() {
+ return clazz.getName();
+ }
+
+ @Override
+ public boolean isInterface() {
+ return clazz.isInterface();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof RuntimeClassMirror) {
+ RuntimeClassMirror mirr = (RuntimeClassMirror) obj;
+
+ return mirr.clazz == clazz;
+ }
+
+ return false;
+ }
+
+ @Override
+ public MethodMirror[] getDeclaredMethods() {
+ return RuntimeMethodMirror.forMethods(clazz.getDeclaredMethods());
+ }
+
+ @Override
+ public ClassMirror[] getInterfaces() {
+ return forClasses(clazz.getInterfaces());
+ }
+
+ private static ClassMirror forClass(Class<?> clazz) {
+ if (clazz==null) return null;
+ return new RuntimeClassMirror(clazz);
+ }
+
+ private static ClassMirror[] forClasses(Class<?>[] classes) {
+ ClassMirror[] result = new ClassMirror[classes.length];
+ for (int i = 0; i < classes.length; i++) {
+ result[i] = RuntimeClassMirror.forClass(classes[i]);
+ }
+ return result;
+ }
+
+ @Override
+ public ClassMirror getSuperclass() {
+ return RuntimeClassMirror.forClass(clazz.getSuperclass());
+ }
+
+ @Override
+ public boolean isAssignableFrom(ClassMirror c) {
+ if (c instanceof RuntimeClassMirror) {
+ RuntimeClassMirror cc = (RuntimeClassMirror) c;
+ return clazz.isAssignableFrom(cc.clazz);
+ } else {
+ return false;
+ }
+ }
+
+ }
+
+ @Override
+ public ClassMirror classForName(String className)
+ throws ClassMirrorNotFoundException {
+ try {
+ return new RuntimeClassMirror(Class.forName(className));
+ } catch (ClassNotFoundException e) {
+ throw new ClassMirrorNotFoundException(e);
+ }
+ }
+
+ @Override
+ public ClassMirror mirror(Class<?> clazz) {
+ if (clazz == null) return null;
+ return new RuntimeClassMirror(clazz);
+ }
+
+ @Override
+ public MethodMirror mirror(Method mth) {
+ if (mth == null) return null;
+ return RuntimeMethodMirror.forMethod(mth);
+ }
+
+ @Override
+ public FieldMirror mirror(Field member) {
+ return RuntimeFieldMirror.forField(member);
+ }
+
+ @Override
+ public MemberMirror mirror(Member member) {
+ if (member instanceof Method) {
+ return mirror((Method)member);
+ } else if (member instanceof Field) {
+ return mirror((Field)member);
+ } else {
+ throw new RuntimeException("member is not field or method?");
+ }
+ }
+}
View
2  src/kilim/nio/EndPoint.java
@@ -87,6 +87,8 @@ public void write(ByteBuffer buf) throws IOException, Pausable {
remaining -= n;
}
}
+
+
/**
* Read into buffer buf and ensure that buf position > atLeastN before returning.
View
3  src/kilim/tools/DumpClass.java
@@ -17,6 +17,7 @@
import java.util.Enumeration;
import java.util.Formatter;
import java.util.HashMap;
+import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
@@ -47,7 +48,7 @@ public static void main(String[] args) throws IOException {
if (name.endsWith(".jar")) {
try {
- Enumeration e = new JarFile(name).entries();
+ Enumeration<JarEntry> e = new JarFile(name).entries();
while (e.hasMoreElements()) {
ZipEntry en = (ZipEntry) e.nextElement();
String n = en.getName();
View
16 src/kilim/tools/FlowAnalyzer.java
@@ -17,11 +17,13 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import kilim.analysis.BasicBlock;
import kilim.analysis.ClassFlow;
+import kilim.analysis.Detector;
import kilim.analysis.Frame;
import kilim.analysis.MethodFlow;
import kilim.analysis.TypeDesc;
@@ -43,18 +45,18 @@ public static void main(String[] args) throws Exception {
}
String name = args[0];
if (name.endsWith(".jar")) {
- analyzeJar(name);
+ analyzeJar(name, Detector.DEFAULT);
} else {
- analyzeClass(name);
+ analyzeClass(name, Detector.DEFAULT);
}
}
- private static void analyzeClass(String className) {
+ private static void analyzeClass(String className, Detector detector) {
try {
pn("-------------------------------------------------");
pn("Class: " + className);
System.out.flush();
- ArrayList<MethodFlow> flows = new ClassFlow(className).analyze(true);
+ ArrayList<MethodFlow> flows = new ClassFlow(className, detector).analyze(true);
for (MethodFlow flow: flows) {
reportFlow(flow, className);
}
@@ -168,15 +170,15 @@ private static int getNumArgs(MethodInsnNode m) {
return ret;
}
- public static void analyzeJar(String jarFile) {
+ public static void analyzeJar(String jarFile, Detector detector) {
try {
- Enumeration e = new JarFile(jarFile).entries();
+ Enumeration<JarEntry> e = new JarFile(jarFile).entries();
while (e.hasMoreElements()) {
ZipEntry en = (ZipEntry) e.nextElement();
String n = en.getName();
if (!n.endsWith(".class")) continue;
n = n.substring(0, n.length() - 6).replace('/','.');
- analyzeClass(n);
+ analyzeClass(n, detector);
}
} catch (Exception e) {
e.printStackTrace();
View
42 src/kilim/tools/Weaver.java
@@ -19,6 +19,7 @@
import kilim.KilimException;
import kilim.analysis.ClassInfo;
import kilim.analysis.ClassWeaver;
+import kilim.analysis.Detector;
import kilim.analysis.FileLister;
/**
@@ -34,6 +35,9 @@
public static void main(String[] args) throws IOException {
// System.out.println(System.getProperty("java.class.path"));
+
+ Detector detector = Detector.DEFAULT;
+
String currentName = null;
for (String name : parseArgs(args)) {
try {
@@ -42,7 +46,7 @@ public static void main(String[] args) throws IOException {
continue;
currentName = name;
weaveFile(name, new BufferedInputStream(
- new FileInputStream(name)));
+ new FileInputStream(name)), detector);
} else if (name.endsWith(".jar")) {
for (FileLister.Entry fe : new FileLister(name)) {
currentName = fe.getFileName();
@@ -51,7 +55,7 @@ public static void main(String[] args) throws IOException {
'.');
if (exclude(currentName))
continue;
- weaveFile(currentName, fe.getInputStream());
+ weaveFile(currentName, fe.getInputStream(), detector);
}
}
} else if (new File(name).isDirectory()) {
@@ -60,11 +64,11 @@ public static void main(String[] args) throws IOException {
if (currentName.endsWith(".class")) {
if (exclude(currentName))
continue;
- weaveFile(currentName, fe.getInputStream());
+ weaveFile(currentName, fe.getInputStream(), detector);
}
}
} else {
- weaveClass(name);
+ weaveClass(name, detector);
}
} catch (KilimException ke) {
System.err.println("Error weaving " + currentName + ". " + ke.getMessage());
@@ -87,31 +91,53 @@ private static boolean exclude(String name) {
.find();
}
- static void weaveFile(String name, InputStream is) throws IOException {
+ static void weaveFile(String name, InputStream is, Detector detector) throws IOException {
try {
- ClassWeaver cw = new ClassWeaver(is);
+ ClassWeaver cw = new ClassWeaver(is, detector);
writeClasses(cw);
} catch (KilimException ke) {
System.err.println("***** Error weaving " + name + ". " + ke.getMessage());
// ke.printStackTrace();
err = 1;
+ } catch (RuntimeException re) {
+ System.err.println("***** Error weaving " + name + ". " + re.getMessage());
+ re.printStackTrace();
+ err = 1;
+ } catch (IOException ioe) {
+ err = 1;
+ System.err.println("***** Unable to find/process '" + name + "'\n" + ioe.getMessage());
+ }
+ }
+
+ public static void weaveClass(String name, Detector detector) {
+ try {
+ ClassWeaver cw = new ClassWeaver(name, detector);
+ writeClasses(cw);
+ } catch (KilimException ke) {
+ err = 1;
+ System.err.println("***** Error weaving " + name + ". " + ke.getMessage());
+// ke.printStackTrace();
+
} catch (IOException ioe) {
err = 1;
System.err.println("***** Unable to find/process '" + name + "'\n" + ioe.getMessage());
}
}
- public static void weaveClass(String name) throws IOException {
+ public static void weaveClass2(String name, Detector detector) throws IOException {
try {
- ClassWeaver cw = new ClassWeaver(name);
+ ClassWeaver cw = new ClassWeaver(name, detector);
writeClasses(cw);
} catch (KilimException ke) {
err = 1;
System.err.println("***** Error weaving " + name + ". " + ke.getMessage());
// ke.printStackTrace();
+ throw ke;
+
} catch (IOException ioe) {
err = 1;
System.err.println("***** Unable to find/process '" + name + "'\n" + ioe.getMessage());
+ throw ioe;
}
}
View
11 test/kilim/test/Base.java
@@ -9,13 +9,14 @@
import java.util.ArrayList;
import java.util.List;
-import org.objectweb.asm.tree.AbstractInsnNode;
-import org.objectweb.asm.tree.MethodInsnNode;
-
+import junit.framework.TestCase;
import kilim.analysis.BasicBlock;
import kilim.analysis.ClassFlow;
+import kilim.analysis.Detector;
import kilim.analysis.MethodFlow;
-import junit.framework.TestCase;
+
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
public class Base extends TestCase {
private static ArrayList<MethodFlow> stflows;
@@ -23,7 +24,7 @@
protected void cache(String className) throws Exception {
if (lastClassName != className) {
- ClassFlow cf = new ClassFlow(className);
+ ClassFlow cf = new ClassFlow(className, Detector.DEFAULT);
stflows = cf.analyze(/* forceAnalysis = */true);
lastClassName = className;
}
View
3  test/kilim/test/TestInvalidPausables.java
@@ -8,12 +8,13 @@
import junit.framework.TestCase;
import kilim.KilimException;
+import kilim.analysis.Detector;
import kilim.tools.Weaver;
public class TestInvalidPausables extends TestCase {
private void ensureException(String className) {
try {
- Weaver.weaveClass(className);
+ Weaver.weaveClass2(className, Detector.DEFAULT);
fail("Expected weave exception while processing " + className);
} catch (KilimException ke) {
} catch (Exception e) {

1 comment on commit aa68747

@krestenkrab

Thanks for making this available.

It would have been nice though to be able to trace which edits are from http://github.com/krestenkrab/kilim, and which ones are from your own additions. Hopefully I'll soon have the time to make my kilim a clone of this; and integrate it into Erjang.

In the future; do you intend to drive development on GIT?

Please sign in to comment.
Something went wrong with that request. Please try again.