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 }