Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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);
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}