From 31376c0ad5639412c82409a89fee70916495fb7c Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Thu, 14 Aug 2014 11:28:36 -0700
Subject: [PATCH] refactor RFFIFactory initialization

---
 .../r/runtime/ffi/Load_RFFIFactory.java       | 60 +++++++++++++++++++
 .../truffle/r/runtime/ffi/RFFIFactory.java    | 39 ++----------
 .../com/oracle/truffle/r/shell/RCommand.java  | 13 +++-
 3 files changed, 77 insertions(+), 35 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java

diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java
new file mode 100644
index 0000000000..29ceaf2d95
--- /dev/null
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.ffi;
+
+import com.oracle.truffle.r.runtime.*;
+
+/**
+ * Selects a particular subclass of {@link RFFIFactory}. Specification is based on system property
+ * {@value #FACTORY_CLASS_PROPERTY}. Current default is a JNR-based implementation.
+ */
+public class Load_RFFIFactory {
+    private static final String FACTORY_CLASS_PROPERTY = "fastr.ffi.factory.class";
+    private static final String PACKAGE_PREFIX = "com.oracle.truffle.r.runtime.ffi.";
+    private static final String SUFFIX = "_RFFIFactory";
+    private static final String DEFAULT_FACTORY = "jnr";
+    private static final String DEFAULT_FACTORY_CLASS = mapSimpleName(DEFAULT_FACTORY);
+
+    private static String mapSimpleName(String simpleName) {
+        return PACKAGE_PREFIX + simpleName + "." + simpleName.toUpperCase() + SUFFIX;
+    }
+
+    public static RFFIFactory initialize() {
+        String prop = System.getProperty(FACTORY_CLASS_PROPERTY);
+        if (prop != null) {
+            if (!prop.contains(".")) {
+                // simple name
+                prop = mapSimpleName(prop);
+            }
+        } else {
+            prop = DEFAULT_FACTORY_CLASS;
+        }
+        try {
+            return (RFFIFactory) Class.forName(prop).newInstance();
+        } catch (Exception ex) {
+            Utils.fail("Failed to instantiate class: " + prop);
+            return null;
+        }
+
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
index cb90413421..6edb8539e4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
@@ -25,44 +25,15 @@ package com.oracle.truffle.r.runtime.ffi;
 import com.oracle.truffle.r.runtime.*;
 
 /**
- * Factory class for the different possible implementations of the {@link RFFI} interface.
- * Specification is based on system property {@value #FACTORY_CLASS_PROPERTY}. Current default is a
- * JNR-based implementation.
+ * Factory class for the different possible implementations of the {@link RFFI} interface. The
+ * choice of factory is made by the R engine and set here by the call to {@link #setRFFIFactory}.
  */
 public abstract class RFFIFactory {
 
-    private static final String FACTORY_CLASS_PROPERTY = "fastr.ffi.factory.class";
-    private static final String PACKAGE_PREFIX = "com.oracle.truffle.r.runtime.ffi.";
-    private static final String SUFFIX = "_RFFIFactory";
-    private static final String DEFAULT_FACTORY = "jnr";
-    private static final String DEFAULT_FACTORY_CLASS = mapSimpleName(DEFAULT_FACTORY);
+    protected static RFFI theRFFI;
 
-    static {
-        String prop = System.getProperty(FACTORY_CLASS_PROPERTY);
-        if (prop != null) {
-            if (!prop.contains(".")) {
-                // simple name
-                prop = mapSimpleName(prop);
-            }
-        } else {
-            prop = DEFAULT_FACTORY_CLASS;
-        }
-        try {
-            theFactory = (RFFIFactory) Class.forName(prop).newInstance();
-        } catch (Exception ex) {
-            Utils.fail("Failed to instantiate class: " + prop);
-        }
-    }
-
-    protected static RFFIFactory theFactory;
-    protected static final RFFI theRFFI = theFactory.createRFFI();
-
-    private static String mapSimpleName(String simpleName) {
-        return PACKAGE_PREFIX + simpleName + "." + simpleName.toUpperCase() + SUFFIX;
-    }
-
-    protected static RFFIFactory getFactory() {
-        return theFactory;
+    public static void setRFFIFactory(RFFIFactory factory) {
+        theRFFI = factory.createRFFI();
     }
 
     public static RFFI getRFFI() {
diff --git a/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java b/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java
index 462fd0051d..3b8ba8ca31 100644
--- a/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java
+++ b/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java
@@ -30,6 +30,7 @@ import java.util.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.r.engine.*;
 import com.oracle.truffle.r.runtime.*;
+import com.oracle.truffle.r.runtime.ffi.*;
 
 import jline.console.*;
 
@@ -37,7 +38,17 @@ import jline.console.*;
  * Emulates the (Gnu)R command as precisely as possible.
  */
 public class RCommand {
-    // CheckStyle: stop system..print check
+
+    /**
+     * The choice of {@link RFFIFactory} is made statically so that it is bound into an AOT-compiled
+     * VM. The decision is node made directly in {@link RFFIFactory} to avoid some project
+     * dependencies that cause build problems.
+     */
+    static {
+        RFFIFactory.setRFFIFactory(Load_RFFIFactory.initialize());
+    }
+
+// CheckStyle: stop system..print check
 
     public static void main(String[] args) {
         RCmdOptionsParser.Result result = RCmdOptionsParser.parseArguments(RCmdOptions.Client.R, args);
-- 
GitLab