< 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
 
 

@@ -111,10 +113,75 @@
   }
   return NULL;
 }
 
 
+// FIXME -- this is used by ValueStack::merge_types only. We should remove this function
+// and use a better way for handling phi nodes.
+bool Instruction::is_flattened_array() const {
+  if (ValueArrayFlatten) {
+    ciType* type = declared_type();
+    if (type != NULL && type->is_value_array_klass()) {
+      ciValueKlass* element_klass = type->as_value_array_klass()->element_klass()->as_value_klass();
+      assert(element_klass->is_loaded(), "ciValueKlasses are always loaded");
+      if (element_klass->flatten_array()) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+bool Instruction::is_loaded_flattened_array() const {
+  if (ValueArrayFlatten) {
+    ciType* type = declared_type();
+    if (type != NULL && type->is_value_array_klass()) {
+      ciValueKlass* element_klass = type->as_value_array_klass()->element_klass()->as_value_klass();
+      assert(element_klass->is_loaded(), "ciValueKlasses are always loaded");
+      if (element_klass->flatten_array()) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+bool Instruction::maybe_flattened_array() {
+  if (ValueArrayFlatten) {
+    ciType* type = declared_type();
+    if (type != NULL) {
+      if (type->is_value_array_klass()) {
+        ciValueKlass* element_klass = type->as_value_array_klass()->element_klass()->as_value_klass();
+        assert(element_klass->is_loaded(), "ciValueKlasses are always loaded");
+        if (element_klass->flatten_array()) {
+          return true;
+        }
+      } else if (type->is_obj_array_klass()) {
+        ciKlass* element_klass = type->as_obj_array_klass()->element_klass();
+        if (!element_klass->is_loaded() || element_klass->is_java_lang_Object() || element_klass->is_interface()) {
+          // Array covariance:
+          //    (ValueType[] <: Object[])
+          //    (ValueType[] <: <any interface>[])
+          // 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 if (as_Phi() != NULL) {
+      // Type info gets lost during Phi merging, 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 +262,20 @@
   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) {
+    ciKlass* element_klass = array()->declared_type()->as_value_array_klass()->element_klass();
+    ciKlass* actual_klass = value()->declared_type()->as_klass();
+    if (element_klass == actual_klass) {
+      return true;
+    }
+  }
+  return false;
+}
 
 ciType* LoadField::declared_type() const {
   return field()->type();
 }
 

@@ -206,11 +283,20 @@
 ciType* NewTypeArray::exact_type() const {
   return ciTypeArrayKlass::make(elt_type());
 }
 
 ciType* NewObjectArray::exact_type() const {
-  return ciObjArrayKlass::make(klass());
+  ciKlass* element_klass = klass();
+  if (element_klass->is_valuetype()) {
+    return ciValueArrayKlass::make(element_klass);
+  } else {
+    return ciObjArrayKlass::make(element_klass);
+  }
+}
+
+ciType* NewMultiArray::exact_type() const {
+  return _klass;
 }
 
 ciType* NewArray::declared_type() const {
   return exact_type();
 }

@@ -221,10 +307,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 +423,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);

@@ -789,20 +893,20 @@
 
     if (is_set(BlockBegin::parser_loop_header_flag)) {
       TRACE_PHI(tty->print_cr("loop header block, initializing phi functions"));
 
       for_each_stack_value(new_state, index, new_value) {
-        new_state->setup_phi_for_stack(this, index);
+        new_state->setup_phi_for_stack(this, index, NULL, new_value);
         TRACE_PHI(tty->print_cr("creating phi-function %c%d for stack %d", new_state->stack_at(index)->type()->tchar(), new_state->stack_at(index)->id(), index));
       }
 
       BitMap& requires_phi_function = new_state->scope()->requires_phi_function();
 
       for_each_local_value(new_state, index, new_value) {
         bool requires_phi = requires_phi_function.at(index) || (new_value->type()->is_double_word() && requires_phi_function.at(index + 1));
         if (requires_phi || !SelectivePhiFunctions) {
-          new_state->setup_phi_for_local(this, index);
+          new_state->setup_phi_for_local(this, index, NULL, new_value);
           TRACE_PHI(tty->print_cr("creating phi-function %c%d for local %d", new_state->local_at(index)->type()->tchar(), new_state->local_at(index)->id(), index));
         }
       }
     }
 

@@ -857,11 +961,11 @@
       for_each_stack_value(existing_state, index, existing_value) {
         Value new_value = new_state->stack_at(index);
         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);
+          existing_state->setup_phi_for_stack(this, index, existing_value, new_value);
           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));
         }
       }
 
       // create necessary phi functions for locals

@@ -871,11 +975,11 @@
 
         if (new_value == NULL || new_value->type()->tag() != existing_value->type()->tag()) {
           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);
+          existing_state->setup_phi_for_local(this, index, existing_value, new_value);
           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));
         }
       }
     }
 
< prev index next >