/*
 * Copyright (c) 2011, 2016, 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.
 *
 * 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.vm.ci.hotspot;

import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;

import java.lang.reflect.Array;

import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MemoryAccessProvider;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.PrimitiveConstant;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaType;

/**
 * HotSpot implementation of {@link MemoryAccessProvider}.
 */
class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {

    protected final HotSpotJVMCIRuntimeProvider runtime;

    HotSpotMemoryAccessProviderImpl(HotSpotJVMCIRuntimeProvider runtime) {
        this.runtime = runtime;
    }

    /**
     * Gets the object boxed by {@code base} that is about to have a value of kind {@code kind} read
     * from it at the offset {@code displacement}.
     *
     * @param base constant value containing the base address for a pending read
     * @return {@code null} if {@code base} does not box an object otherwise the object boxed in
     *         {@code base}
     */
    private Object asObject(Constant base, JavaKind kind, long displacement) {
        if (base instanceof HotSpotObjectConstantImpl) {
            HotSpotObjectConstantImpl constant = (HotSpotObjectConstantImpl) base;
            HotSpotResolvedObjectType type = constant.getType();
            Object object = constant.object();
            checkRead(kind, displacement, type, object);
            return object;
        }
        return null;
    }

    /**
     * Offset of injected {@code java.lang.Class::oop_size} field. No need to make {@code volatile}
     * as initialization is idempotent.
     */
    private long oopSizeOffset;

    private static int computeOopSizeOffset(HotSpotJVMCIRuntimeProvider runtime) {
        MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
        ResolvedJavaType staticType = metaAccess.lookupJavaType(Class.class);
        for (ResolvedJavaField f : staticType.getInstanceFields(false)) {
            if (f.getName().equals("oop_size")) {
                int offset = ((HotSpotResolvedJavaField) f).offset();
                assert offset != 0 : "not expecting offset of java.lang.Class::oop_size to be 0";
                return offset;
            }
        }
        throw new JVMCIError("Could not find injected java.lang.Class::oop_size field");
    }

    private boolean checkRead(JavaKind kind, long displacement, HotSpotResolvedObjectType type, Object object) {
        if (type.isArray()) {
            ResolvedJavaType componentType = type.getComponentType();
            JavaKind componentKind = componentType.getJavaKind();
            final int headerSize = getArrayBaseOffset(componentKind);
            int sizeOfElement = getArrayIndexScale(componentKind);
            int length = Array.getLength(object);
            long arrayEnd = headerSize + (sizeOfElement * length);
            boolean aligned = ((displacement - headerSize) % sizeOfElement) == 0;
            if (displacement < 0 || displacement > (arrayEnd - sizeOfElement) || (kind == JavaKind.Object && !aligned)) {
                int index = (int) ((displacement - headerSize) / sizeOfElement);
                throw new IllegalArgumentException("Unsafe array access: reading element of kind " + kind +
                                " at offset " + displacement + " (index ~ " + index + ") in " +
                                type.toJavaName() + " object of length " + length);
            }
        } else if (kind != JavaKind.Object) {
            long size;
            if (object instanceof Class) {
                if (oopSizeOffset == 0) {
                    oopSizeOffset = computeOopSizeOffset(runtime);
                }
                int wordSize = runtime.getHostJVMCIBackend().getCodeCache().getTarget().wordSize;
                size = UNSAFE.getInt(object, oopSizeOffset) * wordSize;
            } else {
                size = Math.abs(type.instanceSize());
            }
            int bytesToRead = kind.getByteCount();
            if (displacement + bytesToRead > size || displacement < 0) {
                throw new IllegalArgumentException("Unsafe access: reading " + bytesToRead + " bytes at offset " + displacement + " in " +
                                type.toJavaName() + " object of size " + size);
            }
        } else {
            ResolvedJavaField field = type.findInstanceFieldWithOffset(displacement, JavaKind.Object);
            if (field == null && object instanceof Class) {
                // Read of a static field
                MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
                HotSpotResolvedObjectTypeImpl staticFieldsHolder = (HotSpotResolvedObjectTypeImpl) metaAccess.lookupJavaType((Class<?>) object);
                field = staticFieldsHolder.findStaticFieldWithOffset(displacement, JavaKind.Object);
            }
            if (field == null) {
                throw new IllegalArgumentException("Unsafe object access: field not found for read of kind Object" +
                                " at offset " + displacement + " in " + type.toJavaName() + " object");
            }
            if (field.getJavaKind() != JavaKind.Object) {
                throw new IllegalArgumentException("Unsafe object access: field " + field.format("%H.%n:%T") + " not of expected kind Object" +
                                " at offset " + displacement + " in " + type.toJavaName() + " object");
            }
        }
        return true;
    }

    private boolean isValidObjectFieldDisplacement(Constant base, long displacement) {
        if (base instanceof HotSpotMetaspaceConstant) {
            MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
            if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
                if (displacement == runtime.getConfig().classMirrorOffset) {
                    // Klass::_java_mirror is valid for all Klass* values
                    return true;
                }
            } else {
                throw new IllegalArgumentException(String.valueOf(metaspaceObject));
            }
        }
        return false;
    }

    private static long asRawPointer(Constant base) {
        if (base instanceof HotSpotMetaspaceConstantImpl) {
            MetaspaceWrapperObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
            return meta.getMetaspacePointer();
        } else if (base instanceof PrimitiveConstant) {
            PrimitiveConstant prim = (PrimitiveConstant) base;
            if (prim.getJavaKind().isNumericInteger()) {
                return prim.asLong();
            }
        }
        throw new IllegalArgumentException(String.valueOf(base));
    }

    private long readRawValue(Constant baseConstant, long displacement, JavaKind kind, int bits) {
        Object base = asObject(baseConstant, kind, displacement);
        if (base != null) {
            switch (bits) {
                case Byte.SIZE:
                    return UNSAFE.getByte(base, displacement);
                case Short.SIZE:
                    return UNSAFE.getShort(base, displacement);
                case Integer.SIZE:
                    return UNSAFE.getInt(base, displacement);
                case Long.SIZE:
                    return UNSAFE.getLong(base, displacement);
                default:
                    throw new IllegalArgumentException(String.valueOf(bits));
            }
        } else {
            long pointer = asRawPointer(baseConstant);
            switch (bits) {
                case Byte.SIZE:
                    return UNSAFE.getByte(pointer + displacement);
                case Short.SIZE:
                    return UNSAFE.getShort(pointer + displacement);
                case Integer.SIZE:
                    return UNSAFE.getInt(pointer + displacement);
                case Long.SIZE:
                    return UNSAFE.getLong(pointer + displacement);
                default:
                    throw new IllegalArgumentException(String.valueOf(bits));
            }
        }
    }

    private boolean verifyReadRawObject(Object expected, Constant base, long displacement) {
        if (base instanceof HotSpotMetaspaceConstant) {
            MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
            if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
                if (displacement == runtime.getConfig().classMirrorOffset) {
                    assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror();
                }
            }
        }
        return true;
    }

    private Object readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
        long displacement = initialDisplacement;
        Object ret;
        Object base = asObject(baseConstant, JavaKind.Object, displacement);
        if (base == null) {
            assert !compressed;
            displacement += asRawPointer(baseConstant);
            ret = UNSAFE.getUncompressedObject(displacement);
            assert verifyReadRawObject(ret, baseConstant, initialDisplacement);
        } else {
            assert runtime.getConfig().useCompressedOops == compressed;
            ret = UNSAFE.getObject(base, displacement);
        }
        return ret;
    }

    JavaConstant readFieldValue(HotSpotResolvedJavaField field, Object obj) {
        assert obj != null;
        assert !field.isStatic() || obj instanceof Class;
        long displacement = field.offset();
        assert checkRead(field.getJavaKind(), displacement, (HotSpotResolvedObjectType) runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(obj.getClass()), obj);
        if (field.getJavaKind() == JavaKind.Object) {
            Object o = UNSAFE.getObject(obj, displacement);
            return HotSpotObjectConstantImpl.forObject(o);
        } else {
            JavaKind kind = field.getJavaKind();
            switch (kind) {
                case Boolean:
                    return JavaConstant.forBoolean(UNSAFE.getBoolean(obj, displacement));
                case Byte:
                    return JavaConstant.forByte(UNSAFE.getByte(obj, displacement));
                case Char:
                    return JavaConstant.forChar(UNSAFE.getChar(obj, displacement));
                case Short:
                    return JavaConstant.forShort(UNSAFE.getShort(obj, displacement));
                case Int:
                    return JavaConstant.forInt(UNSAFE.getInt(obj, displacement));
                case Long:
                    return JavaConstant.forLong(UNSAFE.getLong(obj, displacement));
                case Float:
                    return JavaConstant.forFloat(UNSAFE.getFloat(obj, displacement));
                case Double:
                    return JavaConstant.forDouble(UNSAFE.getDouble(obj, displacement));
                default:
                    throw new IllegalArgumentException("Unsupported kind: " + kind);
            }
        }
    }

    @Override
    public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) {
        try {
            long rawValue = readRawValue(baseConstant, initialDisplacement, kind, bits);
            switch (kind) {
                case Boolean:
                    return JavaConstant.forBoolean(rawValue != 0);
                case Byte:
                    return JavaConstant.forByte((byte) rawValue);
                case Char:
                    return JavaConstant.forChar((char) rawValue);
                case Short:
                    return JavaConstant.forShort((short) rawValue);
                case Int:
                    return JavaConstant.forInt((int) rawValue);
                case Long:
                    return JavaConstant.forLong(rawValue);
                case Float:
                    return JavaConstant.forFloat(Float.intBitsToFloat((int) rawValue));
                case Double:
                    return JavaConstant.forDouble(Double.longBitsToDouble(rawValue));
                default:
                    throw new IllegalArgumentException("Unsupported kind: " + kind);
            }
        } catch (NullPointerException e) {
            return null;
        }
    }

    @Override
    public JavaConstant readObjectConstant(Constant base, long displacement) {
        if (base instanceof HotSpotObjectConstantImpl) {
            Object o = readRawObject(base, displacement, runtime.getConfig().useCompressedOops);
            return HotSpotObjectConstantImpl.forObject(o);
        }
        if (!isValidObjectFieldDisplacement(base, displacement)) {
            return null;
        }
        return HotSpotObjectConstantImpl.forObject(readRawObject(base, displacement, false));
    }

    @Override
    public JavaConstant readNarrowOopConstant(Constant base, long displacement) {
        return HotSpotObjectConstantImpl.forObject(readRawObject(base, displacement, true), true);
    }

    private HotSpotResolvedObjectTypeImpl readKlass(Constant base, long displacement, boolean compressed) {
        assert (base instanceof HotSpotMetaspaceConstantImpl) || (base instanceof HotSpotObjectConstantImpl) : base.getClass();
        Object baseObject = (base instanceof HotSpotMetaspaceConstantImpl) ? ((HotSpotMetaspaceConstantImpl) base).asResolvedJavaType() : ((HotSpotObjectConstantImpl) base).object();
        return runtime.getCompilerToVM().getResolvedJavaType(baseObject, displacement, compressed);
    }

    @Override
    public Constant readKlassPointerConstant(Constant base, long displacement) {
        HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, false);
        if (klass == null) {
            return JavaConstant.NULL_POINTER;
        }
        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(klass, false);
    }

    @Override
    public Constant readNarrowKlassPointerConstant(Constant base, long displacement) {
        HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, true);
        if (klass == null) {
            return HotSpotCompressedNullConstant.COMPRESSED_NULL;
        }
        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(klass, true);
    }

    @Override
    public Constant readMethodPointerConstant(Constant base, long displacement) {
        assert (base instanceof HotSpotObjectConstantImpl);
        Object baseObject = ((HotSpotObjectConstantImpl) base).object();
        HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod(baseObject, displacement);
        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(method, false);
    }
}
