< prev index next >

src/hotspot/share/cds/aotStreamedHeapWriter.cpp

Print this page

276 
277 template <typename T>
278 void update_buffered_object_field(address buffered_obj, int field_offset, T value) {
279   T* field_addr = cast_to_oop(buffered_obj)->field_addr<T>(field_offset);
280   *field_addr = value;
281 }
282 
283 static bool needs_explicit_size(oop src_obj) {
284   Klass* klass = src_obj->klass();
285   int lh = klass->layout_helper();
286 
287   // Simple instances or arrays don't need explicit size
288   if (Klass::layout_helper_is_instance(lh)) {
289     return Klass::layout_helper_needs_slow_path(lh);
290   }
291 
292   return !Klass::layout_helper_is_array(lh);
293 }
294 
295 size_t AOTStreamedHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {


296   if (needs_explicit_size(src_obj)) {
297     // Explicitly write object size for more complex objects, to avoid having to
298     // pretend the buffer objects are objects when loading the objects, in order
299     // to read the size. Most of the time, the layout helper of the class is enough.
300     write<size_t>(src_obj->size());
301   }
302   size_t byte_size = src_obj->size() * HeapWordSize;
303   assert(byte_size > 0, "no zero-size objects");
304 
305   size_t new_used = _buffer_used + byte_size;
306   assert(new_used > _buffer_used, "no wrap around");
307 
308   ensure_buffer_space(new_used);
309 
310   if (HeapShared::is_interned_string(src_obj)) {
311     java_lang_String::hash_code(src_obj);                   // Sets the hash code field(s)
312     java_lang_String::set_deduplication_forbidden(src_obj); // Allows faster interning at runtime
313     assert(java_lang_String::hash_is_set(src_obj), "hash must be set");
314   }
315 
316   address from = cast_from_oop<address>(src_obj);
317   address to = offset_to_buffered_address<address>(_buffer_used);
318   assert(is_object_aligned(_buffer_used), "sanity");
319   assert(is_object_aligned(byte_size), "sanity");
320   memcpy(to, from, byte_size);
321 
322   if (java_lang_Module::is_instance(src_obj)) {
323     // These native pointers will be restored explicitly at run time.
324     Modules::check_archived_module_oop(src_obj);
325     update_buffered_object_field<ModuleEntry*>(to, java_lang_Module::module_entry_offset(), nullptr);
326   } else if (java_lang_ClassLoader::is_instance(src_obj)) {
327 #ifdef ASSERT
328     // We only archive these loaders
329     if (src_obj != SystemDictionary::java_platform_loader() &&
330         src_obj != SystemDictionary::java_system_loader()) {
331       assert(src_obj->klass()->name()->equals("jdk/internal/loader/ClassLoaders$BootClassLoader"), "must be");
332     }
333 #endif
334     update_buffered_object_field<ClassLoaderData*>(to, java_lang_ClassLoader::loader_data_offset(), nullptr);
335   }
336 
337   size_t buffered_obj_offset = _buffer_used;
338   _buffer_used = new_used;
339 
340   return buffered_obj_offset;

357   oopmap->set_bit(idx);
358 }
359 
360 template <typename T> void AOTStreamedHeapWriter::map_oop_field_in_buffer(oop obj, T* field_addr_in_buffer, CHeapBitMap* oopmap) {
361   if (obj == nullptr) {
362     store_oop_in_buffer(field_addr_in_buffer, 0);
363   } else {
364     int dfs_index = *_dfs_order_table->get(obj);
365     store_oop_in_buffer(field_addr_in_buffer, dfs_index);
366   }
367 
368   mark_oop_pointer<T>(field_addr_in_buffer, oopmap);
369 }
370 
371 void AOTStreamedHeapWriter::update_header_for_buffered_addr(address buffered_addr, oop src_obj,  Klass* src_klass) {
372   narrowKlass nk = ArchiveBuilder::current()->get_requested_narrow_klass(src_klass);
373 
374   markWord mw = markWord::prototype();
375   oopDesc* fake_oop = (oopDesc*)buffered_addr;
376 






377   // We need to retain the identity_hash, because it may have been used by some hashtables
378   // in the shared heap. This also has the side effect of pre-initializing the
379   // identity_hash for all shared objects, so they are less likely to be written
380   // into during run time, increasing the potential of memory sharing.
381   if (src_obj != nullptr) {
382     intptr_t src_hash = src_obj->identity_hash();
383     mw = mw.copy_set_hash(src_hash);











384   }
385 
386   if (HeapShared::is_interned_string(src_obj)) {
387     // Mark the mark word of interned string so the loader knows to link these to
388     // the string table at runtime.
389     mw = mw.set_marked();
390   }
391 
392   if (UseCompactObjectHeaders) {
393     fake_oop->set_mark(mw.set_narrow_klass(nk));
394   } else {
395     fake_oop->set_mark(mw);
396     fake_oop->set_narrow_klass(nk);
397   }
398 }
399 
400 class AOTStreamedHeapWriter::EmbeddedOopMapper: public BasicOopIterateClosure {
401   oop _src_obj;
402   address _buffered_obj;
403   CHeapBitMap* _oopmap;
404   bool _is_java_lang_ref;
405 
406 public:
407   EmbeddedOopMapper(oop src_obj, address buffered_obj, CHeapBitMap* oopmap)
408     : _src_obj(src_obj),
409       _buffered_obj(buffered_obj),
410       _oopmap(oopmap),
411       _is_java_lang_ref(AOTReferenceObjSupport::check_if_ref_obj(src_obj)) {}
412 
413   void do_oop(narrowOop *p) { EmbeddedOopMapper::do_oop_work(p); }
414   void do_oop(      oop *p) { EmbeddedOopMapper::do_oop_work(p); }
415 
416 private:
417   template <typename T>

499     int _num_archived_roots;
500     int* _roots;
501 
502   public:
503     StreamedWriterOopIterator(address buffer_start,
504                               int num_archived_objects,
505                               int num_archived_roots,
506                               int* roots)
507       : AOTStreamedHeapOopIterator(buffer_start, num_archived_objects),
508         _num_archived_roots(num_archived_roots),
509         _roots(roots) {}
510 
511     AOTMapLogger::OopData capture(int dfs_index) override {
512       size_t buffered_offset = _dfs_to_archive_object_table[dfs_index];
513       address buffered_addr = _buffer_start + buffered_offset;
514       oop src_obj = AOTStreamedHeapWriter::buffered_offset_to_source_obj(buffered_offset);
515       assert(src_obj != nullptr, "why is this null?");
516       oopDesc* raw_oop = (oopDesc*)buffered_addr;
517       Klass* klass = src_obj->klass();
518       size_t size = src_obj->size();

519 
520       intptr_t target_location = (intptr_t)buffered_offset;
521       uint32_t narrow_location = checked_cast<uint32_t>(dfs_index);
522 
523       address requested_addr = (address)buffered_offset;
524 
525       return { buffered_addr,
526                requested_addr,
527                target_location,
528                narrow_location,
529                raw_oop,
530                klass,
531                size,
532                false };
533     }
534 
535     GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* roots() override {
536       GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* result = new GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>();
537 
538       for (int i = 0; i < _num_archived_roots; ++i) {

276 
277 template <typename T>
278 void update_buffered_object_field(address buffered_obj, int field_offset, T value) {
279   T* field_addr = cast_to_oop(buffered_obj)->field_addr<T>(field_offset);
280   *field_addr = value;
281 }
282 
283 static bool needs_explicit_size(oop src_obj) {
284   Klass* klass = src_obj->klass();
285   int lh = klass->layout_helper();
286 
287   // Simple instances or arrays don't need explicit size
288   if (Klass::layout_helper_is_instance(lh)) {
289     return Klass::layout_helper_needs_slow_path(lh);
290   }
291 
292   return !Klass::layout_helper_is_array(lh);
293 }
294 
295 size_t AOTStreamedHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {
296   size_t old_size = src_obj->size();
297   size_t size = src_obj->copy_size_cds(old_size, src_obj->mark());
298   if (needs_explicit_size(src_obj)) {
299     // Explicitly write object size for more complex objects, to avoid having to
300     // pretend the buffer objects are objects when loading the objects, in order
301     // to read the size. Most of the time, the layout helper of the class is enough.
302     write<size_t>(size);
303   }
304   size_t byte_size = size * HeapWordSize;
305   assert(byte_size > 0, "no zero-size objects");
306 
307   size_t new_used = _buffer_used + byte_size;
308   assert(new_used > _buffer_used, "no wrap around");
309 
310   ensure_buffer_space(new_used);
311 
312   if (HeapShared::is_interned_string(src_obj)) {
313     java_lang_String::hash_code(src_obj);                   // Sets the hash code field(s)
314     java_lang_String::set_deduplication_forbidden(src_obj); // Allows faster interning at runtime
315     assert(java_lang_String::hash_is_set(src_obj), "hash must be set");
316   }
317 
318   address from = cast_from_oop<address>(src_obj);
319   address to = offset_to_buffered_address<address>(_buffer_used);
320   assert(is_object_aligned(_buffer_used), "sanity");
321   assert(is_object_aligned(byte_size), "sanity");
322   memcpy(to, from, MIN2(size, old_size) * HeapWordSize);
323 
324   if (java_lang_Module::is_instance(src_obj)) {
325     // These native pointers will be restored explicitly at run time.
326     Modules::check_archived_module_oop(src_obj);
327     update_buffered_object_field<ModuleEntry*>(to, java_lang_Module::module_entry_offset(), nullptr);
328   } else if (java_lang_ClassLoader::is_instance(src_obj)) {
329 #ifdef ASSERT
330     // We only archive these loaders
331     if (src_obj != SystemDictionary::java_platform_loader() &&
332         src_obj != SystemDictionary::java_system_loader()) {
333       assert(src_obj->klass()->name()->equals("jdk/internal/loader/ClassLoaders$BootClassLoader"), "must be");
334     }
335 #endif
336     update_buffered_object_field<ClassLoaderData*>(to, java_lang_ClassLoader::loader_data_offset(), nullptr);
337   }
338 
339   size_t buffered_obj_offset = _buffer_used;
340   _buffer_used = new_used;
341 
342   return buffered_obj_offset;

359   oopmap->set_bit(idx);
360 }
361 
362 template <typename T> void AOTStreamedHeapWriter::map_oop_field_in_buffer(oop obj, T* field_addr_in_buffer, CHeapBitMap* oopmap) {
363   if (obj == nullptr) {
364     store_oop_in_buffer(field_addr_in_buffer, 0);
365   } else {
366     int dfs_index = *_dfs_order_table->get(obj);
367     store_oop_in_buffer(field_addr_in_buffer, dfs_index);
368   }
369 
370   mark_oop_pointer<T>(field_addr_in_buffer, oopmap);
371 }
372 
373 void AOTStreamedHeapWriter::update_header_for_buffered_addr(address buffered_addr, oop src_obj,  Klass* src_klass) {
374   narrowKlass nk = ArchiveBuilder::current()->get_requested_narrow_klass(src_klass);
375 
376   markWord mw = markWord::prototype();
377   oopDesc* fake_oop = (oopDesc*)buffered_addr;
378 
379   if (UseCompactObjectHeaders) {
380     mw = mw.set_narrow_klass(nk);
381   } else {
382     fake_oop->set_narrow_klass(nk);
383   }
384 
385   // We need to retain the identity_hash, because it may have been used by some hashtables
386   // in the shared heap. This also has the side effect of pre-initializing the
387   // identity_hash for all shared objects, so they are less likely to be written
388   // into during run time, increasing the potential of memory sharing.
389   if (src_obj != nullptr) {
390     if (UseCompactObjectHeaders) {
391       mw = mw.copy_hashctrl_from(src_obj->mark());
392       if (mw.is_hashed_not_expanded()) {
393         mw = fake_oop->initialize_hash_if_necessary(src_obj, src_klass, mw);
394       } else if (mw.is_not_hashed_expanded()) {
395         // If a scratch mirror class has not been hashed until now, then reset its
396         // hash bits to initial state.
397         mw = mw.set_not_hashed_not_expanded();
398       }
399     } else {
400       intptr_t src_hash = src_obj->identity_hash();
401       mw = mw.copy_set_hash(src_hash);
402     }
403   }
404 
405   if (HeapShared::is_interned_string(src_obj)) {
406     // Mark the mark word of interned string so the loader knows to link these to
407     // the string table at runtime.
408     mw = mw.set_marked();
409   }
410 
411   fake_oop->set_mark(mw);





412 }
413 
414 class AOTStreamedHeapWriter::EmbeddedOopMapper: public BasicOopIterateClosure {
415   oop _src_obj;
416   address _buffered_obj;
417   CHeapBitMap* _oopmap;
418   bool _is_java_lang_ref;
419 
420 public:
421   EmbeddedOopMapper(oop src_obj, address buffered_obj, CHeapBitMap* oopmap)
422     : _src_obj(src_obj),
423       _buffered_obj(buffered_obj),
424       _oopmap(oopmap),
425       _is_java_lang_ref(AOTReferenceObjSupport::check_if_ref_obj(src_obj)) {}
426 
427   void do_oop(narrowOop *p) { EmbeddedOopMapper::do_oop_work(p); }
428   void do_oop(      oop *p) { EmbeddedOopMapper::do_oop_work(p); }
429 
430 private:
431   template <typename T>

513     int _num_archived_roots;
514     int* _roots;
515 
516   public:
517     StreamedWriterOopIterator(address buffer_start,
518                               int num_archived_objects,
519                               int num_archived_roots,
520                               int* roots)
521       : AOTStreamedHeapOopIterator(buffer_start, num_archived_objects),
522         _num_archived_roots(num_archived_roots),
523         _roots(roots) {}
524 
525     AOTMapLogger::OopData capture(int dfs_index) override {
526       size_t buffered_offset = _dfs_to_archive_object_table[dfs_index];
527       address buffered_addr = _buffer_start + buffered_offset;
528       oop src_obj = AOTStreamedHeapWriter::buffered_offset_to_source_obj(buffered_offset);
529       assert(src_obj != nullptr, "why is this null?");
530       oopDesc* raw_oop = (oopDesc*)buffered_addr;
531       Klass* klass = src_obj->klass();
532       size_t size = src_obj->size();
533       size = src_obj->copy_size_cds(size, src_obj->mark());
534 
535       intptr_t target_location = (intptr_t)buffered_offset;
536       uint32_t narrow_location = checked_cast<uint32_t>(dfs_index);
537 
538       address requested_addr = (address)buffered_offset;
539 
540       return { buffered_addr,
541                requested_addr,
542                target_location,
543                narrow_location,
544                raw_oop,
545                klass,
546                size,
547                false };
548     }
549 
550     GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* roots() override {
551       GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* result = new GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>();
552 
553       for (int i = 0; i < _num_archived_roots; ++i) {
< prev index next >