Skip to content

8356255: Add Stable Field Updaters to allow efficient lazy field evaluations #25040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 27 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0e8a854
Initial commit
minborg May 5, 2025
5ecee27
Rename classes
minborg May 5, 2025
6c95aac
Add @Stable for URI and add benchmark
minborg May 5, 2025
2bc67cc
Add examples to doc and fix tests
minborg May 6, 2025
2548d7f
Add copyright header and revert unintended change
minborg May 6, 2025
2fb0cb3
Move raw factories into inner class Raw
minborg May 6, 2025
94b4023
Add unhecked call test
minborg May 6, 2025
a3546a6
Document field alignment assumption
minborg May 6, 2025
33e1779
Address comments
minborg May 6, 2025
52e96c5
Fix raw long updater under 32-bit mode
minborg May 6, 2025
83ce9ac
Add a method handle based field updater
minborg May 7, 2025
0353ff9
Revert changes in public classes
minborg May 7, 2025
4a42b27
Reformat
minborg May 7, 2025
94a9a4e
Merge branch 'master' into stable-updaters
minborg May 7, 2025
6342fbd
Add low level variants
minborg May 7, 2025
a01ba9a
Add convenience methods and documentations
minborg May 7, 2025
de8e238
Reformat
minborg May 7, 2025
e2a2d7b
Add lazy CallSite methods
minborg May 8, 2025
e928591
Revert changes in stable classes
minborg May 8, 2025
1628b26
Add composition of functions and MHs
minborg May 8, 2025
abc0a3b
Merge branch 'master' into stable-updaters
minborg May 9, 2025
ce1b832
Remove unused factories and add comment
minborg May 9, 2025
cbcf13b
Revert unintended change
minborg May 9, 2025
9a58db6
Revert unintended change
minborg May 9, 2025
f6de843
Merge branch 'master' into stable-updaters
minborg May 13, 2025
119cbcf
Wip
minborg May 14, 2025
2df0807
Fix docs
minborg May 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions make/test/BuildMicrobenchmark.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
--add-exports java.base/jdk.internal.classfile.impl=ALL-UNNAMED \
--add-exports java.base/jdk.internal.event=ALL-UNNAMED \
--add-exports java.base/jdk.internal.foreign=ALL-UNNAMED \
--add-exports java.base/jdk.internal.lang.stable=ALL-UNNAMED \
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED \
--add-exports java.base/jdk.internal.util=ALL-UNNAMED \
--add-exports java.base/jdk.internal.vm=ALL-UNNAMED \
Expand Down
23 changes: 16 additions & 7 deletions src/java.base/share/classes/java/lang/reflect/Method.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
package java.lang.reflect;

import jdk.internal.access.SharedSecrets;
import jdk.internal.lang.stable.StableFieldUpdater;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.CallerSensitiveAdapter;
Expand All @@ -47,6 +49,7 @@
import java.lang.annotation.AnnotationFormatError;
import java.nio.ByteBuffer;
import java.util.StringJoiner;
import java.util.function.ToIntFunction;

/**
* A {@code Method} provides information about, and access to, a single method
Expand Down Expand Up @@ -93,7 +96,19 @@ public final class Method extends Executable {
private Method root;
private transient volatile MethodRepository genericInfo;
private @Stable MethodAccessor methodAccessor;

private static final ToIntFunction<Method> HASH_UPDATER =
StableFieldUpdater.Raw.ofInt(Method.class, Unsafe.getUnsafe().objectFieldOffset(Method.class, "hash"), new ToIntFunction<Method>() {
@Override
public int applyAsInt(Method method) {
return method.getDeclaringClass().getName().hashCode() ^ method.getName()
.hashCode();
}
}, 0); // The `hashCode()` is specified so, zeroReplacement is 0
// End shared states

// Used reflectively via HASH_UPDATER
@Stable
private int hash; // not shared right now, eligible if expensive

// Generics infrastructure
Expand Down Expand Up @@ -360,13 +375,7 @@ public boolean equals(Object obj) {
* method's declaring class name and the method's name.
*/
public int hashCode() {
int hc = hash;

if (hc == 0) {
hc = hash = getDeclaringClass().getName().hashCode() ^ getName()
.hashCode();
}
return hc;
return HASH_UPDATER.applyAsInt(this);
}

/**
Expand Down
47 changes: 29 additions & 18 deletions src/java.base/share/classes/java/net/URI.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@
import java.nio.charset.CharacterCodingException;
import java.nio.file.Path;
import java.text.Normalizer;
import java.util.function.ToIntFunction;

import jdk.internal.access.JavaNetUriAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.lang.stable.StableFieldUpdater;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Stable;
import sun.nio.cs.UTF_8;

/**
Expand Down Expand Up @@ -544,6 +549,13 @@ public final class URI
// The remaining fields may be computed on demand, which is safe even in
// the face of multiple threads racing to initialize them
private transient String schemeSpecificPart;

private static final ToIntFunction<URI> HASH_UPDATER = StableFieldUpdater.ofInt(
URI.class, "hash", new ToIntFunction<>() {
@ForceInline @Override public int applyAsInt(URI uri) { return uri.hashCode0(); }}, -1);

// Used reflectively by HASH_UPDATER
@Stable
private transient int hash; // Zero ==> undefined

private transient String decodedUserInfo;
Expand Down Expand Up @@ -1575,25 +1587,24 @@ public boolean equals(Object ob) {
* @return A hash-code value for this URI
*/
public int hashCode() {
int h = hash;
if (h == 0) {
h = hashIgnoringCase(0, scheme);
h = hash(h, fragment);
if (isOpaque()) {
h = hash(h, schemeSpecificPart);
return HASH_UPDATER.applyAsInt(this);
}

private int hashCode0() {
int h = 0;
h = hashIgnoringCase(0, scheme);
h = hash(h, fragment);
if (isOpaque()) {
h = hash(h, schemeSpecificPart);
} else {
h = hash(h, path);
h = hash(h, query);
if (host != null) {
h = hash(h, userInfo);
h = hashIgnoringCase(h, host);
h += 1949 * port;
} else {
h = hash(h, path);
h = hash(h, query);
if (host != null) {
h = hash(h, userInfo);
h = hashIgnoringCase(h, host);
h += 1949 * port;
} else {
h = hash(h, authority);
}
}
if (h != 0) {
hash = h;
h = hash(h, authority);
}
}
return h;
Expand Down
Loading