< prev index next >

src/hotspot/share/oops/valueKlass.cpp

Print this page




  36 #include "oops/valueKlass.hpp"
  37 #include "oops/valueArrayKlass.hpp"
  38 #include "runtime/signature.hpp"
  39 #include "utilities/copy.hpp"
  40 
  41 int ValueKlass::first_field_offset() const {
  42 #ifdef ASSERT
  43   int first_offset = INT_MAX;
  44   for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
  45     if (fs.offset() < first_offset) first_offset= fs.offset();
  46   }
  47 #endif
  48   int base_offset = instanceOopDesc::base_offset_in_bytes();
  49   // The first field of value types is aligned on a long boundary
  50   base_offset = align_up(base_offset, BytesPerLong);
  51   assert(base_offset == first_offset, "inconsistent offsets");
  52   return base_offset;
  53 }
  54 
  55 int ValueKlass::raw_value_byte_size() const {
  56   assert(!is__Value(), "This is not the value type klass you are looking for");
  57   int heapOopAlignedSize = nonstatic_field_size() << LogBytesPerHeapOop;
  58   // If bigger than 64 bits or needs oop alignment, then use jlong aligned
  59   // which for values should be jlong aligned, asserts in raw_field_copy otherwise
  60   if (heapOopAlignedSize >= longSize || contains_oops()) {
  61     return heapOopAlignedSize;
  62   }
  63   // Small primitives...
  64   // If a few small basic type fields, return the actual size, i.e.
  65   // 1 byte = 1
  66   // 2 byte = 2
  67   // 3 byte = 4, because pow2 needed for element stores
  68   int first_offset = first_field_offset();
  69   int last_offset  = 0; // find the last offset, add basic type size
  70   int last_tsz     = 0;
  71   for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
  72     if (fs.offset() > last_offset) {
  73       BasicType type = fs.field_descriptor().field_type();
  74       if (is_java_primitive(type)) {
  75         last_tsz = type2aelembytes(type);
  76       } else if (type == T_VALUETYPE) {


 248         map++;
 249       }
 250 
 251       raw_field_copy(src, dst, raw_byte_size);
 252 
 253       // Post-barriers...
 254       map = start_of_nonstatic_oop_maps();
 255       while (map != end) {
 256         address doop_address = dst_oop_addr + map->offset();
 257         BarrierSet::barrier_set()->write_ref_array((HeapWord*) doop_address, map->count());
 258         map++;
 259       }
 260     } else { // Buffered value case
 261       raw_field_copy(src, dst, raw_byte_size);
 262     }
 263   } else {   // Primitive-only case...
 264     raw_field_copy(src, dst, raw_byte_size);
 265   }
 266 }
 267 
 268 oop ValueKlass::box(Handle src, InstanceKlass* target_klass, TRAPS) {
 269   assert(src()->klass()->is_value(), "src must be a value type");
 270   assert(!target_klass->is_value(), "target_klass must not be a value type");
 271 
 272   target_klass->initialize(CHECK_0);
 273   instanceOop box = target_klass->allocate_instance(CHECK_0);
 274   value_store(data_for_oop(src()), data_for_oop(box), true, false);
 275 
 276   assert(!box->klass()->is_value(), "Sanity check");
 277   return box;
 278 }
 279 
 280 oop ValueKlass::unbox(Handle src, InstanceKlass* target_klass, TRAPS) {
 281   assert(!src()->klass()->is_value(), "src must not be a value type");
 282   assert(target_klass->is_value(), "target_klass must be a value type");
 283   ValueKlass* vtklass = ValueKlass::cast(target_klass);
 284 
 285   vtklass->initialize(CHECK_0);
 286   bool in_heap;
 287   instanceOop value = vtklass->allocate_buffered_or_heap_instance(&in_heap, CHECK_0);
 288   value_store(data_for_oop(src()), data_for_oop(value), in_heap, false);
 289 
 290   assert(value->klass()->is_value(), "Sanity check");
 291   return value;
 292 }
 293 
 294 // Value type arguments are not passed by reference, instead each
 295 // field of the value type is passed as an argument. This helper
 296 // function collects the fields of the value types (including embedded
 297 // value type's fields) in a list. Included with the field's type is
 298 // the offset of each field in the value type: i2c and c2i adapters
 299 // need that to load or store fields. Finally, the list of fields is
 300 // sorted in order of increasing offsets: the adapters and the
 301 // compiled code need and agreed upon order of fields.
 302 //
 303 // The list of basic types that is returned starts with a T_VALUETYPE
 304 // and ends with an extra T_VOID. T_VALUETYPE/T_VOID are used as
 305 // delimiters. Every entry between the two is a field of the value
 306 // type. If there's an embedded value type in the list, it also starts
 307 // with a T_VALUETYPE and ends with a T_VOID. This is so we can
 308 // generate a unique fingerprint for the method's adapters and we can
 309 // generate the list of basic types from the interpreter point of view
 310 // (value types passed as reference: iterate on the list until a
 311 // T_VALUETYPE, drop everything until and including the closing
 312 // T_VOID) or the compiler point of view (each field of the value
 313 // types is an argument: drop all T_VALUETYPE/T_VOID from the list).


 340     } else {
 341       sig_extended.push(SigEntry(bt, offset));
 342       if (bt == T_LONG || bt == T_DOUBLE) {
 343         sig_extended.push(SigEntry(T_VOID, offset));
 344       }
 345     }
 346   }
 347   int offset = base_off + size_helper()*HeapWordSize - (base_off > 0 ? first_field_offset() : 0);
 348   sig_extended.push(SigEntry(T_VOID, offset)); // hack: use T_VOID to mark end of value type fields
 349   if (base_off == 0) {
 350     sig_extended.sort(SigEntry::compare);
 351   }
 352   assert(sig_extended.at(0)._bt == T_VALUETYPE && sig_extended.at(sig_extended.length()-1)._bt == T_VOID, "broken structure");
 353   return sig_extended;
 354 }
 355 
 356 void ValueKlass::initialize_calling_convention() {
 357   // Because the pack and unpack handler addresses need to be loadable from generated code,
 358   // they are stored at a fixed offset in the klass metadata. Since value type klasses do
 359   // not have a vtable, the vtable offset is used to store these addresses.
 360   guarantee(vtable_length() == 0, "vtables are not supported in value klasses");
 361   if (ValueTypeReturnedAsFields || ValueTypePassFieldsAsArgs) {
 362     Thread* THREAD = Thread::current();
 363     assert(!HAS_PENDING_EXCEPTION, "should have no exception");
 364     ResourceMark rm;
 365     const GrowableArray<SigEntry>& sig_vk = collect_fields();
 366     int nb_fields = SigEntry::count_fields(sig_vk)+1;
 367     Array<SigEntry>* extended_sig = MetadataFactory::new_array<SigEntry>(class_loader_data(), sig_vk.length(), CHECK_AND_CLEAR);
 368     *((Array<SigEntry>**)adr_extended_sig()) = extended_sig;
 369     for (int i = 0; i < sig_vk.length(); i++) {
 370       extended_sig->at_put(i, sig_vk.at(i));
 371     }
 372 
 373     if (ValueTypeReturnedAsFields) {
 374       BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, nb_fields);
 375       sig_bt[0] = T_METADATA;
 376       SigEntry::fill_sig_bt(sig_vk, sig_bt+1, nb_fields-1, true);
 377       VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, nb_fields);
 378       int total = SharedRuntime::java_return_convention(sig_bt, regs, nb_fields);
 379 
 380       if (total > 0) {


 403   cleanup_blobs();
 404   InstanceKlass::deallocate_contents(loader_data);
 405 }
 406 
 407 void ValueKlass::cleanup(ValueKlass* ik) {
 408   ik->cleanup_blobs();
 409 }
 410 
 411 void ValueKlass::cleanup_blobs() {
 412   if (pack_handler() != NULL) {
 413     CodeBlob* buffered_blob = CodeCache::find_blob(pack_handler());
 414     assert(buffered_blob->is_buffered_value_type_blob(), "bad blob type");
 415     BufferBlob::free((BufferBlob*)buffered_blob);
 416     *((address*)adr_pack_handler()) = NULL;
 417     *((address*)adr_unpack_handler()) = NULL;
 418   }
 419 }
 420 
 421 // Can this value type be returned as multiple values?
 422 bool ValueKlass::can_be_returned_as_fields() const {
 423   return !is__Value() && (return_regs() != NULL);
 424 }
 425 
 426 // Create handles for all oop fields returned in registers that are going to be live across a safepoint
 427 void ValueKlass::save_oop_fields(const RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
 428   Thread* thread = Thread::current();
 429   const Array<SigEntry>* sig_vk = extended_sig();
 430   const Array<VMRegPair>* regs = return_regs();
 431   int j = 1;
 432 
 433   for (int i = 0; i < sig_vk->length(); i++) {
 434     BasicType bt = sig_vk->at(i)._bt;
 435     if (bt == T_OBJECT || bt == T_VALUETYPEPTR || bt == T_ARRAY) {
 436       int off = sig_vk->at(i)._offset;
 437       VMRegPair pair = regs->at(j);
 438       address loc = reg_map.location(pair.first());
 439       oop v = *(oop*)loc;
 440       assert(v == NULL || oopDesc::is_oop(v), "not an oop?");
 441       assert(Universe::heap()->is_in_or_null(v), "must be heap pointer");
 442       handles.push(Handle(thread, v));
 443     }




  36 #include "oops/valueKlass.hpp"
  37 #include "oops/valueArrayKlass.hpp"
  38 #include "runtime/signature.hpp"
  39 #include "utilities/copy.hpp"
  40 
  41 int ValueKlass::first_field_offset() const {
  42 #ifdef ASSERT
  43   int first_offset = INT_MAX;
  44   for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
  45     if (fs.offset() < first_offset) first_offset= fs.offset();
  46   }
  47 #endif
  48   int base_offset = instanceOopDesc::base_offset_in_bytes();
  49   // The first field of value types is aligned on a long boundary
  50   base_offset = align_up(base_offset, BytesPerLong);
  51   assert(base_offset == first_offset, "inconsistent offsets");
  52   return base_offset;
  53 }
  54 
  55 int ValueKlass::raw_value_byte_size() const {

  56   int heapOopAlignedSize = nonstatic_field_size() << LogBytesPerHeapOop;
  57   // If bigger than 64 bits or needs oop alignment, then use jlong aligned
  58   // which for values should be jlong aligned, asserts in raw_field_copy otherwise
  59   if (heapOopAlignedSize >= longSize || contains_oops()) {
  60     return heapOopAlignedSize;
  61   }
  62   // Small primitives...
  63   // If a few small basic type fields, return the actual size, i.e.
  64   // 1 byte = 1
  65   // 2 byte = 2
  66   // 3 byte = 4, because pow2 needed for element stores
  67   int first_offset = first_field_offset();
  68   int last_offset  = 0; // find the last offset, add basic type size
  69   int last_tsz     = 0;
  70   for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
  71     if (fs.offset() > last_offset) {
  72       BasicType type = fs.field_descriptor().field_type();
  73       if (is_java_primitive(type)) {
  74         last_tsz = type2aelembytes(type);
  75       } else if (type == T_VALUETYPE) {


 247         map++;
 248       }
 249 
 250       raw_field_copy(src, dst, raw_byte_size);
 251 
 252       // Post-barriers...
 253       map = start_of_nonstatic_oop_maps();
 254       while (map != end) {
 255         address doop_address = dst_oop_addr + map->offset();
 256         BarrierSet::barrier_set()->write_ref_array((HeapWord*) doop_address, map->count());
 257         map++;
 258       }
 259     } else { // Buffered value case
 260       raw_field_copy(src, dst, raw_byte_size);
 261     }
 262   } else {   // Primitive-only case...
 263     raw_field_copy(src, dst, raw_byte_size);
 264   }
 265 }
 266 


























 267 // Value type arguments are not passed by reference, instead each
 268 // field of the value type is passed as an argument. This helper
 269 // function collects the fields of the value types (including embedded
 270 // value type's fields) in a list. Included with the field's type is
 271 // the offset of each field in the value type: i2c and c2i adapters
 272 // need that to load or store fields. Finally, the list of fields is
 273 // sorted in order of increasing offsets: the adapters and the
 274 // compiled code need and agreed upon order of fields.
 275 //
 276 // The list of basic types that is returned starts with a T_VALUETYPE
 277 // and ends with an extra T_VOID. T_VALUETYPE/T_VOID are used as
 278 // delimiters. Every entry between the two is a field of the value
 279 // type. If there's an embedded value type in the list, it also starts
 280 // with a T_VALUETYPE and ends with a T_VOID. This is so we can
 281 // generate a unique fingerprint for the method's adapters and we can
 282 // generate the list of basic types from the interpreter point of view
 283 // (value types passed as reference: iterate on the list until a
 284 // T_VALUETYPE, drop everything until and including the closing
 285 // T_VOID) or the compiler point of view (each field of the value
 286 // types is an argument: drop all T_VALUETYPE/T_VOID from the list).


 313     } else {
 314       sig_extended.push(SigEntry(bt, offset));
 315       if (bt == T_LONG || bt == T_DOUBLE) {
 316         sig_extended.push(SigEntry(T_VOID, offset));
 317       }
 318     }
 319   }
 320   int offset = base_off + size_helper()*HeapWordSize - (base_off > 0 ? first_field_offset() : 0);
 321   sig_extended.push(SigEntry(T_VOID, offset)); // hack: use T_VOID to mark end of value type fields
 322   if (base_off == 0) {
 323     sig_extended.sort(SigEntry::compare);
 324   }
 325   assert(sig_extended.at(0)._bt == T_VALUETYPE && sig_extended.at(sig_extended.length()-1)._bt == T_VOID, "broken structure");
 326   return sig_extended;
 327 }
 328 
 329 void ValueKlass::initialize_calling_convention() {
 330   // Because the pack and unpack handler addresses need to be loadable from generated code,
 331   // they are stored at a fixed offset in the klass metadata. Since value type klasses do
 332   // not have a vtable, the vtable offset is used to store these addresses.
 333   //guarantee(vtable_length() == 0, "vtables are not supported in value klasses");
 334   if (ValueTypeReturnedAsFields || ValueTypePassFieldsAsArgs) {
 335     Thread* THREAD = Thread::current();
 336     assert(!HAS_PENDING_EXCEPTION, "should have no exception");
 337     ResourceMark rm;
 338     const GrowableArray<SigEntry>& sig_vk = collect_fields();
 339     int nb_fields = SigEntry::count_fields(sig_vk)+1;
 340     Array<SigEntry>* extended_sig = MetadataFactory::new_array<SigEntry>(class_loader_data(), sig_vk.length(), CHECK_AND_CLEAR);
 341     *((Array<SigEntry>**)adr_extended_sig()) = extended_sig;
 342     for (int i = 0; i < sig_vk.length(); i++) {
 343       extended_sig->at_put(i, sig_vk.at(i));
 344     }
 345 
 346     if (ValueTypeReturnedAsFields) {
 347       BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, nb_fields);
 348       sig_bt[0] = T_METADATA;
 349       SigEntry::fill_sig_bt(sig_vk, sig_bt+1, nb_fields-1, true);
 350       VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, nb_fields);
 351       int total = SharedRuntime::java_return_convention(sig_bt, regs, nb_fields);
 352 
 353       if (total > 0) {


 376   cleanup_blobs();
 377   InstanceKlass::deallocate_contents(loader_data);
 378 }
 379 
 380 void ValueKlass::cleanup(ValueKlass* ik) {
 381   ik->cleanup_blobs();
 382 }
 383 
 384 void ValueKlass::cleanup_blobs() {
 385   if (pack_handler() != NULL) {
 386     CodeBlob* buffered_blob = CodeCache::find_blob(pack_handler());
 387     assert(buffered_blob->is_buffered_value_type_blob(), "bad blob type");
 388     BufferBlob::free((BufferBlob*)buffered_blob);
 389     *((address*)adr_pack_handler()) = NULL;
 390     *((address*)adr_unpack_handler()) = NULL;
 391   }
 392 }
 393 
 394 // Can this value type be returned as multiple values?
 395 bool ValueKlass::can_be_returned_as_fields() const {
 396   return return_regs() != NULL;
 397 }
 398 
 399 // Create handles for all oop fields returned in registers that are going to be live across a safepoint
 400 void ValueKlass::save_oop_fields(const RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
 401   Thread* thread = Thread::current();
 402   const Array<SigEntry>* sig_vk = extended_sig();
 403   const Array<VMRegPair>* regs = return_regs();
 404   int j = 1;
 405 
 406   for (int i = 0; i < sig_vk->length(); i++) {
 407     BasicType bt = sig_vk->at(i)._bt;
 408     if (bt == T_OBJECT || bt == T_VALUETYPEPTR || bt == T_ARRAY) {
 409       int off = sig_vk->at(i)._offset;
 410       VMRegPair pair = regs->at(j);
 411       address loc = reg_map.location(pair.first());
 412       oop v = *(oop*)loc;
 413       assert(v == NULL || oopDesc::is_oop(v), "not an oop?");
 414       assert(Universe::heap()->is_in_or_null(v), "must be heap pointer");
 415       handles.push(Handle(thread, v));
 416     }


< prev index next >