9583e3657e
Co-authored-by: Ron Pressler <rpressler@openjdk.org> Co-authored-by: Alan Bateman <alanb@openjdk.org> Co-authored-by: Erik Österlund <eosterlund@openjdk.org> Co-authored-by: Andrew Haley <aph@openjdk.org> Co-authored-by: Rickard Bäckman <rbackman@openjdk.org> Co-authored-by: Markus Grönlund <mgronlun@openjdk.org> Co-authored-by: Leonid Mesnik <lmesnik@openjdk.org> Co-authored-by: Serguei Spitsyn <sspitsyn@openjdk.org> Co-authored-by: Chris Plummer <cjplummer@openjdk.org> Co-authored-by: Coleen Phillimore <coleenp@openjdk.org> Co-authored-by: Robbin Ehn <rehn@openjdk.org> Co-authored-by: Stefan Karlsson <stefank@openjdk.org> Co-authored-by: Thomas Schatzl <tschatzl@openjdk.org> Co-authored-by: Sergey Kuksenko <skuksenko@openjdk.org> Reviewed-by: lancea, eosterlund, rehn, sspitsyn, stefank, tschatzl, dfuchs, lmesnik, dcubed, kevinw, amenkov, dlong, mchung, psandoz, bpb, coleenp, smarks, egahlin, mseledtsov, coffeys, darcy
537 lines
15 KiB
Java
537 lines
15 KiB
Java
/*
|
|
* Copyright (c) 2021, 2022, 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.loom.ring;
|
|
|
|
import java.util.Objects;
|
|
import java.util.concurrent.BlockingQueue;
|
|
import java.util.stream.IntStream;
|
|
|
|
public class Channels {
|
|
|
|
static class DirectChannel<T> implements Channel<T> {
|
|
private final BlockingQueue<T> q;
|
|
|
|
DirectChannel(BlockingQueue<T> q) {
|
|
this.q = q;
|
|
}
|
|
|
|
@Override
|
|
public void send(T e) {
|
|
boolean interrupted = false;
|
|
while (true) {
|
|
try {
|
|
q.put(e);
|
|
break;
|
|
} catch (InterruptedException x) {
|
|
interrupted = true;
|
|
}
|
|
}
|
|
if (interrupted)
|
|
Thread.currentThread().interrupt();
|
|
}
|
|
|
|
@Override
|
|
public T receive() {
|
|
boolean interrupted = false;
|
|
T e;
|
|
while (true) {
|
|
try {
|
|
e = q.take();
|
|
break;
|
|
} catch (InterruptedException x) {
|
|
interrupted = true;
|
|
}
|
|
}
|
|
if (interrupted)
|
|
Thread.currentThread().interrupt();
|
|
return e;
|
|
}
|
|
}
|
|
|
|
static abstract class AbstractStackChannel<T> implements Channel<T> {
|
|
private final BlockingQueue<T> q;
|
|
|
|
protected AbstractStackChannel(BlockingQueue<T> q) {
|
|
this.q = q;
|
|
}
|
|
|
|
public void sendImpl(T e) {
|
|
boolean interrupted = false;
|
|
while (true) {
|
|
try {
|
|
q.put(e);
|
|
break;
|
|
} catch (InterruptedException x) {
|
|
interrupted = true;
|
|
}
|
|
}
|
|
if (interrupted)
|
|
Thread.currentThread().interrupt();
|
|
}
|
|
|
|
public T receiveImpl() {
|
|
boolean interrupted = false;
|
|
T e;
|
|
while (true) {
|
|
try {
|
|
e = q.take();
|
|
break;
|
|
} catch (InterruptedException x) {
|
|
interrupted = true;
|
|
}
|
|
}
|
|
if (interrupted)
|
|
Thread.currentThread().interrupt();
|
|
return e;
|
|
}
|
|
|
|
}
|
|
|
|
public static class ChannelFixedStackI1<T> extends AbstractStackChannel<T> {
|
|
private final int depth;
|
|
private T sendMsg; // store data in heap, not on stack
|
|
private T receiveMsg;
|
|
|
|
public ChannelFixedStackI1(BlockingQueue<T> q, int depth) {
|
|
super(q);
|
|
this.depth = depth;
|
|
}
|
|
|
|
@Override
|
|
public void send(T e) {
|
|
sendMsg = e;
|
|
recursiveSend(depth);
|
|
}
|
|
|
|
@Override
|
|
public T receive() {
|
|
recursiveReceive(depth);
|
|
return receiveMsg;
|
|
}
|
|
|
|
private void recursiveSend(int depth) {
|
|
if (depth == 0) {
|
|
sendImpl(sendMsg);
|
|
} else {
|
|
recursiveSend(depth - 1);
|
|
}
|
|
}
|
|
|
|
private void recursiveReceive(int depth) {
|
|
if (depth == 0) {
|
|
receiveMsg = receiveImpl();
|
|
} else {
|
|
recursiveReceive(depth - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ChannelFixedStackI2<T> extends AbstractStackChannel<T> {
|
|
private final int depth;
|
|
private int x2 = 42;
|
|
private T sendMsg; // store data in heap, not on stack
|
|
private T receiveMsg;
|
|
|
|
public ChannelFixedStackI2(BlockingQueue<T> q, int depth) {
|
|
super(q);
|
|
this.depth = depth;
|
|
}
|
|
|
|
@Override
|
|
public void send(T e) {
|
|
sendMsg = e;
|
|
recursiveSend(depth, x2);
|
|
}
|
|
|
|
@Override
|
|
public T receive() {
|
|
recursiveReceive(depth, x2);
|
|
return receiveMsg;
|
|
}
|
|
|
|
private void recursiveSend(int depth, int x2) {
|
|
if (depth == 0) {
|
|
sendImpl(sendMsg);
|
|
} else {
|
|
recursiveSend(depth - 1, x2 + 1);
|
|
}
|
|
}
|
|
|
|
private void recursiveReceive(int depth, int x2) {
|
|
if (depth == 0) {
|
|
receiveMsg = receiveImpl();
|
|
} else {
|
|
recursiveReceive(depth - 1, x2 + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ChannelFixedStackI4<T> extends AbstractStackChannel<T> {
|
|
private final int depth;
|
|
private int x2 = 42;
|
|
private int x3 = 43;
|
|
private int x4 = 44;
|
|
private T sendMsg; // store data in heap, not on stack
|
|
private T receiveMsg;
|
|
|
|
public ChannelFixedStackI4(BlockingQueue<T> q, int depth) {
|
|
super(q);
|
|
this.depth = depth;
|
|
}
|
|
|
|
@Override
|
|
public void send(T e) {
|
|
sendMsg = e;
|
|
recursiveSend(depth, x2, x3, x4);
|
|
}
|
|
|
|
@Override
|
|
public T receive() {
|
|
recursiveReceive(depth, x2, x3, x4);
|
|
return receiveMsg;
|
|
}
|
|
|
|
private void recursiveSend(int depth, int x2, int x3, int x4) {
|
|
if (depth == 0) {
|
|
sendImpl(sendMsg);
|
|
} else {
|
|
recursiveSend(depth - 1, x2 + 1, x3 + 2, x4 + 3);
|
|
}
|
|
}
|
|
|
|
private void recursiveReceive(int depth, int x2, int x3, int x4) {
|
|
if (depth == 0) {
|
|
receiveMsg = receiveImpl();
|
|
} else {
|
|
recursiveReceive(depth - 1, x2 + 1, x3 + 2, x4 + 3);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ChannelFixedStackI8<T> extends AbstractStackChannel<T> {
|
|
private final int depth;
|
|
private int x2 = 42;
|
|
private int x3 = 43;
|
|
private int x4 = 44;
|
|
private int x5 = 45;
|
|
private int x6 = 46;
|
|
private int x7 = 47;
|
|
private int x8 = 48;
|
|
private T sendMsg; // store data in heap, not on stack
|
|
private T receiveMsg;
|
|
|
|
public ChannelFixedStackI8(BlockingQueue<T> q, int depth) {
|
|
super(q);
|
|
this.depth = depth;
|
|
}
|
|
|
|
@Override
|
|
public void send(T e) {
|
|
sendMsg = e;
|
|
recursiveSend(depth, x2, x3, x4, x5, x6, x7, x8);
|
|
}
|
|
|
|
@Override
|
|
public T receive() {
|
|
recursiveReceive(depth, x2, x3, x4, x5, x6, x7, x8);
|
|
return receiveMsg;
|
|
}
|
|
|
|
private void recursiveSend(int depth, int x2, int x3, int x4, int x5, int x6, int x7, int x8) {
|
|
if (depth == 0) {
|
|
sendImpl(sendMsg);
|
|
} else {
|
|
recursiveSend(depth - 1, x2 + 1, x3 + 2, x4 + 3, x5 + 4, x6 + 5, x7 + 6, x8 + 7);
|
|
}
|
|
}
|
|
|
|
private void recursiveReceive(int depth, int x2, int x3, int x4, int x5, int x6, int x7, int x8) {
|
|
if (depth == 0) {
|
|
receiveMsg = receiveImpl();
|
|
} else {
|
|
recursiveReceive(depth - 1, x2 + 1, x3 + 2, x4 + 3, x5 + 4, x6 + 5, x7 + 6, x8 + 7);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ChannelFixedStackR1<T> extends AbstractStackChannel<T> {
|
|
private final int depth;
|
|
private int x1;
|
|
|
|
public ChannelFixedStackR1(BlockingQueue<T> q, int depth, int start) {
|
|
super(q);
|
|
this.depth = depth;
|
|
x1 = start + 1;
|
|
}
|
|
|
|
@Override
|
|
public void send(T e) {
|
|
recursiveSend(depth, e, Ref.of(x1));
|
|
}
|
|
|
|
@Override
|
|
public T receive() {
|
|
return recursiveReceive(depth, Ref.of(x1));
|
|
}
|
|
|
|
private void recursiveSend(int depth, T msg, Ref x1) {
|
|
if (depth == 0) {
|
|
sendImpl(msg);
|
|
} else {
|
|
recursiveSend(depth - 1, msg, x1.inc());
|
|
}
|
|
}
|
|
|
|
private T recursiveReceive(int depth, Ref x1) {
|
|
if (depth == 0) {
|
|
return receiveImpl();
|
|
} else {
|
|
return recursiveReceive(depth - 1, x1.inc());
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ChannelFixedStackR2<T> extends AbstractStackChannel<T> {
|
|
private final int depth;
|
|
private int x1;
|
|
private int x2;
|
|
|
|
public ChannelFixedStackR2(BlockingQueue<T> q, int depth, int start) {
|
|
super(q);
|
|
this.depth = depth;
|
|
x1 = start + 1;
|
|
x2 = start + 2;
|
|
}
|
|
|
|
@Override
|
|
public void send(T e) {
|
|
recursiveSend(depth, e, Ref.of(x1), Ref.of(x2));
|
|
}
|
|
|
|
@Override
|
|
public T receive() {
|
|
return recursiveReceive(depth, Ref.of(x1), Ref.of(x2));
|
|
}
|
|
|
|
private void recursiveSend(int depth, T msg, Ref x1, Ref x2) {
|
|
if (depth == 0) {
|
|
sendImpl(msg);
|
|
} else {
|
|
recursiveSend(depth - 1, msg, x1.inc(), x2.inc());
|
|
}
|
|
}
|
|
|
|
private T recursiveReceive(int depth, Ref x1, Ref x2) {
|
|
if (depth == 0) {
|
|
return receiveImpl();
|
|
} else {
|
|
return recursiveReceive(depth - 1, x1.inc(), x2.inc());
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ChannelFixedStackR4<T> extends AbstractStackChannel<T> {
|
|
private final int depth;
|
|
private int x1;
|
|
private int x2;
|
|
private int x3;
|
|
private int x4;
|
|
|
|
public ChannelFixedStackR4(BlockingQueue<T> q, int depth, int start) {
|
|
super(q);
|
|
this.depth = depth;
|
|
x1 = start + 1;
|
|
x2 = start + 2;
|
|
x3 = start + 3;
|
|
x4 = start + 4;
|
|
|
|
}
|
|
|
|
@Override
|
|
public void send(T e) {
|
|
recursiveSend(depth, e, Ref.of(x1), Ref.of(x2), Ref.of(x3), Ref.of(x4));
|
|
}
|
|
|
|
@Override
|
|
public T receive() {
|
|
return recursiveReceive(depth, Ref.of(x1), Ref.of(x2), Ref.of(x3), Ref.of(x4));
|
|
}
|
|
|
|
private void recursiveSend(int depth, T msg, Ref x1, Ref x2, Ref x3, Ref x4) {
|
|
if (depth == 0) {
|
|
sendImpl(msg);
|
|
} else {
|
|
recursiveSend(depth - 1, msg, x1.inc(), x2.inc(), x3.inc(), x4.inc());
|
|
}
|
|
}
|
|
|
|
private T recursiveReceive(int depth, Ref x1, Ref x2, Ref x3, Ref x4) {
|
|
if (depth == 0) {
|
|
return receiveImpl();
|
|
} else {
|
|
return recursiveReceive(depth - 1, x1.inc(), x2.inc(), x3.inc(), x4.inc());
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ChannelFixedStackR8<T> extends AbstractStackChannel<T> {
|
|
private final int depth;
|
|
private int x1;
|
|
private int x2;
|
|
private int x3;
|
|
private int x4;
|
|
private int x5;
|
|
private int x6;
|
|
private int x7;
|
|
private int x8;
|
|
|
|
public ChannelFixedStackR8(BlockingQueue<T> q, int depth, int start) {
|
|
super(q);
|
|
this.depth = depth;
|
|
x1 = start + 1;
|
|
x2 = start + 2;
|
|
x3 = start + 3;
|
|
x4 = start + 4;
|
|
x5 = start + 5;
|
|
x6 = start + 6;
|
|
x7 = start + 7;
|
|
x8 = start + 8;
|
|
}
|
|
|
|
@Override
|
|
public void send(T e) {
|
|
recursiveSend(depth, e, Ref.of(x1), Ref.of(x2), Ref.of(x3), Ref.of(x4), Ref.of(x5), Ref.of(x6), Ref.of(x7), Ref.of(x8));
|
|
}
|
|
|
|
@Override
|
|
public T receive() {
|
|
return recursiveReceive(depth, Ref.of(x1), Ref.of(x2), Ref.of(x3), Ref.of(x4), Ref.of(x5), Ref.of(x6), Ref.of(x7), Ref.of(x8));
|
|
}
|
|
|
|
private void recursiveSend(int depth, T msg, Ref x1, Ref x2, Ref x3, Ref x4, Ref x5, Ref x6, Ref x7, Ref x8) {
|
|
if (depth == 0) {
|
|
sendImpl(msg);
|
|
} else {
|
|
recursiveSend(depth - 1, msg, x1.inc(), x2.inc(), x3.inc(), x4.inc(), x5.inc(), x6.inc(), x7.inc(), x8.inc());
|
|
}
|
|
}
|
|
|
|
private T recursiveReceive(int depth, Ref x1, Ref x2, Ref x3, Ref x4, Ref x5, Ref x6, Ref x7, Ref x8) {
|
|
if (depth == 0) {
|
|
return receiveImpl();
|
|
} else {
|
|
return recursiveReceive(depth - 1, x1.inc(), x2.inc(), x3.inc(), x4.inc(), x5.inc(), x6.inc(), x7.inc(), x8.inc());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static class Ref {
|
|
private final int v;
|
|
|
|
Ref(int v) {
|
|
this.v = v;
|
|
}
|
|
|
|
public static Ref of(int v) {
|
|
return ((v >= 0) && (v < CACHE_MAX)) ? cache[v] : new Ref(v);
|
|
}
|
|
|
|
private static final int CACHE_MAX = 1024*2;
|
|
private static final Ref[] cache = IntStream.range(0, CACHE_MAX).mapToObj(Ref::new).toArray(Ref[]::new);
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) return true;
|
|
if (!(o instanceof Ref)) return false;
|
|
Ref ref = (Ref) o;
|
|
return v == ref.v;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(v);
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "Ref{" +
|
|
"v=" + v +
|
|
'}';
|
|
}
|
|
|
|
public Ref inc() {
|
|
return of(v + 1);
|
|
}
|
|
}
|
|
|
|
// static class Ref {
|
|
// private final int v;
|
|
//
|
|
// Ref(int v) {
|
|
// this.v = v;
|
|
// }
|
|
//
|
|
// public static Ref of(int v) {
|
|
// return getRef(new Ref(v));
|
|
// }
|
|
//
|
|
// @CompilerControl(CompilerControl.Mode.DONT_INLINE)
|
|
// private static Ref getRef(Ref x) {
|
|
// Ref y = cache.get(x);
|
|
// return y == null ? x : y;
|
|
// }
|
|
//
|
|
// private static final int CACHE_MAX = 1024*2;
|
|
//
|
|
// private static final Map<Ref, Ref> cache = IntStream.range(0, CACHE_MAX).mapToObj(Ref::new).collect(Collectors.toMap( k -> k, v-> v));
|
|
//
|
|
// @Override
|
|
// public boolean equals(Object o) {
|
|
// if (this == o) return true;
|
|
// if (!(o instanceof Ref)) return false;
|
|
// Ref ref = (Ref) o;
|
|
// return v == ref.v;
|
|
// }
|
|
//
|
|
// @Override
|
|
// public int hashCode() {
|
|
// return Objects.hash(v);
|
|
// }
|
|
//
|
|
// @Override
|
|
// public String toString() {
|
|
// return "Ref{" +
|
|
// "v=" + v +
|
|
// '}';
|
|
// }
|
|
//
|
|
// public Ref inc() {
|
|
// return of(v + 1);
|
|
// }
|
|
// }
|
|
|
|
|
|
}
|