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); } }
static void emitToNativeConversion( AsmBuilder builder, SkinnyMethodAdapter mv, ToNativeType toNativeType) { ToNativeConverter parameterConverter = toNativeType.getToNativeConverter(); if (parameterConverter != null) { Method toNativeMethod = getToNativeMethod(toNativeType, builder.getClassLoader()); if (toNativeType.getDeclaredType().isPrimitive()) { boxValue( builder, mv, getBoxedClass(toNativeType.getDeclaredType()), toNativeType.getDeclaredType()); } if (!toNativeMethod.getParameterTypes()[0].isAssignableFrom( getBoxedClass(toNativeType.getDeclaredType()))) { mv.checkcast(toNativeMethod.getParameterTypes()[0]); } mv.aload(0); AsmBuilder.ObjectField toNativeConverterField = builder.getToNativeConverterField(parameterConverter); mv.getfield( builder.getClassNamePath(), toNativeConverterField.name, ci(toNativeConverterField.klass)); if (!toNativeMethod.getDeclaringClass().equals(toNativeConverterField.klass)) { mv.checkcast(toNativeMethod.getDeclaringClass()); } // Re-order so the value to be converted is on the top of the stack mv.swap(); // load context parameter (if there is one) if (toNativeType.getToNativeContext() != null) { getfield(mv, builder, builder.getToNativeContextField(toNativeType.getToNativeContext())); } else { mv.aconst_null(); } if (toNativeMethod.getDeclaringClass().isInterface()) { mv.invokeinterface( toNativeMethod.getDeclaringClass(), toNativeMethod.getName(), toNativeMethod.getReturnType(), toNativeMethod.getParameterTypes()); } else { mv.invokevirtual( toNativeMethod.getDeclaringClass(), toNativeMethod.getName(), toNativeMethod.getReturnType(), toNativeMethod.getParameterTypes()); } if (!parameterConverter.nativeType().isAssignableFrom(toNativeMethod.getReturnType())) { mv.checkcast(p(parameterConverter.nativeType())); } } }
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); } }
static void getfield(SkinnyMethodAdapter mv, AsmBuilder builder, AsmBuilder.ObjectField field) { mv.aload(0); mv.getfield(builder.getClassNamePath(), field.name, ci(field.klass)); }