⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 constantanalyzer.java

📁 Java Optimize and Decompile Environment 源代码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/* ConstantAnalyzer Copyright (C) 1999-2002 Jochen Hoenicke. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING.  If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: ConstantAnalyzer.java.in,v 1.3.2.6 2002/05/28 17:34:16 hoenicke Exp $ */package jode.obfuscator.modules;import jode.AssertError;import jode.GlobalOptions;import jode.bytecode.*;import jode.jvm.InterpreterException;import jode.obfuscator.*;import java.lang.reflect.Array;import java.lang.reflect.Modifier;import java.lang.reflect.InvocationTargetException;import java.util.BitSet;import java.util.Arrays;import java.util.Collection;import java.util.HashSet;import java.util.Set;import java.util.HashMap;import java.util.Map;import java.util.Iterator;import java.util.ListIterator;/** * Analyze the code, assuming every field that is not yet written to * is constant.  This may imply that some code is dead code. * * @author Jochen Hoenicke */public class ConstantAnalyzer extends SimpleAnalyzer 	implements Opcodes, CodeAnalyzer {    BytecodeInfo bytecode;    private static ConstantRuntimeEnvironment runtime	= new ConstantRuntimeEnvironment();    private final static int CMP_EQ = 0;    private final static int CMP_NE = 1;    private final static int CMP_LT = 2;    private final static int CMP_GE = 3;    private final static int CMP_GT = 4;    private final static int CMP_LE = 5;    private final static int CMP_GREATER_MASK	= (1 << CMP_GT)|(1 << CMP_GE)|(1 << CMP_NE);    private final static int CMP_LESS_MASK	= (1 << CMP_LT)|(1 << CMP_LE)|(1 << CMP_NE);    private final static int CMP_EQUAL_MASK	= (1 << CMP_GE)|(1 << CMP_LE)|(1 << CMP_EQ);    final static int CONSTANT      = 0x02;    final static int CONSTANTFLOW  = 0x04;    final static int RETASTORE     = 0x08;    final static int RETURNINGJSR  = 0x10;    private interface ConstantListener {	public void constantChanged();    }    private final static class JSRTargetInfo implements Cloneable {	Instruction jsrTarget;	BitSet usedLocals;	/**	 * The dependent entries, that want to know if the bit set changed.	 * This is either a StackLocalInfo (the ret info) or a single	 * JSRTargetInfo or a Collection of JSRTargetInfos.	 */	Object dependent;	public JSRTargetInfo(Instruction target) {	    jsrTarget = target;	    usedLocals = new BitSet();	}	public JSRTargetInfo copy() {	    try {		JSRTargetInfo result = (JSRTargetInfo) clone();		result.usedLocals = (BitSet) usedLocals.clone();		addDependent(result);		return result;	    } catch (CloneNotSupportedException ex) {		throw new IncompatibleClassChangeError(ex.getMessage());	    }	}	private void addDependent(JSRTargetInfo result) {	    if (dependent == null || dependent == result)		dependent = result;	    else if (dependent instanceof JSRTargetInfo) {		Set newDeps = new HashSet();		newDeps.add(dependent);		newDeps.add(result);	    } else if (dependent instanceof Collection) {		((Collection) dependent).add(result);	    }	}	public void setRetInfo(StackLocalInfo retInfo) {	    dependent = retInfo;	}	public boolean uses(int localSlot) {	    return usedLocals.get(localSlot);	}	public void addUsed(int localSlot) {	    if (usedLocals.get(localSlot))		return;	    usedLocals.set(localSlot);	    if (dependent instanceof StackLocalInfo)		((StackLocalInfo) dependent).enqueue();	    else if (dependent instanceof JSRTargetInfo)		((JSRTargetInfo) dependent).addUsed(localSlot);	    else if (dependent instanceof Collection) {		Iterator iter = ((Collection) dependent).iterator();		while (iter.hasNext()) {		    JSRTargetInfo dep = (JSRTargetInfo) iter.next();		    dep.addUsed(localSlot);		}	    }	}	public void merge(JSRTargetInfo o) {	    o.addDependent(this);	    for (int slot = 0; slot < o.usedLocals.size(); slot++) {		if (o.usedLocals.get(slot))		    addUsed(slot);	    }	}	public String toString() {	    StringBuffer sb = new StringBuffer(String.valueOf(jsrTarget));	    if (dependent instanceof StackLocalInfo)		sb.append("->").append(((StackLocalInfo) dependent).instr);	    return sb.append(usedLocals)		.append('_').append(hashCode()).toString();	}    }    private static class ConstValue implements ConstantListener {	public final static Object VOLATILE = new Object();	/**	 * The constant value, VOLATILE if value is not constant.	 * This may also be an instance of JSRTargetInfo	 */	Object value;	/**	 * The number of slots this value takes on the stack.	 */	int stackSize;	/**	 * The constant listeners, that want to be informed if this is	 * no longer constant.	 */	Set listeners;		public ConstValue(Object constant) {	    value = constant;	    stackSize = (constant instanceof Double			 || constant instanceof Long) ? 2 : 1;	    listeners = new HashSet();	}		public ConstValue(ConstValue constant) {	    value = constant.value;	    stackSize = constant.stackSize;	    listeners = new HashSet();	    constant.addConstantListener(this);	}		public ConstValue(int stackSize) {	    this.value = VOLATILE;	    this.stackSize = stackSize;	}		public ConstValue copy() {	    return (value == VOLATILE) ? this		: new ConstValue(this);	}		public void addConstantListener(ConstantListener l) {	    listeners.add(l);	}		public void removeConstantListener(ConstantListener l) {	    listeners.remove(l);	}		public void fireChanged() {	    value = VOLATILE;	    for (Iterator i = listeners.iterator(); i.hasNext(); )		((ConstantListener) i.next()).constantChanged();	    listeners = null;	}		public void constantChanged() {	    if (value != VOLATILE)		fireChanged();	}		/**	 * Merge the other value into this value.	 */	public void merge(ConstValue other) {	    if (this == other)		return;	    if (value == null ? other.value == null		: value.equals(other.value)) {		if (value != VOLATILE) { 		    other.addConstantListener(this);		    this.addConstantListener(other);		}		return;	    }	    if (value instanceof JSRTargetInfo		&& other.value instanceof JSRTargetInfo		&& (((JSRTargetInfo) value).jsrTarget		    == ((JSRTargetInfo) other.value).jsrTarget)) {		((JSRTargetInfo) value).merge((JSRTargetInfo) other.value);		return;	    }	    if (value != VOLATILE)		fireChanged();//  	    if (other.value != VOLATILE)//  		other.fireChanged();	}	public String toString() {	    return value == VOLATILE ? "vol("+stackSize+")" : ""+value;	}    }    private static class TodoQueue {	StackLocalInfo first;    }    private static class StackLocalInfo implements ConstantListener {	ConstValue[] stack;	ConstValue[] locals;	Instruction instr;	ConstantInfo constInfo;	StackLocalInfo retInfo;	StackLocalInfo nextOnQueue;	/**	 * The queue that should be notified, if the constant values of	 * this instruction changes.  We put ourself on this queue in that	 * case.	 */	TodoQueue notifyQueue;	public ConstValue copy(ConstValue value) {	    return (value == null) ? null : value.copy();	}	private StackLocalInfo(ConstValue[] stack, 			       ConstValue[] locals,			       TodoQueue notifyQueue) {	    this.stack = stack;	    this.locals = new ConstValue[locals.length];	    for (int i=0; i< locals.length; i++)		this.locals[i] = copy(locals[i]);	    this.notifyQueue = notifyQueue;	}    	public StackLocalInfo(int numLocals, 			      boolean isStatic, String methodTypeSig,			      TodoQueue notifyQueue) {	    	    String[] paramTypes 		= TypeSignature.getParameterTypes(methodTypeSig);	    locals = new ConstValue[numLocals];	    stack = new ConstValue[0];	    this.notifyQueue = notifyQueue;	    int slot = 0;	    if (!isStatic)		locals[slot++] = new ConstValue(1);	    for (int i=0; i< paramTypes.length; i++) {		int stackSize = TypeSignature.getTypeSize(paramTypes[i]);		locals[slot] = unknownValue[stackSize-1];		slot += stackSize;	    }	}	public final void enqueue() {	    if (nextOnQueue == null) {		this.nextOnQueue = notifyQueue.first;		notifyQueue.first = this;	    }	}    	public void constantChanged() {	    enqueue();	}    	public StackLocalInfo poppush(int pops, ConstValue push) {	    ConstValue[] newStack 		= new ConstValue[stack.length - pops + push.stackSize];	    ConstValue[] newLocals = (ConstValue[]) locals.clone();	    System.arraycopy(stack, 0, newStack, 0, stack.length-pops);	    newStack[stack.length-pops] = push.copy();	    return new StackLocalInfo(newStack, newLocals, notifyQueue);	}	public StackLocalInfo pop(int pops) {	    ConstValue[] newStack 		= new ConstValue[stack.length - pops];	    ConstValue[] newLocals = (ConstValue[]) locals.clone();	    System.arraycopy(stack, 0, newStack, 0, stack.length-pops);	    return new StackLocalInfo(newStack, newLocals, notifyQueue);	}	public StackLocalInfo dup(int count, int depth) {	    ConstValue[] newStack 		= new ConstValue[stack.length + count];	    ConstValue[] newLocals = (ConstValue[]) locals.clone();	    if (depth == 0)		System.arraycopy(stack, 0, newStack, 0, stack.length);	    else {		int pos = stack.length - count - depth;		System.arraycopy(stack, 0, newStack, 0, pos);		for (int i=0; i < count; i++)		    newStack[pos++] = copy(stack[stack.length-count + i]);		for (int i=0; i < depth; i++)		    newStack[pos++] = copy(stack[stack.length-count-depth + i]);	    }	    for (int i=0; i < count; i++)		newStack[stack.length+i] = copy(stack[stack.length-count + i]);	    return new StackLocalInfo(newStack, newLocals, notifyQueue);	}	public StackLocalInfo swap() {	    ConstValue[] newStack 		= new ConstValue[stack.length];	    ConstValue[] newLocals = (ConstValue[]) locals.clone();	    System.arraycopy(stack, 0, newStack, 0, stack.length - 2);	    newStack[stack.length-2] = stack[stack.length-1].copy();	    newStack[stack.length-1] = stack[stack.length-2].copy();	    return new StackLocalInfo(newStack, newLocals, notifyQueue);	}	public StackLocalInfo copy() {	    ConstValue[] newStack = (ConstValue[]) stack.clone();	    ConstValue[] newLocals = (ConstValue[]) locals.clone();	    return new StackLocalInfo(newStack, newLocals, notifyQueue);	}	public ConstValue getLocal(int slot) {	    return locals[slot];	}	public ConstValue getStack(int depth) {	    return stack[stack.length - depth];	}	public StackLocalInfo setLocal(int slot, ConstValue value) {	    locals[slot] = value;	    if (value != null && value.stackSize == 2)		locals[slot+1] = null;	    for (int i=0; i< locals.length; i++) {		if (locals[i] != null		    && locals[i].value instanceof JSRTargetInfo) {		    JSRTargetInfo jsrInfo = (JSRTargetInfo)locals[i].value;		    if (!jsrInfo.uses(slot)) {			jsrInfo = jsrInfo.copy();			locals[i] = locals[i].copy();			locals[i].value = jsrInfo;			jsrInfo.addUsed(slot);		    }		}	    }	    for (int i=0; i< stack.length; i++) {		if (stack[i] != null		    && stack[i].value instanceof JSRTargetInfo) {		    JSRTargetInfo jsrInfo = (JSRTargetInfo)stack[i].value;		    if (!jsrInfo.uses(slot)) {			jsrInfo = jsrInfo.copy();			stack[i] = stack[i].copy();			stack[i].value = jsrInfo;			jsrInfo.addUsed(slot);		    }		}	    }	    return this;	}	public StackLocalInfo mergeRetLocals(JSRTargetInfo jsrTargetInfo,					     StackLocalInfo retInfo) {	    for (int slot = 0; slot < locals.length; slot++) {		if (jsrTargetInfo.uses(slot))		    locals[slot] = retInfo.locals[slot];	    }	    locals[retInfo.instr.getLocalSlot()] = null;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -