diff -r 83f679127b97 -r fb0286d50ed8 jdk/test/tools/pack200/pack200-verifier/src/xmlkit/InstructionAssembler.java --- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/InstructionAssembler.java Sun Apr 22 19:09:02 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,464 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code 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 - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*- - -import xmlkit.XMLKit.Element; -import java.util.HashMap; -/* - * @author jrose - */ -abstract class InstructionAssembler extends InstructionSyntax { - - InstructionAssembler() { - } - - public static String assemble(Element instructions, String pcAttrName, - ClassSyntax.GetCPIndex getCPI) { - int insCount = instructions.size(); - Element[] insElems = new Element[insCount]; - int[] elemToIndexMap; - int[] insLocs; - byte[] ops = new byte[insCount]; - int[] operands = new int[insCount]; - boolean[] isWide = new boolean[insCount]; - int[] branches; - int[] branchInsLocs; - HashMap labels = new HashMap(); - - final int WIDE = 0xc4; - final int GOTO = 0xa7; - final int GOTO_W = 0xc8; - final int GOTO_LEN = 3; - final int GOTO_W_LEN = 5; - assert ("wide".equals(bcNames[WIDE])); - assert ("goto".equals(bcNames[GOTO])); - assert ("goto_w".equals(bcNames[GOTO_W])); - assert (bcFormats[GOTO].length() == GOTO_LEN); - assert (bcFormats[GOTO_W].length() == GOTO_W_LEN); - - // Unpack instructions into temp. arrays, and find branches and labels. - { - elemToIndexMap = (pcAttrName != null) ? new int[insCount] : null; - int[] buffer = operands; - int id = 0; - int branchCount = 0; - for (int i = 0; i < insCount; i++) { - Element ins = (Element) instructions.get(i); - if (elemToIndexMap != null) { - elemToIndexMap[i] = (ins.getAttr(pcAttrName) != null ? id : -1); - } - String lab = ins.getAttr("pc"); - if (lab != null) { - labels.put(lab, String.valueOf(id)); - } - int op = opCode(ins.getName()); - if (op < 0) { - assert (ins.getAttr(pcAttrName) != null - || ins.getName().equals("label")); - continue; // delete PC holder element - } - if (op == WIDE) { //0xc4 - isWide[id] = true; // force wide format - continue; - } - if (bcFormats[op].indexOf('o') >= 0) { - buffer[branchCount++] = id; - } - if (bcFormats[op] == bcWideFormats[op]) { - isWide[id] = false; - } - insElems[id] = ins; - ops[id] = (byte) op; - id++; - } - insCount = id; // maybe we deleted some wide prefixes, etc. - branches = new int[branchCount + 1]; - System.arraycopy(buffer, 0, branches, 0, branchCount); - branches[branchCount] = -1; // sentinel - } - - // Compute instruction sizes. These sizes are final, - // except for branch instructions, which may need lengthening. - // Some instructions (ldc, bipush, iload, iinc) are automagically widened. - insLocs = new int[insCount + 1]; - int loc = 0; - for (int bn = 0, id = 0; id < insCount; id++) { - insLocs[id] = loc; - Element ins = insElems[id]; - int op = ops[id] & 0xFF; - String format = opFormat(op, isWide[id]); - // Make sure operands fit within the given format. - for (int j = 1, jlimit = format.length(); j < jlimit; j++) { - char fc = format.charAt(j); - int x = 0; - switch (fc) { - case 'l': - x = (int) ins.getAttrLong("loc"); - assert (x >= 0); - if (x > 0xFF && !isWide[id]) { - isWide[id] = true; - format = opFormat(op, isWide[id]); - } - assert (x <= 0xFFFF); - break; - case 'k': - char fc2 = format.charAt(Math.min(j + 1, format.length() - 1)); - x = getCPIndex(ins, fc2, getCPI); - if (x > 0xFF && j == jlimit - 1) { - assert (op == 0x12); //ldc - ops[id] = (byte) (op = 0x13); //ldc_w - format = opFormat(op); - } - assert (x <= 0xFFFF); - j++; // skip type-of-constant marker - break; - case 'x': - x = (int) ins.getAttrLong("num"); - assert (x >= 0 && x <= ((j == jlimit - 1) ? 0xFF : 0xFFFF)); - break; - case 's': - x = (int) ins.getAttrLong("num"); - if (x != (byte) x && j == jlimit - 1) { - switch (op) { - case 0x10: //bipush - ops[id] = (byte) (op = 0x11); //sipush - break; - case 0x84: //iinc - isWide[id] = true; - format = opFormat(op, isWide[id]); - break; - default: - assert (false); // cannot lengthen - } - } - // unsign the value now, to make later steps clearer - if (j == jlimit - 1) { - assert (x == (byte) x); - x = x & 0xFF; - } else { - assert (x == (short) x); - x = x & 0xFFFF; - } - break; - case 'o': - assert (branches[bn] == id); - bn++; - // make local copies of the branches, and fix up labels - insElems[id] = ins = new Element(ins); - String newLab = labels.get(ins.getAttr("lab")); - assert (newLab != null); - ins.setAttr("lab", newLab); - int prevCas = 0; - int k = 0; - for (Element cas : ins.elements()) { - assert (cas.getName().equals("Case")); - ins.set(k++, cas = new Element(cas)); - newLab = labels.get(cas.getAttr("lab")); - assert (newLab != null); - cas.setAttr("lab", newLab); - int thisCas = (int) cas.getAttrLong("num"); - assert (op == 0xab - || op == 0xaa && (k == 0 || thisCas == prevCas + 1)); - prevCas = thisCas; - } - break; - case 't': - // switch table is represented as Switch.Case sub-elements - break; - default: - assert (false); - } - operands[id] = x; // record operand (last if there are 2) - // skip redundant chars - while (j + 1 < jlimit && format.charAt(j + 1) == fc) { - ++j; - } - } - - switch (op) { - case 0xaa: //tableswitch - loc = switchBase(loc); - loc += 4 * (3 + ins.size()); - break; - case 0xab: //lookupswitch - loc = switchBase(loc); - loc += 4 * (2 + 2 * ins.size()); - break; - default: - if (isWide[id]) { - loc++; // 'wide' opcode prefix - } - loc += format.length(); - break; - } - } - insLocs[insCount] = loc; - - // compute branch offsets, and see if any branches need expansion - for (int maxTries = 9, tries = 0;; ++tries) { - boolean overflowing = false; - boolean[] branchExpansions = null; - for (int bn = 0; bn < branches.length - 1; bn++) { - int id = branches[bn]; - Element ins = insElems[id]; - int insSize = insLocs[id + 1] - insLocs[id]; - int origin = insLocs[id]; - int target = insLocs[(int) ins.getAttrLong("lab")]; - int offset = target - origin; - operands[id] = offset; - //System.out.println("branch id="+id+" len="+insSize+" to="+target+" offset="+offset); - assert (insSize == GOTO_LEN || insSize == GOTO_W_LEN || ins.getName().indexOf("switch") > 0); - boolean thisOverflow = (insSize == GOTO_LEN && (offset != (short) offset)); - if (thisOverflow && !overflowing) { - overflowing = true; - branchExpansions = new boolean[branches.length]; - } - if (thisOverflow || tries == maxTries - 1) { - // lengthen the branch - assert (!(thisOverflow && isWide[id])); - isWide[id] = true; - branchExpansions[bn] = true; - } - } - if (!overflowing) { - break; // done, usually on first try - } - assert (tries <= maxTries); - - // Walk over all instructions, expanding branches and updating locations. - int fixup = 0; - for (int bn = 0, id = 0; id < insCount; id++) { - insLocs[id] += fixup; - if (branches[bn] == id) { - int op = ops[id] & 0xFF; - int wop; - boolean invert; - if (branchExpansions[bn]) { - switch (op) { - case GOTO: //0xa7 - wop = GOTO_W; //0xc8 - invert = false; - break; - case 0xa8: //jsr - wop = 0xc9; //jsr_w - invert = false; - break; - default: - wop = invertBranchOp(op); - invert = true; - break; - } - assert (op != wop); - ops[id] = (byte) wop; - isWide[id] = invert; - if (invert) { - fixup += GOTO_W_LEN; //branch around a wide goto - } else { - fixup += (GOTO_W_LEN - GOTO_LEN); - } - // done expanding: ops and isWide reflect the decision - } - bn++; - } - } - insLocs[insCount] += fixup; - } - // we know the layout now - - // notify the caller of offsets, if requested - if (elemToIndexMap != null) { - for (int i = 0; i < elemToIndexMap.length; i++) { - int id = elemToIndexMap[i]; - if (id >= 0) { - Element ins = (Element) instructions.get(i); - ins.setAttr(pcAttrName, "" + insLocs[id]); - } - } - elemToIndexMap = null; // release the pointer - } - - // output the bytes - StringBuffer sbuf = new StringBuffer(insLocs[insCount]); - for (int bn = 0, id = 0; id < insCount; id++) { - //System.out.println("output id="+id+" loc="+insLocs[id]+" len="+(insLocs[id+1]-insLocs[id])+" #sbuf="+sbuf.length()); - assert (sbuf.length() == insLocs[id]); - Element ins; - int pc = insLocs[id]; - int nextpc = insLocs[id + 1]; - int op = ops[id] & 0xFF; - int opnd = operands[id]; - String format; - if (branches[bn] == id) { - bn++; - sbuf.append((char) op); - if (isWide[id]) { - // emit