0N/A/*
2362N/A * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.tools.asm;
0N/A
0N/Aimport sun.tools.java.*;
0N/Aimport java.util.Enumeration;
0N/Aimport java.io.IOException;
0N/Aimport java.io.DataOutputStream;
0N/Aimport java.io.PrintStream;
0N/Aimport java.util.Vector;
0N/A// JCOV
0N/Aimport sun.tools.javac.*;
0N/Aimport java.io.File;
0N/Aimport java.io.BufferedInputStream;
0N/Aimport java.io.DataInputStream;
0N/Aimport java.io.FileInputStream;
0N/Aimport java.io.FileNotFoundException;
0N/Aimport java.io.FileOutputStream;
0N/Aimport java.lang.String;
0N/A// end JCOV
0N/A
0N/A/**
0N/A * This class is used to assemble the bytecode instructions for a method.
0N/A *
0N/A * WARNING: The contents of this source file are not part of any
0N/A * supported API. Code that depends on them does so at its own risk:
0N/A * they are subject to change or removal without notice.
0N/A *
0N/A * @author Arthur van Hoff
0N/A */
0N/Apublic final
0N/Aclass Assembler implements Constants {
0N/A static final int NOTREACHED = 0;
0N/A static final int REACHED = 1;
0N/A static final int NEEDED = 2;
0N/A
0N/A Label first = new Label();
0N/A Instruction last = first;
0N/A int maxdepth;
0N/A int maxvar;
0N/A int maxpc;
0N/A
0N/A /**
0N/A * Add an instruction
0N/A */
0N/A public void add(Instruction inst) {
0N/A if (inst != null) {
0N/A last.next = inst;
0N/A last = inst;
0N/A }
0N/A }
0N/A public void add(long where, int opc) {
0N/A add(new Instruction(where, opc, null));
0N/A }
0N/A public void add(long where, int opc, Object obj) {
0N/A add(new Instruction(where, opc, obj));
0N/A }
0N/A// JCOV
0N/A public void add(long where, int opc, Object obj, boolean flagCondInverted) {
0N/A add(new Instruction(where, opc, obj, flagCondInverted));
0N/A }
0N/A
0N/A public void add(boolean flagNoCovered, long where, int opc, Object obj) {
0N/A add(new Instruction(flagNoCovered, where, opc, obj));
0N/A }
0N/A
0N/A public void add(long where, int opc, boolean flagNoCovered) {
0N/A add(new Instruction(where, opc, flagNoCovered));
0N/A }
0N/A
0N/A static Vector SourceClassList = new Vector();
0N/A
0N/A static Vector TmpCovTable = new Vector();
0N/A
0N/A static int[] JcovClassCountArray = new int[CT_LAST_KIND + 1];
0N/A
0N/A static String JcovMagicLine = "JCOV-DATA-FILE-VERSION: 2.0";
0N/A static String JcovClassLine = "CLASS: ";
0N/A static String JcovSrcfileLine = "SRCFILE: ";
0N/A static String JcovTimestampLine = "TIMESTAMP: ";
0N/A static String JcovDataLine = "DATA: ";
0N/A static String JcovHeadingLine = "#kind\tcount";
0N/A
0N/A static int[] arrayModifiers =
0N/A {M_PUBLIC, M_PRIVATE, M_PROTECTED, M_ABSTRACT, M_FINAL, M_INTERFACE};
0N/A static int[] arrayModifiersOpc =
0N/A {PUBLIC, PRIVATE, PROTECTED, ABSTRACT, FINAL, INTERFACE};
0N/A//end JCOV
0N/A
0N/A /**
0N/A * Optimize instructions and mark those that can be reached
0N/A */
0N/A void optimize(Environment env, Label lbl) {
0N/A lbl.pc = REACHED;
0N/A
0N/A for (Instruction inst = lbl.next ; inst != null ; inst = inst.next) {
0N/A switch (inst.pc) {
0N/A case NOTREACHED:
0N/A inst.optimize(env);
0N/A inst.pc = REACHED;
0N/A break;
0N/A case REACHED:
0N/A return;
0N/A case NEEDED:
0N/A break;
0N/A }
0N/A
0N/A switch (inst.opc) {
0N/A case opc_label:
0N/A case opc_dead:
0N/A if (inst.pc == REACHED) {
0N/A inst.pc = NOTREACHED;
0N/A }
0N/A break;
0N/A
0N/A case opc_ifeq:
0N/A case opc_ifne:
0N/A case opc_ifgt:
0N/A case opc_ifge:
0N/A case opc_iflt:
0N/A case opc_ifle:
0N/A case opc_if_icmpeq:
0N/A case opc_if_icmpne:
0N/A case opc_if_icmpgt:
0N/A case opc_if_icmpge:
0N/A case opc_if_icmplt:
0N/A case opc_if_icmple:
0N/A case opc_if_acmpeq:
0N/A case opc_if_acmpne:
0N/A case opc_ifnull:
0N/A case opc_ifnonnull:
0N/A optimize(env, (Label)inst.value);
0N/A break;
0N/A
0N/A case opc_goto:
0N/A optimize(env, (Label)inst.value);
0N/A return;
0N/A
0N/A case opc_jsr:
0N/A optimize(env, (Label)inst.value);
0N/A break;
0N/A
0N/A case opc_ret:
0N/A case opc_return:
0N/A case opc_ireturn:
0N/A case opc_lreturn:
0N/A case opc_freturn:
0N/A case opc_dreturn:
0N/A case opc_areturn:
0N/A case opc_athrow:
0N/A return;
0N/A
0N/A case opc_tableswitch:
0N/A case opc_lookupswitch: {
0N/A SwitchData sw = (SwitchData)inst.value;
0N/A optimize(env, sw.defaultLabel);
0N/A for (Enumeration e = sw.tab.elements() ; e.hasMoreElements();) {
0N/A optimize(env, (Label)e.nextElement());
0N/A }
0N/A return;
0N/A }
0N/A
0N/A case opc_try: {
0N/A TryData td = (TryData)inst.value;
0N/A td.getEndLabel().pc = NEEDED;
0N/A for (Enumeration e = td.catches.elements() ; e.hasMoreElements();) {
0N/A CatchData cd = (CatchData)e.nextElement();
0N/A optimize(env, cd.getLabel());
0N/A }
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Eliminate instructions that are not reached
0N/A */
0N/A boolean eliminate() {
0N/A boolean change = false;
0N/A Instruction prev = first;
0N/A
0N/A for (Instruction inst = first.next ; inst != null ; inst = inst.next) {
0N/A if (inst.pc != NOTREACHED) {
0N/A prev.next = inst;
0N/A prev = inst;
0N/A inst.pc = NOTREACHED;
0N/A } else {
0N/A change = true;
0N/A }
0N/A }
0N/A first.pc = NOTREACHED;
0N/A prev.next = null;
0N/A return change;
0N/A }
0N/A
0N/A /**
0N/A * Optimize the byte codes
0N/A */
0N/A public void optimize(Environment env) {
0N/A //listing(System.out);
0N/A do {
0N/A // Figure out which instructions are reached
0N/A optimize(env, first);
0N/A
0N/A // Eliminate instructions that are not reached
0N/A } while (eliminate() && env.opt());
0N/A }
0N/A
0N/A /**
0N/A * Collect all constants into the constant table
0N/A */
0N/A public void collect(Environment env, MemberDefinition field, ConstantPool tab) {
0N/A // Collect constants for arguments only
0N/A // if a local variable table is generated
0N/A if ((field != null) && env.debug_vars()) {
0N/A if (field.getArguments() != null) {
0N/A for (Enumeration e = field.getArguments().elements() ; e.hasMoreElements() ;) {
0N/A MemberDefinition f = (MemberDefinition)e.nextElement();
0N/A tab.put(f.getName().toString());
0N/A tab.put(f.getType().getTypeSignature());
0N/A }
0N/A }
0N/A }
0N/A
0N/A // Collect constants from the instructions
0N/A for (Instruction inst = first ; inst != null ; inst = inst.next) {
0N/A inst.collect(tab);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Determine stack size, count local variables
0N/A */
0N/A void balance(Label lbl, int depth) {
0N/A for (Instruction inst = lbl ; inst != null ; inst = inst.next) {
0N/A //Environment.debugOutput(inst.toString() + ": " + depth + " => " +
0N/A // (depth + inst.balance()));
0N/A depth += inst.balance();
0N/A if (depth < 0) {
0N/A throw new CompilerError("stack under flow: " + inst.toString() + " = " + depth);
0N/A }
0N/A if (depth > maxdepth) {
0N/A maxdepth = depth;
0N/A }
0N/A switch (inst.opc) {
0N/A case opc_label:
0N/A lbl = (Label)inst;
0N/A if (inst.pc == REACHED) {
0N/A if (lbl.depth != depth) {
0N/A throw new CompilerError("stack depth error " +
0N/A depth + "/" + lbl.depth +
0N/A ": " + inst.toString());
0N/A }
0N/A return;
0N/A }
0N/A lbl.pc = REACHED;
0N/A lbl.depth = depth;
0N/A break;
0N/A
0N/A case opc_ifeq:
0N/A case opc_ifne:
0N/A case opc_ifgt:
0N/A case opc_ifge:
0N/A case opc_iflt:
0N/A case opc_ifle:
0N/A case opc_if_icmpeq:
0N/A case opc_if_icmpne:
0N/A case opc_if_icmpgt:
0N/A case opc_if_icmpge:
0N/A case opc_if_icmplt:
0N/A case opc_if_icmple:
0N/A case opc_if_acmpeq:
0N/A case opc_if_acmpne:
0N/A case opc_ifnull:
0N/A case opc_ifnonnull:
0N/A balance((Label)inst.value, depth);
0N/A break;
0N/A
0N/A case opc_goto:
0N/A balance((Label)inst.value, depth);
0N/A return;
0N/A
0N/A case opc_jsr:
0N/A balance((Label)inst.value, depth + 1);
0N/A break;
0N/A
0N/A case opc_ret:
0N/A case opc_return:
0N/A case opc_ireturn:
0N/A case opc_lreturn:
0N/A case opc_freturn:
0N/A case opc_dreturn:
0N/A case opc_areturn:
0N/A case opc_athrow:
0N/A return;
0N/A
0N/A case opc_iload:
0N/A case opc_fload:
0N/A case opc_aload:
0N/A case opc_istore:
0N/A case opc_fstore:
0N/A case opc_astore: {
0N/A int v = ((inst.value instanceof Number)
0N/A ? ((Number)inst.value).intValue()
0N/A : ((LocalVariable)inst.value).slot) + 1;
0N/A if (v > maxvar)
0N/A maxvar = v;
0N/A break;
0N/A }
0N/A
0N/A case opc_lload:
0N/A case opc_dload:
0N/A case opc_lstore:
0N/A case opc_dstore: {
0N/A int v = ((inst.value instanceof Number)
0N/A ? ((Number)inst.value).intValue()
0N/A : ((LocalVariable)inst.value).slot) + 2;
0N/A if (v > maxvar)
0N/A maxvar = v;
0N/A break;
0N/A }
0N/A
0N/A case opc_iinc: {
0N/A int v = ((int[])inst.value)[0] + 1;
0N/A if (v > maxvar)
0N/A maxvar = v + 1;
0N/A break;
0N/A }
0N/A
0N/A case opc_tableswitch:
0N/A case opc_lookupswitch: {
0N/A SwitchData sw = (SwitchData)inst.value;
0N/A balance(sw.defaultLabel, depth);
0N/A for (Enumeration e = sw.tab.elements() ; e.hasMoreElements();) {
0N/A balance((Label)e.nextElement(), depth);
0N/A }
0N/A return;
0N/A }
0N/A
0N/A case opc_try: {
0N/A TryData td = (TryData)inst.value;
0N/A for (Enumeration e = td.catches.elements() ; e.hasMoreElements();) {
0N/A CatchData cd = (CatchData)e.nextElement();
0N/A balance(cd.getLabel(), depth + 1);
0N/A }
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Generate code
0N/A */
0N/A public void write(Environment env, DataOutputStream out,
0N/A MemberDefinition field, ConstantPool tab)
0N/A throws IOException {
0N/A //listing(System.out);
0N/A
0N/A if ((field != null) && field.getArguments() != null) {
0N/A int sum = 0;
0N/A Vector v = field.getArguments();
0N/A for (Enumeration e = v.elements(); e.hasMoreElements(); ) {
0N/A MemberDefinition f = ((MemberDefinition)e.nextElement());
0N/A sum += f.getType().stackSize();
0N/A }
0N/A maxvar = sum;
0N/A }
0N/A
0N/A // Make sure the stack balances. Also calculate maxvar and maxstack
0N/A try {
0N/A balance(first, 0);
0N/A } catch (CompilerError e) {
0N/A System.out.println("ERROR: " + e);
0N/A listing(System.out);
0N/A throw e;
0N/A }
0N/A
0N/A // Assign PCs
0N/A int pc = 0, nexceptions = 0;
0N/A for (Instruction inst = first ; inst != null ; inst = inst.next) {
0N/A inst.pc = pc;
0N/A int sz = inst.size(tab);
0N/A if (pc<65536 && (pc+sz)>=65536) {
0N/A env.error(inst.where, "warn.method.too.long");
0N/A }
0N/A pc += sz;
0N/A
0N/A if (inst.opc == opc_try) {
0N/A nexceptions += ((TryData)inst.value).catches.size();
0N/A }
0N/A }
0N/A
0N/A // Write header
0N/A out.writeShort(maxdepth);
0N/A out.writeShort(maxvar);
0N/A out.writeInt(maxpc = pc);
0N/A
0N/A // Generate code
0N/A for (Instruction inst = first.next ; inst != null ; inst = inst.next) {
0N/A inst.write(out, tab);
0N/A }
0N/A
0N/A // write exceptions
0N/A out.writeShort(nexceptions);
0N/A if (nexceptions > 0) {
0N/A //listing(System.out);
0N/A writeExceptions(env, out, tab, first, last);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Write the exceptions table
0N/A */
0N/A void writeExceptions(Environment env, DataOutputStream out, ConstantPool tab, Instruction first, Instruction last) throws IOException {
0N/A for (Instruction inst = first ; inst != last.next ; inst = inst.next) {
0N/A if (inst.opc == opc_try) {
0N/A TryData td = (TryData)inst.value;
0N/A writeExceptions(env, out, tab, inst.next, td.getEndLabel());
0N/A for (Enumeration e = td.catches.elements() ; e.hasMoreElements();) {
0N/A CatchData cd = (CatchData)e.nextElement();
0N/A //System.out.println("EXCEPTION: " + env.getSource() + ", pc=" + inst.pc + ", end=" + td.getEndLabel().pc + ", hdl=" + cd.getLabel().pc + ", tp=" + cd.getType());
0N/A out.writeShort(inst.pc);
0N/A out.writeShort(td.getEndLabel().pc);
0N/A out.writeShort(cd.getLabel().pc);
0N/A if (cd.getType() != null) {
0N/A out.writeShort(tab.index(cd.getType()));
0N/A } else {
0N/A out.writeShort(0);
0N/A }
0N/A }
0N/A inst = td.getEndLabel();
0N/A }
0N/A }
0N/A }
0N/A
0N/A//JCOV
0N/A /**
0N/A * Write the coverage table
0N/A */
0N/A public void writeCoverageTable(Environment env, ClassDefinition c, DataOutputStream out, ConstantPool tab, long whereField) throws IOException {
0N/A Vector TableLot = new Vector(); /* Coverage table */
0N/A boolean begseg = false;
0N/A boolean begmeth = false;
0N/A long whereClass = ((SourceClass)c).getWhere();
0N/A Vector whereTry = new Vector();
0N/A int numberTry = 0;
0N/A int count = 0;
0N/A
0N/A for (Instruction inst = first ; inst != null ; inst = inst.next) {
0N/A long n = (inst.where >> WHEREOFFSETBITS);
0N/A if (n > 0 && inst.opc != opc_label) {
0N/A if (!begmeth) {
0N/A if ( whereClass == inst.where)
0N/A TableLot.addElement(new Cover(CT_FIKT_METHOD, whereField, inst.pc));
0N/A else
0N/A TableLot.addElement(new Cover(CT_METHOD, whereField, inst.pc));
0N/A count++;
0N/A begmeth = true;
0N/A }
0N/A if (!begseg && !inst.flagNoCovered ) {
0N/A boolean findTry = false;
0N/A for (Enumeration e = whereTry.elements(); e.hasMoreElements();) {
0N/A if ( ((Long)(e.nextElement())).longValue() == inst.where) {
0N/A findTry = true;
0N/A break;
0N/A }
0N/A }
0N/A if (!findTry) {
0N/A TableLot.addElement(new Cover(CT_BLOCK, inst.where, inst.pc));
0N/A count++;
0N/A begseg = true;
0N/A }
0N/A }
0N/A }
0N/A switch (inst.opc) {
0N/A case opc_label:
0N/A begseg = false;
0N/A break;
0N/A case opc_ifeq:
0N/A case opc_ifne:
0N/A case opc_ifnull:
0N/A case opc_ifnonnull:
0N/A case opc_ifgt:
0N/A case opc_ifge:
0N/A case opc_iflt:
0N/A case opc_ifle:
0N/A case opc_if_icmpeq:
0N/A case opc_if_icmpne:
0N/A case opc_if_icmpgt:
0N/A case opc_if_icmpge:
0N/A case opc_if_icmplt:
0N/A case opc_if_icmple:
0N/A case opc_if_acmpeq:
0N/A case opc_if_acmpne: {
0N/A if ( inst.flagCondInverted ) {
0N/A TableLot.addElement(new Cover(CT_BRANCH_TRUE, inst.where, inst.pc));
0N/A TableLot.addElement(new Cover(CT_BRANCH_FALSE, inst.where, inst.pc));
0N/A } else {
0N/A TableLot.addElement(new Cover(CT_BRANCH_FALSE, inst.where, inst.pc));
0N/A TableLot.addElement(new Cover(CT_BRANCH_TRUE, inst.where, inst.pc));
0N/A }
0N/A count += 2;
0N/A begseg = false;
0N/A break;
0N/A }
0N/A
0N/A case opc_goto: {
0N/A begseg = false;
0N/A break;
0N/A }
0N/A
0N/A case opc_ret:
0N/A case opc_return:
0N/A case opc_ireturn:
0N/A case opc_lreturn:
0N/A case opc_freturn:
0N/A case opc_dreturn:
0N/A case opc_areturn:
0N/A case opc_athrow: {
0N/A break;
0N/A }
0N/A
0N/A case opc_try: {
0N/A whereTry.addElement(new Long(inst.where));
0N/A begseg = false;
0N/A break;
0N/A }
0N/A
0N/A case opc_tableswitch: {
0N/A SwitchData sw = (SwitchData)inst.value;
0N/A for (int i = sw.minValue; i <= sw.maxValue; i++) {
0N/A TableLot.addElement(new Cover(CT_CASE, sw.whereCase(new Integer(i)), inst.pc));
0N/A count++;
0N/A }
0N/A if (!sw.getDefault()) {
0N/A TableLot.addElement(new Cover(CT_SWITH_WO_DEF, inst.where, inst.pc));
0N/A count++;
0N/A } else {
0N/A TableLot.addElement(new Cover(CT_CASE, sw.whereCase("default"), inst.pc));
0N/A count++;
0N/A }
0N/A begseg = false;
0N/A break;
0N/A }
0N/A case opc_lookupswitch: {
0N/A SwitchData sw = (SwitchData)inst.value;
0N/A for (Enumeration e = sw.sortedKeys(); e.hasMoreElements() ; ) {
0N/A Integer v = (Integer)e.nextElement();
0N/A TableLot.addElement(new Cover(CT_CASE, sw.whereCase(v), inst.pc));
0N/A count++;
0N/A }
0N/A if (!sw.getDefault()) {
0N/A TableLot.addElement(new Cover(CT_SWITH_WO_DEF, inst.where, inst.pc));
0N/A count++;
0N/A } else {
0N/A TableLot.addElement(new Cover(CT_CASE, sw.whereCase("default"), inst.pc));
0N/A count++;
0N/A }
0N/A begseg = false;
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A Cover Lot;
0N/A long ln, pos;
0N/A
0N/A out.writeShort(count);
0N/A for (int i = 0; i < count; i++) {
0N/A Lot = (Cover)TableLot.elementAt(i);
0N/A ln = (Lot.Addr >> WHEREOFFSETBITS);
0N/A pos = (Lot.Addr << (64 - WHEREOFFSETBITS)) >> (64 - WHEREOFFSETBITS);
0N/A out.writeShort(Lot.NumCommand);
0N/A out.writeShort(Lot.Type);
0N/A out.writeInt((int)ln);
0N/A out.writeInt((int)pos);
0N/A
0N/A if ( !(Lot.Type == CT_CASE && Lot.Addr == 0) ) {
0N/A JcovClassCountArray[Lot.Type]++;
0N/A }
0N/A }
0N/A
0N/A }
0N/A
0N/A/*
0N/A * Increase count of methods for native methods
0N/A */
0N/A
0N/Apublic void addNativeToJcovTab(Environment env, ClassDefinition c) {
0N/A JcovClassCountArray[CT_METHOD]++;
0N/A}
0N/A
0N/A/*
0N/A * Create class jcov element
0N/A */
0N/A
0N/Aprivate String createClassJcovElement(Environment env, ClassDefinition c) {
0N/A String SourceClass = (Type.mangleInnerType((c.getClassDeclaration()).getName())).toString();
0N/A String ConvSourceClass;
0N/A String classJcovLine;
0N/A
0N/A SourceClassList.addElement(SourceClass);
0N/A ConvSourceClass = SourceClass.replace('.', '/');
0N/A classJcovLine = JcovClassLine + ConvSourceClass;
0N/A
0N/A classJcovLine = classJcovLine + " [";
0N/A String blank = "";
0N/A
0N/A for (int i = 0; i < arrayModifiers.length; i++ ) {
0N/A if ((c.getModifiers() & arrayModifiers[i]) != 0) {
0N/A classJcovLine = classJcovLine + blank + opNames[arrayModifiersOpc[i]];
0N/A blank = " ";
0N/A }
0N/A }
0N/A classJcovLine = classJcovLine + "]";
0N/A
0N/A return classJcovLine;
0N/A}
0N/A
0N/A/*
0N/A * generate coverage data
0N/A */
0N/A
0N/Apublic void GenVecJCov(Environment env, ClassDefinition c, long Time) {
0N/A String SourceFile = ((SourceClass)c).getAbsoluteName();
0N/A
0N/A TmpCovTable.addElement(createClassJcovElement(env, c));
0N/A TmpCovTable.addElement(JcovSrcfileLine + SourceFile);
0N/A TmpCovTable.addElement(JcovTimestampLine + Time);
0N/A TmpCovTable.addElement(JcovDataLine + "A"); // data format
0N/A TmpCovTable.addElement(JcovHeadingLine);
0N/A
0N/A for (int i = CT_FIRST_KIND; i <= CT_LAST_KIND; i++) {
0N/A if (JcovClassCountArray[i] != 0) {
0N/A TmpCovTable.addElement(new String(i + "\t" + JcovClassCountArray[i]));
0N/A JcovClassCountArray[i] = 0;
0N/A }
0N/A }
0N/A}
0N/A
0N/A
0N/A/*
0N/A * generate file of coverage data
0N/A */
0N/A
0N/Apublic void GenJCov(Environment env) {
0N/A
0N/A try {
0N/A File outFile = env.getcovFile();
0N/A if( outFile.exists()) {
0N/A DataInputStream JCovd = new DataInputStream(
0N/A new BufferedInputStream(
0N/A new FileInputStream(outFile)));
0N/A String CurrLine = null;
0N/A boolean first = true;
0N/A String Class;
0N/A
0N/A CurrLine = JCovd.readLine();
0N/A if ((CurrLine != null) && CurrLine.startsWith(JcovMagicLine)) {
0N/A // this is a good Jcov file
0N/A
0N/A while((CurrLine = JCovd.readLine()) != null ) {
0N/A if ( CurrLine.startsWith(JcovClassLine) ) {
0N/A first = true;
0N/A for(Enumeration e = SourceClassList.elements(); e.hasMoreElements();) {
0N/A String clsName = CurrLine.substring(JcovClassLine.length());
0N/A int idx = clsName.indexOf(' ');
0N/A
0N/A if (idx != -1) {
0N/A clsName = clsName.substring(0, idx);
0N/A }
0N/A Class = (String)e.nextElement();
0N/A if ( Class.compareTo(clsName) == 0) {
0N/A first = false;
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A if (first) // re-write old class
0N/A TmpCovTable.addElement(CurrLine);
0N/A }
0N/A }
0N/A JCovd.close();
0N/A }
0N/A PrintStream CovFile = new PrintStream(new DataOutputStream(new FileOutputStream(outFile)));
0N/A CovFile.println(JcovMagicLine);
0N/A for(Enumeration e = TmpCovTable.elements(); e.hasMoreElements();) {
0N/A CovFile.println(e.nextElement());
0N/A }
0N/A CovFile.close();
0N/A }
0N/A catch (FileNotFoundException e) {
0N/A System.out.println("ERROR: " + e);
0N/A }
0N/A catch (IOException e) {
0N/A System.out.println("ERROR: " + e);
0N/A }
0N/A}
0N/A// end JCOV
0N/A
0N/A
0N/A /**
0N/A * Write the linenumber table
0N/A */
0N/A public void writeLineNumberTable(Environment env, DataOutputStream out, ConstantPool tab) throws IOException {
0N/A long ln = -1;
0N/A int count = 0;
0N/A
0N/A for (Instruction inst = first ; inst != null ; inst = inst.next) {
0N/A long n = (inst.where >> WHEREOFFSETBITS);
0N/A if ((n > 0) && (ln != n)) {
0N/A ln = n;
0N/A count++;
0N/A }
0N/A }
0N/A
0N/A ln = -1;
0N/A out.writeShort(count);
0N/A for (Instruction inst = first ; inst != null ; inst = inst.next) {
0N/A long n = (inst.where >> WHEREOFFSETBITS);
0N/A if ((n > 0) && (ln != n)) {
0N/A ln = n;
0N/A out.writeShort(inst.pc);
0N/A out.writeShort((int)ln);
0N/A //System.out.println("pc = " + inst.pc + ", ln = " + ln);
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Figure out when registers contain a legal value. This is done
0N/A * using a simple data flow algorithm. This information is later used
0N/A * to generate the local variable table.
0N/A */
0N/A void flowFields(Environment env, Label lbl, MemberDefinition locals[]) {
0N/A if (lbl.locals != null) {
0N/A // Been here before. Erase any conflicts.
0N/A MemberDefinition f[] = lbl.locals;
0N/A for (int i = 0 ; i < maxvar ; i++) {
0N/A if (f[i] != locals[i]) {
0N/A f[i] = null;
0N/A }
0N/A }
0N/A return;
0N/A }
0N/A
0N/A // Remember the set of active registers at this point
0N/A lbl.locals = new MemberDefinition[maxvar];
0N/A System.arraycopy(locals, 0, lbl.locals, 0, maxvar);
0N/A
0N/A MemberDefinition newlocals[] = new MemberDefinition[maxvar];
0N/A System.arraycopy(locals, 0, newlocals, 0, maxvar);
0N/A locals = newlocals;
0N/A
0N/A for (Instruction inst = lbl.next ; inst != null ; inst = inst.next) {
0N/A switch (inst.opc) {
0N/A case opc_istore: case opc_istore_0: case opc_istore_1:
0N/A case opc_istore_2: case opc_istore_3:
0N/A case opc_fstore: case opc_fstore_0: case opc_fstore_1:
0N/A case opc_fstore_2: case opc_fstore_3:
0N/A case opc_astore: case opc_astore_0: case opc_astore_1:
0N/A case opc_astore_2: case opc_astore_3:
0N/A case opc_lstore: case opc_lstore_0: case opc_lstore_1:
0N/A case opc_lstore_2: case opc_lstore_3:
0N/A case opc_dstore: case opc_dstore_0: case opc_dstore_1:
0N/A case opc_dstore_2: case opc_dstore_3:
0N/A if (inst.value instanceof LocalVariable) {
0N/A LocalVariable v = (LocalVariable)inst.value;
0N/A locals[v.slot] = v.field;
0N/A }
0N/A break;
0N/A
0N/A case opc_label:
0N/A flowFields(env, (Label)inst, locals);
0N/A return;
0N/A
0N/A case opc_ifeq: case opc_ifne: case opc_ifgt:
0N/A case opc_ifge: case opc_iflt: case opc_ifle:
0N/A case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpgt:
0N/A case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmple:
0N/A case opc_if_acmpeq: case opc_if_acmpne:
0N/A case opc_ifnull: case opc_ifnonnull:
0N/A case opc_jsr:
0N/A flowFields(env, (Label)inst.value, locals);
0N/A break;
0N/A
0N/A case opc_goto:
0N/A flowFields(env, (Label)inst.value, locals);
0N/A return;
0N/A
0N/A case opc_return: case opc_ireturn: case opc_lreturn:
0N/A case opc_freturn: case opc_dreturn: case opc_areturn:
0N/A case opc_athrow: case opc_ret:
0N/A return;
0N/A
0N/A case opc_tableswitch:
0N/A case opc_lookupswitch: {
0N/A SwitchData sw = (SwitchData)inst.value;
0N/A flowFields(env, sw.defaultLabel, locals);
0N/A for (Enumeration e = sw.tab.elements() ; e.hasMoreElements();) {
0N/A flowFields(env, (Label)e.nextElement(), locals);
0N/A }
0N/A return;
0N/A }
0N/A
0N/A case opc_try: {
0N/A Vector catches = ((TryData)inst.value).catches;
0N/A for (Enumeration e = catches.elements(); e.hasMoreElements();) {
0N/A CatchData cd = (CatchData)e.nextElement();
0N/A flowFields(env, cd.getLabel(), locals);
0N/A }
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Write the local variable table. The necessary constants have already been
0N/A * added to the constant table by the collect() method. The flowFields method
0N/A * is used to determine which variables are alive at each pc.
0N/A */
0N/A public void writeLocalVariableTable(Environment env, MemberDefinition field, DataOutputStream out, ConstantPool tab) throws IOException {
0N/A MemberDefinition locals[] = new MemberDefinition[maxvar];
0N/A int i = 0;
0N/A
0N/A // Initialize arguments
0N/A if ((field != null) && (field.getArguments() != null)) {
0N/A int reg = 0;
0N/A Vector v = field.getArguments();
0N/A for (Enumeration e = v.elements(); e.hasMoreElements(); ) {
0N/A MemberDefinition f = ((MemberDefinition)e.nextElement());
0N/A locals[reg] = f;
0N/A reg += f.getType().stackSize();
0N/A }
0N/A }
0N/A
0N/A flowFields(env, first, locals);
0N/A LocalVariableTable lvtab = new LocalVariableTable();
0N/A
0N/A // Initialize arguments again
0N/A for (i = 0; i < maxvar; i++)
0N/A locals[i] = null;
0N/A if ((field != null) && (field.getArguments() != null)) {
0N/A int reg = 0;
0N/A Vector v = field.getArguments();
0N/A for (Enumeration e = v.elements(); e.hasMoreElements(); ) {
0N/A MemberDefinition f = ((MemberDefinition)e.nextElement());
0N/A locals[reg] = f;
0N/A lvtab.define(f, reg, 0, maxpc);
0N/A reg += f.getType().stackSize();
0N/A }
0N/A }
0N/A
0N/A int pcs[] = new int[maxvar];
0N/A
0N/A for (Instruction inst = first ; inst != null ; inst = inst.next) {
0N/A switch (inst.opc) {
0N/A case opc_istore: case opc_istore_0: case opc_istore_1:
0N/A case opc_istore_2: case opc_istore_3: case opc_fstore:
0N/A case opc_fstore_0: case opc_fstore_1: case opc_fstore_2:
0N/A case opc_fstore_3:
0N/A case opc_astore: case opc_astore_0: case opc_astore_1:
0N/A case opc_astore_2: case opc_astore_3:
0N/A case opc_lstore: case opc_lstore_0: case opc_lstore_1:
0N/A case opc_lstore_2: case opc_lstore_3:
0N/A case opc_dstore: case opc_dstore_0: case opc_dstore_1:
0N/A case opc_dstore_2: case opc_dstore_3:
0N/A if (inst.value instanceof LocalVariable) {
0N/A LocalVariable v = (LocalVariable)inst.value;
0N/A int pc = (inst.next != null) ? inst.next.pc : inst.pc;
0N/A if (locals[v.slot] != null) {
0N/A lvtab.define(locals[v.slot], v.slot, pcs[v.slot], pc);
0N/A }
0N/A pcs[v.slot] = pc;
0N/A locals[v.slot] = v.field;
0N/A }
0N/A break;
0N/A
0N/A case opc_label: {
0N/A // flush previous labels
0N/A for (i = 0 ; i < maxvar ; i++) {
0N/A if (locals[i] != null) {
0N/A lvtab.define(locals[i], i, pcs[i], inst.pc);
0N/A }
0N/A }
0N/A // init new labels
0N/A int pc = inst.pc;
0N/A MemberDefinition[] labelLocals = ((Label)inst).locals;
0N/A if (labelLocals == null) { // unreachable code??
0N/A for (i = 0; i < maxvar; i++)
0N/A locals[i] = null;
0N/A } else {
0N/A System.arraycopy(labelLocals, 0, locals, 0, maxvar);
0N/A }
0N/A for (i = 0 ; i < maxvar ; i++) {
0N/A pcs[i] = pc;
0N/A }
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A
0N/A // flush remaining labels
0N/A for (i = 0 ; i < maxvar ; i++) {
0N/A if (locals[i] != null) {
0N/A lvtab.define(locals[i], i, pcs[i], maxpc);
0N/A }
0N/A }
0N/A
0N/A // write the local variable table
0N/A lvtab.write(env, out, tab);
0N/A }
0N/A
0N/A /**
0N/A * Return true if empty
0N/A */
0N/A public boolean empty() {
0N/A return first == last;
0N/A }
0N/A
0N/A /**
0N/A * Print the byte codes
0N/A */
0N/A public void listing(PrintStream out) {
0N/A out.println("-- listing --");
0N/A for (Instruction inst = first ; inst != null ; inst = inst.next) {
0N/A out.println(inst.toString());
0N/A }
0N/A }
0N/A}