0001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
0002:
0003: This file is part of the db4o open source object database.
0004:
0005: db4o is free software; you can redistribute it and/or modify it under
0006: the terms of version 2 of the GNU General Public License as published
0007: by the Free Software Foundation and as clarified by db4objects' GPL
0008: interpretation policy, available at
0009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
0010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
0011: Suite 350, San Mateo, CA 94403, USA.
0012:
0013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
0014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0016: for more details.
0017:
0018: You should have received a copy of the GNU General Public License along
0019: with this program; if not, write to the Free Software Foundation, Inc.,
0020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
0021: package EDU.purdue.cs.bloat.editor;
0022:
0023: import java.util.*;
0024:
0025: import EDU.purdue.cs.bloat.reflect.*;
0026: import EDU.purdue.cs.bloat.util.*;
0027:
0028: /**
0029: * CodeArray converts an array of Instructions into an array of bytes suitable
0030: * for saving to a <tt>MethodInfo</tt> with <tt>setCode</tt>.
0031: *
0032: * <p>
0033: *
0034: * The byte array is returned by calling the <tt>array</tt> method.
0035: *
0036: * <p>
0037: *
0038: * This code assumes no branch will be longer than 65536 bytes.
0039: *
0040: * @see Instruction
0041: * @see MethodInfo
0042: * @see MethodInfo#setCode
0043: *
0044: * @author Nate Nystrom (<a
0045: * href="mailto:nystrom@cs.purdue.edu">nystrom@cs.purdue.edu</a>)
0046: */
0047: public class CodeArray implements InstructionVisitor, Opcode {
0048: public static boolean DEBUG = Boolean.getBoolean("CodeArray.DEBUG");
0049:
0050: private ByteCell codeTail; // Linked list of ByteCells representing code
0051:
0052: private int codeLength; // Number of bytes in method
0053:
0054: private Map branches;
0055:
0056: private Map longBranches;
0057:
0058: private Map branchInsts;
0059:
0060: private Map labels; // Labels mapped to their offsets
0061:
0062: private int lastInst; // Offset of last (most recent) instrucion
0063:
0064: private int maxStack; // Max stack height
0065:
0066: private int stackHeight; // Current stack height
0067:
0068: private int maxLocals; // Max number of local variables
0069:
0070: private ConstantPool constants;
0071:
0072: private MethodEditor method;
0073:
0074: private boolean longBranch; // Do we use long (wide) jumps?
0075:
0076: private List insts;
0077:
0078: /**
0079: * Create the byte array for a method.
0080: *
0081: * @param method
0082: * The method being edited.
0083: * @param constants
0084: * The constant pool of the class.
0085: * @param insts
0086: * A List of Instructions and Labels to convert to a byte array.
0087: * @see MethodEditor
0088: * @see ConstantPool
0089: * @see Instruction
0090: * @see Label
0091: */
0092: public CodeArray(final MethodEditor method,
0093: final ConstantPool constants, final List insts) {
0094: this .constants = constants;
0095: this .method = method;
0096: this .insts = insts;
0097: this .maxStack = 0;
0098: this .maxLocals = 0;
0099:
0100: longBranch = false;
0101: buildCode();
0102: }
0103:
0104: /**
0105: * Examine the method's Labels and Instructions. Keep track of such things
0106: * as the height of the stack at each instruction and to where subroutines
0107: * return. The ultimate goal is to compute the max stack height of this
0108: * method. This computation is complicated by subroutines that may be
0109: * invoked at a variety of stack heights.
0110: */
0111: private void buildCode() {
0112: codeTail = null;
0113: codeLength = 0;
0114: branches = new HashMap();
0115: longBranches = new HashMap();
0116: branchInsts = new HashMap();
0117: labels = new HashMap();
0118:
0119: // We need at least enought locals to store the parameters
0120: maxLocals = method.type().stackHeight();
0121:
0122: if (!method.isStatic()) {
0123: // One more for the this pointer
0124: maxLocals++;
0125: }
0126:
0127: stackHeight = 0;
0128:
0129: final Map labelPos = new HashMap(); // Maps Labels to their code offsets
0130: final int[] heights = new int[insts.size()]; // Stack height at each
0131: // inst
0132:
0133: // Maps Labels that begin jsrs to their return targets. Maps ret
0134: // instructions to the subroutine from which they return.
0135: final Map retTargets = new HashMap();
0136: final Map retInsts = new HashMap();
0137:
0138: // Print the code we're dealing with
0139: if (CodeArray.DEBUG) {
0140: System.out.println("Building code for "
0141: + method.declaringClass().name() + "."
0142: + method.name());
0143: final Iterator iter = insts.iterator();
0144: while (iter.hasNext()) {
0145: final Object o = iter.next();
0146: System.out.println(" " + o);
0147: }
0148: }
0149:
0150: // Build the bytecode array, assuming each basic block begins with
0151: // stack height 0. We'll fix up the heights later.
0152: final Iterator iter = insts.iterator();
0153: int i = 0; // Which instruction are we at?
0154: while (iter.hasNext()) {
0155: final Object ce = iter.next();
0156:
0157: if (ce instanceof Label) {
0158: final Label label = (Label) ce;
0159:
0160: // A Label starts a new basic block. Reset the stack height.
0161:
0162: stackHeight = 0;
0163: labelPos.put(label, new Integer(i));
0164:
0165: addLabel(label);
0166: heights[i++] = stackHeight;
0167:
0168: // If this label starts a subroutine (i.e. is the target of
0169: // jsr instruction), then make not of it.
0170: if (retTargets.containsKey(label)) {
0171: }
0172:
0173: } else if (ce instanceof Instruction) {
0174: final Instruction inst = (Instruction) ce;
0175:
0176: // Visit this instruction to compute the current stack height
0177: inst.visit(this );
0178:
0179: if (inst.isJsr()) {
0180: // Make sure that the jsr is not the last instruction in the
0181: // method. If it was, where would we return to? Make note
0182: // of the return target (the Label following the jsr).
0183:
0184: heights[i++] = stackHeight;
0185:
0186: Assert.isTrue(iter.hasNext(), inst
0187: + " found at end of method");
0188:
0189: final Object x = iter.next();
0190:
0191: Assert.isTrue(x instanceof Label, inst
0192: + " not followed by label");
0193:
0194: final Label sub = (Label) inst.operand();
0195: final Label target = (Label) x;
0196:
0197: // Maintain a mapping between a subroutine (the Label that
0198: // begins it) and all return targets.
0199: Set targets = (Set) retTargets.get(sub);
0200: if (targets == null) {
0201: targets = new HashSet();
0202: retTargets.put(sub, targets);
0203: }
0204: targets.add(target);
0205:
0206: stackHeight = 0;
0207: labelPos.put(target, new Integer(i));
0208:
0209: addLabel(target);
0210: heights[i++] = stackHeight;
0211:
0212: } else {
0213: heights[i++] = stackHeight;
0214: }
0215:
0216: } else {
0217: // Something bad in instruction list
0218: throw new IllegalArgumentException();
0219: }
0220: }
0221:
0222: // Sorry, but we have to make another forward pass over some of
0223: // the code to determine the subroutine from which a given ret
0224: // instruction returns.
0225: final Iterator subLabels = retTargets.keySet().iterator();
0226: while (subLabels.hasNext()) {
0227: final Label subLabel = (Label) subLabels.next();
0228: final int pos = insts.indexOf(subLabel);
0229: Assert
0230: .isTrue(pos != -1, "Label " + subLabel
0231: + " not found");
0232: boolean foundRet = false;
0233: final ListIterator liter = insts.listIterator(pos);
0234: while (liter.hasNext()) {
0235: final Object o = liter.next();
0236: if (o instanceof Instruction) {
0237: final Instruction inst = (Instruction) o;
0238: if (inst.isRet()) {
0239: retInsts.put(inst, subLabel);
0240: foundRet = true;
0241: break;
0242: }
0243: }
0244: }
0245: Assert
0246: .isTrue(foundRet, "No ret for subroutine "
0247: + subLabel);
0248: }
0249:
0250: if (CodeArray.DEBUG) {
0251: // Print subroutine to return target mapping
0252: System.out.println("Subroutines and return targets:");
0253: final Iterator subs = retTargets.keySet().iterator();
0254: while (subs.hasNext()) {
0255: final Label sub = (Label) subs.next();
0256: System.out.print(" " + sub + ": ");
0257: final Set s = (Set) retTargets.get(sub);
0258: Assert
0259: .isTrue(s != null, "No return targets for "
0260: + sub);
0261: final Iterator rets = s.iterator();
0262: while (rets.hasNext()) {
0263: final Label ret = (Label) rets.next();
0264: System.out.print(ret.toString());
0265: if (rets.hasNext()) {
0266: System.out.print(", ");
0267: }
0268: }
0269: System.out.println("");
0270: }
0271: }
0272:
0273: // Fix up the stack heights by propagating the heights at each catch
0274: // and each branch to their targets. Visit the blocks
0275: // depth-first. Remember that the classfile requires the maximum
0276: // stack height. I would assume that is why we do all of this
0277: // stack height calculation stuff.
0278:
0279: final Set visited = new HashSet(); // Labels that we've seen
0280: final Stack stack = new Stack(); // Stack of HeightRecords
0281: Label label;
0282:
0283: // Start with the first Label
0284: if (insts.size() > 0) {
0285: Assert.isTrue((insts.get(0) instanceof Label),
0286: "A method must begin with a Label, not "
0287: + insts.get(0));
0288: label = (Label) insts.get(0);
0289: visited.add(label);
0290: stack.push(new HeightRecord(label, 0));
0291: }
0292:
0293: // Also examine each exception handler. Recall that the exception
0294: // object is implicitly pushed on the stack. So, the HeightRecord
0295: // initially has height 1.
0296: final Iterator e = method.tryCatches().iterator();
0297: while (e.hasNext()) {
0298: final TryCatch tc = (TryCatch) e.next();
0299: visited.add(tc.handler());
0300: stack.push(new HeightRecord(tc.handler(), 1));
0301: }
0302:
0303: // Examine the HeightRecords on the stack. Make sure that the
0304: // stack height has not exceeded 256. If the height at a given
0305: // label has changed since we last visited it, then propagate this
0306: // change to labels following the block begun by the label in
0307: // question.
0308: while (!stack.isEmpty()) {
0309: final HeightRecord h = (HeightRecord) stack.pop();
0310:
0311: Assert.isTrue(h.height < 256, "Stack height of " + h.height
0312: + " reached. " + h.label + " ("
0313: + labelPos.get(h.label) + ")");
0314:
0315: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0316: System.out.println(h.label + " has height " + h.height);
0317: }
0318:
0319: Integer labelIndex = (Integer) labelPos.get(h.label);
0320: Assert.isTrue(labelIndex != null, "Index of " + h.label
0321: + " not found");
0322:
0323: final int start = labelIndex.intValue();
0324: int diff = h.height - heights[start];
0325:
0326: // Propagate the change in height to the next branch.
0327: // Then push the branch targets.
0328: if (ClassEditor.DEBUG) {
0329: /*
0330: * System.out.println(" " + h.label + ": change " +
0331: * heights[start] + " to " + h.height);
0332: */
0333: }
0334:
0335: heights[start] = h.height;
0336:
0337: final ListIterator blockIter = insts
0338: .listIterator(start + 1);
0339: i = start;
0340:
0341: // Examine the instructions following the label
0342: while (blockIter.hasNext()) {
0343: final Object ce = blockIter.next();
0344:
0345: i++;
0346:
0347: if (ce instanceof Instruction) {
0348: final Instruction inst = (Instruction) ce;
0349:
0350: if (inst.isReturn() || inst.isThrow()) {
0351: // The method terminates. The stack is popped empty.
0352: heights[i] = 0;
0353:
0354: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0355: System.out.println(" " + heights[i] + ") "
0356: + inst);
0357: }
0358:
0359: // Consider next HeightRecord on stack.
0360: break;
0361:
0362: } else if (inst.isConditionalJump()) {
0363: // If the stack height at this Label has changed since
0364: // we
0365: // last saw it or if we have not processed the target of
0366: // the jump, add a new HeightRecord for the target
0367: // Label.
0368:
0369: heights[i] += diff;
0370:
0371: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0372: System.out.println(" " + heights[i] + ") "
0373: + inst);
0374: }
0375:
0376: label = (Label) inst.operand();
0377:
0378: if ((diff > 0) || !visited.contains(label)) {
0379: visited.add(label);
0380: stack.push(new HeightRecord(label,
0381: heights[i]));
0382: }
0383:
0384: // Fall through. That is, process the instruction after
0385: // the conditional jump. Remember that the code is in
0386: // trace order so the false block (which is the next
0387: // block
0388: // in a depth first traversal) follows. The height of
0389: // the
0390: // stack won't change when we fall through.
0391:
0392: } else if (inst.isGoto() || inst.isJsr()) {
0393: // Once again, if we have already visited the target
0394: // block, add a HeightRecord to the stack.
0395:
0396: heights[i] += diff;
0397:
0398: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0399: System.out.println(" " + heights[i] + ") "
0400: + inst);
0401: }
0402:
0403: label = (Label) inst.operand();
0404:
0405: if ((diff > 0) || !visited.contains(label)) {
0406: visited.add(label);
0407: stack.push(new HeightRecord(label,
0408: heights[i]));
0409: }
0410:
0411: // Deal with the next HeightRecord on the stack.
0412: break;
0413:
0414: } else if (inst.isRet()) {
0415: // Process any unvisited return targets (of the current
0416: // jsr) or those whose current height is less than the
0417: // height at this return instruction.
0418:
0419: heights[i] += diff;
0420:
0421: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0422: System.out.println(" " + heights[i] + ") "
0423: + inst);
0424: }
0425:
0426: final Label subLabel = (Label) retInsts
0427: .get(inst);
0428: Assert.isTrue(subLabel != null,
0429: "Not inside a subroutine at " + inst);
0430:
0431: final Set targets = (Set) retTargets
0432: .get(subLabel);
0433: Assert.isTrue(targets != null, "Subroutine "
0434: + subLabel + " has no return targets");
0435:
0436: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0437: System.out.println(" Returning from: "
0438: + subLabel);
0439: }
0440:
0441: final Iterator retIter = targets.iterator();
0442:
0443: while (retIter.hasNext()) {
0444: label = (Label) retIter.next();
0445:
0446: labelIndex = (Integer) labelPos.get(label);
0447: Assert.isTrue(labelIndex != null,
0448: "Index of " + label + " not found");
0449:
0450: final int idx = labelIndex.intValue();
0451:
0452: if ((heights[idx] < heights[i])
0453: || !visited.contains(label)) {
0454: visited.add(label);
0455: stack.push(new HeightRecord(label,
0456: heights[i]));
0457: }
0458: }
0459:
0460: break;
0461:
0462: } else if (inst.isSwitch()) {
0463: // Visit each unvisited switch target if it increases
0464: // the
0465: // stack height
0466:
0467: // If the height at this Label has changed since it was
0468: // last visited, process each target Label. Otherwise,
0469: // only process unvisited Labels.
0470:
0471: heights[i] += diff;
0472:
0473: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0474: System.out.println(" " + heights[i] + ") "
0475: + inst);
0476: }
0477:
0478: // A switch.
0479: final Switch sw = (Switch) inst.operand();
0480:
0481: label = sw.defaultTarget();
0482:
0483: if ((diff > 0) || !visited.contains(label)) {
0484: visited.add(label);
0485: stack.push(new HeightRecord(label,
0486: heights[i]));
0487: }
0488:
0489: final Label[] targets = sw.targets();
0490:
0491: for (int j = 0; j < targets.length; j++) {
0492: label = targets[j];
0493: if ((diff > 0) || !visited.contains(label)) {
0494: visited.add(label);
0495: stack.push(new HeightRecord(label,
0496: heights[i]));
0497: }
0498: }
0499:
0500: break;
0501:
0502: } else {
0503: // No other blocks to visit. Just adjust the height.
0504:
0505: heights[i] += diff;
0506:
0507: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0508: System.out.println(" " + heights[i] + ") "
0509: + inst);
0510: }
0511: }
0512:
0513: } else if (ce instanceof Label) {
0514: // We've hit the next block. Update the stack height.
0515: // Process this next block if has not been visited or its
0516: // current height is different from the previous
0517: // instruction.
0518:
0519: label = (Label) ce;
0520:
0521: diff = heights[i - 1] - heights[i];
0522:
0523: if ((diff > 0) || !visited.contains(label)) {
0524: visited.add(label);
0525: heights[i] = heights[i - 1];
0526: }
0527:
0528: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0529: System.out.println(" " + heights[i] + ") "
0530: + label);
0531: }
0532: }
0533: }
0534: }
0535:
0536: // Find the maximum stack height.
0537: maxStack = 0;
0538:
0539: for (i = 0; i < heights.length; i++) {
0540: final int h = heights[i];
0541:
0542: if (h > maxStack) {
0543: maxStack = h;
0544: }
0545: }
0546: }
0547:
0548: /**
0549: * Returns the maximum number of local variables used by this method.
0550: */
0551: public int maxLocals() {
0552: return maxLocals;
0553: }
0554:
0555: /**
0556: * Returns the maximum height of the stack at any point in this method.
0557: */
0558: public int maxStack() {
0559: return maxStack;
0560: }
0561:
0562: /**
0563: * Returns the index in the byte array of the given label.
0564: */
0565: public int labelIndex(final Label label) {
0566: final Integer i = (Integer) labels.get(label);
0567:
0568: if (i != null) {
0569: return i.intValue();
0570: }
0571:
0572: throw new IllegalArgumentException("Label " + label
0573: + " not found");
0574: }
0575:
0576: /**
0577: * Returns the byte array after resolving branches.
0578: */
0579: public byte[] array() {
0580: if (branches.size() > 0) {
0581: if (!longBranch && (codeLength >= 0x10000)) {
0582: longBranch = true;
0583: buildCode();
0584: }
0585: }
0586:
0587: final byte[] c = new byte[codeLength];
0588: int i = codeLength;
0589:
0590: for (ByteCell p = codeTail; p != null; p = p.prev) {
0591: c[--i] = p.value;
0592: }
0593:
0594: Iterator e;
0595:
0596: e = branches.keySet().iterator();
0597:
0598: while (e.hasNext()) {
0599: final Integer branch = (Integer) e.next();
0600: final int branchIndex = branch.intValue();
0601:
0602: final Integer inst = (Integer) branchInsts.get(branch);
0603: final int instIndex = inst.intValue();
0604:
0605: final Label label = (Label) branches.get(branch);
0606: final Integer target = (Integer) labels.get(label);
0607:
0608: Assert.isTrue(target != null, "Index of " + label
0609: + " not found");
0610:
0611: int diff = target.intValue() - instIndex;
0612:
0613: Assert.isTrue((-diff < 0x10000) && (diff < 0x10000),
0614: "Branch offset too large: " + diff);
0615:
0616: c[branchIndex] = (byte) ((diff >>> 8) & 0xff);
0617: c[branchIndex + 1] = (byte) (diff & 0xff);
0618: }
0619:
0620: e = longBranches.keySet().iterator();
0621:
0622: while (e.hasNext()) {
0623: final Integer branch = (Integer) e.next();
0624: final int branchIndex = branch.intValue();
0625:
0626: final Integer inst = (Integer) branchInsts.get(branch);
0627: final int instIndex = inst.intValue();
0628:
0629: final Label label = (Label) longBranches.get(branch);
0630: final Integer target = (Integer) labels.get(label);
0631:
0632: final int diff = target.intValue() - instIndex;
0633:
0634: c[branchIndex] = (byte) ((diff >>> 24) & 0xff);
0635: c[branchIndex + 1] = (byte) ((diff >>> 16) & 0xff);
0636: c[branchIndex + 2] = (byte) ((diff >>> 8) & 0xff);
0637: c[branchIndex + 3] = (byte) (diff & 0xff);
0638: }
0639:
0640: return c;
0641: }
0642:
0643: /**
0644: * Makes note of a label.
0645: */
0646: public void addLabel(final Label label) {
0647: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0648: System.out.println(" " + codeLength + ": " + "label "
0649: + label);
0650: }
0651:
0652: labels.put(label, new Integer(codeLength));
0653: }
0654:
0655: /**
0656: * Adds a 4-byte branch to a given label. The branch is from the index of
0657: * the last opcode added.
0658: */
0659: public void addLongBranch(final Label label) {
0660: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0661: System.out.println(" " + codeLength + ": "
0662: + "long branch to " + label);
0663: }
0664:
0665: branchInsts.put(new Integer(codeLength), new Integer(lastInst));
0666: longBranches.put(new Integer(codeLength), label);
0667: addByte(0);
0668: addByte(0);
0669: addByte(0);
0670: addByte(0);
0671: }
0672:
0673: /**
0674: * Adds a 2-byte branch to a given label. The branch is from the index of
0675: * the last opcode added.
0676: */
0677: public void addBranch(final Label label) {
0678: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0679: System.out.println(" " + codeLength + ": "
0680: + "branch to " + label);
0681: }
0682:
0683: branchInsts.put(new Integer(codeLength), new Integer(lastInst));
0684: branches.put(new Integer(codeLength), label);
0685: addByte(0);
0686: addByte(0);
0687: }
0688:
0689: /**
0690: * Add an opcode to the byte array, adjusting for 4-byte alignment for
0691: * switch instructions and saving the index for calculating branches.
0692: *
0693: * @param opcode
0694: * The opcode.
0695: * @see Opcode
0696: */
0697: public void addOpcode(final int opcode) {
0698: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0699: System.out.println(" " + codeLength + ": " + "opcode "
0700: + Opcode.opcNames[opcode]);
0701: }
0702:
0703: lastInst = codeLength;
0704:
0705: addByte(opcode);
0706:
0707: if ((opcode == Opcode.opc_tableswitch)
0708: || (opcode == Opcode.opc_lookupswitch)) {
0709: // Switch instructions are followed by padding so that table
0710: // starts on a 4-byte boundary.
0711: while (codeLength % 4 != 0) {
0712: addByte(0);
0713: }
0714: }
0715: }
0716:
0717: /**
0718: * Adds a single byte to the array.
0719: */
0720: public void addByte(final int i) {
0721: if (ClassEditor.DEBUG) {
0722: System.out
0723: .println(" " + codeLength + ": " + "byte " + i);
0724: }
0725:
0726: // The bytecode array is represented as a linked list of
0727: // ByteCells. This method creates a new ByteCell and appends it
0728: // to the linked list.
0729:
0730: final ByteCell p = new ByteCell();
0731: p.value = (byte) (i & 0xff);
0732: p.prev = codeTail;
0733: codeTail = p;
0734: codeLength++;
0735: }
0736:
0737: /**
0738: * Adds a 2-byte short to the array, high byte first.
0739: */
0740: public void addShort(final int i) {
0741: if (ClassEditor.DEBUG) {
0742: System.out.println(" " + codeLength + ": " + "short "
0743: + i);
0744: }
0745:
0746: addByte(i >>> 8);
0747: addByte(i);
0748: }
0749:
0750: /**
0751: * Adds a 4-byte int to the array, high byte first.
0752: */
0753: public void addInt(final int i) {
0754: if (ClassEditor.DEBUG) {
0755: System.out.println(" " + codeLength + ": " + "int " + i);
0756: }
0757:
0758: addByte(i >>> 24);
0759: addByte(i >>> 16);
0760: addByte(i >>> 8);
0761: addByte(i);
0762: }
0763:
0764: public void visit_nop(final Instruction inst) {
0765: // If it must have been put there for a reason.
0766: addOpcode(Opcode.opc_nop);
0767: stackHeight += 0;
0768: }
0769:
0770: /*
0771: * Does pretty much what you'd expect. Examines the instruction's operand to
0772: * determine if one of the special constant opcodes (e.g. iconst_1) can be
0773: * used. Adds the most appropriate instruction.
0774: */
0775: public void visit_ldc(final Instruction inst) {
0776: final Object operand = inst.operand();
0777:
0778: if (operand == null) {
0779: addOpcode(Opcode.opc_aconst_null);
0780: stackHeight++;
0781:
0782: } else if (operand instanceof Integer) {
0783: final int v = ((Integer) operand).intValue();
0784:
0785: switch (v) {
0786: case -1:
0787: addOpcode(Opcode.opc_iconst_m1);
0788: break;
0789: case 0:
0790: addOpcode(Opcode.opc_iconst_0);
0791: break;
0792: case 1:
0793: addOpcode(Opcode.opc_iconst_1);
0794: break;
0795: case 2:
0796: addOpcode(Opcode.opc_iconst_2);
0797: break;
0798: case 3:
0799: addOpcode(Opcode.opc_iconst_3);
0800: break;
0801: case 4:
0802: addOpcode(Opcode.opc_iconst_4);
0803: break;
0804: case 5:
0805: addOpcode(Opcode.opc_iconst_5);
0806: break;
0807: default: {
0808: if ((byte) v == v) {
0809: addOpcode(Opcode.opc_bipush);
0810: addByte(v);
0811: } else if ((short) v == v) {
0812: addOpcode(Opcode.opc_sipush);
0813: addShort(v);
0814: } else {
0815: final int index = constants.addConstant(
0816: Constant.INTEGER, operand);
0817: if (index < 256) {
0818: addOpcode(Opcode.opc_ldc);
0819: addByte(index);
0820: } else {
0821: addOpcode(Opcode.opc_ldc_w);
0822: addShort(index);
0823: }
0824: }
0825: break;
0826: }
0827: }
0828:
0829: stackHeight++;
0830:
0831: } else if (operand instanceof Float) {
0832: final float v = ((Float) operand).floatValue();
0833:
0834: if (v == 0.0F) {
0835: addOpcode(Opcode.opc_fconst_0);
0836: } else if (v == 1.0F) {
0837: addOpcode(Opcode.opc_fconst_1);
0838: } else if (v == 2.0F) {
0839: addOpcode(Opcode.opc_fconst_2);
0840: } else {
0841: final int index = constants.addConstant(Constant.FLOAT,
0842: operand);
0843: if (index < 256) {
0844: addOpcode(Opcode.opc_ldc);
0845: addByte(index);
0846: } else {
0847: addOpcode(Opcode.opc_ldc_w);
0848: addShort(index);
0849: }
0850: }
0851:
0852: stackHeight++;
0853:
0854: } else if (operand instanceof Long) {
0855: final long v = ((Long) operand).longValue();
0856:
0857: if (v == 0) {
0858: addOpcode(Opcode.opc_lconst_0);
0859: } else if (v == 1) {
0860: addOpcode(Opcode.opc_lconst_1);
0861: } else {
0862: final int index = constants.addConstant(Constant.LONG,
0863: operand);
0864: addOpcode(Opcode.opc_ldc2_w);
0865: addShort(index);
0866: }
0867:
0868: stackHeight += 2;
0869:
0870: } else if (operand instanceof Double) {
0871: final double v = ((Double) operand).doubleValue();
0872:
0873: if (v == 0.0) {
0874: addOpcode(Opcode.opc_dconst_0);
0875: } else if (v == 1.0) {
0876: addOpcode(Opcode.opc_dconst_1);
0877: } else {
0878: final int index = constants.addConstant(
0879: Constant.DOUBLE, operand);
0880: addOpcode(Opcode.opc_ldc2_w);
0881: addShort(index);
0882: }
0883:
0884: stackHeight += 2;
0885:
0886: } else if (operand instanceof String) {
0887: final int index = constants.addConstant(Constant.STRING,
0888: operand);
0889:
0890: if (index < 256) {
0891: addOpcode(Opcode.opc_ldc);
0892: addByte(index);
0893: } else {
0894: addOpcode(Opcode.opc_ldc_w);
0895: addShort(index);
0896: }
0897:
0898: stackHeight++;
0899: } else {
0900: throw new RuntimeException();
0901: }
0902: }
0903:
0904: /*
0905: * Tries to use the shorter iload_x instructions.
0906: */
0907: public void visit_iload(final Instruction inst) {
0908: final int index = ((LocalVariable) inst.operand()).index();
0909:
0910: if (index + 1 > maxLocals) {
0911: maxLocals = index + 1;
0912: }
0913:
0914: if (inst.useSlow()) {
0915: if (index < 256) {
0916: addOpcode(Opcode.opc_iload);
0917: addByte(index);
0918: } else {
0919: addOpcode(Opcode.opc_wide);
0920: addByte(Opcode.opc_iload);
0921: addShort(index);
0922: }
0923: stackHeight++;
0924: return;
0925: }
0926:
0927: switch (index) {
0928: case 0:
0929: addOpcode(Opcode.opc_iload_0);
0930: break;
0931: case 1:
0932: addOpcode(Opcode.opc_iload_1);
0933: break;
0934: case 2:
0935: addOpcode(Opcode.opc_iload_2);
0936: break;
0937: case 3:
0938: addOpcode(Opcode.opc_iload_3);
0939: break;
0940: default:
0941: if (index < 256) {
0942: addOpcode(Opcode.opc_iload);
0943: addByte(index);
0944: } else {
0945: addOpcode(Opcode.opc_wide);
0946: addByte(Opcode.opc_iload);
0947: addShort(index);
0948: }
0949: break;
0950: }
0951:
0952: stackHeight++;
0953: }
0954:
0955: public void visit_lload(final Instruction inst) {
0956: final int index = ((LocalVariable) inst.operand()).index();
0957:
0958: if (index + 2 > maxLocals) {
0959: maxLocals = index + 2;
0960: }
0961:
0962: if (inst.useSlow()) {
0963: if (index < 256) {
0964: addOpcode(Opcode.opc_lload);
0965: addByte(index);
0966: } else {
0967: addOpcode(Opcode.opc_wide);
0968: addByte(Opcode.opc_lload);
0969: addShort(index);
0970: }
0971: stackHeight++;
0972: return;
0973: }
0974:
0975: switch (index) {
0976: case 0:
0977: addOpcode(Opcode.opc_lload_0);
0978: break;
0979: case 1:
0980: addOpcode(Opcode.opc_lload_1);
0981: break;
0982: case 2:
0983: addOpcode(Opcode.opc_lload_2);
0984: break;
0985: case 3:
0986: addOpcode(Opcode.opc_lload_3);
0987: break;
0988: default:
0989: if (index < 256) {
0990: addOpcode(Opcode.opc_lload);
0991: addByte(index);
0992: } else {
0993: addOpcode(Opcode.opc_wide);
0994: addByte(Opcode.opc_lload);
0995: addShort(index);
0996: }
0997: break;
0998: }
0999:
1000: stackHeight += 2;
1001: }
1002:
1003: public void visit_fload(final Instruction inst) {
1004: final int index = ((LocalVariable) inst.operand()).index();
1005:
1006: if (index + 1 > maxLocals) {
1007: maxLocals = index + 1;
1008: }
1009:
1010: if (inst.useSlow()) {
1011: if (index < 256) {
1012: addOpcode(Opcode.opc_fload);
1013: addByte(index);
1014: } else {
1015: addOpcode(Opcode.opc_wide);
1016: addByte(Opcode.opc_fload);
1017: addShort(index);
1018: }
1019:
1020: stackHeight++;
1021: return;
1022: }
1023:
1024: switch (index) {
1025: case 0:
1026: addOpcode(Opcode.opc_fload_0);
1027: break;
1028: case 1:
1029: addOpcode(Opcode.opc_fload_1);
1030: break;
1031: case 2:
1032: addOpcode(Opcode.opc_fload_2);
1033: break;
1034: case 3:
1035: addOpcode(Opcode.opc_fload_3);
1036: break;
1037: default:
1038: if (index < 256) {
1039: addOpcode(Opcode.opc_fload);
1040: addByte(index);
1041: } else {
1042: addOpcode(Opcode.opc_wide);
1043: addByte(Opcode.opc_fload);
1044: addShort(index);
1045: }
1046: break;
1047: }
1048:
1049: stackHeight++;
1050: }
1051:
1052: public void visit_dload(final Instruction inst) {
1053: final int index = ((LocalVariable) inst.operand()).index();
1054:
1055: if (index + 2 > maxLocals) {
1056: maxLocals = index + 2;
1057: }
1058:
1059: if (inst.useSlow()) {
1060: if (index < 256) {
1061: addOpcode(Opcode.opc_dload);
1062: addByte(index);
1063: } else {
1064: addOpcode(Opcode.opc_wide);
1065: addByte(Opcode.opc_dload);
1066: addShort(index);
1067: }
1068: stackHeight += 2;
1069: return;
1070: }
1071:
1072: switch (index) {
1073: case 0:
1074: addOpcode(Opcode.opc_dload_0);
1075: break;
1076: case 1:
1077: addOpcode(Opcode.opc_dload_1);
1078: break;
1079: case 2:
1080: addOpcode(Opcode.opc_dload_2);
1081: break;
1082: case 3:
1083: addOpcode(Opcode.opc_dload_3);
1084: break;
1085: default:
1086: if (index < 256) {
1087: addOpcode(Opcode.opc_dload);
1088: addByte(index);
1089: } else {
1090: addOpcode(Opcode.opc_wide);
1091: addByte(Opcode.opc_dload);
1092: addShort(index);
1093: }
1094: break;
1095: }
1096:
1097: stackHeight += 2;
1098: }
1099:
1100: public void visit_aload(final Instruction inst) {
1101: final int index = ((LocalVariable) inst.operand()).index();
1102:
1103: if (index + 1 > maxLocals) {
1104: maxLocals = index + 1;
1105: }
1106:
1107: if (inst.useSlow()) {
1108: if (index < 256) {
1109: addOpcode(Opcode.opc_aload);
1110: addByte(index);
1111: } else {
1112: addOpcode(Opcode.opc_wide);
1113: addByte(Opcode.opc_aload);
1114: addShort(index);
1115: }
1116: stackHeight++;
1117: return;
1118: }
1119:
1120: switch (index) {
1121: case 0:
1122: addOpcode(Opcode.opc_aload_0);
1123: break;
1124: case 1:
1125: addOpcode(Opcode.opc_aload_1);
1126: break;
1127: case 2:
1128: addOpcode(Opcode.opc_aload_2);
1129: break;
1130: case 3:
1131: addOpcode(Opcode.opc_aload_3);
1132: break;
1133: default:
1134: if (index < 256) {
1135: addOpcode(Opcode.opc_aload);
1136: addByte(index);
1137: } else {
1138: addOpcode(Opcode.opc_wide);
1139: addByte(Opcode.opc_aload);
1140: addShort(index);
1141: }
1142: break;
1143: }
1144:
1145: stackHeight++;
1146: }
1147:
1148: /**
1149: * Pops an item off the stack.
1150: */
1151: public void visit_iaload(final Instruction inst) {
1152: addOpcode(Opcode.opc_iaload);
1153: stackHeight--;
1154: }
1155:
1156: public void visit_laload(final Instruction inst) {
1157: addOpcode(Opcode.opc_laload);
1158: stackHeight += 0;
1159: }
1160:
1161: public void visit_faload(final Instruction inst) {
1162: addOpcode(Opcode.opc_faload);
1163: stackHeight--;
1164: }
1165:
1166: public void visit_daload(final Instruction inst) {
1167: addOpcode(Opcode.opc_daload);
1168: stackHeight += 0;
1169: }
1170:
1171: public void visit_aaload(final Instruction inst) {
1172: addOpcode(Opcode.opc_aaload);
1173: stackHeight--;
1174: }
1175:
1176: public void visit_baload(final Instruction inst) {
1177: addOpcode(Opcode.opc_baload);
1178: stackHeight--;
1179: }
1180:
1181: public void visit_caload(final Instruction inst) {
1182: addOpcode(Opcode.opc_caload);
1183: stackHeight--;
1184: }
1185:
1186: public void visit_saload(final Instruction inst) {
1187: addOpcode(Opcode.opc_saload);
1188: stackHeight--;
1189: }
1190:
1191: /*
1192: * Try to take advantage of smaller opcodes (e.g. istore_1).
1193: */
1194: public void visit_istore(final Instruction inst) {
1195: final int index = ((LocalVariable) inst.operand()).index();
1196:
1197: if (index + 1 > maxLocals) {
1198: maxLocals = index + 1;
1199: }
1200:
1201: if (inst.useSlow()) {
1202: if (index < 256) {
1203: addOpcode(Opcode.opc_istore);
1204: addByte(index);
1205: } else {
1206: addOpcode(Opcode.opc_wide);
1207: addByte(Opcode.opc_istore);
1208: addShort(index);
1209: }
1210: stackHeight--;
1211: return;
1212: }
1213:
1214: switch (index) {
1215: case 0:
1216: addOpcode(Opcode.opc_istore_0);
1217: break;
1218: case 1:
1219: addOpcode(Opcode.opc_istore_1);
1220: break;
1221: case 2:
1222: addOpcode(Opcode.opc_istore_2);
1223: break;
1224: case 3:
1225: addOpcode(Opcode.opc_istore_3);
1226: break;
1227: default:
1228: if (index < 256) {
1229: addOpcode(Opcode.opc_istore);
1230: addByte(index);
1231: } else {
1232: addOpcode(Opcode.opc_wide);
1233: addByte(Opcode.opc_istore);
1234: addShort(index);
1235: }
1236: break;
1237: }
1238:
1239: stackHeight--;
1240: }
1241:
1242: public void visit_lstore(final Instruction inst) {
1243: final int index = ((LocalVariable) inst.operand()).index();
1244:
1245: if (index + 2 > maxLocals) {
1246: maxLocals = index + 2;
1247: }
1248:
1249: if (inst.useSlow()) {
1250: if (index < 256) {
1251: addOpcode(Opcode.opc_lstore);
1252: addByte(index);
1253: } else {
1254: addOpcode(Opcode.opc_wide);
1255: addByte(Opcode.opc_lstore);
1256: addShort(index);
1257: }
1258: stackHeight -= 2;
1259: return;
1260: }
1261:
1262: switch (index) {
1263: case 0:
1264: addOpcode(Opcode.opc_lstore_0);
1265: break;
1266: case 1:
1267: addOpcode(Opcode.opc_lstore_1);
1268: break;
1269: case 2:
1270: addOpcode(Opcode.opc_lstore_2);
1271: break;
1272: case 3:
1273: addOpcode(Opcode.opc_lstore_3);
1274: break;
1275: default:
1276: if (index < 256) {
1277: addOpcode(Opcode.opc_lstore);
1278: addByte(index);
1279: } else {
1280: addOpcode(Opcode.opc_wide);
1281: addByte(Opcode.opc_lstore);
1282: addShort(index);
1283: }
1284: break;
1285: }
1286:
1287: stackHeight -= 2;
1288: }
1289:
1290: public void visit_fstore(final Instruction inst) {
1291: final int index = ((LocalVariable) inst.operand()).index();
1292:
1293: if (index + 1 > maxLocals) {
1294: maxLocals = index + 1;
1295: }
1296:
1297: if (inst.useSlow()) {
1298: if (index < 256) {
1299: addOpcode(Opcode.opc_fstore);
1300: addByte(index);
1301: } else {
1302: addOpcode(Opcode.opc_wide);
1303: addByte(Opcode.opc_fstore);
1304: addShort(index);
1305: }
1306: stackHeight--;
1307: return;
1308: }
1309:
1310: switch (index) {
1311: case 0:
1312: addOpcode(Opcode.opc_fstore_0);
1313: break;
1314: case 1:
1315: addOpcode(Opcode.opc_fstore_1);
1316: break;
1317: case 2:
1318: addOpcode(Opcode.opc_fstore_2);
1319: break;
1320: case 3:
1321: addOpcode(Opcode.opc_fstore_3);
1322: break;
1323: default:
1324: if (index < 256) {
1325: addOpcode(Opcode.opc_fstore);
1326: addByte(index);
1327: } else {
1328: addOpcode(Opcode.opc_wide);
1329: addByte(Opcode.opc_fstore);
1330: addShort(index);
1331: }
1332: break;
1333: }
1334:
1335: stackHeight--;
1336: }
1337:
1338: public void visit_dstore(final Instruction inst) {
1339: final int index = ((LocalVariable) inst.operand()).index();
1340:
1341: if (index + 2 > maxLocals) {
1342: maxLocals = index + 2;
1343: }
1344:
1345: if (inst.useSlow()) {
1346: if (index < 256) {
1347: addOpcode(Opcode.opc_dstore);
1348: addByte(index);
1349: } else {
1350: addOpcode(Opcode.opc_wide);
1351: addByte(Opcode.opc_dstore);
1352: addShort(index);
1353: }
1354: stackHeight -= 2;
1355: return;
1356: }
1357:
1358: switch (index) {
1359: case 0:
1360: addOpcode(Opcode.opc_dstore_0);
1361: break;
1362: case 1:
1363: addOpcode(Opcode.opc_dstore_1);
1364: break;
1365: case 2:
1366: addOpcode(Opcode.opc_dstore_2);
1367: break;
1368: case 3:
1369: addOpcode(Opcode.opc_dstore_3);
1370: break;
1371: default:
1372: if (index < 256) {
1373: addOpcode(Opcode.opc_dstore);
1374: addByte(index);
1375: } else {
1376: addOpcode(Opcode.opc_wide);
1377: addByte(Opcode.opc_dstore);
1378: addShort(index);
1379: }
1380: break;
1381: }
1382:
1383: stackHeight -= 2;
1384: }
1385:
1386: public void visit_astore(final Instruction inst) {
1387: final int index = ((LocalVariable) inst.operand()).index();
1388:
1389: if (index + 1 > maxLocals) {
1390: maxLocals = index + 1;
1391: }
1392:
1393: if (inst.useSlow()) {
1394: if (index < 256) {
1395: addOpcode(Opcode.opc_astore);
1396: addByte(index);
1397: } else {
1398: addOpcode(Opcode.opc_wide);
1399: addByte(Opcode.opc_astore);
1400: addShort(index);
1401: }
1402: stackHeight--;
1403: return;
1404: }
1405:
1406: switch (index) {
1407: case 0:
1408: addOpcode(Opcode.opc_astore_0);
1409: break;
1410: case 1:
1411: addOpcode(Opcode.opc_astore_1);
1412: break;
1413: case 2:
1414: addOpcode(Opcode.opc_astore_2);
1415: break;
1416: case 3:
1417: addOpcode(Opcode.opc_astore_3);
1418: break;
1419: default:
1420: if (index < 256) {
1421: addOpcode(Opcode.opc_astore);
1422: addByte(index);
1423: } else {
1424: addOpcode(Opcode.opc_wide);
1425: addByte(Opcode.opc_astore);
1426: addShort(index);
1427: }
1428: break;
1429: }
1430:
1431: stackHeight--;
1432: }
1433:
1434: /*
1435: * Store into an array. Pop 3+ items off the stack.
1436: */
1437: public void visit_iastore(final Instruction inst) {
1438: addOpcode(Opcode.opc_iastore);
1439: stackHeight -= 3;
1440: }
1441:
1442: public void visit_lastore(final Instruction inst) {
1443: addOpcode(Opcode.opc_lastore);
1444: stackHeight -= 4;
1445: }
1446:
1447: public void visit_fastore(final Instruction inst) {
1448: addOpcode(Opcode.opc_fastore);
1449: stackHeight -= 3;
1450: }
1451:
1452: public void visit_dastore(final Instruction inst) {
1453: addOpcode(Opcode.opc_dastore);
1454: stackHeight -= 4;
1455: }
1456:
1457: public void visit_aastore(final Instruction inst) {
1458: addOpcode(Opcode.opc_aastore);
1459: stackHeight -= 3;
1460: }
1461:
1462: public void visit_bastore(final Instruction inst) {
1463: addOpcode(Opcode.opc_bastore);
1464: stackHeight -= 3;
1465: }
1466:
1467: public void visit_castore(final Instruction inst) {
1468: addOpcode(Opcode.opc_castore);
1469: stackHeight -= 3;
1470: }
1471:
1472: public void visit_sastore(final Instruction inst) {
1473: addOpcode(Opcode.opc_sastore);
1474: stackHeight -= 3;
1475: }
1476:
1477: public void visit_pop(final Instruction inst) {
1478: addOpcode(Opcode.opc_pop);
1479: stackHeight--;
1480: }
1481:
1482: public void visit_pop2(final Instruction inst) {
1483: addOpcode(Opcode.opc_pop2);
1484: stackHeight -= 2;
1485: }
1486:
1487: public void visit_dup(final Instruction inst) {
1488: addOpcode(Opcode.opc_dup);
1489: stackHeight++;
1490: }
1491:
1492: public void visit_dup_x1(final Instruction inst) {
1493: addOpcode(Opcode.opc_dup_x1);
1494: stackHeight++;
1495: }
1496:
1497: public void visit_dup_x2(final Instruction inst) {
1498: addOpcode(Opcode.opc_dup_x2);
1499: stackHeight++;
1500: }
1501:
1502: public void visit_dup2(final Instruction inst) {
1503: addOpcode(Opcode.opc_dup2);
1504: stackHeight += 2;
1505: }
1506:
1507: public void visit_dup2_x1(final Instruction inst) {
1508: addOpcode(Opcode.opc_dup2_x1);
1509: stackHeight += 2;
1510: }
1511:
1512: public void visit_dup2_x2(final Instruction inst) {
1513: addOpcode(Opcode.opc_dup2_x2);
1514: stackHeight += 2;
1515: }
1516:
1517: public void visit_swap(final Instruction inst) {
1518: addOpcode(Opcode.opc_swap);
1519: }
1520:
1521: public void visit_iadd(final Instruction inst) {
1522: addOpcode(Opcode.opc_iadd);
1523: stackHeight--;
1524: }
1525:
1526: public void visit_ladd(final Instruction inst) {
1527: addOpcode(Opcode.opc_ladd);
1528: stackHeight -= 2;
1529: }
1530:
1531: public void visit_fadd(final Instruction inst) {
1532: addOpcode(Opcode.opc_fadd);
1533: stackHeight--;
1534: }
1535:
1536: public void visit_dadd(final Instruction inst) {
1537: addOpcode(Opcode.opc_dadd);
1538: stackHeight -= 2;
1539: }
1540:
1541: public void visit_isub(final Instruction inst) {
1542: addOpcode(Opcode.opc_isub);
1543: stackHeight--;
1544: }
1545:
1546: public void visit_lsub(final Instruction inst) {
1547: addOpcode(Opcode.opc_lsub);
1548: stackHeight -= 2;
1549: }
1550:
1551: public void visit_fsub(final Instruction inst) {
1552: addOpcode(Opcode.opc_fsub);
1553: stackHeight--;
1554: }
1555:
1556: public void visit_dsub(final Instruction inst) {
1557: addOpcode(Opcode.opc_dsub);
1558: stackHeight -= 2;
1559: }
1560:
1561: public void visit_imul(final Instruction inst) {
1562: addOpcode(Opcode.opc_imul);
1563: stackHeight--;
1564: }
1565:
1566: public void visit_lmul(final Instruction inst) {
1567: addOpcode(Opcode.opc_lmul);
1568: stackHeight -= 2;
1569: }
1570:
1571: public void visit_fmul(final Instruction inst) {
1572: addOpcode(Opcode.opc_fmul);
1573: stackHeight--;
1574: }
1575:
1576: public void visit_dmul(final Instruction inst) {
1577: addOpcode(Opcode.opc_dmul);
1578: stackHeight -= 2;
1579: }
1580:
1581: public void visit_idiv(final Instruction inst) {
1582: addOpcode(Opcode.opc_idiv);
1583: stackHeight--;
1584: }
1585:
1586: public void visit_ldiv(final Instruction inst) {
1587: addOpcode(Opcode.opc_ldiv);
1588: stackHeight -= 2;
1589: }
1590:
1591: public void visit_fdiv(final Instruction inst) {
1592: addOpcode(Opcode.opc_fdiv);
1593: stackHeight--;
1594: }
1595:
1596: public void visit_ddiv(final Instruction inst) {
1597: addOpcode(Opcode.opc_ddiv);
1598: stackHeight -= 2;
1599: }
1600:
1601: public void visit_irem(final Instruction inst) {
1602: addOpcode(Opcode.opc_irem);
1603: stackHeight--;
1604: }
1605:
1606: public void visit_lrem(final Instruction inst) {
1607: addOpcode(Opcode.opc_lrem);
1608: stackHeight -= 2;
1609: }
1610:
1611: public void visit_frem(final Instruction inst) {
1612: addOpcode(Opcode.opc_frem);
1613: stackHeight--;
1614: }
1615:
1616: public void visit_drem(final Instruction inst) {
1617: addOpcode(Opcode.opc_drem);
1618: stackHeight -= 2;
1619: }
1620:
1621: public void visit_ineg(final Instruction inst) {
1622: addOpcode(Opcode.opc_ineg);
1623: stackHeight += 0;
1624: }
1625:
1626: public void visit_lneg(final Instruction inst) {
1627: addOpcode(Opcode.opc_lneg);
1628: stackHeight += 0;
1629: }
1630:
1631: public void visit_fneg(final Instruction inst) {
1632: addOpcode(Opcode.opc_fneg);
1633: stackHeight += 0;
1634: }
1635:
1636: public void visit_dneg(final Instruction inst) {
1637: addOpcode(Opcode.opc_dneg);
1638: stackHeight += 0;
1639: }
1640:
1641: public void visit_ishl(final Instruction inst) {
1642: addOpcode(Opcode.opc_ishl);
1643: stackHeight--;
1644: }
1645:
1646: public void visit_lshl(final Instruction inst) {
1647: addOpcode(Opcode.opc_lshl);
1648: stackHeight--;
1649: }
1650:
1651: public void visit_ishr(final Instruction inst) {
1652: addOpcode(Opcode.opc_ishr);
1653: stackHeight--;
1654: }
1655:
1656: public void visit_lshr(final Instruction inst) {
1657: addOpcode(Opcode.opc_lshr);
1658: stackHeight--;
1659: }
1660:
1661: public void visit_iushr(final Instruction inst) {
1662: addOpcode(Opcode.opc_iushr);
1663: stackHeight--;
1664: }
1665:
1666: public void visit_lushr(final Instruction inst) {
1667: addOpcode(Opcode.opc_lushr);
1668: stackHeight--;
1669: }
1670:
1671: public void visit_iand(final Instruction inst) {
1672: addOpcode(Opcode.opc_iand);
1673: stackHeight--;
1674: }
1675:
1676: public void visit_land(final Instruction inst) {
1677: addOpcode(Opcode.opc_land);
1678: stackHeight -= 2;
1679: }
1680:
1681: public void visit_ior(final Instruction inst) {
1682: addOpcode(Opcode.opc_ior);
1683: stackHeight--;
1684: }
1685:
1686: public void visit_lor(final Instruction inst) {
1687: addOpcode(Opcode.opc_lor);
1688: stackHeight -= 2;
1689: }
1690:
1691: public void visit_ixor(final Instruction inst) {
1692: addOpcode(Opcode.opc_ixor);
1693: stackHeight--;
1694: }
1695:
1696: public void visit_lxor(final Instruction inst) {
1697: addOpcode(Opcode.opc_lxor);
1698: stackHeight -= 2;
1699: }
1700:
1701: public void visit_iinc(final Instruction inst) {
1702: final IncOperand operand = (IncOperand) inst.operand();
1703:
1704: final int index = operand.var().index();
1705:
1706: if (index + 1 > maxLocals) {
1707: maxLocals = index + 1;
1708: }
1709:
1710: final int incr = operand.incr();
1711:
1712: if ((index < 256) && ((byte) incr == incr)) {
1713: addOpcode(Opcode.opc_iinc);
1714: addByte(index);
1715: addByte(incr);
1716: } else {
1717: addOpcode(Opcode.opc_wide);
1718: addByte(Opcode.opc_iinc);
1719: addShort(index);
1720: addShort(incr);
1721: }
1722:
1723: stackHeight += 0;
1724: }
1725:
1726: public void visit_i2l(final Instruction inst) {
1727: addOpcode(Opcode.opc_i2l);
1728: stackHeight++;
1729: }
1730:
1731: public void visit_i2f(final Instruction inst) {
1732: addOpcode(Opcode.opc_i2f);
1733: stackHeight += 0;
1734: }
1735:
1736: public void visit_i2d(final Instruction inst) {
1737: addOpcode(Opcode.opc_i2d);
1738: stackHeight++;
1739: }
1740:
1741: public void visit_l2i(final Instruction inst) {
1742: addOpcode(Opcode.opc_l2i);
1743: stackHeight--;
1744: }
1745:
1746: public void visit_l2f(final Instruction inst) {
1747: addOpcode(Opcode.opc_l2f);
1748: stackHeight--;
1749: }
1750:
1751: public void visit_l2d(final Instruction inst) {
1752: addOpcode(Opcode.opc_l2d);
1753: stackHeight += 0;
1754: }
1755:
1756: public void visit_f2i(final Instruction inst) {
1757: addOpcode(Opcode.opc_f2i);
1758: stackHeight += 0;
1759: }
1760:
1761: public void visit_f2l(final Instruction inst) {
1762: addOpcode(Opcode.opc_f2l);
1763: stackHeight++;
1764: }
1765:
1766: public void visit_f2d(final Instruction inst) {
1767: addOpcode(Opcode.opc_f2d);
1768: stackHeight++;
1769: }
1770:
1771: public void visit_d2i(final Instruction inst) {
1772: addOpcode(Opcode.opc_d2i);
1773: stackHeight--;
1774: }
1775:
1776: public void visit_d2l(final Instruction inst) {
1777: addOpcode(Opcode.opc_d2l);
1778: stackHeight += 0;
1779: }
1780:
1781: public void visit_d2f(final Instruction inst) {
1782: addOpcode(Opcode.opc_d2f);
1783: stackHeight--;
1784: }
1785:
1786: public void visit_i2b(final Instruction inst) {
1787: addOpcode(Opcode.opc_i2b);
1788: stackHeight += 0;
1789: }
1790:
1791: public void visit_i2c(final Instruction inst) {
1792: addOpcode(Opcode.opc_i2c);
1793: stackHeight += 0;
1794: }
1795:
1796: public void visit_i2s(final Instruction inst) {
1797: addOpcode(Opcode.opc_i2s);
1798: stackHeight += 0;
1799: }
1800:
1801: public void visit_lcmp(final Instruction inst) {
1802: addOpcode(Opcode.opc_lcmp);
1803: stackHeight -= 3;
1804: }
1805:
1806: public void visit_fcmpl(final Instruction inst) {
1807: addOpcode(Opcode.opc_fcmpl);
1808: stackHeight--;
1809: }
1810:
1811: public void visit_fcmpg(final Instruction inst) {
1812: addOpcode(Opcode.opc_fcmpg);
1813: stackHeight--;
1814: }
1815:
1816: public void visit_dcmpl(final Instruction inst) {
1817: addOpcode(Opcode.opc_dcmpl);
1818: stackHeight -= 3;
1819: }
1820:
1821: public void visit_dcmpg(final Instruction inst) {
1822: addOpcode(Opcode.opc_dcmpg);
1823: stackHeight -= 3;
1824: }
1825:
1826: /*
1827: * Handle long branches.
1828: */
1829: public void visit_ifeq(final Instruction inst) {
1830: if (longBranch) {
1831: final Label tmp = method.newLabel();
1832: addOpcode(Opcode.opc_ifne);
1833: addBranch(tmp);
1834: addOpcode(Opcode.opc_goto_w);
1835: addLongBranch((Label) inst.operand());
1836: addLabel(tmp);
1837: } else {
1838: addOpcode(Opcode.opc_ifeq);
1839: addBranch((Label) inst.operand());
1840: }
1841:
1842: stackHeight--;
1843: }
1844:
1845: public void visit_ifne(final Instruction inst) {
1846: if (longBranch) {
1847: final Label tmp = method.newLabel();
1848: addOpcode(Opcode.opc_ifeq);
1849: addBranch(tmp);
1850: addOpcode(Opcode.opc_goto_w);
1851: addLongBranch((Label) inst.operand());
1852: addLabel(tmp);
1853: } else {
1854: addOpcode(Opcode.opc_ifne);
1855: addBranch((Label) inst.operand());
1856: }
1857:
1858: stackHeight--;
1859: }
1860:
1861: public void visit_iflt(final Instruction inst) {
1862: if (longBranch) {
1863: final Label tmp = method.newLabel();
1864: addOpcode(Opcode.opc_ifge);
1865: addBranch(tmp);
1866: addOpcode(Opcode.opc_goto_w);
1867: addLongBranch((Label) inst.operand());
1868: addLabel(tmp);
1869: } else {
1870: addOpcode(Opcode.opc_iflt);
1871: addBranch((Label) inst.operand());
1872: }
1873:
1874: stackHeight--;
1875: }
1876:
1877: public void visit_ifge(final Instruction inst) {
1878: if (longBranch) {
1879: final Label tmp = method.newLabel();
1880: addOpcode(Opcode.opc_iflt);
1881: addBranch(tmp);
1882: addOpcode(Opcode.opc_goto_w);
1883: addLongBranch((Label) inst.operand());
1884: addLabel(tmp);
1885: } else {
1886: addOpcode(Opcode.opc_ifge);
1887: addBranch((Label) inst.operand());
1888: }
1889:
1890: stackHeight--;
1891: }
1892:
1893: public void visit_ifgt(final Instruction inst) {
1894: if (longBranch) {
1895: final Label tmp = method.newLabel();
1896: addOpcode(Opcode.opc_ifle);
1897: addBranch(tmp);
1898: addOpcode(Opcode.opc_goto_w);
1899: addLongBranch((Label) inst.operand());
1900: addLabel(tmp);
1901: } else {
1902: addOpcode(Opcode.opc_ifgt);
1903: addBranch((Label) inst.operand());
1904: }
1905:
1906: stackHeight--;
1907: }
1908:
1909: public void visit_ifle(final Instruction inst) {
1910: if (longBranch) {
1911: final Label tmp = method.newLabel();
1912: addOpcode(Opcode.opc_ifgt);
1913: addBranch(tmp);
1914: addOpcode(Opcode.opc_goto_w);
1915: addLongBranch((Label) inst.operand());
1916: addLabel(tmp);
1917: } else {
1918: addOpcode(Opcode.opc_ifle);
1919: addBranch((Label) inst.operand());
1920: }
1921:
1922: stackHeight--;
1923: }
1924:
1925: public void visit_if_icmpeq(final Instruction inst) {
1926: if (longBranch) {
1927: final Label tmp = method.newLabel();
1928: addOpcode(Opcode.opc_if_icmpne);
1929: addBranch(tmp);
1930: addOpcode(Opcode.opc_goto_w);
1931: addLongBranch((Label) inst.operand());
1932: addLabel(tmp);
1933: } else {
1934: addOpcode(Opcode.opc_if_icmpeq);
1935: addBranch((Label) inst.operand());
1936: }
1937:
1938: stackHeight -= 2;
1939: }
1940:
1941: public void visit_if_icmpne(final Instruction inst) {
1942: if (longBranch) {
1943: final Label tmp = method.newLabel();
1944: addOpcode(Opcode.opc_if_icmpeq);
1945: addBranch(tmp);
1946: addOpcode(Opcode.opc_goto_w);
1947: addLongBranch((Label) inst.operand());
1948: addLabel(tmp);
1949: } else {
1950: addOpcode(Opcode.opc_if_icmpne);
1951: addBranch((Label) inst.operand());
1952: }
1953:
1954: stackHeight -= 2;
1955: }
1956:
1957: public void visit_if_icmplt(final Instruction inst) {
1958: if (longBranch) {
1959: final Label tmp = method.newLabel();
1960: addOpcode(Opcode.opc_if_icmpge);
1961: addBranch(tmp);
1962: addOpcode(Opcode.opc_goto_w);
1963: addLongBranch((Label) inst.operand());
1964: addLabel(tmp);
1965: } else {
1966: addOpcode(Opcode.opc_if_icmplt);
1967: addBranch((Label) inst.operand());
1968: }
1969:
1970: stackHeight -= 2;
1971: }
1972:
1973: public void visit_if_icmpge(final Instruction inst) {
1974: if (longBranch) {
1975: final Label tmp = method.newLabel();
1976: addOpcode(Opcode.opc_if_icmplt);
1977: addBranch(tmp);
1978: addOpcode(Opcode.opc_goto_w);
1979: addLongBranch((Label) inst.operand());
1980: addLabel(tmp);
1981: } else {
1982: addOpcode(Opcode.opc_if_icmpge);
1983: addBranch((Label) inst.operand());
1984: }
1985:
1986: stackHeight -= 2;
1987: }
1988:
1989: public void visit_if_icmpgt(final Instruction inst) {
1990: if (longBranch) {
1991: final Label tmp = method.newLabel();
1992: addOpcode(Opcode.opc_if_icmple);
1993: addBranch(tmp);
1994: addOpcode(Opcode.opc_goto_w);
1995: addLongBranch((Label) inst.operand());
1996: addLabel(tmp);
1997: } else {
1998: addOpcode(Opcode.opc_if_icmpgt);
1999: addBranch((Label) inst.operand());
2000: }
2001:
2002: stackHeight -= 2;
2003: }
2004:
2005: public void visit_if_icmple(final Instruction inst) {
2006: if (longBranch) {
2007: final Label tmp = method.newLabel();
2008: addOpcode(Opcode.opc_if_icmpgt);
2009: addBranch(tmp);
2010: addOpcode(Opcode.opc_goto_w);
2011: addLongBranch((Label) inst.operand());
2012: addLabel(tmp);
2013: } else {
2014: addOpcode(Opcode.opc_if_icmple);
2015: addBranch((Label) inst.operand());
2016: }
2017:
2018: stackHeight -= 2;
2019: }
2020:
2021: public void visit_if_acmpeq(final Instruction inst) {
2022: if (longBranch) {
2023: final Label tmp = method.newLabel();
2024: addOpcode(Opcode.opc_if_acmpne);
2025: addBranch(tmp);
2026: addOpcode(Opcode.opc_goto_w);
2027: addLongBranch((Label) inst.operand());
2028: addLabel(tmp);
2029: } else {
2030: addOpcode(Opcode.opc_if_acmpeq);
2031: addBranch((Label) inst.operand());
2032: }
2033:
2034: stackHeight -= 2;
2035: }
2036:
2037: public void visit_if_acmpne(final Instruction inst) {
2038: if (longBranch) {
2039: final Label tmp = method.newLabel();
2040: addOpcode(Opcode.opc_if_acmpeq);
2041: addBranch(tmp);
2042: addOpcode(Opcode.opc_goto_w);
2043: addLongBranch((Label) inst.operand());
2044: addLabel(tmp);
2045: } else {
2046: addOpcode(Opcode.opc_if_acmpne);
2047: addBranch((Label) inst.operand());
2048: }
2049:
2050: stackHeight -= 2;
2051: }
2052:
2053: public void visit_goto(final Instruction inst) {
2054: if (longBranch) {
2055: addOpcode(Opcode.opc_goto_w);
2056: addLongBranch((Label) inst.operand());
2057: } else {
2058: addOpcode(Opcode.opc_goto);
2059: addBranch((Label) inst.operand());
2060: }
2061:
2062: stackHeight += 0;
2063: }
2064:
2065: public void visit_jsr(final Instruction inst) {
2066: if (longBranch) {
2067: addOpcode(Opcode.opc_jsr_w);
2068: addLongBranch((Label) inst.operand());
2069: } else {
2070: addOpcode(Opcode.opc_jsr);
2071: addBranch((Label) inst.operand());
2072: }
2073:
2074: stackHeight++;
2075: }
2076:
2077: public void visit_ret(final Instruction inst) {
2078: final int index = ((LocalVariable) inst.operand()).index();
2079:
2080: if (index + 1 > maxLocals) {
2081: maxLocals = index + 1;
2082: }
2083:
2084: if (index < 256) {
2085: addOpcode(Opcode.opc_ret);
2086: addByte(index);
2087: } else {
2088: addOpcode(Opcode.opc_wide);
2089: addByte(Opcode.opc_ret);
2090: addShort(index);
2091: }
2092:
2093: stackHeight += 0;
2094: }
2095:
2096: public void visit_switch(final Instruction inst) {
2097: final Switch sw = (Switch) inst.operand();
2098:
2099: final int[] values = sw.values();
2100: final Label[] targets = sw.targets();
2101:
2102: if (values.length == 0) {
2103: if (longBranch) {
2104: addOpcode(Opcode.opc_pop); // Pop switch "index" off stack
2105: addOpcode(Opcode.opc_goto_w);
2106: addLongBranch(sw.defaultTarget());
2107: } else {
2108: addOpcode(Opcode.opc_pop); // Pop switch "index" off stack
2109: addOpcode(Opcode.opc_goto);
2110: addBranch(sw.defaultTarget());
2111: }
2112: } else if (sw.hasContiguousValues()) {
2113: addOpcode(Opcode.opc_tableswitch);
2114: addLongBranch(sw.defaultTarget());
2115:
2116: addInt(values[0]);
2117: addInt(values[values.length - 1]);
2118:
2119: for (int i = 0; i < targets.length; i++) {
2120: addLongBranch(targets[i]);
2121: }
2122: } else {
2123: addOpcode(Opcode.opc_lookupswitch);
2124: addLongBranch(sw.defaultTarget());
2125:
2126: addInt(values.length);
2127:
2128: for (int i = 0; i < targets.length; i++) {
2129: addInt(values[i]);
2130: addLongBranch(targets[i]);
2131: }
2132: }
2133:
2134: stackHeight--;
2135: }
2136:
2137: public void visit_ireturn(final Instruction inst) {
2138: addOpcode(Opcode.opc_ireturn);
2139: stackHeight = 0;
2140: }
2141:
2142: public void visit_lreturn(final Instruction inst) {
2143: addOpcode(Opcode.opc_lreturn);
2144: stackHeight = 0;
2145: }
2146:
2147: public void visit_freturn(final Instruction inst) {
2148: addOpcode(Opcode.opc_freturn);
2149: stackHeight = 0;
2150: }
2151:
2152: public void visit_dreturn(final Instruction inst) {
2153: addOpcode(Opcode.opc_dreturn);
2154: stackHeight = 0;
2155: }
2156:
2157: public void visit_areturn(final Instruction inst) {
2158: addOpcode(Opcode.opc_areturn);
2159: stackHeight = 0;
2160: }
2161:
2162: public void visit_return(final Instruction inst) {
2163: addOpcode(Opcode.opc_return);
2164: stackHeight = 0;
2165: }
2166:
2167: public void visit_getstatic(final Instruction inst) {
2168: final int index = constants.addConstant(Constant.FIELD_REF,
2169: inst.operand());
2170: addOpcode(Opcode.opc_getstatic);
2171: addShort(index);
2172:
2173: final Type type = ((MemberRef) inst.operand()).nameAndType()
2174: .type();
2175: stackHeight += type.stackHeight();
2176: }
2177:
2178: public void visit_putstatic(final Instruction inst) {
2179: final int index = constants.addConstant(Constant.FIELD_REF,
2180: inst.operand());
2181: addOpcode(Opcode.opc_putstatic);
2182: addShort(index);
2183:
2184: final Type type = ((MemberRef) inst.operand()).nameAndType()
2185: .type();
2186: stackHeight -= type.stackHeight();
2187: }
2188:
2189: public void visit_putstatic_nowb(final Instruction inst) {
2190: final int index = constants.addConstant(Constant.FIELD_REF,
2191: inst.operand());
2192: addOpcode(Opcode.opc_putstatic_nowb);
2193: addShort(index);
2194:
2195: final Type type = ((MemberRef) inst.operand()).nameAndType()
2196: .type();
2197: stackHeight -= type.stackHeight();
2198: }
2199:
2200: public void visit_getfield(final Instruction inst) {
2201: final int index = constants.addConstant(Constant.FIELD_REF,
2202: inst.operand());
2203: addOpcode(Opcode.opc_getfield);
2204: addShort(index);
2205:
2206: final Type type = ((MemberRef) inst.operand()).nameAndType()
2207: .type();
2208: stackHeight += type.stackHeight() - 1;
2209: }
2210:
2211: public void visit_putfield(final Instruction inst) {
2212: final int index = constants.addConstant(Constant.FIELD_REF,
2213: inst.operand());
2214: addOpcode(Opcode.opc_putfield);
2215: addShort(index);
2216:
2217: final Type type = ((MemberRef) inst.operand()).nameAndType()
2218: .type();
2219: stackHeight -= type.stackHeight() + 1;
2220: }
2221:
2222: public void visit_putfield_nowb(final Instruction inst) {
2223: final int index = constants.addConstant(Constant.FIELD_REF,
2224: inst.operand());
2225: addOpcode(Opcode.opc_putfield_nowb);
2226: addShort(index);
2227:
2228: final Type type = ((MemberRef) inst.operand()).nameAndType()
2229: .type();
2230: stackHeight -= type.stackHeight() + 1;
2231: }
2232:
2233: public void visit_invokevirtual(final Instruction inst) {
2234: final int index = constants.addConstant(Constant.METHOD_REF,
2235: inst.operand());
2236: addOpcode(Opcode.opc_invokevirtual);
2237: addShort(index);
2238:
2239: final MemberRef method = (MemberRef) inst.operand();
2240: final Type type = method.nameAndType().type();
2241:
2242: stackHeight += type.returnType().stackHeight()
2243: - type.stackHeight() - 1;
2244: }
2245:
2246: public void visit_invokespecial(final Instruction inst) {
2247: final int index = constants.addConstant(Constant.METHOD_REF,
2248: inst.operand());
2249: addOpcode(Opcode.opc_invokespecial);
2250: addShort(index);
2251:
2252: final MemberRef method = (MemberRef) inst.operand();
2253: final Type type = method.nameAndType().type();
2254:
2255: stackHeight += type.returnType().stackHeight()
2256: - type.stackHeight() - 1;
2257: }
2258:
2259: public void visit_invokestatic(final Instruction inst) {
2260: final int index = constants.addConstant(Constant.METHOD_REF,
2261: inst.operand());
2262: addOpcode(Opcode.opc_invokestatic);
2263: addShort(index);
2264:
2265: final MemberRef method = (MemberRef) inst.operand();
2266: final Type type = method.nameAndType().type();
2267:
2268: Assert.isTrue(type.isMethod(),
2269: "Trying to invoke a type that is not a method: "
2270: + method);
2271:
2272: stackHeight += type.returnType().stackHeight()
2273: - type.stackHeight();
2274: }
2275:
2276: public void visit_invokeinterface(final Instruction inst) {
2277: final int index = constants.addConstant(
2278: Constant.INTERFACE_METHOD_REF, inst.operand());
2279: final MemberRef method = (MemberRef) constants
2280: .constantAt(index);
2281: final Type type = method.nameAndType().type();
2282:
2283: addOpcode(Opcode.opc_invokeinterface);
2284: addShort(index);
2285: addByte(type.stackHeight() + 1);
2286: addByte(0);
2287:
2288: stackHeight += type.returnType().stackHeight()
2289: - type.stackHeight() - 1;
2290: }
2291:
2292: public void visit_new(final Instruction inst) {
2293: final int index = constants.addConstant(Constant.CLASS, inst
2294: .operand());
2295: addOpcode(Opcode.opc_new);
2296: addShort(index);
2297:
2298: stackHeight++;
2299: }
2300:
2301: public void visit_newarray(final Instruction inst) {
2302: final Type type = (Type) inst.operand();
2303:
2304: if (type.isReference()) {
2305: final int index = constants.addConstant(Constant.CLASS,
2306: type);
2307: addOpcode(Opcode.opc_anewarray);
2308: addShort(index);
2309: } else {
2310: addOpcode(Opcode.opc_newarray);
2311: addByte(type.typeCode());
2312: }
2313:
2314: stackHeight += 0;
2315: }
2316:
2317: public void visit_arraylength(final Instruction inst) {
2318: addOpcode(Opcode.opc_arraylength);
2319: stackHeight += 0;
2320: }
2321:
2322: public void visit_athrow(final Instruction inst) {
2323: addOpcode(Opcode.opc_athrow);
2324: stackHeight = 0;
2325: }
2326:
2327: public void visit_checkcast(final Instruction inst) {
2328: final int index = constants.addConstant(Constant.CLASS, inst
2329: .operand());
2330: addOpcode(Opcode.opc_checkcast);
2331: addShort(index);
2332: stackHeight += 0;
2333: }
2334:
2335: public void visit_instanceof (final Instruction inst) {
2336: final int index = constants.addConstant(Constant.CLASS, inst
2337: .operand());
2338: addOpcode(Opcode.opc_instanceof );
2339: addShort(index);
2340: stackHeight += 0;
2341: }
2342:
2343: public void visit_monitorenter(final Instruction inst) {
2344: addOpcode(Opcode.opc_monitorenter);
2345: stackHeight--;
2346: }
2347:
2348: public void visit_monitorexit(final Instruction inst) {
2349: addOpcode(Opcode.opc_monitorexit);
2350: stackHeight--;
2351: }
2352:
2353: public void visit_multianewarray(final Instruction inst) {
2354: final MultiArrayOperand operand = (MultiArrayOperand) inst
2355: .operand();
2356: final Type type = operand.type();
2357: final int dim = operand.dimensions();
2358: final int index = constants.addConstant(Constant.CLASS, type);
2359: addOpcode(Opcode.opc_multianewarray);
2360: addShort(index);
2361: addByte(dim);
2362:
2363: stackHeight += 1 - dim;
2364: }
2365:
2366: public void visit_ifnull(final Instruction inst) {
2367: if (longBranch) {
2368: final Label tmp = method.newLabel();
2369: addOpcode(Opcode.opc_ifnonnull);
2370: addBranch(tmp);
2371: addOpcode(Opcode.opc_goto_w);
2372: addLongBranch((Label) inst.operand());
2373: addLabel(tmp);
2374: } else {
2375: addOpcode(Opcode.opc_ifnull);
2376: addBranch((Label) inst.operand());
2377: }
2378:
2379: stackHeight--;
2380: }
2381:
2382: public void visit_ifnonnull(final Instruction inst) {
2383: if (longBranch) {
2384: final Label tmp = method.newLabel();
2385: addOpcode(Opcode.opc_ifnull);
2386: addBranch(tmp);
2387: addOpcode(Opcode.opc_goto_w);
2388: addLongBranch((Label) inst.operand());
2389: addLabel(tmp);
2390: } else {
2391: addOpcode(Opcode.opc_ifnonnull);
2392: addBranch((Label) inst.operand());
2393: }
2394:
2395: stackHeight--;
2396: }
2397:
2398: public void visit_rc(final Instruction inst) {
2399: final Integer operand = (Integer) inst.operand();
2400: addOpcode(Opcode.opc_rc);
2401: addByte(operand.intValue());
2402: stackHeight += 0;
2403: }
2404:
2405: public void visit_aswizzle(final Instruction inst) {
2406: addOpcode(Opcode.opc_aswizzle);
2407: stackHeight -= 2;
2408: }
2409:
2410: public void visit_aswrange(final Instruction inst) {
2411: addOpcode(Opcode.opc_aswrange);
2412: stackHeight -= 3;
2413: }
2414:
2415: public void visit_aupdate(final Instruction inst) {
2416: final Integer operand = (Integer) inst.operand();
2417: addOpcode(Opcode.opc_aupdate);
2418: addByte(operand.intValue());
2419: stackHeight += 0;
2420: }
2421:
2422: public void visit_supdate(final Instruction inst) {
2423: final Integer operand = (Integer) inst.operand();
2424: addOpcode(Opcode.opc_supdate);
2425: addByte(operand.intValue());
2426: stackHeight += 0;
2427: }
2428:
2429: /**
2430: * Represents the height of the stack at given Label.
2431: */
2432: class HeightRecord {
2433: Label label;
2434:
2435: int height;
2436:
2437: public HeightRecord(final Label label, final int height) {
2438: if (ClassEditor.DEBUG || CodeArray.DEBUG) {
2439: System.out.println(" push " + label + " at "
2440: + height);
2441: }
2442:
2443: this .label = label;
2444: this .height = height;
2445: }
2446: }
2447:
2448: /**
2449: * Used to represent the byte array.
2450: */
2451: class ByteCell {
2452: byte value;
2453:
2454: ByteCell prev;
2455: }
2456: }
|