001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.classloader;
014    
015    import java.io.DataInputStream;
016    import java.io.IOException;
017    
018    /**
019     * A java method's local variable information
020     */
021    public final class LocalVariableTable {
022      /**
023       * Local variables in this table
024       */
025      private final LocalVariable[] locals;
026    
027      /**
028       * Information needed to describe a local variable
029       */
030      static class LocalVariable {
031        /**
032         * The start PC location where the variable is active
033         */
034        private final int startPC;
035    
036        /**
037         * The variable is active in PC values [startPC, startPC+length].
038         */
039        private final int length;
040    
041        /**
042         * The variable's name.
043         */
044        private final Atom name;
045    
046        /**
047         * The variable's type descriptor.
048         */
049        private final Atom descriptor;
050    
051        /**
052         * The slot on the local variable stack where the variable is stored.
053         */
054        private final int frameIndex;
055    
056        /**
057         * Construct a local variable.
058         *
059         * @param startPC
060         * @param length
061         * @param name
062         * @param descriptor
063         * @param frameIndex
064         */
065        LocalVariable(int startPC, int length, Atom name, Atom descriptor, int frameIndex) {
066          this.startPC = startPC;
067          this.length = length;
068          this.name = name;
069          this.descriptor = descriptor;
070          this.frameIndex = frameIndex;
071        }
072    
073        /**
074         * String represenation of this local variable.
075         */
076        public String toString() {
077          return (startPC + " " +
078                 length + " " +
079                 name.toString() + " " +
080                 descriptor.toString() + " " +
081                 frameIndex + "\n");
082        }
083      }
084    
085      /**
086       * Construct the local variable table
087       *
088       * @param locals
089       */
090      LocalVariableTable(LocalVariable[] locals) {
091        this.locals = locals;
092      }
093    
094      /**
095       * Read the local variable table
096       *
097       * @return a local variable table or null if none were present
098       */
099      static LocalVariableTable readLocalVariableTable(DataInputStream input, int[] constantPool) throws IOException {
100        int numVars = input.readUnsignedShort();
101        if (numVars > 0) {
102          LocalVariable[] lvs = new LocalVariable[numVars];
103          for (int i = 0; i < numVars; ++i) {
104            LocalVariable lv = new LocalVariable(
105                input.readUnsignedShort(),
106                input.readUnsignedShort(),
107                ClassFileReader.getUtf(constantPool, input.readUnsignedShort()),
108                ClassFileReader.getUtf(constantPool, input.readUnsignedShort()),
109                input.readUnsignedShort());
110            lvs[i] = lv;
111          }
112          return new LocalVariableTable(lvs);
113        } else {
114          return null;
115        }
116      }
117    
118      /**
119       * String representation of the local variable table.
120       */
121      public String toString() {
122        StringBuilder sb = new StringBuilder();
123        sb.append("Local Variable Table: \n");
124        for (LocalVariable lv : locals) {
125          sb.append(lv.toString());
126        }
127        return sb.toString();
128      }
129    }