Пример #1
0
  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()));
      }
    }
  }
Пример #2
0
 private static void unboxPointerOrStruct(
     final SkinnyMethodAdapter mv, final Class type, final Class nativeType) {
   mv.invokestatic(
       p(AsmRuntime.class),
       long.class == nativeType ? "longValue" : "intValue",
       sig(nativeType, type));
 }
Пример #3
0
  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);
    }
  }
Пример #4
0
  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);
    }
  }
Пример #5
0
  static void unboxNumber(
      final SkinnyMethodAdapter mv,
      final Class boxedType,
      final Class unboxedType,
      final jnr.ffi.NativeType nativeType) {

    if (Number.class.isAssignableFrom(boxedType)) {

      switch (nativeType) {
        case SCHAR:
        case UCHAR:
          mv.invokevirtual(p(boxedType), "byteValue", "()B");
          convertPrimitive(mv, byte.class, unboxedType, nativeType);
          break;

        case SSHORT:
        case USHORT:
          mv.invokevirtual(p(boxedType), "shortValue", "()S");
          convertPrimitive(mv, short.class, unboxedType, nativeType);
          break;

        case SINT:
        case UINT:
        case SLONG:
        case ULONG:
        case ADDRESS:
          if (sizeof(nativeType) == 4) {
            mv.invokevirtual(p(boxedType), "intValue", "()I");
            convertPrimitive(mv, int.class, unboxedType, nativeType);
          } else {
            mv.invokevirtual(p(boxedType), "longValue", "()J");
            convertPrimitive(mv, long.class, unboxedType, nativeType);
          }
          break;

        case SLONGLONG:
        case ULONGLONG:
          mv.invokevirtual(p(boxedType), "longValue", "()J");
          narrow(mv, long.class, unboxedType);
          break;

        case FLOAT:
          mv.invokevirtual(p(boxedType), "floatValue", "()F");
          break;

        case DOUBLE:
          mv.invokevirtual(p(boxedType), "doubleValue", "()D");
          break;
      }

    } else if (Boolean.class.isAssignableFrom(boxedType)) {
      unboxBoolean(mv, unboxedType);

    } else {
      throw new IllegalArgumentException("unsupported boxed type: " + boxedType);
    }
  }
Пример #6
0
  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);
    }
  }
Пример #7
0
  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();
    }
  }
Пример #8
0
  static void unboxNumber(
      final SkinnyMethodAdapter mv, final Class boxedType, final Class nativeType) {

    if (Number.class.isAssignableFrom(boxedType)) {

      if (byte.class == nativeType) {
        mv.invokevirtual(p(boxedType), "byteValue", "()B");

      } else if (short.class == nativeType) {
        mv.invokevirtual(p(boxedType), "shortValue", "()S");

      } else if (int.class == nativeType) {
        mv.invokevirtual(p(boxedType), "intValue", "()I");

      } else if (long.class == nativeType) {
        mv.invokevirtual(p(boxedType), "longValue", "()J");

      } else if (float.class == nativeType) {
        mv.invokevirtual(p(boxedType), "floatValue", "()F");

      } else if (double.class == nativeType) {
        mv.invokevirtual(p(boxedType), "doubleValue", "()D");

      } else {
        throw new IllegalArgumentException("unsupported Number subclass: " + boxedType);
      }

    } else if (Boolean.class.isAssignableFrom(boxedType)) {
      unboxBoolean(mv, nativeType);

    } else {
      throw new IllegalArgumentException("unsupported boxed type: " + boxedType);
    }
  }
Пример #9
0
  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);
    }
  }
Пример #10
0
 static void tryfinally(SkinnyMethodAdapter mv, Runnable codeBlock, Runnable finallyBlock) {
   Label before = new Label(), after = new Label(), ensure = new Label(), done = new Label();
   mv.trycatch(before, after, ensure, null);
   mv.label(before);
   codeBlock.run();
   mv.label(after);
   if (finallyBlock != null) finallyBlock.run();
   mv.go_to(done);
   if (finallyBlock != null) {
     mv.label(ensure);
     finallyBlock.run();
     mv.athrow();
   }
   mv.label(done);
 }
Пример #11
0
 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();
   }
 }
Пример #12
0
 static void getfield(SkinnyMethodAdapter mv, AsmBuilder builder, AsmBuilder.ObjectField field) {
   mv.aload(0);
   mv.getfield(builder.getClassNamePath(), field.name, ci(field.klass));
 }
Пример #13
0
 static void unboxBoolean(final SkinnyMethodAdapter mv, Class boxedType, final Class nativeType) {
   mv.invokevirtual(p(boxedType), "booleanValue", "()Z");
   widen(mv, boolean.class, nativeType);
 }