< prev index next >

src/share/vm/opto/type.cpp

Print this page

        

@@ -21,10 +21,11 @@
  * questions.
  *
  */
 
 #include "precompiled.hpp"
+#include "ci/ciField.hpp"
 #include "ci/ciMethodData.hpp"
 #include "ci/ciTypeFlow.hpp"
 #include "ci/ciValueKlass.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"

@@ -1808,27 +1809,74 @@
     ShouldNotReachHere();
   }
   return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt, field_array))->hashcons();
 }
 
+static int extra_value_fields(ciValueKlass* vk) {
+  int vt_extra = vk->nof_nonstatic_fields() - 1;
+  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, "embedded");
+    if (bt == T_LONG || bt == T_DOUBLE) {
+      vt_extra++;
+    }
+  }
+  return vt_extra;
+}
+
+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) {
+const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig, bool is_cc) {
   uint arg_cnt = sig->size();
 
+  int vt_extra = 0;
+  if (is_cc) {
+    for (int i = 0; i < sig->count(); i++) {
+      ciType* type = sig->type_at(i);
+      if (type->basic_type() == T_VALUETYPE) {
+        assert(type->is_valuetype(), "");
+        ciValueKlass* vk = (ciValueKlass*)type;
+        vt_extra += extra_value_fields(vk);
+      }
+    }
+    assert(((int)arg_cnt) + vt_extra >= 0, "");
+  }
+
   uint pos = TypeFunc::Parms;
   const Type **field_array;
   if (recv != NULL) {
     arg_cnt++;
-    field_array = fields(arg_cnt);
+    if (is_cc && recv->is_valuetype()) {
+      ciValueKlass* vk = (ciValueKlass*)recv;
+      vt_extra += extra_value_fields(vk);
+    }
+    field_array = fields(arg_cnt + vt_extra);
     // Use get_const_type here because it respects UseUniqueSubclasses:
+    if (is_cc && recv->is_valuetype()) {
+      ciValueKlass* vk = (ciValueKlass*)recv;
+      collect_value_fields(vk, field_array, pos);
+    } else {
     field_array[pos++] = get_const_type(recv)->join_speculative(TypePtr::NOTNULL);
+    }
   } else {
-    field_array = fields(arg_cnt);
+    field_array = fields(arg_cnt + vt_extra);
   }
 
   int i = 0;
-  while (pos < TypeFunc::Parms + arg_cnt) {
+  while (pos < TypeFunc::Parms + arg_cnt + vt_extra) {
     ciType* type = sig->type_at(i);
 
     switch (type->basic_type()) {
     case T_LONG:
       field_array[pos++] = TypeLong::LONG;

@@ -1837,27 +1885,37 @@
     case T_DOUBLE:
       field_array[pos++] = Type::DOUBLE;
       field_array[pos++] = 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[pos++] = get_const_type(type);
       break;
+    case T_VALUETYPE: {
+      assert(type->is_valuetype(), "");
+      if (is_cc) {
+        ciValueKlass* vk = (ciValueKlass*)type;
+        collect_value_fields(vk, field_array, pos);
+      } else {
+        field_array[pos++] = get_const_type(type);
+      }
+      break;
+    }
     default:
       ShouldNotReachHere();
     }
     i++;
   }
+  assert(pos == TypeFunc::Parms + arg_cnt + vt_extra, "");
 
-  return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt, field_array))->hashcons();
+  return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt + vt_extra, field_array))->hashcons();
 }
 
 const TypeTuple *TypeTuple::make( uint cnt, const Type **fields ) {
   return (TypeTuple*)(new TypeTuple(cnt,fields))->hashcons();
 }

@@ -5364,27 +5422,35 @@
 
 //=============================================================================
 // Convenience common pre-built types.
 
 //------------------------------make-------------------------------------------
-const TypeFunc *TypeFunc::make( const TypeTuple *domain, const TypeTuple *range ) {
-  return (TypeFunc*)(new TypeFunc(domain,range))->hashcons();
+const TypeFunc *TypeFunc::make( const TypeTuple *domain, const TypeTuple* domain_cc, const TypeTuple *range ) {
+  return (TypeFunc*)(new TypeFunc(domain, domain_cc, range))->hashcons();
 }
 
 //------------------------------make-------------------------------------------
 const TypeFunc *TypeFunc::make(ciMethod* method) {
   Compile* C = Compile::current();
   const TypeFunc* tf = C->last_tf(method); // check cache
   if (tf != NULL)  return tf;  // The hit rate here is almost 50%.
-  const TypeTuple *domain;
+  const TypeTuple *domain_sig, *domain_cc;
+  // Value type arguments are not passed by reference, instead each
+  // field of the value type is passed as an argument. We maintain 2
+  // views of the argument list here: one based on the signature (with
+  // a value type argument as a single slot), one based on the actual
+  // calling convention (with a value type argument as a list of its
+  // fields).
   if (method->is_static()) {
-    domain = TypeTuple::make_domain(NULL, method->signature());
+    domain_sig = TypeTuple::make_domain(NULL, method->signature(), false);
+    domain_cc = TypeTuple::make_domain(NULL, method->signature(), ValueTypePassFieldsAsArgs);
   } else {
-    domain = TypeTuple::make_domain(method->holder(), method->signature());
+    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, range);
+  tf = TypeFunc::make(domain_sig, domain_cc, range);
   C->set_last_tf(method, tf);  // fill cache
   return tf;
 }
 
 //------------------------------meet-------------------------------------------

@@ -5416,18 +5482,19 @@
 
 //------------------------------eq---------------------------------------------
 // Structural equality check for Type representations
 bool TypeFunc::eq( const Type *t ) const {
   const TypeFunc *a = (const TypeFunc*)t;
-  return _domain == a->_domain &&
+  return _domain_sig == a->_domain_sig &&
+    _domain_cc == a->_domain_cc &&
     _range == a->_range;
 }
 
 //------------------------------hash-------------------------------------------
 // Type-specific hashing function.
 int TypeFunc::hash(void) const {
-  return (intptr_t)_domain + (intptr_t)_range;
+  return (intptr_t)_domain_sig + (intptr_t)_domain_cc + (intptr_t)_range;
 }
 
 //------------------------------dump2------------------------------------------
 // Dump Function Type
 #ifndef PRODUCT

@@ -5447,15 +5514,15 @@
   if( !depth || d[this] ) {     // Check for recursive dump
     st->print("...)");
     return;
   }
   d.Insert((void*)this,(void*)this);    // Stop recursion
-  if (Parms < _domain->cnt())
-    _domain->field_at(Parms)->dump2(d,depth-1,st);
-  for (uint i = Parms+1; i < _domain->cnt(); i++) {
+  if (Parms < _domain_sig->cnt())
+    _domain_sig->field_at(Parms)->dump2(d,depth-1,st);
+  for (uint i = Parms+1; i < _domain_sig->cnt(); i++) {
     st->print(", ");
-    _domain->field_at(i)->dump2(d,depth-1,st);
+    _domain_sig->field_at(i)->dump2(d,depth-1,st);
   }
   st->print(" )");
 }
 #endif
 
< prev index next >