/*
* This file is part of JOP, the Java Optimized Processor
* see <http://www.jopdesign.com/>
*
* Copyright (C) 2008, Wolfgang Puffitsch
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jopdesign.dfa.framework;
import com.jopdesign.common.AppInfo;
import com.jopdesign.common.MethodCode;
import com.jopdesign.common.MethodInfo;
import com.jopdesign.common.code.CallString;
import com.jopdesign.common.code.CallString.CallStringSerialization;
import com.jopdesign.common.misc.MethodNotFoundException;
import com.jopdesign.common.type.MemberID;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import java.io.Serializable;
public class FlowEdge {
public static final int NORMAL_EDGE = 0;
public static final int TRUE_EDGE = 1;
public static final int FALSE_EDGE = 2;
private final InstructionHandle tail;
private final InstructionHandle head;
private final int type;
private final Context context;
public FlowEdge(InstructionHandle tail, InstructionHandle head, int type) {
this(tail,head,type,null);
}
@SuppressWarnings({"AccessingNonPublicFieldOfAnotherObject"})
public FlowEdge(FlowEdge f, Context c) {
this(f.tail,f.head,f.type,c);
}
public FlowEdge(InstructionHandle tail, InstructionHandle head, int type, Context ctx) {
this.tail = tail;
this.head = head;
this.context = ctx;
this.type = type;
}
public InstructionHandle getHead() {
return head;
}
public InstructionHandle getTail() {
return tail;
}
public Context getContext() {
return context;
}
public int getType() {
return type;
}
public String toString() {
return tail.toString(false) + " -> " + head.toString(false);
}
@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((context == null) ? 0 : context.hashCode());
result = PRIME * result + ((head == null) ? 0 : head.getInstruction().hashCode());
result = PRIME * result + ((head == null) ? 0 : head.getPosition());
result = PRIME * result + ((tail == null) ? 0 : tail.getInstruction().hashCode());
result = PRIME * result + ((tail == null) ? 0 : tail.getPosition());
result = PRIME * result + type;
return result;
}
@SuppressWarnings({"AccessingNonPublicFieldOfAnotherObject"})
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final FlowEdge other = (FlowEdge) obj;
if (context == null) {
if (other.context != null)
return false;
} else if (!context.equals(other.context))
return false;
if (head == null) {
if (other.head != null)
return false;
} else if (!head.equals(other.head))
return false;
if (tail == null) {
if (other.tail != null)
return false;
} else if (!tail.equals(other.tail))
return false;
if (type != other.type)
return false;
return true;
}
public static class SerializedFlowEdge implements Serializable {
private static final long serialVersionUID = 2L;
private int type;
private String methodName;
private CallStringSerialization cs;
private int headIns;
private int tailIns;
public static boolean exists(FlowEdge e) {
MethodCode code = e.getContext().getMethodInfo().getCode();
InstructionList il = code.getInstructionList(true, false);
if (e.getHead().getPosition() == -1 || e.getHead().getPosition() == -1) return false;
if (il.findHandle(e.getHead().getPosition()) != e.getHead()) return false;
if (il.findHandle(e.getTail().getPosition()) != e.getTail()) return false;
return true;
}
public SerializedFlowEdge(FlowEdge e) {
this.type = e.type;
this.cs = new CallString.CallStringSerialization(e.getContext().callString);
this.methodName = e.getContext().getMethodInfo().getFQMethodName();
this.headIns = e.getHead().getPosition();
this.tailIns = e.getTail().getPosition();
}
public FlowEdge toFlowEdge(AppInfo appInfo) throws MethodNotFoundException {
MethodInfo method = appInfo.getMethodInfo(MemberID.parse(methodName));
InstructionList instructions = method.getCode().getInstructionList(false, false);
Context ctx = new Context();
ctx.setMethodInfo(method);
ctx.callString = cs.getCallString(appInfo);
return new FlowEdge(instructions.findHandle(tailIns),
instructions.findHandle(headIns), this.type, ctx);
}
}
}