< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java

Print this page

  1 /*
  2  * Copyright (c) 2020, 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 package jdk.internal.foreign;
 27 
 28 import jdk.incubator.foreign.*;
 29 import jdk.internal.access.JavaNioAccess;
 30 import jdk.internal.access.SharedSecrets;
 31 import jdk.internal.access.foreign.MemorySegmentProxy;
 32 import jdk.internal.access.foreign.UnmapperProxy;
 33 import jdk.internal.misc.ScopedMemoryAccess;
 34 import jdk.internal.util.ArraysSupport;
 35 import jdk.internal.vm.annotation.ForceInline;
 36 import sun.security.action.GetPropertyAction;
 37 
 38 import java.nio.ByteBuffer;

 39 import java.util.*;
 40 import java.util.function.Consumer;
 41 import java.util.function.Function;
 42 import java.util.function.IntFunction;
 43 import java.util.stream.Stream;
 44 import java.util.stream.StreamSupport;
 45 


 46 /**
 47  * This abstract class provides an immutable implementation for the {@code MemorySegment} interface. This class contains information
 48  * about the segment's spatial and temporal bounds; each memory segment implementation is associated with an owner thread which is set at creation time.
 49  * Access to certain sensitive operations on the memory segment will fail with {@code IllegalStateException} if the
 50  * segment is either in an invalid state (e.g. it has already been closed) or if access occurs from a thread other
 51  * than the owner thread. See {@link ResourceScopeImpl} for more details on management of temporal bounds. Subclasses
 52  * are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and
 53  * {@link MappedMemorySegmentImpl}.
 54  */
 55 public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegmentProxy implements MemorySegment {
 56 
 57     private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
 58 
 59     private static final boolean enableSmallSegments =
 60             Boolean.parseBoolean(GetPropertyAction.privilegedGetProperty("jdk.incubator.foreign.SmallSegments", "true"));
 61 
 62     static final int READ_ONLY = 1;
 63     static final int SMALL = READ_ONLY << 1;
 64     static final long NONCE = new Random().nextLong();
 65 
 66     static final JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess();
 67 
 68     final long length;
 69     final int mask;
 70     final ResourceScopeImpl scope;
 71 
 72     @ForceInline
 73     AbstractMemorySegmentImpl(long length, int mask, ResourceScopeImpl scope) {
 74         this.length = length;
 75         this.mask = mask;

123         }
124         if (byteSize() % elementLayout.byteSize() != 0) {
125             throw new IllegalArgumentException("Segment size is no a multiple of layout size");
126         }
127         return new SegmentSplitter(elementLayout.byteSize(), byteSize() / elementLayout.byteSize(),
128                 this);
129     }
130 
131     @Override
132     public Stream<MemorySegment> elements(MemoryLayout elementLayout) {
133         return StreamSupport.stream(spliterator(elementLayout), false);
134     }
135 
136     @Override
137     public final MemorySegment fill(byte value){
138         checkAccess(0, length, false);
139         SCOPED_MEMORY_ACCESS.setMemory(scope, base(), min(), length, value);
140         return this;
141     }
142 
143     public void copyFrom(MemorySegment src) {
144         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(src);
145         long size = that.byteSize();
146         checkAccess(0, size, false);
147         that.checkAccess(0, size, true);
148         SCOPED_MEMORY_ACCESS.copyMemory(scope, that.scope,
149                 that.base(), that.min(),
150                 base(), min(), size);
151     }
152 
153     public void copyFromSwap(MemorySegment src, long elemSize) {
154         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)src;
155         long size = that.byteSize();
156         checkAccess(0, size, false);
157         that.checkAccess(0, size, true);
158         SCOPED_MEMORY_ACCESS.copySwapMemory(scope, that.scope,
159                         that.base(), that.min(),
160                         base(), min(), size, elemSize);
161     }
162 
163     @Override
164     public long mismatch(MemorySegment other) {
165         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other);
166         final long thisSize = this.byteSize();
167         final long thatSize = that.byteSize();
168         final long length = Math.min(thisSize, thatSize);
169         this.checkAccess(0, length, true);
170         that.checkAccess(0, length, true);
171         if (this == other) {
172             checkValidState();
173             return -1;
174         }
175 
176         long i = 0;
177         if (length > 7) {
178             if (MemoryAccess.getByte(this) != MemoryAccess.getByte(that)) {
179                 return 0;
180             }
181             i = vectorizedMismatchLargeForBytes(scope, that.scope,
182                     this.base(), this.min(),
183                     that.base(), that.min(),
184                     length);
185             if (i >= 0) {
186                 return i;
187             }
188             long remaining = ~i;
189             assert remaining < 8 : "remaining greater than 7: " + remaining;
190             i = length - remaining;
191         }
192         for (; i < length; i++) {
193             if (MemoryAccess.getByteAtOffset(this, i) != MemoryAccess.getByteAtOffset(that, i)) {
194                 return i;
195             }
196         }
197         return thisSize != thatSize ? length : -1;
198     }
199 
200     /**
201      * Mismatch over long lengths.
202      */
203     private static long vectorizedMismatchLargeForBytes(ResourceScopeImpl aScope, ResourceScopeImpl bScope,
204                                                         Object a, long aOffset,
205                                                         Object b, long bOffset,
206                                                         long length) {
207         long off = 0;
208         long remaining = length;
209         int i, size;
210         boolean lastSubRange = false;
211         while (remaining > 7 && !lastSubRange) {
212             if (remaining > Integer.MAX_VALUE) {
213                 size = Integer.MAX_VALUE;
214             } else {
215                 size = (int) remaining;
216                 lastSubRange = true;
217             }
218             i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(aScope, bScope,
219                     a, aOffset + off,
220                     b, bOffset + off,
221                     size, ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE);
222             if (i >= 0)
223                 return off + i;
224 
225             i = size - ~i;
226             off += i;
227             remaining -= i;
228         }
229         return ~remaining;
230     }
231 
232     @Override
233     @ForceInline
234     public final MemoryAddress address() {
235         return new MemoryAddressImpl(this, 0L);
236     }
237 
238     @Override
239     public final ByteBuffer asByteBuffer() {
240         checkArraySize("ByteBuffer", 1);
241         ByteBuffer _bb = makeByteBuffer();
242         if (isSet(READ_ONLY)) {
243             //scope is IMMUTABLE - obtain a RO byte buffer
244             _bb = _bb.asReadOnlyBuffer();
245         }
246         return _bb;
247     }
248 
249     @Override
250     public final long byteSize() {
251         return length;
252     }
253 
254     public final boolean isAlive() {
255         return scope.isAlive();
256     }
257 
258     public Thread ownerThread() {
259         return scope.ownerThread();
260     }
261 
262     @Override
263     public boolean isMapped() {
264         return false;
265     }
266 
267     @Override
268     public boolean isNative() {
269         return false;
270     }
271 



























272     @Override
273     public void load() {
274         throw new UnsupportedOperationException("Not a mapped segment");
275     }
276 
277     @Override
278     public void unload() {
279         throw new UnsupportedOperationException("Not a mapped segment");
280     }
281 
282     @Override
283     public boolean isLoaded() {
284         throw new UnsupportedOperationException("Not a mapped segment");
285     }
286 
287     @Override
288     public void force() {
289         throw new UnsupportedOperationException("Not a mapped segment");
290     }
291 
292     @Override
293     public final byte[] toByteArray() {
294         return toArray(byte[].class, 1, byte[]::new, MemorySegment::ofArray);
295     }
296 
297     @Override
298     public final short[] toShortArray() {
299         return toArray(short[].class, 2, short[]::new, MemorySegment::ofArray);
300     }
301 
302     @Override
303     public final char[] toCharArray() {
304         return toArray(char[].class, 2, char[]::new, MemorySegment::ofArray);
305     }
306 
307     @Override
308     public final int[] toIntArray() {
309         return toArray(int[].class, 4, int[]::new, MemorySegment::ofArray);
310     }
311 
312     @Override
313     public final float[] toFloatArray() {
314         return toArray(float[].class, 4, float[]::new, MemorySegment::ofArray);
315     }
316 
317     @Override
318     public final long[] toLongArray() {
319         return toArray(long[].class, 8, long[]::new, MemorySegment::ofArray);
320     }
321 
322     @Override
323     public final double[] toDoubleArray() {
324         return toArray(double[].class, 8, double[]::new, MemorySegment::ofArray);
325     }
326 
327     private <Z> Z toArray(Class<Z> arrayClass, int elemSize, IntFunction<Z> arrayFactory, Function<Z, MemorySegment> segmentFactory) {
328         int size = checkArraySize(arrayClass.getSimpleName(), elemSize);
329         Z arr = arrayFactory.apply(size);
330         MemorySegment arrSegment = segmentFactory.apply(arr);
331         arrSegment.copyFrom(this);
332         return arr;
333     }
334 
335     @Override
336     public boolean isSmall() {
337         return isSet(SMALL);
338     }
339 
340     @Override
341     public void checkAccess(long offset, long length, boolean readOnly) {
342         if (!readOnly && isSet(READ_ONLY)) {
343             throw new UnsupportedOperationException("Attempt to write a read-only segment");
344         }
345         checkBounds(offset, length);
346     }
347 
348     void checkValidState() {
349         try {
350             scope.checkValidState();
351         } catch (ScopedMemoryAccess.Scope.ScopedAccessError ex) {

365 
366     // Helper methods
367 
368     private boolean isSet(int mask) {
369         return (this.mask & mask) != 0;
370     }
371 
372     private int checkArraySize(String typeName, int elemSize) {
373         if (length % elemSize != 0) {
374             throw new IllegalStateException(String.format("Segment size is not a multiple of %d. Size: %d", elemSize, length));
375         }
376         long arraySize = length / elemSize;
377         if (arraySize > (Integer.MAX_VALUE - 8)) { //conservative check
378             throw new IllegalStateException(String.format("Segment is too large to wrap as %s. Size: %d", typeName, length));
379         }
380         return (int)arraySize;
381     }
382 
383     private void checkBounds(long offset, long length) {
384         if (isSmall() &&
385                 offset < Integer.MAX_VALUE && length < Integer.MAX_VALUE &&
386                 offset > Integer.MIN_VALUE && length > Integer.MIN_VALUE) {
387             checkBoundsSmall((int)offset, (int)length);
388         } else {
389             if (length < 0 ||

390                     offset < 0 ||
391                     offset > this.length - length) { // careful of overflow
392                 throw outOfBoundException(offset, length);
393             }
394         }
395     }
396 
397     @Override
398     public ResourceScopeImpl scope() {
399         return scope;
400     }
401 
402     private void checkBoundsSmall(int offset, int length) {
403         if (length < 0 ||
404                 offset < 0 ||
405                 offset > (int)this.length - length) { // careful of overflow
406             throw outOfBoundException(offset, length);
407         }
408     }
409 

  1 /*
  2  * Copyright (c) 2020, 2021, 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 package jdk.internal.foreign;
 27 
 28 import jdk.incubator.foreign.*;
 29 import jdk.internal.access.JavaNioAccess;
 30 import jdk.internal.access.SharedSecrets;
 31 import jdk.internal.access.foreign.MemorySegmentProxy;
 32 import jdk.internal.access.foreign.UnmapperProxy;
 33 import jdk.internal.misc.ScopedMemoryAccess;
 34 import jdk.internal.util.ArraysSupport;
 35 import jdk.internal.vm.annotation.ForceInline;
 36 import sun.security.action.GetPropertyAction;
 37 
 38 import java.nio.ByteBuffer;
 39 import java.nio.ByteOrder;
 40 import java.util.*;
 41 import java.util.function.Consumer;
 42 import java.util.function.Function;
 43 import java.util.function.IntFunction;
 44 import java.util.stream.Stream;
 45 import java.util.stream.StreamSupport;
 46 
 47 import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE;
 48 
 49 /**
 50  * This abstract class provides an immutable implementation for the {@code MemorySegment} interface. This class contains information
 51  * about the segment's spatial and temporal bounds; each memory segment implementation is associated with an owner thread which is set at creation time.
 52  * Access to certain sensitive operations on the memory segment will fail with {@code IllegalStateException} if the
 53  * segment is either in an invalid state (e.g. it has already been closed) or if access occurs from a thread other
 54  * than the owner thread. See {@link ResourceScopeImpl} for more details on management of temporal bounds. Subclasses
 55  * are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and
 56  * {@link MappedMemorySegmentImpl}.
 57  */
 58 public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegmentProxy implements MemorySegment, SegmentAllocator, Scoped {
 59 
 60     private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
 61 
 62     private static final boolean enableSmallSegments =
 63             Boolean.parseBoolean(GetPropertyAction.privilegedGetProperty("jdk.incubator.foreign.SmallSegments", "true"));
 64 
 65     static final int READ_ONLY = 1;
 66     static final int SMALL = READ_ONLY << 1;
 67     static final long NONCE = new Random().nextLong();
 68 
 69     static final JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess();
 70 
 71     final long length;
 72     final int mask;
 73     final ResourceScopeImpl scope;
 74 
 75     @ForceInline
 76     AbstractMemorySegmentImpl(long length, int mask, ResourceScopeImpl scope) {
 77         this.length = length;
 78         this.mask = mask;

126         }
127         if (byteSize() % elementLayout.byteSize() != 0) {
128             throw new IllegalArgumentException("Segment size is no a multiple of layout size");
129         }
130         return new SegmentSplitter(elementLayout.byteSize(), byteSize() / elementLayout.byteSize(),
131                 this);
132     }
133 
134     @Override
135     public Stream<MemorySegment> elements(MemoryLayout elementLayout) {
136         return StreamSupport.stream(spliterator(elementLayout), false);
137     }
138 
139     @Override
140     public final MemorySegment fill(byte value){
141         checkAccess(0, length, false);
142         SCOPED_MEMORY_ACCESS.setMemory(scope, base(), min(), length, value);
143         return this;
144     }
145 
146     @Override
147     public MemorySegment allocate(long bytesSize, long bytesAlignment) {
148         return asSlice(0, bytesSize);















149     }
150 
151     @Override
152     public long mismatch(MemorySegment other) {
153         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other);
154         final long thisSize = this.byteSize();
155         final long thatSize = that.byteSize();
156         final long length = Math.min(thisSize, thatSize);
157         this.checkAccess(0, length, true);
158         that.checkAccess(0, length, true);
159         if (this == other) {
160             checkValidState();
161             return -1;
162         }
163 
164         long i = 0;
165         if (length > 7) {
166             if (get(JAVA_BYTE, 0) != that.get(JAVA_BYTE, 0)) {
167                 return 0;
168             }
169             i = vectorizedMismatchLargeForBytes(scope, that.scope,
170                     this.base(), this.min(),
171                     that.base(), that.min(),
172                     length);
173             if (i >= 0) {
174                 return i;
175             }
176             long remaining = ~i;
177             assert remaining < 8 : "remaining greater than 7: " + remaining;
178             i = length - remaining;
179         }
180         for (; i < length; i++) {
181             if (get(JAVA_BYTE, i) != that.get(JAVA_BYTE, i)) {
182                 return i;
183             }
184         }
185         return thisSize != thatSize ? length : -1;
186     }
187 
188     /**
189      * Mismatch over long lengths.
190      */
191     private static long vectorizedMismatchLargeForBytes(ResourceScopeImpl aScope, ResourceScopeImpl bScope,
192                                                         Object a, long aOffset,
193                                                         Object b, long bOffset,
194                                                         long length) {
195         long off = 0;
196         long remaining = length;
197         int i, size;
198         boolean lastSubRange = false;
199         while (remaining > 7 && !lastSubRange) {
200             if (remaining > Integer.MAX_VALUE) {
201                 size = Integer.MAX_VALUE;
202             } else {
203                 size = (int) remaining;
204                 lastSubRange = true;
205             }
206             i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(aScope, bScope,
207                     a, aOffset + off,
208                     b, bOffset + off,
209                     size, ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE);
210             if (i >= 0)
211                 return off + i;
212 
213             i = size - ~i;
214             off += i;
215             remaining -= i;
216         }
217         return ~remaining;
218     }
219 
220     @Override
221     public MemoryAddress address() {
222         throw new UnsupportedOperationException("Cannot obtain address of on-heap segment");

223     }
224 
225     @Override
226     public final ByteBuffer asByteBuffer() {
227         checkArraySize("ByteBuffer", 1);
228         ByteBuffer _bb = makeByteBuffer();
229         if (isSet(READ_ONLY)) {
230             //scope is IMMUTABLE - obtain a RO byte buffer
231             _bb = _bb.asReadOnlyBuffer();
232         }
233         return _bb;
234     }
235 
236     @Override
237     public final long byteSize() {
238         return length;
239     }
240 
241     public final boolean isAlive() {
242         return scope.isAlive();
243     }
244 
245     public Thread ownerThread() {
246         return scope.ownerThread();
247     }
248 
249     @Override
250     public boolean isMapped() {
251         return false;
252     }
253 
254     @Override
255     public boolean isNative() {
256         return false;
257     }
258 
259     @Override
260     public final MemorySegment asOverlappingSlice(MemorySegment other) {
261         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other);
262         if (base() == that.base()) {  // both either native or heap
263             final long thisStart = this.min();
264             final long thatStart = that.min();
265             final long thisEnd = thisStart + this.byteSize();
266             final long thatEnd = thatStart + that.byteSize();
267 
268             if (thisStart < thatEnd && thisEnd > thatStart) {  //overlap occurs
269                 long offsetToThat = this.segmentOffset(that);
270                 long newOffset = offsetToThat >= 0 ? offsetToThat : 0;
271                 return asSlice(newOffset, Math.min(this.byteSize() - newOffset, that.byteSize() + offsetToThat));
272             }
273         }
274         return null;
275     }
276 
277     @Override
278     public final long segmentOffset(MemorySegment other) {
279         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl) Objects.requireNonNull(other);
280         if (base() == that.base()) {
281             return that.min() - this.min();
282         }
283         throw new UnsupportedOperationException("Cannot compute offset from native to heap (or vice versa).");
284     }
285 
286     @Override
287     public void load() {
288         throw new UnsupportedOperationException("Not a mapped segment");
289     }
290 
291     @Override
292     public void unload() {
293         throw new UnsupportedOperationException("Not a mapped segment");
294     }
295 
296     @Override
297     public boolean isLoaded() {
298         throw new UnsupportedOperationException("Not a mapped segment");
299     }
300 
301     @Override
302     public void force() {
303         throw new UnsupportedOperationException("Not a mapped segment");
304     }
305 
306     @Override
307     public final byte[] toArray(ValueLayout.OfByte elementLayout) {
308         return toArray(byte[].class, elementLayout, byte[]::new, MemorySegment::ofArray);
309     }
310 
311     @Override
312     public final short[] toArray(ValueLayout.OfShort elementLayout) {
313         return toArray(short[].class, elementLayout, short[]::new, MemorySegment::ofArray);
314     }
315 
316     @Override
317     public final char[] toArray(ValueLayout.OfChar elementLayout) {
318         return toArray(char[].class, elementLayout, char[]::new, MemorySegment::ofArray);
319     }
320 
321     @Override
322     public final int[] toArray(ValueLayout.OfInt elementLayout) {
323         return toArray(int[].class, elementLayout, int[]::new, MemorySegment::ofArray);
324     }
325 
326     @Override
327     public final float[] toArray(ValueLayout.OfFloat elementLayout) {
328         return toArray(float[].class, elementLayout, float[]::new, MemorySegment::ofArray);
329     }
330 
331     @Override
332     public final long[] toArray(ValueLayout.OfLong elementLayout) {
333         return toArray(long[].class, elementLayout, long[]::new, MemorySegment::ofArray);
334     }
335 
336     @Override
337     public final double[] toArray(ValueLayout.OfDouble elementLayout) {
338         return toArray(double[].class, elementLayout, double[]::new, MemorySegment::ofArray);
339     }
340 
341     private <Z> Z toArray(Class<Z> arrayClass, ValueLayout elemLayout, IntFunction<Z> arrayFactory, Function<Z, MemorySegment> segmentFactory) {
342         int size = checkArraySize(arrayClass.getSimpleName(), (int)elemLayout.byteSize());
343         Z arr = arrayFactory.apply(size);
344         MemorySegment arrSegment = segmentFactory.apply(arr);
345         MemorySegment.copy(this, elemLayout, 0, arrSegment, elemLayout.withOrder(ByteOrder.nativeOrder()), 0, size);
346         return arr;
347     }
348 
349     @Override
350     public boolean isSmall() {
351         return isSet(SMALL);
352     }
353 
354     @Override
355     public void checkAccess(long offset, long length, boolean readOnly) {
356         if (!readOnly && isSet(READ_ONLY)) {
357             throw new UnsupportedOperationException("Attempt to write a read-only segment");
358         }
359         checkBounds(offset, length);
360     }
361 
362     void checkValidState() {
363         try {
364             scope.checkValidState();
365         } catch (ScopedMemoryAccess.Scope.ScopedAccessError ex) {

379 
380     // Helper methods
381 
382     private boolean isSet(int mask) {
383         return (this.mask & mask) != 0;
384     }
385 
386     private int checkArraySize(String typeName, int elemSize) {
387         if (length % elemSize != 0) {
388             throw new IllegalStateException(String.format("Segment size is not a multiple of %d. Size: %d", elemSize, length));
389         }
390         long arraySize = length / elemSize;
391         if (arraySize > (Integer.MAX_VALUE - 8)) { //conservative check
392             throw new IllegalStateException(String.format("Segment is too large to wrap as %s. Size: %d", typeName, length));
393         }
394         return (int)arraySize;
395     }
396 
397     private void checkBounds(long offset, long length) {
398         if (isSmall() &&
399                 offset <= Integer.MAX_VALUE && length <= Integer.MAX_VALUE &&
400                 offset >= Integer.MIN_VALUE && length >= Integer.MIN_VALUE) {
401             checkBoundsSmall((int)offset, (int)length);
402         } else if (this != NativeMemorySegmentImpl.EVERYTHING) { // oob not possible for everything segment
403             if (
404                     length < 0 ||
405                     offset < 0 ||
406                     offset > this.length - length) { // careful of overflow
407                 throw outOfBoundException(offset, length);
408             }
409         }
410     }
411 
412     @Override
413     public ResourceScopeImpl scope() {
414         return scope;
415     }
416 
417     private void checkBoundsSmall(int offset, int length) {
418         if (length < 0 ||
419                 offset < 0 ||
420                 offset > (int)this.length - length) { // careful of overflow
421             throw outOfBoundException(offset, length);
422         }
423     }
424 
< prev index next >