JITCompiler.java

  1. /*
  2.  *
  3.  */
  4. package org.jruby.ext.ffi.jffi;

  5. import com.kenai.jffi.CallingConvention;
  6. import java.lang.ref.ReferenceQueue;
  7. import java.lang.ref.WeakReference;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. import java.util.WeakHashMap;

  11. import org.jruby.RubyInstanceConfig;
  12. import org.jruby.ext.ffi.CallbackInfo;
  13. import org.jruby.ext.ffi.MappedType;
  14. import org.jruby.ext.ffi.NativeType;
  15. import org.jruby.ext.ffi.Type;
  16. import org.jruby.util.WeakIdentityHashMap;
  17. import org.jruby.util.cli.Options;

  18. /**
  19.  *
  20.  */
  21. class JITCompiler {
  22.    
  23.     private final Map<JITSignature, HandleRef>
  24.             handles = new HashMap<JITSignature, HandleRef>();

  25.     private final Map<Class<? extends NativeInvoker>, JITHandle>
  26.             classes = new WeakHashMap();

  27.     private final ReferenceQueue referenceQueue = new ReferenceQueue();
  28.    
  29.     private final JITHandle failedHandle = new JITHandle(this,
  30.             new JITSignature(NativeType.VOID, new NativeType[0], false, new boolean[0], CallingConvention.DEFAULT, false),
  31.             true);

  32.     private static class SingletonHolder {
  33.         private static final JITCompiler INSTANCE = new JITCompiler();
  34.     }
  35.    
  36.     public static JITCompiler getInstance() {
  37.         return SingletonHolder.INSTANCE;
  38.     }
  39.    
  40.     private static final class HandleRef extends WeakReference<JITHandle> {
  41.         JITSignature signature;

  42.         public HandleRef(JITHandle handle, JITSignature signature, ReferenceQueue refqueue) {
  43.             super(handle, refqueue);
  44.             this.signature = signature;
  45.         }
  46.     }

  47.     private void cleanup() {
  48.         HandleRef ref;
  49.         while ((ref = (HandleRef) referenceQueue.poll()) != null) {
  50.             handles.remove(ref.signature);
  51.         }
  52.     }
  53.    
  54.    
  55.     JITHandle getHandle(Signature signature, boolean unique) {
  56.        
  57.         boolean hasResultConverter = !(signature.getResultType() instanceof Type.Builtin);
  58.         NativeType nativeResultType;
  59.         Type resultType = signature.getResultType();
  60.        
  61.         if (resultType instanceof Type.Builtin || resultType instanceof CallbackInfo) {
  62.             nativeResultType = resultType.getNativeType();
  63.        
  64.         } else if (resultType instanceof MappedType) {
  65.             nativeResultType = ((MappedType) resultType).getRealType().getNativeType();
  66.        
  67.         } else {
  68.             return failedHandle;
  69.         }

  70.         NativeType[] nativeParameterTypes = new NativeType[signature.getParameterCount()];
  71.         boolean[] hasParameterConverter = new boolean[signature.getParameterCount()];
  72.        
  73.         for (int i = 0; i < hasParameterConverter.length; i++) {
  74.             Type parameterType = signature.getParameterType(i);
  75.             if (parameterType instanceof Type.Builtin || parameterType instanceof CallbackInfo) {
  76.                 nativeParameterTypes[i] = parameterType.getNativeType();
  77.        
  78.             } else if (parameterType instanceof MappedType) {
  79.                 nativeParameterTypes[i] = ((MappedType) parameterType).getRealType().getNativeType();
  80.        
  81.             } else {
  82.                 return failedHandle;
  83.             }

  84.             hasParameterConverter[i] = !(parameterType instanceof Type.Builtin)
  85.                     || DataConverters.isEnumConversionRequired(parameterType, signature.getEnums());
  86.         }
  87.        
  88.         JITSignature jitSignature = new JITSignature(nativeResultType, nativeParameterTypes,
  89.                 hasResultConverter, hasParameterConverter, signature.getCallingConvention(), signature.isIgnoreError());
  90.        
  91.         if (unique) {
  92.             return new JITHandle(this, jitSignature, Options.COMPILE_MODE.load() == RubyInstanceConfig.CompileMode.OFF);
  93.         }

  94.         synchronized (this) {
  95.             cleanup();
  96.             HandleRef ref = handles.get(jitSignature);
  97.             JITHandle handle = ref != null ? ref.get() : null;
  98.             if (handle == null) {
  99.                 handle = new JITHandle(this, jitSignature, Options.COMPILE_MODE.load() == RubyInstanceConfig.CompileMode.OFF);
  100.                 handles.put(jitSignature, new HandleRef(handle, jitSignature, referenceQueue));
  101.             }
  102.            
  103.             return handle;
  104.         }
  105.     }

  106.     void registerClass(JITHandle handle, Class<? extends NativeInvoker> klass) {
  107.         classes.put(klass, handle);
  108.     }
  109. }