Mirror of the BLOAT repository
https://www.cs.purdue.edu/homes/hosking/bloat/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
5.5 KiB
232 lines
5.5 KiB
/**
|
|
* All files in the distribution of BLOAT (Bytecode Level Optimization and
|
|
* Analysis tool for Java(tm)) are Copyright 1997-2001 by the Purdue
|
|
* Research Foundation of Purdue University. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
package EDU.purdue.cs.bloat.editor;
|
|
|
|
/**
|
|
* Switch is used to hold the lookup values and branch targets of a tableswitch
|
|
* or lookup switch instruction.
|
|
* <p>
|
|
* The tableswitch low-to-high range of values is represented by storing each
|
|
* lookup value in the range. This allows the tableswitch to be replaced with a
|
|
* lookupswitch if branches are deleted.
|
|
*
|
|
* @author Nate Nystrom (<a
|
|
* href="mailto:nystrom@cs.purdue.edu">nystrom@cs.purdue.edu</a>)
|
|
*/
|
|
public class Switch {
|
|
private Label defaultTarget;
|
|
|
|
private Label[] targets;
|
|
|
|
private int[] values;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param defaultTarget
|
|
* The default target of the switch.
|
|
* @param targets
|
|
* The non-default branch targets of the switch.
|
|
* @param values
|
|
* The lookup values of the switch. This array must be the same
|
|
* size as the targets array.
|
|
*/
|
|
public Switch(final Label defaultTarget, final Label[] targets,
|
|
final int[] values) {
|
|
this.defaultTarget = defaultTarget;
|
|
this.targets = targets;
|
|
this.values = values;
|
|
sort();
|
|
uniq();
|
|
}
|
|
|
|
/**
|
|
* Set the default target of the switch.
|
|
*
|
|
* @param target
|
|
* The default target of the switch.
|
|
*/
|
|
public void setDefaultTarget(final Label target) {
|
|
defaultTarget = target;
|
|
}
|
|
|
|
/**
|
|
* Get the default target of the switch.
|
|
*
|
|
* @return The default target of the switch.
|
|
*/
|
|
public Label defaultTarget() {
|
|
return defaultTarget;
|
|
}
|
|
|
|
/**
|
|
* Get the non-default branch targets of the switch. The targets are sorted
|
|
* by the corresponding lookup value.
|
|
*
|
|
* @return The non-default branch targets of the switch.
|
|
*/
|
|
public Label[] targets() {
|
|
return targets;
|
|
}
|
|
|
|
/**
|
|
* Get the lookup values of the switch, sorted low to high.
|
|
*
|
|
* @return The lookup values of the switch.
|
|
*/
|
|
public int[] values() {
|
|
return values;
|
|
}
|
|
|
|
/**
|
|
* Check if the all the values in the range of lookup values are contiguous.
|
|
* If they are, a table switch can be used. If not a lookupswitch can be
|
|
* used.
|
|
*
|
|
* @return true if contiguous, false if not.
|
|
*/
|
|
public boolean hasContiguousValues() {
|
|
return values.length == highValue() - lowValue() + 1;
|
|
}
|
|
|
|
/**
|
|
* Get the low value in the range the lookup values.
|
|
*
|
|
* @return The low value.
|
|
*/
|
|
public int lowValue() {
|
|
return values[0];
|
|
}
|
|
|
|
/**
|
|
* Get the high value in the range the lookup values.
|
|
*
|
|
* @return The high value.
|
|
*/
|
|
public int highValue() {
|
|
return values[values.length - 1];
|
|
}
|
|
|
|
/**
|
|
* Sort the targets and values arrays so that values is sorted low to high.
|
|
*/
|
|
private void sort() {
|
|
quicksort(0, values.length - 1);
|
|
}
|
|
|
|
/**
|
|
* Utility function to sort the targets and values arrays so that values is
|
|
* sorted low to high.
|
|
*
|
|
* @param p
|
|
* The low index of the portion of the array to sort.
|
|
* @param r
|
|
* The high index of the portion of the array to sort.
|
|
*/
|
|
private void quicksort(final int p, final int r) {
|
|
if (p < r) {
|
|
final int q = partition(p, r);
|
|
quicksort(p, q);
|
|
quicksort(q + 1, r);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Utility function to sort the targets and values arrays so that values is
|
|
* sorted low to high.
|
|
* <p>
|
|
* Partition the arrays so that the values less than values[p] are to the
|
|
* left.
|
|
*
|
|
* @param p
|
|
* The low index of the portion of the array to sort.
|
|
* @param r
|
|
* The high index of the portion of the array to sort.
|
|
* @return The index at which the partition finished.
|
|
*/
|
|
private int partition(final int p, final int r) {
|
|
final int x = values[p];
|
|
int i = p - 1;
|
|
int j = r + 1;
|
|
|
|
while (true) {
|
|
do {
|
|
j--;
|
|
} while (values[j] > x);
|
|
|
|
do {
|
|
i++;
|
|
} while (values[i] < x);
|
|
|
|
if (i < j) {
|
|
final int v = values[i];
|
|
values[i] = values[j];
|
|
values[j] = v;
|
|
|
|
final Label t = targets[i];
|
|
targets[i] = targets[j];
|
|
targets[j] = t;
|
|
} else {
|
|
return j;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove duplicates from the values and targets arrays.
|
|
*/
|
|
private void uniq() {
|
|
if (values.length == 0) {
|
|
return;
|
|
}
|
|
|
|
final int[] v = new int[values.length];
|
|
final Label[] t = new Label[values.length];
|
|
|
|
v[0] = values[0];
|
|
t[0] = targets[0];
|
|
|
|
int j = 1;
|
|
|
|
for (int i = 1; i < values.length; i++) {
|
|
if (v[j - 1] != values[i]) {
|
|
v[j] = values[i];
|
|
t[j] = targets[i];
|
|
j++;
|
|
}
|
|
}
|
|
|
|
values = new int[j];
|
|
System.arraycopy(v, 0, values, 0, j);
|
|
|
|
targets = new Label[j];
|
|
System.arraycopy(t, 0, targets, 0, j);
|
|
}
|
|
|
|
/**
|
|
* Convert the operand to a string.
|
|
*
|
|
* @return A string representation of the operand.
|
|
*/
|
|
public String toString() {
|
|
return "" + values.length + " pairs";
|
|
}
|
|
}
|
|
|