001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.pack200.bytecode;
018:
019: import java.io.DataOutputStream;
020: import java.io.IOException;
021: import java.util.ArrayList;
022: import java.util.List;
023:
024: public class LocalVariableTableAttribute extends BCIRenumberedAttribute {
025:
026: private int local_variable_table_length;
027: private int[] start_pcs;
028: private int[] lengths;
029: private int[] name_indexes;
030: private int[] descriptor_indexes;
031: private int[] indexes;
032: private CPUTF8[] names;
033: private CPUTF8[] descriptors;
034:
035: public LocalVariableTableAttribute(int local_variable_table_length,
036: int[] start_pcs, int[] lengths, CPUTF8[] names,
037: CPUTF8[] descriptors, int[] indexes) {
038: super ("LocalVariableTable");
039: this .local_variable_table_length = local_variable_table_length;
040: this .start_pcs = start_pcs;
041: this .lengths = lengths;
042: this .names = names;
043: this .descriptors = descriptors;
044: this .indexes = indexes;
045: }
046:
047: protected int getLength() {
048: return 2 + (10 * local_variable_table_length);
049: }
050:
051: protected void writeBody(DataOutputStream dos) throws IOException {
052: dos.writeShort(local_variable_table_length);
053: for (int i = 0; i < local_variable_table_length; i++) {
054: dos.writeShort(start_pcs[i]);
055: dos.writeShort(lengths[i]);
056: dos.writeShort(name_indexes[i]);
057: dos.writeShort(descriptor_indexes[i]);
058: dos.writeShort(indexes[i]);
059: }
060: }
061:
062: protected ClassFileEntry[] getNestedClassFileEntries() {
063: ArrayList nestedEntries = new ArrayList();
064: nestedEntries.add(getAttributeName());
065: for (int i = 0; i < local_variable_table_length; i++) {
066: nestedEntries.add(names[i]);
067: nestedEntries.add(descriptors[i]);
068: }
069: ClassFileEntry[] nestedEntryArray = new ClassFileEntry[nestedEntries
070: .size()];
071: nestedEntries.toArray(nestedEntryArray);
072: return nestedEntryArray;
073: }
074:
075: protected void resolve(ClassConstantPool pool) {
076: super .resolve(pool);
077: name_indexes = new int[local_variable_table_length];
078: descriptor_indexes = new int[local_variable_table_length];
079: for (int i = 0; i < local_variable_table_length; i++) {
080: names[i].resolve(pool);
081: descriptors[i].resolve(pool);
082: name_indexes[i] = pool.indexOf(names[i]);
083: descriptor_indexes[i] = pool.indexOf(descriptors[i]);
084: }
085: }
086:
087: public String toString() {
088: return "LocalVariableTable: " + +local_variable_table_length
089: + " variables";
090: }
091:
092: protected int[] getStartPCs() {
093: return start_pcs;
094: }
095:
096: /* (non-Javadoc)
097: * @see org.apache.harmony.pack200.bytecode.BCIRenumberedAttribute#renumber(java.util.List)
098: */
099: public void renumber(List byteCodeOffsets) {
100: // Remember the unrenumbered start_pcs, since that's used later
101: // to calculate end position.
102: int[] unrenumbered_start_pcs = new int[start_pcs.length];
103: System.arraycopy(start_pcs, 0, unrenumbered_start_pcs, 0,
104: start_pcs.length);
105:
106: // Next renumber start_pcs in place
107: super .renumber(byteCodeOffsets);
108:
109: // lengths are BRANCH5 encoded, not BCI-encoded.
110: // In other words:
111: // start_pc is BCI5 start_pc
112: // end_pc is byteCodeOffset[(index of start_pc in byteCodeOffset) + (encoded length)]
113: // real length = end_pc - start_pc
114: // special case if end_pc is beyond end of bytecode array
115:
116: // First figure out the maximum size of the byteCodeOffsets array
117: int lastInstruction = ((Integer) byteCodeOffsets
118: .get(byteCodeOffsets.size() - 1)).intValue();
119: int maxSize = lastInstruction + 1;
120:
121: // Iterate through the lengths and update each in turn.
122: // This is done in place in the lengths array.
123: for (int index = 0; index < lengths.length; index++) {
124: int start_pc = start_pcs[index];
125: int revisedLength = -1;
126: int encodedLength = lengths[index];
127:
128: // First get the index of the start_pc in the byteCodeOffsets
129: int indexOfStartPC = unrenumbered_start_pcs[index];
130: // Given the index of the start_pc, we can now add
131: // the encodedLength to it to get the stop index.
132: int stopIndex = indexOfStartPC + encodedLength;
133:
134: // Length can either be an index into the byte code offsets, or one beyond the
135: // end of the byte code offsets. Need to determine which this is.
136: if (stopIndex == byteCodeOffsets.size()) {
137: // Pointing to one past the end of the byte code array
138: revisedLength = maxSize - start_pc;
139: } else {
140: // We're indexed into the byte code array
141: int stopValue = ((Integer) byteCodeOffsets
142: .get(stopIndex)).intValue();
143: revisedLength = stopValue - start_pc;
144: }
145: lengths[index] = revisedLength;
146: }
147: }
148: }
|