Skip to content

Commit f9799f4

Browse files
committed
8378519: [lworld] Fold fieldDescriptor / ResolvedFieldEntry checks into the FlatFieldPayload constructor
Reviewed-by: fparain
1 parent adb1cb8 commit f9799f4

File tree

9 files changed

+347
-70
lines changed

9 files changed

+347
-70
lines changed

src/hotspot/share/interpreter/interpreterRuntime.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,6 @@ JRT_END
234234

235235
JRT_BLOCK_ENTRY(void, InterpreterRuntime::read_flat_field(JavaThread* current, oopDesc* obj, ResolvedFieldEntry* entry))
236236
assert(oopDesc::is_oop(obj), "Sanity check");
237-
#ifdef ASSERT
238-
InstanceKlass* holder = InstanceKlass::cast(entry->field_holder());
239-
assert(entry->field_holder()->field_is_flat(entry->field_index()), "Sanity check");
240-
fieldDescriptor fd;
241-
bool found = holder->find_field_from_offset(entry->field_offset(), false, &fd);
242-
assert(found, "Field not found");
243-
assert(fd.is_flat(), "Field must be flat");
244-
#endif // ASSERT
245237

246238
FlatFieldPayload payload(instanceOop(obj), entry);
247239
if (payload.is_payload_null()) {

src/hotspot/share/oops/flatArrayKlass.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,13 @@ class FlatArrayKlass : public ObjArrayKlass {
5959

6060
// Casting from Klass*
6161
static FlatArrayKlass* cast(Klass* k) {
62+
return const_cast<FlatArrayKlass*>(cast(const_cast<const Klass*>(k)));
63+
}
64+
65+
static const FlatArrayKlass* cast(const Klass* k) {
66+
assert(k != nullptr, "k should not be null");
6267
assert(k->is_flatArray_klass(), "cast to FlatArrayKlass");
63-
return (FlatArrayKlass*) k;
68+
return static_cast<const FlatArrayKlass*>(k);
6469
}
6570

6671
// klass allocation

src/hotspot/share/oops/instanceKlass.cpp

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
#include "oops/instanceOop.hpp"
7171
#include "oops/instanceStackChunkKlass.hpp"
7272
#include "oops/klass.inline.hpp"
73+
#include "oops/layoutKind.hpp"
7374
#include "oops/markWord.hpp"
7475
#include "oops/method.hpp"
7576
#include "oops/oop.inline.hpp"
@@ -100,6 +101,7 @@
100101
#include "utilities/events.hpp"
101102
#include "utilities/macros.hpp"
102103
#include "utilities/nativeStackPrinter.hpp"
104+
#include "utilities/ostream.hpp"
103105
#include "utilities/stringUtils.hpp"
104106
#ifdef COMPILER1
105107
#include "c1/c1_Compiler.hpp"
@@ -157,6 +159,25 @@ void InlineLayoutInfo::metaspace_pointers_do(MetaspaceClosure* it) {
157159
it->push(&_klass);
158160
}
159161

162+
void InlineLayoutInfo::print() const {
163+
print_on(tty);
164+
}
165+
166+
void InlineLayoutInfo::print_on(outputStream* st) const {
167+
st->print_cr("_klass: " PTR_FORMAT, p2i(_klass));
168+
if (_klass != nullptr) {
169+
StreamIndentor si(st);
170+
_klass->print_on(st);
171+
st->cr();
172+
}
173+
174+
st->print("_layout: ");
175+
LayoutKindHelper::print_on(_kind, st);
176+
st->cr();
177+
178+
st->print("_null_marker_offset: %d", _null_marker_offset);
179+
}
180+
160181
bool InstanceKlass::_finalization_enabled = true;
161182

162183
static inline bool is_class_loader(const Symbol* class_name,
@@ -2177,7 +2198,6 @@ bool InstanceKlass::find_local_field_from_offset(int offset, bool is_static, fie
21772198
return false;
21782199
}
21792200

2180-
21812201
bool InstanceKlass::find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const {
21822202
const InstanceKlass* klass = this;
21832203
while (klass != nullptr) {
@@ -2189,6 +2209,45 @@ bool InstanceKlass::find_field_from_offset(int offset, bool is_static, fieldDesc
21892209
return false;
21902210
}
21912211

2212+
bool InstanceKlass::find_local_flat_field_containing_offset(int offset, fieldDescriptor* fd) const {
2213+
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
2214+
if (!fs.is_flat()) {
2215+
continue;
2216+
}
2217+
2218+
if (fs.offset() > offset) {
2219+
continue;
2220+
}
2221+
2222+
const int offset_in_flat_field = offset - fs.offset();
2223+
const InlineLayoutInfo layout_info = inline_layout_info(fs.index());
2224+
const int field_size = layout_info.klass()->layout_size_in_bytes(layout_info.kind());
2225+
2226+
assert(LayoutKindHelper::is_flat(layout_info.kind()), "Must be flat");
2227+
2228+
if (offset_in_flat_field < field_size) {
2229+
fd->reinitialize(const_cast<InstanceKlass*>(this), fs.to_FieldInfo());
2230+
assert(!fd->is_static(), "Static fields are not flattened");
2231+
2232+
return true;
2233+
}
2234+
}
2235+
2236+
return false;
2237+
}
2238+
2239+
bool InstanceKlass::find_flat_field_containing_offset(int offset, fieldDescriptor* fd) const {
2240+
const InstanceKlass* klass = this;
2241+
while (klass != nullptr) {
2242+
if (klass->find_local_flat_field_containing_offset(offset, fd)) {
2243+
return true;
2244+
}
2245+
2246+
klass = klass->super();
2247+
}
2248+
2249+
return false;
2250+
}
21922251

21932252
void InstanceKlass::methods_do(void f(Method* method)) {
21942253
// Methods aren't stable until they are loaded. This can be read outside

src/hotspot/share/oops/instanceKlass.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ class InlineLayoutInfo : public MetaspaceObj {
169169

170170
static ByteSize klass_offset() { return byte_offset_of(InlineLayoutInfo, _klass); }
171171
static ByteSize null_marker_offset_offset() { return byte_offset_of(InlineLayoutInfo, _null_marker_offset); }
172+
173+
// Print
174+
void print() const;
175+
void print_on(outputStream* st) const;
172176
};
173177

174178
class InstanceKlass: public Klass {
@@ -689,6 +693,9 @@ class InstanceKlass: public Klass {
689693
bool find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
690694
bool find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
691695

696+
bool find_local_flat_field_containing_offset(int offset, fieldDescriptor* fd) const;
697+
bool find_flat_field_containing_offset(int offset, fieldDescriptor* fd) const;
698+
692699
private:
693700
inline static int quick_search(const Array<Method*>* methods, const Symbol* name);
694701

src/hotspot/share/oops/valuePayload.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,10 @@ class ValuePayload {
121121
inline oop& container();
122122
inline oop container() const;
123123

124-
private:
125124
inline void print_on(outputStream* st) const NOT_DEBUG_RETURN;
125+
126+
private:
127+
inline void assert_is_flat_field(const InstanceKlass* klass, int offset) const NOT_DEBUG_RETURN;
126128
inline void assert_post_construction_invariants() const NOT_DEBUG_RETURN;
127129
static inline void assert_pre_copy_invariants(const ValuePayload& src,
128130
const ValuePayload& dst,
@@ -221,6 +223,13 @@ class FlatFieldPayload : public FlatValuePayload {
221223
ptrdiff_t offset,
222224
InlineLayoutInfo* inline_layout_info);
223225

226+
inline void assert_post_construction_invariants(instanceOop container,
227+
ResolvedFieldEntry* resolved_field_entry,
228+
InstanceKlass* klass) const NOT_DEBUG_RETURN;
229+
inline void assert_post_construction_invariants(instanceOop container,
230+
fieldDescriptor* field_descriptor,
231+
InstanceKlass* klass) const NOT_DEBUG_RETURN;
232+
224233
public:
225234
FlatFieldPayload() = default;
226235

src/hotspot/share/oops/valuePayload.inline.hpp

Lines changed: 106 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,47 @@ inline void ValuePayload::print_on(outputStream* st) const {
275275
}
276276
}
277277

278+
inline void ValuePayload::assert_is_flat_field(const InstanceKlass* klass, int offset) const {
279+
OnVMError on_assertion_failure_field_descriptor([&](outputStream* st) {
280+
st->print_cr("=== assert_is_flat_field(" PTR_FORMAT ", %d) failure ===", p2i(klass), offset);
281+
StreamIndentor si(st);
282+
if (klass != nullptr) {
283+
klass->print_on(st);
284+
st->cr();
285+
}
286+
});
287+
288+
fieldDescriptor field_descriptor;
289+
postcond(klass->find_flat_field_containing_offset(offset, &field_descriptor));
290+
291+
const InlineLayoutInfo inline_layout_info = field_descriptor.field_holder()->inline_layout_info(field_descriptor.index());
292+
293+
OnVMError on_assertion_failure_inline_layout_info([&](outputStream* st) {
294+
st->print_cr("=== assert_is_flat_field(" PTR_FORMAT ", %d) failure ===", p2i(klass), offset);
295+
StreamIndentor si(st);
296+
st->print("field_descriptor: ");
297+
field_descriptor.print_on(st);
298+
st->cr();
299+
st->print("inline_layout_info: ");
300+
inline_layout_info.print_on(st);
301+
st->cr();
302+
});
303+
304+
if (inline_layout_info.klass() == this->klass()) {
305+
// Found the field in klass
306+
postcond(offset == field_descriptor.offset());
307+
postcond(inline_layout_info.kind() == layout_kind());
308+
postcond(field_descriptor.layout_kind() == layout_kind());
309+
postcond(field_descriptor.is_flat());
310+
} else {
311+
// Nested flat field
312+
postcond(offset >= field_descriptor.offset());
313+
const InlineKlass* const field_klass = inline_layout_info.klass();
314+
const int payload_offset = field_klass->payload_offset();
315+
assert_is_flat_field(field_klass, offset - field_descriptor.offset() + payload_offset);
316+
}
317+
}
318+
278319
inline void ValuePayload::assert_post_construction_invariants() const {
279320
OnVMError on_assertion_failure([&](outputStream* st) {
280321
st->print_cr("=== assert_post_construction_invariants failure ===");
@@ -283,12 +324,38 @@ inline void ValuePayload::assert_post_construction_invariants() const {
283324
st->cr();
284325
});
285326

286-
postcond(uses_absolute_addr() || container() != nullptr);
287327
postcond(layout_kind() != LayoutKind::REFERENCE);
288328
postcond(layout_kind() != LayoutKind::UNKNOWN);
289329
postcond(klass()->is_layout_supported(layout_kind()));
290-
postcond(uses_absolute_addr() || (container()->klass() == klass()) ==
291-
(layout_kind() == LayoutKind::BUFFERED));
330+
331+
if (!uses_absolute_addr()) {
332+
postcond(container() != nullptr);
333+
const Klass* const container_klass = container()->klass();
334+
if (container_klass == klass()) {
335+
postcond(layout_kind() == LayoutKind::BUFFERED);
336+
} else {
337+
postcond(layout_kind() != LayoutKind::BUFFERED);
338+
if (container_klass->is_mirror_instance_klass()) {
339+
fatal("java.lang.Class has no flat fields. Static fields are not flattened");
340+
} else if (container_klass->is_instance_klass()) {
341+
assert_is_flat_field(InstanceKlass::cast(container_klass), checked_cast<int>(offset()));
342+
} else {
343+
const FlatArrayKlass* const container_flat_array_klass = FlatArrayKlass::cast(container_klass);
344+
if (container_flat_array_klass->element_klass() == klass()) {
345+
postcond(container_flat_array_klass->layout_kind() == layout_kind());
346+
} else {
347+
// Accessing nested flat field
348+
const InlineKlass* const element_klass = container_flat_array_klass->element_klass();
349+
const int element_offset =
350+
(checked_cast<int>(this->offset()) -
351+
checked_cast<int>(flatArrayOopDesc::base_offset_in_bytes())) %
352+
container_flat_array_klass->element_byte_size();
353+
const int payload_offset = element_klass->payload_offset();
354+
assert_is_flat_field(element_klass, element_offset + payload_offset);
355+
}
356+
}
357+
}
358+
}
292359
}
293360

294361
inline void ValuePayload::assert_pre_copy_invariants(const ValuePayload& src,
@@ -525,6 +592,40 @@ inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
525592
InlineLayoutInfo* inline_layout_info)
526593
: FlatValuePayload(container, offset, inline_layout_info->klass(), inline_layout_info->kind()) {}
527594

595+
#ifdef ASSERT
596+
597+
inline void FlatFieldPayload::assert_post_construction_invariants(instanceOop container,
598+
ResolvedFieldEntry* resolved_field_entry,
599+
InstanceKlass* klass) const {
600+
OnVMError on_assertion_failure([&](outputStream* st) {
601+
st->print_cr("=== assert_post_construction_invariants failure ===");
602+
StreamIndentor si(st);
603+
print_on(st);
604+
st->cr();
605+
});
606+
607+
postcond(container->klass()->is_subclass_of(klass));
608+
postcond(klass == resolved_field_entry->field_holder());
609+
postcond(resolved_field_entry->is_flat());
610+
}
611+
612+
inline void FlatFieldPayload::assert_post_construction_invariants(instanceOop container,
613+
fieldDescriptor* field_descriptor,
614+
InstanceKlass* klass) const {
615+
OnVMError on_assertion_failure([&](outputStream* st) {
616+
st->print_cr("=== assert_post_construction_invariants failure ===");
617+
StreamIndentor si(st);
618+
print_on(st);
619+
st->cr();
620+
});
621+
622+
postcond(container->klass()->is_subclass_of(klass));
623+
postcond(klass == field_descriptor->field_holder());
624+
postcond(field_descriptor->is_flat());
625+
}
626+
627+
#endif // ASSERT
628+
528629
inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
529630
fieldDescriptor* field_descriptor)
530631
: FlatFieldPayload(container, field_descriptor,
@@ -536,7 +637,7 @@ inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
536637
: FlatFieldPayload(container,
537638
field_descriptor->offset(),
538639
klass->inline_layout_info_adr(field_descriptor->index())) {
539-
postcond(container->klass() == klass);
640+
assert_post_construction_invariants(container, field_descriptor, klass);
540641
}
541642

542643
inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
@@ -551,7 +652,7 @@ inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
551652
: FlatFieldPayload(container,
552653
resolved_field_entry->field_offset(),
553654
klass->inline_layout_info_adr(resolved_field_entry->field_index())) {
554-
postcond(container->klass()->is_subclass_of(klass));
655+
assert_post_construction_invariants(container, resolved_field_entry, klass);
555656
}
556657

557658
inline instanceOop FlatFieldPayload::container() const {

src/hotspot/share/prims/jni.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1931,7 +1931,8 @@ JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldI
19311931
assert(k->is_instance_klass(), "Only instances can have flat fields");
19321932
InstanceKlass* ik = InstanceKlass::cast(k);
19331933
fieldDescriptor fd;
1934-
ik->find_field_from_offset(offset, false, &fd);
1934+
bool found = ik->find_field_from_offset(offset, false, &fd);
1935+
assert(found, "Field not found");
19351936
FlatFieldPayload payload(instanceOop(o), &fd);
19361937
payload.write(inlineOop(JNIHandles::resolve(value)), CHECK);
19371938
}

0 commit comments

Comments
 (0)