8200131: Improve lazy init of InetAddress.canonicalHostName and NativeObject.pageSize
Reviewed-by: alanb

   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 jdk.internal.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     /**
 392      * Cache for page size.
 393      * Lazily initialized via a data race; safe because ints are atomic.
 394      */
 395     private static int pageSize = -1;
 396 
 397     /**
 398      * Returns the page size of the underlying hardware.
 399      *
 400      * @return  The page size, in bytes
 401      */
 402     static int pageSize() {
 403         int value = pageSize;
 404         if (value == -1)
 405             pageSize = value = unsafe.pageSize();
 406         return value;
 407     }
 408 
 409 }
--- EOF ---