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
29package sun.nio.ch;                                     // Formerly in sun.misc
30
31import java.nio.ByteOrder;
32import 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
41class 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