Allow the additional parameter for constructor wrappers occur at every place

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1253 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 25 years ago
parent 46f4102cec
commit 96ef935ccc
  1. 15
      jode/jode/expr/InvokeOperator.java
  2. 56
      jode/jode/jvm/SyntheticAnalyzer.java

@ -170,9 +170,9 @@ public final class InvokeOperator extends Operator
} catch (IOException ex) {
classInfo.guess(ClassInfo.OUTERCLASS);
}
checkAnonymousClasses();
}
}
checkAnonymousClasses();
}
public final boolean isStatic() {
@ -200,8 +200,7 @@ public final class InvokeOperator extends Operator
|| (Options.options & Options.OPTION_ANON) == 0)
return;
if (classInfo != null
&& classInfo.isMethodScoped()
&& classInfo.getClassName() == null)
&& classInfo.isMethodScoped())
methodAnalyzer.addAnonymousConstructor(this);
}
@ -581,6 +580,7 @@ public final class InvokeOperator extends Operator
if (getMethodAnalyzer() != null) {
SyntheticAnalyzer synth = getMethodAnalyzer().getSynthetic();
if (synth != null) {
int unifyParam = synth.getUnifyParam();
Expression op = null;
switch (synth.getKind()) {
case SyntheticAnalyzer.ACCESSGETFIELD:
@ -610,9 +610,9 @@ public final class InvokeOperator extends Operator
synth.getReference());
break;
case SyntheticAnalyzer.ACCESSCONSTRUCTOR:
if (subExpressions[1] instanceof ConstOperator
if (subExpressions[unifyParam] instanceof ConstOperator
&& ((ConstOperator)
subExpressions[1]).getValue() == null) {
subExpressions[unifyParam]).getValue() == null) {
op = new InvokeOperator(methodAnalyzer, CONSTRUCTOR,
synth.getReference());
}
@ -622,8 +622,9 @@ public final class InvokeOperator extends Operator
if (op != null) {
if (subExpressions != null) {
for (int i=subExpressions.length; i-- > 0; ) {
if (i == 1 && synth.getKind()
== SyntheticAnalyzer.ACCESSCONSTRUCTOR)
if (synth.getKind()
== SyntheticAnalyzer.ACCESSCONSTRUCTOR
&& i == unifyParam)
// skip the null param.
continue;
op = op.addOperand(subExpressions[i]);

@ -28,6 +28,7 @@ import jode.bytecode.Instruction;
import jode.bytecode.MethodInfo;
import jode.bytecode.Opcodes;
import jode.bytecode.Reference;
import jode.bytecode.TypeSignature;
import jode.type.Type;
import jode.type.MethodType;
@ -49,6 +50,8 @@ public class SyntheticAnalyzer implements Opcodes {
public final static int ACCESSCONSTRUCTOR = 8;
int kind = UNKNOWN;
int unifyParam;
Reference reference;
ClassInfo classInfo;
MethodInfo method;
@ -78,6 +81,14 @@ public class SyntheticAnalyzer implements Opcodes {
return reference;
}
/**
* Gets the index of the dummy parameter for an ACCESSCONSTRUCTOR.
* Normally the 1 but for inner classes it may be 2.
*/
public int getUnifyParam() {
return unifyParam;
}
private static final int[] getClassOpcodes = {
opc_aload, opc_invokestatic, opc_areturn,
opc_astore, opc_new, opc_dup, opc_aload,
@ -376,10 +387,11 @@ public class SyntheticAnalyzer implements Opcodes {
public boolean checkConstructorAccess() {
BasicBlocks bb = method.getBasicBlocks();
String[] paramTypes
= TypeSignature.getParameterTypes(method.getType());
Handler[] excHandlers = bb.getExceptionHandlers();
if (excHandlers != null && excHandlers.length != 0)
return false;
Block[] blocks = bb.getBlocks();
Block startBlock = bb.getStartBlock();
if (startBlock == null)
return false;
@ -389,19 +401,22 @@ public class SyntheticAnalyzer implements Opcodes {
Iterator iter = startBlock.getInstructions().iterator();
if (!iter.hasNext())
return false;
Instruction instr = (Instruction) iter.next();
if (instr.getOpcode() != opc_aload || instr.getLocalSlot() != 0)
return false;
if (!iter.hasNext())
return false;
instr = (Instruction) iter.next();
// slot begins with 2. Slot 1 contains a dummy value, that
// is used so that the constructor has a different type signature.
int params = 0, slot = 2;
unifyParam = -1;
Instruction instr = (Instruction) iter.next();
int params = 0, slot = 0;
while (instr.getOpcode() >= opc_iload
&& instr.getOpcode() <= opc_aload
&& instr.getLocalSlot() == slot) {
&& instr.getOpcode() <= opc_aload) {
if (instr.getLocalSlot() > slot
&& unifyParam == -1 && params > 0
&& paramTypes[params-1].charAt(0) == 'L') {
unifyParam = params;
params++;
slot++;
}
if (instr.getLocalSlot() != slot)
return false;
params++;
slot += (instr.getOpcode() == opc_lload
|| instr.getOpcode() == opc_dload) ? 2 : 1;
@ -409,6 +424,13 @@ public class SyntheticAnalyzer implements Opcodes {
return false;
instr = (Instruction) iter.next();
}
if (unifyParam == -1
&& params > 0 && params <= paramTypes.length
&& paramTypes[params-1].charAt(0) == 'L') {
unifyParam = params;
params++;
slot++;
}
if (instr.getOpcode() == opc_invokespecial) {
Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1);
@ -420,11 +442,15 @@ public class SyntheticAnalyzer implements Opcodes {
MethodType refType = Type.tMethod(ref.getType());
if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE
|| !refMethod.getName().equals("<init>")
|| refType.getParameterTypes().length != params)
return false;
|| unifyParam == -1
|| refType.getParameterTypes().length != params - 2)
return false;
if (iter.hasNext())
return false;
/* For valid bytecode the types matches automatically */
/* We don't check if types matches. No problem since we only
* need to make sure, this constructor doesn't do anything
* more than relay to the real one.
*/
reference = ref;
kind = ACCESSCONSTRUCTOR;
return true;

Loading…
Cancel
Save