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

📄 localoptimizer.java

📁 Java Optimize and Decompile Environment 源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
			}			InstrInfo retInfo = info.nextInfo.nextReads			    [info.instr.getLocalSlot()];			if (retInfo != null) {			    if (retInfo.instr.getOpcode() != opc_ret)				throw new AssertError				    ("reading return address");			    info.retInfo = retInfo;			    retInfo.jsrTargetInfo = info;			    /* Now promote reads from the instruction			     * after the jsr to the ret instruction if			     * they are modified by the subroutine,			     * and to the jsr instruction otherwise.  			     */			    Instruction nextInstr = predInstr.getNextByAddr();			    InstrInfo nextInfo 				= (InstrInfo) instrInfos.get(nextInstr);			    promoteReads(nextInfo, retInfo.instr,					 retInfo.usedBySub, false);			    promoteReads(nextInfo, predInstr, 					 retInfo.usedBySub, true);			}		    }		    promoteReads(info, instr.getPreds()[i]);		}	    }	    for (int i=0; i < handlers.length; i++) {		if (handlers[i].catcher == instr) {		    for (Instruction preInstr = handlers[i].start;			 preInstr != handlers[i].end.getNextByAddr(); 			 preInstr = preInstr.getNextByAddr()) {			promoteReads(info, preInstr);		    }		}	    }	}	changedInfos = null;	/* Now merge with the parameters	 * The params should be the locals in firstInfo.nextReads	 */	for (int i=0; i< paramLocals.length; i++) {	    if (firstInfo.nextReads[i] != null) {		firstInfo.nextReads[i].local.combineInto(paramLocals[i]);		paramLocals[i] = paramLocals[i].getReal();	    }	}    }    public void stripLocals() {	ListIterator iter = bc.getInstructions().listIterator(); 	for (InstrInfo info = firstInfo; info != null; info = info.nextInfo) {	    Instruction instr = (Instruction) iter.next();	    if (info.local != null && info.local.usingInstrs.size() == 1) {		/* If this is a store, whose value is never read; it can                 * be removed, i.e replaced by a pop. */		switch (instr.getOpcode()) {		case opc_istore:		case opc_fstore:		case opc_astore:		    iter.set(new Instruction(opc_pop));		    break;		case opc_lstore:		case opc_dstore:		    iter.set(new Instruction(opc_pop2));		    break;		default:		}	    }	}    }    void distributeLocals(Vector locals) {	if (locals.size() == 0)	    return;	/* Find the local with the least conflicts. */	int min = Integer.MAX_VALUE;	LocalInfo bestLocal = null;	Enumeration enum = locals.elements();	while (enum.hasMoreElements()) {	    LocalInfo li = (LocalInfo) enum.nextElement();	    int conflicts = 0;	    Enumeration conflenum = li.conflictingLocals.elements();	    while (conflenum.hasMoreElements()) {		if (((LocalInfo)conflenum.nextElement()).newSlot != -2)		    conflicts++;	    }	    if (conflicts < min) {		min = conflicts;		bestLocal = li;	    }	}	/* Mark the local as taken */	locals.removeElement(bestLocal);	bestLocal.newSlot = -2;	/* Now distribute the remaining locals recursively. */	distributeLocals(locals);	/* Finally find a new slot */    next_slot:	for (int slot = 0; ; slot++) {	    Enumeration conflenum = bestLocal.conflictingLocals.elements();	    while (conflenum.hasMoreElements()) {		LocalInfo conflLocal = (LocalInfo)conflenum.nextElement();		if (bestLocal.size == 2 && conflLocal.newSlot == slot+1) {		    slot++;		    continue next_slot;		}		if (conflLocal.size == 2 && conflLocal.newSlot+1 == slot)		    continue next_slot;		if (conflLocal.newSlot == slot) {		    if (conflLocal.size == 2)			slot++;		    continue next_slot;		}	    }	    bestLocal.newSlot = slot;	    break;	}    }        public void distributeLocals() {	/* give locals new slots.  This is a graph coloring 	 * algorithm (the optimal solution is NP complete, but this	 * should be a good approximation).	 */	/* first give the params the same slot as they had before.	 */	for (int i=0; i<paramLocals.length; i++)	    if (paramLocals[i] != null)		paramLocals[i].newSlot = i;	/* Now calculate the conflict settings.	 */	for (InstrInfo info = firstInfo; info != null; info = info.nextInfo) {	    if (info.instr.getOpcode() >= BytecodeInfo.opc_istore		&& info.instr.getOpcode() <= BytecodeInfo.opc_astore) {		/* This is a store.  It conflicts with every local, whose		 * value will be read without write.		 *		 * If this is inside a ret, it also conflicts with		 * locals, that are not used inside, and where any jsr		 * would conflict with.  		 */		for (int i=0; i < maxlocals; i++) {		    if (i != info.instr.getLocalSlot()			&& info.nextReads[i] != null)			info.local.conflictsWith(info.nextReads[i].local);		    if (info.nextInfo.nextReads[i] != null			&& info.nextInfo.nextReads[i].jsrTargetInfo != null) {			Instruction[] jsrs = info.nextInfo.nextReads[i]			    .jsrTargetInfo.instr.getPreds();			for (int j=0; j< jsrs.length; j++) {			    InstrInfo jsrInfo 				= (InstrInfo) instrInfos.get(jsrs[j]);			    for (int k=0; k < maxlocals; k++) {				if (!info.nextInfo.nextReads[i].usedBySub				    .get(k)				    && jsrInfo.nextReads[k] != null)				    info.local.conflictsWith					(jsrInfo.nextReads[k].local);			    }			}		    }		}	    }	}	/* Now put the locals that need a color into a vector.	 */	Vector locals = new Vector();	for (InstrInfo info = firstInfo; info != null; info = info.nextInfo) {	    if (info.local != null 		&& info.local.newSlot == -1		&& !locals.contains(info.local))		locals.addElement(info.local);	}	/* Now distribute slots recursive.	 */	distributeLocals(locals);	/* Update the instructions.	 */	for (InstrInfo info = firstInfo; info != null; info = info.nextInfo) {	    if (info.local != null)		info.instr.setLocalSlot(info.local.newSlot);	}	/* Update LocalVariableTable	 */	if (produceLVT)	    buildNewLVT();    }    private InstrInfo CONFLICT = new InstrInfo();    boolean promoteLifeLocals(LocalInfo[] newLife, InstrInfo nextInfo) {	if (nextInfo.lifeLocals == null) {	    nextInfo.lifeLocals = (LocalInfo[]) newLife.clone();	    return true;	}	boolean changed = false;	for (int i=0; i< maxlocals; i++) {	    LocalInfo local = nextInfo.lifeLocals[i];	    if (local == null)		/* A conflict has already happened, or this slot		 * may not have been initialized. */		continue;	    local = local.getReal();	    LocalInfo newLocal = newLife[i];	    if (newLocal != null)		newLocal = newLocal.getReal();	    if (local != newLocal) {		nextInfo.lifeLocals[i] = null;		changed = true;	    }	}	return changed;    }    public void buildNewLVT() {	/* First we recalculate the usedBySub, to use the new local numbers.	 */	for (InstrInfo info = firstInfo; info != null; info = info.nextInfo)	    if (info.usedBySub != null)		info.usedBySub = new BitSet();	for (InstrInfo info = firstInfo; info != null; info = info.nextInfo) {	    if (info.local != null) {		for (int i=0; i < info.nextReads.length; i++) {		    if (info.nextReads[i] != null 			&& info.nextReads[i].instr.getOpcode() == opc_ret)			info.nextReads[i].usedBySub.set(info.local.newSlot);		}	    }	}	/* Now we begin with the first Instruction and follow program flow.	 * We remember which locals are life in lifeLocals.	 */	firstInfo.lifeLocals = new LocalInfo[maxlocals];	for (int i=0; i < paramLocals.length; i++)	    firstInfo.lifeLocals[i] = paramLocals[i];	Stack changedInfo = new Stack();	changedInfo.push(firstInfo);	Handler[] handlers = bc.getExceptionHandlers();	while (!changedInfo.isEmpty()) {	    InstrInfo info = (InstrInfo) changedInfo.pop();	    Instruction instr = info.instr;	    LocalInfo[] newLife = info.lifeLocals;	    if (instr.hasLocalSlot()) {		int slot = instr.getLocalSlot();		LocalInfo instrLocal = info.local.getReal();		newLife = (LocalInfo[]) newLife.clone();		newLife[slot] = instrLocal;		if (instrLocal.name != null) {		    for (int j=0; j< newLife.length; j++) {			if (j != slot			    && newLife[j] != null			    && instrLocal.name.equals(newLife[j].name)) {			    /* This local changed the slot. */		 	   newLife[j] = null;			}		    }		}	    }	    	    if (!instr.doesAlwaysJump()) {		InstrInfo nextInfo = info.nextInfo;		if (promoteLifeLocals(newLife, nextInfo))		    changedInfo.push(nextInfo);	    } 	    if (instr.hasSuccs()) {		Instruction[] succs = instr.getSuccs();		for (int i = 0; i < succs.length; i++) {		    InstrInfo nextInfo			= (InstrInfo) instrInfos.get(succs[i]);		    if (promoteLifeLocals(newLife, nextInfo))			changedInfo.push(nextInfo);		}	    }	    for (int i=0; i < handlers.length; i++) {		if (handlers[i].start.compareTo(instr) <= 0		    && handlers[i].end.compareTo(instr) >= 0) {		    InstrInfo nextInfo			= (InstrInfo) instrInfos.get(handlers[i].catcher);		    if (promoteLifeLocals(newLife, nextInfo))			changedInfo.push(nextInfo);		}	    }	    if (info.instr.getOpcode() == opc_jsr) {		/* On a jsr we do a special merge */		Instruction jsrTargetInstr = info.instr.getSingleSucc();		InstrInfo jsrTargetInfo		    = (InstrInfo) instrInfos.get(jsrTargetInstr);		InstrInfo retInfo = jsrTargetInfo.retInfo;		if (retInfo != null && retInfo.lifeLocals != null) {		    LocalInfo[] retLife = (LocalInfo[]) newLife.clone();		    for (int i=0; i< maxlocals; i++) {			if (retInfo.usedBySub.get(i))			    retLife[i] = retInfo.lifeLocals[i];		    }		    if (promoteLifeLocals(retLife, info.nextInfo))			changedInfo.push(info.nextInfo);		}	    }	    if (info.jsrTargetInfo != null) {		/* On a ret we do a special merge */		Instruction jsrTargetInstr = info.jsrTargetInfo.instr;		for (int j=0; j< jsrTargetInstr.getPreds().length; j++) {		    InstrInfo jsrInfo			= (InstrInfo) instrInfos.get(jsrTargetInstr.getPreds()[j]);		    if (jsrInfo.lifeLocals == null)			/* life locals are not calculated, yet */			continue;		    LocalInfo[] retLife = (LocalInfo[]) newLife.clone();		    for (int i=0; i< maxlocals; i++) {			if (!info.usedBySub.get(i))			    retLife[i] = jsrInfo.lifeLocals[i];		    }		    if (promoteLifeLocals(retLife, jsrInfo.nextInfo))			changedInfo.push(jsrInfo.nextInfo);		}	    }	}	Vector lvtEntries = new Vector();	LocalVariableInfo[] lvi = new LocalVariableInfo[maxlocals];	LocalInfo[] currentLocal = new LocalInfo[maxlocals];	for (int i=0; i< paramLocals.length; i++) {	    if (paramLocals[i] != null) {		currentLocal[i] = paramLocals[i];		if (currentLocal[i].name != null) {		    lvi[i] = new LocalVariableInfo();		    lvtEntries.addElement(lvi[i]);		    lvi[i].name = currentLocal[i].name; /* XXX obfuscation? */		    lvi[i].type = Main.getClassBundle()			.getTypeAlias(currentLocal[i].type);		    lvi[i].start = (Instruction) bc.getInstructions().get(0);		    lvi[i].slot = i;		}	    }	}	Instruction lastInstr = null;	for (InstrInfo info = firstInfo; info != null; info = info.nextInfo) {	    for (int i=0; i< maxlocals; i++) {		LocalInfo lcl = info.lifeLocals != null ? info.lifeLocals[i]		    : null;		if (lcl != currentLocal[i]		    && (lcl == null || currentLocal[i] == null			|| lcl.name == null || lcl.type == null			|| !lcl.name.equals(currentLocal[i].name)			|| !lcl.type.equals(currentLocal[i].type))) {		    if (lvi[i] != null) {			lvi[i].end = info.instr.getPrevByAddr();		    }		    lvi[i] = null;		    currentLocal[i] = lcl;		    if (currentLocal[i] != null			&& currentLocal[i].name != null			&& currentLocal[i].type != null) {			lvi[i] = new LocalVariableInfo();			lvtEntries.addElement(lvi[i]);			lvi[i].name = currentLocal[i].name;			lvi[i].type = Main.getClassBundle()			    .getTypeAlias(currentLocal[i].type);			lvi[i].start = info.instr;			lvi[i].slot = i;		    }		}	    }	    lastInstr = info.instr;	}	for (int i=0; i< maxlocals; i++) {	    if (lvi[i] != null)		lvi[i].end = lastInstr;	}	LocalVariableInfo[] lvt = new LocalVariableInfo[lvtEntries.size()];	lvtEntries.copyInto(lvt);	bc.setLocalVariableTable(lvt);    }    public void dumpLocals() {	Vector locals = new Vector();	for (InstrInfo info = firstInfo; info != null; info = info.nextInfo) {	    GlobalOptions.err.println(info.instr.getDescription());	    GlobalOptions.err.print("nextReads: ");	    for (int i=0; i<maxlocals; i++)		if (info.nextReads[i] == null)		    GlobalOptions.err.print("-,");		else		    GlobalOptions.err.print(info.nextReads[i].instr.getAddr()+",");	    if (info.usedBySub != null)		GlobalOptions.err.print("  usedBySub: "+info.usedBySub);	    if (info.retInfo != null)		GlobalOptions.err.print("  ret info: "					+info.retInfo.instr.getAddr());	    if (info.jsrTargetInfo != null)		GlobalOptions.err.print("  jsr info: "					+info.jsrTargetInfo.instr.getAddr());	    GlobalOptions.err.println();	    if (info.local != null && !locals.contains(info.local))		locals.addElement(info.local);	}	Enumeration enum = locals.elements();	while (enum.hasMoreElements()) {	    LocalInfo li = (LocalInfo) enum.nextElement();	    int slot = ((InstrInfo)li.usingInstrs.elementAt(0))		.instr.getLocalSlot();	    GlobalOptions.err.print("Slot: "+slot+" conflicts:");	    Enumeration enum1 = li.conflictingLocals.elements();	    while (enum1.hasMoreElements()) {		LocalInfo cfl = (LocalInfo)enum1.nextElement();		GlobalOptions.err.print(cfl.getFirstAddr()+", ");	    }	    GlobalOptions.err.println();	    GlobalOptions.err.print(li.getFirstAddr());	    GlobalOptions.err.print("     instrs: ");	    Enumeration enum2 = li.usingInstrs.elements();	    while (enum2.hasMoreElements())		GlobalOptions.err.print(((InstrInfo)enum2.nextElement())					.instr.getAddr()+", ");	    GlobalOptions.err.println();	}	GlobalOptions.err.println("-----------");    }    public void transformCode(BytecodeInfo bytecode) {	this.bc = bytecode;	calcLocalInfo();	if ((GlobalOptions.debuggingFlags 	     & GlobalOptions.DEBUG_LOCALS) != 0) {	    GlobalOptions.err.println("Before Local Optimization: ");	    dumpLocals();	}	stripLocals();	distributeLocals();		if ((GlobalOptions.debuggingFlags 	     & GlobalOptions.DEBUG_LOCALS) != 0) {	    GlobalOptions.err.println("After Local Optimization: ");	    dumpLocals();	}	firstInfo = null;	changedInfos = null;	instrInfos = null;	paramLocals = null;    }}

⌨️ 快捷键说明

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