--- /dev/null 2018-11-02 08:21:54.000000000 -0700 +++ new/src/java.base/share/classes/jdk/internal/unsupported/UnsafeForwarder.java 2018-11-02 08:21:53.000000000 -0700 @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.unsupported; + +import jdk.internal.misc.Unsafe; +import jdk.internal.ref.Cleaner; +import jdk.internal.vm.annotation.ForceInline; +import sun.nio.ch.DirectBuffer; + +import java.lang.reflect.Field; + +public final class UnsafeForwarder { + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + private static final UnsafeForwarder HELPER = new UnsafeForwarder(); + + private UnsafeForwarder() { + } + + public static UnsafeForwarder getUnsafeHelper() { + return HELPER; + } + + /// peek and poke operations + /// (compilers should optimize these to memory ops) + public int getInt(Object o, long offset) { + return UNSAFE.getInt(o, offset); + } + + public void putInt(Object o, long offset, int x) { + UNSAFE.putInt(o, offset, x); + } + + public Object getReference(Object o, long offset) { + return UNSAFE.getReference(o, offset); + } + + public void putReference(Object o, long offset, Object x) { + UNSAFE.putReference(o, offset, x); + } + + public boolean getBoolean(Object o, long offset) { + return UNSAFE.getBoolean(o, offset); + } + + public void putBoolean(Object o, long offset, boolean x) { + UNSAFE.putBoolean(o, offset, x); + } + + public byte getByte(Object o, long offset) { + return UNSAFE.getByte(o, offset); + } + + public void putByte(Object o, long offset, byte x) { + UNSAFE.putByte(o, offset, x); + } + + public short getShort(Object o, long offset) { + return UNSAFE.getShort(o, offset); + } + + public void putShort(Object o, long offset, short x) { + UNSAFE.putShort(o, offset, x); + } + + public char getChar(Object o, long offset) { + return UNSAFE.getChar(o, offset); + } + + public void putChar(Object o, long offset, char x) { + UNSAFE.putChar(o, offset, x); + } + + public long getLong(Object o, long offset) { + return UNSAFE.getLong(o, offset); + } + + public void putLong(Object o, long offset, long x) { + UNSAFE.putLong(o, offset, x); + } + + public float getFloat(Object o, long offset) { + return UNSAFE.getFloat(o, offset); + } + + public void putFloat(Object o, long offset, float x) { + UNSAFE.putFloat(o, offset, x); + } + + public double getDouble(Object o, long offset) { + return UNSAFE.getDouble(o, offset); + } + + public void putDouble(Object o, long offset, double x) { + UNSAFE.putDouble(o, offset, x); + } + + // These work on values in the C heap. + + public byte getByte(long address) { + return UNSAFE.getByte(address); + } + + public void putByte(long address, byte x) { + UNSAFE.putByte(address, x); + } + + public short getShort(long address) { + return UNSAFE.getShort(address); + } + + public void putShort(long address, short x) { + UNSAFE.putShort(address, x); + } + + public char getChar(long address) { + return UNSAFE.getChar(address); + } + + public void putChar(long address, char x) { + UNSAFE.putChar(address, x); + } + + public int getInt(long address) { + return UNSAFE.getInt(address); + } + + public void putInt(long address, int x) { + UNSAFE.putInt(address, x); + } + + public long getLong(long address) { + return UNSAFE.getLong(address); + } + + public void putLong(long address, long x) { + UNSAFE.putLong(address, x); + } + + public float getFloat(long address) { + return UNSAFE.getFloat(address); + } + + public void putFloat(long address, float x) { + UNSAFE.putFloat(address, x); + } + + public double getDouble(long address) { + return UNSAFE.getDouble(address); + } + + public void putDouble(long address, double x) { + UNSAFE.putDouble(address, x); + } + + public long getAddress(long address) { + return UNSAFE.getAddress(address); + } + + public void putAddress(long address, long x) { + UNSAFE.putAddress(address, x); + } + + /// wrappers for malloc, realloc, free: + + public long allocateMemory(long bytes) { + return UNSAFE.allocateMemory(bytes); + } + + public long reallocateMemory(long address, long bytes) { + return UNSAFE.reallocateMemory(address, bytes); + } + + public void setMemory(Object o, long offset, long bytes, byte value) { + UNSAFE.setMemory(o, offset, bytes, value); + } + + public void setMemory(long address, long bytes, byte value) { + UNSAFE.setMemory(address, bytes, value); + } + + public void copyMemory(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes) { + UNSAFE.copyMemory(srcBase, srcOffset, destBase, destOffset, bytes); + } + + public void copyMemory(long srcAddress, long destAddress, long bytes) { + UNSAFE.copyMemory(srcAddress, destAddress, bytes); + } + + public void freeMemory(long address) { + UNSAFE.freeMemory(address); + } + + /// random queries + + /** + * This constant differs from all results that will ever be returned from + * {@link #staticFieldOffset}, {@link #objectFieldOffset}, + * or {@link #arrayBaseOffset}. + */ + public static final int INVALID_FIELD_OFFSET = jdk.internal.misc.Unsafe.INVALID_FIELD_OFFSET; + + public long objectFieldOffset(Field f) { + return UNSAFE.objectFieldOffset(f); + } + + public long staticFieldOffset(Field f) { + return UNSAFE.staticFieldOffset(f); + } + + public Object staticFieldBase(Field f) { + return UNSAFE.staticFieldBase(f); + } + + public boolean shouldBeInitialized(Class c) { + return UNSAFE.shouldBeInitialized(c); + } + + public void ensureClassInitialized(Class c) { + UNSAFE.ensureClassInitialized(c); + } + + public int arrayBaseOffset(Class arrayClass) { + return UNSAFE.arrayBaseOffset(arrayClass); + } + + /** + * The value of {@code arrayBaseOffset(boolean[].class)} + */ + public static final int ARRAY_BOOLEAN_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_BOOLEAN_BASE_OFFSET; + + /** + * The value of {@code arrayBaseOffset(byte[].class)} + */ + public static final int ARRAY_BYTE_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; + + /** + * The value of {@code arrayBaseOffset(short[].class)} + */ + public static final int ARRAY_SHORT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_SHORT_BASE_OFFSET; + + /** + * The value of {@code arrayBaseOffset(char[].class)} + */ + public static final int ARRAY_CHAR_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_CHAR_BASE_OFFSET; + + /** + * The value of {@code arrayBaseOffset(int[].class)} + */ + public static final int ARRAY_INT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_INT_BASE_OFFSET; + + /** + * The value of {@code arrayBaseOffset(long[].class)} + */ + public static final int ARRAY_LONG_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_LONG_BASE_OFFSET; + + /** + * The value of {@code arrayBaseOffset(float[].class)} + */ + public static final int ARRAY_FLOAT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_FLOAT_BASE_OFFSET; + + /** + * The value of {@code arrayBaseOffset(double[].class)} + */ + public static final int ARRAY_DOUBLE_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_DOUBLE_BASE_OFFSET; + + /** + * The value of {@code arrayBaseOffset(Object[].class)} + */ + public static final int ARRAY_OBJECT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_OBJECT_BASE_OFFSET; + + public int arrayIndexScale(Class arrayClass) { + return UNSAFE.arrayIndexScale(arrayClass); + } + + public static final int ARRAY_BOOLEAN_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_BOOLEAN_INDEX_SCALE; + + public static final int ARRAY_BYTE_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE; + + public static final int ARRAY_SHORT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_SHORT_INDEX_SCALE; + + public static final int ARRAY_CHAR_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_CHAR_INDEX_SCALE; + + public static final int ARRAY_INT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_INT_INDEX_SCALE; + + public static final int ARRAY_LONG_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_LONG_INDEX_SCALE; + + public static final int ARRAY_FLOAT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_FLOAT_INDEX_SCALE; + + public static final int ARRAY_DOUBLE_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_DOUBLE_INDEX_SCALE; + + public static final int ARRAY_OBJECT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_OBJECT_INDEX_SCALE; + + public int addressSize() { + return UNSAFE.addressSize(); + } + + /** + * The value of {@code addressSize()} + */ + public static final int ADDRESS_SIZE = UNSAFE.addressSize(); + + public int pageSize() { + return UNSAFE.pageSize(); + } + + + /// random trusted operations from JNI: + public Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches) { + return UNSAFE.defineAnonymousClass(hostClass, data, cpPatches); + } + + public Object allocateInstance(Class cls) + throws InstantiationException { + return UNSAFE.allocateInstance(cls); + } + + public void throwException(Throwable ee) { + UNSAFE.throwException(ee); + } + + public final boolean compareAndSetReference(Object o, long offset, + Object expected, + Object x) { + return UNSAFE.compareAndSetReference(o, offset, expected, x); + } + + public final boolean compareAndSetInt(Object o, long offset, + int expected, + int x) { + return UNSAFE.compareAndSetInt(o, offset, expected, x); + } + + public final boolean compareAndSetLong(Object o, long offset, + long expected, + long x) { + return UNSAFE.compareAndSetLong(o, offset, expected, x); + } + + public Object getReferenceVolatile(Object o, long offset) { + return UNSAFE.getReferenceVolatile(o, offset); + } + + public void putReferenceVolatile(Object o, long offset, Object x) { + UNSAFE.putReferenceVolatile(o, offset, x); + } + + public int getIntVolatile(Object o, long offset) { + return UNSAFE.getIntVolatile(o, offset); + } + + public void putIntVolatile(Object o, long offset, int x) { + UNSAFE.putIntVolatile(o, offset, x); + } + + public boolean getBooleanVolatile(Object o, long offset) { + return UNSAFE.getBooleanVolatile(o, offset); + } + + public void putBooleanVolatile(Object o, long offset, boolean x) { + UNSAFE.putBooleanVolatile(o, offset, x); + } + + public byte getByteVolatile(Object o, long offset) { + return UNSAFE.getByteVolatile(o, offset); + } + + public void putByteVolatile(Object o, long offset, byte x) { + UNSAFE.putByteVolatile(o, offset, x); + } + + public short getShortVolatile(Object o, long offset) { + return UNSAFE.getShortVolatile(o, offset); + } + + public void putShortVolatile(Object o, long offset, short x) { + UNSAFE.putShortVolatile(o, offset, x); + } + + public char getCharVolatile(Object o, long offset) { + return UNSAFE.getCharVolatile(o, offset); + } + + public void putCharVolatile(Object o, long offset, char x) { + UNSAFE.putCharVolatile(o, offset, x); + } + + public long getLongVolatile(Object o, long offset) { + return UNSAFE.getLongVolatile(o, offset); + } + + public void putLongVolatile(Object o, long offset, long x) { + UNSAFE.putLongVolatile(o, offset, x); + } + + public float getFloatVolatile(Object o, long offset) { + return UNSAFE.getFloatVolatile(o, offset); + } + + public void putFloatVolatile(Object o, long offset, float x) { + UNSAFE.putFloatVolatile(o, offset, x); + } + + public double getDoubleVolatile(Object o, long offset) { + return UNSAFE.getDoubleVolatile(o, offset); + } + + public void putDoubleVolatile(Object o, long offset, double x) { + UNSAFE.putDoubleVolatile(o, offset, x); + } + + public void putReferenceRelease(Object o, long offset, Object x) { + UNSAFE.putReferenceRelease(o, offset, x); + } + + public void putIntRelease(Object o, long offset, int x) { + UNSAFE.putIntRelease(o, offset, x); + } + + public void putLongRelease(Object o, long offset, long x) { + UNSAFE.putLongRelease(o, offset, x); + } + + public void unpark(Object thread) { + UNSAFE.unpark(thread); + } + + @ForceInline + public void park(boolean isAbsolute, long time) { + UNSAFE.park(isAbsolute, time); + } + + @ForceInline + public final int getAndAddInt(Object o, long offset, int delta) { + return UNSAFE.getAndAddInt(o, offset, delta); + } + + @ForceInline + public final long getAndAddLong(Object o, long offset, long delta) { + return UNSAFE.getAndAddLong(o, offset, delta); + } + + @ForceInline + public final int getAndSetInt(Object o, long offset, int newValue) { + return UNSAFE.getAndSetInt(o, offset, newValue); + } + + @ForceInline + public final long getAndSetLong(Object o, long offset, long newValue) { + return UNSAFE.getAndSetLong(o, offset, newValue); + } + + @ForceInline + public final Object getAndSetReference(Object o, long offset, Object newValue) { + return UNSAFE.getAndSetReference(o, offset, newValue); + } + + @ForceInline + public void loadFence() { + UNSAFE.loadFence(); + } + + @ForceInline + public void storeFence() { + UNSAFE.storeFence(); + } + + @ForceInline + public void fullFence() { + UNSAFE.fullFence(); + } + + /** + * Invokes the given direct byte buffer's cleaner, if any. + * + * @param directBuffer a direct byte buffer + * @throws NullPointerException if {@code directBuffer} is null + * @throws IllegalArgumentException if {@code directBuffer} is non-direct, + * or is a {@link java.nio.Buffer#slice slice}, or is a + * {@link java.nio.Buffer#duplicate duplicate} + * @since 9 + */ + public void invokeCleaner(java.nio.ByteBuffer directBuffer) { + if (!directBuffer.isDirect()) + throw new IllegalArgumentException("buffer is non-direct"); + + DirectBuffer db = (DirectBuffer) directBuffer; + if (db.attachment() != null) + throw new IllegalArgumentException("duplicate or slice"); + + Cleaner cleaner = db.cleaner(); + if (cleaner != null) { + cleaner.clean(); + } + } +} +