Skip to content

Commit da9aa23

Browse files
committed
8279822: CI: Constant pool entries in error state are not supported
Reviewed-by: goetz Backport-of: c5c8c0644d9442846de15422285fffeb91c3e0a1
1 parent fcc1cc6 commit da9aa23

File tree

10 files changed

+403
-90
lines changed

10 files changed

+403
-90
lines changed

src/hotspot/share/ci/bcEscapeAnalyzer.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,11 +416,11 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
416416
// Avoid calling get_constant() which will try to allocate
417417
// unloaded constant. We need only constant's type.
418418
int index = s.get_constant_pool_index();
419-
constantTag tag = s.get_constant_pool_tag(index);
420-
if (tag.is_long() || tag.is_double()) {
419+
BasicType con_bt = s.get_basic_type_for_constant_at(index);
420+
if (con_bt == T_LONG || con_bt == T_DOUBLE) {
421421
// Only longs and doubles use 2 stack slots.
422422
state.lpush();
423-
} else if (tag.basic_type() == T_OBJECT) {
423+
} else if (con_bt == T_OBJECT) {
424424
state.apush(unknown_obj);
425425
} else {
426426
state.spush();

src/hotspot/share/ci/ciConstant.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,17 @@ class ciConstant {
127127
bool is_valid() const {
128128
return basic_type() != T_ILLEGAL;
129129
}
130+
131+
bool is_loaded() const {
132+
if (is_valid()) {
133+
if (is_reference_type(basic_type())) {
134+
return as_object()->is_loaded();
135+
} else {
136+
return true;
137+
}
138+
}
139+
return false;
140+
}
130141
// Debugging output
131142
void print();
132143
};

src/hotspot/share/ci/ciEnv.cpp

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -432,13 +432,6 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
432432
domain = Handle(current, accessing_klass->protection_domain());
433433
}
434434

435-
// setup up the proper type to return on OOM
436-
ciKlass* fail_type;
437-
if (sym->char_at(0) == JVM_SIGNATURE_ARRAY) {
438-
fail_type = _unloaded_ciobjarrayklass;
439-
} else {
440-
fail_type = _unloaded_ciinstance_klass;
441-
}
442435
Klass* found_klass;
443436
{
444437
ttyUnlocker ttyul; // release tty lock to avoid ordering problems
@@ -520,15 +513,14 @@ ciKlass* ciEnv::get_klass_by_index_impl(const constantPoolHandle& cpool,
520513
int index,
521514
bool& is_accessible,
522515
ciInstanceKlass* accessor) {
523-
EXCEPTION_CONTEXT;
524516
Klass* klass = NULL;
525517
Symbol* klass_name = NULL;
526518

527519
if (cpool->tag_at(index).is_symbol()) {
528520
klass_name = cpool->symbol_at(index);
529521
} else {
530522
// Check if it's resolved if it's not a symbol constant pool entry.
531-
klass = ConstantPool::klass_at_if_loaded(cpool, index);
523+
klass = ConstantPool::klass_at_if_loaded(cpool, index);
532524
// Try to look it up by name.
533525
if (klass == NULL) {
534526
klass_name = cpool->klass_name_at(index);
@@ -588,7 +580,6 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
588580
int pool_index, int cache_index,
589581
ciInstanceKlass* accessor) {
590582
bool ignore_will_link;
591-
EXCEPTION_CONTEXT;
592583
int index = pool_index;
593584
if (cache_index >= 0) {
594585
assert(index < 0, "only one kind of index at a time");
@@ -599,12 +590,14 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
599590
return ciConstant(T_OBJECT, get_object(NULL));
600591
}
601592
BasicType bt = T_OBJECT;
602-
if (cpool->tag_at(index).is_dynamic_constant())
593+
if (cpool->tag_at(index).is_dynamic_constant()) {
603594
bt = Signature::basic_type(cpool->uncached_signature_ref_at(index));
604-
if (is_reference_type(bt)) {
605-
} else {
595+
}
596+
if (!is_reference_type(bt)) {
606597
// we have to unbox the primitive value
607-
if (!is_java_primitive(bt)) return ciConstant();
598+
if (!is_java_primitive(bt)) {
599+
return ciConstant();
600+
}
608601
jvalue value;
609602
BasicType bt2 = java_lang_boxing_object::get_value(obj, &value);
610603
assert(bt2 == bt, "");
@@ -639,6 +632,7 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
639632
} else if (tag.is_double()) {
640633
return ciConstant((jdouble)cpool->double_at(index));
641634
} else if (tag.is_string()) {
635+
EXCEPTION_CONTEXT;
642636
oop string = NULL;
643637
assert(cache_index >= 0, "should have a cache index");
644638
string = cpool->string_at(index, cache_index, THREAD);
@@ -655,24 +649,18 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
655649
return ciConstant(T_OBJECT, constant);
656650
}
657651
} else if (tag.is_unresolved_klass_in_error()) {
658-
return ciConstant();
652+
return ciConstant(T_OBJECT, get_unloaded_klass_mirror(NULL));
659653
} else if (tag.is_klass() || tag.is_unresolved_klass()) {
660-
// 4881222: allow ldc to take a class type
661654
ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor);
662-
if (HAS_PENDING_EXCEPTION) {
663-
CLEAR_PENDING_EXCEPTION;
664-
record_out_of_memory_failure();
665-
return ciConstant();
666-
}
667655
assert (klass->is_instance_klass() || klass->is_array_klass(),
668656
"must be an instance or array klass ");
669657
return ciConstant(T_OBJECT, klass->java_mirror());
670-
} else if (tag.is_method_type()) {
658+
} else if (tag.is_method_type() || tag.is_method_type_in_error()) {
671659
// must execute Java code to link this CP entry into cache[i].f1
672660
ciSymbol* signature = get_symbol(cpool->method_type_signature_at(index));
673661
ciObject* ciobj = get_unloaded_method_type_constant(signature);
674662
return ciConstant(T_OBJECT, ciobj);
675-
} else if (tag.is_method_handle()) {
663+
} else if (tag.is_method_handle() || tag.is_method_handle_in_error()) {
676664
// must execute Java code to link this CP entry into cache[i].f1
677665
int ref_kind = cpool->method_handle_ref_kind_at(index);
678666
int callee_index = cpool->method_handle_klass_index_at(index);
@@ -681,10 +669,10 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
681669
ciSymbol* signature = get_symbol(cpool->method_handle_signature_ref_at(index));
682670
ciObject* ciobj = get_unloaded_method_handle_constant(callee, name, signature, ref_kind);
683671
return ciConstant(T_OBJECT, ciobj);
684-
} else if (tag.is_dynamic_constant()) {
685-
return ciConstant();
672+
} else if (tag.is_dynamic_constant() || tag.is_dynamic_constant_in_error()) {
673+
return ciConstant(); // not supported
686674
} else {
687-
ShouldNotReachHere();
675+
assert(false, "unknown tag: %d (%s)", tag.value(), tag.internal_name());
688676
return ciConstant();
689677
}
690678
}

src/hotspot/share/ci/ciStreams.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,14 @@ constantTag ciBytecodeStream::get_constant_pool_tag(int index) const {
251251
return _method->get_Method()->constants()->constant_tag_at(index);
252252
}
253253

254+
// ------------------------------------------------------------------
255+
// ciBytecodeStream::get_basic_type_for_constant_at
256+
//
257+
BasicType ciBytecodeStream::get_basic_type_for_constant_at(int index) const {
258+
VM_ENTRY_MARK;
259+
return _method->get_Method()->constants()->basic_type_for_constant_at(index);
260+
}
261+
254262
// ------------------------------------------------------------------
255263
// ciBytecodeStream::get_field_index
256264
//

src/hotspot/share/ci/ciStreams.hpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class ciBytecodeStream : StackObj {
140140

141141
bool is_wide() const { return ( _pc == _was_wide ); }
142142

143-
// Does this instruction contain an index which refes into the CP cache?
143+
// Does this instruction contain an index which refers into the CP cache?
144144
bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
145145

146146
int get_index_u1() const {
@@ -224,18 +224,27 @@ class ciBytecodeStream : StackObj {
224224
// constant. Do not attempt to resolve it, since that would require
225225
// execution of Java code. If it is not resolved, return an unloaded
226226
// object (ciConstant.as_object()->is_loaded() == false).
227-
ciConstant get_constant();
227+
ciConstant get_constant();
228228
constantTag get_constant_pool_tag(int index) const;
229+
BasicType get_basic_type_for_constant_at(int index) const;
229230

230231
// True if the klass-using bytecode points to an unresolved klass
231232
bool is_unresolved_klass() const {
232233
constantTag tag = get_constant_pool_tag(get_klass_index());
233234
return tag.is_unresolved_klass();
234235
}
235236

236-
bool is_unresolved_klass_in_error() const {
237-
constantTag tag = get_constant_pool_tag(get_klass_index());
238-
return tag.is_unresolved_klass_in_error();
237+
bool is_in_error() const {
238+
assert(cur_bc() == Bytecodes::_ldc ||
239+
cur_bc() == Bytecodes::_ldc_w ||
240+
cur_bc() == Bytecodes::_ldc2_w, "not supported: %s", Bytecodes::name(cur_bc()));
241+
242+
int index = get_constant_pool_index();
243+
constantTag tag = get_constant_pool_tag(index);
244+
return tag.is_unresolved_klass_in_error() ||
245+
tag.is_method_handle_in_error() ||
246+
tag.is_method_type_in_error() ||
247+
tag.is_dynamic_constant_in_error();
239248
}
240249

241250
// If this bytecode is one of get_field, get_static, put_field,

src/hotspot/share/ci/ciTypeFlow.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,11 @@ void ciTypeFlow::StateVector::do_jsr(ciBytecodeStream* str) {
720720
// ------------------------------------------------------------------
721721
// ciTypeFlow::StateVector::do_ldc
722722
void ciTypeFlow::StateVector::do_ldc(ciBytecodeStream* str) {
723+
if (str->is_in_error()) {
724+
trap(str, NULL, Deoptimization::make_trap_request(Deoptimization::Reason_unhandled,
725+
Deoptimization::Action_none));
726+
return;
727+
}
723728
ciConstant con = str->get_constant();
724729
if (con.is_valid()) {
725730
BasicType basic_type = con.basic_type();
@@ -735,14 +740,10 @@ void ciTypeFlow::StateVector::do_ldc(ciBytecodeStream* str) {
735740
push_translate(ciType::make(basic_type));
736741
}
737742
} else {
738-
if (str->is_unresolved_klass_in_error()) {
739-
trap(str, NULL, Deoptimization::make_trap_request(Deoptimization::Reason_unhandled,
740-
Deoptimization::Action_none));
741-
} else {
742-
// OutOfMemoryError in the CI while loading constant
743-
push_null();
744-
outer()->record_failure("ldc did not link");
745-
}
743+
// OutOfMemoryError in the CI while loading constant.
744+
// Unresolved condy also lands here (not yet supported).
745+
push_null();
746+
outer()->record_failure("ldc did not link");
746747
}
747748
}
748749

@@ -2173,7 +2174,7 @@ bool ciTypeFlow::can_trap(ciBytecodeStream& str) {
21732174
case Bytecodes::_ldc:
21742175
case Bytecodes::_ldc_w:
21752176
case Bytecodes::_ldc2_w:
2176-
return str.is_unresolved_klass_in_error();
2177+
return str.is_in_error();
21772178

21782179
case Bytecodes::_aload_0:
21792180
// These bytecodes can trap for rewriting. We need to assume that

src/hotspot/share/oops/constantPool.cpp

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -884,11 +884,9 @@ void ConstantPool::save_and_throw_exception(const constantPoolHandle& this_cp, i
884884

885885
constantTag ConstantPool::constant_tag_at(int which) {
886886
constantTag tag = tag_at(which);
887-
if (tag.is_dynamic_constant() ||
888-
tag.is_dynamic_constant_in_error()) {
887+
if (tag.is_dynamic_constant()) {
889888
BasicType bt = basic_type_for_constant_at(which);
890-
// dynamic constant could return an array, treat as object
891-
return constantTag::ofBasicType(is_reference_type(bt) ? T_OBJECT : bt);
889+
return constantTag(constantTag::type2tag(bt));
892890
}
893891
return tag;
894892
}
@@ -975,7 +973,6 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp,
975973
switch (tag.value()) {
976974

977975
case JVM_CONSTANT_UnresolvedClass:
978-
case JVM_CONSTANT_UnresolvedClassInError:
979976
case JVM_CONSTANT_Class:
980977
{
981978
assert(cache_index == _no_index_sentinel, "should not have been set");
@@ -1043,14 +1040,6 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp,
10431040
result_oop = string_at_impl(this_cp, index, cache_index, CHECK_NULL);
10441041
break;
10451042

1046-
case JVM_CONSTANT_DynamicInError:
1047-
case JVM_CONSTANT_MethodHandleInError:
1048-
case JVM_CONSTANT_MethodTypeInError:
1049-
{
1050-
throw_resolution_error(this_cp, index, CHECK_NULL);
1051-
break;
1052-
}
1053-
10541043
case JVM_CONSTANT_MethodHandle:
10551044
{
10561045
int ref_kind = this_cp->method_handle_ref_kind_at(index);
@@ -1064,11 +1053,14 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp,
10641053
callee_index, name->as_C_string(), signature->as_C_string());
10651054
}
10661055

1067-
Klass* callee = klass_at_impl(this_cp, callee_index, CHECK_NULL);
1056+
Klass* callee = klass_at_impl(this_cp, callee_index, THREAD);
1057+
if (HAS_PENDING_EXCEPTION) {
1058+
save_and_throw_exception(this_cp, index, tag, CHECK_NULL);
1059+
}
10681060

10691061
// Check constant pool method consistency
10701062
if ((callee->is_interface() && m_tag.is_method()) ||
1071-
((!callee->is_interface() && m_tag.is_interface_method()))) {
1063+
(!callee->is_interface() && m_tag.is_interface_method())) {
10721064
ResourceMark rm(THREAD);
10731065
stringStream ss;
10741066
ss.print("Inconsistent constant pool data in classfile for class %s. "
@@ -1080,17 +1072,18 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp,
10801072
index,
10811073
callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef",
10821074
callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef");
1083-
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
1075+
Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IncompatibleClassChangeError(), "%s", ss.as_string());
1076+
save_and_throw_exception(this_cp, index, tag, CHECK_NULL);
10841077
}
10851078

10861079
Klass* klass = this_cp->pool_holder();
10871080
Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind,
10881081
callee, name, signature,
10891082
THREAD);
1090-
result_oop = value();
10911083
if (HAS_PENDING_EXCEPTION) {
10921084
save_and_throw_exception(this_cp, index, tag, CHECK_NULL);
10931085
}
1086+
result_oop = value();
10941087
break;
10951088
}
10961089

@@ -1135,10 +1128,15 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp,
11351128
result_oop = java_lang_boxing_object::create(T_DOUBLE, &prim_value, CHECK_NULL);
11361129
break;
11371130

1131+
case JVM_CONSTANT_UnresolvedClassInError:
1132+
case JVM_CONSTANT_DynamicInError:
1133+
case JVM_CONSTANT_MethodHandleInError:
1134+
case JVM_CONSTANT_MethodTypeInError:
1135+
throw_resolution_error(this_cp, index, CHECK_NULL);
1136+
break;
1137+
11381138
default:
1139-
DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d",
1140-
this_cp(), index, cache_index, tag.value()));
1141-
assert(false, "unexpected constant tag");
1139+
fatal("unexpected constant tag at CP %p[%d/%d] = %d", this_cp(), index, cache_index, tag.value());
11421140
break;
11431141
}
11441142

src/hotspot/share/opto/parse2.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,33 +1876,35 @@ void Parse::do_one_bytecode() {
18761876
case Bytecodes::_bipush: push(intcon(iter().get_constant_u1())); break;
18771877
case Bytecodes::_sipush: push(intcon(iter().get_constant_u2())); break;
18781878
case Bytecodes::_aconst_null: push(null()); break;
1879+
18791880
case Bytecodes::_ldc:
18801881
case Bytecodes::_ldc_w:
1881-
case Bytecodes::_ldc2_w:
1882-
// If the constant is unresolved, run this BC once in the interpreter.
1883-
{
1884-
ciConstant constant = iter().get_constant();
1885-
if (!constant.is_valid() ||
1886-
(constant.basic_type() == T_OBJECT &&
1887-
!constant.as_object()->is_loaded())) {
1888-
int index = iter().get_constant_pool_index();
1889-
constantTag tag = iter().get_constant_pool_tag(index);
1890-
uncommon_trap(Deoptimization::make_trap_request
1891-
(Deoptimization::Reason_unloaded,
1892-
Deoptimization::Action_reinterpret,
1893-
index),
1894-
NULL, tag.internal_name());
1895-
break;
1896-
}
1882+
case Bytecodes::_ldc2_w: {
1883+
ciConstant constant = iter().get_constant();
1884+
if (constant.is_loaded()) {
18971885
assert(constant.basic_type() != T_OBJECT || constant.as_object()->is_instance(),
18981886
"must be java_mirror of klass");
18991887
const Type* con_type = Type::make_from_constant(constant);
19001888
if (con_type != NULL) {
19011889
push_node(con_type->basic_type(), makecon(con_type));
19021890
}
1903-
}
1891+
} else {
1892+
// If the constant is unresolved or in error state, run this BC in the interpreter.
1893+
if (iter().is_in_error()) {
1894+
uncommon_trap(Deoptimization::make_trap_request(Deoptimization::Reason_unhandled,
1895+
Deoptimization::Action_none),
1896+
NULL, "constant in error state", true /* must_throw */);
19041897

1898+
} else {
1899+
int index = iter().get_constant_pool_index();
1900+
uncommon_trap(Deoptimization::make_trap_request(Deoptimization::Reason_unloaded,
1901+
Deoptimization::Action_reinterpret,
1902+
index),
1903+
NULL, "unresolved constant", false /* must_throw */);
1904+
}
1905+
}
19051906
break;
1907+
}
19061908

19071909
case Bytecodes::_aload_0:
19081910
push( local(0) );

0 commit comments

Comments
 (0)