From aeadfab9572e4b441b1bc1f0708cf4c72dfe181e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 16 Jun 2023 01:16:55 +0200 Subject: GlueGen Struct [4]: JavaConfiguration Change: Drop 'ManualStaticInitCall', 'ForceStaticInitCode'; Add 'ReturnsStringOnly', 'MaxOneElement' and 'ImmutableAccess' Drop 'ManualStaticInitCall', 'ForceStaticInitCode': With new CCodeUnit's `JVMUtil_NewDirectByteBufferCopy(..)` implementation and generalized Buffers' methods, no specific init code is required anymore. Add 'ReturnsStringOnly', 'MaxOneElement' and 'ImmutableAccess': - 'ReturnsStringOnly' only String getter, drop ByteBuffer/byte[] - 'MaxOneElement' only one element maximum for pointer reference - 'ImmutableAccess' strict read-only, also reduces generated code a lot --- src/java/com/jogamp/gluegen/JavaConfiguration.java | 144 +++++++++++++-------- src/java/com/jogamp/gluegen/JavaEmitter.java | 29 ----- src/java/com/jogamp/gluegen/MethodBinding.java | 23 ---- 3 files changed, 93 insertions(+), 103 deletions(-) diff --git a/src/java/com/jogamp/gluegen/JavaConfiguration.java b/src/java/com/jogamp/gluegen/JavaConfiguration.java index 019ca2d..f392525 100644 --- a/src/java/com/jogamp/gluegen/JavaConfiguration.java +++ b/src/java/com/jogamp/gluegen/JavaConfiguration.java @@ -1,6 +1,6 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -138,8 +138,10 @@ public class JavaConfiguration { private final Map accessControl = new HashMap(); private final Map typeInfoMap = new HashMap(); private final Set returnsString = new HashSet(); + private final Set returnsStringOnly = new HashSet(); private final Map returnsOpaqueJType = new HashMap(); private final Map returnedArrayLengths = new HashMap(); + private final Set maxOneElement = new HashSet(); /** * Key is function that has some byte[] or short[] arguments that should be @@ -159,10 +161,9 @@ public class JavaConfiguration { private final Set useNIOOnly = new HashSet(); private boolean forceUseNIODirectOnly4All = false; private final Set useNIODirectOnly = new HashSet(); + private final Set immutableAccessSymbols = new HashSet(); private final Set manuallyImplement = new HashSet(); private final Map delegatedImplementation = new HashMap(); - private final Set manualStaticInitCall = new HashSet(); - private final Set forceStaticInitCode = new HashSet(); private final Map> customJavaCode = new HashMap>(); private final Map> classJavadoc = new HashMap>(); private final Map> methodJavadoc = new HashMap>(); @@ -520,10 +521,17 @@ public class JavaConfiguration { oneInSet(returnsString, symbol.getAliasedNames()); } + /** Indicates whether the given function (which returns a + char* in C) should be translated as returning a + java.lang.String only. Excluding other variants for struct field access. */ + public boolean returnsStringOnly(final String functionName) { + return returnsStringOnly.contains(functionName); + } + /** * Returns a MessageFormat string of the Java expression calculating * the number of elements in the returned array from the specified function - * name. The literal 1 indicates a single object. + * name or struct-field array-size. The literal 1 indicates a constant single object. *

* If symbol references a struct fields, see {@link #canonicalStructFieldSymbol(String, String)}, * it describes field's array-length or element-count referenced by a pointer. @@ -535,8 +543,17 @@ public class JavaConfiguration { * either {@link #returnValueCapacity(String)} or {@link #returnValueLength(String)}! *

*/ - public String returnedArrayLength(final String functionName) { - return returnedArrayLengths.get(functionName); + public String returnedArrayLength(final String symbol) { + return returnedArrayLengths.get(symbol); + } + + /** + * Indicates whether the given symbol covers no or one single object. + * This is useful for struct-field pointer, indicating a null value + * holding no object or at most referincing memory for one single object. + */ + public boolean maxOneElement(final String symbol) { + return maxOneElement.contains(symbol); } /** Returns a list of Integers which are the indices of const char* @@ -571,32 +588,6 @@ public class JavaConfiguration { return forceUseNIODirectOnly4All || useNIODirectOnly.contains(functionName); } - /** - * Returns true if the static initialization java code calling initializeImpl() - * for the given class will be manually implemented by the end user - * as requested via configuration directive ManualStaticInitCall 'class-name'. - */ - public boolean manualStaticInitCall(final String clazzName) { - return manualStaticInitCall.contains(clazzName); - } - - /** - * Returns true if the static initialization java code implementing initializeImpl() - * and the native code implementing: - *
-   *   static jobject JVMUtil_NewDirectByteBufferCopy(JNIEnv *env, void * source_address, jlong capacity);
-   * 
- * for the given class will be included in the generated code, always, - * as requested via configuration directive ForceStaticInitCode 'class-name'. - *

- * If case above code has been generated, static class initialization is generated - * to call initializeImpl(), see {@link #manualStaticInitCall(String)}. - *

- */ - public boolean forceStaticInitCode(final String clazzName) { - return forceStaticInitCode.contains(clazzName); - } - /** Returns a list of Strings containing user-implemented code for the given Java type name (not fully-qualified, only the class name); returns either null or an empty list if there is no @@ -834,6 +825,43 @@ public class JavaConfiguration { return structName+"."+fieldName; } + /** + * Returns true if the glue code for the given aliased symbol + * shall produce code for immutable access only. + *

+ * This is implemented for whole struct-type symbols or struct-field names, + * where no setter methods will be produced if marked immutable. + *

+ */ + public final boolean immutableAccess(final AliasedSymbol symbol) { + final String name = symbol.getName(); + final Set aliases = symbol.getAliasedNames(); + + if ( immutableAccessSymbols.contains( name ) || + oneInSet(immutableAccessSymbols, aliases) + ) + { + LOG.log(INFO, getASTLocusTag(symbol), "Immutable access: {0}", symbol); + return true; + } + return false; + } + /** + * Returns true if the glue code for the given symbol + * shall produce code for immutable access only. + *

+ * This is implemented for whole struct-type symbols or struct-field names, + * where no setter methods will be produced if marked immutable. + *

+ */ + public final boolean immutableAccess(final String symbol) { + if ( immutableAccessSymbols.contains( symbol ) ) { + LOG.log(INFO, "Immutable access: {0}", symbol); + return true; + } + return false; + } + /** * Variant of {@link #manuallyImplement(AliasedSymbol)}, * where this method only considers the {@link AliasedSymbol#getName() current-name} @@ -1257,12 +1285,16 @@ public class JavaConfiguration { readOpaque(tok, filename, lineNo); } else if (cmd.equalsIgnoreCase("ReturnsString")) { readReturnsString(tok, filename, lineNo); + } else if (cmd.equalsIgnoreCase("ReturnsStringOnly")) { + readReturnsStringOnly(tok, filename, lineNo); } else if (cmd.equalsIgnoreCase("ReturnsOpaque")) { readReturnsOpaque(tok, filename, lineNo); } else if (cmd.equalsIgnoreCase("ReturnedArrayLength")) { readReturnedArrayLength(tok, filename, lineNo); // Warning: make sure delimiters are reset at the top of this loop // because ReturnedArrayLength changes them. + } else if (cmd.equalsIgnoreCase("MaxOneElement")) { + readMaxOneElement(tok, filename, lineNo); } else if (cmd.equalsIgnoreCase("ArgumentIsString")) { readArgumentIsString(tok, filename, lineNo); } else if (cmd.equalsIgnoreCase("ExtendedInterfaceSymbolsIgnore")) { @@ -1287,12 +1319,10 @@ public class JavaConfiguration { readUnimplemented(tok, filename, lineNo); } else if (cmd.equalsIgnoreCase("IgnoreField")) { readIgnoreField(tok, filename, lineNo); + } else if (cmd.equalsIgnoreCase("ImmutableAccess")) { + readImmutableAccess(tok, filename, lineNo); } else if (cmd.equalsIgnoreCase("ManuallyImplement")) { readManuallyImplement(tok, filename, lineNo); - } else if (cmd.equalsIgnoreCase("ManualStaticInitCall")) { - readManualStaticInitCall(tok, filename, lineNo); - } else if (cmd.equalsIgnoreCase("ForceStaticInitCode")) { - readForceStaticInitCode(tok, filename, lineNo); } else if (cmd.equalsIgnoreCase("CustomJavaCode")) { readCustomJavaCode(tok, filename, lineNo); // Warning: make sure delimiters are reset at the top of this loop @@ -1476,6 +1506,16 @@ public class JavaConfiguration { } } + protected void readReturnsStringOnly(final StringTokenizer tok, final String filename, final int lineNo) { + try { + final String name = tok.nextToken(); + returnsStringOnly.add(name); + } catch (final NoSuchElementException e) { + throw new RuntimeException("Error parsing \"ReturnsStringOnly\" command at line " + lineNo + + " in file \"" + filename + "\"", e); + } + } + protected void readReturnedArrayLength(final StringTokenizer tok, final String filename, final int lineNo) { try { final String functionName = tok.nextToken(); @@ -1488,6 +1528,16 @@ public class JavaConfiguration { } } + protected void readMaxOneElement(final StringTokenizer tok, final String filename, final int lineNo) { + try { + final String name = tok.nextToken(); + maxOneElement.add(name); + } catch (final NoSuchElementException e) { + throw new RuntimeException("Error parsing \"MaxOneElement\" command at line " + lineNo + + " in file \"" + filename + "\"", e); + } + } + protected void readExtendedIntfImplSymbols(final StringTokenizer tok, final String filename, final int lineNo, final boolean forInterface, final boolean forImplementation, final boolean onlyList) { File javaFile; BufferedReader javaReader; @@ -1598,30 +1648,22 @@ public class JavaConfiguration { } } - protected void readManuallyImplement(final StringTokenizer tok, final String filename, final int lineNo) { + protected void readImmutableAccess(final StringTokenizer tok, final String filename, final int lineNo) { try { final String name = tok.nextToken(); - manuallyImplement.add(name); + immutableAccessSymbols.add(name); } catch (final NoSuchElementException e) { - throw new RuntimeException("Error parsing \"ManuallyImplement\" command at line " + lineNo + + throw new RuntimeException("Error parsing \"ImmutableAccess\" command at line " + lineNo + " in file \"" + filename + "\"", e); } } - protected void readManualStaticInitCall(final StringTokenizer tok, final String filename, final int lineNo) { - try { - final String name = tok.nextToken(); - manualStaticInitCall.add(name); - } catch (final NoSuchElementException e) { - throw new RuntimeException("Error parsing \"ManualStaticInitCall\" command at line " + lineNo + - " in file \"" + filename + "\"", e); - } - } - protected void readForceStaticInitCode(final StringTokenizer tok, final String filename, final int lineNo) { + + protected void readManuallyImplement(final StringTokenizer tok, final String filename, final int lineNo) { try { final String name = tok.nextToken(); - forceStaticInitCode.add(name); + manuallyImplement.add(name); } catch (final NoSuchElementException e) { - throw new RuntimeException("Error parsing \"ForceStaticInitCode\" command at line " + lineNo + + throw new RuntimeException("Error parsing \"ManuallyImplement\" command at line " + lineNo + " in file \"" + filename + "\"", e); } } diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java index 577bca4..4e8a35f 100644 --- a/src/java/com/jogamp/gluegen/JavaEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaEmitter.java @@ -407,22 +407,6 @@ public class JavaEmitter implements GlueEmitter { return cfg; } - /** - * Returns true if implementation (java and native-code) - * requires {@link #staticClassInitCodeCCode} and {@link #staticClassInitCallJavaCode} - * and have initializeImpl() being called at static class initialization. - *

- * This is currently true, if one of the following method returns true - *

    - *
  • {@link MethodBinding#signatureRequiresStaticInitialization() one of the binding's signature requires it}
  • - *
  • {@link JavaConfiguration#forceStaticInitCode(String)}
  • - *
- *

- */ - protected final boolean requiresStaticInitialization(final String clazzName) { - return requiresStaticInitialization || cfg.forceStaticInitCode(clazzName); - } - /** * Generates the public emitters for this MethodBinding which will * produce either simply signatures (for the interface class, if @@ -466,13 +450,6 @@ public class JavaEmitter implements GlueEmitter { null != prologue || null != epilogue; - if( !requiresStaticInitialization ) { - requiresStaticInitialization = binding.signatureRequiresStaticInitialization(); - if( requiresStaticInitialization ) { - LOG.log(INFO, cSymbol.getASTLocusTag(), "StaticInit Trigger.1 \"{0}\"", binding); - } - } - final boolean emitBody = !signatureOnly && needsBody; final boolean isNativeMethod = !isUnimplemented && !needsBody && !signatureOnly; @@ -535,12 +512,6 @@ public class JavaEmitter implements GlueEmitter { cfg.javaEpilogueForMethod(binding, false, false) != null ; if ( !cfg.isUnimplemented( cSymbol ) ) { - if( !requiresStaticInitialization ) { - requiresStaticInitialization = binding.signatureRequiresStaticInitialization(); - if( requiresStaticInitialization ) { - LOG.log(INFO, cSymbol.getASTLocusTag(), "StaticInit Trigger.2 \"{0}\"", binding); - } - } // If we already generated a public native entry point for this // method, don't emit another one diff --git a/src/java/com/jogamp/gluegen/MethodBinding.java b/src/java/com/jogamp/gluegen/MethodBinding.java index efa938f..42bae04 100644 --- a/src/java/com/jogamp/gluegen/MethodBinding.java +++ b/src/java/com/jogamp/gluegen/MethodBinding.java @@ -69,7 +69,6 @@ public class MethodBinding { private boolean signatureUsesCPrimitivePointers; private boolean signatureUsesCArrays; private boolean signatureUsesJavaPrimitiveArrays; - private boolean signatureRequiresStaticInitialization; private int thisPointerIndex = -1; /** @@ -96,7 +95,6 @@ public class MethodBinding { this.signatureUsesCPrimitivePointers = bindingToCopy.signatureUsesCPrimitivePointers; this.signatureUsesCArrays = bindingToCopy.signatureUsesCArrays; this.signatureUsesJavaPrimitiveArrays = bindingToCopy.signatureUsesJavaPrimitiveArrays; - this.signatureRequiresStaticInitialization = bindingToCopy.signatureRequiresStaticInitialization; this.thisPointerIndex = bindingToCopy.thisPointerIndex; } @@ -283,21 +281,6 @@ public class MethodBinding { return signatureUsesCompoundTypeWrappers; } - /** - * Returns true if the wrapper implementation requires - * static native code to be initialized, see {@link JavaConfiguration#forceStaticInitCode(String)}. - *

- * Currently triggered by: - *

    - *
  • Return type is a "compound type" and not a pointer
  • - *
- *

- */ - public boolean signatureRequiresStaticInitialization() { - computeSignatureProperties(); - return signatureRequiresStaticInitialization; - } - /** * Returns true if the return type or any of the outgoing arguments * in the method's signature use arrays of "compound type wrappers", @@ -371,17 +354,11 @@ public class MethodBinding { signatureUsesCPrimitivePointers = false; signatureUsesCArrays = false; signatureUsesJavaPrimitiveArrays = false; - signatureRequiresStaticInitialization = false; if ( javaReturnType.isCompoundTypeWrapper() ) { // Needs wrapping and/or setting of byte order (neither of which // can be done easily from native code) signatureUsesCompoundTypeWrappers = true; - - final Type cReturnType = getCReturnType(); - if ( !cReturnType.isPointer() ) { // FIXME: Compound call-by-value - signatureRequiresStaticInitialization = true; - } } if (javaReturnType.isNIOBuffer() || -- cgit v1.2.3