1 /* 2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.apple.jobjc; 26 27 import java.nio.ByteOrder; 28 29 import com.apple.jobjc.Coder.PrimitivePointerCoder; 30 31 import javax.tools.annotation.GenerateNativeHeader; 32 33 /* No native methods here, but the constants are needed in the supporting JNI code */ 34 @GenerateNativeHeader 35 public final class NativeArgumentBuffer{ 36 private static final ThreadLocal<NativeArgumentBuffer> threadLocal = new ThreadLocal<NativeArgumentBuffer>(); 37 38 static NativeArgumentBuffer getThreadLocalBuffer(final JObjCRuntime runtime) { 39 runtime.assertOK(); 40 final NativeArgumentBuffer alreadyCreated = threadLocal.get(); 41 if (alreadyCreated != null) return alreadyCreated; 42 43 final NativeArgumentBuffer newThreadLocalState = new NativeArgumentBuffer(runtime); 44 threadLocal.set(newThreadLocalState); 45 return newThreadLocalState; 46 } 47 48 final JObjCRuntime runtime; 49 50 final NativeBuffer buffer; 51 52 long argPtrsPtr; 53 long argValuesPtr; 54 final long retValPtr; 55 56 private static final int MAX_ARGS = 512; 57 private static final int BUF_SIZE = MAX_ARGS * 8 * 2; 58 private static final int ARG_VALS_OFFSET = BUF_SIZE/2; 59 60 private NativeArgumentBuffer(final JObjCRuntime runtime) { 61 runtime.assertOK(); 62 this.runtime = runtime; 63 this.buffer = new NativeBuffer(BUF_SIZE); 64 this.buffer.buffer.order(ByteOrder.nativeOrder()); 65 66 reset(); 67 this.retValPtr = buffer.bufferPtr; 68 } 69 70 71 // Call before each new call 72 public void reset() { 73 argPtrsPtr = buffer.bufferPtr; 74 argValuesPtr = buffer.bufferPtr + ARG_VALS_OFFSET; 75 assert buffer.ptrInBounds(argValuesPtr); 76 } 77 78 // Push a pointer to a block of memory 79 public void doPutArgPtr(long ptr) { 80 assert buffer.ptrInBounds(argPtrsPtr); 81 PrimitivePointerCoder.INST.push(runtime, argPtrsPtr, ptr); 82 argPtrsPtr += JObjCRuntime.PTR_LEN; 83 } 84 85 // Call this after having written a value of size `sizeof` to `argValuesPtr`. 86 public void didPutArgValue(int sizeof) { 87 assert buffer.ptrInBounds(argValuesPtr); 88 doPutArgPtr(argValuesPtr); 89 argValuesPtr += sizeof; 90 } 91 92 93 @Override public String toString() { 94 final StringBuilder builder = new StringBuilder(); 95 final long bptr = buffer.bufferPtr; 96 97 for(long i = bptr; i < bptr + ARG_VALS_OFFSET; i += JObjCRuntime.PTR_LEN){ 98 if(argPtrsPtr == i) 99 builder.append("*"); 100 builder.append(PrimitivePointerCoder.INST.popPtr(JObjCRuntime.inst(), i)); 101 builder.append(" "); 102 } 103 104 builder.append("\n"); 105 106 for(long i = bptr + ARG_VALS_OFFSET; i < bptr + BUF_SIZE; i += JObjCRuntime.PTR_LEN){ 107 if(argValuesPtr == i) 108 builder.append("*"); 109 builder.append(PrimitivePointerCoder.INST.popPtr(JObjCRuntime.inst(), i)); 110 builder.append(" "); 111 } 112 113 return builder.toString(); 114 } 115 }