packages feed

timberc-1.0.3: rtsPOSIX/cyclic.c

// The Timber compiler <timber-lang.org>
// 
// Copyright 2008-2009 Johan Nordlander <nordland@csee.ltu.se>
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 
// 3. Neither the names of the copyright holder and any identified
//    contributors, nor the names of their affiliations, may be used to 
//    endorse or promote products derived from this software without 
//    specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.


#define BIT0(val)               (((WORD)(val)) & 0x01)
#define CLR0(val)               ((WORD)(val) & (~0x01))
#define TOGGLE0(val)            ((WORD)(val) ^ 0x01)

#define ISPLACEHOLDER(obj)      (BIT0(obj) && ((int)(obj) < 0))
#define INDEXOF(obj)            (((-(int)(obj)) >> 1) - current_thread->placeholders)
#define PLACEHOLDER(index)      (-((((index) + current_thread->placeholders) << 1) | 0x01))

#define CURRENT_CYCLE(obj,roots)    !INSIDE(heapchain,obj,(ADDR)roots)

#define SUBST(obj,off,roots,lim)      { ADDR obj1 = (ADDR)obj[off]; \
                                        if (ISPLACEHOLDER(obj1)) { \
                                                int index = INDEXOF(obj1); \
                                                if (index >= 0 && index < (lim)) \
                                                        obj[off] = (WORD)roots->elems[index]; \
                                        } \
                                      }

ADDR substObj(ADDR obj, Array roots, int limit, Thread current_thread) {
        ADDR info = IND0(obj);
        if (!info)                                      // if gcinfo is null we have reached the end of a heap segment
                return (ADDR)obj[1];                    // pointer to first object of next segment is found in subsequent slot
        switch (GC_TYPE(info)) {
                case GC_STD: {
                        WORD size = STATIC_SIZE(info), i = 2, offset = info[i];
                        while (offset) {
                                SUBST(obj,offset,roots,limit);
                                offset = info[++i];
                        }
                        return obj + size;
                }
                case GC_ARRAY: {
                        WORD size = STATIC_SIZE(info) + obj[1], offset = 2;     // find size of dynamic part in second slot of obj, add static size
                        if (info[2])
                                return obj + size;                              // return immediately if array contains only scalars
                        while (offset<size) {
                                SUBST(obj,offset,roots,limit);
                                offset++;
                        }
                        return obj + size;
                }
                case GC_TUPLE: {
                        WORD width = obj[1], offset = 1 + POLYTAGS(width), i = 1, j, tags;
                        while (width > 32) {
                                for (j = 0, tags = obj[i++]; j < 32; j++, offset++, tags = tags >> 1)
                                        if (!(tags & 1))
                                                SUBST(obj,offset,roots,limit);
                                width -= 32;
                        }
                        for (tags = obj[i]; width > 0; width--, offset++, tags = tags >> 1) 
                                if (!(tags & 1))
                                        SUBST(obj,offset,roots,limit);
                        return obj + STATIC_SIZE(info) + width + POLYTAGS(width);
                }
                case GC_BIG: {
                        WORD size = STATIC_SIZE(info), i = 2, offset = info[i];
                        while (offset) {                                        // subst all statically known pointer fields
                                SUBST(obj,offset,roots,limit);
                                offset = info[++i];
                        }
                        offset = info[++i];
                        while (offset) {                                        // subst dynamically identified pointers
                                WORD tagword = info[++i];
                                WORD bitno = info[++i];
                                if ((tagword & (1 << bitno)) == 0)
                                        SUBST(obj,offset,roots,limit);
                                offset = info[++i];
                        }
                        return obj + size;
                }
                case GC_MUT: {
                        return substObj(obj + STATIC_SIZE(info), roots, limit, current_thread);
                }
        }
        return (ADDR)0;                 // Not reached
}

void subst(Array roots, int limit, ADDR stop, Thread current_thread) {
        ADDR p = (ADDR)roots + STATIC_SIZE(roots->GCINFO) + roots->size;
        int i;
        for (i = 0; i < limit; i++)
                if (ISPLACEHOLDER(roots->elems[i])) 
                        RAISE(2);
        while (p != stop)
                p = substObj(p, roots, limit, current_thread);
}

Array CYCLIC_BEGIN(Int n, Int updates) {
        Thread current_thread = CURRENT();
        Array roots = EmptyArray(0,n);
        int i;
        for (i = 0; i < n; i++)
                roots->elems[i] = (POLY)PLACEHOLDER(i);
        current_thread->placeholders += n;
        return roots;
}

void CYCLIC_UPDATE(Array roots, Int limit, ADDR stop) {
        Thread current_thread = CURRENT();
        current_thread->placeholders -= roots->size;
        subst(roots, limit, stop, current_thread);
        current_thread->placeholders += roots->size;
}

void CYCLIC_END(Array roots, ADDR stop) {
        Thread current_thread = CURRENT();
        current_thread->placeholders -= roots->size;
        subst(roots, roots->size, stop, current_thread);
}