/* * 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.nodes.intrinsics.interop; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.CanResolve; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.MessageResolution; import com.oracle.truffle.api.interop.Resolve; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; @NodeChild(type = LLVMExpressionNode.class) public abstract class LLVMTruffleManagedMalloc extends LLVMIntrinsic { @MessageResolution(receiverType = ManagedMallocObject.class) public static class ManagedMallocForeignAccess { @CanResolve public abstract static class Check extends Node { protected static boolean test(TruffleObject receiver) { return receiver instanceof ManagedMallocObject; } } @Resolve(message = "HAS_SIZE") public abstract static class ForeignHasSizeNode extends Node { protected Object access(@SuppressWarnings("unused") ManagedMallocObject malloc) { return true; } } @Resolve(message = "GET_SIZE") public abstract static class ForeignGetSizeNode extends Node { protected Object access(ManagedMallocObject malloc) { return malloc.getSize(); } } @Resolve(message = "READ") public abstract static class ForeignReadNode extends Node { protected Object access(ManagedMallocObject malloc, int index) { return malloc.get(index); } } @Resolve(message = "WRITE") public abstract static class ForeignWriteNode extends Node { protected Object access(ManagedMallocObject malloc, int index, Object value) { malloc.set(index, value); return value; } } } public static class ManagedMallocObject implements TruffleObject { private final Object[] contents; public ManagedMallocObject(int entries) { contents = new Object[entries]; } public Object get(int index) { return contents[index]; } public void set(int index, Object value) { contents[index] = value; } public int getSize() { return contents.length; } @Override public ForeignAccess getForeignAccess() { return ManagedMallocForeignAccessForeign.ACCESS; } } @Specialization public Object executeIntrinsic(long size) { if (size < 0) { CompilerDirectives.transferToInterpreter(); throw new IllegalArgumentException("Can't truffle_managed_malloc less than zero bytes"); } long roundedSize = size + ((LLVMExpressionNode.ADDRESS_SIZE_IN_BYTES - size) % LLVMExpressionNode.ADDRESS_SIZE_IN_BYTES); if (roundedSize / LLVMExpressionNode.ADDRESS_SIZE_IN_BYTES > Integer.MAX_VALUE) { CompilerDirectives.transferToInterpreter(); throw new IllegalArgumentException("Can't truffle_managed_malloc for more than 2^31 objects"); } return new ManagedMallocObject((int) (roundedSize)); } }