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 } 69 70 template <typename T, class OopClosureType> 71 void InstanceStackChunkKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) { 72 assert(!Devirtualizer::do_metadata(closure), "Code to handle metadata is not implemented"); 73 stackChunkOop chunk = stackChunkOopDesc::cast(obj); 74 oop_oop_iterate_stack<T>(chunk, closure); 75 oop_oop_iterate_header<T>(chunk, closure); 76 } 77 78 template <typename T, class OopClosureType> 79 void InstanceStackChunkKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) { 80 stackChunkOop chunk = stackChunkOopDesc::cast(obj); 81 if (Devirtualizer::do_metadata(closure)) { 82 if (mr.contains(obj)) { 83 Devirtualizer::do_klass(closure, this); 84 } 85 } 86 oop_oop_iterate_stack_bounded<T>(chunk, closure, mr); 87 oop_oop_iterate_header_bounded<T>(chunk, closure, mr); 88 } 89 90 template <typename T, class OopClosureType> 91 void InstanceStackChunkKlass::oop_oop_iterate_header(stackChunkOop chunk, OopClosureType* closure) { 92 T* parent_addr = chunk->field_addr<T>(jdk_internal_vm_StackChunk::parent_offset()); 93 T* cont_addr = chunk->field_addr<T>(jdk_internal_vm_StackChunk::cont_offset()); 94 Devirtualizer::do_oop(closure, parent_addr); 95 Devirtualizer::do_oop(closure, cont_addr); 96 } 97 98 template <typename T, class OopClosureType> 99 void InstanceStackChunkKlass::oop_oop_iterate_header_bounded(stackChunkOop chunk, OopClosureType* closure, MemRegion mr) { 100 T* parent_addr = chunk->field_addr<T>(jdk_internal_vm_StackChunk::parent_offset()); 101 T* cont_addr = chunk->field_addr<T>(jdk_internal_vm_StackChunk::cont_offset()); 102 if (mr.contains(parent_addr)) { 103 Devirtualizer::do_oop(closure, parent_addr); 104 } 105 if (mr.contains(cont_addr)) { 106 Devirtualizer::do_oop(closure, cont_addr); 107 } 108 } 109 110 template <typename T, class OopClosureType> 111 void InstanceStackChunkKlass::oop_oop_iterate_stack_bounded(stackChunkOop chunk, OopClosureType* closure, MemRegion mr) { 112 if (chunk->has_bitmap()) { 113 intptr_t* start = chunk->sp_address() - frame::metadata_words_at_bottom; 114 intptr_t* end = chunk->end_address(); 115 // mr.end() can actually be less than start. In that case, we only walk the metadata 116 if ((intptr_t*)mr.start() > start) { 117 start = (intptr_t*)mr.start(); 118 } 119 if ((intptr_t*)mr.end() < end) { 120 end = (intptr_t*)mr.end(); 121 } 122 oop_oop_iterate_stack_with_bitmap<T>(chunk, closure, start, end); 123 } else { 124 oop_oop_iterate_stack_slow(chunk, closure, mr); 125 } 126 } 127 128 template <typename T, class OopClosureType> 129 void InstanceStackChunkKlass::oop_oop_iterate_stack(stackChunkOop chunk, OopClosureType* closure) { 130 if (chunk->has_bitmap()) { 131 oop_oop_iterate_stack_with_bitmap<T>(chunk, closure, chunk->sp_address() - frame::metadata_words_at_bottom, chunk->end_address()); 132 } else { 133 oop_oop_iterate_stack_slow(chunk, closure, chunk->range()); 134 } 135 } 136 137 template <typename T, class OopClosureType> 138 class StackChunkOopIterateBitmapClosure { 139 stackChunkOop _chunk; 140 OopClosureType* const _closure; 141 142 public: 143 StackChunkOopIterateBitmapClosure(stackChunkOop chunk, OopClosureType* closure) : _chunk(chunk), _closure(closure) {} 144 145 bool do_bit(BitMap::idx_t index) { 146 Devirtualizer::do_oop(_closure, _chunk->address_for_bit<T>(index)); 147 return true; 148 } 149 }; 150 151 template <typename T, class OopClosureType> 152 void InstanceStackChunkKlass::oop_oop_iterate_stack_with_bitmap(stackChunkOop chunk, OopClosureType* closure, 153 intptr_t* start, intptr_t* end) { 154 if (Devirtualizer::do_metadata(closure)) { 155 do_methods(chunk, closure); 156 } 157 158 if (end > start) { 159 StackChunkOopIterateBitmapClosure<T, OopClosureType> bitmap_closure(chunk, closure); 160 chunk->bitmap().iterate(&bitmap_closure, chunk->bit_index_for((T*)start), chunk->bit_index_for((T*)end)); 161 } 162 } 163 164 #endif // SHARE_OOPS_INSTANCESTACKCHUNKKLASS_INLINE_HPP