下面列出了org.objectweb.asm.Type#DOUBLE 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private static void hash_primitive(CodeEmitter e, Type type) {
switch (type.getSort()) {
case Type.BOOLEAN:
// f ? 0 : 1
e.push(1);
e.math(e.XOR, Type.INT_TYPE);
break;
case Type.FLOAT:
// Float.floatToIntBits(f)
e.invoke_static(Constants.TYPE_FLOAT, FLOAT_TO_INT_BITS);
break;
case Type.DOUBLE:
// Double.doubleToLongBits(f), hash_code(Long.TYPE)
e.invoke_static(Constants.TYPE_DOUBLE, DOUBLE_TO_LONG_BITS);
// fall through
case Type.LONG:
hash_long(e);
}
}
@Override
protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) {
Type expectedType = expected.getType();
Type type = value.getType();
switch (expectedType.getSort()) {
case Type.INT:
case Type.FLOAT:
case Type.LONG:
case Type.DOUBLE:
return type.equals(expectedType);
case Type.ARRAY:
case Type.OBJECT:
if ("Lnull;".equals(type.getDescriptor())) {
return true;
} else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
return isAssignableFrom(expectedType, type);
} else {
return false;
}
default:
throw new Error("Internal error");
}
}
/**
* Handle adding the variable to the maps.
*
* @param ast
* AST containing variable.
* @param root
* Root of AST.
* @param index
* Index to add variable to.
*
* @throws AssemblerException
* When fetching type information from the var-reference fails.
*/
private void addVariable(VariableReference ast, RootAST root, int index) throws AssemblerException {
String name = ast.getVariableName().getName();
// Fetch type information
int sort = -1;
if(ast instanceof Instruction)
sort = getType(((Instruction) ast).getOpcode().getOpcode());
else if(ast instanceof DefinitionArgAST) {
String desc = ((DefinitionArgAST) ast).getDesc().getDesc();
sort = Type.getType(desc).getSort();
}
if(sort == -1) {
int line = ((AST)ast).getLine();
throw new AssemblerException("Unknown variable type: " + ast, line);
}
// Update maps
int used = index + TypeUtil.sortToSize(sort);
if (used > maxIndex)
maxIndex = used;
nameToIndex.put(name, index);
indexToSort.put(index, sort);
if (sort >= Type.BOOLEAN && sort <= Type.DOUBLE)
nameToDesc.put(name, sortToDesc(sort));
}
public static int getReturnOpcode(Type type) {
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
return Opcodes.IRETURN;
case Type.FLOAT:
return Opcodes.FRETURN;
case Type.LONG:
return Opcodes.LRETURN;
case Type.DOUBLE:
return Opcodes.DRETURN;
case Type.ARRAY:
case Type.OBJECT:
return Opcodes.ARETURN;
case Type.VOID:
return Opcodes.RETURN;
default:
throw new AssertionError("Unknown type sort: " + type.getClassName());
}
}
public static AbstractInsnNode nullValueForType(Type returnType) {
switch (returnType.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.CHAR:
case Type.SHORT:
case Type.INT:
return new InsnNode(ICONST_0);
case Type.FLOAT:
return new InsnNode(FCONST_0);
case Type.DOUBLE:
return new InsnNode(DCONST_0);
case Type.LONG:
return new InsnNode(LCONST_0);
case Type.ARRAY:
case Type.OBJECT:
return new InsnNode(ACONST_NULL);
default:
throw new UnsupportedOperationException();
}
}
private void boxingIfShould(final String desc) {
switch (Type.getType(desc).getSort()) {
case Type.BOOLEAN:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
break;
case Type.BYTE:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
break;
case Type.CHAR:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
break;
case Type.SHORT:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
break;
case Type.INT:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
break;
case Type.FLOAT:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
break;
case Type.LONG:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
break;
case Type.DOUBLE:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
break;
}
}
/**
* Pops the stack in to the the local variable table. You may run in to problems if the item on top of the stack isn't of the same type
* as the variable it's being put in to.
* @param variable variable within the local variable table to save to
* @return instructions to pop an item off the top of the stack and save it to {@code variable}
* @throws NullPointerException if any argument is {@code null}
* @throws IllegalArgumentException if {@code variable} has been released
*/
public static InsnList saveVar(Variable variable) {
Validate.notNull(variable);
InsnList ret = new InsnList();
switch (variable.getType().getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.CHAR:
case Type.SHORT:
case Type.INT:
ret.add(new VarInsnNode(Opcodes.ISTORE, variable.getIndex()));
break;
case Type.LONG:
ret.add(new VarInsnNode(Opcodes.LSTORE, variable.getIndex()));
break;
case Type.FLOAT:
ret.add(new VarInsnNode(Opcodes.FSTORE, variable.getIndex()));
break;
case Type.DOUBLE:
ret.add(new VarInsnNode(Opcodes.DSTORE, variable.getIndex()));
break;
case Type.OBJECT:
case Type.ARRAY:
ret.add(new VarInsnNode(Opcodes.ASTORE, variable.getIndex()));
break;
default:
throw new IllegalStateException(); // should never happen, there is code in Variable/VariableTable to make sure invalid
// types aren't set
}
return ret;
}
private static void loadType(MethodVisitor mv, Type type, Type ownerType) {
switch (type.getSort()) {
case Type.VOID:
mv.visitFieldInsn(GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;");
break;
case Type.BOOLEAN:
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
break;
case Type.CHAR:
mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
break;
case Type.BYTE:
mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
break;
case Type.SHORT:
mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
break;
case Type.INT:
mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
break;
case Type.FLOAT:
mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
break;
case Type.LONG:
mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
break;
case Type.DOUBLE:
mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
break;
case Type.ARRAY:
loadArrayType(mv, type, ownerType);
break;
default:
loadObjectType(mv, type, ownerType);
}
}
@Override
protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) {
Type expectedType = expected.getType();
Type type = value.getType();
switch (expectedType.getSort()) {
case Type.INT:
case Type.FLOAT:
case Type.LONG:
case Type.DOUBLE:
return type.equals(expectedType);
case Type.ARRAY:
case Type.OBJECT:
if (type.equals(NULL_TYPE)) {
return true;
} else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
if (isAssignableFrom(expectedType, type)) {
return true;
} else if (getClass(expectedType).isInterface()) {
// The merge of class or interface types can only yield class types (because it is not
// possible in general to find an unambiguous common super interface, due to multiple
// inheritance). Because of this limitation, we need to relax the subtyping check here
// if 'value' is an interface.
return Object.class.isAssignableFrom(getClass(type));
} else {
return false;
}
} else {
return false;
}
default:
throw new AssertionError();
}
}
@Override
public void generate(CodeEmitter code) {
// VOID, BOOLEAN, CHAR, BYTE, SHORT, INT, FLOAT, LONG, DOUBLE, ARRAY, OBJECT or METHOD.
int opcode;
switch (getType().getJVMType().getSort()) {
case Type.VOID:
case Type.METHOD:
throw new UnsupportedOperationException("Unsupported NullExpr type: " + getType());
case Type.BOOLEAN:
case Type.SHORT:
case Type.INT:
case Type.CHAR:
opcode = Opcodes.ICONST_0;
break;
case Type.FLOAT:
opcode = Opcodes.FCONST_0;
break;
case Type.LONG:
opcode = Opcodes.LCONST_0;
break;
case Type.DOUBLE:
opcode = Opcodes.DCONST_0;
break;
case Type.ARRAY:
case Type.OBJECT:
opcode = Opcodes.ACONST_NULL;
break;
default:
throw new UnsupportedOperationException("Unknown NullExpr type: " + getType());
}
code.getMethodVisitor().visitInsn(opcode);
if (opcode == Opcodes.ACONST_NULL) {
code.cast(getType(), AnyTypeWidget.getInstance());
}
}
/**
* Generates the instruction to push the given value on the stack.
*
* @param value the value to be pushed on the stack.
*/
public void push(final Type value) {
if (value == null) {
mv.visitInsn(Opcodes.ACONST_NULL);
} else {
switch (value.getSort()) {
case Type.BOOLEAN:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.CHAR:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.BYTE:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.SHORT:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.INT:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.FLOAT:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.LONG:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.DOUBLE:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double", "TYPE", CLASS_DESCRIPTOR);
break;
default:
mv.visitLdcInsn(value);
break;
}
}
}
@Override
protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) {
Type expectedType = expected.getType();
Type type = value.getType();
switch (expectedType.getSort()) {
case Type.INT:
case Type.FLOAT:
case Type.LONG:
case Type.DOUBLE:
return type.equals(expectedType);
case Type.ARRAY:
case Type.OBJECT:
if (type.equals(NULL_TYPE)) {
return true;
} else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
if (isAssignableFrom(expectedType, type)) {
return true;
} else if (getClass(expectedType).isInterface()) {
// The merge of class or interface types can only yield class types (because it is not
// possible in general to find an unambiguous common super interface, due to multiple
// inheritance). Because of this limitation, we need to relax the subtyping check here
// if 'value' is an interface.
return Object.class.isAssignableFrom(getClass(type));
} else {
return false;
}
} else {
return false;
}
default:
throw new AssertionError();
}
}
/**
* Constructs a new local variable of the given type.
*
* @param type the type of the local variable to be created.
* @return the identifier of the newly created local variable.
*/
public int newLocal(final Type type) {
Object localType;
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
localType = Opcodes.INTEGER;
break;
case Type.FLOAT:
localType = Opcodes.FLOAT;
break;
case Type.LONG:
localType = Opcodes.LONG;
break;
case Type.DOUBLE:
localType = Opcodes.DOUBLE;
break;
case Type.ARRAY:
localType = type.getDescriptor();
break;
case Type.OBJECT:
localType = type.getInternalName();
break;
default:
throw new AssertionError();
}
int local = newLocalMapping(type);
setLocalType(local, type);
setFrameLocal(local, localType);
return local;
}
public static Type asSimpleType(Type type) {
if (type.getSort() >= Type.BOOLEAN && type.getSort() <= Type.INT) {
return Type.INT_TYPE;
} else if (type.getSort() >= Type.FLOAT && type.getSort() <= Type.DOUBLE) {
return type;
} else {
return OBJECT_TYPE;
}
}
private static void enhanceForPutValueObject(ClassVisitor cw, String accessClassNm, String clazzNm, Field[] fields) {
int maxStack = 6;
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "putValue", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, accessClassNm, "fieldNames", "[Ljava/lang/String;");
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "binarySearch", "([Ljava/lang/Object;Ljava/lang/Object;)I");
mv.visitVarInsn(ISTORE, 4);
mv.visitVarInsn(ILOAD, 4);
if (fields.length > 0) {
maxStack = 5;
Label[] labels = constructLabels(fields);
Label defaultLabel = new Label();
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
for (int i = 0, n = labels.length; i < n; i++) {
Field field = fields[i];
mv.visitLabel(labels[i]);
mv.visitFrame(F_SAME, 0, null, 0, null);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, clazzNm);
mv.visitVarInsn(ALOAD, 3);
Type fieldType = Type.getType(field.getType());
switch (fieldType.getSort()) {
case Type.BOOLEAN:
mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
break;
case Type.BYTE:
mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
break;
case Type.CHAR:
mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
break;
case Type.SHORT:
mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
break;
case Type.INT:
mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
break;
case Type.FLOAT:
mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
break;
case Type.LONG:
mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
break;
case Type.DOUBLE:
mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
break;
case Type.ARRAY:
mv.visitTypeInsn(CHECKCAST, fieldType.getDescriptor());
break;
case Type.OBJECT:
mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName());
break;
}
mv.visitFieldInsn(PUTFIELD, clazzNm, field.getName(), fieldType.getDescriptor());
mv.visitInsn(RETURN);
}
mv.visitLabel(defaultLabel);
mv.visitFrame(F_SAME, 0, null, 0, null);
} else {
maxStack = 6;
}
enhanceForThrowingException(mv, IllegalArgumentException.class, "Field was not found", "Ljava/lang/Object;", ALOAD, 2);
mv.visitMaxs(maxStack, 5);
mv.visitEnd();
}
private static void enhanceForGetValuePrimitive(ClassVisitor cw, String accessClassNm, String clazzNm, Field[] fields, Type type) {
String methodName;
final String typeNm = type.getDescriptor();
final int instruction;
switch (type.getSort()) {
case Type.BOOLEAN:
methodName = "getBooleanValue";
instruction = IRETURN;
break;
case Type.BYTE:
methodName = "getByteValue";
instruction = IRETURN;
break;
case Type.CHAR:
methodName = "getCharValue";
instruction = IRETURN;
break;
case Type.SHORT:
methodName = "getShortValue";
instruction = IRETURN;
break;
case Type.INT:
methodName = "getIntValue";
instruction = IRETURN;
break;
case Type.FLOAT:
methodName = "getFloatValue";
instruction = FRETURN;
break;
case Type.LONG:
methodName = "getLongValue";
instruction = LRETURN;
break;
case Type.DOUBLE:
methodName = "getDoubleValue";
instruction = DRETURN;
break;
default:
methodName = "getValue";
instruction = ARETURN;
break;
}
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "(Ljava/lang/Object;Ljava/lang/String;)" + typeNm, null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, accessClassNm, "fieldNames", "[Ljava/lang/String;");
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "binarySearch", "([Ljava/lang/Object;Ljava/lang/Object;)I");
mv.visitVarInsn(ISTORE, 3);
mv.visitVarInsn(ILOAD, 3);
final int maxStack;
if (fields.length > 0) {
maxStack = 5;
Label[] labels = constructLabels(fields);
Label defaultLabel = new Label();
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
for (int i = 0, n = labels.length; i < n; i++) {
Field field = fields[i];
mv.visitLabel(labels[i]);
mv.visitFrame(F_SAME, 0, null, 0, null);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, clazzNm);
mv.visitFieldInsn(GETFIELD, clazzNm, field.getName(), typeNm);
mv.visitInsn(instruction);
}
mv.visitLabel(defaultLabel);
mv.visitFrame(F_SAME, 0, null, 0, null);
} else {
maxStack = 6;
}
enhanceForThrowingException(mv, IllegalArgumentException.class, "Field was not found", "Ljava/lang/Object;", ALOAD, 2);
mv.visitMaxs(maxStack, 4);
mv.visitEnd();
}
/**
* Compute sizes required for the storage arrays that will contain the operand stack at this frame.
* @param frame frame to compute for
* @param offset the position within the operand stack to start calculating
* @param length the number of stack items to include in calculation
* @return size required by each storage array
* @throws NullPointerException if any argument is {@code null}
* @throws IllegalArgumentException if any numeric argument is negative, or if {@code offset + length} is larger than the size of the
* operand stack
*/
public static StorageSizes computeSizes(Frame<BasicValue> frame, int offset, int length) {
Validate.notNull(frame);
Validate.isTrue(offset >= 0);
Validate.isTrue(length >= 0);
Validate.isTrue(offset < frame.getStackSize());
Validate.isTrue(offset + length <= frame.getStackSize());
// Count size required for each storage array
int intsSize = 0;
int longsSize = 0;
int floatsSize = 0;
int doublesSize = 0;
int objectsSize = 0;
for (int i = offset + length - 1; i >= offset; i--) {
BasicValue basicValue = frame.getStack(i);
Type type = basicValue.getType();
// If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise'
// the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this
// point in the code so we can avoid saving it. When we load it back up, we can simply push a null in to that slot, thereby
// keeping the same 'Lnull;' type.
if ("Lnull;".equals(type.getDescriptor())) {
continue;
}
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.SHORT:
case Type.CHAR:
case Type.INT:
intsSize++;
break;
case Type.FLOAT:
floatsSize++;
break;
case Type.LONG:
longsSize++;
break;
case Type.DOUBLE:
doublesSize++;
break;
case Type.ARRAY:
case Type.OBJECT:
objectsSize++;
break;
case Type.METHOD:
case Type.VOID:
default:
throw new IllegalStateException();
}
}
return new StorageSizes(intsSize, longsSize, floatsSize, doublesSize, objectsSize);
}
/**
* Constructs a new {@link AnalyzerAdapter}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
* @param owner the owner's class name.
* @param access the method's access flags (see {@link Opcodes}).
* @param name the method's name.
* @param descriptor the method's descriptor (see {@link Type}).
* @param methodVisitor the method visitor to which this adapter delegates calls. May be {@literal
* null}.
*/
protected AnalyzerAdapter(
final int api,
final String owner,
final int access,
final String name,
final String descriptor,
final MethodVisitor methodVisitor) {
super(api, methodVisitor);
this.owner = owner;
locals = new ArrayList<Object>();
stack = new ArrayList<Object>();
uninitializedTypes = new HashMap<Object, Object>();
if ((access & Opcodes.ACC_STATIC) == 0) {
if ("<init>".equals(name)) {
locals.add(Opcodes.UNINITIALIZED_THIS);
} else {
locals.add(owner);
}
}
for (Type argumentType : Type.getArgumentTypes(descriptor)) {
switch (argumentType.getSort()) {
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
locals.add(Opcodes.INTEGER);
break;
case Type.FLOAT:
locals.add(Opcodes.FLOAT);
break;
case Type.LONG:
locals.add(Opcodes.LONG);
locals.add(Opcodes.TOP);
break;
case Type.DOUBLE:
locals.add(Opcodes.DOUBLE);
locals.add(Opcodes.TOP);
break;
case Type.ARRAY:
locals.add(argumentType.getDescriptor());
break;
case Type.OBJECT:
locals.add(argumentType.getInternalName());
break;
default:
throw new AssertionError();
}
}
maxLocals = locals.size();
}
static ComputationalCategory getCategory(Type t) {
if (t.getSort() == Type.LONG
|| t.getSort() == Type.DOUBLE)
return ComputationalCategory.CAT_2;
return ComputationalCategory.CAT_1;
}
public static boolean isPrimitive(Type type) {
return type.getSort() >= Type.BOOLEAN && type.getSort() <= Type.DOUBLE;
}