use of org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode in project kotlin by JetBrains.
the class FieldRemapper method foldFieldAccessChainIfNeeded.
@Nullable
private AbstractInsnNode foldFieldAccessChainIfNeeded(@NotNull List<AbstractInsnNode> capturedFieldAccess, int currentInstruction, @NotNull MethodNode node) {
boolean checkParent = !isRoot() && currentInstruction < capturedFieldAccess.size() - 1;
if (checkParent) {
AbstractInsnNode transformed = parent.foldFieldAccessChainIfNeeded(capturedFieldAccess, currentInstruction + 1, node);
if (transformed != null) {
return transformed;
}
}
FieldInsnNode insnNode = (FieldInsnNode) capturedFieldAccess.get(currentInstruction);
if (canProcess(insnNode.owner, insnNode.name, true)) {
insnNode.name = "$$$" + insnNode.name;
insnNode.setOpcode(Opcodes.GETSTATIC);
AbstractInsnNode next = capturedFieldAccess.get(0);
while (next != insnNode) {
AbstractInsnNode toDelete = next;
next = next.getNext();
node.instructions.remove(toDelete);
}
return capturedFieldAccess.get(capturedFieldAccess.size() - 1);
}
return null;
}
use of org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode in project kotlin by JetBrains.
the class LintDriver method isSuppressed.
// Unfortunately, ASMs nodes do not extend a common DOM node type with parent
// pointers, so we have to have multiple methods which pass in each type
// of node (class, method, field) to be checked.
/**
* Returns whether the given issue is suppressed in the given method.
*
* @param issue the issue to be checked, or null to just check for "all"
* @param classNode the class containing the issue
* @param method the method containing the issue
* @param instruction the instruction within the method, if any
* @return true if there is a suppress annotation covering the specific
* issue on this method
*/
public boolean isSuppressed(@Nullable Issue issue, @NonNull ClassNode classNode, @NonNull MethodNode method, @Nullable AbstractInsnNode instruction) {
if (method.invisibleAnnotations != null) {
@SuppressWarnings("unchecked") List<AnnotationNode> annotations = method.invisibleAnnotations;
return isSuppressed(issue, annotations);
}
// for members and <clinit> for static fields).
if (instruction != null && method.name.charAt(0) == '<') {
AbstractInsnNode next = LintUtils.getNextInstruction(instruction);
if (next != null && next.getType() == AbstractInsnNode.FIELD_INSN) {
FieldInsnNode fieldRef = (FieldInsnNode) next;
FieldNode field = findField(classNode, fieldRef.owner, fieldRef.name);
if (field != null && isSuppressed(issue, field)) {
return true;
}
} else if (classNode.outerClass != null && classNode.outerMethod == null && isAnonymousClass(classNode)) {
if (isSuppressed(issue, classNode)) {
return true;
}
}
}
return false;
}
use of org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode in project kotlin by JetBrains.
the class ControlFlowGraph method create.
/**
* Creates a new {@link ControlFlowGraph} and populates it with the flow
* control for the given method. If the optional {@code initial} parameter is
* provided with an existing graph, then the graph is simply populated, not
* created. This allows subclassing of the graph instance, if necessary.
*
* @param initial usually null, but can point to an existing instance of a
* {@link ControlFlowGraph} in which that graph is reused (but
* populated with new edges)
* @param classNode the class containing the method to be analyzed
* @param method the method to be analyzed
* @return a {@link ControlFlowGraph} with nodes for the control flow in the
* given method
* @throws AnalyzerException if the underlying bytecode library is unable to
* analyze the method bytecode
*/
@NonNull
public static ControlFlowGraph create(@Nullable ControlFlowGraph initial, @NonNull ClassNode classNode, @NonNull MethodNode method) throws AnalyzerException {
final ControlFlowGraph graph = initial != null ? initial : new ControlFlowGraph();
final InsnList instructions = method.instructions;
graph.mNodeMap = Maps.newHashMapWithExpectedSize(instructions.size());
graph.mMethod = method;
// Create a flow control graph using ASM5's analyzer. According to the ASM 4 guide
// (download.forge.objectweb.org/asm/asm4-guide.pdf) there are faster ways to construct
// it, but those require a lot more code.
Analyzer analyzer = new Analyzer(new BasicInterpreter()) {
@Override
protected void newControlFlowEdge(int insn, int successor) {
// Update the information as of whether the this object has been
// initialized at the given instruction.
AbstractInsnNode from = instructions.get(insn);
AbstractInsnNode to = instructions.get(successor);
graph.add(from, to);
}
@Override
protected boolean newControlFlowExceptionEdge(int insn, TryCatchBlockNode tcb) {
AbstractInsnNode from = instructions.get(insn);
graph.exception(from, tcb);
return super.newControlFlowExceptionEdge(insn, tcb);
}
@Override
protected boolean newControlFlowExceptionEdge(int insn, int successor) {
AbstractInsnNode from = instructions.get(insn);
AbstractInsnNode to = instructions.get(successor);
graph.exception(from, to);
return super.newControlFlowExceptionEdge(insn, successor);
}
};
analyzer.analyze(classNode.name, method);
return graph;
}
use of org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode in project kotlin by JetBrains.
the class ControlFlowGraph method dotDescribe.
private static String dotDescribe(Node node) {
AbstractInsnNode instruction = node.instruction;
if (instruction instanceof LabelNode) {
return "Label";
} else if (instruction instanceof LineNumberNode) {
LineNumberNode lineNode = (LineNumberNode) instruction;
return "Line " + lineNode.line;
} else if (instruction instanceof FrameNode) {
return "Stack Frame";
} else if (instruction instanceof MethodInsnNode) {
MethodInsnNode method = (MethodInsnNode) instruction;
String cls = method.owner.substring(method.owner.lastIndexOf('/') + 1);
cls = cls.replace('$', '.');
return "Call " + cls + "#" + method.name;
} else if (instruction instanceof FieldInsnNode) {
FieldInsnNode field = (FieldInsnNode) instruction;
String cls = field.owner.substring(field.owner.lastIndexOf('/') + 1);
cls = cls.replace('$', '.');
return "Field " + cls + "#" + field.name;
} else if (instruction instanceof TypeInsnNode && instruction.getOpcode() == Opcodes.NEW) {
return "New " + ((TypeInsnNode) instruction).desc;
}
StringBuilder sb = new StringBuilder();
String opcodeName = getOpcodeName(instruction.getOpcode());
sb.append(opcodeName);
if (instruction instanceof IntInsnNode) {
IntInsnNode in = (IntInsnNode) instruction;
sb.append(" ").append(Integer.toString(in.operand));
} else if (instruction instanceof LdcInsnNode) {
LdcInsnNode ldc = (LdcInsnNode) instruction;
sb.append(" ");
if (ldc.cst instanceof String) {
sb.append("\\\"");
}
sb.append(ldc.cst);
if (ldc.cst instanceof String) {
sb.append("\\\"");
}
}
return sb.toString();
}
use of org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode in project intellij-community by JetBrains.
the class NullableInterpreter method processState.
private void processState(State state) throws AnalyzerException {
Conf conf = state.conf;
int insnIndex = conf.insnIndex;
List<Conf> history = state.history;
boolean taken = state.taken;
Frame<BasicValue> frame = conf.frame;
AbstractInsnNode insnNode = methodNode.instructions.get(insnIndex);
List<Conf> nextHistory = dfsTree.loopEnters[insnIndex] ? append(history, conf) : history;
addComputed(insnIndex, state);
execute(frame, insnNode, taken);
if (subResult == NPE || top) {
earlyResult = NPE;
return;
}
if (subResult instanceof ConditionalNPE) {
myResult = combineNullable(myResult, subResult);
}
int opcode = insnNode.getOpcode();
switch(opcode) {
case ARETURN:
if (popValue(frame) instanceof ParamValue) {
earlyResult = NPE;
}
return;
case IRETURN:
case LRETURN:
case FRETURN:
case DRETURN:
case RETURN:
return;
default:
}
if (opcode == ATHROW) {
if (taken) {
earlyResult = NPE;
}
return;
}
if (opcode == IFNONNULL && popValue(frame) instanceof ParamValue) {
int nextInsnIndex = insnIndex + 1;
pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
return;
}
if (opcode == IFNULL && popValue(frame) instanceof ParamValue) {
int nextInsnIndex = methodNode.instructions.indexOf(((JumpInsnNode) insnNode).label);
pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
return;
}
if (opcode == IFEQ && popValue(frame) == InstanceOfCheckValue) {
int nextInsnIndex = methodNode.instructions.indexOf(((JumpInsnNode) insnNode).label);
pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
return;
}
if (opcode == IFNE && popValue(frame) == InstanceOfCheckValue) {
int nextInsnIndex = insnIndex + 1;
pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
return;
}
// general case
for (int nextInsnIndex : controlFlow.transitions[insnIndex]) {
Frame<BasicValue> nextFrame1 = nextFrame;
if (controlFlow.errors[nextInsnIndex] && controlFlow.errorTransitions.contains(new Edge(insnIndex, nextInsnIndex))) {
nextFrame1 = new Frame<>(frame);
nextFrame1.clearStack();
nextFrame1.push(ASMUtils.THROWABLE_VALUE);
}
pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame1), nextHistory, taken, false));
}
}
Aggregations