Package sun.misc

Source Code of sun.misc.NativeUnsafe

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package sun.misc;

import java.lang.reflect.Field;
import java.security.ProtectionDomain;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.CodeSource;
import java.security.Policy;
import java.security.cert.Certificate;
import java.util.Map;
import java.util.HashMap;
import org.vmmagic.unboxed.ObjectReference;
import org.vmmagic.unboxed.Address;
import org.jnode.vm.classmgr.VmStaticField;
import org.jnode.vm.classmgr.VmInstanceField;
import org.jnode.vm.classmgr.VmConstString;
import org.jnode.vm.classmgr.VmField;
import org.jnode.vm.classmgr.VmType;
import org.jnode.vm.classmgr.VmArray;
import org.jnode.vm.classmgr.VmClassLoader;
import org.jnode.vm.facade.VmUtils;
import org.jnode.vm.scheduler.VmProcessor;
import org.jnode.vm.VmMagic;
import org.jnode.vm.VmReflection;
import org.jnode.annotation.MagicPermission;
import org.jnode.annotation.SharedStatics;

/**
* @author Levente S\u00e1ntha
*/
@MagicPermission
@SharedStatics
class NativeUnsafe {
    static void registerNatives() {
    }

    public static int getInt(Unsafe instance, Object o, long offset) {
        if(o instanceof StaticAccess){
            return ((StaticAccess) o).getInt((int) offset);
        } else {
            return ObjectReference.fromObject(o).toAddress().add((int) offset).loadInt();
        }
    }

    public static void putInt(Unsafe instance, Object o, long offset, int x) {
        if(o instanceof StaticAccess){
            ((StaticAccess) o).setInt(x, (int)offset);
        } else {
            ObjectReference.fromObject(o).toAddress().add((int)offset).store(x);
        }
    }

    /**
     * @see org.jnode.vm.VmReflection#getObject(org.jnode.vm.classmgr.VmField, Object)
     */
    public static Object getObject(Unsafe instance, Object o, long offset) {
        if(o instanceof StaticAccess){
            return ((StaticAccess) o).getObject((int)offset);
        } else {
            return ObjectReference.fromObject(o).toAddress().add((int) offset).loadObjectReference().toObject();
        }
    }

    /**
     * @see org.jnode.vm.VmReflection#setObject(org.jnode.vm.classmgr.VmField, Object, Object)
     */
    public static void putObject(Unsafe instance, Object o, long offset, Object x) {
        if(o instanceof StaticAccess){
            ((StaticAccess) o).setObject(x, (int)offset);
        } else {
            ObjectReference.fromObject(o).toAddress().add((int)offset).store(ObjectReference.fromObject(x));
        }
    }

    public static boolean getBoolean(Unsafe instance, Object o, long offset) {
        if(o instanceof StaticAccess){
            return ((StaticAccess) o).getBoolean((int) offset);
        } else {
            return ObjectReference.fromObject(o).toAddress().add((int) offset).loadByte() != 0;
        }
    }

    public static void putBoolean(Unsafe instance, Object o, long offset, boolean x) {
        if(o instanceof StaticAccess){
            ((StaticAccess) o).setBoolean(x, (int)offset);
        } else {
            ObjectReference.fromObject(o).toAddress().add((int)offset).store((byte)(x ? 1 : 0));
        }
    }

    public static byte getByte(Unsafe instance, Object o, long offset) {
        if(o instanceof StaticAccess){
            return ((StaticAccess) o).getByte((int) offset);
        } else {
            return ObjectReference.fromObject(o).toAddress().add((int) offset).loadByte();
        }
    }

    public static void putByte(Unsafe instance, Object o, long offset, byte x) {
        if(o instanceof StaticAccess){
            ((StaticAccess) o).setByte(x, (int) offset);
        } else {
            ObjectReference.fromObject(o).toAddress().add((int)offset).store(x);
        }
    }

    public static short getShort(Unsafe instance, Object o, long offset) {
        if(o instanceof StaticAccess){
            return ((StaticAccess) o).getShort((int) offset);
        } else {
            return ObjectReference.fromObject(o).toAddress().add((int) offset).loadShort();
        }
    }

    public static void putShort(Unsafe instance, Object o, long offset, short x) {
        if(o instanceof StaticAccess){
            ((StaticAccess) o).setShort(x, (int) offset);
        } else {
            ObjectReference.fromObject(o).toAddress().add((int)offset).store(x);
        }
    }

    public static char getChar(Unsafe instance, Object o, long offset) {
        if(o instanceof StaticAccess){
            return ((StaticAccess) o).getChar((int) offset);
        } else {
            return ObjectReference.fromObject(o).toAddress().add((int) offset).loadChar();
        }
    }

    public static void putChar(Unsafe instance, Object o, long offset, char x) {
        if(o instanceof StaticAccess){
            ((StaticAccess) o).setChar(x, (int) offset);
        } else {
            ObjectReference.fromObject(o).toAddress().add((int)offset).store(x);
        }
    }

    public static long getLong(Unsafe instance, Object o, long offset) {
        if(o instanceof StaticAccess){
            return ((StaticAccess) o).getLong((int) offset);
        } else {
            return ObjectReference.fromObject(o).toAddress().add((int) offset).loadLong();
        }
    }

    public static void putLong(Unsafe instance, Object o, long offset, long x) {
        if(o instanceof StaticAccess){
            ((StaticAccess) o).setLong(x, (int) offset);
        } else {
            ObjectReference.fromObject(o).toAddress().add((int)offset).store(x);
        }
    }

    public static float getFloat(Unsafe instance, Object o, long offset) {
        if(o instanceof StaticAccess){
            return ((StaticAccess) o).getFloat((int) offset);
        } else {
            return ObjectReference.fromObject(o).toAddress().add((int) offset).loadFloat();
        }
    }

    public static void putFloat(Unsafe instance, Object o, long offset, float x) {
        if(o instanceof StaticAccess){
            ((StaticAccess) o).setFloat(x, (int) offset);
        } else {
            ObjectReference.fromObject(o).toAddress().add((int)offset).store(x);
        }
    }

    public static double getDouble(Unsafe instance, Object o, long offset) {
        if(o instanceof StaticAccess){
            return ((StaticAccess) o).getDouble((int) offset);
        } else {
            return ObjectReference.fromObject(o).toAddress().add((int) offset).loadDouble();
        }
    }

    public static void putDouble(Unsafe instance, Object o, long offset, double x) {
        if(o instanceof StaticAccess){
            ((StaticAccess) o).setDouble(x, (int) offset);
        } else {
            ObjectReference.fromObject(o).toAddress().add((int)offset).store(x);
        }
    }

    public static byte getByte(Unsafe instance, long address) {
        throw new UnsupportedOperationException();
    }

    public static void putByte(Unsafe instance, long address, byte x) {
        throw new UnsupportedOperationException();
    }

    public static short getShort(Unsafe instance, long address) {
        throw new UnsupportedOperationException();
    }

    public static void putShort(Unsafe instance, long address, short x) {
        throw new UnsupportedOperationException();
    }

    public static char getChar(Unsafe instance, long address) {
        throw new UnsupportedOperationException();
    }

    public static void putChar(Unsafe instance, long address, char x) {
        throw new UnsupportedOperationException();
    }

    public static int getInt(Unsafe instance, long address) {
        throw new UnsupportedOperationException();
    }

    public static void putInt(Unsafe instance, long address, int x) {
        throw new UnsupportedOperationException();
    }

    public static long getLong(Unsafe instance, long address) {
        throw new UnsupportedOperationException();
    }

    public static void putLong(Unsafe instance, long address, long x) {
        throw new UnsupportedOperationException();
    }

    public static float getFloat(Unsafe instance, long address) {
        throw new UnsupportedOperationException();
    }

    public static void putFloat(Unsafe instance, long address, float x) {
        throw new UnsupportedOperationException();
    }

    public static double getDouble(Unsafe instance, long address) {
        throw new UnsupportedOperationException();
    }

    public static void putDouble(Unsafe instance, long address, double x) {
        throw new UnsupportedOperationException();
    }

    public static long getAddress(Unsafe instance, long address) {
        throw new UnsupportedOperationException();
    }

    public static void putAddress(Unsafe instance, long address, long x) {
        throw new UnsupportedOperationException();
    }

    public static long allocateMemory(Unsafe instance, long bytes) {
        throw new UnsupportedOperationException();
    }

    public static long reallocateMemory(Unsafe instance, long address, long bytes) {
        throw new UnsupportedOperationException();
    }

    public static void setMemory(Unsafe instance, long address, long bytes, byte value) {
        throw new UnsupportedOperationException();
    }

    public static void copyMemory(Unsafe instance, long srcAddress, long destAddress,
                           long bytes) {
        throw new UnsupportedOperationException();
    }

    public static void freeMemory(Unsafe instance, long address) {
        throw new UnsupportedOperationException();
    }
   
    @MagicPermission
    static class StaticAccess {
        protected long  address;

        StaticAccess(long address){
            this.address = address;
        }

        final boolean getBoolean(int offset){
            return Address.fromLong(address).add(offset).loadInt() != 0;
        }

        final void setBoolean(boolean value, int offset){
            Address.fromLong(address).add(offset).store(value ? 1 : 0);
        }

        final byte getByte(int offset) {
            return (byte) Address.fromLong(address).add(offset).loadInt();
        }

        final void setByte(byte value, int offset) {
            Address.fromLong(address).add(offset).store((int) value);
        }

        final short getShort(int offset){
            return (short) Address.fromLong(address).add(offset).loadInt();
        }

        final void setShort(short value, int offset){
            Address.fromLong(address).add(offset).store((int) value);
        }

        final char getChar(int offset){
            return (char) Address.fromLong(address).add(offset).loadInt();
        }

        final void setChar(char value, int offset){
            Address.fromLong(address).add(offset).store((int) value);
        }

        final int getInt(int offset){
            return Address.fromLong(address).add(offset).loadInt();
        }

        final void setInt(int value, int offset){
            Address.fromLong(address).add(offset).store(value);
        }

        final long getLong(int offset){
            return Address.fromLong(address).add(offset).loadLong();
        }

        final void setLong(long value, int offset){
            Address.fromLong(address).add(offset).store(value);
        }

        final float getFloat(int offset){
            return Address.fromLong(address).add(offset).loadFloat();
        }

        final void setFloat(float value, int offset){
            Address.fromLong(address).add(offset).store(value);
        }

        final double getDouble(int offset){
            return Address.fromLong(address).add(offset).loadDouble();
        }

        final void setDouble(double value, int offset){
            Address.fromLong(address).add(offset).store(value);
        }

        Object getObject(int offset){
            return Address.fromLong(address).add(offset).loadObjectReference().toObject();
        }

        void setObject(Object obj, int offset){
            Address.fromLong(address).add(offset).store(ObjectReference.fromObject(obj));
        }
    }

    /**
     * @see org.jnode.vm.VmReflection#getObject(org.jnode.vm.classmgr.VmField, Object)
     */
    static class IrregularStaticAccess  extends StaticAccess {

        IrregularStaticAccess(long address) {
            super(address);
        }

        @Override
        Object getObject(int offset){
            Object obj = super.getObject(offset);
            //handles the reflective access to static final String fields, which didn't work.
            if(obj instanceof VmConstString){
                VmConstString cs = (VmConstString) obj;
                obj = VmUtils.getVm().getSharedStatics().getStringEntry(cs.getSharedStaticsIndex());
            }
            return obj;
        }

        @Override
        void setObject(Object obj, int offset){
            //do nothing - since this is access if for final fields
            throw new UnsupportedOperationException();
        }
    }

    /**
     * @see org.jnode.vm.VmReflection#getStaticFieldAddress(org.jnode.vm.classmgr.VmStaticField)
     */
    public static Object staticFieldBase(Unsafe instance, Field f) {
        final VmProcessor proc = VmProcessor.current();
    final Address tablePtr;
        VmStaticField sf = (VmStaticField) getVmField(f);
        if (sf.isShared()) {
            tablePtr = VmMagic.getArrayData(proc.getSharedStaticsTable());
        } else {
            tablePtr = VmMagic.getArrayData(proc.getIsolatedStaticsTable());
        }
    Object ret = tablePtr.loadObjectReference().toObject();
        if(sf.isStatic() && sf.isFinal() && f.getType().equals(String.class))
            ret = new IrregularStaticAccess(tablePtr.toLong());
        else
            ret = new StaticAccess(tablePtr.toLong());
        return ret;
    }

    /**
     * @see org.jnode.vm.VmReflection#getInstanceFieldAddress(Object, org.jnode.vm.classmgr.VmInstanceField)  
     */
    public static long staticFieldOffset(Unsafe instance, Field f) {
    final int offset;
        VmStaticField sf = (VmStaticField) getVmField(f);
        if (sf.isShared()) {
            offset = sf.getSharedStaticsIndex() << 2;
        } else {
            offset = sf.getIsolatedStaticsIndex() << 2;
        }
    return offset;
    }

    public static long objectFieldOffset(Unsafe instance, Field f) {
        return ((VmInstanceField) getVmField(f)).getOffset();
    }

    private static VmField getVmField(Field f) {
        VmType<?> vmClass = VmType.fromClass((Class<?>) f.getDeclaringClass());
        //vmClass.link();
        return vmClass.getDeclaredField(f.getSlot());
    }

    public static void ensureClassInitialized(Unsafe instance, Class<?> c) {
        VmType.fromClass(c).initialize();
    }

    public static int arrayBaseOffset(Unsafe instance, Class<?> arrayClass) {
        return VmArray.DATA_OFFSET * VmProcessor.current().getArchitecture().getReferenceSize();
    }

    public static int arrayIndexScale(Unsafe instance, Class<?> arrayClass) {
        //see VmHeapManager.newArray()
        final int elemSize;
        VmType<?> arrayCls = VmType.fromClass(arrayClass);
        if (arrayCls.isPrimitiveArray()) {
            switch (arrayCls.getSecondNameChar()) {
                case 'B': // byte
                case 'Z': // boolean
                    elemSize = 1;
                    break;
                case 'C': // char
                case 'S': // short
                    elemSize = 2;
                    break;
                case 'I': // int
                case 'F': // float
                    elemSize = 4;
                    break;
                case 'D': // double
                case 'J': // long
                    elemSize = 8;
                    break;
                default:
                    throw new IllegalArgumentException(arrayCls.getName());
            }
        } else {
            elemSize = VmProcessor.current().getArchitecture().getReferenceSize();
        }
        return elemSize;
    }

    public static int addressSize(Unsafe instance) {
        return VmProcessor.current().getArchitecture().getReferenceSize();
    }

    public static int pageSize(Unsafe instance) {
        throw new UnsupportedOperationException();
    }

    public static Class<?> defineClass(Unsafe instance, String name, byte[] b, int off, int len,
            ClassLoader loader, ProtectionDomain protDomain) {
        if (protDomain == null) {
            protDomain = AccessController
                    .doPrivileged(new PrivilegedAction<ProtectionDomain>() {

                        public ProtectionDomain run() {
                            final CodeSource cs = new CodeSource(null, (Certificate[]) null);
                            return new ProtectionDomain(cs, Policy.getPolicy().getPermissions(cs));
                        }
                    });
        }
        return ((VmClassLoader) loader.getVmClassLoader()).
                defineClass(name, b, off, len, protDomain).asClass();

    }

    public static Class<?> defineClass(Unsafe instance, String name, byte[] b, int off, int len) {
        throw new UnsupportedOperationException();
    }

    public static Object allocateInstance(Unsafe instance, Class<?> cls)
            throws InstantiationException {
        //todo improve exception handling
        try {
            return VmReflection.newInstance(VmType.fromClass(cls).getMethod("<init>", new VmType[]{}));
        } catch (Exception x) {
            throw new InstantiationException("Reason: " + x.getMessage());
        }
    }

    public static void monitorEnter(Unsafe instance, Object o) {
        throw new UnsupportedOperationException();
    }

    public static void monitorExit(Unsafe instance, Object o) {
        throw new UnsupportedOperationException();
    }

    public static boolean tryMonitorEnter(Unsafe instance, Object o) {
        throw new UnsupportedOperationException();
    }

    public static void throwException(Unsafe instance, Throwable ee) throws Throwable{
        //todo review it, when inlined in Unsafe the bytecode would be rejected by a verifier
        throw ee;
    }

    public static boolean compareAndSwapObject(Unsafe instance, Object o, long offset,
                                              Object expected, Object x) {
        //todo make sure it's atomic
        final Address address = ObjectReference.fromObject(o).toAddress().add((int) offset);
        if(address.loadObjectReference().toObject() == expected){
            address.store(ObjectReference.fromObject(x));
            return true;
        } else {
            return false;
        }
    }

    public static boolean compareAndSwapInt(Unsafe instance, Object o, long offset,
                                           int expected, int x) {
        //todo make sure it's atomic
        final Address address = ObjectReference.fromObject(o).toAddress().add((int) offset);
        if(address.loadInt() == expected){
            address.store(x);
            return true;
        } else {
            return false;
        }
    }

    public static final boolean compareAndSwapLong(Unsafe instance, Object o, long offset,
                                            long expected,
                                            long x) {
        //todo make sure it's atomic
        final Address address = ObjectReference.fromObject(o).toAddress().add((int) offset);
        if(address.loadLong() == expected){
            address.store(x);
            return true;
        } else {
            return false;
        }
    }

    public static Object getObjectVolatile(Unsafe instance, Object o, long offset) {
        //todo implement volatile semantics
        return getObject(instance, o,  offset);
    }

    public static void putObjectVolatile(Unsafe instance, Object o, long offset, Object x) {
        //todo implement volatile semantics
        putObject(instance, o, offset, x);
    }

    public static int getIntVolatile(Unsafe instance, Object o, long offset) {
        //todo implement volatile semantics
        return getInt(instance, o, offset);
    }

    public static void putIntVolatile(Unsafe instance, Object o, long offset, int x) {
        //todo implement volatile semantics
        putInt(instance, o, offset, x);
    }

    public static boolean getBooleanVolatile(Unsafe instance, Object o, long offset) {
        //todo ensure volatile semantics
        return getBoolean(instance, o, offset);
    }

    public static void putBooleanVolatile(Unsafe instance, Object o, long offset, boolean x) {
        //todo ensure volatile semantics
        putBoolean(instance, o, offset, x);
    }

    public static byte getByteVolatile(Unsafe instance, Object o, long offset) {
        //todo ensure volatile semantics
        return getByte(instance, o, offset);
    }

    public static void putByteVolatile(Unsafe instance, Object o, long offset, byte x) {
        //todo ensure volatile semantics
        putByte(instance, o, offset, x);
    }

    public static short getShortVolatile(Unsafe instance, Object o, long offset) {
        //todo ensure volatile semantics
        return getShort(instance, o, offset);
    }

    public static void putShortVolatile(Unsafe instance, Object o, long offset, short x) {
        //todo ensure volatile semantics
        putShort(instance, o, offset, x);
    }

    public static char getCharVolatile(Unsafe instance, Object o, long offset) {
        //todo ensure volatile semantics
        return getChar(instance, o, offset);
    }

    public static void putCharVolatile(Unsafe instance, Object o, long offset, char x) {
        //todo ensure volatile semantics
        putChar(instance, o, offset, x);
    }

    public static long getLongVolatile(Unsafe instance, Object o, long offset) {
        //todo ensure volatile semantics
        return getLong(instance, o, offset);
    }

    public static void putLongVolatile(Unsafe instance, Object o, long offset, long x) {
        //todo ensure volatile semantics
        putLong(instance, o, offset, x);
    }

    public static float getFloatVolatile(Unsafe instance, Object o, long offset) {
        //todo ensure volatile semantics
        return getFloat(instance, o, offset);
    }

    public static void putFloatVolatile(Unsafe instance, Object o, long offset, float x) {
        //todo ensure volatile semantics
        putFloat(instance, o, offset, x);
    }

    public static double getDoubleVolatile(Unsafe instance, Object o, long offset) {
        //todo ensure volatile semantics
        return getDouble(instance, o, offset);
    }

    public static void putDoubleVolatile(Unsafe instance, Object o, long offset, double x) {
        //todo ensure volatile semantics
        putDouble(instance, o, offset, x);
    }

    public static void putOrderedObject(Unsafe instance, Object o, long offset, Object x) {
        //todo ensure ordered semantics
        putObject(instance, o, offset, x);
    }

    public static void putOrderedInt(Unsafe instance, Object o, long offset, int x) {
        //todo ensure ordered semantics
        putInt(instance, o, offset, x);
    }

    public static void putOrderedLong(Unsafe instance, Object o, long offset, long x) {
        //todo ensure ordered semantics
        putLong(instance, o, offset, x);
    }

    static final Map<Object, ThreadParker> parking = new HashMap<Object, ThreadParker>();
    @SharedStatics
    private static class ThreadParker {
        private synchronized void park(long time){
            try {
                wait(time);
            }catch (InterruptedException x){
                //ignore
            }
        }

        private synchronized void unpark() {
            notifyAll();
        }
    }
    /**
     * @see Unsafe#unpark(Object)
     */
    public static void unpark(Unsafe instance, Object thread) {
        synchronized (parking){
            ThreadParker p =parking.get(thread);
            if(p != null){
                p.unpark();
            } else {
                parking.put(thread, new ThreadParker());
            }
        }
    }

    /**
     * @see Unsafe#park(boolean, long)
     */
    public static void park(Unsafe instance, boolean isAbsolute, long time) {
        //todo add proper support for nanotime parking
        ThreadParker p;
        synchronized (parking){
            Thread thread = Thread.currentThread();
            p = parking.get(thread);
            if(p == null){
                if(isAbsolute){
                    time = time - System.currentTimeMillis();
                    if(time < 0) time = 1;
                } else if(time > 0) {
                    time = time / 10000000;
                    if(time == 0)
                        time = 1;
                } else if (time < 0){
                    time = 1;
                }
                p = new ThreadParker();
                parking.put(thread, p);
            } else {               
                p = null;
            }
        }

        if(p != null){
            p.park(time);
            synchronized (parking){
                parking.remove(Thread.currentThread());
            }
        }
    }

    public static int getLoadAverage(Unsafe instance, double[] loadavg, int nelems) {
        throw new UnsupportedOperationException();
    }
}
TOP

Related Classes of sun.misc.NativeUnsafe

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.