FastLongMethodGenerator.java

  1. package org.jruby.ext.ffi.jffi;


  2. import com.kenai.jffi.CallContext;
  3. import com.kenai.jffi.CallingConvention;
  4. import com.kenai.jffi.Platform;
  5. import org.jruby.ext.ffi.NativeType;

  6. /**
  7.  *
  8.  */
  9. final class FastLongMethodGenerator extends AbstractNumericMethodGenerator {
  10.     private static final int MAX_PARAMETERS = getMaximumFastLongParameters();

  11.     private static final String[] signatures = buildSignatures(long.class, MAX_PARAMETERS);

  12.     private static final String[] methodNames = {
  13.         "invokeL0", "invokeL1", "invokeL2", "invokeL3", "invokeL4", "invokeL5", "invokeL6"
  14.     };

  15.     String getInvokerMethodName(JITSignature signature) {

  16.         final int parameterCount = signature.getParameterCount();

  17.         if (parameterCount <= MAX_PARAMETERS && parameterCount <= methodNames.length) {
  18.             return methodNames[parameterCount];

  19.         } else {
  20.             throw new IllegalArgumentException("invalid fast-long parameter count: " + parameterCount);
  21.         }
  22.     }

  23.     String getInvokerSignature(int parameterCount) {
  24.         if (parameterCount <= MAX_PARAMETERS && parameterCount <= signatures.length) {
  25.             return signatures[parameterCount];
  26.         }
  27.         throw new IllegalArgumentException("invalid fast-long parameter count: " + parameterCount);
  28.     }

  29.     final Class getInvokerIntType() {
  30.         return long.class;
  31.     }

  32.     public boolean isSupported(JITSignature signature) {
  33.         final int parameterCount = signature.getParameterCount();

  34.         if (!signature.getCallingConvention().equals(CallingConvention.DEFAULT) || parameterCount > MAX_PARAMETERS) {
  35.             return false;
  36.         }

  37.         final Platform platform = Platform.getPlatform();

  38.         if (platform.getOS().equals(Platform.OS.WINDOWS)) {
  39.             return false;
  40.         }

  41.         // Only supported on amd64 arches
  42.         if (!platform.getCPU().equals(Platform.CPU.X86_64)) {
  43.             return false;
  44.         }

  45.         for (int i = 0; i < parameterCount; i++) {
  46.             if (!isFastLongParameter(platform, signature.getParameterType(i))) {
  47.                 return false;
  48.             }
  49.         }

  50.         return isFastLongResult(platform, signature.getResultType());
  51.     }


  52.     final static int getMaximumFastLongParameters() {
  53.         try {
  54.             com.kenai.jffi.Invoker.class.getDeclaredMethod("invokeL6", CallContext.class, long.class,
  55.                     long.class, long.class, long.class, long.class, long.class, long.class);
  56.             return 6;
  57.         } catch (Throwable t) {
  58.             return -1;
  59.         }
  60.     }


  61.     private static boolean isFastLongType(Platform platform, NativeType type) {
  62.         switch (type) {
  63.             case BOOL:
  64.             case CHAR:
  65.             case UCHAR:
  66.             case SHORT:
  67.             case USHORT:
  68.             case INT:
  69.             case UINT:
  70.             case LONG:
  71.             case ULONG:
  72.             case LONG_LONG:
  73.             case ULONG_LONG:
  74.             case POINTER:
  75.                 return true;

  76.             default:
  77.                 return false;
  78.         }
  79.     }


  80.     static boolean isFastLongResult(Platform platform, NativeType type) {
  81.         switch (type) {
  82.             case VOID:
  83.                 return true;
  84.                
  85.             case POINTER:
  86.             case STRING:
  87.             case TRANSIENT_STRING:
  88.                 return platform.addressSize() == 64;

  89.             default:
  90.                 return isFastLongType(platform, type);
  91.         }
  92.     }

  93.     static boolean isFastLongParameter(Platform platform, NativeType type) {
  94.         switch (type) {
  95.             case POINTER:
  96.             case BUFFER_IN:
  97.             case BUFFER_OUT:
  98.             case BUFFER_INOUT:
  99.             case STRING:
  100.             case TRANSIENT_STRING:
  101.                 return platform.addressSize() == 64;
  102.            
  103.             default:
  104.                 return isFastLongType(platform, type);
  105.         }
  106.     }
  107. }