001: /* CreateCheckNull Copyright (C) 1999-2002 Jochen Hoenicke.
002: *
003: * This program is free software; you can redistribute it and/or modify
004: * it under the terms of the GNU Lesser General Public License as published by
005: * the Free Software Foundation; either version 2, or (at your option)
006: * any later version.
007: *
008: * This program is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: * GNU General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public License
014: * along with this program; see the file COPYING.LESSER. If not, write to
015: * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
016: *
017: * $Id: CreateCheckNull.java,v 1.11.4.1 2002/05/28 17:34:08 hoenicke Exp $
018: */
019:
020: package jode.flow;
021:
022: import jode.expr.*;
023: import jode.type.Type;
024: import jode.decompiler.LocalInfo;
025:
026: public class CreateCheckNull {
027:
028: /* Situation:
029: *
030: * javac:
031: * DUP
032: * POP.getClass();
033: *
034: * jikes:
035: * DUP
036: * if (POP == null)
037: * throw null;
038: */
039:
040: /**
041: * Transforms the code
042: * <pre>
043: * DUP
044: * POP.getClass()
045: * </pre>
046: * to a CheckNullOperator. This is what javac generates when it
047: * calls ".new" on an operand.
048: */
049: public static boolean transformJavac(InstructionContainer ic,
050: StructuredBlock last) {
051: if (!(last.outer instanceof SequentialBlock)
052: || !(ic.getInstruction() instanceof Operator)
053: || !(last.outer.getSubBlocks()[0] instanceof SpecialBlock))
054: return false;
055:
056: SpecialBlock dup = (SpecialBlock) last.outer.getSubBlocks()[0];
057: if (dup.type != SpecialBlock.DUP || dup.count != 1
058: || dup.depth != 0)
059: return false;
060:
061: Operator ce = (Operator) ic.getInstruction();
062:
063: if (!(ce.getOperator() instanceof PopOperator)
064: || !(ce.getSubExpressions()[0] instanceof InvokeOperator))
065: return false;
066:
067: InvokeOperator getClassCall = (InvokeOperator) ce
068: .getSubExpressions()[0];
069: if (!getClassCall.getMethodName().equals("getClass")
070: || !(getClassCall.getMethodType().toString()
071: .equals("()Ljava/lang/Class;")))
072: return false;
073:
074: LocalInfo li = new LocalInfo();
075: ic.setInstruction(new CheckNullOperator(Type.tUObject, li));
076: last.replace(last.outer);
077: return true;
078: }
079:
080: /**
081: * Transforms the code
082: * <pre>
083: * DUP
084: * if (POP == null) {
085: * throw null
086: * GOTO END_OF_METHOD // not checked
087: * }
088: * </pre>
089: * to a CheckNullOperator. This is what jikes generates when it
090: * calls ".new" on an operand.
091: */
092: public static boolean transformJikes(IfThenElseBlock ifBlock,
093: StructuredBlock last) {
094: if (!(last.outer instanceof SequentialBlock)
095: || !(last.outer.getSubBlocks()[0] instanceof SpecialBlock)
096: || ifBlock.elseBlock != null
097: || !(ifBlock.thenBlock instanceof ThrowBlock))
098: return false;
099:
100: SpecialBlock dup = (SpecialBlock) last.outer.getSubBlocks()[0];
101: if (dup.type != SpecialBlock.DUP || dup.count != 1
102: || dup.depth != 0)
103: return false;
104:
105: if (!(ifBlock.cond instanceof CompareUnaryOperator))
106: return false;
107: CompareUnaryOperator cmpOp = (CompareUnaryOperator) ifBlock.cond;
108: if (cmpOp.getOperatorIndex() != Operator.EQUALS_OP
109: || !(cmpOp.getCompareType().isOfType(Type.tUObject)))
110: return false;
111:
112: LocalInfo li = new LocalInfo();
113: InstructionContainer ic = new InstructionBlock(
114: new CheckNullOperator(Type.tUObject, li));
115: ifBlock.flowBlock.removeSuccessor(ifBlock.thenBlock.jump);
116: ic.moveJump(ifBlock.jump);
117: if (last == ifBlock) {
118: ic.replace(last.outer);
119: last = ic;
120: } else {
121: ic.replace(ifBlock);
122: last.replace(last.outer);
123: }
124: return true;
125: }
126: }
|