1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 * 25 */ 26 27 package jdk.incubator.foreign; 28 29 import jdk.internal.foreign.MemoryAddressImpl; 30 31 /** 32 * A memory address models a reference into a memory location. Memory addresses are typically obtained using the 33 * {@link MemorySegment#baseAddress()} method; such addresses are said to be <em>checked</em>, and can be expressed 34 * as <em>offsets</em> into some underlying memory segment (see {@link #segment()} and {@link #segmentOffset()}). 35 * Since checked memory addresses feature both spatial and temporal bounds, these addresses can <em>safely</em> be 36 * dereferenced using a memory access var handle (see {@link MemoryHandles}). 37 * <p> 38 * If an address does not have any associated segment, it is said to be <em>unchecked</em>. Unchecked memory 39 * addresses do not feature known spatial or temporal bounds; as such, attempting a memory dereference operation 40 * using an unchecked memory address will result in a runtime exception. Unchecked addresses can be obtained 41 * e.g. by calling the {@link #ofLong(long)} method. 42 * <p> 43 * All implementations of this interface must be <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>; 44 * use of identity-sensitive operations (including reference equality ({@code ==}), identity hash code, or synchronization) on 45 * instances of {@code MemoryAddress} may have unpredictable results and should be avoided. The {@code equals} method should 46 * be used for comparisons. 47 * <p> 48 * Non-platform classes should not implement {@linkplain MemoryAddress} directly. 49 * 50 * @apiNote In the future, if the Java language permits, {@link MemoryAddress} 51 * may become a {@code sealed} interface, which would prohibit subclassing except by 52 * explicitly permitted types. 53 * 54 * @implSpec 55 * Implementations of this interface are immutable and thread-safe. 56 */ 57 public interface MemoryAddress { 58 /** 59 * Creates a new memory address with given offset (in bytes), which might be negative, from current one. 60 * @param offset specified offset (in bytes), relative to this address, which should be used to create the new address. 61 * @return a new memory address with given offset from current one. 62 */ 63 MemoryAddress addOffset(long offset); 64 65 /** 66 * Returns the offset of this memory address into the underlying segment (if any). 67 * @return the offset of this memory address into the underlying segment (if any). 68 * @throws UnsupportedOperationException if no segment is associated with this memory address, 69 * e.g. if {@code segment() == null}. 70 */ 71 long segmentOffset(); 72 73 /** 74 * Returns the raw long value associated to this memory address. 75 * @return The raw long value associated to this memory address. 76 * @throws UnsupportedOperationException if this memory address is associated with an heap segment. 77 */ 78 long toRawLongValue(); 79 80 /** 81 * Returns the memory segment (if any) this address belongs to. 82 * @return The memory segment this address belongs to, or {@code null} if no such segment exists. 83 */ 84 MemorySegment segment(); 85 86 /** 87 * Reinterpret this address as an offset into the provided segment. 88 * @param segment the segment to be rebased 89 * @return a new address pointing to the same memory location through the provided segment 90 * @throws IllegalArgumentException if the provided segment is not a valid rebase target for this address. This 91 * can happen, for instance, if an heap-based addressed is rebased to an off-heap memory segment. 92 */ 93 MemoryAddress rebase(MemorySegment segment); 94 95 /** 96 * Compares the specified object with this address for equality. Returns {@code true} if and only if the specified 97 * object is also an address, and it refers to the same memory location as this address. 98 * 99 * @apiNote two addresses might be considered equal despite their associated segments differ. This 100 * can happen, for instance, if the segment associated with one address is a <em>slice</em> 101 * (see {@link MemorySegment#asSlice(long, long)}) of the segment associated with the other address. Moreover, 102 * two addresses might be considered equals despite differences in the temporal bounds associated with their 103 * corresponding segments. 104 * 105 * @param that the object to be compared for equality with this address. 106 * @return {@code true} if the specified object is equal to this address. 107 */ 108 @Override 109 boolean equals(Object that); 110 111 /** 112 * Returns the hash code value for this address. 113 * @return the hash code value for this address. 114 */ 115 @Override 116 int hashCode(); 117 118 /** 119 * Perform bulk copy from source address to target address. More specifically, the bytes at addresses {@code src} 120 * through {@code src.addOffset(bytes - 1)} are copied into addresses {@code dst} through {@code dst.addOffset(bytes - 1)}. 121 * If the source and address ranges overlap, then the copying is performed as if the bytes at addresses {@code src} 122 * through {@code src.addOffset(bytes - 1)} were first copied into a temporary segment with size {@code bytes}, 123 * and then the contents of the temporary segment were copied into the bytes at addresses {@code dst} through 124 * {@code dst.addOffset(bytes - 1)}. 125 * <p> 126 * The result of a bulk copy is unspecified if, in the uncommon case, the source and target address ranges do not 127 * overlap, but refer to overlapping regions of the same backing storage using different addresses. For example, 128 * this may occur if the same file is {@link MemorySegment#mapFromPath mapped} to two segments. 129 * 130 * @param src the source address. 131 * @param dst the target address. 132 * @param bytes the number of bytes to be copied. 133 * @throws IndexOutOfBoundsException if {@code bytes < 0}, or if it is greater than the size of the segments 134 * associated with either {@code src} or {@code dst}. 135 * @throws IllegalStateException if either the source address or the target address belong to memory segments 136 * which have been already closed, or if access occurs from a thread other than the thread owning either segment. 137 * @throws UnsupportedOperationException if either {@code src} or {@code dst} do not feature required access modes; 138 * more specifically, {@code src} should be associated with a segment with {@link MemorySegment#READ} access mode, 139 * while {@code dst} should be associated with a segment with {@link MemorySegment#WRITE} access mode. 140 */ 141 static void copy(MemoryAddress src, MemoryAddress dst, long bytes) { 142 MemoryAddressImpl.copy((MemoryAddressImpl)src, (MemoryAddressImpl)dst, bytes); 143 } 144 145 /** 146 * The <em>unchecked</em> memory address instance modelling the {@code NULL} address. This address is <em>not</em> backed by 147 * a memory segment and hence it cannot be dereferenced. 148 */ 149 MemoryAddress NULL = new MemoryAddressImpl( 0L); 150 151 /** 152 * Obtain a new <em>unchecked</em> memory address instance from given long address. The returned address is <em>not</em> backed by 153 * a memory segment and hence it cannot be dereferenced. 154 * @param value the long address. 155 * @return the new memory address instance. 156 */ 157 static MemoryAddress ofLong(long value) { 158 return value == 0 ? 159 NULL : 160 new MemoryAddressImpl(value); 161 } 162 163 }