< prev index next >

src/share/vm/opto/type.cpp

Print this page

        

@@ -589,10 +589,12 @@
   TypeNarrowOop::NULL_PTR = TypeNarrowOop::make( TypePtr::NULL_PTR );
   TypeNarrowOop::BOTTOM   = TypeNarrowOop::make( TypeInstPtr::BOTTOM );
 
   TypeNarrowKlass::NULL_PTR = TypeNarrowKlass::make( TypePtr::NULL_PTR );
 
+  TypeValueTypePtr::NOTNULL = EnableValhalla ? TypeValueTypePtr::make(TypePtr::NotNull, current->env()->___Value_klass()->as_value_klass()) : NULL;
+
   mreg2type[Op_Node] = Type::BOTTOM;
   mreg2type[Op_Set ] = 0;
   mreg2type[Op_RegN] = TypeNarrowOop::BOTTOM;
   mreg2type[Op_RegI] = TypeInt::INT;
   mreg2type[Op_RegP] = TypePtr::BOTTOM;

@@ -1912,16 +1914,70 @@
 const TypeTuple *TypeTuple::INT_PAIR;
 const TypeTuple *TypeTuple::LONG_PAIR;
 const TypeTuple *TypeTuple::INT_CC_PAIR;
 const TypeTuple *TypeTuple::LONG_CC_PAIR;
 
+static void collect_value_fields(ciValueKlass* vk, const Type** field_array, uint& pos) {
+  for (int j = 0; j < vk->nof_nonstatic_fields(); j++) {
+    ciField* f = vk->nonstatic_field_at(j);
+    BasicType bt = f->type()->basic_type();
+    assert(bt < T_VALUETYPE && bt >= T_BOOLEAN, "not yet supported");
+    field_array[pos++] = Type::get_const_type(f->type());
+    if (bt == T_LONG || bt == T_DOUBLE) {
+      field_array[pos++] = Type::HALF;
+    }
+  }
+}
+
+// Can a value type instance of this type be returned as multiple
+// returned values?
+static bool vt_can_be_returned_as_fields(ciValueKlass* vk) {
+  if (vk == ciEnv::current()->___Value_klass()) {
+    return false;
+  }
+
+  ResourceMark rm;
+  uint args = vk->value_arg_slots() + 1 /* return vk as well */;
+
+  BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, args);
+  VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, args);
+
+  sig_bt[0] = T_METADATA;
+  for (uint i = 0, j = 1; i < (uint)vk->nof_nonstatic_fields(); i++) {
+    BasicType bt = vk->nonstatic_field_at(i)->layout_type();
+    assert(i+j < args, "out of bounds access");
+    sig_bt[i+j] = bt;
+    if (bt == T_LONG || bt == T_DOUBLE) {
+      j++;
+      assert(i+j < args, "out of bounds access");
+      sig_bt[i+j] = T_VOID;
+    }
+  }
+
+  if (SharedRuntime::java_return_convention(sig_bt, regs, args) <= 0) {
+    return false;
+  }
+  
+  return true;
+}
+
 
 //------------------------------make-------------------------------------------
 // Make a TypeTuple from the range of a method signature
-const TypeTuple *TypeTuple::make_range(ciSignature* sig) {
+const TypeTuple *TypeTuple::make_range(ciSignature* sig, bool ret_vt_fields) {
   ciType* return_type = sig->return_type();
-  uint arg_cnt = return_type->size();
+  uint arg_cnt = 0;
+  if (ret_vt_fields) {
+    ret_vt_fields = return_type->is_valuetype() && vt_can_be_returned_as_fields((ciValueKlass*)return_type);
+  }
+  if (ret_vt_fields) {
+    ciValueKlass* vk = (ciValueKlass*)return_type;
+    arg_cnt = vk->value_arg_slots()+1;
+  } else {
+    arg_cnt = return_type->size();
+  }
+
   const Type **field_array = fields(arg_cnt);
   switch (return_type->basic_type()) {
   case T_LONG:
     field_array[TypeFunc::Parms]   = TypeLong::LONG;
     field_array[TypeFunc::Parms+1] = Type::HALF;

@@ -1929,40 +1985,38 @@
   case T_DOUBLE:
     field_array[TypeFunc::Parms]   = Type::DOUBLE;
     field_array[TypeFunc::Parms+1] = Type::HALF;
     break;
   case T_OBJECT:
-  case T_VALUETYPE:
   case T_ARRAY:
   case T_BOOLEAN:
   case T_CHAR:
   case T_FLOAT:
   case T_BYTE:
   case T_SHORT:
   case T_INT:
     field_array[TypeFunc::Parms] = get_const_type(return_type);
     break;
+  case T_VALUETYPE:
+    if (ret_vt_fields) {
+      ciValueKlass* vk = (ciValueKlass*)return_type;
+      uint pos = TypeFunc::Parms;
+      field_array[pos] = TypeKlassPtr::make(vk);
+      pos++;
+      collect_value_fields(vk, field_array, pos);
+    } else {
+      field_array[TypeFunc::Parms] = get_const_type(return_type);
+    }
+    break;
   case T_VOID:
     break;
   default:
     ShouldNotReachHere();
   }
   return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt, field_array))->hashcons();
 }
 
-static void collect_value_fields(ciValueKlass* vk, const Type**& field_array, uint& pos) {
-  for (int j = 0; j < vk->nof_nonstatic_fields(); j++) {
-    ciField* f = vk->nonstatic_field_at(j);
-    BasicType bt = f->type()->basic_type();
-    assert(bt < T_VALUETYPE && bt >= T_BOOLEAN, "not yet supported");
-    field_array[pos++] = Type::get_const_type(f->type());
-    if (bt == T_LONG || bt == T_DOUBLE) {
-      field_array[pos++] = Type::HALF;
-    }
-  }
-}
-
 // Make a TypeTuple from the domain of a method signature
 const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig, bool vt_fields_as_args) {
   uint arg_cnt = sig->size();
 
   int vt_extra = 0;

@@ -4699,10 +4753,11 @@
 //=============================================================================
 
 
 //=============================================================================
 
+const TypeValueTypePtr* TypeValueTypePtr::NOTNULL;
 //------------------------------make-------------------------------------------
 const TypeValueTypePtr* TypeValueTypePtr::make(const TypeValueType* vt, PTR ptr, ciObject* o, Offset offset, int instance_id, const TypePtr* speculative, int inline_depth) {
   return (TypeValueTypePtr*)(new TypeValueTypePtr(vt, ptr, o, offset, instance_id, speculative, inline_depth))->hashcons();
 }
 

@@ -4806,10 +4861,26 @@
       int depth = meet_inline_depth(tp->inline_depth());
       // Compute constant oop
       ciObject* o = NULL;
       ciObject* this_oop  = const_oop();
       ciObject* tp_oop = tp->const_oop();
+      const TypeValueType* vt = NULL;
+      if (_vt != tp->_vt) {
+        ciKlass* __value_klass = ciEnv::current()->___Value_klass();
+        assert(klass() == __value_klass || tp->klass() == __value_klass, "impossible meet");
+        if (above_centerline(ptr)) {
+          vt = klass() == __value_klass ? tp->_vt : _vt;
+        } else if (above_centerline(this->_ptr) && !above_centerline(tp->_ptr)) {
+          vt = tp->_vt;
+        } else if (above_centerline(tp->_ptr) && !above_centerline(this->_ptr)) {
+          vt = _vt;
+        } else {
+          vt = klass() == __value_klass ? _vt : tp->_vt;
+        }
+      } else {
+        vt = _vt;
+      }
       if (ptr == Constant) {
         if (this_oop != NULL && tp_oop != NULL &&
             this_oop->equals(tp_oop) ) {
           o = this_oop;
         } else if (above_centerline(this ->_ptr)) {

@@ -4818,11 +4889,11 @@
           o = this_oop;
         } else {
           ptr = NotNull;
         }
       }
-      return make(_vt, ptr, o, offset, instance_id, speculative, depth);
+      return make(vt, ptr, o, offset, instance_id, speculative, depth);
     }
     }
 }
 
 // Dual: compute field-by-field dual

@@ -5591,16 +5662,17 @@
 
 //=============================================================================
 // Convenience common pre-built types.
 
 //------------------------------make-------------------------------------------
-const TypeFunc *TypeFunc::make( const TypeTuple *domain_sig, const TypeTuple* domain_cc, const TypeTuple *range ) {
-  return (TypeFunc*)(new TypeFunc(domain_sig, domain_cc, range))->hashcons();
+const TypeFunc *TypeFunc::make(const TypeTuple *domain_sig, const TypeTuple* domain_cc,
+                               const TypeTuple *range_sig, const TypeTuple *range_cc) {
+  return (TypeFunc*)(new TypeFunc(domain_sig, domain_cc, range_sig, range_cc))->hashcons();
 }
 
-const TypeFunc *TypeFunc::make( const TypeTuple *domain, const TypeTuple *range ) {
-  return make(domain, domain, range);
+const TypeFunc *TypeFunc::make(const TypeTuple *domain, const TypeTuple *range) {
+  return make(domain, domain, range, range);
 }
 
 //------------------------------make-------------------------------------------
 const TypeFunc *TypeFunc::make(ciMethod* method) {
   Compile* C = Compile::current();

@@ -5618,12 +5690,13 @@
     domain_cc = TypeTuple::make_domain(NULL, method->signature(), ValueTypePassFieldsAsArgs);
   } else {
     domain_sig = TypeTuple::make_domain(method->holder(), method->signature(), false);
     domain_cc = TypeTuple::make_domain(method->holder(), method->signature(), ValueTypePassFieldsAsArgs);
   }
-  const TypeTuple *range  = TypeTuple::make_range(method->signature());
-  tf = TypeFunc::make(domain_sig, domain_cc, range);
+  const TypeTuple *range_sig = TypeTuple::make_range(method->signature(), false);
+  const TypeTuple *range_cc = TypeTuple::make_range(method->signature(), ValueTypeReturnedAsFields);
+  tf = TypeFunc::make(domain_sig, domain_cc, range_sig, range_cc);
   C->set_last_tf(method, tf);  // fill cache
   return tf;
 }
 
 //------------------------------meet-------------------------------------------

@@ -5657,32 +5730,33 @@
 // Structural equality check for Type representations
 bool TypeFunc::eq( const Type *t ) const {
   const TypeFunc *a = (const TypeFunc*)t;
   return _domain_sig == a->_domain_sig &&
     _domain_cc == a->_domain_cc &&
-    _range == a->_range;
+    _range_sig == a->_range_sig &&
+    _range_cc == a->_range_cc;
 }
 
 //------------------------------hash-------------------------------------------
 // Type-specific hashing function.
 int TypeFunc::hash(void) const {
-  return (intptr_t)_domain_sig + (intptr_t)_domain_cc + (intptr_t)_range;
+  return (intptr_t)_domain_sig + (intptr_t)_domain_cc + (intptr_t)_range_sig + (intptr_t)_range_cc;
 }
 
 //------------------------------dump2------------------------------------------
 // Dump Function Type
 #ifndef PRODUCT
 void TypeFunc::dump2( Dict &d, uint depth, outputStream *st ) const {
-  if( _range->cnt() <= Parms )
+  if( _range_sig->cnt() <= Parms )
     st->print("void");
   else {
     uint i;
-    for (i = Parms; i < _range->cnt()-1; i++) {
-      _range->field_at(i)->dump2(d,depth,st);
+    for (i = Parms; i < _range_sig->cnt()-1; i++) {
+      _range_sig->field_at(i)->dump2(d,depth,st);
       st->print("/");
     }
-    _range->field_at(i)->dump2(d,depth,st);
+    _range_sig->field_at(i)->dump2(d,depth,st);
   }
   st->print(" ");
   st->print("( ");
   if( !depth || d[this] ) {     // Check for recursive dump
     st->print("...)");

@@ -5711,10 +5785,10 @@
   return false;                 // Never empty
 }
 
 
 BasicType TypeFunc::return_type() const{
-  if (range()->cnt() == TypeFunc::Parms) {
+  if (range_sig()->cnt() == TypeFunc::Parms) {
     return T_VOID;
   }
-  return range()->field_at(TypeFunc::Parms)->basic_type();
+  return range_sig()->field_at(TypeFunc::Parms)->basic_type();
 }
< prev index next >