alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Assembler.java)

This example Java source code file (Assembler.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

constantpool, cover, dataoutputstream, enumeration, instruction, ioexception, javac, label, memberdefinition, notreached, reached, string, suppresswarnings, util, vector, whereoffsetbits

The Assembler.java Java example source code

/*
 * Copyright (c) 1994, 2013, 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 sun.tools.asm;

import sun.tools.java.*;
import java.util.Enumeration;
import java.io.IOException;
import java.io.DataOutputStream;
import java.io.PrintStream;
import java.util.Vector;
// JCOV
import sun.tools.javac.*;
import java.io.File;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.lang.String;
// end JCOV

/**
 * This class is used to assemble the bytecode instructions for a method.
 *
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 *
 * @author Arthur van Hoff
 */
public final
class Assembler implements Constants {
    static final int NOTREACHED         = 0;
    static final int REACHED            = 1;
    static final int NEEDED             = 2;

    Label first = new Label();
    Instruction last = first;
    int maxdepth;
    int maxvar;
    int maxpc;

    /**
     * Add an instruction
     */
    public void add(Instruction inst) {
        if (inst != null) {
            last.next = inst;
            last = inst;
        }
    }
    public void add(long where, int opc) {
        add(new Instruction(where, opc, null));
    }
    public void add(long where, int opc, Object obj) {
        add(new Instruction(where, opc, obj));
    }
// JCOV
    public void add(long where, int opc, Object obj, boolean flagCondInverted) {
        add(new Instruction(where, opc, obj, flagCondInverted));
    }

    public void add(boolean flagNoCovered, long where, int opc, Object obj) {
        add(new Instruction(flagNoCovered, where, opc, obj));
    }

    public void add(long where, int opc, boolean flagNoCovered) {
        add(new Instruction(where, opc, flagNoCovered));
    }

    static Vector<String> SourceClassList = new Vector<>();

    static Vector<String> TmpCovTable = new Vector<>();

    static int[]  JcovClassCountArray = new int[CT_LAST_KIND + 1];

    static String JcovMagicLine     = "JCOV-DATA-FILE-VERSION: 2.0";
    static String JcovClassLine     = "CLASS: ";
    static String JcovSrcfileLine   = "SRCFILE: ";
    static String JcovTimestampLine = "TIMESTAMP: ";
    static String JcovDataLine      = "DATA: ";
    static String JcovHeadingLine   = "#kind\tcount";

    static int[]  arrayModifiers    =
                {M_PUBLIC, M_PRIVATE, M_PROTECTED, M_ABSTRACT, M_FINAL, M_INTERFACE};
    static int[]  arrayModifiersOpc =
                {PUBLIC, PRIVATE, PROTECTED, ABSTRACT, FINAL, INTERFACE};
//end JCOV

    /**
     * Optimize instructions and mark those that can be reached
     */
    void optimize(Environment env, Label lbl) {
        lbl.pc = REACHED;

        for (Instruction inst = lbl.next ; inst != null ; inst = inst.next)  {
            switch (inst.pc) {
              case NOTREACHED:
                inst.optimize(env);
                inst.pc = REACHED;
                break;
              case REACHED:
                return;
              case NEEDED:
                break;
            }

            switch (inst.opc) {
              case opc_label:
              case opc_dead:
                if (inst.pc == REACHED) {
                    inst.pc = NOTREACHED;
                }
                break;

              case opc_ifeq:
              case opc_ifne:
              case opc_ifgt:
              case opc_ifge:
              case opc_iflt:
              case opc_ifle:
              case opc_if_icmpeq:
              case opc_if_icmpne:
              case opc_if_icmpgt:
              case opc_if_icmpge:
              case opc_if_icmplt:
              case opc_if_icmple:
              case opc_if_acmpeq:
              case opc_if_acmpne:
              case opc_ifnull:
              case opc_ifnonnull:
                optimize(env, (Label)inst.value);
                break;

              case opc_goto:
                optimize(env, (Label)inst.value);
                return;

              case opc_jsr:
                optimize(env, (Label)inst.value);
                break;

              case opc_ret:
              case opc_return:
              case opc_ireturn:
              case opc_lreturn:
              case opc_freturn:
              case opc_dreturn:
              case opc_areturn:
              case opc_athrow:
                return;

              case opc_tableswitch:
              case opc_lookupswitch: {
                SwitchData sw = (SwitchData)inst.value;
                optimize(env, sw.defaultLabel);
                for (Enumeration<Label> e = sw.tab.elements() ; e.hasMoreElements();) {
                    optimize(env, e.nextElement());
                }
                return;
              }

              case opc_try: {
                TryData td = (TryData)inst.value;
                td.getEndLabel().pc = NEEDED;
                for (Enumeration<CatchData> e = td.catches.elements() ; e.hasMoreElements();) {
                    CatchData cd = e.nextElement();
                    optimize(env, cd.getLabel());
                }
                break;
              }
            }
        }
    }

    /**
     * Eliminate instructions that are not reached
     */
    boolean eliminate() {
        boolean change = false;
        Instruction prev = first;

        for (Instruction inst = first.next ; inst != null ; inst = inst.next) {
            if (inst.pc != NOTREACHED) {
                prev.next = inst;
                prev = inst;
                inst.pc = NOTREACHED;
            } else {
                change = true;
            }
        }
        first.pc = NOTREACHED;
        prev.next = null;
        return change;
    }

    /**
     * Optimize the byte codes
     */
    public void optimize(Environment env) {
        //listing(System.out);
        do {
            // Figure out which instructions are reached
            optimize(env, first);

            // Eliminate instructions that are not reached
        } while (eliminate() && env.opt());
    }

    /**
     * Collect all constants into the constant table
     */
    public void collect(Environment env, MemberDefinition field, ConstantPool tab) {
        // Collect constants for arguments only
        // if a local variable table is generated
        if ((field != null) && env.debug_vars()) {
            @SuppressWarnings("unchecked")
            Vector<MemberDefinition> v = (Vector)field.getArguments();
            if (v != null) {
                for (Enumeration<MemberDefinition> e = v.elements() ; e.hasMoreElements() ;) {
                    MemberDefinition f = e.nextElement();
                    tab.put(f.getName().toString());
                    tab.put(f.getType().getTypeSignature());
                }
            }
        }

        // Collect constants from the instructions
        for (Instruction inst = first ; inst != null ; inst = inst.next) {
            inst.collect(tab);
        }
    }

    /**
     * Determine stack size, count local variables
     */
    void balance(Label lbl, int depth) {
        for (Instruction inst = lbl ; inst != null ; inst = inst.next)  {
            //Environment.debugOutput(inst.toString() + ": " + depth + " => " +
            //                                 (depth + inst.balance()));
            depth += inst.balance();
            if (depth < 0) {
               throw new CompilerError("stack under flow: " + inst.toString() + " = " + depth);
            }
            if (depth > maxdepth) {
                maxdepth = depth;
            }
            switch (inst.opc) {
              case opc_label:
                lbl = (Label)inst;
                if (inst.pc == REACHED) {
                    if (lbl.depth != depth) {
                        throw new CompilerError("stack depth error " +
                                                depth + "/" + lbl.depth +
                                                ": " + inst.toString());
                    }
                    return;
                }
                lbl.pc = REACHED;
                lbl.depth = depth;
                break;

              case opc_ifeq:
              case opc_ifne:
              case opc_ifgt:
              case opc_ifge:
              case opc_iflt:
              case opc_ifle:
              case opc_if_icmpeq:
              case opc_if_icmpne:
              case opc_if_icmpgt:
              case opc_if_icmpge:
              case opc_if_icmplt:
              case opc_if_icmple:
              case opc_if_acmpeq:
              case opc_if_acmpne:
              case opc_ifnull:
              case opc_ifnonnull:
                balance((Label)inst.value, depth);
                break;

              case opc_goto:
                balance((Label)inst.value, depth);
                return;

              case opc_jsr:
                balance((Label)inst.value, depth + 1);
                break;

              case opc_ret:
              case opc_return:
              case opc_ireturn:
              case opc_lreturn:
              case opc_freturn:
              case opc_dreturn:
              case opc_areturn:
              case opc_athrow:
                return;

              case opc_iload:
              case opc_fload:
              case opc_aload:
              case opc_istore:
              case opc_fstore:
              case opc_astore: {
                int v = ((inst.value instanceof Number)
                            ? ((Number)inst.value).intValue()
                            : ((LocalVariable)inst.value).slot) + 1;
                if (v > maxvar)
                    maxvar = v;
                break;
              }

              case opc_lload:
              case opc_dload:
              case opc_lstore:
              case opc_dstore: {
                int v = ((inst.value instanceof Number)
                            ? ((Number)inst.value).intValue()
                            : ((LocalVariable)inst.value).slot) + 2;
                if (v  > maxvar)
                    maxvar = v;
                break;
              }

              case opc_iinc: {
                  int v = ((int[])inst.value)[0] + 1;
                  if (v  > maxvar)
                      maxvar = v + 1;
                  break;
              }

              case opc_tableswitch:
              case opc_lookupswitch: {
                SwitchData sw = (SwitchData)inst.value;
                balance(sw.defaultLabel, depth);
                for (Enumeration<Label> e = sw.tab.elements() ; e.hasMoreElements();) {
                    balance(e.nextElement(), depth);
                }
                return;
              }

              case opc_try: {
                TryData td = (TryData)inst.value;
                for (Enumeration<CatchData> e = td.catches.elements() ; e.hasMoreElements();) {
                    CatchData cd = e.nextElement();
                    balance(cd.getLabel(), depth + 1);
                }
                break;
              }
            }
        }
    }

    /**
     * Generate code
     */
    public void write(Environment env, DataOutputStream out,
                      MemberDefinition field, ConstantPool tab)
                 throws IOException {
        //listing(System.out);

        if ((field != null) && field.getArguments() != null) {
              int sum = 0;
              @SuppressWarnings("unchecked")
              Vector<MemberDefinition> v = (Vector)field.getArguments();
              for (Enumeration<MemberDefinition> e = v.elements(); e.hasMoreElements(); ) {
                  MemberDefinition f = e.nextElement();
                  sum += f.getType().stackSize();
              }
              maxvar = sum;
        }

        // Make sure the stack balances.  Also calculate maxvar and maxstack
        try {
            balance(first, 0);
        } catch (CompilerError e) {
            System.out.println("ERROR: " + e);
            listing(System.out);
            throw e;
        }

        // Assign PCs
        int pc = 0, nexceptions = 0;
        for (Instruction inst = first ; inst != null ; inst = inst.next) {
            inst.pc = pc;
            int sz = inst.size(tab);
            if (pc<65536 && (pc+sz)>=65536) {
               env.error(inst.where, "warn.method.too.long");
            }
            pc += sz;

            if (inst.opc == opc_try) {
                nexceptions += ((TryData)inst.value).catches.size();
            }
        }

        // Write header
        out.writeShort(maxdepth);
        out.writeShort(maxvar);
        out.writeInt(maxpc = pc);

        // Generate code
        for (Instruction inst = first.next ; inst != null ; inst = inst.next) {
            inst.write(out, tab);
        }

        // write exceptions
        out.writeShort(nexceptions);
        if (nexceptions > 0) {
            //listing(System.out);
            writeExceptions(env, out, tab, first, last);
        }
    }

    /**
     * Write the exceptions table
     */
    void writeExceptions(Environment env, DataOutputStream out, ConstantPool tab, Instruction first, Instruction last) throws IOException {
        for (Instruction inst = first ; inst != last.next ; inst = inst.next) {
            if (inst.opc == opc_try) {
                TryData td = (TryData)inst.value;
                writeExceptions(env, out, tab, inst.next, td.getEndLabel());
                for (Enumeration<CatchData> e = td.catches.elements() ; e.hasMoreElements();) {
                    CatchData cd = e.nextElement();
                    //System.out.println("EXCEPTION: " + env.getSource() + ", pc=" + inst.pc + ", end=" + td.getEndLabel().pc + ", hdl=" + cd.getLabel().pc + ", tp=" + cd.getType());
                    out.writeShort(inst.pc);
                    out.writeShort(td.getEndLabel().pc);
                    out.writeShort(cd.getLabel().pc);
                    if (cd.getType() != null) {
                        out.writeShort(tab.index(cd.getType()));
                    } else {
                        out.writeShort(0);
                    }
                }
                inst = td.getEndLabel();
            }
        }
    }

//JCOV
    /**
     * Write the coverage table
     */
    public void writeCoverageTable(Environment env, ClassDefinition c, DataOutputStream out, ConstantPool tab, long whereField) throws IOException {
        Vector<Cover> TableLot = new Vector<>();         /* Coverage table */
        boolean begseg = false;
        boolean begmeth = false;
        @SuppressWarnings("deprecation")
        long whereClass = ((SourceClass)c).getWhere();
        Vector<Long> whereTry = new Vector<>();
        int numberTry = 0;
        int count = 0;

        for (Instruction inst = first ; inst != null ; inst = inst.next) {
            long n = (inst.where >> WHEREOFFSETBITS);
            if (n > 0 && inst.opc != opc_label) {
                if (!begmeth) {
                  if ( whereClass == inst.where)
                        TableLot.addElement(new Cover(CT_FIKT_METHOD, whereField, inst.pc));
                  else
                        TableLot.addElement(new Cover(CT_METHOD, whereField, inst.pc));
                  count++;
                  begmeth = true;
                }
                if (!begseg && !inst.flagNoCovered ) {
                  boolean findTry = false;
                  for (Enumeration<Long> e = whereTry.elements(); e.hasMoreElements();) {
                       if (e.nextElement().longValue() == inst.where) {
                              findTry = true;
                              break;
                       }
                  }
                  if (!findTry) {
                      TableLot.addElement(new Cover(CT_BLOCK, inst.where, inst.pc));
                      count++;
                      begseg = true;
                  }
                }
            }
            switch (inst.opc) {
              case opc_label:
                begseg = false;
                break;
              case opc_ifeq:
              case opc_ifne:
              case opc_ifnull:
              case opc_ifnonnull:
              case opc_ifgt:
              case opc_ifge:
              case opc_iflt:
              case opc_ifle:
              case opc_if_icmpeq:
              case opc_if_icmpne:
              case opc_if_icmpgt:
              case opc_if_icmpge:
              case opc_if_icmplt:
              case opc_if_icmple:
              case opc_if_acmpeq:
              case opc_if_acmpne: {
                if ( inst.flagCondInverted ) {
                   TableLot.addElement(new Cover(CT_BRANCH_TRUE, inst.where, inst.pc));
                   TableLot.addElement(new Cover(CT_BRANCH_FALSE, inst.where, inst.pc));
                } else {
                   TableLot.addElement(new Cover(CT_BRANCH_FALSE, inst.where, inst.pc));
                   TableLot.addElement(new Cover(CT_BRANCH_TRUE, inst.where, inst.pc));
                }
                count += 2;
                begseg = false;
                break;
              }

              case opc_goto: {
                begseg = false;
                break;
              }

              case opc_ret:
              case opc_return:
              case opc_ireturn:
              case opc_lreturn:
              case opc_freturn:
              case opc_dreturn:
              case opc_areturn:
              case opc_athrow: {
                break;
              }

              case opc_try: {
                whereTry.addElement(Long.valueOf(inst.where));
                begseg = false;
                break;
              }

              case opc_tableswitch: {
                SwitchData sw = (SwitchData)inst.value;
                for (int i = sw.minValue; i <= sw.maxValue; i++) {
                     TableLot.addElement(new Cover(CT_CASE, sw.whereCase(new Integer(i)), inst.pc));
                     count++;
                }
                if (!sw.getDefault()) {
                     TableLot.addElement(new Cover(CT_SWITH_WO_DEF, inst.where, inst.pc));
                     count++;
                } else {
                     TableLot.addElement(new Cover(CT_CASE, sw.whereCase("default"), inst.pc));
                     count++;
                }
                begseg = false;
                break;
              }
              case opc_lookupswitch: {
                SwitchData sw = (SwitchData)inst.value;
                for (Enumeration<Integer> e = sw.sortedKeys(); e.hasMoreElements() ; ) {
                     Integer v = e.nextElement();
                     TableLot.addElement(new Cover(CT_CASE, sw.whereCase(v), inst.pc));
                     count++;
                }
                if (!sw.getDefault()) {
                     TableLot.addElement(new Cover(CT_SWITH_WO_DEF, inst.where, inst.pc));
                     count++;
                } else {
                     TableLot.addElement(new Cover(CT_CASE, sw.whereCase("default"), inst.pc));
                     count++;
                }
                begseg = false;
                break;
              }
            }
        }
        Cover Lot;
        long ln, pos;

        out.writeShort(count);
        for (int i = 0; i < count; i++) {
           Lot = TableLot.elementAt(i);
           ln = (Lot.Addr >> WHEREOFFSETBITS);
           pos = (Lot.Addr << (64 - WHEREOFFSETBITS)) >> (64 - WHEREOFFSETBITS);
           out.writeShort(Lot.NumCommand);
           out.writeShort(Lot.Type);
           out.writeInt((int)ln);
           out.writeInt((int)pos);

           if ( !(Lot.Type == CT_CASE && Lot.Addr == 0) ) {
                JcovClassCountArray[Lot.Type]++;
           }
        }

    }

/*
 *  Increase count of methods for native methods
 */

public void addNativeToJcovTab(Environment env, ClassDefinition c) {
        JcovClassCountArray[CT_METHOD]++;
}

/*
 *  Create class jcov element
 */

private String createClassJcovElement(Environment env, ClassDefinition c) {
        String SourceClass = (Type.mangleInnerType((c.getClassDeclaration()).getName())).toString();
        String ConvSourceClass;
        String classJcovLine;

        SourceClassList.addElement(SourceClass);
        ConvSourceClass = SourceClass.replace('.', '/');
        classJcovLine = JcovClassLine + ConvSourceClass;

        classJcovLine = classJcovLine + " [";
        String blank = "";

        for (int i = 0; i < arrayModifiers.length; i++ ) {
            if ((c.getModifiers() & arrayModifiers[i]) != 0) {
                classJcovLine = classJcovLine + blank + opNames[arrayModifiersOpc[i]];
                blank = " ";
            }
        }
        classJcovLine = classJcovLine + "]";

        return classJcovLine;
}

/*
 *  generate coverage data
 */

public void GenVecJCov(Environment env, ClassDefinition c, long Time) {
        @SuppressWarnings("deprecation")
        String SourceFile = ((SourceClass)c).getAbsoluteName();

        TmpCovTable.addElement(createClassJcovElement(env, c));
        TmpCovTable.addElement(JcovSrcfileLine + SourceFile);
        TmpCovTable.addElement(JcovTimestampLine + Time);
        TmpCovTable.addElement(JcovDataLine + "A");             // data format
        TmpCovTable.addElement(JcovHeadingLine);

        for (int i = CT_FIRST_KIND; i <= CT_LAST_KIND; i++) {
            if (JcovClassCountArray[i] != 0) {
                TmpCovTable.addElement(new String(i + "\t" + JcovClassCountArray[i]));
                JcovClassCountArray[i] = 0;
            }
        }
}


/*
 * generate file of coverage data
 */

@SuppressWarnings("deprecation") // for JCovd.readLine() calls
public void GenJCov(Environment env) {

     try {
        File outFile = env.getcovFile();
        if( outFile.exists()) {
           DataInputStream JCovd = new DataInputStream(
                                                       new BufferedInputStream(
                                                                               new FileInputStream(outFile)));
           String CurrLine = null;
           boolean first = true;
           String Class;

           CurrLine = JCovd.readLine();
           if ((CurrLine != null) && CurrLine.startsWith(JcovMagicLine)) {
                // this is a good Jcov file

                   while((CurrLine = JCovd.readLine()) != null ) {
                      if ( CurrLine.startsWith(JcovClassLine) ) {
                             first = true;
                             for(Enumeration<String> e = SourceClassList.elements(); e.hasMoreElements();) {
                                 String clsName = CurrLine.substring(JcovClassLine.length());
                                 int idx = clsName.indexOf(' ');

                                 if (idx != -1) {
                                     clsName = clsName.substring(0, idx);
                                 }
                                 Class = e.nextElement();
                                 if ( Class.compareTo(clsName) == 0) {
                                     first = false;
                                     break;
                                 }
                             }
                      }
                      if (first)        // re-write old class
                          TmpCovTable.addElement(CurrLine);
                   }
           }
           JCovd.close();
        }
        PrintStream CovFile = new PrintStream(new DataOutputStream(new FileOutputStream(outFile)));
        CovFile.println(JcovMagicLine);
        for(Enumeration<String> e = TmpCovTable.elements(); e.hasMoreElements();) {
              CovFile.println(e.nextElement());
        }
        CovFile.close();
    }
    catch (FileNotFoundException e) {
       System.out.println("ERROR: " + e);
    }
    catch (IOException e) {
       System.out.println("ERROR: " + e);
    }
}
// end JCOV


    /**
     * Write the linenumber table
     */
    public void writeLineNumberTable(Environment env, DataOutputStream out, ConstantPool tab) throws IOException {
        long ln = -1;
        int count = 0;

        for (Instruction inst = first ; inst != null ; inst = inst.next) {
            long n = (inst.where >> WHEREOFFSETBITS);
            if ((n > 0) && (ln != n)) {
                ln = n;
                count++;
            }
        }

        ln = -1;
        out.writeShort(count);
        for (Instruction inst = first ; inst != null ; inst = inst.next) {
            long n = (inst.where >> WHEREOFFSETBITS);
            if ((n > 0) && (ln != n)) {
                ln = n;
                out.writeShort(inst.pc);
                out.writeShort((int)ln);
                //System.out.println("pc = " + inst.pc + ", ln = " + ln);
            }
        }
    }

    /**
     * Figure out when registers contain a legal value. This is done
     * using a simple data flow algorithm. This information is later used
     * to generate the local variable table.
     */
    void flowFields(Environment env, Label lbl, MemberDefinition locals[]) {
        if (lbl.locals != null) {
            // Been here before. Erase any conflicts.
            MemberDefinition f[] = lbl.locals;
            for (int i = 0 ; i < maxvar ; i++) {
                if (f[i] != locals[i]) {
                    f[i] = null;
                }
            }
            return;
        }

        // Remember the set of active registers at this point
        lbl.locals = new MemberDefinition[maxvar];
        System.arraycopy(locals, 0, lbl.locals, 0, maxvar);

        MemberDefinition newlocals[] = new MemberDefinition[maxvar];
        System.arraycopy(locals, 0, newlocals, 0, maxvar);
        locals = newlocals;

        for (Instruction inst = lbl.next ; inst != null ; inst = inst.next)  {
            switch (inst.opc) {
              case opc_istore:   case opc_istore_0: case opc_istore_1:
              case opc_istore_2: case opc_istore_3:
              case opc_fstore:   case opc_fstore_0: case opc_fstore_1:
              case opc_fstore_2: case opc_fstore_3:
              case opc_astore:   case opc_astore_0: case opc_astore_1:
              case opc_astore_2: case opc_astore_3:
              case opc_lstore:   case opc_lstore_0: case opc_lstore_1:
              case opc_lstore_2: case opc_lstore_3:
              case opc_dstore:   case opc_dstore_0: case opc_dstore_1:
              case opc_dstore_2: case opc_dstore_3:
                if (inst.value instanceof LocalVariable) {
                    LocalVariable v = (LocalVariable)inst.value;
                    locals[v.slot] = v.field;
                }
                break;

              case opc_label:
                flowFields(env, (Label)inst, locals);
                return;

              case opc_ifeq: case opc_ifne: case opc_ifgt:
              case opc_ifge: case opc_iflt: case opc_ifle:
              case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpgt:
              case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmple:
              case opc_if_acmpeq: case opc_if_acmpne:
              case opc_ifnull: case opc_ifnonnull:
              case opc_jsr:
                flowFields(env, (Label)inst.value, locals);
                break;

              case opc_goto:
                flowFields(env, (Label)inst.value, locals);
                return;

              case opc_return:   case opc_ireturn:  case opc_lreturn:
              case opc_freturn:  case opc_dreturn:  case opc_areturn:
              case opc_athrow:   case opc_ret:
                return;

              case opc_tableswitch:
              case opc_lookupswitch: {
                SwitchData sw = (SwitchData)inst.value;
                flowFields(env, sw.defaultLabel, locals);
                for (Enumeration<Label> e = sw.tab.elements() ; e.hasMoreElements();) {
                    flowFields(env, e.nextElement(), locals);
                }
                return;
              }

              case opc_try: {
                Vector<CatchData> catches = ((TryData)inst.value).catches;
                for (Enumeration<CatchData> e = catches.elements(); e.hasMoreElements();) {
                    CatchData cd = e.nextElement();
                    flowFields(env, cd.getLabel(), locals);
                }
                break;
              }
            }
        }
    }

    /**
     * Write the local variable table. The necessary constants have already been
     * added to the constant table by the collect() method. The flowFields method
     * is used to determine which variables are alive at each pc.
     */
    public void writeLocalVariableTable(Environment env, MemberDefinition field, DataOutputStream out, ConstantPool tab) throws IOException {
        MemberDefinition locals[] = new MemberDefinition[maxvar];
        int i = 0;

        // Initialize arguments
        if ((field != null) && (field.getArguments() != null)) {
            int reg = 0;
            @SuppressWarnings("unchecked")
            Vector<MemberDefinition> v = (Vector)field.getArguments();
            for (Enumeration<MemberDefinition> e = v.elements(); e.hasMoreElements(); ) {
                MemberDefinition f = e.nextElement();
                locals[reg] = f;
                reg += f.getType().stackSize();
            }
        }

        flowFields(env, first, locals);
        LocalVariableTable lvtab = new LocalVariableTable();

        // Initialize arguments again
        for (i = 0; i < maxvar; i++)
            locals[i] = null;
        if ((field != null) && (field.getArguments() != null)) {
            int reg = 0;
            @SuppressWarnings("unchecked")
            Vector<MemberDefinition> v = (Vector)field.getArguments();
            for (Enumeration<MemberDefinition> e = v.elements(); e.hasMoreElements(); ) {
                MemberDefinition f = e.nextElement();
                locals[reg] = f;
                lvtab.define(f, reg, 0, maxpc);
                reg += f.getType().stackSize();
            }
        }

        int pcs[] = new int[maxvar];

        for (Instruction inst = first ; inst != null ; inst = inst.next)  {
            switch (inst.opc) {
              case opc_istore:   case opc_istore_0: case opc_istore_1:
              case opc_istore_2: case opc_istore_3: case opc_fstore:
              case opc_fstore_0: case opc_fstore_1: case opc_fstore_2:
              case opc_fstore_3:
              case opc_astore:   case opc_astore_0: case opc_astore_1:
              case opc_astore_2: case opc_astore_3:
              case opc_lstore:   case opc_lstore_0: case opc_lstore_1:
              case opc_lstore_2: case opc_lstore_3:
              case opc_dstore:   case opc_dstore_0: case opc_dstore_1:
              case opc_dstore_2: case opc_dstore_3:
                if (inst.value instanceof LocalVariable) {
                    LocalVariable v = (LocalVariable)inst.value;
                    int pc = (inst.next != null) ? inst.next.pc : inst.pc;
                    if (locals[v.slot] != null) {
                        lvtab.define(locals[v.slot], v.slot, pcs[v.slot], pc);
                    }
                    pcs[v.slot] = pc;
                    locals[v.slot] = v.field;
                }
                break;

              case opc_label: {
                // flush  previous labels
                for (i = 0 ; i < maxvar ; i++) {
                    if (locals[i] != null) {
                        lvtab.define(locals[i], i, pcs[i], inst.pc);
                    }
                }
                // init new labels
                int pc = inst.pc;
                MemberDefinition[] labelLocals = ((Label)inst).locals;
                if (labelLocals == null) { // unreachable code??
                    for (i = 0; i < maxvar; i++)
                        locals[i] = null;
                } else {
                    System.arraycopy(labelLocals, 0, locals, 0, maxvar);
                }
                for (i = 0 ; i < maxvar ; i++) {
                    pcs[i] = pc;
                }
                break;
              }
            }
        }

        // flush  remaining labels
        for (i = 0 ; i < maxvar ; i++) {
            if (locals[i] != null) {
                lvtab.define(locals[i], i, pcs[i], maxpc);
            }
        }

        // write the local variable table
        lvtab.write(env, out, tab);
    }

    /**
     * Return true if empty
     */
    public boolean empty() {
        return first == last;
    }

    /**
     * Print the byte codes
     */
    public void listing(PrintStream out) {
        out.println("-- listing --");
        for (Instruction inst = first ; inst != null ; inst = inst.next) {
            out.println(inst.toString());
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java Assembler.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.