Skip to content
Permalink
Browse files

Automatic merge of foreign-memaccess into foreign-abi

  • Loading branch information
duke
duke committed May 15, 2020
2 parents c8df5aa + 3487383 commit d4ce7aacc6804bacf50a3829cef639e638c77b6e
@@ -115,33 +115,6 @@
@Override
int hashCode();

/**
* Perform bulk copy from source address to target address. More specifically, the bytes at addresses {@code src}
* through {@code src.addOffset(bytes - 1)} are copied into addresses {@code dst} through {@code dst.addOffset(bytes - 1)}.
* If the source and address ranges overlap, then the copying is performed as if the bytes at addresses {@code src}
* through {@code src.addOffset(bytes - 1)} were first copied into a temporary segment with size {@code bytes},
* and then the contents of the temporary segment were copied into the bytes at addresses {@code dst} through
* {@code dst.addOffset(bytes - 1)}.
* <p>
* The result of a bulk copy is unspecified if, in the uncommon case, the source and target address ranges do not
* overlap, but refer to overlapping regions of the same backing storage using different addresses. For example,
* this may occur if the same file is {@link MemorySegment#mapFromPath mapped} to two segments.
*
* @param src the source address.
* @param dst the target address.
* @param bytes the number of bytes to be copied.
* @throws IndexOutOfBoundsException if {@code bytes < 0}, or if it is greater than the size of the segments
* associated with either {@code src} or {@code dst}.
* @throws IllegalStateException if either the source address or the target address belong to memory segments
* which have been already closed, or if access occurs from a thread other than the thread owning either segment.
* @throws UnsupportedOperationException if either {@code src} or {@code dst} do not feature required access modes;
* more specifically, {@code src} should be associated with a segment with {@link MemorySegment#READ} access mode,
* while {@code dst} should be associated with a segment with {@link MemorySegment#WRITE} access mode.
*/
static void copy(MemoryAddress src, MemoryAddress dst, long bytes) {
MemoryAddressImpl.copy((MemoryAddressImpl)src, (MemoryAddressImpl)dst, bytes);
}

/**
* The <em>unchecked</em> memory address instance modelling the {@code NULL} address. This address is <em>not</em> backed by
* a memory segment and hence it cannot be dereferenced.
@@ -31,6 +31,7 @@
import jdk.internal.foreign.AbstractMemorySegmentImpl;
import jdk.internal.foreign.HeapMemorySegmentImpl;
import jdk.internal.foreign.MappedMemorySegmentImpl;
import jdk.internal.foreign.MemoryAddressImpl;
import jdk.internal.foreign.NativeMemorySegmentImpl;
import jdk.internal.foreign.Utils;

@@ -308,6 +309,29 @@
*/
MemorySegment fill(byte value);

/**
* Perform bulk copy from given source segment to this segment. More specifically, the bytes at
* offset {@code 0} through {@code src.byteSize() - 1} in the source segment are copied into this segment
* at offset {@code 0} through {@code src.byteSize() - 1}.
* If the source segment overlaps with this segment, then the copying is performed as if the bytes at
* offset {@code 0} through {@code src.byteSize() - 1} in the source segment were first copied into a
* temporary segment with size {@code bytes}, and then the contents of the temporary segment were copied into
* this segment at offset {@code 0} through {@code src.byteSize() - 1}.
* <p>
* The result of a bulk copy is unspecified if, in the uncommon case, the source segment does not overlap with
* this segment, but it instead refers to an overlapping regions of the same backing storage using different addresses.
* For example, this may occur if the same file is {@link MemorySegment#mapFromPath mapped} to two segments.
*
* @param src the source segment.
* @throws IndexOutOfBoundsException if {src.byteSize() > this.byteSize()}.
* @throws IllegalStateException if either the source segment or this segment have been already closed,
* or if access occurs from a thread other than the thread owning either segment.
* @throws UnsupportedOperationException if either the source segment or this segment do not feature required access modes;
* more specifically, {@code src} should feature at least the {@link MemorySegment#READ} access mode,
* while this segment should feature at least the {@link MemorySegment#WRITE} access mode.
*/
void copyFrom(MemorySegment src);

/**
* Wraps this segment in a {@link ByteBuffer}. Some of the properties of the returned buffer are linked to
* the properties of this segment. For instance, if this segment is <em>immutable</em>
@@ -121,6 +121,17 @@ public final MemorySegment fill(byte value){
return this;
}

public void copyFrom(MemorySegment src) {
long size = src.byteSize();
((AbstractMemorySegmentImpl)src).checkRange(0, size, true);
checkRange(0, size, false);
long offsetSrc = ((AbstractMemorySegmentImpl) src).min();
long offsetDst = min();
Object baseSrc = ((AbstractMemorySegmentImpl) src).base();
Object baseDst = base();
UNSAFE.copyMemory(baseSrc, offsetSrc, baseDst, offsetDst, size);
}

@Override
@ForceInline
public final MemoryAddress baseAddress() {
@@ -224,7 +235,7 @@ final AbstractMemorySegmentImpl acquire() {
checkIntSize("byte[]");
byte[] arr = new byte[(int)length];
MemorySegment arrSegment = MemorySegment.ofArray(arr);
MemoryAddress.copy(baseAddress(), arrSegment.baseAddress(), length);
arrSegment.copyFrom(this);
return arr;
}

@@ -54,17 +54,6 @@ public MemoryAddressImpl(AbstractMemorySegmentImpl segment, long offset) {
this.offset = offset;
}

public static void copy(MemoryAddressImpl src, MemoryAddressImpl dst, long size) {
src.checkAccess(0, size, true);
dst.checkAccess(0, size, false);
//check disjoint
long offsetSrc = src.unsafeGetOffset();
long offsetDst = dst.unsafeGetOffset();
Object baseSrc = src.unsafeGetBase();
Object baseDst = dst.unsafeGetBase();
UNSAFE.copyMemory(baseSrc, offsetSrc, baseDst, offsetDst, size);
}

// MemoryAddress methods

@Override
@@ -427,7 +427,7 @@ public void testCopyHeapToNative(Consumer<MemoryAddress> checker, Consumer<Memor
try (MemorySegment nativeArray = MemorySegment.allocateNative(bytes);
MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes])) {
initializer.accept(heapArray.baseAddress());
MemoryAddress.copy(heapArray.baseAddress(), nativeArray.baseAddress(), bytes);
nativeArray.copyFrom(heapArray);
checker.accept(nativeArray.baseAddress());
}
}
@@ -439,7 +439,7 @@ public void testCopyNativeToHeap(Consumer<MemoryAddress> checker, Consumer<Memor
try (MemorySegment nativeArray = MemorySegment.allocateNative(seq);
MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes])) {
initializer.accept(nativeArray.baseAddress());
MemoryAddress.copy(nativeArray.baseAddress(), heapArray.baseAddress(), bytes);
heapArray.copyFrom(nativeArray);
checker.accept(heapArray.baseAddress());
}
}
@@ -57,7 +57,7 @@ public void testCopy(SegmentSlice s1, SegmentSlice s2) {
BYTE_HANDLE.set(addr1.addOffset(i), (byte) i);
}
//perform copy
MemoryAddress.copy(addr1, addr2, size);
s2.segment.copyFrom(s1.segment.asSlice(0, size));
//check that copy actually worked
for (int i = 0 ; i < size ; i++) {
assertEquals((byte)i, BYTE_HANDLE.get(addr2.addOffset(i)));
@@ -321,6 +321,7 @@ MemoryLayout make(long size) {
final static List<String> CONFINED_NAMES = List.of(
"close",
"fill",
"copyFrom",
"toByteArray",
"withOwnerThread"
);
@@ -0,0 +1,92 @@
/*
* Copyright (c) 2020, 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.
*
* 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 org.openjdk.bench.jdk.incubator.foreign;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import sun.misc.Unsafe;

import jdk.incubator.foreign.MemorySegment;
import java.util.concurrent.TimeUnit;

import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT;

@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(3)
public class BulkOps {

static final Unsafe unsafe = Utils.unsafe;

static final int ELEM_SIZE = 1_000_000;
static final int CARRIER_SIZE = (int)JAVA_INT.byteSize();
static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE;

static final long unsafe_addr = unsafe.allocateMemory(ALLOC_SIZE);
static final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE);

static final int[] bytes = new int[ELEM_SIZE];
static final MemorySegment bytesSegment = MemorySegment.ofArray(bytes);
static final int UNSAFE_INT_OFFSET = unsafe.arrayBaseOffset(int[].class);

static {
for (int i = 0 ; i < bytes.length ; i++) {
bytes[i] = i;
}
}

@Benchmark
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void unsafe_fill() {
unsafe.setMemory(unsafe_addr, ALLOC_SIZE, (byte)0);
}

@Benchmark
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void segment_fill() {
segment.fill((byte)0);
}

@Benchmark
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void unsafe_copy() {
unsafe.copyMemory(bytes, UNSAFE_INT_OFFSET, null, unsafe_addr, ALLOC_SIZE);
}

@Benchmark
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void segment_copy() {
segment.copyFrom(bytesSegment);
}
}

0 comments on commit d4ce7aa

Please sign in to comment.
You can’t perform that action at this time.