mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-24 13:24:27 +02:00
8350118: Simplify the layout access VarHandle
Reviewed-by: mcimadamore, jvernee, erikj
This commit is contained in:
parent
fb659eba02
commit
c7fa499bf5
18 changed files with 1977 additions and 1140 deletions
|
@ -42,6 +42,17 @@ define GenerateScopedOp
|
|||
|
||||
$1_Type := $2
|
||||
|
||||
ifeq ($$($1_Type), Boolean)
|
||||
$1_type := boolean
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Byte)
|
||||
$1_type := byte
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
@ -50,6 +61,7 @@ define GenerateScopedOp
|
|||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -Kbyte
|
||||
endif
|
||||
|
||||
|
@ -60,6 +72,8 @@ define GenerateScopedOp
|
|||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KUnaligned
|
||||
endif
|
||||
|
||||
|
@ -70,6 +84,8 @@ define GenerateScopedOp
|
|||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KUnaligned
|
||||
endif
|
||||
|
||||
|
@ -82,8 +98,6 @@ define GenerateScopedOp
|
|||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KAtomicAdd
|
||||
$1_ARGS += -KBitwise
|
||||
$1_ARGS += -KUnaligned
|
||||
endif
|
||||
|
||||
|
@ -96,8 +110,6 @@ define GenerateScopedOp
|
|||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KAtomicAdd
|
||||
$1_ARGS += -KBitwise
|
||||
$1_ARGS += -KUnaligned
|
||||
endif
|
||||
|
||||
|
@ -133,7 +145,7 @@ define GenerateScopedOp
|
|||
$1_ARGS += -KBitwise
|
||||
endif
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Byte Short Char), )
|
||||
ifneq ($$(findstring $$($1_Type), Boolean Byte Short Char), )
|
||||
$1_ARGS += -KShorterThanInt
|
||||
endif
|
||||
endef
|
||||
|
@ -141,7 +153,7 @@ endef
|
|||
################################################################################
|
||||
# Setup a rule for generating the ScopedMemoryAccess java class
|
||||
|
||||
SCOPE_MEMORY_ACCESS_TYPES := Byte Short Char Int Long Float Double
|
||||
SCOPE_MEMORY_ACCESS_TYPES := Boolean Byte Short Char Int Long Float Double
|
||||
$(foreach t, $(SCOPE_MEMORY_ACCESS_TYPES), \
|
||||
$(eval $(call GenerateScopedOp,BIN_$t,$t)))
|
||||
|
||||
|
|
|
@ -174,6 +174,18 @@ define GenerateVarHandleMemorySegment
|
|||
|
||||
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleSegmentAs$$($1_Type)s.java
|
||||
|
||||
ifeq ($$($1_Type), Boolean)
|
||||
$1_type := boolean
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -Kbyte
|
||||
$1_ARGS += -KShorterThanInt
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Byte)
|
||||
$1_type := byte
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
@ -183,6 +195,7 @@ define GenerateVarHandleMemorySegment
|
|||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -Kbyte
|
||||
$1_ARGS += -KShorterThanInt
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Short)
|
||||
|
@ -192,6 +205,8 @@ define GenerateVarHandleMemorySegment
|
|||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KShorterThanInt
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Char)
|
||||
|
@ -201,6 +216,8 @@ define GenerateVarHandleMemorySegment
|
|||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KShorterThanInt
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Int)
|
||||
|
@ -277,7 +294,7 @@ $(foreach t, $(VARHANDLES_BYTE_ARRAY_TYPES), \
|
|||
$(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t)))
|
||||
|
||||
# List the types to generate source for, with capitalized first letter
|
||||
VARHANDLES_MEMORY_SEGMENT_TYPES := Byte Short Char Int Long Float Double
|
||||
VARHANDLES_MEMORY_SEGMENT_TYPES := Boolean Byte Short Char Int Long Float Double
|
||||
$(foreach t, $(VARHANDLES_MEMORY_SEGMENT_TYPES), \
|
||||
$(eval $(call GenerateVarHandleMemorySegment,VAR_HANDLE_MEMORY_SEGMENT_$t,$t)))
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -43,6 +43,7 @@ import sun.invoke.util.Wrapper;
|
|||
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.foreign.MemoryLayout;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
@ -1552,8 +1553,8 @@ abstract class MethodHandleImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VarHandle memorySegmentViewHandle(Class<?> carrier, long alignmentMask, ByteOrder order) {
|
||||
return VarHandles.memorySegmentViewHandle(carrier, alignmentMask, order);
|
||||
public VarHandle memorySegmentViewHandle(Class<?> carrier, MemoryLayout enclosing, long alignmentMask, ByteOrder order, boolean constantOffset, long offset) {
|
||||
return VarHandles.memorySegmentViewHandle(carrier, enclosing, alignmentMask, constantOffset, offset, order);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang.invoke;
|
||||
|
||||
import java.lang.foreign.MemoryLayout;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.util.Objects;
|
||||
|
||||
import jdk.internal.foreign.AbstractMemorySegmentImpl;
|
||||
import jdk.internal.misc.ScopedMemoryAccess;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
/**
|
||||
* A var handle that accesses primitive values in a memory segment.
|
||||
*/
|
||||
final class SegmentVarHandle extends VarHandle {
|
||||
|
||||
// Common implementation fields for the VarForms
|
||||
static final boolean BE = MethodHandleStatics.UNSAFE.isBigEndian();
|
||||
static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
|
||||
|
||||
/** endianness **/
|
||||
final boolean be;
|
||||
/** The layout the accessed segment must be compatible with. */
|
||||
final MemoryLayout enclosing;
|
||||
/** The offset value, if is constant. vform decides if offset is constant or variable. */
|
||||
final long offset;
|
||||
|
||||
SegmentVarHandle(VarForm form, boolean be, MemoryLayout enclosing, long offset, boolean exact) {
|
||||
super(form, exact);
|
||||
this.be = be;
|
||||
this.enclosing = enclosing;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(VarHandle.AccessType accessType) {
|
||||
var getType = vform.methodType_table[0]; // erased, but our value type is erase-compatible
|
||||
return getType.parameterCount() == 2
|
||||
? accessType.accessModeType(MemorySegment.class, getType.returnType(), long.class)
|
||||
: accessType.accessModeType(MemorySegment.class, getType.returnType(), long.class, long.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SegmentVarHandle withInvokeExactBehavior() {
|
||||
return hasInvokeExactBehavior() ?
|
||||
this :
|
||||
new SegmentVarHandle(vform, be, enclosing, offset, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SegmentVarHandle withInvokeBehavior() {
|
||||
return !hasInvokeExactBehavior() ?
|
||||
this :
|
||||
new SegmentVarHandle(vform, be, enclosing, offset, false);
|
||||
}
|
||||
|
||||
// Common implementation methods for the VarForms
|
||||
|
||||
@ForceInline
|
||||
static long offset(AbstractMemorySegmentImpl bb, long base, long offset) {
|
||||
long segment_base = bb.unsafeGetOffset();
|
||||
return segment_base + base + offset;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
AbstractMemorySegmentImpl checkSegment(Object obb, long base, boolean ro) {
|
||||
AbstractMemorySegmentImpl oo = (AbstractMemorySegmentImpl) Objects.requireNonNull(obb);
|
||||
oo.checkEnclosingLayout(base, this.enclosing, ro);
|
||||
return oo;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -36,6 +36,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
|
||||
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||
|
||||
/**
|
||||
* A var handle form containing a set of member name, one for each operation.
|
||||
|
@ -43,6 +44,7 @@ import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
|
|||
*/
|
||||
final class VarForm {
|
||||
|
||||
// implClass must be initialized when the member names are accessed!
|
||||
final Class<?> implClass;
|
||||
|
||||
final @Stable MethodType[] methodType_table;
|
||||
|
@ -63,6 +65,15 @@ final class VarForm {
|
|||
}
|
||||
}
|
||||
|
||||
VarForm(Class<?> implClass, VarForm methodTypeSource) {
|
||||
this.implClass = implClass;
|
||||
// reuse initMethodTypes result from methodTypeSource
|
||||
this.methodType_table = methodTypeSource.methodType_table;
|
||||
this.methodType_V_table = methodTypeSource.methodType_V_table;
|
||||
this.memberName_table = new MemberName[VarHandle.AccessMode.COUNT];
|
||||
assert assertMethodTypeTableInitialized() : implClass;
|
||||
}
|
||||
|
||||
// Used by IndirectVarHandle
|
||||
VarForm(Class<?> value, Class<?>[] coordinates) {
|
||||
this.methodType_table = new MethodType[VarHandle.AccessType.COUNT];
|
||||
|
@ -103,6 +114,15 @@ final class VarForm {
|
|||
type.changeReturnType(boolean.class);
|
||||
}
|
||||
|
||||
private boolean assertMethodTypeTableInitialized() {
|
||||
if (methodType_table == null)
|
||||
return false;
|
||||
for (int i = 0; i < VarHandle.AccessType.COUNT; i++) {
|
||||
assert methodType_table[i] != null : implClass + " " + VarHandle.AccessType.values()[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
final MethodType getMethodType(int type) {
|
||||
return methodType_table[type];
|
||||
|
@ -137,6 +157,7 @@ final class VarForm {
|
|||
AccessMode value = AccessMode.valueFromOrdinal(mode);
|
||||
String methodName = value.methodName();
|
||||
MethodType type = methodType_table[value.at.ordinal()].insertParameterTypes(0, VarHandle.class);
|
||||
assert !UNSAFE.shouldBeInitialized(implClass) : implClass;
|
||||
return memberName_table[mode] = MethodHandles.Lookup.IMPL_LOOKUP
|
||||
.resolveOrNull(REF_invokeStatic, implClass, methodName, type);
|
||||
}
|
||||
|
|
|
@ -472,8 +472,7 @@ import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
|||
* @since 9
|
||||
*/
|
||||
public abstract sealed class VarHandle implements Constable
|
||||
permits IndirectVarHandle, LazyInitializingVarHandle,
|
||||
VarHandleSegmentViewBase,
|
||||
permits IndirectVarHandle, LazyInitializingVarHandle, SegmentVarHandle,
|
||||
VarHandleByteArrayAsChars.ByteArrayViewVarHandle,
|
||||
VarHandleByteArrayAsDoubles.ByteArrayViewVarHandle,
|
||||
VarHandleByteArrayAsFloats.ByteArrayViewVarHandle,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang.invoke;
|
||||
|
||||
/**
|
||||
* Base class for memory segment var handle view implementations.
|
||||
*/
|
||||
abstract sealed class VarHandleSegmentViewBase extends VarHandle permits
|
||||
VarHandleSegmentAsBytes,
|
||||
VarHandleSegmentAsChars,
|
||||
VarHandleSegmentAsDoubles,
|
||||
VarHandleSegmentAsFloats,
|
||||
VarHandleSegmentAsInts,
|
||||
VarHandleSegmentAsLongs,
|
||||
VarHandleSegmentAsShorts {
|
||||
|
||||
/** endianness **/
|
||||
final boolean be;
|
||||
|
||||
/** alignment constraint (in bytes, expressed as a bit mask) **/
|
||||
final long alignmentMask;
|
||||
|
||||
VarHandleSegmentViewBase(VarForm form, boolean be, long alignmentMask, boolean exact) {
|
||||
super(form, exact);
|
||||
this.be = be;
|
||||
this.alignmentMask = alignmentMask;
|
||||
}
|
||||
|
||||
static UnsupportedOperationException newUnsupportedAccessModeForAlignment(long alignment) {
|
||||
return new UnsupportedOperationException("Unsupported access mode for alignment: " + alignment);
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ package java.lang.invoke;
|
|||
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import java.lang.foreign.MemoryLayout;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
@ -291,44 +292,55 @@ final class VarHandles {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a memory segment view var handle.
|
||||
*
|
||||
* Creates a memory segment view var handle accessing a {@code carrier} element. It has access coordinates
|
||||
* {@code (MS, long)} if {@code constantOffset}, {@code (MS, long, (validated) long)} otherwise.
|
||||
* <p>
|
||||
* The resulting var handle will take a memory segment as first argument (the segment to be dereferenced),
|
||||
* and a {@code long} as second argument (the offset into the segment).
|
||||
* and a {@code long} as second argument (the offset into the segment). Both arguments are checked.
|
||||
* <p>
|
||||
* If {@code constantOffset == false}, the resulting var handle will take a third pre-validated additional
|
||||
* offset instead of the given fixed {@code offset}, and caller must ensure that passed additional offset,
|
||||
* either to the handle (such as computing through method handles) or as fixed {@code offset} here, is valid.
|
||||
*
|
||||
* Note: the returned var handle does not perform any size or alignment check. It is up to clients
|
||||
* to adapt the returned var handle and insert the appropriate checks.
|
||||
*
|
||||
* @param carrier the Java carrier type.
|
||||
* @param alignmentMask alignment requirement to be checked upon access. In bytes. Expressed as a mask.
|
||||
* @param byteOrder the byte order.
|
||||
* @return the created VarHandle.
|
||||
* @param carrier the Java carrier type of the element
|
||||
* @param enclosing the enclosing layout to perform bound and alignment checks against
|
||||
* @param alignmentMask alignment of this accessed element in the enclosing layout
|
||||
* @param constantOffset if access path has a constant offset value, i.e. it has no strides
|
||||
* @param offset the offset value, if the offset is constant
|
||||
* @param byteOrder the byte order
|
||||
* @return the created var handle
|
||||
*/
|
||||
static VarHandle memorySegmentViewHandle(Class<?> carrier, long alignmentMask,
|
||||
ByteOrder byteOrder) {
|
||||
if (!carrier.isPrimitive() || carrier == void.class || carrier == boolean.class) {
|
||||
static VarHandle memorySegmentViewHandle(Class<?> carrier, MemoryLayout enclosing, long alignmentMask,
|
||||
boolean constantOffset, long offset, ByteOrder byteOrder) {
|
||||
if (!carrier.isPrimitive() || carrier == void.class) {
|
||||
throw new IllegalArgumentException("Invalid carrier: " + carrier.getName());
|
||||
}
|
||||
boolean be = byteOrder == ByteOrder.BIG_ENDIAN;
|
||||
boolean exact = VAR_HANDLE_SEGMENT_FORCE_EXACT;
|
||||
|
||||
// All carrier types must persist across MethodType erasure
|
||||
VarForm form;
|
||||
if (carrier == byte.class) {
|
||||
return maybeAdapt(new VarHandleSegmentAsBytes(be, alignmentMask, exact));
|
||||
form = VarHandleSegmentAsBytes.selectForm(alignmentMask, constantOffset);
|
||||
} else if (carrier == char.class) {
|
||||
return maybeAdapt(new VarHandleSegmentAsChars(be, alignmentMask, exact));
|
||||
form = VarHandleSegmentAsChars.selectForm(alignmentMask, constantOffset);
|
||||
} else if (carrier == short.class) {
|
||||
return maybeAdapt(new VarHandleSegmentAsShorts(be, alignmentMask, exact));
|
||||
form = VarHandleSegmentAsShorts.selectForm(alignmentMask, constantOffset);
|
||||
} else if (carrier == int.class) {
|
||||
return maybeAdapt(new VarHandleSegmentAsInts(be, alignmentMask, exact));
|
||||
form = VarHandleSegmentAsInts.selectForm(alignmentMask, constantOffset);
|
||||
} else if (carrier == float.class) {
|
||||
return maybeAdapt(new VarHandleSegmentAsFloats(be, alignmentMask, exact));
|
||||
form = VarHandleSegmentAsFloats.selectForm(alignmentMask, constantOffset);
|
||||
} else if (carrier == long.class) {
|
||||
return maybeAdapt(new VarHandleSegmentAsLongs(be, alignmentMask, exact));
|
||||
form = VarHandleSegmentAsLongs.selectForm(alignmentMask, constantOffset);
|
||||
} else if (carrier == double.class) {
|
||||
return maybeAdapt(new VarHandleSegmentAsDoubles(be, alignmentMask, exact));
|
||||
form = VarHandleSegmentAsDoubles.selectForm(alignmentMask, constantOffset);
|
||||
} else if (carrier == boolean.class) {
|
||||
form = VarHandleSegmentAsBooleans.selectForm(alignmentMask, constantOffset);
|
||||
} else {
|
||||
throw new IllegalStateException("Cannot get here");
|
||||
}
|
||||
|
||||
return maybeAdapt(new SegmentVarHandle(form, be, enclosing, offset, exact));
|
||||
}
|
||||
|
||||
private static VarHandle maybeAdapt(VarHandle target) {
|
||||
|
@ -724,7 +736,7 @@ final class VarHandles {
|
|||
// Object getAndUpdate(Object value);
|
||||
// }
|
||||
//
|
||||
// record HandleType(Class<?> receiver, Class<?> value, Class<?>... intermediates) {
|
||||
// record HandleType(Class<?> receiver, Class<?>... intermediates) {
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
|
@ -744,48 +756,31 @@ final class VarHandles {
|
|||
// System.out.println();
|
||||
//
|
||||
// // Declare the stream of shapes
|
||||
// Stream<HandleType> hts = Stream.of(
|
||||
// // Object->Object
|
||||
// new HandleType(Object.class, Object.class),
|
||||
// // Object->int
|
||||
// List<HandleType> hts = List.of(
|
||||
// // Object->T
|
||||
// new HandleType(Object.class),
|
||||
//
|
||||
// // <static>->T
|
||||
// new HandleType(null),
|
||||
//
|
||||
// // Array[index]->T
|
||||
// new HandleType(Object.class, int.class),
|
||||
// // Object->long
|
||||
//
|
||||
// // MS[base]->T
|
||||
// new HandleType(Object.class, long.class),
|
||||
// // Object->float
|
||||
// new HandleType(Object.class, float.class),
|
||||
// // Object->double
|
||||
// new HandleType(Object.class, double.class),
|
||||
//
|
||||
// // <static>->Object
|
||||
// new HandleType(null, Object.class),
|
||||
// // <static>->int
|
||||
// new HandleType(null, int.class),
|
||||
// // <static>->long
|
||||
// new HandleType(null, long.class),
|
||||
// // <static>->float
|
||||
// new HandleType(null, float.class),
|
||||
// // <static>->double
|
||||
// new HandleType(null, double.class),
|
||||
//
|
||||
// // Array[int]->Object
|
||||
// new HandleType(Object.class, Object.class, int.class),
|
||||
// // Array[int]->int
|
||||
// new HandleType(Object.class, int.class, int.class),
|
||||
// // Array[int]->long
|
||||
// new HandleType(Object.class, long.class, int.class),
|
||||
// // Array[int]->float
|
||||
// new HandleType(Object.class, float.class, int.class),
|
||||
// // Array[int]->double
|
||||
// new HandleType(Object.class, double.class, int.class),
|
||||
//
|
||||
// // Array[long]->int
|
||||
// new HandleType(Object.class, int.class, long.class),
|
||||
// // Array[long]->long
|
||||
// // MS[base][offset]->T
|
||||
// new HandleType(Object.class, long.class, long.class)
|
||||
// );
|
||||
//
|
||||
// hts.flatMap(ht -> Stream.of(VarHandleTemplate.class.getMethods()).
|
||||
// map(m -> generateMethodType(m, ht.receiver, ht.value, ht.intermediates))).
|
||||
// Stream.of(VarHandleTemplate.class.getMethods()).<MethodType>
|
||||
// mapMulti((m, sink) -> {
|
||||
// for (var ht : hts) {
|
||||
// for (var bt : LambdaForm.BasicType.ARG_TYPES) {
|
||||
// sink.accept(generateMethodType(m, ht.receiver, bt.btClass, ht.intermediates));
|
||||
// }
|
||||
// }
|
||||
// }).
|
||||
// distinct().
|
||||
// map(GuardMethodGenerator::generateMethod).
|
||||
// forEach(System.out::println);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,53 +25,106 @@
|
|||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.foreign.AbstractMemorySegmentImpl;
|
||||
import jdk.internal.foreign.Utils;
|
||||
import jdk.internal.misc.ScopedMemoryAccess;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
import java.lang.foreign.MemoryLayout;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.ref.Reference;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||
import static java.lang.invoke.SegmentVarHandle.*;
|
||||
|
||||
#warn
|
||||
|
||||
final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
||||
|
||||
static final boolean BE = UNSAFE.isBigEndian();
|
||||
|
||||
static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
|
||||
{#if[byte]?final:sealed} class VarHandleSegmentAs$Type$s {
|
||||
|
||||
#if[!byte]
|
||||
static final int NON_PLAIN_ACCESS_MIN_ALIGN_MASK = $BoxType$.BYTES - 1;
|
||||
|
||||
static final VarForm FORM = new VarForm(VarHandleSegmentAs$Type$s.class, MemorySegment.class, $type$.class, MemoryLayout.class, long.class, long.class);
|
||||
|
||||
VarHandleSegmentAs$Type$s(boolean be, long alignmentMask, boolean exact) {
|
||||
super(FORM, be, alignmentMask, exact);
|
||||
#end[byte]
|
||||
static VarForm selectForm(long alignmentMask, boolean constantOffset) {
|
||||
#if[byte]
|
||||
return constantOffset ? CONSTANT_OFFSET_FORM : VARIABLE_OFFSET_FORM;
|
||||
#else[byte]
|
||||
return (alignmentMask & NON_PLAIN_ACCESS_MIN_ALIGN_MASK) != NON_PLAIN_ACCESS_MIN_ALIGN_MASK ?
|
||||
(constantOffset ? CONSTANT_OFFSET_FORM : VARIABLE_OFFSET_FORM) :
|
||||
(constantOffset ? VarHandleSegmentAs$Type$sAligned.CONSTANT_OFFSET_FORM : VarHandleSegmentAs$Type$sAligned.VARIABLE_OFFSET_FORM);
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(VarHandle.AccessType accessType) {
|
||||
return accessType.accessModeType(MemorySegment.class, $type$.class, MemoryLayout.class, long.class, long.class);
|
||||
static final VarForm CONSTANT_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$s.class, MemorySegment.class, $type$.class, long.class);
|
||||
static final VarForm VARIABLE_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$s.class, MemorySegment.class, $type$.class, long.class, long.class);
|
||||
|
||||
VarHandleSegmentAs$Type$s() { throw new AssertionError(); }
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(VarHandle ob, Object obb, long base) {
|
||||
return get(ob, obb, base, ((SegmentVarHandle) ob).offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VarHandleSegmentAs$Type$s withInvokeExactBehavior() {
|
||||
return hasInvokeExactBehavior() ?
|
||||
this :
|
||||
new VarHandleSegmentAs$Type$s(be, alignmentMask, true);
|
||||
@ForceInline
|
||||
static $type$ get(VarHandle ob, Object obb, long base, long offset) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true);
|
||||
#if[floatingPoint]
|
||||
$rawType$ rawValue = SCOPED_MEMORY_ACCESS.get$RawType$Unaligned(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offset(bb, base, offset),
|
||||
handle.be);
|
||||
return $Type$.$rawType$BitsTo$Type$(rawValue);
|
||||
#else[floatingPoint]
|
||||
#if[byte]
|
||||
return SCOPED_MEMORY_ACCESS.get$Type$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offset(bb, base, offset));
|
||||
#else[byte]
|
||||
return SCOPED_MEMORY_ACCESS.get$Type$Unaligned(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offset(bb, base, offset),
|
||||
handle.be);
|
||||
#end[byte]
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@Override
|
||||
public VarHandleSegmentAs$Type$s withInvokeBehavior() {
|
||||
return !hasInvokeExactBehavior() ?
|
||||
this :
|
||||
new VarHandleSegmentAs$Type$s(be, alignmentMask, false);
|
||||
@ForceInline
|
||||
static void set(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
set(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[floatingPoint]
|
||||
SCOPED_MEMORY_ACCESS.put$RawType$Unaligned(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offset(bb, base, offset),
|
||||
$Type$.$type$ToRaw$RawType$Bits(value),
|
||||
handle.be);
|
||||
#else[floatingPoint]
|
||||
#if[byte]
|
||||
SCOPED_MEMORY_ACCESS.put$Type$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offset(bb, base, offset),
|
||||
value);
|
||||
#else[byte]
|
||||
SCOPED_MEMORY_ACCESS.put$Type$Unaligned(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offset(bb, base, offset),
|
||||
value,
|
||||
handle.be);
|
||||
#end[byte]
|
||||
#end[floatingPoint]
|
||||
}
|
||||
#if[!byte]
|
||||
}
|
||||
|
||||
// This class must be accessed through non-aligned VarHandleSegmentAs$Type$s
|
||||
final class VarHandleSegmentAs$Type$sAligned extends VarHandleSegmentAs$Type$s {
|
||||
|
||||
static final VarForm CONSTANT_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$sAligned.class, VarHandleSegmentAs$Type$s.CONSTANT_OFFSET_FORM);
|
||||
static final VarForm VARIABLE_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$sAligned.class, VarHandleSegmentAs$Type$s.VARIABLE_OFFSET_FORM);
|
||||
|
||||
VarHandleSegmentAs$Type$sAligned() { throw new AssertionError(); }
|
||||
#end[byte]
|
||||
|
||||
#if[floatingPoint]
|
||||
@ForceInline
|
||||
static $rawType$ convEndian(boolean big, $type$ v) {
|
||||
|
@ -99,296 +152,338 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
|||
#end[floatingPoint]
|
||||
|
||||
@ForceInline
|
||||
static AbstractMemorySegmentImpl checkSegment(Object obb, Object encl, long base, boolean ro) {
|
||||
AbstractMemorySegmentImpl oo = (AbstractMemorySegmentImpl)Objects.requireNonNull(obb);
|
||||
oo.checkEnclosingLayout(base, (MemoryLayout)encl, ro);
|
||||
return oo;
|
||||
static $type$ getVolatile(VarHandle ob, Object obb, long base) {
|
||||
return getVolatile(ob, obb, base, ((SegmentVarHandle) ob).offset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static long offsetNonPlain(AbstractMemorySegmentImpl bb, long base, long offset, long alignmentMask) {
|
||||
if ((alignmentMask & NON_PLAIN_ACCESS_MIN_ALIGN_MASK) != NON_PLAIN_ACCESS_MIN_ALIGN_MASK) {
|
||||
throw VarHandleSegmentViewBase.newUnsupportedAccessModeForAlignment(alignmentMask + 1);
|
||||
}
|
||||
return offsetPlain(bb, base, offset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static long offsetPlain(AbstractMemorySegmentImpl bb, long base, long offset) {
|
||||
long segment_base = bb.unsafeGetOffset();
|
||||
return segment_base + base + offset;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(VarHandle ob, Object obb, Object encl, long base, long offset) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true);
|
||||
#if[floatingPoint]
|
||||
$rawType$ rawValue = SCOPED_MEMORY_ACCESS.get$RawType$Unaligned(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetPlain(bb, base, offset),
|
||||
handle.be);
|
||||
return $Type$.$rawType$BitsTo$Type$(rawValue);
|
||||
#else[floatingPoint]
|
||||
#if[byte]
|
||||
return SCOPED_MEMORY_ACCESS.get$Type$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetPlain(bb, base, offset));
|
||||
#else[byte]
|
||||
return SCOPED_MEMORY_ACCESS.get$Type$Unaligned(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetPlain(bb, base, offset),
|
||||
handle.be);
|
||||
#end[byte]
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
#if[floatingPoint]
|
||||
SCOPED_MEMORY_ACCESS.put$RawType$Unaligned(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetPlain(bb, base, offset),
|
||||
$Type$.$type$ToRaw$RawType$Bits(value),
|
||||
handle.be);
|
||||
#else[floatingPoint]
|
||||
#if[byte]
|
||||
SCOPED_MEMORY_ACCESS.put$Type$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetPlain(bb, base, offset),
|
||||
value);
|
||||
#else[byte]
|
||||
SCOPED_MEMORY_ACCESS.put$Type$Unaligned(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetPlain(bb, base, offset),
|
||||
value,
|
||||
handle.be);
|
||||
#end[byte]
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(VarHandle ob, Object obb, Object encl, long base, long offset) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true);
|
||||
static $type$ getVolatile(VarHandle ob, Object obb, long base, long offset) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true);
|
||||
return convEndian(handle.be,
|
||||
SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask)));
|
||||
offset(bb, base, offset)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static void setVolatile(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
setVolatile(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
SCOPED_MEMORY_ACCESS.put$RawType$Volatile(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(VarHandle ob, Object obb, Object encl, long base, long offset) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true);
|
||||
static $type$ getAcquire(VarHandle ob, Object obb, long base) {
|
||||
return getAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(VarHandle ob, Object obb, long base, long offset) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true);
|
||||
return convEndian(handle.be,
|
||||
SCOPED_MEMORY_ACCESS.get$RawType$Acquire(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask)));
|
||||
offset(bb, base, offset)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static void setRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
setRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
SCOPED_MEMORY_ACCESS.put$RawType$Release(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(VarHandle ob, Object obb, Object encl, long base, long offset) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true);
|
||||
return convEndian(handle.be,
|
||||
SCOPED_MEMORY_ACCESS.get$RawType$Opaque(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask)));
|
||||
static $type$ getOpaque(VarHandle ob, Object obb, long base) {
|
||||
return getOpaque(ob, obb, base, ((SegmentVarHandle) ob).offset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getOpaque(VarHandle ob, Object obb, long base, long offset) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true);
|
||||
return convEndian(handle.be,
|
||||
SCOPED_MEMORY_ACCESS.get$RawType$Opaque(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offset(bb, base, offset)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
setOpaque(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
SCOPED_MEMORY_ACCESS.put$RawType$Opaque(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static boolean compareAndSet(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||
return compareAndSet(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return SCOPED_MEMORY_ACCESS.compareAndSet$RawType$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchange(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ compareAndExchange(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||
return compareAndExchange(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchange(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return convEndian(handle.be,
|
||||
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ compareAndExchangeAcquire(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||
return compareAndExchangeAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return convEndian(handle.be,
|
||||
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Acquire(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ compareAndExchangeRelease(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||
return compareAndExchangeRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return convEndian(handle.be,
|
||||
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Release(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetPlain(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static boolean weakCompareAndSetPlain(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||
return weakCompareAndSetPlain(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetPlain(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Plain(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static boolean weakCompareAndSet(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||
return weakCompareAndSet(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static boolean weakCompareAndSetAcquire(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||
return weakCompareAndSetAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Acquire(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static boolean weakCompareAndSetRelease(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||
return weakCompareAndSetRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Release(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndSet(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndSet(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return convEndian(handle.be,
|
||||
SCOPED_MEMORY_ACCESS.getAndSet$RawType$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSetAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndSetAcquire(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndSetAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSetAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return convEndian(handle.be,
|
||||
SCOPED_MEMORY_ACCESS.getAndSet$RawType$Acquire(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSetRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndSetRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndSetRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSetRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
return convEndian(handle.be,
|
||||
SCOPED_MEMORY_ACCESS.getAndSet$RawType$Release(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ delta) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndAdd(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndAdd(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(VarHandle ob, Object obb, long base, long offset, $type$ delta) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
delta);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), delta);
|
||||
return getAndAddConvEndianWithCAS(bb, offset(bb, base, offset), delta);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAddAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ delta) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndAddAcquire(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndAddAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAddAcquire(VarHandle ob, Object obb, long base, long offset, $type$ delta) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Acquire(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
delta);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), delta);
|
||||
return getAndAddConvEndianWithCAS(bb, offset(bb, base, offset), delta);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAddRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ delta) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndAddRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndAddRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAddRelease(VarHandle ob, Object obb, long base, long offset, $type$ delta) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Release(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
delta);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), delta);
|
||||
return getAndAddConvEndianWithCAS(bb, offset(bb, base, offset), delta);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
#if[!byte]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAddConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ delta) {
|
||||
|
@ -398,53 +493,82 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
|||
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
||||
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
||||
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
||||
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta)));
|
||||
nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue + delta))));
|
||||
return expectedValue;
|
||||
}
|
||||
#end[byte]
|
||||
#end[AtomicAdd]
|
||||
#if[Bitwise]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseOr(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndBitwiseOr(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndBitwiseOr(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseOr(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
value);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
||||
return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseOrRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndBitwiseOrRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndBitwiseOrRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseOrRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Release(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
value);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
||||
return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndBitwiseOrAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Acquire(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
value);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
||||
return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
#if[!byte]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseOrConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) {
|
||||
|
@ -454,51 +578,81 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
|||
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
||||
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
||||
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
||||
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue | value)));
|
||||
nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue | value))));
|
||||
return expectedValue;
|
||||
}
|
||||
#end[byte]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseAnd(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndBitwiseAnd(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndBitwiseAnd(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseAnd(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
value);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
||||
return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseAndRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndBitwiseAndRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndBitwiseAndRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseAndRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Release(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
value);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
||||
return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndBitwiseAndAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Acquire(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
value);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
||||
return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
#if[!byte]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseAndConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) {
|
||||
|
@ -508,52 +662,80 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
|||
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
||||
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
||||
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
||||
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue & value)));
|
||||
nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue & value))));
|
||||
return expectedValue;
|
||||
}
|
||||
|
||||
#end[byte]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseXor(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndBitwiseXor(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndBitwiseXor(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseXor(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
value);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
||||
return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseXorRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndBitwiseXorRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndBitwiseXorRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseXorRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Release(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
value);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
||||
return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
||||
static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object obb, long base, $type$ value) {
|
||||
return getAndBitwiseXorAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||
#if[!byte]
|
||||
if (handle.be == BE) {
|
||||
#end[byte]
|
||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Acquire(bb.sessionImpl(),
|
||||
bb.unsafeGetBase(),
|
||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
||||
offset(bb, base, offset),
|
||||
value);
|
||||
#if[!byte]
|
||||
} else {
|
||||
return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
||||
return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||
}
|
||||
#end[byte]
|
||||
}
|
||||
#if[!byte]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndBitwiseXorConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) {
|
||||
|
@ -563,8 +745,9 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
|||
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
||||
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
||||
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
||||
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue ^ value)));
|
||||
nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue ^ value))));
|
||||
return expectedValue;
|
||||
}
|
||||
#end[byte]
|
||||
#end[Bitwise]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,8 +27,8 @@ package jdk.internal.access;
|
|||
|
||||
import jdk.internal.foreign.abi.NativeEntryPoint;
|
||||
|
||||
import java.lang.foreign.MemoryLayout;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
@ -75,7 +75,7 @@ public interface JavaLangInvokeAccess {
|
|||
* Used by {@code jdk.internal.foreign.LayoutPath} and
|
||||
* {@code java.lang.invoke.MethodHandles}.
|
||||
*/
|
||||
VarHandle memorySegmentViewHandle(Class<?> carrier, long alignmentMask, ByteOrder order);
|
||||
VarHandle memorySegmentViewHandle(Class<?> carrier, MemoryLayout enclosing, long alignmentMask, ByteOrder order, boolean constantOffset, long offset);
|
||||
|
||||
/**
|
||||
* Var handle carrier combinator.
|
||||
|
|
|
@ -59,6 +59,7 @@ public class LayoutPath {
|
|||
private static final long[] EMPTY_STRIDES = new long[0];
|
||||
private static final long[] EMPTY_BOUNDS = new long[0];
|
||||
private static final MethodHandle[] EMPTY_DEREF_HANDLES = new MethodHandle[0];
|
||||
public static final MemoryLayout.PathElement[] EMPTY_PATH_ELEMENTS = new MemoryLayout.PathElement[0];
|
||||
|
||||
private static final MethodHandle MH_ADD_SCALED_OFFSET;
|
||||
private static final MethodHandle MH_SLICE;
|
||||
|
@ -205,15 +206,13 @@ public class LayoutPath {
|
|||
String.format("Path does not select a value layout: %s", breadcrumbs()));
|
||||
}
|
||||
|
||||
VarHandle handle = Utils.makeRawSegmentViewVarHandle(valueLayout); // (MS, ML, long, long)
|
||||
handle = MethodHandles.insertCoordinates(handle, 1, rootLayout()); // (MS, long, long)
|
||||
if (strides.length > 0) {
|
||||
MethodHandle offsetAdapter = offsetHandle();
|
||||
boolean constantOffset = strides.length == 0;
|
||||
// (MS, long, long) if variable offset, (MS, long) if constant offset
|
||||
VarHandle handle = Utils.makeRawSegmentViewVarHandle(rootLayout(), valueLayout, constantOffset, offset);
|
||||
if (!constantOffset) {
|
||||
MethodHandle offsetAdapter = offsetHandle(); // Adapter performs the bound checks
|
||||
offsetAdapter = MethodHandles.insertArguments(offsetAdapter, 0, 0L);
|
||||
handle = MethodHandles.collectCoordinates(handle, 2, offsetAdapter); // (MS, long)
|
||||
} else {
|
||||
// simpler adaptation
|
||||
handle = MethodHandles.insertCoordinates(handle, 2, offset); // (MS, long)
|
||||
}
|
||||
|
||||
if (adapt) {
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package jdk.internal.foreign;
|
||||
|
@ -34,7 +33,6 @@ import sun.invoke.util.Wrapper;
|
|||
|
||||
import java.lang.foreign.AddressLayout;
|
||||
import java.lang.foreign.MemoryLayout;
|
||||
import java.lang.foreign.MemoryLayout.PathElement;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.StructLayout;
|
||||
import java.lang.foreign.ValueLayout;
|
||||
|
@ -46,6 +44,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
|
@ -56,25 +55,31 @@ public final class Utils {
|
|||
// Suppresses default constructor, ensuring non-instantiability.
|
||||
private Utils() {}
|
||||
|
||||
private static final MethodHandle BYTE_TO_BOOL;
|
||||
private static final MethodHandle BOOL_TO_BYTE;
|
||||
private static final MethodHandle ADDRESS_TO_LONG;
|
||||
private static final Class<?> ADDRESS_CARRIER_TYPE;
|
||||
private static final MethodHandle LONG_TO_CARRIER;
|
||||
private static final MethodHandle LONG_TO_ADDRESS_TARGET;
|
||||
private static final MethodHandle LONG_TO_ADDRESS_NO_TARGET;
|
||||
|
||||
static {
|
||||
try {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
BYTE_TO_BOOL = lookup.findStatic(Utils.class, "byteToBoolean",
|
||||
MethodType.methodType(boolean.class, byte.class));
|
||||
BOOL_TO_BYTE = lookup.findStatic(Utils.class, "booleanToByte",
|
||||
MethodType.methodType(byte.class, boolean.class));
|
||||
ADDRESS_TO_LONG = lookup.findStatic(SharedUtils.class, "unboxSegment",
|
||||
MethodType.methodType(long.class, MemorySegment.class));
|
||||
String unboxSegmentName;
|
||||
Class<?> rawAddressType;
|
||||
if (Unsafe.getUnsafe().addressSize() == 8) {
|
||||
unboxSegmentName = "unboxSegment";
|
||||
rawAddressType = long.class;
|
||||
} else {
|
||||
assert Unsafe.getUnsafe().addressSize() == 4 : Unsafe.getUnsafe().addressSize();
|
||||
unboxSegmentName = "unboxSegment32";
|
||||
rawAddressType = int.class;
|
||||
}
|
||||
ADDRESS_CARRIER_TYPE = rawAddressType;
|
||||
try {
|
||||
LONG_TO_CARRIER = lookup.findStatic(SharedUtils.class, unboxSegmentName,
|
||||
MethodType.methodType(rawAddressType, MemorySegment.class));
|
||||
LONG_TO_ADDRESS_TARGET = lookup.findStatic(Utils.class, "longToAddress",
|
||||
MethodType.methodType(MemorySegment.class, long.class, AddressLayout.class));
|
||||
MethodType.methodType(MemorySegment.class, rawAddressType, AddressLayout.class));
|
||||
LONG_TO_ADDRESS_NO_TARGET = lookup.findStatic(Utils.class, "longToAddress",
|
||||
MethodType.methodType(MemorySegment.class, long.class));
|
||||
MethodType.methodType(MemorySegment.class, rawAddressType));
|
||||
} catch (Throwable ex) {
|
||||
throw new ExceptionInInitializerError(ex);
|
||||
}
|
||||
|
@ -90,48 +95,57 @@ public final class Utils {
|
|||
}
|
||||
|
||||
/**
|
||||
* This method returns a <em>raw var handle</em>, that is, a var handle that does not perform any size
|
||||
* or alignment checks. Such checks are added (using adaptation) by {@link LayoutPath#dereferenceHandle()}.
|
||||
* This method returns a var handle that accesses a target layout in an enclosing layout, taking the memory offset
|
||||
* and the base offset of the enclosing layout in the segment.
|
||||
* <p>
|
||||
* If the offset of the target layout in the enclosing layout is constant, the coordinates are (MS, long).
|
||||
* If the offset of the target layout in the enclosing layout is variable, the coordinates are (MS, long, long).
|
||||
* The trailing long is a pre-validated, variable extra offset, which the var handle does not perform any size or
|
||||
* alignment checks against. Such checks are added (using adaptation) by {@link LayoutPath#dereferenceHandle()}.
|
||||
* <p>
|
||||
* We provide two level of caching of the generated var handles. First, the var handle associated
|
||||
* with a {@link ValueLayout#varHandle()} call is cached inside a stable field of the value layout implementation.
|
||||
* This optimizes common code idioms like {@code JAVA_INT.varHandle().getInt(...)}. A second layer of caching
|
||||
* is then provided by this method: after all, var handles constructed by {@link MemoryLayout#varHandle(PathElement...)}
|
||||
* will be obtained by adapting some raw var handle generated by this method.
|
||||
* is then provided by this method, so different value layouts with same effects can reuse var handle instances.
|
||||
* (The 2nd layer may be redundant in the long run)
|
||||
*
|
||||
* @param layout the value layout for which a raw memory segment var handle is to be created.
|
||||
* @return a raw memory segment var handle.
|
||||
* @param enclosing the enclosing context of the value layout
|
||||
* @param layout the value layout for which a raw memory segment var handle is to be created
|
||||
* @param constantOffset if the VH carries a constant offset instead of taking a variable offset
|
||||
* @param offset the offset if it is a constant
|
||||
* @return a raw memory segment var handle
|
||||
*/
|
||||
public static VarHandle makeRawSegmentViewVarHandle(ValueLayout layout) {
|
||||
final class VarHandleCache {
|
||||
public static VarHandle makeRawSegmentViewVarHandle(MemoryLayout enclosing, ValueLayout layout, boolean constantOffset, long offset) {
|
||||
if (enclosing instanceof ValueLayout direct) {
|
||||
assert direct.equals(layout) && constantOffset && offset == 0;
|
||||
record VarHandleCache() implements Function<ValueLayout, VarHandle> {
|
||||
private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>();
|
||||
private static final VarHandleCache INSTANCE = new VarHandleCache();
|
||||
|
||||
@Override
|
||||
public VarHandle apply(ValueLayout valueLayout) {
|
||||
return Utils.makeRawSegmentViewVarHandleInternal(valueLayout, valueLayout, true, 0);
|
||||
}
|
||||
return VarHandleCache.HANDLE_MAP
|
||||
.computeIfAbsent(layout.withoutName(), Utils::makeRawSegmentViewVarHandleInternal);
|
||||
}
|
||||
return VarHandleCache.HANDLE_MAP.computeIfAbsent(direct.withoutName(), VarHandleCache.INSTANCE);
|
||||
}
|
||||
return makeRawSegmentViewVarHandleInternal(enclosing, layout, constantOffset, offset);
|
||||
}
|
||||
|
||||
private static VarHandle makeRawSegmentViewVarHandleInternal(ValueLayout layout) {
|
||||
private static VarHandle makeRawSegmentViewVarHandleInternal(MemoryLayout enclosing, ValueLayout layout, boolean constantOffset, long offset) {
|
||||
Class<?> baseCarrier = layout.carrier();
|
||||
if (layout.carrier() == MemorySegment.class) {
|
||||
baseCarrier = switch ((int) ValueLayout.ADDRESS.byteSize()) {
|
||||
case Long.BYTES -> long.class;
|
||||
case Integer.BYTES -> int.class;
|
||||
default -> throw new UnsupportedOperationException("Unsupported address layout");
|
||||
};
|
||||
} else if (layout.carrier() == boolean.class) {
|
||||
baseCarrier = byte.class;
|
||||
baseCarrier = ADDRESS_CARRIER_TYPE;
|
||||
}
|
||||
|
||||
VarHandle handle = SharedSecrets.getJavaLangInvokeAccess().memorySegmentViewHandle(baseCarrier,
|
||||
layout.byteAlignment() - 1, layout.order());
|
||||
enclosing, layout.byteAlignment() - 1, layout.order(), constantOffset, offset);
|
||||
|
||||
if (layout.carrier() == boolean.class) {
|
||||
handle = MethodHandles.filterValue(handle, BOOL_TO_BYTE, BYTE_TO_BOOL);
|
||||
} else if (layout instanceof AddressLayout addressLayout) {
|
||||
if (layout instanceof AddressLayout addressLayout) {
|
||||
MethodHandle longToAddressAdapter = addressLayout.targetLayout().isPresent() ?
|
||||
MethodHandles.insertArguments(LONG_TO_ADDRESS_TARGET, 1, addressLayout) :
|
||||
LONG_TO_ADDRESS_NO_TARGET;
|
||||
handle = MethodHandles.filterValue(handle, ADDRESS_TO_LONG, longToAddressAdapter);
|
||||
handle = MethodHandles.filterValue(handle, LONG_TO_CARRIER, longToAddressAdapter);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
@ -149,11 +163,23 @@ public final class Utils {
|
|||
return longToAddress(addr, 0, 1);
|
||||
}
|
||||
|
||||
// 32 bit
|
||||
@ForceInline
|
||||
public static MemorySegment longToAddress(int addr) {
|
||||
return longToAddress(addr, 0, 1);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static MemorySegment longToAddress(long addr, AddressLayout layout) {
|
||||
return longToAddress(addr, pointeeByteSize(layout), pointeeByteAlign(layout));
|
||||
}
|
||||
|
||||
// 32 bit
|
||||
@ForceInline
|
||||
public static MemorySegment longToAddress(int addr, AddressLayout layout) {
|
||||
return longToAddress(addr, pointeeByteSize(layout), pointeeByteAlign(layout));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static MemorySegment longToAddress(long addr, long size, long align) {
|
||||
if (!isAligned(addr, align)) {
|
||||
|
|
|
@ -321,11 +321,20 @@ public final class SharedUtils {
|
|||
}
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static long unboxSegment(MemorySegment segment) {
|
||||
checkNative(segment);
|
||||
return segment.address();
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static int unboxSegment32(MemorySegment segment) {
|
||||
// This cast to 'int' is safe, because we only call this method on 32-bit
|
||||
// platforms, where we know the address of a segment is truncated to 32-bits.
|
||||
// There's a similar cast for 4-byte addresses in Unsafe.putAddress.
|
||||
return (int) unboxSegment(segment);
|
||||
}
|
||||
|
||||
public static void checkExceptions(MethodHandle target) {
|
||||
Class<?>[] exceptions = JLIA.exceptionTypes(target);
|
||||
if (exceptions != null && exceptions.length != 0) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
package jdk.internal.foreign.layout;
|
||||
|
||||
import jdk.internal.foreign.LayoutPath;
|
||||
import jdk.internal.foreign.Utils;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.reflect.CallerSensitive;
|
||||
|
@ -38,10 +39,8 @@ import java.lang.foreign.MemorySegment;
|
|||
import java.lang.foreign.ValueLayout;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as <em>integral</em> types
|
||||
|
@ -159,19 +158,13 @@ public final class ValueLayouts {
|
|||
|
||||
@ForceInline
|
||||
public final VarHandle varHandle() {
|
||||
final class VarHandleCache {
|
||||
private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>();
|
||||
var vh = handle;
|
||||
if (vh == null) {
|
||||
vh = varHandleInternal(LayoutPath.EMPTY_PATH_ELEMENTS);
|
||||
// benign race stable field store is safe because VarHandle is thread safe
|
||||
handle = vh;
|
||||
}
|
||||
if (handle == null) {
|
||||
// this store to stable field is safe, because return value of 'makeMemoryAccessVarHandle' has stable identity
|
||||
handle = VarHandleCache.HANDLE_MAP.computeIfAbsent(self().withoutName(), _ -> varHandleInternal());
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final V self() {
|
||||
return (V) this;
|
||||
return vh;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -33,6 +33,9 @@ import java.lang.invoke.VarHandle;
|
|||
/**
|
||||
* Static factories for certain VarHandle/MethodHandle variants.
|
||||
* <p>
|
||||
* Some methods take no receiver argument. In these cases, the receiver is the
|
||||
* lookup class.
|
||||
* <p>
|
||||
* The methods will throw an {@link InternalError} if the lookup fails.
|
||||
* <p>
|
||||
* Here is an example of how one of these methods could be used:
|
||||
|
@ -63,6 +66,11 @@ public final class MhUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static MethodHandle findVirtual(MethodHandles.Lookup lookup,
|
||||
String name,
|
||||
MethodType type) {
|
||||
return findVirtual(lookup, lookup.lookupClass(), name, type);
|
||||
}
|
||||
|
||||
public static MethodHandle findVirtual(MethodHandles.Lookup lookup,
|
||||
Class<?> refc,
|
||||
|
@ -75,4 +83,21 @@ public final class MhUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static MethodHandle findStatic(MethodHandles.Lookup lookup,
|
||||
String name,
|
||||
MethodType type) {
|
||||
return findStatic(lookup, lookup.lookupClass(), name, type);
|
||||
}
|
||||
|
||||
public static MethodHandle findStatic(MethodHandles.Lookup lookup,
|
||||
Class<?> refc,
|
||||
String name,
|
||||
MethodType type) {
|
||||
try {
|
||||
return lookup.findStatic(refc, name, type);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ import jdk.internal.vm.vector.VectorSupport;
|
|||
* which might be deemed to expensive; in other words, this approach prioritizes the performance of memory access over
|
||||
* that of releasing a shared memory resource.
|
||||
*/
|
||||
public class ScopedMemoryAccess {
|
||||
public final class ScopedMemoryAccess {
|
||||
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ public class TestAccessModes {
|
|||
// access is unaligned
|
||||
assertTrue(segment.maxByteAlignment() < layout.byteAlignment());
|
||||
}
|
||||
assertEquals(varHandle.isAccessModeSupported(mode), compatible);
|
||||
}
|
||||
|
||||
static ValueLayout accessLayout(MemoryLayout layout) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue