From e388426759e02e15ccc93b9df2e5c0400590d057 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Thu, 6 Oct 2011 02:05:22 +0200
Subject: Enhance ReleasePrimitiveArrayCritical: Use mode-flag JNI_ABORT if
 array is const, ie no write-back

We shall consider the C header declaration as being correct
and no modification shall happen on const arrays.

Tested w/ unit tests and JOGL

+++

Cleanup JavaType: final immutable fields, proper CVoidPointer name
---
 make/scripts/runtest.sh                            |  5 ++-
 .../com/jogamp/gluegen/CMethodBindingEmitter.java  | 30 +++++++++------
 src/java/com/jogamp/gluegen/JavaEmitter.java       |  2 +-
 src/java/com/jogamp/gluegen/JavaType.java          | 38 +++++++++++++------
 .../gluegen/test/junit/generation/BaseClass.java   | 43 +++++++++++++++++++++-
 .../jogamp/gluegen/test/junit/generation/test1.c   | 15 ++++++--
 .../jogamp/gluegen/test/junit/generation/test1.h   |  7 +++-
 7 files changed, 107 insertions(+), 33 deletions(-)

diff --git a/make/scripts/runtest.sh b/make/scripts/runtest.sh
index 9326412..31de364 100755
--- a/make/scripts/runtest.sh
+++ b/make/scripts/runtest.sh
@@ -30,7 +30,7 @@ rm -f $LOG
 #D_ARGS="-Djogamp.debug.ProcAddressHelper=true -Djogamp.debug.NativeLibrary=true"
 #D_ARGS="-Djogamp.debug.TraceLock"
 #D_ARGS="-Djogamp.debug.JARUtil"
-D_ARGS="-Djogamp.debug.TempFileCache"
+#D_ARGS="-Djogamp.debug.TempFileCache"
 #D_ARGS="-Djogamp.debug.JNILibLoader -Djogamp.debug.TempFileCache -Djogamp.debug.JARUtil"
 #D_ARGS="-Djogamp.debug.JNILibLoader -Djogamp.gluegen.UseTempJarCache=false"
 #D_ARGS="-Djogamp.debug.JNILibLoader"
@@ -61,6 +61,7 @@ function onetest() {
 #onetest com.jogamp.gluegen.test.TestPointerBufferEndian 2>&1 | tee -a $LOG
 #onetest com.jogamp.common.nio.TestStructAccessorEndian 2>&1 | tee -a $LOG
 #onetest com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter 2>&1 | tee -a $LOG
+onetest com.jogamp.gluegen.test.junit.generation.Test1p2ProcAddressEmitter 2>&1 | tee -a $LOG
 #onetest com.jogamp.common.util.TestPlatform01 2>&1 | tee -a $LOG
 #onetest com.jogamp.common.util.TestIOUtil01 2>&1 | tee -a $LOG
-onetest com.jogamp.common.util.TestTempJarCache 2>&1 | tee -a $LOG
+#onetest com.jogamp.common.util.TestTempJarCache 2>&1 | tee -a $LOG
diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
index 5d0124c..114f091 100644
--- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
+++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
@@ -48,8 +48,6 @@ import com.jogamp.gluegen.cgram.types.*;
 
 import java.util.logging.Logger;
 
-import static java.util.logging.Level.*;
-
 /** Emits the C-side component of the Java<->C JNI binding. */
 public class CMethodBindingEmitter extends FunctionEmitter {
 
@@ -528,6 +526,17 @@ public class CMethodBindingEmitter extends FunctionEmitter {
     return (type.getSize(machDesc) == 1);
   }
 
+  /** Checks a type (expected to be pointer) for const-ness */
+  protected boolean isConstPtr(Type type) {
+    if (type.pointerDepth() != 1) {
+      return false;
+    }
+    if (type.asPointer().getTargetType().isConst()) {
+      return true;
+    }
+    return false;
+  }
+
   /** Checks a type (expected to be pointer-to-pointer) for const-ness */
   protected boolean isConstPtrPtr(Type type) {
     if (type.pointerDepth() != 2) {
@@ -779,8 +788,9 @@ public class CMethodBindingEmitter extends FunctionEmitter {
         if (!needsDataCopy) {
           writer.println("  if ( NULL != " + javaArgName + " && JNI_FALSE == " + isNIOArgName(i) + " ) {");
 
-          // Release array 
-          writer.print("    (*env)->ReleasePrimitiveArrayCritical(env, " + javaArgName + ", " + convName + ", 0);");
+          // Release array
+          final String modeFlag = isConstPtr(cArgType) || isConstPtrPtr(cArgType) ? "JNI_ABORT" : "0" ; 
+          writer.print("    (*env)->ReleasePrimitiveArrayCritical(env, " + javaArgName + ", " + convName + ", "+modeFlag+");");
         } else {
           writer.println("  if ( NULL != " + javaArgName + " ) {");
 
@@ -1373,9 +1383,9 @@ public class CMethodBindingEmitter extends FunctionEmitter {
       ptrTypeString = cType.getName();
     }
 
+    writer.print("  ");
     if (!needsDataCopy) {
       // declare the pointer variable
-      writer.print("  ");
       writer.print(ptrTypeString);
       writer.print(" ");
       writer.print(cVariableName);
@@ -1391,16 +1401,14 @@ public class CMethodBindingEmitter extends FunctionEmitter {
             cElementTypeName = cPtrType.getTargetType().asPointer().getName();
         }
         if (isConstPtrPtr(cType)) {
-            writer.print("  const "+cElementTypeName+" *");
-        } else {
-            writer.print("  "+cElementTypeName+" *");
+            writer.print("const ");
         }
+        writer.print(cElementTypeName+" *");
       } else {
         if (isConstPtrPtr(cType)) {
-            writer.print("  const " + ptrTypeString);
-        } else {
-            writer.print("  " + ptrTypeString);
+            writer.print("const ");
         }
+        writer.print(ptrTypeString);
       }
       writer.print(" ");
       writer.print(cVariableName);
diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java
index c7c6cc8..d768858 100644
--- a/src/java/com/jogamp/gluegen/JavaEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaEmitter.java
@@ -1241,7 +1241,7 @@ public class JavaEmitter implements GlueEmitter {
         // arrays, NIO buffers, or both in expandMethodBinding
         if (t.pointerDepth() == 1 || t.arrayDimension() == 1) {
           if (targetType.isVoid()) {
-            return JavaType.createForVoidPointer();
+            return JavaType.createForCVoidPointer();
           } else if (targetType.isInt()) {
             // size_t and intptr_t is always a PointerBuffer since size is arch dependent
             if ("size_t".equals(targetType.getName()) || "intptr_t".equals(targetType.getName())) {
diff --git a/src/java/com/jogamp/gluegen/JavaType.java b/src/java/com/jogamp/gluegen/JavaType.java
index 04d14de..a6cf890 100644
--- a/src/java/com/jogamp/gluegen/JavaType.java
+++ b/src/java/com/jogamp/gluegen/JavaType.java
@@ -59,10 +59,10 @@ public class JavaType {
       VOID, CHAR, SHORT, INT32, INT64, FLOAT, DOUBLE;
   }
 
-  private Class<?> clazz; // Primitive types and other types representable as Class objects
-  private String name;  // Types we're generating glue code for (i.e., C structs)
-  private Type   elementType; // Element type if this JavaType represents a C array
-  private C_PTR  primitivePointerType;
+  private final Class<?> clazz; // Primitive types and other types representable as Class objects
+  private final String name;  // Types we're generating glue code for (i.e., C structs)
+  private final Type   elementType; // Element type if this JavaType represents a C array
+  private final C_PTR  primitivePointerType;
 
   private static JavaType nioBufferType;
   private static JavaType nioByteBufferType;
@@ -126,7 +126,7 @@ public class JavaType {
     return new JavaType(elementType);
   }
 
-  public static JavaType createForVoidPointer() {
+  public static JavaType createForCVoidPointer() {
     return new JavaType(C_PTR.VOID);
   }
 
@@ -436,6 +436,7 @@ public class JavaType {
     return elementType != null;
   }
   
+  
   public boolean isCPrimitivePointerType() {
     return primitivePointerType != null;
   }
@@ -474,13 +475,7 @@ public class JavaType {
 
   @Override
   public Object clone() {
-    JavaType clone = new JavaType(primitivePointerType);
-
-    clone.clazz = this.clazz;
-    clone.name = this.name;
-    clone.elementType = this.elementType;
-
-    return clone;
+    return new JavaType(primitivePointerType, clazz, name, elementType);
   }
 
   @Override
@@ -505,16 +500,25 @@ public class JavaType {
    * argument.
    */
   private JavaType(Class<?> clazz) {
+    this.primitivePointerType = null;
     this.clazz = clazz;
+    this.name = null;
+    this.elementType = null;
   }
 
   /** Constructs a type representing a named C struct. */
   private JavaType(String name) {
+    this.primitivePointerType = null;
+    this.clazz = null;
     this.name = name;
+    this.elementType = null;
   }
 
   /** Constructs a type representing an array of C pointers. */
   private JavaType(Type elementType) {
+    this.primitivePointerType = null;
+    this.clazz = null;
+    this.name = null;
     this.elementType = elementType;
   }
 
@@ -522,8 +526,18 @@ public class JavaType {
       (integer, floating-point, or void pointer) type. */
   private JavaType(C_PTR primitivePointerType) {
     this.primitivePointerType = primitivePointerType;
+    this.clazz = null;
+    this.name = null;
+    this.elementType = null;
   }
 
+  private JavaType(C_PTR primitivePointerType, Class<?> clazz, String name, Type elementType) {
+    this.primitivePointerType = primitivePointerType;
+    this.clazz = clazz;
+    this.name = name;
+    this.elementType = elementType;
+  }
+  
   private String arrayName(Class<?> clazz) {
     StringBuilder buf = new StringBuilder();
     int arrayCount = 0;
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java
index e73aca6..f2a85fe 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java
@@ -268,7 +268,7 @@ public class BaseClass {
           result = binding.arrayTestFooNioOnly(context, lb1);
           Assert.assertTrue("Wrong result: "+result, 1+8000==result);
 
-          // LongBuffer arrayTestFoo2 ( LongBuffer )
+          // LongBuffer arrayTestFoo2 ( LongBuffer ) - don't write-back array-arg
           {
               lb2.rewind();
               LongBuffer lb3 = newLongBuffer(Bindingtest1.ARRAY_SIZE, direct);
@@ -290,11 +290,12 @@ public class BaseClass {
               Assert.assertTrue("Wrong result: "+lbR.remaining(), Bindingtest1.ARRAY_SIZE == lbR.remaining());
               int j=0;
               for(j=0; j<Bindingtest1.ARRAY_SIZE; j++) {
+                Assert.assertTrue("Wrong result: s:"+lb2.get(j)+" c: "+lb3.get(j), lb2.get(j)==lb3.get(j));
                 Assert.assertTrue("Wrong result: s:"+lb3.get(j)+" d: "+lbR.get(j), 1+lb3.get(j)==lbR.get(j));
               }
           }
 
-          // LongBuffer arrayTestFoo2 ( long[], int )
+          // LongBuffer arrayTestFoo2 ( long[], int ) - don't write-back array-arg
           {
               long[] larray3 = new long[Bindingtest1.ARRAY_SIZE];
               for(i=0; i<Bindingtest1.ARRAY_SIZE; i++) {
@@ -308,10 +309,48 @@ public class BaseClass {
               Assert.assertTrue("Wrong result: "+lbR.remaining(), Bindingtest1.ARRAY_SIZE == lbR.remaining());
               int j=0;
               for(j=0; j<Bindingtest1.ARRAY_SIZE; j++) {
+                Assert.assertTrue("Wrong result: s:"+larray2[j]+" c: "+larray3[j], larray2[j]==larray3[j]);
                 Assert.assertTrue("Wrong result: s:"+larray3[j]+" d: "+lbR.get(j), 1+larray3[j]==lbR.get(j));
               }
           }
 
+          // void arrayTestFoo3 ( LongBuffer ) - write-back array-arg
+          {
+              lb2.rewind();
+              LongBuffer lb3 = newLongBuffer(Bindingtest1.ARRAY_SIZE, direct);
+              lb3.put(lb2);
+              lb3.rewind();
+              lb2.rewind();
+
+              // System.out.println("lb3: "+lb3);
+              Assert.assertTrue("Wrong result: "+lb3.capacity(), Bindingtest1.ARRAY_SIZE == lb3.capacity());
+              Assert.assertTrue("Wrong result: "+lb3.remaining(), Bindingtest1.ARRAY_SIZE == lb3.remaining());
+
+              binding.arrayTestFoo3(lb3);
+
+              Assert.assertTrue("Wrong result: "+lb3.capacity(), Bindingtest1.ARRAY_SIZE == lb3.capacity());
+              Assert.assertTrue("Wrong result: "+lb3.remaining(), Bindingtest1.ARRAY_SIZE == lb3.remaining());
+              int j=0;
+              for(j=0; j<Bindingtest1.ARRAY_SIZE; j++) {
+                Assert.assertTrue("Wrong result: s:"+lb2.get(j)+" d: "+lb3.get(j), 1+lb2.get(j)==lb3.get(j));
+              }
+          }
+
+          // void arrayTestFoo3 ( long[], int ) - write-back array-arg
+          {
+              long[] larray3 = new long[Bindingtest1.ARRAY_SIZE];
+              for(i=0; i<Bindingtest1.ARRAY_SIZE; i++) {
+                larray3[i]=  larray2[i];
+              }
+
+              binding.arrayTestFoo3(larray3, 0);
+
+              int j=0;
+              for(j=0; j<Bindingtest1.ARRAY_SIZE; j++) {
+                Assert.assertTrue("Wrong result: s:"+larray2[j]+" d: "+larray3[j], 1+larray2[j]==larray3[j]);
+              }
+          }
+
           // PointerBuffer arrayTestFoo3ArrayToPtrPtr(LongBuffer)
           // PointerBuffer arrayTestFoo3PtrPtr(PointerBuffer)
           {
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c
index 2d7aa71..ae3c8a5 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c
@@ -36,7 +36,7 @@ MYAPI int64_t MYAPIENTRY arrayTestInt64(int64_t context, int64_t * array) {
     return r+context;
 }
 
-MYAPI foo * MYAPIENTRY arrayTestFoo2( foo * array ) {
+MYAPI foo * MYAPIENTRY arrayTestFoo2( const foo * array ) {
     int i;
     foo * result = calloc(ARRAY_SIZE, sizeof(foo));
     assert(NULL!=array);
@@ -47,11 +47,20 @@ MYAPI foo * MYAPIENTRY arrayTestFoo2( foo * array ) {
     return result;
 }
 
-MYAPI foo * * MYAPIENTRY arrayTestFoo3ArrayToPtrPtr(foo * array) {
+MYAPI void MYAPIENTRY arrayTestFoo3( foo * array ) {
+    int i;
+    assert(NULL!=array);
+    for(i=0; i<ARRAY_SIZE; i++) {
+        array[i] += 1;
+        // printf("array[%d]: %d -> %d\n", i, (int)array[i], (int)result[i]);
+    }
+}
+
+MYAPI foo * * MYAPIENTRY arrayTestFoo3ArrayToPtrPtr(const foo * array) {
     int j;
     foo * * result = calloc(ARRAY_SIZE, sizeof(foo *));
     for(j=0; j<ARRAY_SIZE; j++) {
-        result[j] = array + ARRAY_SIZE * j ;
+        result[j] = (foo *) ( array + ARRAY_SIZE * j ) ;
     }
     return result;
 }
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h
index 3e20307..6c38a03 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h
@@ -42,10 +42,13 @@ MYAPI int64_t MYAPIENTRY arrayTestInt64(int64_t context, int64_t * array );
 MYAPI foo MYAPIENTRY arrayTestFoo1(int64_t context, foo * array );
 
 /** Returns a copy of the passed array, each element incr by 1 */
-MYAPI foo * MYAPIENTRY arrayTestFoo2(foo * array );
+MYAPI foo * MYAPIENTRY arrayTestFoo2(const foo * array );
+
+/** Increments each element of the passed array by 1 - IDENTITY */
+MYAPI void MYAPIENTRY arrayTestFoo3(foo * array );
 
 /** Returns a array-array of the passed array, split at ARRAY size - IDENTITY! */
-MYAPI foo * * MYAPIENTRY arrayTestFoo3ArrayToPtrPtr(foo * array);
+MYAPI foo * * MYAPIENTRY arrayTestFoo3ArrayToPtrPtr(const foo * array);
 
 /** Fills dest array ptr of ARRAY size with arrays (allocs) and copies content of src to it - COPY! */
 MYAPI void MYAPIENTRY arrayTestFoo3CopyPtrPtrA(foo * * dest, const foo * * src);
-- 
cgit v1.2.3