Skip to content
This repository was archived by the owner on Feb 23, 2018. It is now read-only.

Commit 4bddf8b

Browse files
lrytzCarsten Varming
authored and
Carsten Varming
committed
[asm-cherry-pick] Multiple methods for initializing analysis values
Introduces a number of methods that are called when initializing or updating abstract values in an analyzer frame. Before this commit, Analyzer.analyze and Frame.execute would always call Interpreter.newValue for initializing or updating frame values. Having multiple methods allows users to return more precise values for the individual cases. For example, in a nullness analysis, the initial value for the `this` parameter of an instance method can be set to not-null.
1 parent 3dcfa7b commit 4bddf8b

File tree

3 files changed

+64
-9
lines changed

3 files changed

+64
-9
lines changed

src/main/java/scala/tools/asm/tree/analysis/Analyzer.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -158,21 +158,26 @@ public Frame<V>[] analyze(final String owner, final MethodNode m)
158158
// initializes the data structures for the control flow analysis
159159
Frame<V> current = newFrame(m.maxLocals, m.maxStack);
160160
Frame<V> handler = newFrame(m.maxLocals, m.maxStack);
161-
current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
161+
current.setReturn(interpreter.newReturnTypeValue(Type.getReturnType(m.desc)));
162162
Type[] args = Type.getArgumentTypes(m.desc);
163163
int local = 0;
164-
if ((m.access & ACC_STATIC) == 0) {
164+
boolean isInstanceMethod = (m.access & ACC_STATIC) == 0;
165+
if (isInstanceMethod) {
165166
Type ctype = Type.getObjectType(owner);
166-
current.setLocal(local++, interpreter.newValue(ctype));
167+
current.setLocal(local, interpreter.newParameterValue(isInstanceMethod, local, ctype));
168+
local++;
167169
}
168170
for (int i = 0; i < args.length; ++i) {
169-
current.setLocal(local++, interpreter.newValue(args[i]));
171+
current.setLocal(local, interpreter.newParameterValue(isInstanceMethod, local, args[i]));
172+
local++;
170173
if (args[i].getSize() == 2) {
171-
current.setLocal(local++, interpreter.newValue(null));
174+
current.setLocal(local, interpreter.newEmptyValueAfterSize2Local(local));
175+
local++;
172176
}
173177
}
174178
while (local < m.maxLocals) {
175-
current.setLocal(local++, interpreter.newValue(null));
179+
current.setLocal(local, interpreter.newEmptyNonParameterLocalValue(local));
180+
local++;
176181
}
177182
merge(0, current, null);
178183

@@ -285,7 +290,7 @@ public Frame<V>[] analyze(final String owner, final MethodNode m)
285290
if (newControlFlowExceptionEdge(insn, tcb)) {
286291
handler.init(f);
287292
handler.clearStack();
288-
handler.push(interpreter.newValue(type));
293+
handler.push(interpreter.newExceptionValue(tcb, handler, type));
289294
merge(jump, handler, subroutine);
290295
}
291296
}

src/main/java/scala/tools/asm/tree/analysis/Frame.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,12 +312,12 @@ public void execute(final AbstractInsnNode insn,
312312
var = ((VarInsnNode) insn).var;
313313
setLocal(var, value1);
314314
if (value1.getSize() == 2) {
315-
setLocal(var + 1, interpreter.newValue(null));
315+
setLocal(var + 1, interpreter.newEmptyValueAfterSize2Local(var + 1));
316316
}
317317
if (var > 0) {
318318
Value local = getLocal(var - 1);
319319
if (local != null && local.getSize() == 2) {
320-
setLocal(var - 1, interpreter.newValue(null));
320+
setLocal(var - 1, interpreter.newEmptyValueForPreviousSize2Local(var - 1));
321321
}
322322
}
323323
break;

src/main/java/scala/tools/asm/tree/analysis/Interpreter.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
import scala.tools.asm.Type;
3535
import scala.tools.asm.tree.AbstractInsnNode;
36+
import scala.tools.asm.tree.TryCatchBlockNode;
3637

3738
/**
3839
* A semantic bytecode interpreter. More precisely, this interpreter only
@@ -70,6 +71,55 @@ protected Interpreter(final int api) {
7071
*/
7172
public abstract V newValue(Type type);
7273

74+
/**
75+
* Called by the analyzer for initializing the return type value of a frame.
76+
*/
77+
public V newReturnTypeValue(Type type) {
78+
return newValue(type);
79+
}
80+
81+
/**
82+
* Called by the analyzer when initializing the value of a parameter in a frame.
83+
*/
84+
public V newParameterValue(boolean isInstanceMethod, int local, Type type) {
85+
return newValue(type);
86+
}
87+
88+
/**
89+
* Called by the analyzer when initializing a non-parameter local in a frame.
90+
* This method has to return a size-1 value representing an empty slot.
91+
*/
92+
public V newEmptyNonParameterLocalValue(int local) {
93+
return newValue(null);
94+
}
95+
96+
/**
97+
* Called by the analyzer and the interpreter. When initializing or setting the value of a
98+
* size-2 local, the value of the subsequent slot is reset using this method.
99+
* This method has to return a size-1 value representing an empty slot.
100+
*/
101+
public V newEmptyValueAfterSize2Local(int local) {
102+
return newValue(null);
103+
}
104+
105+
/**
106+
* Called by the interpreter. When setting the value of a local variable, the interpreter checks
107+
* whether the current value stored at the preceding index is of size-2. In this case, the
108+
* preceding size-2 value is no longer valid and reset using this method.
109+
* This method has to return a size-1 value representing an empty slot.
110+
*/
111+
public V newEmptyValueForPreviousSize2Local(int local) {
112+
return newValue(null);
113+
}
114+
115+
/**
116+
* Called by the analyzer when initializing the exception value on the call stack at the entry
117+
* of an exception handler.
118+
*/
119+
public V newExceptionValue(TryCatchBlockNode tryCatchBlockNode, Frame handlerFrame, Type exceptionType) {
120+
return newValue(exceptionType);
121+
}
122+
73123
/**
74124
* Interprets a bytecode instruction without arguments. This method is
75125
* called for the following opcodes:

0 commit comments

Comments
 (0)