120 lines
3.4 KiB
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;
|
|
}
|
|
} |