git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@224 379699f6-c40d-0410-875b-85095c16579estable
parent
af4d434563
commit
a0cf5d2b52
@ -0,0 +1,65 @@ |
|||||||
|
/* |
||||||
|
* CheckNullOperator (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.decompiler; |
||||||
|
import jode.Type; |
||||||
|
|
||||||
|
/** |
||||||
|
* This is a pseudo operator, which represents the check against null |
||||||
|
* that jikes and javac generates for inner classes: |
||||||
|
* |
||||||
|
* <pre> |
||||||
|
* outer.new Inner() |
||||||
|
* </pre> |
||||||
|
* is translated by javac to |
||||||
|
* <pre> |
||||||
|
* new Outer$Inner(outer ((void) DUP.getClass())); |
||||||
|
* </pre> |
||||||
|
* and by jikes to |
||||||
|
* <pre> |
||||||
|
* new Outer$Inner(outer (DUP == null ? throw null)); |
||||||
|
* </pre> |
||||||
|
*/ |
||||||
|
|
||||||
|
public class CheckNullOperator extends SimpleOperator { |
||||||
|
|
||||||
|
public CheckNullOperator(Type type) { |
||||||
|
super(type, 0, 1); |
||||||
|
operandTypes[0] = type; |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 200; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOperandPriority(int i) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(String[] operands) { |
||||||
|
/* There is no way to produce exactly the same code. |
||||||
|
* This is a good approximation. |
||||||
|
* op.getClass will throw a null pointer exception if operands[0] |
||||||
|
* is null, otherwise return something not equal to null. |
||||||
|
* The bad thing is that this isn't atomar. |
||||||
|
*/ |
||||||
|
return "/*CHECK NULL*/ " + |
||||||
|
operands[0] + ".getClass() != null ? " + operands[0] + " : null"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,105 @@ |
|||||||
|
/* |
||||||
|
* CreateCheckNull (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.flow; |
||||||
|
import jode.decompiler.*; |
||||||
|
import jode.Type; |
||||||
|
|
||||||
|
public class CreateCheckNull { |
||||||
|
|
||||||
|
/* Situation: |
||||||
|
* |
||||||
|
* javac: |
||||||
|
* DUP |
||||||
|
* stack_0.getClass(); |
||||||
|
* |
||||||
|
* jikes: |
||||||
|
* DUP |
||||||
|
* if (!stack_0 != null) |
||||||
|
* throw null; |
||||||
|
*/ |
||||||
|
|
||||||
|
public static boolean transformJavac(InstructionContainer ic, |
||||||
|
StructuredBlock last) { |
||||||
|
if (!(last.outer instanceof SequentialBlock) |
||||||
|
|| !(ic.getInstruction() instanceof ComplexExpression) |
||||||
|
|| !(last.outer.getSubBlocks()[0] instanceof SpecialBlock)) |
||||||
|
return false; |
||||||
|
|
||||||
|
SpecialBlock dup = (SpecialBlock) last.outer.getSubBlocks()[0]; |
||||||
|
if (dup.type != SpecialBlock.DUP |
||||||
|
|| dup.count != 1 || dup.depth != 0) |
||||||
|
return false; |
||||||
|
|
||||||
|
ComplexExpression ce = (ComplexExpression) ic.getInstruction(); |
||||||
|
|
||||||
|
if (!(ce.getOperator() instanceof PopOperator) |
||||||
|
|| !(ce.getSubExpressions()[0] instanceof InvokeOperator)) |
||||||
|
return false; |
||||||
|
|
||||||
|
InvokeOperator getClassCall |
||||||
|
= (InvokeOperator) ce.getSubExpressions()[0]; |
||||||
|
if (!getClassCall.getMethodName().equals("getClass") |
||||||
|
|| !(getClassCall.getMethodType().toString() |
||||||
|
.equals("()Ljava/lang/Class;"))) |
||||||
|
return false; |
||||||
|
|
||||||
|
ic.setInstruction(new CheckNullOperator(Type.tUObject)); |
||||||
|
last.replace(last.outer); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean transformJikes(IfThenElseBlock ifBlock, |
||||||
|
StructuredBlock last) { |
||||||
|
if (!(last.outer instanceof SequentialBlock) |
||||||
|
|| !(last.outer.getSubBlocks()[0] instanceof SpecialBlock) |
||||||
|
|| ifBlock.elseBlock != null |
||||||
|
|| !(ifBlock.thenBlock instanceof ThrowBlock)) |
||||||
|
return false; |
||||||
|
System.err.println("last.outer: "+last.outer); |
||||||
|
|
||||||
|
SpecialBlock dup = (SpecialBlock) last.outer.getSubBlocks()[0]; |
||||||
|
if (dup.type != SpecialBlock.DUP |
||||||
|
|| dup.count != 1 || dup.depth != 0) |
||||||
|
return false; |
||||||
|
|
||||||
|
System.err.println("tick1"); |
||||||
|
/* negate the instruction back to its original state */ |
||||||
|
Expression expr = ifBlock.cond.negate(); |
||||||
|
System.err.println(expr); |
||||||
|
if (!(expr instanceof CompareUnaryOperator) |
||||||
|
|| expr.getOperator().getOperatorIndex() != Operator.NOTEQUALS_OP |
||||||
|
|| !(expr.getOperator().getOperandType(0).isOfType(Type.tUObject))) |
||||||
|
return false; |
||||||
|
|
||||||
|
System.err.println("tick2"); |
||||||
|
InstructionContainer ic = |
||||||
|
new InstructionBlock(new CheckNullOperator(Type.tUObject)); |
||||||
|
ifBlock.flowBlock.removeSuccessor(ifBlock.thenBlock.jump); |
||||||
|
ic.moveJump(ifBlock.jump); |
||||||
|
if (last == ifBlock) { |
||||||
|
ic.replace(last.outer); |
||||||
|
last = ic; |
||||||
|
} else { |
||||||
|
ic.replace(ifBlock); |
||||||
|
last.replace(last.outer); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package jode.test; |
||||||
|
|
||||||
|
public class ClassOpTest { |
||||||
|
static void test1() { |
||||||
|
Class c1 = ClassOpTest.class; |
||||||
|
Class c2 = Object.class; |
||||||
|
Class c3 = ClassOpTest.class; |
||||||
|
} |
||||||
|
|
||||||
|
void test2() { |
||||||
|
Class c2 = Object.class; |
||||||
|
Class c3 = ClassOpTest.class; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue