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 }