static struct GC_ms_entry* markObject(GC_word* addr, struct GC_ms_entry* mark_stack_ptr, struct GC_ms_entry* mark_stack_limit, GC_word env) { Object* obj = (Object*) addr; if (obj == NULL || obj->clazz == NULL || obj->clazz->object.clazz != java_lang_Class) { // According to the comments in gc_mark.h the GC sometimes calls the mark_proc with unused objects. // Such objects have been cleared except for the first word which points to a free list link field. // A valid RovoVM Object must point to a Class and the Class of the Object's Class must be java.lang.Class. return mark_stack_ptr; } mark_stack_ptr = GC_MARK_AND_PUSH(obj->clazz, mark_stack_ptr, mark_stack_limit, NULL); if (obj->clazz == java_lang_Class) { // Class* Class* clazz = (Class*) obj; mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_data, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH((void*) clazz->name, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->classLoader, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->superclass, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->componentType, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_interfaces, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_fields, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_methods, mark_stack_ptr, mark_stack_limit, NULL); void** start = (void**) (((char*) clazz) + offsetof(Class, data)); void** end = (void**) (((char*) start) + clazz->classRefCount * sizeof(Object*)); mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } else if (CLASS_IS_ARRAY(obj->clazz)) { if (!CLASS_IS_PRIMITIVE(obj->clazz->componentType)) { // Array of objects. Mark all values in the array. ObjectArray* array = (ObjectArray*) obj; void** start = (void**) (((char*) array) + offsetof(ObjectArray, values)); void** end = (void**) (((char*) start) + sizeof(Object*) * array->length); mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } } else { // Object* - for each Class in the hierarchy of obj's Class we mark the first instanceRefCount*sizeof(Object*) bytes Class* clazz = obj->clazz; while (clazz != NULL) { void** start = (void**) (((char*) obj) + clazz->instanceDataOffset); void** end = (void**) (((char*) start) + clazz->instanceRefCount * sizeof(Object*)); if (clazz == java_lang_ref_Reference) { // Don't mark the referent field void** referent_start = (void**) (((char*) obj) + java_lang_ref_Reference_referent->offset); void** referent_end = (void**) (((char*) referent_start) + sizeof(Object*)); mark_stack_ptr = markRegion(start, referent_start, mark_stack_ptr, mark_stack_limit); mark_stack_ptr = markRegion(referent_end, end, mark_stack_ptr, mark_stack_limit); } else { mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } clazz = clazz->superclass; } } return mark_stack_ptr; }
static inline struct GC_ms_entry* markRegion(void** start, void** end, struct GC_ms_entry* mark_stack_ptr, struct GC_ms_entry* mark_stack_limit) { void** p = start; while (p < end) { mark_stack_ptr = GC_MARK_AND_PUSH(*p, mark_stack_ptr, mark_stack_limit, NULL); p++; } return mark_stack_ptr; }
struct GC_ms_entry * fake_gcj_mark_proc(word * addr, struct GC_ms_entry *mark_stack_ptr, struct GC_ms_entry *mark_stack_limit, word env ) { sexpr x; if (1 == env) { /* Object allocated with debug allocator. */ addr = (word *)GC_USR_PTR_FROM_BASE(addr); } x = (sexpr)(addr + 1); /* Skip the vtable pointer. */ mark_stack_ptr = GC_MARK_AND_PUSH( (void *)(x -> sexpr_cdr), mark_stack_ptr, mark_stack_limit, (void * *)&(x -> sexpr_cdr)); mark_stack_ptr = GC_MARK_AND_PUSH( (void *)(x -> sexpr_car), mark_stack_ptr, mark_stack_limit, (void * *)&(x -> sexpr_car)); return(mark_stack_ptr); }
static struct GC_ms_entry * mark_weak_value_table (GC_word *addr, struct GC_ms_entry *mark_stack_ptr, struct GC_ms_entry *mark_stack_limit, GC_word env) { scm_t_weak_entry *entries = (scm_t_weak_entry*) addr; unsigned long k, size = GC_size (addr) / sizeof (scm_t_weak_entry); for (k = 0; k < size; k++) if (entries[k].hash && entries[k].value) { SCM key = SCM_PACK (entries[k].key); mark_stack_ptr = GC_MARK_AND_PUSH ((GC_word*) SCM2PTR (key), mark_stack_ptr, mark_stack_limit, NULL); } return mark_stack_ptr; }
static struct GC_ms_entry* markObject(GC_word* addr, struct GC_ms_entry* mark_stack_ptr, struct GC_ms_entry* mark_stack_limit, GC_word env) { Object* obj = (Object*) addr; if (obj == NULL || obj->clazz == NULL || obj->clazz->object.clazz != java_lang_Class) { // According to the comments in gc_mark.h the GC sometimes calls the mark_proc with unused objects. // Such objects have been cleared except for the first word which points to a free list link field. // A valid RovoVM Object must point to a Class and the Class of the Object's Class must be java.lang.Class. return mark_stack_ptr; } // This mark procedure should never be called for array instances. assert(!CLASS_IS_ARRAY(obj->clazz)); mark_stack_ptr = GC_MARK_AND_PUSH(obj->clazz, mark_stack_ptr, mark_stack_limit, NULL); if (obj->clazz == java_lang_Class) { // Class* Class* clazz = (Class*) obj; mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_data, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH((void*) clazz->name, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->typeInfo, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->vitable, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->itables, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->classLoader, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->superclass, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->componentType, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_interfaces, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_fields, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_methods, mark_stack_ptr, mark_stack_limit, NULL); void** start = (void**) (((char*) clazz) + offsetof(Class, data)); void** end = (void**) (((char*) start) + clazz->classRefCount * sizeof(Object*)); mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } else { // Object* - for each Class in the hierarchy of obj's Class we mark the first instanceRefCount*sizeof(Object*) bytes Class* clazz = obj->clazz; while (clazz != NULL) { void** start = (void**) (((char*) obj) + clazz->instanceDataOffset); void** end = (void**) (((char*) start) + clazz->instanceRefCount * sizeof(Object*)); if (clazz == java_lang_ref_Reference) { // Don't mark the referent field void** referent_start = (void**) (((char*) obj) + java_lang_ref_Reference_referent->offset); void** referent_end = (void**) (((char*) referent_start) + sizeof(Object*)); mark_stack_ptr = markRegion(start, referent_start, mark_stack_ptr, mark_stack_limit); mark_stack_ptr = markRegion(referent_end, end, mark_stack_ptr, mark_stack_limit); } else { mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } // Some classes use longs and ints to store pointers to GC allocated memory. // For each such class we need to mark those fields here. // Note: java.lang.Thread, java.lang.reflect.Constructor, java.lang.reflect.Method, // java.lang.reflect.Field also contain such fields but we don't have // to mark those because the Thread, Method and Field C structures those // point to are also referenced by other roots (the threads list, Class structures) // that prevent GCing. if (clazz == java_lang_Throwable) { // The 'stackState' field in java.lang.Throwable is a long but contains // a pointer to an address on the GCed heap. void** field_start = (void**) (((char*) obj) + java_lang_Throwable_stackState->offset); void** field_end = (void**) (((char*) field_start) + sizeof(jlong)); mark_stack_ptr = markRegion(field_start, field_end, mark_stack_ptr, mark_stack_limit); } else if (clazz == org_robovm_rt_bro_Struct) { // The 'handle' field in org.robovm.rt.bro.Struct (actually in its // superclass NativeObject) is a long but contains a pointer. // Possibly to an address on the GCed heap. void** field_start = (void**) (((char*) obj) + org_robovm_rt_bro_Struct_handle->offset); void** field_end = (void**) (((char*) field_start) + sizeof(jlong)); mark_stack_ptr = markRegion(field_start, field_end, mark_stack_ptr, mark_stack_limit); } else if (clazz == java_nio_MemoryBlock) { // The 'address' field in java.nio.MemoryBlock is a long but contains a pointer. // Possibly to an address on the GCed heap. void** field_start = (void**) (((char*) obj) + java_nio_MemoryBlock_address->offset); void** field_end = (void**) (((char*) field_start) + sizeof(jlong)); mark_stack_ptr = markRegion(field_start, field_end, mark_stack_ptr, mark_stack_limit); } clazz = clazz->superclass; } } return mark_stack_ptr; }