Skip to content

Commit c003c12

Browse files
committed
8331865: Consolidate size and alignment checks in LayoutPath
Reviewed-by: psandoz, jvernee
1 parent 6d718ae commit c003c12

File tree

12 files changed

+166
-133
lines changed

12 files changed

+166
-133
lines changed

src/java.base/share/classes/java/lang/foreign/MemoryLayout.java

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -625,12 +625,12 @@ public sealed interface MemoryLayout
625625
* (this layout), or an {@link IllegalArgumentException} is thrown. Note
626626
* that the alignment constraint of the root layout can be more strict
627627
* (but not less) than the alignment constraint of the selected value layout.</li>
628-
* <li>The offset of the access operation (computed as above) must fall inside
629-
* the spatial bounds of the accessed memory segment, or an
630-
* {@link IndexOutOfBoundsException} is thrown. This is the case when
631-
* {@code O + A <= S}, where {@code O} is the accessed offset (computed as above),
632-
* {@code A} is the size of the selected layout and {@code S} is the size of the
633-
* accessed memory segment.</li>
628+
* <li>The access operation must fall inside the spatial bounds of the accessed
629+
* memory segment, or an {@link IndexOutOfBoundsException} is thrown. This is the case
630+
* when {@code B + A <= S}, where {@code B} is the base offset (defined above),
631+
* {@code A} is the size of this layout and {@code S} is the size of the
632+
* accessed memory segment. Note that the size of this layout might be <em>bigger</em>
633+
* than the size of the accessed layout (e.g. when accessing a struct member).</li>
634634
* <li>If the provided layout path has an open path element whose size is {@code S},
635635
* its corresponding trailing {@code long} coordinate value {@code I} must be
636636
* {@code 0 <= I < S}, or an {@link IndexOutOfBoundsException} is thrown.</li>
@@ -753,12 +753,12 @@ public sealed interface MemoryLayout
753753
* (this layout), or an {@link IllegalArgumentException} is thrown. Note
754754
* that the alignment constraint of the root layout can be more strict
755755
* (but not less) than the alignment constraint of the selected value layout.</li>
756-
* <li>The offset of the access operation (computed as above) must fall inside
757-
* the spatial bounds of the accessed memory segment, or an
758-
* {@link IndexOutOfBoundsException} is thrown. This is the case when
759-
* {@code O + A <= S}, where {@code O} is the accessed offset (computed as above),
760-
* {@code A} is the size of the selected layout and {@code S} is the size of the
761-
* accessed memory segment.</li>
756+
* <li>The access operation must fall inside the spatial bounds of the accessed
757+
* memory segment, or an {@link IndexOutOfBoundsException} is thrown. This is the case
758+
* when {@code B + A <= S}, where {@code B} is the base offset (defined above),
759+
* {@code A} is the size of this layout and {@code S} is the size of the
760+
* accessed memory segment. Note that the size of this layout might be <em>bigger</em>
761+
* than the size of the accessed layout (e.g. when accessing a struct member).</li>
762762
* <li>If the provided layout path has an open path element whose size is {@code S},
763763
* its corresponding trailing {@code long} coordinate value {@code I} must be
764764
* {@code 0 <= I < S}, or an {@link IndexOutOfBoundsException} is thrown.</li>
@@ -822,12 +822,12 @@ public sealed interface MemoryLayout
822822
* (this layout), or an {@link IllegalArgumentException} will be issued. Note
823823
* that the alignment constraint of the root layout can be more strict
824824
* (but not less) than the alignment constraint of the selected layout.</li>
825-
* <li>The start offset of the slicing operation (computed as above) must fall
826-
* inside the spatial bounds of the accessed memory segment, or an
827-
* {@link IndexOutOfBoundsException} is thrown. This is the case when
828-
* {@code O + A <= S}, where {@code O} is the start offset of
829-
* the slicing operation (computed as above), {@code A} is the size of the
830-
* selected layout and {@code S} is the size of the accessed memory segment.</li>
825+
* <li>The slicing operation must fall inside the spatial bounds of the accessed
826+
* memory segment, or an {@link IndexOutOfBoundsException} is thrown. This is the case
827+
* when {@code B + A <= S}, where {@code B} is the base offset (defined above),
828+
* {@code A} is the size of this layout and {@code S} is the size of the
829+
* accessed memory segment. Note that the size of this layout might be <em>bigger</em>
830+
* than the size of the accessed layout (e.g. when accessing a struct member).</li>
831831
* <li>If the provided layout path has an open path element whose size is {@code S},
832832
* its corresponding trailing {@code long} coordinate value {@code I} must be
833833
* {@code 0 <= I < S}, or an {@link IndexOutOfBoundsException} is thrown.</li>

src/java.base/share/classes/java/lang/invoke/VarHandleSegmentViewBase.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
2525

2626
package java.lang.invoke;
2727

28-
import jdk.internal.foreign.Utils;
29-
3028
/**
3129
* Base class for memory segment var handle view implementations.
3230
*/
@@ -42,23 +40,15 @@ abstract sealed class VarHandleSegmentViewBase extends VarHandle permits
4240
/** endianness **/
4341
final boolean be;
4442

45-
/** access size (in bytes, computed from var handle carrier type) **/
46-
final long length;
47-
4843
/** alignment constraint (in bytes, expressed as a bit mask) **/
4944
final long alignmentMask;
5045

51-
VarHandleSegmentViewBase(VarForm form, boolean be, long length, long alignmentMask, boolean exact) {
46+
VarHandleSegmentViewBase(VarForm form, boolean be, long alignmentMask, boolean exact) {
5247
super(form, exact);
5348
this.be = be;
54-
this.length = length;
5549
this.alignmentMask = alignmentMask;
5650
}
5751

58-
static IllegalArgumentException newIllegalArgumentExceptionForMisalignedAccess(long address) {
59-
return new IllegalArgumentException("Misaligned access at address: " + Utils.toHexString(address));
60-
}
61-
6252
static UnsupportedOperationException newUnsupportedAccessModeForAlignment(long alignment) {
6353
return new UnsupportedOperationException("Unsupported access mode for alignment: " + alignment);
6454
}

src/java.base/share/classes/java/lang/invoke/VarHandles.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -306,6 +306,9 @@ else if (viewComponentType == float.class) {
306306
* The resulting var handle will take a memory segment as first argument (the segment to be dereferenced),
307307
* and a {@code long} as second argument (the offset into the segment).
308308
*
309+
* Note: the returned var handle does not perform any size or alignment check. It is up to clients
310+
* to adapt the returned var handle and insert the appropriate checks.
311+
*
309312
* @param carrier the Java carrier type.
310313
* @param alignmentMask alignment requirement to be checked upon access. In bytes. Expressed as a mask.
311314
* @param byteOrder the byte order.
@@ -316,24 +319,23 @@ static VarHandle memorySegmentViewHandle(Class<?> carrier, long alignmentMask,
316319
if (!carrier.isPrimitive() || carrier == void.class || carrier == boolean.class) {
317320
throw new IllegalArgumentException("Invalid carrier: " + carrier.getName());
318321
}
319-
long size = Utils.byteWidthOfPrimitive(carrier);
320322
boolean be = byteOrder == ByteOrder.BIG_ENDIAN;
321323
boolean exact = VAR_HANDLE_SEGMENT_FORCE_EXACT;
322324

323325
if (carrier == byte.class) {
324-
return maybeAdapt(new VarHandleSegmentAsBytes(be, size, alignmentMask, exact));
326+
return maybeAdapt(new VarHandleSegmentAsBytes(be, alignmentMask, exact));
325327
} else if (carrier == char.class) {
326-
return maybeAdapt(new VarHandleSegmentAsChars(be, size, alignmentMask, exact));
328+
return maybeAdapt(new VarHandleSegmentAsChars(be, alignmentMask, exact));
327329
} else if (carrier == short.class) {
328-
return maybeAdapt(new VarHandleSegmentAsShorts(be, size, alignmentMask, exact));
330+
return maybeAdapt(new VarHandleSegmentAsShorts(be, alignmentMask, exact));
329331
} else if (carrier == int.class) {
330-
return maybeAdapt(new VarHandleSegmentAsInts(be, size, alignmentMask, exact));
332+
return maybeAdapt(new VarHandleSegmentAsInts(be, alignmentMask, exact));
331333
} else if (carrier == float.class) {
332-
return maybeAdapt(new VarHandleSegmentAsFloats(be, size, alignmentMask, exact));
334+
return maybeAdapt(new VarHandleSegmentAsFloats(be, alignmentMask, exact));
333335
} else if (carrier == long.class) {
334-
return maybeAdapt(new VarHandleSegmentAsLongs(be, size, alignmentMask, exact));
336+
return maybeAdapt(new VarHandleSegmentAsLongs(be, alignmentMask, exact));
335337
} else if (carrier == double.class) {
336-
return maybeAdapt(new VarHandleSegmentAsDoubles(be, size, alignmentMask, exact));
338+
return maybeAdapt(new VarHandleSegmentAsDoubles(be, alignmentMask, exact));
337339
} else {
338340
throw new IllegalStateException("Cannot get here");
339341
}

0 commit comments

Comments
 (0)