changeset 13721:2f944a810dd4

added list to PTXHotSpotBackend for keeping a valid installed kernel (and its associated nmethods) alive
author Doug Simon <doug.simon@oracle.com>
date Tue, 21 Jan 2014 15:26:38 +0100
parents 4281521dc39a
children 2d4a8d3d286b
files graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXMethodInvalidation2Test.java graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java
diffstat 3 files changed, 34 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXMethodInvalidation2Test.java	Tue Jan 21 12:14:38 2014 +0100
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXMethodInvalidation2Test.java	Tue Jan 21 15:26:38 2014 +0100
@@ -42,7 +42,6 @@
 public class PTXMethodInvalidation2Test extends PTXTest {
 
     @Test
-    @Ignore("still need to make a strong reference from a PTX wrapper to a PTX kernel")
     public void test() {
         test("testSnippet", 100);
     }
@@ -57,7 +56,7 @@
         while (ref.get() != null) {
             System.gc();
             // Give up after 1000 attempts
-            Assume.assumeTrue(attempts++ < 1000);
+            Assume.assumeTrue(++attempts < 1000);
         }
 
         Assert.assertFalse(code.getStart() == 0L);
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Tue Jan 21 12:14:38 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Tue Jan 21 15:26:38 2014 +0100
@@ -181,9 +181,27 @@
 
     }
 
-    public HotSpotNmethod installKernel(ResolvedJavaMethod method, ExternalCompilationResult ptxCode) {
-        assert ptxCode.getEntryPoint() != 0L;
-        return getProviders().getCodeCache().addExternalMethod(method, ptxCode);
+    /**
+     * A list of the {@linkplain #installKernel(ResolvedJavaMethod, ExternalCompilationResult)
+     * installed} kernels. This is required so that there is a strong reference to each installed
+     * kernel as long as it is {@linkplain HotSpotNmethod#isValid() valid}. The list is pruned of
+     * invalid kernels every time a new kernel is installed.
+     */
+    private List<HotSpotNmethod> installedKernels = new LinkedList<>();
+
+    public final HotSpotNmethod installKernel(ResolvedJavaMethod method, ExternalCompilationResult ptxCode) {
+        assert OmitDeviceInit || ptxCode.getEntryPoint() != 0L;
+        HotSpotNmethod kernel = getProviders().getCodeCache().addExternalMethod(method, ptxCode);
+        synchronized (installedKernels) {
+            for (Iterator<HotSpotNmethod> i = installedKernels.iterator(); i.hasNext();) {
+                HotSpotNmethod entry = i.next();
+                if (!entry.isValid()) {
+                    i.remove();
+                }
+            }
+            installedKernels.add(kernel);
+        }
+        return kernel;
     }
 
     static final class RegisterAnalysis extends ValueProcedure {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Tue Jan 21 12:14:38 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Tue Jan 21 15:26:38 2014 +0100
@@ -54,9 +54,9 @@
 import com.oracle.graal.word.*;
 
 /**
- * Utility for building a graph that "wraps" the PTX binary compiled for a method. Such a wrapper
- * handles the transition from the host CPU to the GPU and back. The graph created is something like
- * the following pseudo code with UPPER CASE denoting compile-time constants:
+ * Utility for building a graph that "wraps" a compiled PTX kernel. Such a wrapper handles the
+ * transition from the host CPU to the GPU and back. The graph created is something like the
+ * following pseudo code with UPPER CASE denoting compile-time constants:
  * 
  * <pre>
  *     T kernel(p0, p1, ..., pN) {
@@ -66,6 +66,10 @@
  *         return convert(result);
  *     }
  * </pre>
+ * <p>
+ * The generated graph includes a reference to the {@link HotSpotNmethod} for the kernel. There must
+ * be another reference to the same {@link HotSpotNmethod} object to ensure that the nmethod is not
+ * unloaded by the next full GC.
  */
 public class PTXWrapperBuilder extends GraphKit {
 
@@ -98,9 +102,10 @@
      * Creates the graph implementing the CPU to GPU transition.
      * 
      * @param method a method that has been compiled to GPU binary code
-     * @param ptxInstalledCode the installed GPU binary for {@code method}
+     * @param kernel the installed GPU binary for {@code method}
+     * @see PTXWrapperBuilder
      */
-    public PTXWrapperBuilder(ResolvedJavaMethod method, HotSpotNmethod ptxInstalledCode, HotSpotProviders providers) {
+    public PTXWrapperBuilder(ResolvedJavaMethod method, HotSpotNmethod kernel, HotSpotProviders providers) {
         super(new StructuredGraph(method), providers);
         int wordSize = providers.getCodeCache().getTarget().wordSize;
         Kind wordKind = providers.getCodeCache().getTarget().wordKind;
@@ -133,13 +138,13 @@
             }
         }
 
-        InvokeNode kernel = createInvoke(getClass(), "getKernelStart", ConstantNode.forObject(ptxInstalledCode, providers.getMetaAccess(), getGraph()));
+        InvokeNode kernelStart = createInvoke(getClass(), "getKernelStart", ConstantNode.forObject(kernel, providers.getMetaAccess(), getGraph()));
 
         AllocaNode buf = append(new AllocaNode(bufSize / wordSize, objects));
 
         Map<LaunchArg, ValueNode> args = new EnumMap<>(LaunchArg.class);
         args.put(Thread, append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), true, false)));
-        args.put(Kernel, kernel);
+        args.put(Kernel, kernelStart);
         args.put(DimX, forInt(1, getGraph()));
         args.put(DimY, forInt(1, getGraph()));
         args.put(DimZ, forInt(1, getGraph()));