1 /*
  2  * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  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 "gc/shared/memAllocator.hpp"
 26 #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp"
 27 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
 28 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
 29 #include "gc/shenandoah/shenandoahObjArrayAllocator.hpp"
 30 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
 31 #include "memory/universe.hpp"
 32 #include "oops/arrayKlass.hpp"
 33 #include "oops/arrayOop.hpp"
 34 #include "runtime/interfaceSupport.inline.hpp"
 35 #include "utilities/copy.hpp"
 36 #include "utilities/globalDefinitions.hpp"
 37 
 38 ShenandoahObjArrayAllocator::ShenandoahObjArrayAllocator(
 39     Klass* klass, size_t word_size, int length, bool do_zero, Thread* thread)
 40   : ObjArrayAllocator(klass, word_size, length, do_zero, thread) {
 41   assert(_length >= 0, "length should be non-negative");
 42 }
 43 
 44 oop ShenandoahObjArrayAllocator::initialize(HeapWord* mem) const {
 45   // threshold of object size, while above this size current mutator will yield to safepoint
 46   // when it clears the array content.
 47   constexpr size_t THRESHOLD = 64 * K / BytesPerWord;
 48 
 49   ShenandoahHeap* const heap = ShenandoahHeap::heap();
 50 
 51   // Fast path: delegate to base class for small arrays or no-zero case.
 52   // In no-zero case(_do_zero is false), the content of the array won't be zeroed, therefore no need to fall into slow-path.
 53   if (!_do_zero || _word_size <= THRESHOLD) {
 54     return ObjArrayAllocator::initialize(mem);
 55   }
 56 
 57   // Slow path: yield to safepoint when clearing for large arrays
 58 
 59   // Compute clearing bounds
 60   const BasicType element_type = ArrayKlass::cast(_klass)->element_type();
 61   const size_t base_offset_in_bytes = (size_t)arrayOopDesc::base_offset_in_bytes(element_type);
 62   const size_t process_start_offset_in_bytes = align_up(base_offset_in_bytes, (size_t)BytesPerWord);
 63 
 64   const size_t process_start = process_start_offset_in_bytes / BytesPerWord;
 65   const size_t process_size = _word_size - process_start;
 66 
 67   // Pin the region before clearing to avoid moving the object until it is done
 68   ShenandoahHeapRegion* region = heap->heap_region_containing(mem);
 69   region->record_pin();
 70 
 71   // Always initialize the mem with primitive array first so GC won't look into the elements in the array.
 72   // For obj array, the header will be corrected to object array after clearing the memory.
 73   Klass* filling_klass = _klass;
 74 
 75   // Flat arrays containing oops are not supported and only contain primitives
 76   // from here on out.
 77   const bool is_ref_type = (element_type != T_FLAT_ELEMENT) && is_reference_type(element_type);
 78 
 79   if (is_ref_type) {
 80     filling_klass = LP64_ONLY(UseCompressedOops ? Universe::intArrayKlass() : Universe::longArrayKlass()) NOT_LP64(Universe::intArrayKlass());
 81     assert(type2aelembytes(ArrayKlass::cast(filling_klass)->element_type()) == type2aelembytes(element_type), "filling element size must match ref size");
 82   }
 83   // Use _length directly: it matches the ref count, and the filling element size equals the ref size.
 84   ObjArrayAllocator filling_array_allocator(filling_klass, _word_size, _length, /* do_zero */ false);
 85   filling_array_allocator.initialize(mem);
 86 
 87   // Invisible roots will be scanned and marked at the end of marking.
 88   ShenandoahThreadLocalData::set_invisible_root(_thread, mem, _word_size);
 89 
 90   {
 91     // The mem has been initialized as primitive array, the entire clearing work is safe for safepoint
 92     ThreadBlockInVM tbivm(JavaThread::cast(_thread)); // Allow safepoint to proceed.
 93     // Handle potential 4-byte alignment gap before array data
 94     if (process_start_offset_in_bytes != base_offset_in_bytes) {
 95       assert(process_start_offset_in_bytes - base_offset_in_bytes == 4, "Must be 4-byte aligned");
 96       *reinterpret_cast<int*>(reinterpret_cast<char*>(mem) + base_offset_in_bytes) = 0;
 97     }
 98 
 99     Copy::zero_to_words(mem + process_start, process_size);
100 
101     if (!is_ref_type) {
102       // zap paddings
103       mem_zap_start_padding(mem);
104       mem_zap_end_padding(mem);
105     }
106   }
107 
108   // reference array, header need to be overridden to its own.
109   if (is_ref_type) {
110     finish(mem);
111     // zap paddings after setting correct klass
112     mem_zap_start_padding(mem);
113     mem_zap_end_padding(mem);
114   }
115 
116   oop arrayObj = cast_to_oop(mem);
117   if (heap->is_concurrent_young_mark_in_progress() && !heap->marking_context()->allocated_after_mark_start(arrayObj)) {
118     // Keep the obj alive because we don't know the progress of marking,
119     // current concurrent marking could have done and VM is calling safepoint for final mark.
120     heap->keep_alive(arrayObj);
121   }
122   ShenandoahThreadLocalData::clear_invisible_root(_thread);
123 
124   region->record_unpin();
125 
126   return arrayObj;
127 }