/* * Copyright (c) 2006-2012 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit.internal.util; import mockit.external.asm4.*; import static mockit.external.asm4.Opcodes.*; public final class TypeConversion { private static final String[] PRIMITIVE_WRAPPER_TYPE = { null, "java/lang/Boolean", "java/lang/Character", "java/lang/Byte", "java/lang/Short", "java/lang/Integer", "java/lang/Float", "java/lang/Long", "java/lang/Double" }; private static final String PRIMITIVE_WRAPPER_TYPES = "java/lang/Boolean java/lang/Character java/lang/Byte java/lang/Short " + "java/lang/Integer java/lang/Float java/lang/Long java/lang/Double"; private static final String[] UNBOXING_NAME = { null, "booleanValue", "charValue", "byteValue", "shortValue", "intValue", "floatValue", "longValue", "doubleValue" }; private static final String[] UNBOXING_DESC = {null, "()Z", "()C", "()B", "()S", "()I", "()F", "()J", "()D"}; public static void generateCastToObject(MethodVisitor mv, Type type) { int sort = type.getSort(); if (sort < Type.ARRAY) { String wrapperType = PRIMITIVE_WRAPPER_TYPE[sort]; String desc = '(' + type.getDescriptor() + ")L" + wrapperType + ';'; mv.visitMethodInsn(INVOKESTATIC, wrapperType, "valueOf", desc); } } public static void generateCastFromObject(MethodVisitor mv, Type toType) { int sort = toType.getSort(); if (sort == Type.VOID) { mv.visitInsn(POP); } else { generateTypeCheck(mv, toType); if (sort < Type.ARRAY) { mv.visitMethodInsn(INVOKEVIRTUAL, PRIMITIVE_WRAPPER_TYPE[sort], UNBOXING_NAME[sort], UNBOXING_DESC[sort]); } } } private static void generateTypeCheck(MethodVisitor mv, Type toType) { int sort = toType.getSort(); String typeDesc; switch (sort) { case Type.ARRAY: typeDesc = toType.getDescriptor(); break; case Type.OBJECT: typeDesc = toType.getInternalName(); break; default: typeDesc = PRIMITIVE_WRAPPER_TYPE[sort]; } mv.visitTypeInsn(CHECKCAST, typeDesc); } public static void generateCastOrUnboxing(MethodVisitor mv, Type parameterType, int opcode) { if (opcode == ASTORE) { generateTypeCheck(mv, parameterType); return; } int sort = parameterType.getSort(); String typeDesc; if (sort < Type.ARRAY) { typeDesc = PRIMITIVE_WRAPPER_TYPE[sort]; } else { typeDesc = parameterType.getInternalName(); int i = PRIMITIVE_WRAPPER_TYPES.indexOf(typeDesc); if (i >= 0) { sort = i / 20 + 1; } else if (opcode == ISTORE && "java/lang/Number".equals(typeDesc)) { sort = Type.INT; } else { sort = Type.INT; switch (opcode) { case FSTORE: sort = Type.FLOAT; break; case LSTORE: sort = Type.LONG; break; case DSTORE: sort = Type.DOUBLE; } typeDesc = PRIMITIVE_WRAPPER_TYPE[sort]; } } mv.visitTypeInsn(CHECKCAST, typeDesc); mv.visitMethodInsn(INVOKEVIRTUAL, typeDesc, UNBOXING_NAME[sort], UNBOXING_DESC[sort]); } public static boolean isPrimitiveWrapper(String typeDesc) { return PRIMITIVE_WRAPPER_TYPES.contains(typeDesc); } public static boolean isBoxing(String owner, String name, String desc) { return desc.charAt(2) == ')' && "valueOf".equals(name) && isPrimitiveWrapper(owner); } public static boolean isUnboxing(int opcode, String owner, String desc) { return opcode == INVOKEVIRTUAL && desc.charAt(1) == ')' && isPrimitiveWrapper(owner); } }