< prev index next >

src/hotspot/share/opto/parse3.cpp

Print this page

        

@@ -25,17 +25,19 @@
 #include "precompiled.hpp"
 #include "compiler/compileLog.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "memory/universe.hpp"
 #include "oops/objArrayKlass.hpp"
+#include "oops/valueArrayKlass.hpp"
 #include "opto/addnode.hpp"
 #include "opto/castnode.hpp"
 #include "opto/memnode.hpp"
 #include "opto/parse.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
 #include "opto/subnode.hpp"
+#include "opto/valuetypenode.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/handles.inline.hpp"
 
 //=============================================================================
 // Helper methods for _get* and _put* bytecodes

@@ -78,10 +80,18 @@
   ciField* field = iter().get_field(will_link);
   assert(will_link, "getfield: typeflow responsibility");
 
   ciInstanceKlass* field_holder = field->holder();
 
+  if (is_field && field_holder->is_valuetype() && peek()->is_ValueType()) {
+    assert(is_get, "value type field store not supported");
+    ValueTypeNode* vt = pop()->as_ValueType();
+    Node* value = vt->field_value_by_offset(field->offset());
+    push_node(field->layout_type(), value);
+    return;
+  }
+
   if (is_field == field->is_static()) {
     // Interpreter will throw java_lang_IncompatibleClassChangeError
     // Check this before allowing <clinit> methods to access static fields
     uncommon_trap(Deoptimization::Reason_unhandled,
                   Deoptimization::Action_none);

@@ -125,10 +135,13 @@
     if (is_get) {
       (void) pop();  // pop receiver before getting
       do_get_xxx(obj, field, is_field);
     } else {
       do_put_xxx(obj, field, is_field);
+      if (stopped()) {
+        return;
+      }
       (void) pop();  // pop receiver after putting
     }
   } else {
     const TypeInstPtr* tip = TypeInstPtr::make(field_holder->java_mirror());
     obj = _gvn.makecon(tip);

@@ -138,11 +151,10 @@
       do_put_xxx(obj, field, is_field);
     }
   }
 }
 
-
 void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
   BasicType bt = field->layout_type();
 
   // Does this field have a constant value?  If so, just push the value.
   if (field->is_constant() &&

@@ -160,10 +172,12 @@
     }
   }
 
   ciType* field_klass = field->type();
   bool is_vol = field->is_volatile();
+  bool flattened = field->is_flattened();
+  bool flattenable = field->is_flattenable();
 
   // Compute address and memory type.
   int offset = field->offset_in_bytes();
   const TypePtr* adr_type = C->alias_type(field)->adr_type();
   Node *adr = basic_plus_adr(obj, obj, offset);

@@ -171,16 +185,11 @@
   // Build the resultant type of the load
   const Type *type;
 
   bool must_assert_null = false;
 
-  DecoratorSet decorators = IN_HEAP;
-  decorators |= is_vol ? MO_SEQ_CST : MO_UNORDERED;
-
-  bool is_obj = bt == T_OBJECT || bt == T_ARRAY;
-
-  if (is_obj) {
+  if (bt == T_OBJECT || bt == T_ARRAY || bt == T_VALUETYPE) {
     if (!field->type()->is_loaded()) {
       type = TypeInstPtr::BOTTOM;
       must_assert_null = true;
     } else if (field->is_static_constant()) {
       // This can happen if the constant oop is non-perm.

@@ -193,16 +202,41 @@
         type = TypeOopPtr::make_from_constant(con)->isa_oopptr();
       }
       assert(type != NULL, "field singleton type must be consistent");
     } else {
       type = TypeOopPtr::make_from_klass(field_klass->as_klass());
+      if (bt == T_VALUETYPE && field->is_static()) {
+        // Check if static value type field is already initialized
+        assert(!flattened, "static fields should not be flattened");
+        ciInstance* mirror = field->holder()->java_mirror();
+        ciObject* val = mirror->field_value(field).as_object();
+        if (!val->is_null_object()) {
+          type = type->join_speculative(TypePtr::NOTNULL);
+        }
+      }
     }
   } else {
     type = Type::get_const_basic_type(bt);
   }
 
-  Node* ld = access_load_at(obj, adr, adr_type, type, bt, decorators);
+  Node* ld = NULL;
+  if (flattened) {
+    // Load flattened value type
+    ld = ValueTypeNode::make_from_flattened(this, field_klass->as_value_klass(), obj, obj, field->holder(), offset);
+  } else {
+    DecoratorSet decorators = IN_HEAP;
+    decorators |= is_vol ? MO_SEQ_CST : MO_UNORDERED;
+    ld = access_load_at(obj, adr, adr_type, type, bt, decorators);
+    if (flattenable) {
+      // Load a non-flattened but flattenable value type from memory
+      if (field_klass->as_value_klass()->is_scalarizable()) {
+        ld = ValueTypeNode::make_from_oop(this, ld, field_klass->as_value_klass());
+      } else {
+        ld = null2default(ld, field_klass->as_value_klass());
+      }
+    }
+  }
 
   // Adjust Java stack
   if (type2size[bt] == 1)
     push(ld);
   else

@@ -245,24 +279,39 @@
   Node* val = type2size[bt] == 1 ? pop() : pop_pair();
 
   DecoratorSet decorators = IN_HEAP;
   decorators |= is_vol ? MO_SEQ_CST : MO_UNORDERED;
 
-  bool is_obj = bt == T_OBJECT || bt == T_ARRAY;
-
   // Store the value.
   const Type* field_type;
   if (!field->type()->is_loaded()) {
     field_type = TypeInstPtr::BOTTOM;
   } else {
-    if (is_obj) {
+    if (bt == T_OBJECT || bt == T_ARRAY || bt == T_VALUETYPE) {
       field_type = TypeOopPtr::make_from_klass(field->type()->as_klass());
     } else {
       field_type = Type::BOTTOM;
     }
   }
+
+  if (field->is_flattenable() && !val->is_ValueType()) {
+    inc_sp(1);
+    val = null_check(val);
+    dec_sp(1);
+    if (stopped()) return;
+  }
+
+  if (field->is_flattened()) {
+    // Store flattened value type to a non-static field
+    if (!val->is_ValueType()) {
+      assert(!gvn().type(val)->maybe_null(), "should never be null");
+      val = ValueTypeNode::make_from_oop(this, val, field->type()->as_value_klass());
+    }
+    val->as_ValueType()->store_flattened(this, obj, obj, field->holder(), offset);
+  } else {
   access_store_at(obj, adr, adr_type, val, field_type, bt, decorators);
+  }
 
   if (is_field) {
     // Remember we wrote a volatile field.
     // For not multiple copy atomic cpu (ppc64) a barrier should be issued
     // in constructors which have such stores. See do_exits() in parse1.cpp.

@@ -290,27 +339,35 @@
     }
   }
 }
 
 //=============================================================================
-void Parse::do_anewarray() {
+
+void Parse::do_newarray() {
   bool will_link;
   ciKlass* klass = iter().get_klass(will_link);
 
   // Uncommon Trap when class that array contains is not loaded
   // we need the loaded class for the rest of graph; do not
   // initialize the container class (see Java spec)!!!
-  assert(will_link, "anewarray: typeflow responsibility");
+  assert(will_link, "newarray: typeflow responsibility");
 
-  ciObjArrayKlass* array_klass = ciObjArrayKlass::make(klass);
+  ciArrayKlass* array_klass = ciArrayKlass::make(klass);
   // Check that array_klass object is loaded
   if (!array_klass->is_loaded()) {
     // Generate uncommon_trap for unloaded array_class
     uncommon_trap(Deoptimization::Reason_unloaded,
                   Deoptimization::Action_reinterpret,
                   array_klass);
     return;
+  } else if (array_klass->element_klass() != NULL &&
+             array_klass->element_klass()->is_valuetype() &&
+             !array_klass->element_klass()->as_value_klass()->is_initialized()) {
+    uncommon_trap(Deoptimization::Reason_uninitialized,
+                  Deoptimization::Action_reinterpret,
+                  NULL);
+    return;
   }
 
   kill_dead_locals();
 
   const TypeKlassPtr* array_klass_type = TypeKlassPtr::make(array_klass);
< prev index next >