< prev index next >

src/hotspot/share/c1/c1_Instruction.cpp

Print this page
@@ -25,10 +25,12 @@
  #include "precompiled.hpp"
  #include "c1/c1_IR.hpp"
  #include "c1/c1_Instruction.hpp"
  #include "c1/c1_InstructionPrinter.hpp"
  #include "c1/c1_ValueStack.hpp"
+ #include "ci/ciFlatArrayKlass.hpp"
+ #include "ci/ciInlineKlass.hpp"
  #include "ci/ciObjArrayKlass.hpp"
  #include "ci/ciTypeArrayKlass.hpp"
  #include "utilities/bitMap.inline.hpp"
  
  

@@ -104,17 +106,77 @@
      exception_state()->values_do(f);
    }
  }
  
  ciType* Instruction::exact_type() const {
-   ciType* t =  declared_type();
+   ciType* t = declared_type();
    if (t != NULL && t->is_klass()) {
      return t->as_klass()->exact_klass();
    }
    return NULL;
  }
  
+ ciKlass* Instruction::as_loaded_klass_or_null() const {
+   ciType* type = declared_type();
+   if (type != NULL && type->is_klass()) {
+     ciKlass* klass = type->as_klass();
+     if (klass->is_loaded()) {
+       return klass;
+     }
+   }
+   return NULL;
+ }
+ 
+ bool Instruction::is_loaded_flattened_array() const {
+   if (UseFlatArray) {
+     ciType* type = declared_type();
+     return type != NULL && type->is_flat_array_klass();
+   }
+   return false;
+ }
+ 
+ bool Instruction::maybe_flattened_array() {
+   if (UseFlatArray) {
+     ciType* type = declared_type();
+     if (type != NULL) {
+       if (type->is_obj_array_klass() && !type->as_obj_array_klass()->is_elem_null_free()) {
+         // The runtime type of [LMyValue might be [QMyValue due to [QMyValue <: [LMyValue.
+         ciKlass* element_klass = type->as_obj_array_klass()->element_klass();
+         if (element_klass->can_be_inline_klass() && (!element_klass->is_inlinetype() || element_klass->as_inline_klass()->flatten_array())) {
+           return true;
+         }
+       } else if (type->is_flat_array_klass()) {
+         return true;
+       } else if (type->is_klass() && type->as_klass()->is_java_lang_Object()) {
+         // This can happen as a parameter to System.arraycopy()
+         return true;
+       }
+     } else {
+       // Type info gets lost during Phi merging (Phi, IfOp, etc), but we might be storing into a
+       // flattened array, so we should do a runtime check.
+       return true;
+     }
+   }
+   return false;
+ }
+ 
+ bool Instruction::maybe_null_free_array() {
+   ciType* type = declared_type();
+   if (type != NULL) {
+     if (type->is_obj_array_klass()) {
+       // Due to array covariance, the runtime type might be a null-free array.
+       if (type->as_obj_array_klass()->can_be_inline_array_klass()) {
+         return true;
+       }
+     }
+   } else {
+     // Type info gets lost during Phi merging (Phi, IfOp, etc), but we might be storing into a
+     // null-free array, so we should do a runtime check.
+     return true;
+   }
+   return false;
+ }
  
  #ifndef PRODUCT
  void Instruction::check_state(ValueStack* state) {
    if (state != NULL) {
      state->verify();

@@ -171,11 +233,11 @@
    return NULL;
  }
  
  ciType* LoadIndexed::exact_type() const {
    ciType* array_type = array()->exact_type();
-   if (array_type != NULL) {
+   if (delayed() == NULL && array_type != NULL) {
      assert(array_type->is_array_klass(), "what else?");
      ciArrayKlass* ak = (ciArrayKlass*)array_type;
  
      if (ak->element_type()->is_instance_klass()) {
        ciInstanceKlass* ik = (ciInstanceKlass*)ak->element_type();

@@ -185,21 +247,37 @@
      }
    }
    return Instruction::exact_type();
  }
  
- 
  ciType* LoadIndexed::declared_type() const {
+   if (delayed() != NULL) {
+     return delayed()->field()->type();
+   }
    ciType* array_type = array()->declared_type();
    if (array_type == NULL || !array_type->is_loaded()) {
      return NULL;
    }
    assert(array_type->is_array_klass(), "what else?");
    ciArrayKlass* ak = (ciArrayKlass*)array_type;
    return ak->element_type();
  }
  
+ bool StoreIndexed::is_exact_flattened_array_store() const {
+   if (array()->is_loaded_flattened_array() && value()->as_Constant() == NULL && value()->declared_type() != NULL) {
+     ciKlass* element_klass = array()->declared_type()->as_flat_array_klass()->element_klass();
+     ciKlass* actual_klass = value()->declared_type()->as_klass();
+ 
+     // The following check can fail with inlining:
+     //     void test45_inline(Object[] oa, Object o, int index) { oa[index] = o; }
+     //     void test45(MyValue1[] va, int index, MyValue2 v) { test45_inline(va, v, index); }
+     if (element_klass == actual_klass) {
+       return true;
+     }
+   }
+   return false;
+ }
  
  ciType* LoadField::declared_type() const {
    return field()->type();
  }
  

@@ -207,11 +285,15 @@
  ciType* NewTypeArray::exact_type() const {
    return ciTypeArrayKlass::make(elt_type());
  }
  
  ciType* NewObjectArray::exact_type() const {
-   return ciObjArrayKlass::make(klass());
+   return ciArrayKlass::make(klass(), is_null_free());
+ }
+ 
+ ciType* NewMultiArray::exact_type() const {
+   return _klass;
  }
  
  ciType* NewArray::declared_type() const {
    return exact_type();
  }

@@ -222,10 +304,18 @@
  
  ciType* NewInstance::declared_type() const {
    return exact_type();
  }
  
+ ciType* NewInlineTypeInstance::exact_type() const {
+   return klass();
+ }
+ 
+ ciType* NewInlineTypeInstance::declared_type() const {
+   return exact_type();
+ }
+ 
  ciType* CheckCast::declared_type() const {
    return klass();
  }
  
  // Implementation of ArithmeticOp

@@ -317,23 +407,59 @@
      }
    }
  }
  
  
+ StoreField::StoreField(Value obj, int offset, ciField* field, Value value, bool is_static,
+                        ValueStack* state_before, bool needs_patching)
+   : AccessField(obj, offset, field, is_static, state_before, needs_patching)
+   , _value(value)
+   , _enclosing_field(NULL)
+ {
+   set_flag(NeedsWriteBarrierFlag, as_ValueType(field_type())->is_object());
+ #ifdef ASSERT
+   AssertValues assert_value;
+   values_do(&assert_value);
+ #endif
+   pin();
+   if (value->as_NewInlineTypeInstance() != NULL) {
+     value->as_NewInlineTypeInstance()->set_not_larva_anymore();
+   }
+ }
+ 
+ StoreIndexed::StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value,
+                            ValueStack* state_before, bool check_boolean, bool mismatched)
+   : AccessIndexed(array, index, length, elt_type, state_before, mismatched)
+   , _value(value), _check_boolean(check_boolean)
+ {
+   set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object()));
+   set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object()));
+ #ifdef ASSERT
+   AssertValues assert_value;
+   values_do(&assert_value);
+ #endif
+   pin();
+   if (value->as_NewInlineTypeInstance() != NULL) {
+     value->as_NewInlineTypeInstance()->set_not_larva_anymore();
+   }
+ }
+ 
+ 
  // Implementation of Invoke
  
  
  Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
-                ciMethod* target, ValueStack* state_before)
+                ciMethod* target, ValueStack* state_before, bool null_free)
    : StateSplit(result_type, state_before)
    , _code(code)
    , _recv(recv)
    , _args(args)
    , _target(target)
  {
    set_flag(TargetIsLoadedFlag,   target->is_loaded());
    set_flag(TargetIsFinalFlag,    target_is_loaded() && target->is_final_method());
+   set_null_free(null_free);
  
    assert(args != NULL, "args must exist");
  #ifdef ASSERT
    AssertValues assert_value;
    values_do(&assert_value);

@@ -341,15 +467,22 @@
  
    // provide an initial guess of signature size.
    _signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0));
    if (has_receiver()) {
      _signature->append(as_BasicType(receiver()->type()));
+     if (receiver()->as_NewInlineTypeInstance() != NULL) {
+       receiver()->as_NewInlineTypeInstance()->set_not_larva_anymore();
+     }
    }
    for (int i = 0; i < number_of_arguments(); i++) {
-     ValueType* t = argument_at(i)->type();
+     Value v = argument_at(i);
+     ValueType* t = v->type();
      BasicType bt = as_BasicType(t);
      _signature->append(bt);
+     if (v->as_NewInlineTypeInstance() != NULL) {
+       v->as_NewInlineTypeInstance()->set_not_larva_anymore();
+     }
    }
  }
  
  
  void Invoke::state_values_do(ValueVisitor* f) {

@@ -858,10 +991,12 @@
          Phi* existing_phi = existing_value->as_Phi();
  
          if (new_value != existing_value && (existing_phi == NULL || existing_phi->block() != this)) {
            existing_state->setup_phi_for_stack(this, index);
            TRACE_PHI(tty->print_cr("creating phi-function %c%d for stack %d", existing_state->stack_at(index)->type()->tchar(), existing_state->stack_at(index)->id(), index));
+           if (new_value->as_NewInlineTypeInstance() != NULL) {new_value->as_NewInlineTypeInstance()->set_not_larva_anymore(); }
+           if (existing_value->as_NewInlineTypeInstance() != NULL) {existing_value->as_NewInlineTypeInstance()->set_not_larva_anymore(); }
          }
        }
  
        // create necessary phi functions for locals
        for_each_local_value(existing_state, index, existing_value) {

@@ -872,10 +1007,12 @@
            existing_state->invalidate_local(index);
            TRACE_PHI(tty->print_cr("invalidating local %d because of type mismatch", index));
          } else if (new_value != existing_value && (existing_phi == NULL || existing_phi->block() != this)) {
            existing_state->setup_phi_for_local(this, index);
            TRACE_PHI(tty->print_cr("creating phi-function %c%d for local %d", existing_state->local_at(index)->type()->tchar(), existing_state->local_at(index)->id(), index));
+           if (new_value->as_NewInlineTypeInstance() != NULL) {new_value->as_NewInlineTypeInstance()->set_not_larva_anymore(); }
+           if (existing_value->as_NewInlineTypeInstance() != NULL) {existing_value->as_NewInlineTypeInstance()->set_not_larva_anymore(); }
          }
        }
      }
  
      assert(existing_state->caller_state() == new_state->caller_state(), "caller states must be equal");

@@ -1038,5 +1175,6 @@
  }
  
  void ProfileInvoke::state_values_do(ValueVisitor* f) {
    if (state() != NULL) state()->values_do(f);
  }
+ 
< prev index next >