< prev index next >

src/hotspot/share/c1/c1_Instruction.cpp

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -27,10 +27,12 @@
 #include "c1/c1_Instruction.hpp"
 #include "c1/c1_InstructionPrinter.hpp"
 #include "c1/c1_ValueStack.hpp"
 #include "ci/ciObjArrayKlass.hpp"
 #include "ci/ciTypeArrayKlass.hpp"
+#include "ci/ciValueArrayKlass.hpp"
+#include "ci/ciValueKlass.hpp"
 
 
 // Implementation of Instruction
 
 

@@ -110,10 +112,91 @@
     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 (ValueArrayFlatten) {
+    ciType* type = declared_type();
+    if (type != NULL && type->is_value_array_klass()) {
+      ciValueArrayKlass* vak = type->as_value_array_klass();
+      ArrayStorageProperties props = vak->storage_properties();
+      return (!props.is_empty() && props.is_null_free() && props.is_flattened());
+    }
+  }
+
+  return false;
+}
+
+bool Instruction::maybe_flattened_array() {
+  if (ValueArrayFlatten) {
+    ciType* type = declared_type();
+    if (type != NULL) {
+      if (type->is_obj_array_klass()) {
+        // Check for array covariance. One of the following declared types may be a flattened array:
+        ciKlass* element_klass = type->as_obj_array_klass()->element_klass();
+        if (!element_klass->is_loaded() ||
+            element_klass->is_java_lang_Object() ||                                                // (ValueType[] <: Object[])
+            element_klass->is_interface() ||                                                       // (ValueType[] <: <any interface>[])
+            (element_klass->is_valuetype() && element_klass->as_value_klass()->flatten_array())) { // (ValueType[] <: ValueType?[])
+          // We will add a runtime check for flat-ness.
+          return true;
+        }
+      } else if (type->is_value_array_klass()) {
+        ciKlass* element_klass = type->as_value_array_klass()->element_klass();
+        if (!element_klass->is_loaded() ||
+            (element_klass->is_valuetype() && element_klass->as_value_klass()->flatten_array())) { // (ValueType[] <: ValueType?[])
+          // We will add a runtime check for flat-ness.
+          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()) {
+      // Check for array covariance. One of the following declared types may be a null-free array:
+      ciKlass* element_klass = type->as_obj_array_klass()->element_klass();
+      if (!element_klass->is_loaded() ||
+          element_klass->is_java_lang_Object() ||   // (ValueType[] <: Object[])
+          element_klass->is_interface() ||          // (ValueType[] <: <any interface>[])
+          element_klass->is_valuetype()) {          // (ValueType[] <: ValueType?[])
+          // We will add a runtime check for flat-ness.
+          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;
+}
 
 #ifndef PRODUCT
 void Instruction::check_state(ValueStack* state) {
   if (state != NULL) {
     state->verify();

@@ -195,10 +278,24 @@
   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_value_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();
 }
 

@@ -206,11 +303,24 @@
 ciType* NewTypeArray::exact_type() const {
   return ciTypeArrayKlass::make(elt_type());
 }
 
 ciType* NewObjectArray::exact_type() const {
-  return ciObjArrayKlass::make(klass());
+  ciKlass* element_klass = klass();
+  if (is_never_null() && element_klass->is_valuetype()) {
+    if (element_klass->as_value_klass()->flatten_array()) {
+      return ciValueArrayKlass::make(element_klass);
+    } else {
+      return ciObjArrayKlass::make(element_klass, /*never_null =*/true);
+    }
+  } else {
+    return ciObjArrayKlass::make(element_klass);
+  }
+}
+
+ciType* NewMultiArray::exact_type() const {
+  return _klass;
 }
 
 ciType* NewArray::declared_type() const {
   return exact_type();
 }

@@ -221,10 +331,27 @@
 
 ciType* NewInstance::declared_type() const {
   return exact_type();
 }
 
+Value NewValueTypeInstance::depends_on() {
+  if (_depends_on != this) {
+    if (_depends_on->as_NewValueTypeInstance() != NULL) {
+      return _depends_on->as_NewValueTypeInstance()->depends_on();
+    }
+  }
+  return _depends_on;
+}
+
+ciType* NewValueTypeInstance::exact_type() const {
+  return klass();
+}
+
+ciType* NewValueTypeInstance::declared_type() const {
+  return exact_type();
+}
+
 ciType* CheckCast::declared_type() const {
   return klass();
 }
 
 // Implementation of ArithmeticOp

@@ -320,21 +447,22 @@
 
 // Implementation of Invoke
 
 
 Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
-               int vtable_index, ciMethod* target, ValueStack* state_before)
+               int vtable_index, ciMethod* target, ValueStack* state_before, bool never_null)
   : StateSplit(result_type, state_before)
   , _code(code)
   , _recv(recv)
   , _args(args)
   , _vtable_index(vtable_index)
   , _target(target)
 {
   set_flag(TargetIsLoadedFlag,   target->is_loaded());
   set_flag(TargetIsFinalFlag,    target_is_loaded() && target->is_final_method());
   set_flag(TargetIsStrictfpFlag, target_is_loaded() && target->is_strict());
+  set_never_null(never_null);
 
   assert(args != NULL, "args must exist");
 #ifdef ASSERT
   AssertValues assert_value;
   values_do(&assert_value);
< prev index next >