< prev index next >

src/share/vm/oops/valueKlass.cpp

Print this page




   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "gc/shared/gcLocker.inline.hpp"
  27 #include "interpreter/interpreter.hpp"

  28 #include "oops/oop.inline.hpp"
  29 #include "oops/fieldStreams.hpp"
  30 #include "oops/method.hpp"
  31 #include "oops/objArrayKlass.hpp"
  32 #include "oops/valueKlass.hpp"
  33 #include "oops/valueArrayKlass.hpp"
  34 #include "runtime/signature.hpp"
  35 #include "utilities/copy.hpp"
  36 
  37 int ValueKlass::first_field_offset() const {
  38 #ifdef ASSERT
  39   int first_offset = INT_MAX;
  40   for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
  41     if (fs.offset() < first_offset) first_offset= fs.offset();
  42   }
  43 #endif
  44   int base_offset = instanceOopDesc::base_offset_in_bytes();
  45   // The first field of value types is aligned on a long boundary
  46   base_offset = align_size_up(base_offset, BytesPerLong);
  47   assert(base_offset == first_offset, "inconsistent offsets");


  69     if (fs.offset() > last_offset) {
  70       BasicType type = fs.field_descriptor().field_type();
  71       if (is_java_primitive(type)) {
  72         last_tsz = type2aelembytes(type);
  73       } else if (type == T_VALUETYPE) {
  74         // Not just primitives. Layout aligns embedded value, so use jlong aligned it is
  75         return heapOopAlignedSize;
  76       } else {
  77         guarantee(0, "Unknown type %d", type);
  78       }
  79       assert(last_tsz != 0, "Invariant");
  80       last_offset = fs.offset();
  81     }
  82   }
  83   // Assumes VT with no fields are meaningless and illegal
  84   last_offset += last_tsz;
  85   assert(last_offset > first_offset && last_tsz, "Invariant");
  86   return 1 << upper_log2(last_offset - first_offset);
  87 }
  88 






















  89 bool ValueKlass::is_atomic() {
  90   return (nonstatic_field_size() * heapOopSize) <= longSize;
  91 }
  92 
  93 int ValueKlass::nonstatic_oop_count() {
  94   int oops = 0;
  95   int map_count = nonstatic_oop_map_count();
  96   OopMapBlock* block = start_of_nonstatic_oop_maps();
  97   OopMapBlock* end = block + map_count;
  98   while (block != end) {
  99     oops += block->count();
 100     block++;
 101   }
 102   return oops;
 103 }
 104 
 105 // Arrays of...
 106 
 107 bool ValueKlass::flatten_array() {
 108   if (!ValueArrayFlatten) {


 218       } else {
 219         oopDesc::bs()->write_ref_array_pre((oop*) doop_address, map->count(), dst_uninitialized);
 220       }
 221       map++;
 222     }
 223 
 224     raw_field_copy(src, dst, raw_byte_size);
 225 
 226     // Post-barriers...
 227     map = start_of_nonstatic_oop_maps();
 228     while (map != end) {
 229       address doop_address = dst_oop_addr + map->offset();
 230       oopDesc::bs()->write_ref_array((HeapWord*) doop_address, map->count());
 231       map++;
 232     }
 233   } else {   // Primitive-only case...
 234     raw_field_copy(src, dst, raw_byte_size);
 235   }
 236 }
 237 
 238 oop ValueKlass::derive_value_type_copy(Handle src, InstanceKlass* target_klass, TRAPS) {
 239   assert(EnableMVT, "Only supported with the MVT programming model");
 240   // assert(InstanceKlass::cast(src->klass())->derive_value_type_klass() == target_klass, "Not this DVT");
 241 #ifdef ASSERT
 242   if (InstanceKlass::cast(src->klass())->has_vcc_klass()) {
 243     assert(InstanceKlass::cast(src->klass())->get_vcc_klass() == target_klass,
 244            "VCC/DVT mismatch");
 245   } else {
 246     assert(target_klass->has_vcc_klass(), "Sanity check");
 247     assert(target_klass->get_vcc_klass() == InstanceKlass::cast(src->klass()),
 248            "VCC/DVT mismatch");
 249   }
 250 #endif // ASSERT
 251 
 252   // Allocate new for safety, simply reinstalling the klass pointer is a little too risky
 253   target_klass->initialize(CHECK_0);
 254   instanceOop value = target_klass->allocate_instance(CHECK_0);
 255   value_store(data_for_oop(src()), data_for_oop(value), true, true);
















 256   return value;
 257 }
 258 
 259 // Value type arguments are not passed by reference, instead each
 260 // field of the value type is passed as an argument. This helper
 261 // function collects the fields of the value types (including embedded
 262 // value type's fields) in a list. Included with the field's type is
 263 // the offset of each field in the value type: i2c and c2i adapters
 264 // need that to load or store fields. Finally, the list of fields is
 265 // sorted in order of increasing offsets: the adapters and the
 266 // compiled code need and agreed upon order of fields.
 267 //
 268 // The list of basic types that is returned starts with a T_VALUETYPE
 269 // and ends with an extra T_VOID. T_VALUETYPE/T_VOID are used as
 270 // delimiters. Every entry between the two is a field of the value
 271 // type. If there's an embedded value type in the list, it also starts
 272 // with a T_VALUETYPE and ends with a T_VOID. This is so we can
 273 // generate a unique fingerprint for the method's adapters and we can
 274 // generate the list of basic types from the interpreter point of view
 275 // (value types passed as reference: iterate on the list until a


 494       break;
 495     }
 496     default:
 497       ShouldNotReachHere();
 498     }
 499     j++;
 500   }
 501   assert(j == nb_fields, "missed a field?");
 502   assert(k == handles.length(), "missed an oop?");
 503   return new_vt;
 504 }
 505 
 506 ValueKlass* ValueKlass::returned_value_type(const RegisterMap& map) {
 507   BasicType bt = T_METADATA;
 508   VMRegPair pair;
 509   int nb = SharedRuntime::java_return_convention(&bt, &pair, 1);
 510   assert(nb == 1, "broken");
 511   
 512   address loc = map.location(pair.first());
 513   intptr_t ptr = *(intptr_t*)loc;
 514   if (Universe::heap()->is_in_reserved((void*)ptr)) {
 515     return NULL;
 516   }
 517   return (ValueKlass*)ptr;






 518 }



   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "gc/shared/gcLocker.inline.hpp"
  27 #include "interpreter/interpreter.hpp"
  28 #include "logging/log.hpp"
  29 #include "oops/oop.inline.hpp"
  30 #include "oops/fieldStreams.hpp"
  31 #include "oops/method.hpp"
  32 #include "oops/objArrayKlass.hpp"
  33 #include "oops/valueKlass.hpp"
  34 #include "oops/valueArrayKlass.hpp"
  35 #include "runtime/signature.hpp"
  36 #include "utilities/copy.hpp"
  37 
  38 int ValueKlass::first_field_offset() const {
  39 #ifdef ASSERT
  40   int first_offset = INT_MAX;
  41   for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
  42     if (fs.offset() < first_offset) first_offset= fs.offset();
  43   }
  44 #endif
  45   int base_offset = instanceOopDesc::base_offset_in_bytes();
  46   // The first field of value types is aligned on a long boundary
  47   base_offset = align_size_up(base_offset, BytesPerLong);
  48   assert(base_offset == first_offset, "inconsistent offsets");


  70     if (fs.offset() > last_offset) {
  71       BasicType type = fs.field_descriptor().field_type();
  72       if (is_java_primitive(type)) {
  73         last_tsz = type2aelembytes(type);
  74       } else if (type == T_VALUETYPE) {
  75         // Not just primitives. Layout aligns embedded value, so use jlong aligned it is
  76         return heapOopAlignedSize;
  77       } else {
  78         guarantee(0, "Unknown type %d", type);
  79       }
  80       assert(last_tsz != 0, "Invariant");
  81       last_offset = fs.offset();
  82     }
  83   }
  84   // Assumes VT with no fields are meaningless and illegal
  85   last_offset += last_tsz;
  86   assert(last_offset > first_offset && last_tsz, "Invariant");
  87   return 1 << upper_log2(last_offset - first_offset);
  88 }
  89 
  90 instanceOop ValueKlass::allocate_instance(TRAPS) {
  91   int size = size_helper();  // Query before forming handle.
  92 
  93   return (instanceOop)CollectedHeap::obj_allocate(this, size, CHECK_NULL);
  94 }
  95 
  96 instanceOop ValueKlass::allocate_buffered_or_heap_instance(bool* in_heap, TRAPS) {
  97   assert(THREAD->is_Java_thread(), "Only Java threads can call this method");
  98 
  99   instanceOop value = NULL;
 100   if (is_bufferable()) {
 101     value = (instanceOop)VTBuffer::allocate_value(this, CHECK_NULL);
 102     *in_heap = false;
 103   }
 104   if (value == NULL) {
 105     log_info(valuetypes)("Value buffering failed, allocating in the Java heap");
 106     value = allocate_instance(CHECK_NULL);
 107     *in_heap = true;
 108   }
 109   return value;
 110 }
 111 
 112 bool ValueKlass::is_atomic() {
 113   return (nonstatic_field_size() * heapOopSize) <= longSize;
 114 }
 115 
 116 int ValueKlass::nonstatic_oop_count() {
 117   int oops = 0;
 118   int map_count = nonstatic_oop_map_count();
 119   OopMapBlock* block = start_of_nonstatic_oop_maps();
 120   OopMapBlock* end = block + map_count;
 121   while (block != end) {
 122     oops += block->count();
 123     block++;
 124   }
 125   return oops;
 126 }
 127 
 128 // Arrays of...
 129 
 130 bool ValueKlass::flatten_array() {
 131   if (!ValueArrayFlatten) {


 241       } else {
 242         oopDesc::bs()->write_ref_array_pre((oop*) doop_address, map->count(), dst_uninitialized);
 243       }
 244       map++;
 245     }
 246 
 247     raw_field_copy(src, dst, raw_byte_size);
 248 
 249     // Post-barriers...
 250     map = start_of_nonstatic_oop_maps();
 251     while (map != end) {
 252       address doop_address = dst_oop_addr + map->offset();
 253       oopDesc::bs()->write_ref_array((HeapWord*) doop_address, map->count());
 254       map++;
 255     }
 256   } else {   // Primitive-only case...
 257     raw_field_copy(src, dst, raw_byte_size);
 258   }
 259 }
 260 
 261 oop ValueKlass::box(Handle src, InstanceKlass* target_klass, TRAPS) {
 262   assert(src()->klass()->is_value(), "src must be a value type");
 263   assert(!target_klass->is_value(), "target_klass must not be a value type");










 264 

 265   target_klass->initialize(CHECK_0);
 266   instanceOop box = target_klass->allocate_instance(CHECK_0);
 267   value_store(data_for_oop(src()), data_for_oop(box), true, false);
 268 
 269   assert(!box->klass()->is_value(), "Sanity check");
 270   return box;
 271 }
 272 
 273 oop ValueKlass::unbox(Handle src, InstanceKlass* target_klass, TRAPS) {
 274   assert(!src()->klass()->is_value(), "src must not be a value type");
 275   assert(target_klass->is_value(), "target_klass must be a value type");
 276   ValueKlass* vtklass = ValueKlass::cast(target_klass);
 277 
 278   vtklass->initialize(CHECK_0);
 279   bool in_heap;
 280   instanceOop value = vtklass->allocate_buffered_or_heap_instance(&in_heap, CHECK_0);
 281   value_store(data_for_oop(src()), data_for_oop(value), in_heap, false);
 282 
 283   assert(value->klass()->is_value(), "Sanity check");
 284   return value;
 285 }
 286 
 287 // Value type arguments are not passed by reference, instead each
 288 // field of the value type is passed as an argument. This helper
 289 // function collects the fields of the value types (including embedded
 290 // value type's fields) in a list. Included with the field's type is
 291 // the offset of each field in the value type: i2c and c2i adapters
 292 // need that to load or store fields. Finally, the list of fields is
 293 // sorted in order of increasing offsets: the adapters and the
 294 // compiled code need and agreed upon order of fields.
 295 //
 296 // The list of basic types that is returned starts with a T_VALUETYPE
 297 // and ends with an extra T_VOID. T_VALUETYPE/T_VOID are used as
 298 // delimiters. Every entry between the two is a field of the value
 299 // type. If there's an embedded value type in the list, it also starts
 300 // with a T_VALUETYPE and ends with a T_VOID. This is so we can
 301 // generate a unique fingerprint for the method's adapters and we can
 302 // generate the list of basic types from the interpreter point of view
 303 // (value types passed as reference: iterate on the list until a


 522       break;
 523     }
 524     default:
 525       ShouldNotReachHere();
 526     }
 527     j++;
 528   }
 529   assert(j == nb_fields, "missed a field?");
 530   assert(k == handles.length(), "missed an oop?");
 531   return new_vt;
 532 }
 533 
 534 ValueKlass* ValueKlass::returned_value_type(const RegisterMap& map) {
 535   BasicType bt = T_METADATA;
 536   VMRegPair pair;
 537   int nb = SharedRuntime::java_return_convention(&bt, &pair, 1);
 538   assert(nb == 1, "broken");
 539   
 540   address loc = map.location(pair.first());
 541   intptr_t ptr = *(intptr_t*)loc;
 542   if (Metaspace::contains((void*)ptr)) {


 543     return (ValueKlass*)ptr;
 544   }
 545   return NULL;
 546 //  if (Universe::heap()->is_in_reserved((void*)ptr)) {
 547 //    return NULL;
 548 //  }
 549 //  return (ValueKlass*)ptr;
 550 }
 551 
< prev index next >