Initial revision

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@224 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent af4d434563
commit a0cf5d2b52
  1. 65
      jode/jode/expr/CheckNullOperator.java
  2. 105
      jode/jode/flow/CreateCheckNull.java
  3. 14
      jode/test/ClassOpTest.java

@ -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…
Cancel
Save