1 /* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #ifndef SHARE_OOPS_INSTANCESTACKCHUNKKLASS_INLINE_HPP 25 #define SHARE_OOPS_INSTANCESTACKCHUNKKLASS_INLINE_HPP 26 27 #include "oops/instanceStackChunkKlass.hpp" 28 29 #include "oops/oop.inline.hpp" 30 #include "oops/stackChunkOop.inline.hpp" 31 #include "runtime/continuationJavaClasses.hpp" 32 #include "runtime/frame.inline.hpp" 33 #include "runtime/handles.inline.hpp" 34 #include "utilities/bitMap.inline.hpp" 35 #include "utilities/debug.hpp" 36 #include "utilities/devirtualizer.inline.hpp" 37 #include "utilities/globalDefinitions.hpp" 38 #include "utilities/macros.hpp" 39 40 inline size_t InstanceStackChunkKlass::instance_size(size_t stack_size_in_words) const { 41 return align_object_size(size_helper() + stack_size_in_words + gc_data_size(stack_size_in_words)); 42 } 43 44 inline size_t InstanceStackChunkKlass::bitmap_size_in_bits(size_t stack_size_in_words) { 45 // Need one bit per potential narrowOop* or oop* address. 46 size_t size_in_bits = stack_size_in_words << (LogBitsPerWord - LogBitsPerHeapOop); 47 48 return align_up(size_in_bits, BitsPerWord); 49 } 50 51 inline size_t InstanceStackChunkKlass::gc_data_size(size_t stack_size_in_words) { 52 // At the moment all GCs are okay with GC data big enough to fit a bit map 53 return bitmap_size(stack_size_in_words); 54 } 55 56 inline size_t InstanceStackChunkKlass::bitmap_size(size_t stack_size_in_words) { 57 return bitmap_size_in_bits(stack_size_in_words) >> LogBitsPerWord; 58 } 59 60 template <typename T, class OopClosureType> 61 void InstanceStackChunkKlass::oop_oop_iterate(oop obj, OopClosureType* closure) { 62 stackChunkOop chunk = stackChunkOopDesc::cast(obj); 63 if (Devirtualizer::do_metadata(closure)) { 64 Devirtualizer::do_klass(closure, this); 65 } 66 oop_oop_iterate_stack<T>(chunk, closure); 67 oop_oop_iterate_header<T>(chunk, closure); 68 oop_oop_iterate_lockstack<T>(chunk, closure, chunk->range()); 69 } 70 71 template <typename T, class OopClosureType> 72 void InstanceStackChunkKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) { 73 assert(!Devirtualizer::do_metadata(closure), "Code to handle metadata is not implemented"); 74 stackChunkOop chunk = stackChunkOopDesc::cast(obj); 75 oop_oop_iterate_stack<T>(chunk, closure); 76 oop_oop_iterate_header<T>(chunk, closure); 77 oop_oop_iterate_lockstack<T>(chunk, closure, chunk->range()); 78 } 79 80 template <typename T, class OopClosureType> 81 void InstanceStackChunkKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) { 82 stackChunkOop chunk = stackChunkOopDesc::cast(obj); 83 if (Devirtualizer::do_metadata(closure)) { 84 if (mr.contains(obj)) { 85 Devirtualizer::do_klass(closure, this); 86 } 87 } 88 oop_oop_iterate_stack_bounded<T>(chunk, closure, mr); 89 oop_oop_iterate_header_bounded<T>(chunk, closure, mr); 90 oop_oop_iterate_lockstack<T>(chunk, closure, mr); 91 } 92 93 template <typename T, class OopClosureType> 94 void InstanceStackChunkKlass::oop_oop_iterate_header(stackChunkOop chunk, OopClosureType* closure) { 95 T* parent_addr = chunk->field_addr<T>(jdk_internal_vm_StackChunk::parent_offset()); 96 T* cont_addr = chunk->field_addr<T>(jdk_internal_vm_StackChunk::cont_offset()); 97 Devirtualizer::do_oop(closure, parent_addr); 98 Devirtualizer::do_oop(closure, cont_addr); 99 } 100 101 template <typename T, class OopClosureType> 102 void InstanceStackChunkKlass::oop_oop_iterate_header_bounded(stackChunkOop chunk, OopClosureType* closure, MemRegion mr) { 103 T* parent_addr = chunk->field_addr<T>(jdk_internal_vm_StackChunk::parent_offset()); 104 T* cont_addr = chunk->field_addr<T>(jdk_internal_vm_StackChunk::cont_offset()); 105 if (mr.contains(parent_addr)) { 106 Devirtualizer::do_oop(closure, parent_addr); 107 } 108 if (mr.contains(cont_addr)) { 109 Devirtualizer::do_oop(closure, cont_addr); 110 } 111 } 112 113 template <typename T, class OopClosureType> 114 void InstanceStackChunkKlass::oop_oop_iterate_stack_bounded(stackChunkOop chunk, OopClosureType* closure, MemRegion mr) { 115 if (chunk->has_bitmap()) { 116 intptr_t* start = chunk->sp_address() - frame::metadata_words_at_bottom; 117 intptr_t* end = chunk->end_address(); 118 // mr.end() can actually be less than start. In that case, we only walk the metadata 119 if ((intptr_t*)mr.start() > start) { 120 start = (intptr_t*)mr.start(); 121 } 122 if ((intptr_t*)mr.end() < end) { 123 end = (intptr_t*)mr.end(); 124 } 125 oop_oop_iterate_stack_with_bitmap<T>(chunk, closure, start, end); 126 } else { 127 oop_oop_iterate_stack_slow(chunk, closure, mr); 128 } 129 } 130 131 template <typename T, class OopClosureType> 132 void InstanceStackChunkKlass::oop_oop_iterate_stack(stackChunkOop chunk, OopClosureType* closure) { 133 if (chunk->has_bitmap()) { 134 oop_oop_iterate_stack_with_bitmap<T>(chunk, closure, chunk->sp_address() - frame::metadata_words_at_bottom, chunk->end_address()); 135 } else { 136 oop_oop_iterate_stack_slow(chunk, closure, chunk->range()); 137 } 138 } 139 140 template <typename T, class OopClosureType> 141 class StackChunkOopIterateBitmapClosure { 142 stackChunkOop _chunk; 143 OopClosureType* const _closure; 144 145 public: 146 StackChunkOopIterateBitmapClosure(stackChunkOop chunk, OopClosureType* closure) : _chunk(chunk), _closure(closure) {} 147 148 bool do_bit(BitMap::idx_t index) { 149 Devirtualizer::do_oop(_closure, _chunk->address_for_bit<T>(index)); 150 return true; 151 } 152 }; 153 154 template <typename T, class OopClosureType> 155 void InstanceStackChunkKlass::oop_oop_iterate_stack_with_bitmap(stackChunkOop chunk, OopClosureType* closure, 156 intptr_t* start, intptr_t* end) { 157 if (Devirtualizer::do_metadata(closure)) { 158 do_methods(chunk, closure); 159 } 160 161 if (end > start) { 162 StackChunkOopIterateBitmapClosure<T, OopClosureType> bitmap_closure(chunk, closure); 163 chunk->bitmap().iterate(&bitmap_closure, chunk->bit_index_for((T*)start), chunk->bit_index_for((T*)end)); 164 } 165 } 166 167 #endif // SHARE_OOPS_INSTANCESTACKCHUNKKLASS_INLINE_HPP