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        @Override
077        public String toString() {
078          return (startPC + " " +
079                 length + " " +
080                 name.toString() + " " +
081                 descriptor.toString() + " " +
082                 frameIndex + "\n");
083        }
084      }
085    
086      /**
087       * Construct the local variable table
088       *
089       * @param locals
090       */
091      LocalVariableTable(LocalVariable[] locals) {
092        this.locals = locals;
093      }
094    
095      /**
096       * Read the local variable table
097       *
098       * @return a local variable table or null if none were present
099       */
100      static LocalVariableTable readLocalVariableTable(DataInputStream input, int[] constantPool) throws IOException {
101        int numVars = input.readUnsignedShort();
102        if (numVars > 0) {
103          LocalVariable[] lvs = new LocalVariable[numVars];
104          for (int i = 0; i < numVars; ++i) {
105            LocalVariable lv = new LocalVariable(
106                input.readUnsignedShort(),
107                input.readUnsignedShort(),
108                ClassFileReader.getUtf(constantPool, input.readUnsignedShort()),
109                ClassFileReader.getUtf(constantPool, input.readUnsignedShort()),
110                input.readUnsignedShort());
111            lvs[i] = lv;
112          }
113          return new LocalVariableTable(lvs);
114        } else {
115          return null;
116        }
117      }
118    
119      /**
120       * String representation of the local variable table.
121       */
122      @Override
123      public String toString() {
124        StringBuilder sb = new StringBuilder();
125        sb.append("Local Variable Table: \n");
126        for (LocalVariable lv : locals) {
127          sb.append(lv.toString());
128        }
129        return sb.toString();
130      }
131    }