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      * The <em>unchecked</em> memory address instance modelling the {@code NULL} address. This address is <em>not</em> backed by
120      * a memory segment and hence it cannot be dereferenced.
121      */
122     MemoryAddress NULL = new MemoryAddressImpl( 0L);
123 
124     /**
125      * Obtain a new <em>unchecked</em> memory address instance from given long address. The returned address is <em>not</em> backed by
126      * a memory segment and hence it cannot be dereferenced.
127      * @param value the long address.
128      * @return the new memory address instance.
129      */
130     static MemoryAddress ofLong(long value) {
131         return value == 0 ?
132                 NULL :
133                 new MemoryAddressImpl(value);
134     }
135 
136 }