
com.ibm.wala.shrike.shrikeCT.LocalVariableTableWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.ibm.wala.shrike Show documentation
Show all versions of com.ibm.wala.shrike Show documentation
T. J. Watson Libraries for Analysis
The newest version!
/*
* Copyright (c) 2002,2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*/
package com.ibm.wala.shrike.shrikeCT;
import com.ibm.wala.shrike.shrikeBT.Compiler;
import java.util.Arrays;
/** This class helps emit LocalVariableTable attributes. */
public final class LocalVariableTableWriter extends ClassWriter.Element {
private final int attrID;
private int[] rawTable = emptyTable;
private static final int[] emptyTable = new int[0];
/**
* Create a blank LocalVariableTable.
*
* @throws IllegalArgumentException if w is null
*/
public LocalVariableTableWriter(ClassWriter w) {
if (w == null) {
throw new IllegalArgumentException("w is null");
}
attrID = w.addCPUtf8("LocalVariableTable");
}
/**
* Set the raw local variable table values. Consider using LocalVariableTableWriter.makeRawTable
* to build the raw values.
*
* @param table the raw values, a flattened sequence of (startPC, length, nameIndex, typeIndex,
* var) tuples
*/
public void setRawTable(int[] table) {
if (table == null) {
table = emptyTable;
}
if (table.length % 5 != 0) {
throw new IllegalArgumentException("Local variable table has bad length: " + table.length);
}
if (table.length / 5 > 0xFFFF) {
throw new IllegalArgumentException(
"Too many local variable table entries: " + table.length / 5);
}
for (int i = 0; i < table.length; i++) {
int v = table[i];
if (v < 0 || v > 0xFFFF) {
throw new IllegalArgumentException("Bad local variable table entry at " + i + ": " + v);
}
}
rawTable = table;
}
@Override
public int getSize() {
return 8 + rawTable.length * 2;
}
@Override
public int copyInto(byte[] buf, int offset) throws IllegalArgumentException {
ClassWriter.setUShort(buf, offset, attrID);
ClassWriter.setInt(buf, offset + 2, 2 + rawTable.length * 2);
ClassWriter.setUShort(buf, offset + 6, rawTable.length / 5);
offset += 8;
for (int element : rawTable) {
ClassWriter.setUShort(buf, offset, element);
offset += 2;
}
return offset;
}
/**
* Build a raw local variable table from a formatted variable map.
*
* @param varMap an array mapping bytecode offsets to a variable map for each offset; a variable
* map is a array of 2*localVars elements, containing a (nameIndex, typeIndex) for each local
* variable; the pair (0,0) indicates that there is no information about that local variable
* at that offset
* @throws IllegalArgumentException if varMap == null
*/
public static int[] makeRawTable(int[][] varMap, Compiler.Output output)
throws IllegalArgumentException {
if (varMap == null) {
throw new IllegalArgumentException("varMap == null");
}
try {
int varCount = 0;
for (int[] element : varMap) {
if (element != null) {
varCount = Math.max(varCount, element.length);
}
}
varCount /= 2;
int[] entries = new int[20];
int[] varEnd = new int[varCount];
Arrays.fill(varEnd, -1);
int[] lastVector = null;
int entryCount = 0;
for (int i = 0; i < varMap.length; i++) {
if (varMap[i] != lastVector) {
lastVector = varMap[i];
if (lastVector != null) {
for (int k = 0; k < lastVector.length / 2 && k < output.getMaxLocals(); k++) {
if (lastVector[k * 2] > 0 && i >= varEnd[k]) {
int entryOffset = entryCount * 5;
entryCount++;
if (entryCount * 5 > entries.length) {
entries = Arrays.copyOf(entries, entries.length * 2);
}
int nameIndex = lastVector[k * 2];
int typeIndex = lastVector[k * 2 + 1];
int end = i + 1;
while (end < varMap.length) {
if (varMap[end] == null
|| k * 2 >= varMap[end].length
|| varMap[end][k * 2] != nameIndex
|| varMap[end][k * 2 + 1] != typeIndex) {
break;
}
end++;
}
varEnd[k] = end;
entries[entryOffset] = i;
entries[entryOffset + 1] = end - i;
entries[entryOffset + 2] = nameIndex;
entries[entryOffset + 3] = typeIndex;
entries[entryOffset + 4] = k;
}
}
}
}
}
if (entryCount == 0) {
return null;
} else {
int[] r = new int[entryCount * 5];
System.arraycopy(entries, 0, r, 0, r.length);
return r;
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException("malformed varMap", e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy