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