< prev index next >
src/hotspot/share/opto/memnode.cpp
Print this page
@@ -1846,15 +1846,32 @@
// unsafe field access may not have a constant offset
C->has_unsafe_access(),
"Field accesses must be precise" );
// For oop loads, we expect the _type to be precise.
- // Optimize loads from constant fields.
const TypeInstPtr* tinst = tp->is_instptr();
+ BasicType bt = memory_type();
+
+ // Fold component and value mirror loads
+ ciInstanceKlass* ik = tinst->klass()->as_instance_klass();
+ if (ik == phase->C->env()->Class_klass() && (off == java_lang_Class::component_mirror_offset_in_bytes() ||
+ off == java_lang_Class::value_mirror_offset_in_bytes())) {
+ ciType* mirror_type = tinst->java_mirror_type();
+ if (mirror_type != NULL) {
+ const Type* const_oop = TypePtr::NULL_PTR;
+ if (mirror_type->is_array_klass()) {
+ const_oop = TypeInstPtr::make(mirror_type->as_array_klass()->component_mirror_instance());
+ } else if (mirror_type->is_valuetype()) {
+ const_oop = TypeInstPtr::make(mirror_type->as_value_klass()->value_mirror_instance());
+ }
+ return (bt == T_NARROWOOP) ? const_oop->make_narrowoop() : const_oop;
+ }
+ }
+
+ // Optimize loads from constant fields.
ciObject* const_oop = tinst->const_oop();
if (!is_mismatched_access() && off != Type::OffsetBot && const_oop != NULL && const_oop->is_instance()) {
- BasicType bt = memory_type();
ciType* mirror_type = const_oop->as_instance()->java_mirror_type();
if (mirror_type != NULL && mirror_type->is_valuetype()) {
ciValueKlass* vk = mirror_type->as_value_klass();
if (off == vk->default_value_offset()) {
// Loading a special hidden field that contains the oop of the default value type
@@ -2234,25 +2251,29 @@
}
}
// Check for loading klass from an array
const TypeAryPtr *tary = tp->isa_aryptr();
- if( tary != NULL ) {
+ if (tary != NULL) {
ciKlass *tary_klass = tary->klass();
if (tary_klass != NULL // can be NULL when at BOTTOM or TOP
&& tary->offset() == oopDesc::klass_offset_in_bytes()) {
- if (tary->klass_is_exact()) {
+ ciArrayKlass* ak = tary_klass->as_array_klass();
+ // Do not fold klass loads from [V? because the runtime type might be [V due to [V <: [V?
+ bool can_be_null_free = !tary->is_known_instance() && ak->is_obj_array_klass() && !ak->storage_properties().is_null_free() && ak->element_klass()->is_valuetype();
+
+ if (tary->klass_is_exact() && !can_be_null_free) {
return TypeKlassPtr::make(tary_klass);
}
- ciArrayKlass *ak = tary->klass()->as_array_klass();
+
// If the klass is an object array, we defer the question to the
// array component klass.
- if( ak->is_obj_array_klass() ) {
- assert( ak->is_loaded(), "" );
+ if (ak->is_obj_array_klass() && !can_be_null_free) {
+ assert(ak->is_loaded(), "");
ciKlass *base_k = ak->as_obj_array_klass()->base_element_klass();
- if( base_k->is_loaded() && base_k->is_instance_klass() ) {
- ciInstanceKlass* ik = base_k->as_instance_klass();
+ if (base_k->is_loaded() && base_k->is_instance_klass()) {
+ ciInstanceKlass *ik = base_k->as_instance_klass();
// See if we can become precise: no subklasses and no interface
if (!ik->is_interface() && !ik->has_subklass()) {
//assert(!UseExactTypes, "this code should be useless with exact types");
// Add a dependence; if any subclass added we need to recompile
if (!ik->is_final()) {
@@ -2261,13 +2282,12 @@
// Return precise array klass
return TypeKlassPtr::make(ak);
}
}
return TypeKlassPtr::make(TypePtr::NotNull, ak, Type::Offset(0));
- } else { // Found a type-array?
+ } else if (ak->is_type_array_klass()) {
//assert(!UseExactTypes, "this code should be useless with exact types");
- assert( ak->is_type_array_klass(), "" );
return TypeKlassPtr::make(ak); // These are always precise
}
}
}
@@ -2286,10 +2306,14 @@
// return TypeKlassPtr::make(TypePtr::Constant, elem, 0);
// The array's TypeKlassPtr was declared 'precise' or 'not precise'
// according to the element type's subclassing.
return TypeKlassPtr::make(tkls->ptr(), elem, Type::Offset(0));
+ } else if (klass->is_value_array_klass() &&
+ tkls->offset() == in_bytes(ObjArrayKlass::element_klass_offset())) {
+ ciKlass* elem = klass->as_value_array_klass()->element_klass();
+ return TypeKlassPtr::make(tkls->ptr(), elem, Type::Offset(0));
}
if( klass->is_instance_klass() && tkls->klass_is_exact() &&
tkls->offset() == in_bytes(Klass::super_offset())) {
ciKlass* sup = klass->as_instance_klass()->super();
// The field is Klass::_super. Return its (constant) value.
< prev index next >