diff --git a/libgst/oop.c b/libgst/oop.c index 9d7b242..244601d 100644 --- a/libgst/oop.c +++ b/libgst/oop.c @@ -2242,68 +2242,89 @@ _gst_add_an_oop_to_mark_queue (OOP oop) void _gst_mark (void) { - while (_gst_mem.currentMarkQueue > _gst_mem.markQueue) - { - int i, n; - OOP oop; - gst_object obj; + int n; + OOP oop; + gst_object obj; - PREFETCH_LOOP (_gst_mem.currentMarkQueue, PREF_READ | PREF_NTA); - _gst_mem.currentMarkQueue--; - oop = *_gst_mem.currentMarkQueue; - obj = OOP_TO_OBJ (oop); + if (_gst_mem.currentMarkQueue <= _gst_mem.markQueue) + return ; + + _gst_mem.currentMarkQueue--; + oop = *_gst_mem.currentMarkQueue; + obj = OOP_TO_OBJ (oop); #if defined(GC_DEBUG_OUTPUT) - printf (">Mark "); - _gst_display_oop (oop); + printf (">Mark "); + _gst_display_oop (oop); - if UNCOMMON (!IS_OOP_ADDR (oop)) - { - printf - ("Error! Invalid OOP %p was found inside %p!\n", - oop, obj); - abort (); - } + if UNCOMMON (!IS_OOP_ADDR (oop)) + { + printf + ("Error! Invalid OOP %p was found inside %p!\n", + oop, obj); + abort (); + } #endif - if UNCOMMON (oop->flags & F_CONTEXT) - { - gst_method_context ctx; - intptr_t methodSP; - ctx = (gst_method_context) obj; - methodSP = TO_INT (ctx->spOffset); - n = ctx->contextStack + methodSP + 1 - obj->data; - - for (i = 0; i < n; i++) - _gst_add_an_oop_to_mark_queue (obj->data[i]); - - _gst_add_an_oop_to_mark_queue (obj->objClass); - } - else if UNCOMMON (oop->flags & (F_EPHEMERON | F_WEAK)) - { - if (oop->flags & F_EPHEMERON) - _gst_add_buf_pointer (oop); + if UNCOMMON (oop->flags & F_CONTEXT) + { + gst_method_context ctx; + intptr_t methodSP; + ctx = (gst_method_context) obj; + methodSP = TO_INT (ctx->spOffset); + n = ctx->contextStack + methodSP + 1 - obj->data; - _gst_add_an_oop_to_mark_queue (obj->objClass); - } - else - { - n = NUM_OOPS (obj); + _gst_mark_oop_range (&obj->data[0], &obj->data[n]); + _gst_add_an_oop_to_mark_queue (obj->objClass); + } + else if UNCOMMON (oop->flags & (F_EPHEMERON | F_WEAK)) + { + if (oop->flags & F_EPHEMERON) + _gst_add_buf_pointer (oop); - for (i = 0; i < n; i++) - _gst_add_an_oop_to_mark_queue (obj->data[i]); + _gst_add_an_oop_to_mark_queue (obj->objClass); + } + else + { + n = NUM_OOPS (obj); - _gst_add_an_oop_to_mark_queue (obj->objClass); - } + _gst_mark_oop_range (&obj->data[0], &obj->data[n]); + _gst_add_an_oop_to_mark_queue (obj->objClass); } + + _gst_mark (); } void _gst_mark_oop_range (OOP *curOOP, OOP *atEndOOP) { - OOP *pOOP; - for (pOOP = curOOP; pOOP < atEndOOP; pOOP++) - MAYBE_MARK_OOP (*pOOP); + OOP *pOOP = curOOP; + + while (pOOP < atEndOOP) + { + OOP oop = *pOOP; + + if (!IS_OOP (oop) || IS_OOP_MARKED (oop)) + { + pOOP++; + continue ; + } + + if (_gst_mem.currentMarkQueue == _gst_mem.lastMarkQueue) + { + const size_t size = _gst_mem.lastMarkQueue - _gst_mem.markQueue; + + _gst_mem.markQueue = (OOP *) xrealloc (_gst_mem.markQueue, 10 * size * sizeof (*_gst_mem.markQueue)); + _gst_mem.currentMarkQueue = &_gst_mem.markQueue[size]; + _gst_mem.lastMarkQueue = &_gst_mem.markQueue[10 * size]; + } + + oop->flags |= F_REACHABLE; + *_gst_mem.currentMarkQueue = oop; + _gst_mem.currentMarkQueue++; + + pOOP++; + } }