Skip to content

Commit 9014ec2

Browse files
committed
8366973: [lworld] Deopt/recompilation cycle due to call to method with unloaded return type
1 parent 45a451a commit 9014ec2

27 files changed

+301
-112
lines changed

src/hotspot/cpu/aarch64/aarch64.ad

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3707,7 +3707,7 @@ encode %{
37073707
// Check that stack depth is unchanged: find majik cookie on stack
37083708
__ call_Unimplemented();
37093709
}
3710-
if (tf()->returns_inline_type_as_fields() && !_method->is_method_handle_intrinsic()) {
3710+
if (tf()->returns_inline_type_as_fields() && !_method->is_method_handle_intrinsic() && _method->return_type()->is_loaded()) {
37113711
// The last return value is not set by the callee but used to pass the null marker to compiled code.
37123712
// Search for the corresponding projection, get the register and emit code that initialized it.
37133713
uint con = (tf()->range_cc()->cnt() - 1);

src/hotspot/cpu/x86/x86.ad

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2718,7 +2718,7 @@ encode %{
27182718
__ int3();
27192719
__ bind(L);
27202720
}
2721-
if (tf()->returns_inline_type_as_fields() && !_method->is_method_handle_intrinsic()) {
2721+
if (tf()->returns_inline_type_as_fields() && !_method->is_method_handle_intrinsic() && _method->return_type()->is_loaded()) {
27222722
// The last return value is not set by the callee but used to pass the null marker to compiled code.
27232723
// Search for the corresponding projection, get the register and emit code that initialized it.
27242724
uint con = (tf()->range_cc()->cnt() - 1);

src/hotspot/share/ci/ciTypeFlow.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -763,17 +763,7 @@ void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str,
763763
// ever sees a non-null value, loading has occurred.
764764
//
765765
// See do_getstatic() for similar explanation, as well as bug 4684993.
766-
if (InlineTypeReturnedAsFields) {
767-
// Return might be in scalarized form but we can't handle it because we
768-
// don't know the type. This can happen due to a missing preload attribute.
769-
// TODO 8284443 Use PhaseMacroExpand::expand_mh_intrinsic_return for this
770-
trap(str, nullptr,
771-
Deoptimization::make_trap_request
772-
(Deoptimization::Reason_uninitialized,
773-
Deoptimization::Action_reinterpret));
774-
} else {
775-
do_null_assert(return_type->as_klass());
776-
}
766+
do_null_assert(return_type->as_klass());
777767
} else {
778768
push_translate(return_type);
779769
}

src/hotspot/share/classfile/classFileParser.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6173,7 +6173,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
61736173
THROW_MSG(vmSymbols::java_lang_ClassCircularityError(),
61746174
err_msg("Class %s cannot have a null-free non-static field of its own type", _class_name->as_C_string()));
61756175
}
6176-
log_info(class, preload)("Preloading class %s during loading of class %s. "
6176+
log_info(class, preload)("Preloading of class %s during loading of class %s. "
61776177
"Cause: a null-free non-static field is declared with this type",
61786178
s->as_C_string(), _class_name->as_C_string());
61796179
InstanceKlass* klass = SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name, s,
@@ -6194,12 +6194,12 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
61946194
log_info(class, preload)("Preloading of class %s during loading of class %s "
61956195
"(cause: null-free non-static field) succeeded",
61966196
s->as_C_string(), _class_name->as_C_string());
6197-
} else if (Signature::has_envelope(sig)) {
6197+
} else if (Signature::has_envelope(sig) && PreloadClasses) {
61986198
// Preloading classes for nullable fields that are listed in the LoadableDescriptors attribute
61996199
// Those classes would be required later for the flattening of nullable inline type fields
62006200
TempNewSymbol name = Signature::strip_envelope(sig);
62016201
if (name != _class_name && is_class_in_loadable_descriptors_attribute(sig)) {
6202-
log_info(class, preload)("Preloading class %s during loading of class %s. "
6202+
log_info(class, preload)("Preloading of class %s during loading of class %s. "
62036203
"Cause: field type in LoadableDescriptors attribute",
62046204
name->as_C_string(), _class_name->as_C_string());
62056205
oop loader = loader_data()->class_loader();
@@ -6214,7 +6214,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
62146214
name->as_C_string(), _class_name->as_C_string());
62156215
} else {
62166216
// Non value class are allowed by the current spec, but it could be an indication of an issue so let's log a warning
6217-
log_warning(class, preload)("Preloading class %s during loading of class %s "
6217+
log_warning(class, preload)("Preloading of class %s during loading of class %s "
62186218
"(cause: field type in LoadableDescriptors attribute) but loaded class is not a value class",
62196219
name->as_C_string(), _class_name->as_C_string());
62206220
}

src/hotspot/share/classfile/systemDictionary.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,7 @@ bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle
11011101
// Some pre-loading does not fail fatally
11021102
bool SystemDictionary::preload_from_null_free_field(InstanceKlass* ik, Handle class_loader, Symbol* sig, int field_index, TRAPS) {
11031103
TempNewSymbol name = Signature::strip_envelope(sig);
1104-
log_info(class, preload)("Preloading class %s during loading of shared class %s. "
1104+
log_info(class, preload)("Preloading of class %s during loading of shared class %s. "
11051105
"Cause: a null-free non-static field is declared with this type",
11061106
name->as_C_string(), ik->name()->as_C_string());
11071107
InstanceKlass* real_k = SystemDictionary::resolve_with_circularity_detection_or_fail(ik->name(), name,
@@ -1139,7 +1139,7 @@ bool SystemDictionary::preload_from_null_free_field(InstanceKlass* ik, Handle cl
11391139
void SystemDictionary::try_preload_from_loadable_descriptors(InstanceKlass* ik, Handle class_loader, Symbol* sig, int field_index, TRAPS) {
11401140
TempNewSymbol name = Signature::strip_envelope(sig);
11411141
if (name != ik->name() && ik->is_class_in_loadable_descriptors_attribute(sig)) {
1142-
log_info(class, preload)("Preloading class %s during loading of shared class %s. "
1142+
log_info(class, preload)("Preloading of class %s during loading of shared class %s. "
11431143
"Cause: field type in LoadableDescriptors attribute",
11441144
name->as_C_string(), ik->name()->as_C_string());
11451145
InstanceKlass* real_k = SystemDictionary::resolve_with_circularity_detection_or_fail(ik->name(), name,

src/hotspot/share/oops/inlineKlass.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ oop InlineKlass::realloc_result(const RegisterMap& reg_map, const GrowableArray<
596596
// Check if we return an inline type in scalarized form, i.e. check if either
597597
// - The return value is a tagged InlineKlass pointer, or
598598
// - The return value is an inline type oop that is also returned in scalarized form
599-
InlineKlass* InlineKlass::returned_inline_klass(const RegisterMap& map, bool* return_oop) {
599+
InlineKlass* InlineKlass::returned_inline_klass(const RegisterMap& map, bool* return_oop, Method* method) {
600600
BasicType bt = T_METADATA;
601601
VMRegPair pair;
602602
int nb = SharedRuntime::java_return_convention(&bt, &pair, 1);
@@ -619,12 +619,13 @@ InlineKlass* InlineKlass::returned_inline_klass(const RegisterMap& map, bool* re
619619
// Return value is not tagged, must be a valid oop
620620
oop o = cast_to_oop(ptr);
621621
assert(oopDesc::is_oop_or_null(o, true), "Bad oop return: " PTR_FORMAT, ptr);
622-
if (return_oop != nullptr && o != nullptr) {
622+
if (return_oop != nullptr && o != nullptr && o->is_inline_type()) {
623623
// Check if inline type is also returned in scalarized form
624-
assert(o->is_inline_type(), "Invalid return value");
625-
InlineKlass* vk = InlineKlass::cast(o->klass());
626-
if (vk->can_be_returned_as_fields()) {
627-
return vk;
624+
InlineKlass* vk_val = InlineKlass::cast(o->klass());
625+
InlineKlass* vk_sig = method->returns_inline_type();
626+
if (vk_val->can_be_returned_as_fields() && vk_sig != nullptr) {
627+
assert(vk_val == vk_sig, "Unexpected return value");
628+
return vk_val;
628629
}
629630
}
630631
return nullptr;

src/hotspot/share/oops/inlineKlass.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ class InlineKlass: public InstanceKlass {
254254
void save_oop_fields(const RegisterMap& map, GrowableArray<Handle>& handles) const;
255255
void restore_oop_results(RegisterMap& map, GrowableArray<Handle>& handles) const;
256256
oop realloc_result(const RegisterMap& reg_map, const GrowableArray<Handle>& handles, TRAPS);
257-
static InlineKlass* returned_inline_klass(const RegisterMap& reg_map, bool* return_oop = nullptr);
257+
static InlineKlass* returned_inline_klass(const RegisterMap& reg_map, bool* return_oop = nullptr, Method* method = nullptr);
258258

259259
address pack_handler() const {
260260
return *(address*)adr_pack_handler();

src/hotspot/share/oops/instanceKlass.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,7 @@ bool InstanceKlass::link_class_impl(TRAPS) {
10671067
Symbol* sig = fs.signature();
10681068
TempNewSymbol s = Signature::strip_envelope(sig);
10691069
if (s != name()) {
1070-
log_info(class, preload)("Preloading class %s during linking of class %s. Cause: a null-free static field is declared with this type", s->as_C_string(), name()->as_C_string());
1070+
log_info(class, preload)("Preloading of class %s during linking of class %s. Cause: a null-free static field is declared with this type", s->as_C_string(), name()->as_C_string());
10711071
Klass* klass = SystemDictionary::resolve_or_fail(s,
10721072
Handle(THREAD, class_loader()), true,
10731073
CHECK_false);
@@ -1110,14 +1110,14 @@ bool InstanceKlass::link_class_impl(TRAPS) {
11101110
}
11111111

11121112
// Aggressively preloading all classes from the LoadableDescriptors attribute
1113-
if (loadable_descriptors() != nullptr) {
1113+
if (loadable_descriptors() != nullptr && PreloadClasses) {
11141114
HandleMark hm(THREAD);
11151115
for (int i = 0; i < loadable_descriptors()->length(); i++) {
11161116
Symbol* sig = constants()->symbol_at(loadable_descriptors()->at(i));
11171117
if (!Signature::has_envelope(sig)) continue;
11181118
TempNewSymbol class_name = Signature::strip_envelope(sig);
11191119
if (class_name == name()) continue;
1120-
log_info(class, preload)("Preloading class %s during linking of class %s because of the class is listed in the LoadableDescriptors attribute", sig->as_C_string(), name()->as_C_string());
1120+
log_info(class, preload)("Preloading of class %s during linking of class %s because of the class is listed in the LoadableDescriptors attribute", sig->as_C_string(), name()->as_C_string());
11211121
oop loader = class_loader();
11221122
Klass* klass = SystemDictionary::resolve_or_null(class_name,
11231123
Handle(THREAD, loader), THREAD);
@@ -1128,7 +1128,7 @@ bool InstanceKlass::link_class_impl(TRAPS) {
11281128
log_info(class, preload)("Preloading of class %s during linking of class %s (cause: LoadableDescriptors attribute) succeeded", class_name->as_C_string(), name()->as_C_string());
11291129
if (!klass->is_inline_klass()) {
11301130
// Non value class are allowed by the current spec, but it could be an indication of an issue so let's log a warning
1131-
log_warning(class, preload)("Preloading class %s during linking of class %s (cause: LoadableDescriptors attribute) but loaded class is not a value class", class_name->as_C_string(), name()->as_C_string());
1131+
log_warning(class, preload)("Preloading of class %s during linking of class %s (cause: LoadableDescriptors attribute) but loaded class is not a value class", class_name->as_C_string(), name()->as_C_string());
11321132
}
11331133
} else {
11341134
log_warning(class, preload)("Preloading of class %s during linking of class %s (cause: LoadableDescriptors attribute) failed", class_name->as_C_string(), name()->as_C_string());

src/hotspot/share/oops/method.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -737,16 +737,14 @@ int Method::extra_stack_words() {
737737
// InlineKlass the method is declared to return. This must not
738738
// safepoint as it is called with references live on the stack at
739739
// locations the GC is unaware of.
740-
InlineKlass* Method::returns_inline_type(Thread* thread) const {
740+
InlineKlass* Method::returns_inline_type() const {
741741
assert(InlineTypeReturnedAsFields, "Inline types should never be returned as fields");
742742
if (is_native()) {
743743
return nullptr;
744744
}
745745
NoSafepointVerifier nsv;
746746
SignatureStream ss(signature());
747-
while (!ss.at_return_type()) {
748-
ss.next();
749-
}
747+
ss.skip_to_return_type();
750748
return ss.as_inline_klass(method_holder());
751749
}
752750

@@ -1313,7 +1311,7 @@ void Method::link_method(const methodHandle& h_method, TRAPS) {
13131311
SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
13141312
!native_bind_event_is_interesting);
13151313
}
1316-
if (InlineTypeReturnedAsFields && returns_inline_type(THREAD) && !has_scalarized_return()) {
1314+
if (InlineTypeReturnedAsFields && returns_inline_type() && !has_scalarized_return()) {
13171315
set_has_scalarized_return();
13181316
}
13191317

src/hotspot/share/oops/method.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ class Method : public Metadata {
516516
Symbol* klass_name() const; // returns the name of the method holder
517517
BasicType result_type() const { return constMethod()->result_type(); }
518518
bool is_returning_oop() const { BasicType r = result_type(); return is_reference_type(r); }
519-
InlineKlass* returns_inline_type(Thread* thread) const;
519+
InlineKlass* returns_inline_type() const;
520520

521521
// Checked exceptions thrown by this method (resolved to mirrors)
522522
objArrayHandle resolved_checked_exceptions(TRAPS) { return resolved_checked_exceptions_impl(this, THREAD); }

0 commit comments

Comments
 (0)