static void emitFromNativeConversion( AsmBuilder builder, SkinnyMethodAdapter mv, FromNativeType fromNativeType, Class nativeClass) { // If there is a result converter, retrieve it and put on the stack FromNativeConverter fromNativeConverter = fromNativeType.getFromNativeConverter(); if (fromNativeConverter != null) { convertPrimitive( mv, nativeClass, unboxedType(fromNativeConverter.nativeType()), fromNativeType.getNativeType()); boxValue(builder, mv, fromNativeConverter.nativeType(), nativeClass); Method fromNativeMethod = getFromNativeMethod(fromNativeType, builder.getClassLoader()); getfield(mv, builder, builder.getFromNativeConverterField(fromNativeConverter)); mv.swap(); if (fromNativeType.getFromNativeContext() != null) { getfield( mv, builder, builder.getFromNativeContextField(fromNativeType.getFromNativeContext())); } else { mv.aconst_null(); } if (fromNativeMethod.getDeclaringClass().isInterface()) { mv.invokeinterface( fromNativeMethod.getDeclaringClass(), fromNativeMethod.getName(), fromNativeMethod.getReturnType(), fromNativeMethod.getParameterTypes()); } else { mv.invokevirtual( fromNativeMethod.getDeclaringClass(), fromNativeMethod.getName(), fromNativeMethod.getReturnType(), fromNativeMethod.getParameterTypes()); } if (fromNativeType.getDeclaredType().isPrimitive()) { // The actual return type is a primitive, but there was a converter for it - extract the // primitive value Class boxedType = getBoxedClass(fromNativeType.getDeclaredType()); if (!boxedType.isAssignableFrom(fromNativeMethod.getReturnType())) mv.checkcast(p(boxedType)); unboxNumber( mv, boxedType, fromNativeType.getDeclaredType(), fromNativeType.getNativeType()); } else if (!fromNativeType .getDeclaredType() .isAssignableFrom(fromNativeMethod.getReturnType())) { mv.checkcast(p(fromNativeType.getDeclaredType())); } } else if (!fromNativeType.getDeclaredType().isPrimitive()) { Class unboxedType = unboxedType(fromNativeType.getDeclaredType()); convertPrimitive(mv, nativeClass, unboxedType, fromNativeType.getNativeType()); boxValue(builder, mv, fromNativeType.getDeclaredType(), unboxedType); } }
public static ClassVisitor newCheckClassAdapter(ClassVisitor cv) { try { Class<? extends ClassVisitor> tmvClass = Class.forName("org.objectweb.asm.util.CheckClassAdapter").asSubclass(ClassVisitor.class); Constructor<? extends ClassVisitor> c = tmvClass.getDeclaredConstructor(ClassVisitor.class); return c.newInstance(cv); } catch (Throwable t) { return cv; } }
public static ClassVisitor newTraceClassVisitor(PrintWriter out) { try { Class<? extends ClassVisitor> tmvClass = Class.forName("org.objectweb.asm.util.TraceClassVisitor").asSubclass(ClassVisitor.class); Constructor<? extends ClassVisitor> c = tmvClass.getDeclaredConstructor(PrintWriter.class); return c.newInstance(out); } catch (Throwable t) { throw new RuntimeException(t); } }
public static MethodVisitor newTraceMethodVisitor(MethodVisitor mv) { try { Class<? extends MethodVisitor> tmvClass = Class.forName("org.objectweb.asm.util.TraceMethodVisitor") .asSubclass(MethodVisitor.class); Constructor<? extends MethodVisitor> c = tmvClass.getDeclaredConstructor(MethodVisitor.class); return c.newInstance(mv); } catch (Throwable t) { return mv; } }
static void emitReturn( AsmBuilder builder, SkinnyMethodAdapter mv, Class returnType, Class nativeIntType) { if (returnType.isPrimitive()) { if (long.class == returnType) { mv.lreturn(); } else if (float.class == returnType) { mv.freturn(); } else if (double.class == returnType) { mv.dreturn(); } else if (void.class == returnType) { mv.voidreturn(); } else { mv.ireturn(); } } else { boxValue(builder, mv, returnType, nativeIntType); mv.areturn(); } }
private static boolean classIsVisible(ClassLoader classLoader, Class klass) { try { return classLoader.loadClass(klass.getName()) == klass; } catch (ClassNotFoundException cnfe) { return false; } }
static boolean isDelegate(Class klass) { for (Method m : klass.getMethods()) { if (m.isAnnotationPresent(Delegate.class)) { return true; } } return false; }
static Method getToNativeMethod(ToNativeType toNativeType, AsmClassLoader classLoader) { ToNativeConverter toNativeConverter = toNativeType.getToNativeConverter(); if (toNativeConverter == null) { return null; } try { Class<? extends ToNativeConverter> toNativeConverterClass = toNativeConverter.getClass(); if (Modifier.isPublic(toNativeConverterClass.getModifiers())) { for (Method method : toNativeConverterClass.getMethods()) { if (!method.getName().equals("toNative")) continue; Class[] methodParameterTypes = method.getParameterTypes(); if (toNativeConverter.nativeType().isAssignableFrom(method.getReturnType()) && methodParameterTypes.length == 2 && methodParameterTypes[0].isAssignableFrom(toNativeType.getDeclaredType()) && methodParameterTypes[1] == ToNativeContext.class && methodIsAccessible(method) && classIsVisible(classLoader, method.getDeclaringClass())) { return method; } } } Method method = toNativeConverterClass.getMethod("toNative", Object.class, ToNativeContext.class); return methodIsAccessible(method) && classIsVisible(classLoader, method.getDeclaringClass()) ? method : ToNativeConverter.class.getDeclaredMethod( "toNative", Object.class, ToNativeContext.class); } catch (NoSuchMethodException nsme) { try { return ToNativeConverter.class.getDeclaredMethod( "toNative", Object.class, ToNativeContext.class); } catch (NoSuchMethodException nsme2) { throw new RuntimeException( "internal error. " + ToNativeConverter.class + " has no toNative() method"); } } }
static void emitReturnOp(SkinnyMethodAdapter mv, Class returnType) { if (!returnType.isPrimitive()) { mv.areturn(); } else if (long.class == returnType) { mv.lreturn(); } else if (float.class == returnType) { mv.freturn(); } else if (double.class == returnType) { mv.dreturn(); } else if (void.class == returnType) { mv.voidreturn(); } else { mv.ireturn(); } }
static void store(SkinnyMethodAdapter mv, Class type, LocalVariable var) { if (!type.isPrimitive()) { mv.astore(var); } else if (long.class == type) { mv.lstore(var); } else if (double.class == type) { mv.dstore(var); } else if (float.class == type) { mv.fstore(var); } else { mv.istore(var); } }
static void load(SkinnyMethodAdapter mv, Class parameterType, LocalVariable parameter) { if (!parameterType.isPrimitive()) { mv.aload(parameter); } else if (long.class == parameterType) { mv.lload(parameter); } else if (float.class == parameterType) { mv.fload(parameter); } else if (double.class == parameterType) { mv.dload(parameter); } else { mv.iload(parameter); } }
static Method getFromNativeMethod(FromNativeType fromNativeType, AsmClassLoader classLoader) { FromNativeConverter fromNativeConverter = fromNativeType.getFromNativeConverter(); if (fromNativeConverter == null) { return null; } try { Class<? extends FromNativeConverter> fromNativeConverterClass = fromNativeConverter.getClass(); if (Modifier.isPublic(fromNativeConverterClass.getModifiers())) { for (Method method : fromNativeConverterClass.getMethods()) { if (!method.getName().equals("fromNative")) continue; Class[] methodParameterTypes = method.getParameterTypes(); Class javaType = fromNativeType.getDeclaredType().isPrimitive() ? boxedType(fromNativeType.getDeclaredType()) : fromNativeType.getDeclaredType(); if (javaType.isAssignableFrom(method.getReturnType()) && methodParameterTypes.length == 2 && methodParameterTypes[0].isAssignableFrom(fromNativeConverter.nativeType()) && methodParameterTypes[1] == FromNativeContext.class && methodIsAccessible(method) && classIsVisible(classLoader, method.getDeclaringClass())) { return method; } } } Method method = fromNativeConverterClass.getMethod("fromNative", Object.class, FromNativeContext.class); return methodIsAccessible(method) && classIsVisible(classLoader, method.getDeclaringClass()) ? method : FromNativeConverter.class.getDeclaredMethod( "fromNative", Object.class, FromNativeContext.class); } catch (NoSuchMethodException nsme) { try { return FromNativeConverter.class.getDeclaredMethod( "fromNative", Object.class, FromNativeContext.class); } catch (NoSuchMethodException nsme2) { throw new RuntimeException( "internal error. " + FromNativeConverter.class + " has no fromNative() method"); } } }
static void boxValue( AsmBuilder builder, SkinnyMethodAdapter mv, Class boxedType, Class unboxedType) { if (boxedType == unboxedType || boxedType.isPrimitive()) { } else if (Boolean.class.isAssignableFrom(boxedType)) { narrow(mv, unboxedType, boolean.class); mv.invokestatic(Boolean.class, "valueOf", Boolean.class, boolean.class); } else if (Pointer.class.isAssignableFrom(boxedType)) { getfield(mv, builder, builder.getRuntimeField()); mv.invokestatic( AsmRuntime.class, "pointerValue", Pointer.class, unboxedType, jnr.ffi.Runtime.class); } else if (Address.class == boxedType) { mv.invokestatic(boxedType, "valueOf", boxedType, unboxedType); } else if (Number.class.isAssignableFrom(boxedType) && boxedType(unboxedType) == boxedType) { mv.invokestatic(boxedType, "valueOf", boxedType, unboxedType); } else { throw new IllegalArgumentException( "cannot box value of type " + unboxedType + " to " + boxedType); } }