/* * Copyright (c) 2016, Oracle and/or its affiliates. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials provided * with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.oracle.truffle.llvm.runtime.memory; import java.lang.reflect.Field; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.llvm.runtime.LLVMAddress; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.vector.LLVMDoubleVector; import com.oracle.truffle.llvm.runtime.vector.LLVMFloatVector; import com.oracle.truffle.llvm.runtime.vector.LLVMI16Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI1Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI32Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI64Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI8Vector; import sun.misc.Unsafe; public abstract class LLVMMemory { static final Unsafe UNSAFE = getUnsafe(); @SuppressWarnings("restriction") private static Unsafe getUnsafe() { CompilerAsserts.neverPartOfCompilation(); try { Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe"); singleoneInstanceField.setAccessible(true); return (Unsafe) singleoneInstanceField.get(null); } catch (Exception e) { throw new AssertionError(); } } /** Use {@link com.oracle.truffle.llvm.runtime.memory.LLVMProfiledMemSet} instead. */ @Deprecated public static void memset(LLVMAddress address, long size, byte value) { UNSAFE.setMemory(address.getVal(), size, value); } public static void memset(long address, long size, byte value) { UNSAFE.setMemory(address, size, value); } public static void free(LLVMAddress address) { UNSAFE.freeMemory(address.getVal()); } public static LLVMAddress allocateMemory(long size) { return LLVMAddress.fromLong(UNSAFE.allocateMemory(size)); } public static LLVMAddress reallocateMemory(LLVMAddress addr, long size) { // a null pointer is a valid argument return LLVMAddress.fromLong(UNSAFE.reallocateMemory(addr.getVal(), size)); } public static boolean getI1(LLVMAddress addr) { return getI1(addr.getVal()); } public static boolean getI1(long ptr) { assert ptr != 0; return UNSAFE.getByte(ptr) != 0; } public static byte getI8(LLVMAddress addr) { return getI8(addr.getVal()); } public static byte getI8(long ptr) { assert ptr != 0; return UNSAFE.getByte(ptr); } public static short getI16(LLVMAddress addr) { return getI16(addr.getVal()); } public static short getI16(long ptr) { assert ptr != 0; return UNSAFE.getShort(ptr); } public static int getI32(LLVMAddress addr) { return getI32(addr.getVal()); } public static int getI32(long ptr) { assert ptr != 0; return UNSAFE.getInt(ptr); } public static LLVMIVarBit getIVarBit(LLVMAddress addr, int bitWidth) { if (bitWidth % Byte.SIZE != 0) { CompilerDirectives.transferToInterpreter(); throw new AssertionError(); } int bytes = bitWidth / Byte.SIZE; byte[] loadedBytes = new byte[bytes]; long currentAddressPtr = addr.getVal(); for (int i = loadedBytes.length - 1; i >= 0; i--) { loadedBytes[i] = getI8(currentAddressPtr); currentAddressPtr += Byte.BYTES; } return LLVMIVarBit.create(bitWidth, loadedBytes); } public static long getI64(LLVMAddress addr) { return getI64(addr.getVal()); } public static long getI64(long ptr) { assert ptr != 0; return UNSAFE.getLong(ptr); } public static float getFloat(LLVMAddress addr) { return getFloat(addr.getVal()); } public static float getFloat(long ptr) { assert ptr != 0; return UNSAFE.getFloat(ptr); } public static double getDouble(LLVMAddress addr) { return getDouble(addr.getVal()); } public static double getDouble(long ptr) { assert ptr != 0; return UNSAFE.getDouble(ptr); } public static LLVM80BitFloat get80BitFloat(LLVMAddress addr) { byte[] bytes = new byte[LLVM80BitFloat.BYTE_WIDTH]; long currentPtr = addr.getVal(); for (int i = 0; i < bytes.length; i++) { bytes[i] = getI8(currentPtr); currentPtr += Byte.BYTES; } return LLVM80BitFloat.fromBytes(bytes); } static long extractAddr(LLVMAddress addr) { assert addr.getVal() != 0; return addr.getVal(); } public static LLVMAddress getAddress(LLVMAddress addr) { return getAddress(addr.getVal()); } public static LLVMAddress getAddress(long ptr) { assert ptr != 0; return LLVMAddress.fromLong(UNSAFE.getAddress(ptr)); } public static void putI1(LLVMAddress addr, boolean value) { putI1(addr.getVal(), value); } public static void putI1(long ptr, boolean value) { assert ptr != 0; UNSAFE.putByte(ptr, (byte) (value ? 1 : 0)); } public static void putI8(LLVMAddress addr, byte value) { putI8(addr.getVal(), value); } public static void putI8(long ptr, byte value) { assert ptr != 0; UNSAFE.putByte(ptr, value); } public static void putI16(LLVMAddress addr, short value) { putI16(addr.getVal(), value); } public static void putI16(long ptr, short value) { assert ptr != 0; UNSAFE.putShort(ptr, value); } public static void putI32(LLVMAddress addr, int value) { putI32(addr.getVal(), value); } public static void putI32(long ptr, int value) { assert ptr != 0; UNSAFE.putInt(ptr, value); } public static void putI64(LLVMAddress addr, long value) { putI64(addr.getVal(), value); } public static void putI64(long ptr, long value) { assert ptr != 0; UNSAFE.putLong(ptr, value); } public static void putIVarBit(LLVMAddress addr, LLVMIVarBit value) { byte[] bytes = value.getBytes(); long currentptr = addr.getVal(); for (int i = bytes.length - 1; i >= 0; i--) { putI8(currentptr, bytes[i]); currentptr += Byte.BYTES; } } private static void putByteArray(LLVMAddress addr, byte[] bytes) { putByteArray(addr.getVal(), bytes); } private static void putByteArray(long ptr, byte[] bytes) { long currentptr = ptr; for (int i = 0; i < bytes.length; i++) { putI8(currentptr, bytes[i]); currentptr += Byte.BYTES; } } public static void putFloat(LLVMAddress addr, float value) { putFloat(addr.getVal(), value); } public static void putFloat(long ptr, float value) { assert ptr != 0; UNSAFE.putFloat(ptr, value); } public static void putDouble(LLVMAddress addr, double value) { putDouble(addr.getVal(), value); } public static void putDouble(long ptr, double value) { assert ptr != 0; UNSAFE.putDouble(ptr, value); } public static void put80BitFloat(LLVMAddress addr, LLVM80BitFloat value) { putByteArray(addr, value.getBytes()); } public static void put80BitFloat(long ptr, LLVM80BitFloat value) { putByteArray(ptr, value.getBytes()); } public static void putAddress(LLVMAddress addr, LLVMAddress value) { putAddress(addr.getVal(), value); } public static void putAddress(LLVMAddress addr, long ptrValue) { putAddress(addr.getVal(), ptrValue); } public static void putAddress(long ptr, LLVMAddress value) { putAddress(ptr, value.getVal()); } public static void putAddress(long ptr, long ptrValue) { assert ptr != 0; UNSAFE.putAddress(ptr, ptrValue); } public static LLVMI32Vector getI32Vector(LLVMAddress addr, int size) { return LLVMI32Vector.readVectorFromMemory(addr, size); } public static LLVMI8Vector getI8Vector(LLVMAddress addr, int size) { return LLVMI8Vector.readVectorFromMemory(addr, size); } public static LLVMI1Vector getI1Vector(LLVMAddress addr, int size) { return LLVMI1Vector.readVectorFromMemory(addr, size); } public static LLVMI16Vector getI16Vector(LLVMAddress addr, int size) { return LLVMI16Vector.readVectorFromMemory(addr, size); } public static LLVMI64Vector getI64Vector(LLVMAddress addr, int size) { return LLVMI64Vector.readVectorFromMemory(addr, size); } public static LLVMFloatVector getFloatVector(LLVMAddress addr, int size) { return LLVMFloatVector.readVectorFromMemory(addr, size); } public static LLVMDoubleVector getDoubleVector(LLVMAddress addr, int size) { return LLVMDoubleVector.readVectorFromMemory(addr, size); } // watch out for casts such as I32* to I32Vector* when changing the way how vectors are // implemented public static void putVector(LLVMAddress addr, LLVMDoubleVector vector) { LLVMDoubleVector.writeVectorToMemory(addr, vector); } public static void putVector(LLVMAddress addr, LLVMFloatVector vector) { LLVMFloatVector.writeVectorToMemory(addr, vector); } public static void putVector(LLVMAddress addr, LLVMI16Vector vector) { LLVMI16Vector.writeVectorToMemory(addr, vector); } public static void putVector(LLVMAddress addr, LLVMI1Vector vector) { LLVMI1Vector.writeVectorToMemory(addr, vector); } public static void putVector(LLVMAddress addr, LLVMI32Vector vector) { LLVMI32Vector.writeVectorToMemory(addr, vector); } public static void putVector(LLVMAddress addr, LLVMI64Vector vector) { LLVMI64Vector.writeVectorToMemory(addr, vector); } public static void putVector(LLVMAddress addr, LLVMI8Vector vector) { LLVMI8Vector.writeVectorToMemory(addr, vector); } }