< prev index next >

src/hotspot/share/ci/ciTypeFlow.cpp

Print this page
*** 23,10 ***
--- 23,11 ---
   */
  
  #include "precompiled.hpp"
  #include "ci/ciConstant.hpp"
  #include "ci/ciField.hpp"
+ #include "ci/ciInlineKlass.hpp"
  #include "ci/ciMethod.hpp"
  #include "ci/ciMethodData.hpp"
  #include "ci/ciObjArrayKlass.hpp"
  #include "ci/ciStreams.hpp"
  #include "ci/ciTypeArrayKlass.hpp"

*** 272,13 ***
    assert(t1 != t2, "checked in caller");
    if (t1->equals(top_type())) {
      return t2;
    } else if (t2->equals(top_type())) {
      return t1;
!   } else if (t1->is_primitive_type() || t2->is_primitive_type()) {
      // Special case null_type.  null_type meet any reference type T
!     // is T.  null_type meet null_type is null_type.
      if (t1->equals(null_type())) {
        if (!t2->is_primitive_type() || t2->equals(null_type())) {
          return t2;
        }
      } else if (t2->equals(null_type())) {
--- 273,23 ---
    assert(t1 != t2, "checked in caller");
    if (t1->equals(top_type())) {
      return t2;
    } else if (t2->equals(top_type())) {
      return t1;
!   }
+   // Unwrap after saving nullness information and handling top meets
+   bool null_free1 = t1->is_null_free();
+   bool null_free2 = t2->is_null_free();
+   if (t1->unwrap() == t2->unwrap() && null_free1 == null_free2) {
+     return t1;
+   }
+   t1 = t1->unwrap();
+   t2 = t2->unwrap();
+ 
+   if (t1->is_primitive_type() || t2->is_primitive_type()) {
      // Special case null_type.  null_type meet any reference type T
!     // is T. null_type meet null_type is null_type.
      if (t1->equals(null_type())) {
        if (!t2->is_primitive_type() || t2->equals(null_type())) {
          return t2;
        }
      } else if (t2->equals(null_type())) {

*** 288,54 ***
      }
  
      // At least one of the two types is a non-top primitive type.
      // The other type is not equal to it.  Fall to bottom.
      return bottom_type();
!   } else {
!     // Both types are non-top non-primitive types.  That is,
!     // both types are either instanceKlasses or arrayKlasses.
!     ciKlass* object_klass = analyzer->env()->Object_klass();
!     ciKlass* k1 = t1->as_klass();
!     ciKlass* k2 = t2->as_klass();
!     if (k1->equals(object_klass) || k2->equals(object_klass)) {
!       return object_klass;
!     } else if (!k1->is_loaded() || !k2->is_loaded()) {
!       // Unloaded classes fall to java.lang.Object at a merge.
!       return object_klass;
!     } else if (k1->is_interface() != k2->is_interface()) {
!       // When an interface meets a non-interface, we get Object;
!       // This is what the verifier does.
!       return object_klass;
!     } else if (k1->is_array_klass() || k2->is_array_klass()) {
!       // When an array meets a non-array, we get Object.
!       // When objArray meets typeArray, we also get Object.
!       // And when typeArray meets different typeArray, we again get Object.
!       // But when objArray meets objArray, we look carefully at element types.
!       if (k1->is_obj_array_klass() && k2->is_obj_array_klass()) {
!         // Meet the element types, then construct the corresponding array type.
!         ciKlass* elem1 = k1->as_obj_array_klass()->element_klass();
!         ciKlass* elem2 = k2->as_obj_array_klass()->element_klass();
!         ciKlass* elem  = type_meet_internal(elem1, elem2, analyzer)->as_klass();
!         // Do an easy shortcut if one type is a super of the other.
!         if (elem == elem1) {
!           assert(k1 == ciObjArrayKlass::make(elem), "shortcut is OK");
!           return k1;
!         } else if (elem == elem2) {
!           assert(k2 == ciObjArrayKlass::make(elem), "shortcut is OK");
!           return k2;
!         } else {
!           return ciObjArrayKlass::make(elem);
!         }
        } else {
!         return object_klass;
        }
      } else {
!       // Must be two plain old instance klasses.
!       assert(k1->is_instance_klass(), "previous cases handle non-instances");
!       assert(k2->is_instance_klass(), "previous cases handle non-instances");
!       return k1->least_common_ancestor(k2);
      }
    }
  }
  
  
  // ------------------------------------------------------------------
--- 299,61 ---
      }
  
      // At least one of the two types is a non-top primitive type.
      // The other type is not equal to it.  Fall to bottom.
      return bottom_type();
!   }
! 
!   // Both types are non-top non-primitive types.  That is,
!   // both types are either instanceKlasses or arrayKlasses.
!   ciKlass* object_klass = analyzer->env()->Object_klass();
!   ciKlass* k1 = t1->as_klass();
!   ciKlass* k2 = t2->as_klass();
!   if (k1->equals(object_klass) || k2->equals(object_klass)) {
!     return object_klass;
!   } else if (!k1->is_loaded() || !k2->is_loaded()) {
!     // Unloaded classes fall to java.lang.Object at a merge.
!     return object_klass;
!   } else if (k1->is_interface() != k2->is_interface()) {
!     // When an interface meets a non-interface, we get Object;
!     // This is what the verifier does.
!     return object_klass;
!   } else if (k1->is_array_klass() || k2->is_array_klass()) {
!     // When an array meets a non-array, we get Object.
!     // When (obj/flat)Array meets typeArray, we also get Object.
!     // And when typeArray meets different typeArray, we again get Object.
!     // But when (obj/flat)Array meets (obj/flat)Array, we look carefully at element types.
!     if ((k1->is_obj_array_klass() || k1->is_flat_array_klass()) &&
!         (k2->is_obj_array_klass() || k2->is_flat_array_klass())) {
!       ciType* elem1 = k1->as_array_klass()->element_klass();
!       ciType* elem2 = k2->as_array_klass()->element_klass();
!       ciType* elem = elem1;
!       if (elem1 != elem2) {
!         elem = type_meet_internal(elem1, elem2, analyzer)->as_klass();
!       }
!       // Do an easy shortcut if one type is a super of the other.
!       if (elem == elem1 && !elem->is_inlinetype()) {
!         assert(k1 == ciArrayKlass::make(elem), "shortcut is OK");
!         return k1;
!       } else if (elem == elem2 && !elem->is_inlinetype()) {
!         assert(k2 == ciArrayKlass::make(elem), "shortcut is OK");
+         return k2;
        } else {
!         return ciArrayKlass::make(elem);
        }
      } else {
!       return object_klass;
!     }
!   } else {
!     // Must be two plain old instance klasses.
+     assert(k1->is_instance_klass(), "previous cases handle non-instances");
+     assert(k2->is_instance_klass(), "previous cases handle non-instances");
+     ciType* result = k1->least_common_ancestor(k2);
+     if (null_free1 && null_free2 && result->is_inlinetype()) {
+       result = analyzer->mark_as_null_free(result);
      }
+     return result;
    }
  }
  
  
  // ------------------------------------------------------------------

*** 393,11 ***
      // even if it were possible for an OSR entry point to be at bci zero.
    }
    // "Push" the method signature into the first few locals.
    state->set_stack_size(-max_locals());
    if (!method()->is_static()) {
!     state->push(method()->holder());
      assert(state->tos() == state->local(0), "");
    }
    for (ciSignatureStream str(method()->signature());
         !str.at_return_type();
         str.next()) {
--- 411,16 ---
      // even if it were possible for an OSR entry point to be at bci zero.
    }
    // "Push" the method signature into the first few locals.
    state->set_stack_size(-max_locals());
    if (!method()->is_static()) {
!     ciType* holder = method()->holder();
+     if (holder->is_inlinetype()) {
+       // The receiver is null-free
+       holder = mark_as_null_free(holder);
+     }
+     state->push(holder);
      assert(state->tos() == state->local(0), "");
    }
    for (ciSignatureStream str(method()->signature());
         !str.at_return_type();
         str.next()) {

*** 543,16 ***
      }
    }
  }
  
  // ------------------------------------------------------------------
! // ciTypeFlow::StateVector::do_aaload
! void ciTypeFlow::StateVector::do_aaload(ciBytecodeStream* str) {
    pop_int();
!   ciObjArrayKlass* array_klass = pop_objArray();
    if (array_klass == nullptr) {
!     // Did aaload on a null reference; push a null and ignore the exception.
      // This instruction will never continue normally.  All we have to do
      // is report a value that will meet correctly with any downstream
      // reference types on paths that will truly be executed.  This null type
      // meets with any reference type to yield that same reference type.
      // (The compiler will generate an unconditional exception here.)
--- 566,16 ---
      }
    }
  }
  
  // ------------------------------------------------------------------
! // ciTypeFlow::StateVector::do_aload
! void ciTypeFlow::StateVector::do_aload(ciBytecodeStream* str) {
    pop_int();
!   ciArrayKlass* array_klass = pop_objOrFlatArray();
    if (array_klass == nullptr) {
!     // Did aload on a null reference; push a null and ignore the exception.
      // This instruction will never continue normally.  All we have to do
      // is report a value that will meet correctly with any downstream
      // reference types on paths that will truly be executed.  This null type
      // meets with any reference type to yield that same reference type.
      // (The compiler will generate an unconditional exception here.)

*** 584,18 ***
  // ciTypeFlow::StateVector::do_checkcast
  void ciTypeFlow::StateVector::do_checkcast(ciBytecodeStream* str) {
    bool will_link;
    ciKlass* klass = str->get_klass(will_link);
    if (!will_link) {
!     // VM's interpreter will not load 'klass' if object is null.
      // Type flow after this block may still be needed in two situations:
      // 1) C2 uses do_null_assert() and continues compilation for later blocks
      // 2) C2 does an OSR compile in a later block (see bug 4778368).
      pop_object();
      do_null_assert(klass);
    } else {
!     pop_object();
      push_object(klass);
    }
  }
  
  // ------------------------------------------------------------------
--- 607,24 ---
  // ciTypeFlow::StateVector::do_checkcast
  void ciTypeFlow::StateVector::do_checkcast(ciBytecodeStream* str) {
    bool will_link;
    ciKlass* klass = str->get_klass(will_link);
    if (!will_link) {
!     // VM's interpreter will not load 'klass' if object is nullptr.
      // Type flow after this block may still be needed in two situations:
      // 1) C2 uses do_null_assert() and continues compilation for later blocks
      // 2) C2 does an OSR compile in a later block (see bug 4778368).
      pop_object();
      do_null_assert(klass);
    } else {
!     ciType* type = pop_value();
+     type = type->unwrap();
+     if (type->is_loaded() && klass->is_loaded() &&
+         type != klass && type->is_subtype_of(klass)) {
+       // Useless cast, propagate more precise type of object
+       klass = type->as_klass();
+     }
      push_object(klass);
    }
  }
  
  // ------------------------------------------------------------------

*** 613,11 ***
    ciField* field = str->get_field(will_link);
    if (!will_link) {
      trap(str, field->holder(), str->get_field_holder_index());
    } else {
      ciType* field_type = field->type();
!     if (!field_type->is_loaded()) {
        // Normally, we need the field's type to be loaded if we are to
        // do anything interesting with its value.
        // We used to do this:  trap(str, str->get_field_signature_index());
        //
        // There is one good reason not to trap here.  Execution can
--- 642,20 ---
    ciField* field = str->get_field(will_link);
    if (!will_link) {
      trap(str, field->holder(), str->get_field_holder_index());
    } else {
      ciType* field_type = field->type();
!     if (field->is_static() && field->is_null_free() &&
+         !field_type->as_instance_klass()->is_initialized()) {
+       // Deoptimize if we load from a static field with an uninitialized inline type
+       // because we need to throw an exception if initialization of the type failed.
+       trap(str, field_type->as_klass(),
+            Deoptimization::make_trap_request
+            (Deoptimization::Reason_unloaded,
+             Deoptimization::Action_reinterpret));
+       return;
+     } else if (!field_type->is_loaded()) {
        // Normally, we need the field's type to be loaded if we are to
        // do anything interesting with its value.
        // We used to do this:  trap(str, str->get_field_signature_index());
        //
        // There is one good reason not to trap here.  Execution can

*** 634,10 ***
--- 672,13 ---
        // here can make an OSR entry point unreachable, triggering the
        // assert on non_osr_block in ciTypeFlow::get_start_state.
        // (See bug 4379915.)
        do_null_assert(field_type->as_klass());
      } else {
+       if (field->is_null_free()) {
+         field_type = outer()->mark_as_null_free(field_type);
+       }
        push_translate(field_type);
      }
    }
  }
  

*** 699,11 ***
          // does not need to be loaded!  The compiler must assume that
          // the value of the unloaded class reference is null; if the code
          // ever sees a non-null value, loading has occurred.
          //
          // See do_getstatic() for similar explanation, as well as bug 4684993.
!         do_null_assert(return_type->as_klass());
        } else {
          push_translate(return_type);
        }
      }
    }
--- 740,21 ---
          // does not need to be loaded!  The compiler must assume that
          // the value of the unloaded class reference is null; if the code
          // ever sees a non-null value, loading has occurred.
          //
          // See do_getstatic() for similar explanation, as well as bug 4684993.
!         if (InlineTypeReturnedAsFields) {
+           // Return might be in scalarized form but we can't handle it because we
+           // don't know the type. This can happen due to a missing preload attribute.
+           // TODO 8284443 Use PhaseMacroExpand::expand_mh_intrinsic_return for this
+           trap(str, nullptr,
+                Deoptimization::make_trap_request
+                (Deoptimization::Reason_uninitialized,
+                 Deoptimization::Action_reinterpret));
+         } else {
+           do_null_assert(return_type->as_klass());
+         }
        } else {
          push_translate(return_type);
        }
      }
    }

*** 731,11 ***
        ciObject* obj = con.as_object();
        if (obj->is_null_object()) {
          push_null();
        } else {
          assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass");
!         push_object(obj->klass());
        }
      } else {
        assert(basic_type == con.basic_type() || con.basic_type() == T_OBJECT,
               "not a boxed form: %s vs %s", type2name(basic_type), type2name(con.basic_type()));
        push_translate(ciType::make(basic_type));
--- 782,15 ---
        ciObject* obj = con.as_object();
        if (obj->is_null_object()) {
          push_null();
        } else {
          assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass");
!         ciType* type = obj->klass();
+         if (type->is_inlinetype()) {
+           type = outer()->mark_as_null_free(type);
+         }
+         push(type);
        }
      } else {
        assert(basic_type == con.basic_type() || con.basic_type() == T_OBJECT,
               "not a boxed form: %s vs %s", type2name(basic_type), type2name(con.basic_type()));
        push_translate(ciType::make(basic_type));

*** 878,17 ***
      tty->print_cr(">> Interpreting bytecode %d:%s", str->cur_bci(),
                    Bytecodes::name(str->cur_bc()));
    }
  
    switch(str->cur_bc()) {
!   case Bytecodes::_aaload: do_aaload(str);                       break;
  
    case Bytecodes::_aastore:
      {
        pop_object();
        pop_int();
!       pop_objArray();
        break;
      }
    case Bytecodes::_aconst_null:
      {
        push_null();
--- 933,17 ---
      tty->print_cr(">> Interpreting bytecode %d:%s", str->cur_bci(),
                    Bytecodes::name(str->cur_bc()));
    }
  
    switch(str->cur_bc()) {
!   case Bytecodes::_aaload: do_aload(str);                           break;
  
    case Bytecodes::_aastore:
      {
        pop_object();
        pop_int();
!       pop_objOrFlatArray();
        break;
      }
    case Bytecodes::_aconst_null:
      {
        push_null();

*** 906,11 ***
        bool will_link;
        ciKlass* element_klass = str->get_klass(will_link);
        if (!will_link) {
          trap(str, element_klass, str->get_klass_index());
        } else {
!         push_object(ciObjArrayKlass::make(element_klass));
        }
        break;
      }
    case Bytecodes::_areturn:
    case Bytecodes::_ifnonnull:
--- 961,11 ---
        bool will_link;
        ciKlass* element_klass = str->get_klass(will_link);
        if (!will_link) {
          trap(str, element_klass, str->get_klass_index());
        } else {
!         push_object(ciArrayKlass::make(element_klass));
        }
        break;
      }
    case Bytecodes::_areturn:
    case Bytecodes::_ifnonnull:

*** 1465,10 ***
--- 1520,11 ---
        ciType* value2 = pop_value();
        push(value1);
        push(value2);
        break;
      }
+ 
    case Bytecodes::_wide:
    default:
      {
        // The iterator should skip this.
        ShouldNotReachHere();

*** 1485,11 ***
  
  #ifndef PRODUCT
  // ------------------------------------------------------------------
  // ciTypeFlow::StateVector::print_cell_on
  void ciTypeFlow::StateVector::print_cell_on(outputStream* st, Cell c) const {
!   ciType* type = type_at(c);
    if (type == top_type()) {
      st->print("top");
    } else if (type == bottom_type()) {
      st->print("bottom");
    } else if (type == null_type()) {
--- 1541,11 ---
  
  #ifndef PRODUCT
  // ------------------------------------------------------------------
  // ciTypeFlow::StateVector::print_cell_on
  void ciTypeFlow::StateVector::print_cell_on(outputStream* st, Cell c) const {
!   ciType* type = type_at(c)->unwrap();
    if (type == top_type()) {
      st->print("top");
    } else if (type == bottom_type()) {
      st->print("bottom");
    } else if (type == null_type()) {

*** 1748,13 ***
            _successors->append_if_missing(block);
          }
          break;
        }
  
!       case Bytecodes::_athrow:     case Bytecodes::_ireturn:
!       case Bytecodes::_lreturn:    case Bytecodes::_freturn:
!       case Bytecodes::_dreturn:    case Bytecodes::_areturn:
        case Bytecodes::_return:
          _successors =
            new (arena) GrowableArray<Block*>(arena, 1, 0, nullptr);
          // No successors
          break;
--- 1804,16 ---
            _successors->append_if_missing(block);
          }
          break;
        }
  
!       case Bytecodes::_athrow:
!       case Bytecodes::_ireturn:
!       case Bytecodes::_lreturn:
+       case Bytecodes::_freturn:
+       case Bytecodes::_dreturn:
+       case Bytecodes::_areturn:
        case Bytecodes::_return:
          _successors =
            new (arena) GrowableArray<Block*>(arena, 1, 0, nullptr);
          // No successors
          break;

*** 3144,10 ***
--- 3203,15 ---
      // Record the first failure reason.
      _failure_reason = reason;
    }
  }
  
+ ciType* ciTypeFlow::mark_as_null_free(ciType* type) {
+   // Wrap the type to carry the information that it is null-free
+   return env()->make_null_free_wrapper(type);
+ }
+ 
  #ifndef PRODUCT
  void ciTypeFlow::print() const       { print_on(tty); }
  
  // ------------------------------------------------------------------
  // ciTypeFlow::print_on
< prev index next >