diff options
author | Kenneth Russel <[email protected]> | 2006-03-06 01:18:05 +0000 |
---|---|---|
committer | Kenneth Russel <[email protected]> | 2006-03-06 01:18:05 +0000 |
commit | 6502e754c6f4c12148433d2376cc241c374d9fc7 (patch) | |
tree | 87ea2b1978e1d0ade92d26e5caf0d9d0222855ef /src/java | |
parent | 7669b88d5ea5d46e0d83632fb2afdcc75f4f5abc (diff) |
Added NativeSignatureEmitter
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/gluegen/trunk@22 a78bb65f-1512-4460-ba86-f6dc96a7bf27
Diffstat (limited to 'src/java')
3 files changed, 789 insertions, 0 deletions
diff --git a/src/java/com/sun/gluegen/nativesig/NativeSignatureEmitter.java b/src/java/com/sun/gluegen/nativesig/NativeSignatureEmitter.java new file mode 100755 index 0000000..4fe81af --- /dev/null +++ b/src/java/com/sun/gluegen/nativesig/NativeSignatureEmitter.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.gluegen.nativesig; + +import java.io.*; +import java.util.*; + +import com.sun.gluegen.*; +import com.sun.gluegen.cgram.types.*; +import com.sun.gluegen.opengl.*; +import com.sun.gluegen.procaddress.*; + +/** Emitter producing NativeSignature attributes. */ + +public class NativeSignatureEmitter extends GLEmitter { + protected List generateMethodBindingEmitters(FunctionSymbol sym) throws Exception { + // Allow superclass to do most of the work for us + List res = super.generateMethodBindingEmitters(sym); + + // Filter out all non-JavaMethodBindingEmitters + for (Iterator iter = res.iterator(); iter.hasNext(); ) { + FunctionEmitter emitter = (FunctionEmitter) iter.next(); + if (!(emitter instanceof JavaMethodBindingEmitter)) { + iter.remove(); + } + } + + if (res.isEmpty()) { + return res; + } + + PrintWriter writer = (getConfig().allStatic() ? javaWriter() : javaImplWriter()); + + List processed = new ArrayList(); + + // First, filter out all emitters going to the "other" (public) writer + for (Iterator iter = res.iterator(); iter.hasNext(); ) { + FunctionEmitter emitter = (FunctionEmitter) iter.next(); + if (emitter.getDefaultOutput() != writer) { + processed.add(emitter); + iter.remove(); + } + } + + // Now process all of the remaining emitters sorted by MethodBinding + while (!res.isEmpty()) { + List emittersForBinding = new ArrayList(); + JavaMethodBindingEmitter emitter = (JavaMethodBindingEmitter) res.remove(0); + emittersForBinding.add(emitter); + MethodBinding binding = emitter.getBinding(); + for (Iterator iter = res.iterator(); iter.hasNext(); ) { + JavaMethodBindingEmitter emitter2 = (JavaMethodBindingEmitter) iter.next(); + if (emitter2.getBinding() == binding) { + emittersForBinding.add(emitter2); + iter.remove(); + } + } + generateNativeSignatureEmitters(binding, emittersForBinding); + processed.addAll(emittersForBinding); + } + + return processed; + } + + protected void generateNativeSignatureEmitters(MethodBinding binding, + List allEmitters) { + if (allEmitters.isEmpty()) { + return; + } + + PrintWriter writer = (getConfig().allStatic() ? javaWriter() : javaImplWriter()); + + // Give ourselves the chance to interpose on the generation of all code to keep things simple + List newEmitters = new ArrayList(); + for (Iterator iter = allEmitters.iterator(); iter.hasNext(); ) { + JavaMethodBindingEmitter javaEmitter = (JavaMethodBindingEmitter) iter.next(); + NativeSignatureJavaMethodBindingEmitter newEmitter = null; + if (javaEmitter instanceof GLJavaMethodBindingEmitter) { + newEmitter = new NativeSignatureJavaMethodBindingEmitter((GLJavaMethodBindingEmitter) javaEmitter); + } else if (javaEmitter instanceof ProcAddressJavaMethodBindingEmitter) { + newEmitter = new NativeSignatureJavaMethodBindingEmitter((ProcAddressJavaMethodBindingEmitter) javaEmitter); + } else { + newEmitter = new NativeSignatureJavaMethodBindingEmitter(javaEmitter, this); + } + newEmitters.add(newEmitter); + } + allEmitters.clear(); + allEmitters.addAll(newEmitters); + + // Detect whether we need to produce more or modify some of these emitters. + // Note that at this point we are assuming that generatePublicEmitters has + // been called with signatureOnly both true and false. + if (signatureContainsStrings(binding) && + !haveEmitterWithBody(allEmitters)) { + // This basically handles glGetString but also any similar methods + NativeSignatureJavaMethodBindingEmitter javaEmitter = findEmitterWithWriter(allEmitters, writer); + + // First, we need to clone this emitter to produce the native + // entry point + NativeSignatureJavaMethodBindingEmitter emitter = + new NativeSignatureJavaMethodBindingEmitter(javaEmitter); + emitter.removeModifier(JavaMethodBindingEmitter.PUBLIC); + emitter.addModifier(JavaMethodBindingEmitter.PRIVATE); + emitter.setForImplementingMethodCall(true); + // Note: this is chosen so we don't have to change the logic in + // emitReturnVariableSetupAndCall which decides which variant + // (direct / indirect) to call + emitter.setForDirectBufferImplementation(true); + allEmitters.add(emitter); + + // Now make the original emitter non-native and cause it to emit a body + javaEmitter.removeModifier(JavaMethodBindingEmitter.NATIVE); + javaEmitter.setEmitBody(true); + } + } + + protected boolean signatureContainsStrings(MethodBinding binding) { + for (int i = 0; i < binding.getNumArguments(); i++) { + JavaType type = binding.getJavaArgumentType(i); + if (type.isString() || type.isStringArray()) { + return true; + } + } + JavaType retType = binding.getJavaReturnType(); + if (retType.isString() || retType.isStringArray()) { + return true; + } + return false; + } + + protected boolean haveEmitterWithBody(List allEmitters) { + for (Iterator iter = allEmitters.iterator(); iter.hasNext(); ) { + JavaMethodBindingEmitter emitter = (JavaMethodBindingEmitter) iter.next(); + if (!emitter.signatureOnly()) { + return true; + } + } + return false; + } + + protected NativeSignatureJavaMethodBindingEmitter findEmitterWithWriter(List allEmitters, PrintWriter writer) { + for (Iterator iter = allEmitters.iterator(); iter.hasNext(); ) { + NativeSignatureJavaMethodBindingEmitter emitter = + (NativeSignatureJavaMethodBindingEmitter) iter.next(); + if (emitter.getDefaultOutput() == writer) { + return emitter; + } + } + throw new RuntimeException("Unexpectedly failed to find an emitter with the given writer"); + } +} diff --git a/src/java/com/sun/gluegen/nativesig/NativeSignatureJavaMethodBindingEmitter.java b/src/java/com/sun/gluegen/nativesig/NativeSignatureJavaMethodBindingEmitter.java new file mode 100755 index 0000000..71382bf --- /dev/null +++ b/src/java/com/sun/gluegen/nativesig/NativeSignatureJavaMethodBindingEmitter.java @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.gluegen.nativesig; + +import java.io.*; +import java.util.*; +import java.text.MessageFormat; + +import com.sun.gluegen.*; +import com.sun.gluegen.cgram.types.*; +import com.sun.gluegen.cgram.*; +import com.sun.gluegen.opengl.*; +import com.sun.gluegen.procaddress.*; + +public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBindingEmitter { + public NativeSignatureJavaMethodBindingEmitter(GLJavaMethodBindingEmitter methodToWrap) { + super(methodToWrap); + } + + public NativeSignatureJavaMethodBindingEmitter(ProcAddressJavaMethodBindingEmitter methodToWrap) { + super(methodToWrap, false); + } + + public NativeSignatureJavaMethodBindingEmitter(JavaMethodBindingEmitter methodToWrap, + NativeSignatureEmitter emitter) { + super(methodToWrap, false, null, false, false, emitter); + } + + protected void emitSignature(PrintWriter writer) { + writer.print(getBaseIndentString()); + emitNativeSignatureAnnotation(writer); + super.emitSignature(writer); + } + + protected void emitNativeSignatureAnnotation(PrintWriter writer) { + if (hasModifier(JavaMethodBindingEmitter.NATIVE)) { + // Emit everything as a leaf for now + // FIXME: make this configurable + writer.print("@NativeSignature(\"l"); + MethodBinding binding = getBinding(); + if (callThroughProcAddress) { + writer.print("p"); + } + writer.print("("); + if (callThroughProcAddress) { + writer.print("P"); + } + for (int i = 0; i < binding.getNumArguments(); i++) { + emitNativeSignatureElement(writer, binding.getJavaArgumentType(i), binding.getCArgumentType(i), i); + } + writer.print(")"); + emitNativeSignatureElement(writer, binding.getJavaReturnType(), binding.getCReturnType(), -1); + writer.println("\")"); + } + } + + protected void emitNativeSignatureElement(PrintWriter writer, JavaType type, Type cType, int index) { + if (type.isVoid()) { + if (index > 0) { + throw new InternalError("Error parsing arguments -- void should not be seen aside from argument 0"); + } + return; + } + + if (type.isNIOBuffer()) { + writer.print("A"); + } else if (type.isPrimitiveArray()) { + writer.print("MO"); + } else if (type.isPrimitive()) { + Class clazz = type.getJavaClass(); + if (clazz == Byte.TYPE) { writer.print("B"); } + else if (clazz == Character.TYPE) { writer.print("C"); } + else if (clazz == Double.TYPE) { writer.print("D"); } + else if (clazz == Float.TYPE) { writer.print("F"); } + else if (clazz == Integer.TYPE) { writer.print("I"); } + else if (clazz == Long.TYPE) { + // See if this is intended to be a pointer at the C level + if (cType.isPointer()) { + writer.print("A"); + } else { + writer.print("J"); + } + } + else if (clazz == Short.TYPE) { writer.print("S"); } + else if (clazz == Boolean.TYPE) { writer.print("Z"); } + else throw new InternalError("Unhandled primitive type " + clazz); + } else if (type.isString()) { + writer.print("A"); + } else { + throw new RuntimeException("Type not yet handled: " + type); + } + } + + protected String getReturnTypeString(boolean skipArray) { + if (isForImplementingMethodCall()) { + JavaType returnType = getBinding().getJavaReturnType(); + if (returnType.isString() || returnType.isNIOByteBuffer()) { + // Treat these as addresses + return "long"; + } + } + return super.getReturnTypeString(skipArray); + } + + protected void emitPreCallSetup(MethodBinding binding, PrintWriter writer) { + super.emitPreCallSetup(binding, writer); + for (int i = 0; i < binding.getNumArguments(); i++) { + JavaType type = binding.getJavaArgumentType(i); + if (type.isNIOBuffer() && !directNIOOnly) { + // Emit declarations for variables holding primitive arrays as type Object + // We don't know 100% sure we're going to use these at this point in the code, though + writer.println(" Object " + getNIOBufferArrayName(i) + " = (_direct ? null : BufferFactory.getArray(" + + getArgumentName(i) + "));"); + } else if (type.isString()) { + writer.println(" long " + binding.getArgumentName(i) + "_c_str = BufferFactoryInternal.newCString(" + binding.getArgumentName(i) + ");"); + } + // FIXME: going to need more of these for Buffer[] and String[], at least + } + } + + protected String getNIOBufferArrayName(int argNumber) { + return "__buffer_array_" + argNumber; + } + + protected int emitArguments(PrintWriter writer) + { + boolean needComma = false; + int numEmitted = 0; + + if (callThroughProcAddress) { + if (changeNameAndArguments) { + writer.print("long procAddress"); + ++numEmitted; + needComma = true; + } + } + + if (forImplementingMethodCall && binding.hasContainingType()) { + if (needComma) { + writer.print(", "); + } + + // Always emit outgoing "this" argument + writer.print("long "); + writer.print(javaThisArgumentName()); + ++numEmitted; + needComma = true; + } + + for (int i = 0; i < binding.getNumArguments(); i++) { + JavaType type = binding.getJavaArgumentType(i); + if (type.isVoid()) { + // Make sure this is the only param to the method; if it isn't, + // there's something wrong with our parsing of the headers. + if (binding.getNumArguments() != 1) { + throw new InternalError( + "\"void\" argument type found in " + + "multi-argument function \"" + binding + "\""); + } + continue; + } + + if (type.isJNIEnv() || binding.isArgumentThisPointer(i)) { + // Don't need to expose these at the Java level + continue; + } + + if (needComma) { + writer.print(", "); + } + + if (forImplementingMethodCall && + (forDirectBufferImplementation && type.isNIOBuffer() || + type.isString())) { + // Direct Buffers and Strings go out as longs + writer.print("long"); + // FIXME: will need more tests here to handle other constructs like String and direct Buffer arrays + } else { + writer.print(erasedTypeString(type, false)); + } + writer.print(" "); + writer.print(getArgumentName(i)); + + ++numEmitted; + needComma = true; + + // Add Buffer and array index offset arguments after each associated argument + if (forIndirectBufferAndArrayImplementation) { + if (type.isNIOBuffer()) { + writer.print(", int " + byteOffsetArgName(i)); + } else if (type.isNIOBufferArray()) { + writer.print(", int[] " + + byteOffsetArrayArgName(i)); + } + } + + // Add offset argument after each primitive array + if (type.isPrimitiveArray()) { + writer.print(", int " + offsetArgName(i)); + } + } + return numEmitted; + } + + protected void emitReturnVariableSetupAndCall(MethodBinding binding, PrintWriter writer) { + writer.print(" "); + JavaType returnType = binding.getJavaReturnType(); + boolean needsResultAssignment = false; + + if (!returnType.isVoid()) { + if (returnType.isCompoundTypeWrapper() || + returnType.isNIOByteBuffer()) { + writer.println("ByteBuffer _res;"); + needsResultAssignment = true; + } else if (returnType.isArrayOfCompoundTypeWrappers()) { + writer.println("ByteBuffer[] _res;"); + needsResultAssignment = true; + } else if (returnType.isString() || returnType.isNIOByteBuffer()) { + writer.print(returnType); + writer.println(" _res;"); + needsResultAssignment = true; + } else { + // Always assign to "_res" variable so we can clean up + // outgoing String arguments, for example + emitReturnType(writer); + writer.println(" _res;"); + needsResultAssignment = true; + } + } + + if (binding.signatureCanUseIndirectNIO() && !directNIOOnly) { + // Must generate two calls for this gated on whether the NIO + // buffers coming in are all direct or indirect + writer.println("if (_direct) {"); + writer.print (" "); + } + + if (needsResultAssignment) { + writer.print(" _res = "); + if (returnType.isString()) { + writer.print("BufferFactoryInternal.newJavaString("); + } else if (returnType.isNIOByteBuffer()) { + writer.print("BufferFactoryInternal.newDirectByteBuffer("); + } + } else { + writer.print(" "); + if (!returnType.isVoid()) { + writer.print("return "); + } + } + + if (binding.signatureUsesJavaPrimitiveArrays() && + !binding.signatureCanUseIndirectNIO()) { + // FIXME: what happens with a C function of the form + // void foo(int* arg0, void* arg1); + // ? + + // Only one call being made in this body, going to indirect + // buffer / array entry point + emitCall(binding, writer, false); + if (returnType.isString() || returnType.isNIOByteBuffer()) { + writer.print(")"); + } + writer.print(";"); + writer.println(); + } else { + emitCall(binding, writer, true); + if (returnType.isString() || returnType.isNIOByteBuffer()) { + writer.print(")"); + } + writer.print(";"); + } + + if (binding.signatureCanUseIndirectNIO() && !directNIOOnly) { + // Must generate two calls for this gated on whether the NIO + // buffers coming in are all direct or indirect + writer.println(); + writer.println(" } else {"); + writer.print (" "); + if (needsResultAssignment) { + writer.print(" _res = "); + } else { + writer.print(" "); + if (!returnType.isVoid()) { + writer.print("return "); + } + } + emitCall(binding, writer, false); + writer.print(";"); + writer.println(); + writer.println(" }"); + } else { + writer.println(); + } + emitPrologueOrEpilogue(epilogue, writer); + if (needsResultAssignment) { + emitCallResultReturn(binding, writer); + } + } + + protected int emitCallArguments(MethodBinding binding, PrintWriter writer, boolean direct) { + // Note that we override this completely because we both need to + // move the potential location of the outgoing proc address as + // well as change the way we pass out Buffers, arrays, Strings, etc. + + boolean needComma = false; + int numArgsEmitted = 0; + + if (callThroughProcAddress) { + writer.print("__addr_"); + needComma = true; + ++numArgsEmitted; + } + + if (binding.hasContainingType()) { + // Emit this pointer + assert(binding.getContainingType().isCompoundTypeWrapper()); + writer.print("BufferFactoryInternal.getDirectBufferAddress("); + writer.print("getBuffer()"); + writer.print(")"); + needComma = true; + ++numArgsEmitted; + } + for (int i = 0; i < binding.getNumArguments(); i++) { + JavaType type = binding.getJavaArgumentType(i); + if (type.isJNIEnv() || binding.isArgumentThisPointer(i)) { + // Don't need to expose these at the Java level + continue; + } + + if (type.isVoid()) { + // Make sure this is the only param to the method; if it isn't, + // there's something wrong with our parsing of the headers. + assert(binding.getNumArguments() == 1); + continue; + } + + if (needComma) { + writer.print(", "); + } + + if (type.isCompoundTypeWrapper()) { + writer.print("BufferFactoryInternal.getDirectBufferAddress("); + writer.print("(("); + } + + if (type.isNIOBuffer()) { + if (!direct) { + writer.print(getNIOBufferArrayName(i)); + } else { + writer.print("BufferFactoryInternal.getDirectBufferAddress("); + writer.print(getArgumentName(i)); + writer.print(")"); + } + } else { + writer.print(getArgumentName(i)); + } + + if (type.isCompoundTypeWrapper()) { + writer.print(" == null) ? null : "); + writer.print(getArgumentName(i)); + writer.print(".getBuffer())"); + writer.print(")"); + } + + if (type.isNIOBuffer()) { + if (direct) { + writer.print("+ BufferFactory.getDirectBufferByteOffset(" + getArgumentName(i) + ")"); + } else { + writer.print(", BufferFactoryInternal.arrayBaseOffset(" + + getNIOBufferArrayName(i) + + ") + BufferFactory.getIndirectBufferByteOffset(" + getArgumentName(i) + ")"); + } + } else if (type.isNIOBufferArray()) { + writer.print(", " + byteOffsetArrayArgName(i)); + } + + // Add Array offset parameter for primitive arrays + if (type.isPrimitiveArray()) { + writer.print(", "); + writer.print("BufferFactoryInternal.arrayBaseOffset(" + getArgumentName(i) + ") + "); + if(type.isFloatArray()) { + writer.print("BufferFactory.SIZEOF_FLOAT * "); + } else if(type.isDoubleArray()) { + writer.print("BufferFactory.SIZEOF_DOUBLE * "); + } else if(type.isByteArray()) { + writer.print("1 * "); + } else if(type.isLongArray()) { + writer.print("BufferFactory.SIZEOF_LONG * "); + } else if(type.isShortArray()) { + writer.print("BufferFactory.SIZEOF_SHORT * "); + } else if(type.isIntArray()) { + writer.print("BufferFactory.SIZEOF_INT * "); + } else { + throw new RuntimeException("Unsupported type for calculating array offset argument for " + + getArgumentName(i) + + "-- error occurred while processing Java glue code for " + getName()); + } + writer.print(offsetArgName(i)); + } + + if (type.isString()) { + writer.print("_c_str"); + } + + if (type.isCompoundTypeWrapper()) { + writer.print(")"); + } + + needComma = true; + ++numArgsEmitted; + } + return numArgsEmitted; + } + + protected void emitCallResultReturn(MethodBinding binding, PrintWriter writer) { + for (int i = 0; i < binding.getNumArguments(); i++) { + JavaType type = binding.getJavaArgumentType(i); + if (type.isString()) { + writer.println(";"); + writer.println(" BufferFactoryInternal.freeCString(" + binding.getArgumentName(i) + "_c_str);"); + } + // FIXME: will need more of these cleanups for things like Buffer[] and String[] (see above) + } + + super.emitCallResultReturn(binding, writer); + } + + public String getName() { + String res = super.getName(); + if (forImplementingMethodCall && bufferObjectVariant) { + return res + "BufObj"; + } + return res; + } + + protected String getImplMethodName(boolean direct) { + String name = null; + if (direct) { + name = binding.getRenamedMethodName() + "$0"; + } else { + name = binding.getRenamedMethodName() + "$1"; + } + if (bufferObjectVariant) { + return name + "BufObj"; + } + return name; + } +} diff --git a/src/java/com/sun/gluegen/runtime/BufferFactoryInternal.java b/src/java/com/sun/gluegen/runtime/BufferFactoryInternal.java new file mode 100755 index 0000000..7a0e6a8 --- /dev/null +++ b/src/java/com/sun/gluegen/runtime/BufferFactoryInternal.java @@ -0,0 +1,115 @@ +/* + + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.gluegen.runtime; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.nio.*; +import sun.misc.Unsafe; + +public class BufferFactoryInternal { + private static final long addressFieldOffset; + private static final Constructor directByteBufferConstructor; + + static { + try { + Field f = Buffer.class.getDeclaredField("address"); + addressFieldOffset = UnsafeAccess.getUnsafe().objectFieldOffset(f); + + Class directByteBufferClass = Class.forName("java.nio.DirectByteBuffer"); + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(new Class[] { Long.TYPE, Integer.TYPE }); + directByteBufferConstructor.setAccessible(true); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static long getDirectBufferAddress(Buffer buf) { + return ((buf == null) ? 0 : UnsafeAccess.getUnsafe().getLong(buf, addressFieldOffset)); + } + + public static ByteBuffer newDirectByteBuffer(long address, int capacity) { + try { + if (address == 0) { + return null; + } + return (ByteBuffer) directByteBufferConstructor.newInstance(new Object[] { new Long(address), new Integer(capacity) }); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static long newCString(String str) { + byte[] strBytes = str.getBytes(); + long strBlock = UnsafeAccess.getUnsafe().allocateMemory(strBytes.length+1); + for (int i = 0; i < strBytes.length; i++) { + UnsafeAccess.getUnsafe().putByte(strBlock+i, strBytes[i]); + } + UnsafeAccess.getUnsafe().putByte(strBlock+strBytes.length, (byte)0); // null termination + return strBlock; + } + + public static void freeCString(long cStr) { + UnsafeAccess.getUnsafe().freeMemory(cStr); + } + + public static String newJavaString(long cStr) { + if (cStr == 0) { + return null; + } + int numChars = 0; + while (UnsafeAccess.getUnsafe().getByte(cStr + numChars) != 0) { + ++numChars; + } + byte[] bytes = new byte[numChars]; + for (int i = 0; i < numChars; i++) { + bytes[i] = UnsafeAccess.getUnsafe().getByte(cStr + i); + } + return new String(bytes); + } + + public static int arrayBaseOffset(Object array) { + return UnsafeAccess.getUnsafe().arrayBaseOffset(array.getClass()); + } + public static int arrayIndexScale(Object array) { + return UnsafeAccess.getUnsafe().arrayIndexScale(array.getClass()); + } +} |