< 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,78 @@
      exception_state()->values_do(f);
    }
  }
  
  ciType* Instruction::exact_type() const {
-   ciType* t =  declared_type();
+   ciType* t = declared_type();
    if (t != nullptr && t->is_klass()) {
      return t->as_klass()->exact_klass();
    }
    return nullptr;
  }
  
+ ciKlass* Instruction::as_loaded_klass_or_null() const {
+   ciType* type = declared_type();
+   if (type != nullptr && type->is_klass()) {
+     ciKlass* klass = type->as_klass();
+     if (klass->is_loaded()) {
+       return klass;
+     }
+   }
+   return nullptr;
+ }
+ 
+ bool Instruction::is_loaded_flat_array() const {
+   if (UseFlatArray) {
+     ciType* type = declared_type();
+     return type != nullptr && type->is_flat_array_klass();
+   }
+   return false;
+ }
+ 
+ bool Instruction::maybe_flat_array() {
+   if (UseFlatArray) {
+     ciType* type = declared_type();
+     if (type != nullptr) {
+       if (type->is_obj_array_klass()) {
+         // TODO 8325106 Fix comment
+         // 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()->flat_in_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
+       // flat array, so we should do a runtime check.
+       return true;
+     }
+   }
+   return false;
+ }
+ 
+ bool Instruction::maybe_null_free_array() {
+   ciType* type = declared_type();
+   if (type != nullptr) {
+     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 != nullptr) {
      state->verify();

@@ -171,11 +234,11 @@
    return nullptr;
  }
  
  ciType* LoadIndexed::exact_type() const {
    ciType* array_type = array()->exact_type();
-   if (array_type != nullptr) {
+   if (delayed() == nullptr && array_type != nullptr) {
      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 +248,37 @@
      }
    }
    return Instruction::exact_type();
  }
  
- 
  ciType* LoadIndexed::declared_type() const {
+   if (delayed() != nullptr) {
+     return delayed()->field()->type();
+   }
    ciType* array_type = array()->declared_type();
    if (array_type == nullptr || !array_type->is_loaded()) {
      return nullptr;
    }
    assert(array_type->is_array_klass(), "what else?");
    ciArrayKlass* ak = (ciArrayKlass*)array_type;
    return ak->element_type();
  }
  
+ bool StoreIndexed::is_exact_flat_array_store() const {
+   if (array()->is_loaded_flat_array() && value()->as_Constant() == nullptr && value()->declared_type() != nullptr) {
+     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 +286,15 @@
  ciType* NewTypeArray::exact_type() const {
    return ciTypeArrayKlass::make(elt_type());
  }
  
  ciType* NewObjectArray::exact_type() const {
-   return ciObjArrayKlass::make(klass());
+   return ciArrayKlass::make(klass());
+ }
+ 
+ ciType* NewMultiArray::exact_type() const {
+   return _klass;
  }
  
  ciType* NewArray::declared_type() const {
    return exact_type();
  }

@@ -317,10 +400,39 @@
      }
    }
  }
  
  
+ 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(nullptr)
+ {
+   set_flag(NeedsWriteBarrierFlag, as_ValueType(field_type())->is_object());
+ #ifdef ASSERT
+   AssertValues assert_value;
+   values_do(&assert_value);
+ #endif
+   pin();
+ }
+ 
+ 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();
+ }
+ 
+ 
  // Implementation of Invoke
  
  
  Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
                 ciMethod* target, ValueStack* state_before)

@@ -343,11 +455,12 @@
    _signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0));
    if (has_receiver()) {
      _signature->append(as_BasicType(receiver()->type()));
    }
    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);
    }
  }
  

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