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      */
NativeObject(long address)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      */
NativeObject(long address, long offset)66     NativeObject(long address, long offset) {
67         this.allocationAddress = address;
68         this.address = address + offset;
69     }
70 
71     // Invoked only by AllocatedNativeObject
72     //
NativeObject(int size, boolean pageAligned)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      */
address()90     long address() {
91         return address;
92     }
93 
allocationAddress()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      */
subObject(int offset)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      */
getObject(int offset)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      */
putObject(int offset, NativeObject ob)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      */
getByte(int offset)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      */
putByte(int offset, byte value)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      */
getShort(int offset)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      */
putShort(int offset, short value)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      */
getChar(int offset)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      */
putChar(int offset, char value)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      */
getInt(int offset)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      */
putInt(int offset, int value)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      */
getLong(int offset)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      */
putLong(int offset, long value)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      */
getFloat(int offset)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      */
putFloat(int offset, float value)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      */
getDouble(int offset)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      */
putDouble(int offset, double value)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      */
addressSize()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      */
byteOrder()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      */
pageSize()402     static int pageSize() {
403         int value = pageSize;
404         if (value == -1)
405             pageSize = value = unsafe.pageSize();
406         return value;
407     }
408 
409 }
410