Trust final fields in records
Christoph Dreis
christoph.dreis at freenet.de
Thu Jun 11 20:38:59 UTC 2020
Hi,
I’ve played around with records the other day and wondered if their (final) fields could be maybe trusted.
This would allow further optimizations to kick in.
E.g. with the following benchmark:
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
public class MyBenchmark {
static final Rectangle rectangle;
static {
rectangle = new Rectangle(1, 1);
}
record Rectangle(int length, int width) {
public int size() {
return length * width;
}
}
@Benchmark public int testSize() { return 1000 / rectangle.size(); }
}
I see the following results when I apply the attached patch:
Benchmark Mode Cnt Score Error Units
MyBenchmark.testSizeBefore avgt 10 3,873 ± 0,044 ns/op
MyBenchmark.testSizePatched avgt 10 1,740 ± 0,058 ns/op
After all, records state that they are "shallowly immutable" - whatever " shallowly" means here.
The risk that I see here is that people could still use reflection on records to change fields - for reasons.
Maybe that aspect could be tightened though before records go non-experimental in favor of the optimization?
I wonder if this could be considered. If so, I would highly appreciate it if someone can sponsor the patch.
Let me know what you think.
Cheers,
Christoph
===== PATCH =====
diff -r 984fde9a0b7f src/hotspot/share/ci/ciField.cpp
--- a/src/hotspot/share/ci/ciField.cpp Tue Jun 09 16:22:54 2020 +0000
+++ b/src/hotspot/share/ci/ciField.cpp Thu Jun 11 22:25:02 2020 +0200
@@ -231,6 +231,9 @@
// Trust final fields in all boxed classes
if (holder->is_box_klass())
return true;
+ // Trust final fields in records
+ if (holder->is_record())
+ return true;
// Trust final fields in String
if (holder->name() == ciSymbol::java_lang_String())
return true;
diff -r 984fde9a0b7f src/hotspot/share/ci/ciInstanceKlass.cpp
--- a/src/hotspot/share/ci/ciInstanceKlass.cpp Tue Jun 09 16:22:54 2020 +0000
+++ b/src/hotspot/share/ci/ciInstanceKlass.cpp Thu Jun 11 22:25:02 2020 +0200
@@ -64,6 +64,7 @@
_has_nonstatic_concrete_methods = ik->has_nonstatic_concrete_methods();
_is_unsafe_anonymous = ik->is_unsafe_anonymous();
_is_hidden = ik->is_hidden();
+ _is_record = ik->is_record();
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
_has_injected_fields = -1;
_implementor = NULL; // we will fill these lazily
@@ -125,6 +126,7 @@
_has_injected_fields = -1;
_is_unsafe_anonymous = false;
_is_hidden = false;
+ _is_record = false;
_loader = loader;
_protection_domain = protection_domain;
_is_shared = false;
diff -r 984fde9a0b7f src/hotspot/share/ci/ciInstanceKlass.hpp
--- a/src/hotspot/share/ci/ciInstanceKlass.hpp Tue Jun 09 16:22:54 2020 +0000
+++ b/src/hotspot/share/ci/ciInstanceKlass.hpp Thu Jun 11 22:25:02 2020 +0200
@@ -57,6 +57,7 @@
bool _has_nonstatic_concrete_methods;
bool _is_unsafe_anonymous;
bool _is_hidden;
+ bool _is_record;
ciFlags _flags;
jint _nonstatic_field_size;
@@ -200,6 +201,10 @@
return _is_hidden;
}
+ bool is_record() const {
+ return _is_record;
+ }
+
ciInstanceKlass* get_canonical_holder(int offset);
ciField* get_field_by_offset(int field_offset, bool is_static);
ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static);
More information about the hotspot-runtime-dev
mailing list