WALA/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/NewInstruction.java

120 lines
3.4 KiB
Java

/*******************************************************************************
* 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.shrikeBT;
public final class NewInstruction extends Instruction {
final private String type;
final private short arrayBoundsCount;
protected NewInstruction(short opcode, String type, short arrayBoundsCount) {
super(opcode);
this.type = type;
this.arrayBoundsCount = arrayBoundsCount;
}
/**
* @param type the type of the object that will be returned (in JVM format, e.g., [Ljava/lang/String;)
* @param arrayBoundsCount the number of array dimensions to preconstruct (equal to the number of integer parameters this
* instruction expects)
* @throws IllegalArgumentException if type is null
*/
public static NewInstruction make(String type, int arrayBoundsCount) throws IllegalArgumentException {
if (type == null) {
throw new IllegalArgumentException("type is null");
}
if (arrayBoundsCount < 0 || arrayBoundsCount > 255) {
throw new IllegalArgumentException("Too many array bounds: " + arrayBoundsCount);
} else {
if (type.length() < arrayBoundsCount + 1) {
throw new IllegalArgumentException("Not enough array nesting in " + type + " for bounds count " + arrayBoundsCount);
}
for (int i = 0; i < arrayBoundsCount; i++) {
if (type.charAt(i) != '[') {
throw new IllegalArgumentException("Not enough array nesting in " + type + " for bounds count " + arrayBoundsCount);
}
}
short opcode;
if (arrayBoundsCount == 0) {
opcode = OP_new;
} else if (arrayBoundsCount == 1) {
char ch = type.charAt(1);
if (ch != 'L' && ch != '[') {
// array of primitive type
opcode = OP_newarray;
} else {
opcode = OP_anewarray;
}
} else {
opcode = OP_multianewarray;
}
return new NewInstruction(opcode, type, (short) arrayBoundsCount);
}
}
@Override
public boolean equals(Object o) {
if (o instanceof NewInstruction) {
NewInstruction i = (NewInstruction) o;
return i.type.equals(type) && i.arrayBoundsCount == arrayBoundsCount;
} else {
return false;
}
}
public int getArrayBoundsCount() {
return arrayBoundsCount;
}
@Override
public int hashCode() {
return 13111143 * type.hashCode() + arrayBoundsCount;
}
@Override
public int getPoppedCount() {
return arrayBoundsCount;
}
@Override
public String getPushedType(String[] types) {
return type;
}
@Override
public byte getPushedWordSize() {
return 1;
}
public String getType() {
return type;
}
@Override
public String toString() {
return "New(" + type + "," + arrayBoundsCount + ")";
}
@Override
public void visit(IInstruction.Visitor v) throws IllegalArgumentException {
if (v == null) {
throw new IllegalArgumentException();
}
v.visitNew(this);
}
@Override
public boolean isPEI() {
return true;
}
}