@@ -135,7 +135,7 @@ bool Heap::all_objects_are_unmarked() {
135
135
namespace {
136
136
void mark_recursively (std::queue<Object *> &queue, bool gc_bit_marked, Reference to_mark,
137
137
std::unordered_set<Object *> const &all_object_pointers) {
138
- auto mark = [&queue, gc_bit_marked, &all_object_pointers](Reference reference) {
138
+ auto enqueue = [&queue, gc_bit_marked, &all_object_pointers](Reference reference) {
139
139
if (reference != JAVA_NULL) {
140
140
Object *object = reference.object ();
141
141
(void ) all_object_pointers;
@@ -148,65 +148,56 @@ void mark_recursively(std::queue<Object *> &queue, bool gc_bit_marked, Reference
148
148
}
149
149
};
150
150
151
- mark (to_mark);
151
+ enqueue (to_mark);
152
152
153
153
while (!queue.empty ()) {
154
154
Object *object = queue.front ();
155
155
queue.pop ();
156
156
157
157
ClassFile *clazz = object->clazz ;
158
- mark (Reference{clazz});
158
+ enqueue (Reference{clazz});
159
159
160
+ // Mark fields of instances and array elements.
161
+ // Keep in mind that classes are also instances that have fields.
160
162
if (!clazz->is_array ()) {
161
163
// TODO we might have to initializes more classes
162
164
assert (clazz->resolved );
163
165
166
+ // we only need to check superclasses because interfaces don't have instance fields
164
167
for (ClassFile *current = clazz; current != nullptr ; current = current->super_class ) {
165
168
for (const auto &field : current->fields ) {
166
- auto const &descriptor = field.descriptor_index ->value ;
167
- if (descriptor.starts_with (" L" ) || descriptor.starts_with (" [" )) {
168
- if (field.is_static ()) {
169
- // static fields are handled when the class itself is marked
170
- } else {
171
- Reference reference{object};
172
- mark (reference.data <Value>()[field.index ].reference );
173
- }
169
+ if (!field.is_static () && field.is_reference_type ()) {
170
+ enqueue (Reference{object}.data <Value>()[field.index ].reference );
174
171
}
175
172
}
176
173
}
177
- } else {
178
- if (!clazz->array_element_type ->is_primitive ()) {
179
- Reference reference{object};
180
- for (s4 i = 0 ; i < object->length ; ++i) {
181
- mark (reference.data <Reference>()[i]);
182
- }
174
+ } else if (!clazz->array_element_type ->is_primitive ()) {
175
+ for (s4 i = 0 ; i < object->length ; ++i) {
176
+ enqueue (Reference{object}.data <Reference>()[i]);
183
177
}
184
178
}
185
179
180
+ // Classes are also objects. When they are marked we also need to
181
+ // enqueue references that are stored in their C++ representation:
186
182
if (clazz->name () == Names::java_lang_Class) {
187
183
auto class_instance = reinterpret_cast <ClassFile *> (object);
188
184
189
- // TODO check if ClassFile references other objects (e.g. inside constant pool entries)
190
-
191
185
// TODO this would not be necessary if classloaders keep a list of loaded clases
192
- mark (Reference{class_instance->super_class });
186
+ enqueue (Reference{class_instance->super_class });
193
187
for (const auto &item : class_instance->interfaces ) {
194
- mark (Reference{item->clazz });
188
+ enqueue (Reference{item->clazz });
195
189
}
196
190
191
+ // resolved classes can have static variables:
197
192
if (class_instance->resolved ) {
198
193
for (const auto &field : class_instance->fields ) {
199
- auto const &descriptor = field.descriptor_index ->value ;
200
- if (descriptor.starts_with (" L" ) || descriptor.starts_with (" [" )) {
201
- if (field.is_static ()) {
202
- mark (class_instance->static_field_values [field.index ].reference );
203
- } else {
204
- // These would be the fields of an instance of class_instance.
205
- // The real fields (from java/lang/Class) have been marked in the loop above.
206
- }
194
+ if (field.is_static () && field.is_reference_type ()) {
195
+ enqueue (class_instance->static_field_values [field.index ].reference );
207
196
}
208
197
}
209
198
}
199
+
200
+ // TODO check if ClassFile references any other objects (e.g. inside constant pool entries)
210
201
}
211
202
}
212
203
};
@@ -219,6 +210,9 @@ void Heap::mark(std::vector<Thread *> &threads, bool gc_bit_marked) {
219
210
return value != 0 && (value % alignof (std::max_align_t )) == 0 ;
220
211
};
221
212
213
+ // Build a hashmap of all known allocations to determine out which
214
+ // values on the operand stack and in local variables are pointers.
215
+ // TODO statically determine the types instead (see StackMapTable Attribute)
222
216
std::unordered_set<Object *> all_object_pointers;
223
217
for (const auto &clazz : classes) {
224
218
auto *object = reinterpret_cast <Object *>(clazz.get ());
0 commit comments