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

@ -28,6 +28,7 @@ import jode.bytecode.Instruction;
import jode.bytecode.MethodInfo; import jode.bytecode.MethodInfo;
import jode.bytecode.Opcodes; import jode.bytecode.Opcodes;
import jode.bytecode.Reference; import jode.bytecode.Reference;
import jode.bytecode.TypeSignature;
import jode.type.Type; import jode.type.Type;
import jode.type.MethodType; import jode.type.MethodType;
@ -49,6 +50,8 @@ public class SyntheticAnalyzer implements Opcodes {
public final static int ACCESSCONSTRUCTOR = 8; public final static int ACCESSCONSTRUCTOR = 8;
int kind = UNKNOWN; int kind = UNKNOWN;
int unifyParam;
Reference reference; Reference reference;
ClassInfo classInfo; ClassInfo classInfo;
MethodInfo method; MethodInfo method;
@ -78,6 +81,14 @@ public class SyntheticAnalyzer implements Opcodes {
return reference; 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 = { private static final int[] getClassOpcodes = {
opc_aload, opc_invokestatic, opc_areturn, opc_aload, opc_invokestatic, opc_areturn,
opc_astore, opc_new, opc_dup, opc_aload, opc_astore, opc_new, opc_dup, opc_aload,
@ -376,10 +387,11 @@ public class SyntheticAnalyzer implements Opcodes {
public boolean checkConstructorAccess() { public boolean checkConstructorAccess() {
BasicBlocks bb = method.getBasicBlocks(); BasicBlocks bb = method.getBasicBlocks();
String[] paramTypes
= TypeSignature.getParameterTypes(method.getType());
Handler[] excHandlers = bb.getExceptionHandlers(); Handler[] excHandlers = bb.getExceptionHandlers();
if (excHandlers != null && excHandlers.length != 0) if (excHandlers != null && excHandlers.length != 0)
return false; return false;
Block[] blocks = bb.getBlocks();
Block startBlock = bb.getStartBlock(); Block startBlock = bb.getStartBlock();
if (startBlock == null) if (startBlock == null)
return false; return false;
@ -389,19 +401,22 @@ public class SyntheticAnalyzer implements Opcodes {
Iterator iter = startBlock.getInstructions().iterator(); Iterator iter = startBlock.getInstructions().iterator();
if (!iter.hasNext()) if (!iter.hasNext())
return false; 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 unifyParam = -1;
// is used so that the constructor has a different type signature. Instruction instr = (Instruction) iter.next();
int params = 0, slot = 2; int params = 0, slot = 0;
while (instr.getOpcode() >= opc_iload while (instr.getOpcode() >= opc_iload
&& instr.getOpcode() <= opc_aload && instr.getOpcode() <= opc_aload) {
&& instr.getLocalSlot() == slot) { 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++; params++;
slot += (instr.getOpcode() == opc_lload slot += (instr.getOpcode() == opc_lload
|| instr.getOpcode() == opc_dload) ? 2 : 1; || instr.getOpcode() == opc_dload) ? 2 : 1;
@ -409,6 +424,13 @@ public class SyntheticAnalyzer implements Opcodes {
return false; return false;
instr = (Instruction) iter.next(); 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) { if (instr.getOpcode() == opc_invokespecial) {
Reference ref = instr.getReference(); Reference ref = instr.getReference();
String refClazz = ref.getClazz().substring(1); String refClazz = ref.getClazz().substring(1);
@ -420,11 +442,15 @@ public class SyntheticAnalyzer implements Opcodes {
MethodType refType = Type.tMethod(ref.getType()); MethodType refType = Type.tMethod(ref.getType());
if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE
|| !refMethod.getName().equals("<init>") || !refMethod.getName().equals("<init>")
|| refType.getParameterTypes().length != params) || unifyParam == -1
return false; || refType.getParameterTypes().length != params - 2)
return false;
if (iter.hasNext()) if (iter.hasNext())
return false; 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; reference = ref;
kind = ACCESSCONSTRUCTOR; kind = ACCESSCONSTRUCTOR;
return true; return true;

Loading…
Cancel
Save