Home | History | Annotate | Download | only in ch
      1 /*
      2  * Copyright (c) 2000, 2002, 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 
     26 /*
     27  */
     28 
     29 package sun.nio.ch;                                     // Formerly in sun.misc
     30 
     31 import java.nio.ByteOrder;
     32 import sun.misc.Unsafe;
     33 
     34 
     35 // ## In the fullness of time, this class will be eliminated
     36 
     37 /**
     38  * Proxies for objects that reside in native memory.
     39  */
     40 
     41 class NativeObject {                                    // package-private
     42 
     43     protected static final Unsafe unsafe = Unsafe.getUnsafe();
     44 
     45     // Native allocation address;
     46     // may be smaller than the base address due to page-size rounding
     47     //
     48     protected long allocationAddress;
     49 
     50     // Native base address
     51     //
     52     private final long address;
     53 
     54     /**
     55      * Creates a new native object that is based at the given native address.
     56      */
     57     NativeObject(long address) {
     58         this.allocationAddress = address;
     59         this.address = address;
     60     }
     61 
     62     /**
     63      * Creates a new native object allocated at the given native address but
     64      * whose base is at the additional offset.
     65      */
     66     NativeObject(long address, long offset) {
     67         this.allocationAddress = address;
     68         this.address = address + offset;
     69     }
     70 
     71     // Invoked only by AllocatedNativeObject
     72     //
     73     protected NativeObject(int size, boolean pageAligned) {
     74         if (!pageAligned) {
     75             this.allocationAddress = unsafe.allocateMemory(size);
     76             this.address = this.allocationAddress;
     77         } else {
     78             int ps = pageSize();
     79             long a = unsafe.allocateMemory(size + ps);
     80             this.allocationAddress = a;
     81             this.address = a + ps - (a & (ps - 1));
     82         }
     83     }
     84 
     85     /**
     86      * Returns the native base address of this native object.
     87      *
     88      * @return The native base address
     89      */
     90     long address() {
     91         return address;
     92     }
     93 
     94     long allocationAddress() {
     95         return allocationAddress;
     96     }
     97 
     98     /**
     99      * Creates a new native object starting at the given offset from the base
    100      * of this native object.
    101      *
    102      * @param  offset
    103      *         The offset from the base of this native object that is to be
    104      *         the base of the new native object
    105      *
    106      * @return The newly created native object
    107      */
    108     NativeObject subObject(int offset) {
    109         return new NativeObject(offset + address);
    110     }
    111 
    112     /**
    113      * Reads an address from this native object at the given offset and
    114      * constructs a native object using that address.
    115      *
    116      * @param  offset
    117      *         The offset of the address to be read.  Note that the size of an
    118      *         address is implementation-dependent.
    119      *
    120      * @return The native object created using the address read from the
    121      *         given offset
    122      */
    123     NativeObject getObject(int offset) {
    124         long newAddress = 0L;
    125         switch (addressSize()) {
    126             case 8:
    127                 newAddress = unsafe.getLong(offset + address);
    128                 break;
    129             case 4:
    130                 newAddress = unsafe.getInt(offset + address) & 0x00000000FFFFFFFF;
    131                 break;
    132             default:
    133                 throw new InternalError("Address size not supported");
    134         }
    135 
    136         return new NativeObject(newAddress);
    137     }
    138 
    139     /**
    140      * Writes the base address of the given native object at the given offset
    141      * of this native object.
    142      *
    143      * @param  offset
    144      *         The offset at which the address is to be written.  Note that the
    145      *         size of an address is implementation-dependent.
    146      *
    147      * @param  ob
    148      *         The native object whose address is to be written
    149      */
    150     void putObject(int offset, NativeObject ob) {
    151         switch (addressSize()) {
    152             case 8:
    153                 putLong(offset, ob.address);
    154                 break;
    155             case 4:
    156                 putInt(offset, (int)(ob.address & 0x00000000FFFFFFFF));
    157                 break;
    158             default:
    159                 throw new InternalError("Address size not supported");
    160         }
    161     }
    162 
    163 
    164     /* -- Value accessors: No range checking! -- */
    165 
    166     /**
    167      * Reads a byte starting at the given offset from base of this native
    168      * object.
    169      *
    170      * @param  offset
    171      *         The offset at which to read the byte
    172      *
    173      * @return The byte value read
    174      */
    175     final byte getByte(int offset) {
    176         return unsafe.getByte(offset + address);
    177     }
    178 
    179     /**
    180      * Writes a byte at the specified offset from this native object's
    181      * base address.
    182      *
    183      * @param  offset
    184      *         The offset at which to write the byte
    185      *
    186      * @param  value
    187      *         The byte value to be written
    188      */
    189     final void putByte(int offset, byte value) {
    190         unsafe.putByte(offset + address,  value);
    191     }
    192 
    193     /**
    194      * Reads a short starting at the given offset from base of this native
    195      * object.
    196      *
    197      * @param  offset
    198      *         The offset at which to read the short
    199      *
    200      * @return The short value read
    201      */
    202     final short getShort(int offset) {
    203         return unsafe.getShort(offset + address);
    204     }
    205 
    206     /**
    207      * Writes a short at the specified offset from this native object's
    208      * base address.
    209      *
    210      * @param  offset
    211      *         The offset at which to write the short
    212      *
    213      * @param  value
    214      *         The short value to be written
    215      */
    216     final void putShort(int offset, short value) {
    217         unsafe.putShort(offset + address,  value);
    218     }
    219 
    220     /**
    221      * Reads a char starting at the given offset from base of this native
    222      * object.
    223      *
    224      * @param  offset
    225      *         The offset at which to read the char
    226      *
    227      * @return The char value read
    228      */
    229     final char getChar(int offset) {
    230         return unsafe.getChar(offset + address);
    231     }
    232 
    233     /**
    234      * Writes a char at the specified offset from this native object's
    235      * base address.
    236      *
    237      * @param  offset
    238      *         The offset at which to write the char
    239      *
    240      * @param  value
    241      *         The char value to be written
    242      */
    243     final void putChar(int offset, char value) {
    244         unsafe.putChar(offset + address,  value);
    245     }
    246 
    247     /**
    248      * Reads an int starting at the given offset from base of this native
    249      * object.
    250      *
    251      * @param  offset
    252      *         The offset at which to read the int
    253      *
    254      * @return The int value read
    255      */
    256     final int getInt(int offset) {
    257         return unsafe.getInt(offset + address);
    258     }
    259 
    260     /**
    261      * Writes an int at the specified offset from this native object's
    262      * base address.
    263      *
    264      * @param  offset
    265      *         The offset at which to write the int
    266      *
    267      * @param  value
    268      *         The int value to be written
    269      */
    270     final void putInt(int offset, int value) {
    271         unsafe.putInt(offset + address, value);
    272     }
    273 
    274     /**
    275      * Reads a long starting at the given offset from base of this native
    276      * object.
    277      *
    278      * @param  offset
    279      *         The offset at which to read the long
    280      *
    281      * @return The long value read
    282      */
    283     final long getLong(int offset) {
    284         return unsafe.getLong(offset + address);
    285     }
    286 
    287     /**
    288      * Writes a long at the specified offset from this native object's
    289      * base address.
    290      *
    291      * @param  offset
    292      *         The offset at which to write the long
    293      *
    294      * @param  value
    295      *         The long value to be written
    296      */
    297     final void putLong(int offset, long value) {
    298         unsafe.putLong(offset + address, value);
    299     }
    300 
    301     /**
    302      * Reads a float starting at the given offset from base of this native
    303      * object.
    304      *
    305      * @param  offset
    306      *         The offset at which to read the float
    307      *
    308      * @return The float value read
    309      */
    310     final float getFloat(int offset) {
    311         return unsafe.getFloat(offset + address);
    312     }
    313 
    314     /**
    315      * Writes a float at the specified offset from this native object's
    316      * base address.
    317      *
    318      * @param  offset
    319      *         The offset at which to write the float
    320      *
    321      * @param  value
    322      *         The float value to be written
    323      */
    324     final void putFloat(int offset, float value) {
    325         unsafe.putFloat(offset + address, value);
    326     }
    327 
    328     /**
    329      * Reads a double starting at the given offset from base of this native
    330      * object.
    331      *
    332      * @param  offset
    333      *         The offset at which to read the double
    334      *
    335      * @return The double value read
    336      */
    337     final double getDouble(int offset) {
    338         return unsafe.getDouble(offset + address);
    339     }
    340 
    341     /**
    342      * Writes a double at the specified offset from this native object's
    343      * base address.
    344      *
    345      * @param  offset
    346      *         The offset at which to write the double
    347      *
    348      * @param  value
    349      *         The double value to be written
    350      */
    351     final void putDouble(int offset, double value) {
    352         unsafe.putDouble(offset + address, value);
    353     }
    354 
    355     /**
    356      * Returns the native architecture's address size in bytes.
    357      *
    358      * @return The address size of the native architecture
    359      */
    360     static int addressSize() {
    361         return unsafe.addressSize();
    362     }
    363 
    364     // Cache for byte order
    365     private static ByteOrder byteOrder = null;
    366 
    367     /**
    368      * Returns the byte order of the underlying hardware.
    369      *
    370      * @return  An instance of {@link java.nio.ByteOrder}
    371      */
    372     static ByteOrder byteOrder() {
    373         if (byteOrder != null)
    374             return byteOrder;
    375         long a = unsafe.allocateMemory(8);
    376         try {
    377             unsafe.putLong(a, 0x0102030405060708L);
    378             byte b = unsafe.getByte(a);
    379             switch (b) {
    380             case 0x01: byteOrder = ByteOrder.BIG_ENDIAN;     break;
    381             case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN;  break;
    382             default:
    383                 assert false;
    384             }
    385         } finally {
    386             unsafe.freeMemory(a);
    387         }
    388         return byteOrder;
    389     }
    390 
    391     // Cache for page size
    392     private static int pageSize = -1;
    393 
    394     /**
    395      * Returns the page size of the underlying hardware.
    396      *
    397      * @return  The page size, in bytes
    398      */
    399     static int pageSize() {
    400         if (pageSize == -1)
    401             pageSize = unsafe.pageSize();
    402         return pageSize;
    403     }
    404 
    405 }
    406