Ejemplo n.º 1
0
PmReturn_t
seqiter_new(pPmObj_t pobj, pPmObj_t *r_pobj)
{
    PmReturn_t retval;
    uint8_t *pchunk;
    pPmSeqIter_t psi;

    C_ASSERT(pobj != C_NULL);
    C_ASSERT(*r_pobj != C_NULL);

    /* Raise a TypeError if pobj is not a sequence */
    if ((OBJ_GET_TYPE(pobj) != OBJ_TYPE_STR)
            && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_TUP)
            && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_LST))
    {
        PM_RAISE(retval, PM_RET_EX_TYPE);
        return retval;
    }

    /* Alloc a chunk for the sequence iterator obj */
    retval = heap_getChunk(sizeof(PmSeqIter_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);

    /* Set the sequence iterator's fields */
    psi = (pPmSeqIter_t)pchunk;
    OBJ_SET_TYPE(psi, OBJ_TYPE_SQI);
    psi->si_sequence = pobj;
    psi->si_index = 0;

    *r_pobj = (pPmObj_t)psi;
    return retval;
}
Ejemplo n.º 2
0
/* Returns an instance of the class by reference */
PmReturn_t
class_instantiate(pPmObj_t pclass, pPmObj_t *r_pobj)
{
    PmReturn_t retval = PM_RET_OK;
    uint8_t *pchunk;
    pPmObj_t pobj;
    pPmObj_t pattrs;
    uint8_t objid;

    /* Allocate a class instance */
    retval = heap_getChunk(sizeof(PmInstance_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pobj = (pPmObj_t)pchunk;
    OBJ_SET_TYPE(pobj, OBJ_TYPE_CLI);

    /* Set the instance's fields */
    ((pPmInstance_t)pobj)->cli_class = (pPmClass_t)pclass;
    ((pPmInstance_t)pobj)->cli_attrs = C_NULL;

    /* Create the attributes dict */
    heap_gcPushTempRoot(pobj, &objid);
    retval = dict_new(&pattrs);
    heap_gcPopTempRoot(objid);
    ((pPmInstance_t)pobj)->cli_attrs = (pPmDict_t)pattrs;

    /* TODO: Store pclass in __class__ attr */

    *r_pobj = pobj;
    return retval;
}
Ejemplo n.º 3
0
PmReturn_t
thread_new(pPmObj_t pframe, pPmObj_t *r_pobj)
{
    PmReturn_t retval = PM_RET_OK;
    pPmThread_t pthread = C_NULL;

    C_ASSERT(pframe != C_NULL);

    /* If it's not a frame, raise TypeError */
    if (OBJ_GET_TYPE(pframe) != OBJ_TYPE_FRM)
    {
        PM_RAISE(retval, PM_RET_EX_TYPE);
        return retval;
    }

    /* Allocate a thread */
    retval = heap_getChunk(sizeof(PmThread_t), (uint8_t **)r_pobj);
    PM_RETURN_IF_ERROR(retval);

    /* Set type, frame and initialize status */
    pthread = (pPmThread_t)*r_pobj;
    OBJ_SET_TYPE(pthread, OBJ_TYPE_THR);
    pthread->pframe = (pPmFrame_t)pframe;
    pthread->interpctrl = INTERP_CTRL_CONT;

    return retval;
}
Ejemplo n.º 4
0
PmReturn_t
mod_new(pPmObj_t pco, pPmObj_t *pmod)
{
    PmReturn_t retval;
    uint8_t *pchunk;
    pPmObj_t pobj;

    /* If it's not a code obj, raise TypeError */
    if (OBJ_GET_TYPE(pco) != OBJ_TYPE_COB)
    {
        PM_RAISE(retval, PM_RET_EX_TYPE);
        return retval;
    }

    /* Alloc and init func obj */
    retval = heap_getChunk(sizeof(PmFunc_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    *pmod = (pPmObj_t)pchunk;
    OBJ_SET_TYPE(*pmod, OBJ_TYPE_MOD);
    ((pPmFunc_t)*pmod)->f_co = (pPmCo_t)pco;

    /* Alloc and init attrs dict */
    retval = dict_new(&pobj);
    ((pPmFunc_t)*pmod)->f_attrs = (pPmDict_t)pobj;

    /* A module's globals is the same as its attrs */
    ((pPmFunc_t)*pmod)->f_globals = (pPmDict_t)pobj;

    return retval;
}
Ejemplo n.º 5
0
PmReturn_t
class_method(pPmObj_t pinstance, pPmObj_t pfunc, pPmObj_t *r_pmeth)
{
    PmReturn_t retval = PM_RET_OK;
    uint8_t *pchunk;
    pPmMethod_t pmeth;
    pPmObj_t pattrs;
    uint8_t objid;

    /* Allocate a method */
    retval = heap_getChunk(sizeof(PmMethod_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    OBJ_SET_TYPE(pchunk, OBJ_TYPE_MTH);

    /* Set method fields */
    pmeth = (pPmMethod_t)pchunk;
    pmeth->m_instance = (pPmInstance_t)pinstance;
    pmeth->m_func = (pPmFunc_t)pfunc;
    pmeth->m_attrs = C_NULL;

    /* Create the attributes dict */
    heap_gcPushTempRoot((pPmObj_t)pmeth, &objid);
    retval = dict_new(&pattrs);
    heap_gcPopTempRoot(objid);
    pmeth->m_attrs = (pPmDict_t)pattrs;

    *r_pmeth = (pPmObj_t)pmeth;
    return retval;
}
Ejemplo n.º 6
0
PmReturn_t
class_new(pPmObj_t pattrs, pPmObj_t pbases, pPmObj_t pname, pPmObj_t *r_pclass)
{
    PmReturn_t retval = PM_RET_OK;
    uint8_t *pchunk;
    pPmObj_t pobj;

    /* Ensure types */
    if ((OBJ_GET_TYPE(pattrs) != OBJ_TYPE_DIC)
            || (OBJ_GET_TYPE(pbases) != OBJ_TYPE_TUP)
            || (OBJ_GET_TYPE(pname) != OBJ_TYPE_STR))
    {
        PM_RAISE(retval, PM_RET_EX_TYPE);
        return retval;
    }

    /* Allocate a class obj */
    retval = heap_getChunk(sizeof(PmClass_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pobj = (pPmObj_t)pchunk;
    OBJ_SET_TYPE(pobj, OBJ_TYPE_CLO);

    /* Class has no access to its CO */
    ((pPmClass_t)pobj)->cl_attrs = (pPmDict_t)pattrs;
    ((pPmClass_t)pobj)->cl_bases = (pPmTuple_t)pbases;

    *r_pclass = pobj;

    return retval;
}
Ejemplo n.º 7
0
PmReturn_t
obj_loadFromImg(PmMemSpace_t memspace,
                uint8_t const **paddr, pPmObj_t *r_pobj)
{
    PmReturn_t retval = PM_RET_OK;
    PmObj_t obj;


    /* Get the object descriptor */
    obj.od = (PmObjDesc_t)0x0000;
    OBJ_SET_TYPE(&obj, mem_getByte(memspace, paddr));

    switch (OBJ_GET_TYPE(&obj))
    {
        case OBJ_TYPE_NON:
            /* If it's the None object, return global None */
            *r_pobj = PM_NONE;
            break;

        case OBJ_TYPE_INT:
            /* Read an integer and create an integer object with the value */
            retval = int_new(mem_getInt(memspace, paddr), r_pobj);
            break;

#ifdef HAVE_FLOAT
        case OBJ_TYPE_FLT:
            /* Read a float and create an float object with the value */
            retval = float_new(mem_getFloat(memspace, paddr), r_pobj);
            break;
#endif /* HAVE_FLOAT */

        case OBJ_TYPE_STR:
            retval = string_loadFromImg(memspace, paddr, r_pobj);
            break;

        case OBJ_TYPE_TUP:
            retval = tuple_loadFromImg(memspace, paddr, r_pobj);
            break;

        case OBJ_TYPE_NIM:
            /* If it's a native code img, load into a code obj */
            retval = no_loadFromImg(memspace, paddr, r_pobj);
            break;

        case OBJ_TYPE_CIM:
            /* If it's a code img, load into a code obj */
            retval = co_loadFromImg(memspace, paddr, r_pobj);
            break;

        default:
            /* All other types should not be in an img obj */
            PM_RAISE(retval, PM_RET_EX_SYS);
            break;
    }
    return retval;
}
Ejemplo n.º 8
0
PmReturn_t
float_new(float f, pPmObj_t *r_pf)
{
    PmReturn_t retval = PM_RET_OK;

    retval = heap_getChunk(sizeof(PmFloat_t), (uint8_t **)r_pf);
    PM_RETURN_IF_ERROR(retval);
    OBJ_SET_TYPE(*r_pf, OBJ_TYPE_FLT);
    ((pPmFloat_t) * r_pf)->val = f;
    return retval;
}
Ejemplo n.º 9
0
PmReturn_t
co_loadFromImg(PmMemSpace_t memspace, uint8_t const **paddr, pPmObj_t *r_pco)
{
    PmReturn_t retval = PM_RET_OK;
    pPmObj_t pobj;
    pPmCo_t pco = C_NULL;
    uint8_t *pchunk;

    /* Store ptr to top of code img (less type byte) */
    uint8_t const *pci = *paddr - 1;

    /* Get size of code img */
    uint16_t size = mem_getWord(memspace, paddr);

    /* Allocate a code obj */
    retval = heap_getChunk(sizeof(PmCo_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pco = (pPmCo_t)pchunk;

    /* Fill in the CO struct */
    OBJ_SET_TYPE(pco, OBJ_TYPE_COB);
    pco->co_memspace = memspace;
    pco->co_codeimgaddr = pci;

    /* Load names (tuple obj) */
    *paddr = pci + CI_NAMES_FIELD;
    retval = obj_loadFromImg(memspace, paddr, &pobj);
    PM_RETURN_IF_ERROR(retval);
    pco->co_names = (pPmTuple_t)pobj;

    /* Load consts (tuple obj) assume it follows names */
    retval = obj_loadFromImg(memspace, paddr, &pobj);
    PM_RETURN_IF_ERROR(retval);
    pco->co_consts = (pPmTuple_t)pobj;

    /* Start of bcode always follows consts */
    pco->co_codeaddr = *paddr;

    /* Set addr to point one past end of img */
    *paddr = pci + size;

    *r_pco = (pPmObj_t)pco;
    return PM_RET_OK;
}
Ejemplo n.º 10
0
PmReturn_t
dict_new(pPmObj_t *r_pdict)
{
    PmReturn_t retval = PM_RET_OK;
    pPmDict_t pdict = C_NULL;
    uint8_t *pchunk;

    /* Allocate a dict */
    retval = heap_getChunk(sizeof(PmDict_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);

    /* Init dict fields */
    pdict = (pPmDict_t)pchunk;
    OBJ_SET_TYPE(pdict, OBJ_TYPE_DIC);
    pdict->length = 0;
    pdict->d_keys = C_NULL;
    pdict->d_vals = C_NULL;

    *r_pdict = (pPmObj_t)pchunk;
    return retval;
}
Ejemplo n.º 11
0
PmReturn_t
no_loadFromImg(PmMemSpace_t memspace, uint8_t const **paddr, pPmObj_t *r_pno)
{
    PmReturn_t retval = PM_RET_OK;
    pPmNo_t pno = C_NULL;
    uint8_t *pchunk;

    /* Allocate a code obj */
    retval = heap_getChunk(sizeof(PmNo_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pno = (pPmNo_t)pchunk;

    /* Fill in the NO struct */
    OBJ_SET_TYPE(pno, OBJ_TYPE_NOB);
    pno->no_argcount = mem_getByte(memspace, paddr);

    /* Get index into native fxn table */
    pno->no_funcindx = (int16_t)mem_getWord(memspace, paddr);

    *r_pno = (pPmObj_t)pno;
    return PM_RET_OK;
}
Ejemplo n.º 12
0
/* Releases chunk to the free list */
PmReturn_t
heap_freeChunk(pPmObj_t ptr)
{
    PmReturn_t retval;

    C_DEBUG_PRINT(VERBOSITY_HIGH, "heap_freeChunk(), id=%p, s=%d\n",
                  ptr, OBJ_GET_SIZE(ptr));

    /* Ensure the chunk falls within the heap */
    C_ASSERT(((uint8_t *)ptr >= pmHeap.base)
             && ((uint8_t *)ptr < pmHeap.base + PM_HEAP_SIZE));

    /* Insert the chunk into the freelist */
    OBJ_SET_FREE(ptr, 1);

    /* Clear type so that heap descriptor's size's upper byte is zero */
    OBJ_SET_TYPE(ptr, 0);
    retval = heap_linkToFreelist((pPmHeapDesc_t)ptr);
    PM_RETURN_IF_ERROR(retval);

    return retval;
}
Ejemplo n.º 13
0
/*
 * Reclaims any object that does not have a current mark.
 * Puts it in the free list.  Coalesces all contiguous free chunks.
 */
static PmReturn_t
heap_gcSweep(void)
{
    PmReturn_t retval;
    pPmObj_t pobj;
    pPmHeapDesc_t pchunk;
    uint16_t totalchunksize;

#if USE_STRING_CACHE
    retval = heap_purgeStringCache(pmHeap.gcval);
#endif

    /* Start at the base of the heap */
    pobj = (pPmObj_t)pmHeap.base;
    while ((uint8_t *)pobj < &pmHeap.base[PM_HEAP_SIZE])
    {
        /* Skip to the next unmarked or free chunk within the heap */
        while (!OBJ_GET_FREE(pobj)
               && (OBJ_GET_GCVAL(pobj) == pmHeap.gcval)
               && ((uint8_t *)pobj < &pmHeap.base[PM_HEAP_SIZE]))
        {
            pobj = (pPmObj_t)((uint8_t *)pobj + OBJ_GET_SIZE(pobj));
        }

        /* Stop if reached the end of the heap */
        if ((uint8_t *)pobj >= &pmHeap.base[PM_HEAP_SIZE])
        {
            break;
        }

        /* Accumulate the sizes of all consecutive unmarked or free chunks */
        totalchunksize = 0;

        /* Coalesce all contiguous free chunks */
        pchunk = (pPmHeapDesc_t)pobj;
        while (OBJ_GET_FREE(pchunk)
               || (!OBJ_GET_FREE(pchunk)
                   && (OBJ_GET_GCVAL(pchunk) != pmHeap.gcval)))
        {
            if ((totalchunksize + OBJ_GET_SIZE(pchunk))
                > HEAP_MAX_FREE_CHUNK_SIZE)
            {
                break;
            }
            totalchunksize = totalchunksize + OBJ_GET_SIZE(pchunk);

            /*
             * If the chunk is already free, unlink it because its size
             * is about to change
             */
            if (OBJ_GET_FREE(pchunk))
            {
                retval = heap_unlinkFromFreelist(pchunk);
                PM_RETURN_IF_ERROR(retval);
            }

            /* Otherwise free and reclaim the unmarked chunk */
            else
            {
                OBJ_SET_TYPE(pchunk, 0);
                OBJ_SET_FREE(pchunk, 1);
            }

            C_DEBUG_PRINT(VERBOSITY_HIGH, "heap_gcSweep(), id=%p, s=%d\n",
                          pchunk, OBJ_GET_SIZE(pchunk));

            /* Proceed to the next chunk */
            pchunk = (pPmHeapDesc_t)
                ((uint8_t *)pchunk + OBJ_GET_SIZE(pchunk));

            /* Stop if it's past the end of the heap */
            if ((uint8_t *)pchunk >= &pmHeap.base[PM_HEAP_SIZE])
            {
                break;
            }
        }

        /* Set the heap descriptor data */
        OBJ_SET_FREE(pobj, 1);
        OBJ_SET_SIZE(pobj, totalchunksize);

        /* Insert chunk into free list */
        retval = heap_linkToFreelist((pPmHeapDesc_t)pobj);
        PM_RETURN_IF_ERROR(retval);

        /* Continue to the next chunk */
        pobj = (pPmObj_t)pchunk;
    }

    return PM_RET_OK;
}
Ejemplo n.º 14
0
PmReturn_t
global_init(void)
{
    PmReturn_t retval;
    uint8_t *codestr = (uint8_t *)"code";
    uint8_t *pchunk;
    pPmObj_t pobj;
#ifdef HAVE_CLASSES
    uint8_t const *initstr = (uint8_t const *)"__init__"; 
#endif /* HAVE_CLASSES */
#ifdef HAVE_GENERATORS
    uint8_t const *genstr = (uint8_t const *)"Generator";
    uint8_t const *nextstr = (uint8_t const *)"next";
#endif /* HAVE_GENERATORS */
#ifdef HAVE_ASSERT
    uint8_t const *exnstr = (uint8_t const *)"Exception";
#endif /* HAVE_ASSERT */
#ifdef HAVE_BYTEARRAY
    uint8_t const *pbastr = (uint8_t const *)"bytearray";
#endif /* HAVE_BYTEARRAY */

    /* Clear the global struct */
    sli_memset((uint8_t *)&gVmGlobal, '\0', sizeof(PmVmGlobal_t));

    /* Set the PyMite release num (for debug and post mortem) */
    gVmGlobal.errVmRelease = PM_RELEASE;

    /* Init zero */
    retval = heap_getChunk(sizeof(PmInt_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pobj = (pPmObj_t)pchunk;
    OBJ_SET_TYPE(pobj, OBJ_TYPE_INT);
    ((pPmInt_t)pobj)->val = (int32_t)0;
    gVmGlobal.pzero = (pPmInt_t)pobj;

    /* Init one */
    retval = heap_getChunk(sizeof(PmInt_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pobj = (pPmObj_t)pchunk;
    OBJ_SET_TYPE(pobj, OBJ_TYPE_INT);
    ((pPmInt_t)pobj)->val = (int32_t)1;
    gVmGlobal.pone = (pPmInt_t)pobj;

    /* Init negone */
    retval = heap_getChunk(sizeof(PmInt_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pobj = (pPmObj_t)pchunk;
    OBJ_SET_TYPE(pobj, OBJ_TYPE_INT);
    ((pPmInt_t)pobj)->val = (int32_t)-1;
    gVmGlobal.pnegone = (pPmInt_t)pobj;

    /* Init False */
    retval = heap_getChunk(sizeof(PmBoolean_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pobj = (pPmObj_t)pchunk;
    OBJ_SET_TYPE(pobj, OBJ_TYPE_BOOL);
    ((pPmBoolean_t) pobj)->val = (int32_t)C_FALSE;
    gVmGlobal.pfalse = (pPmInt_t)pobj;

    /* Init True */
    retval = heap_getChunk(sizeof(PmBoolean_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pobj = (pPmObj_t)pchunk;
    OBJ_SET_TYPE(pobj, OBJ_TYPE_BOOL);
    ((pPmBoolean_t) pobj)->val = (int32_t)C_TRUE;
    gVmGlobal.ptrue = (pPmInt_t)pobj;

    /* Init None */
    retval = heap_getChunk(sizeof(PmObj_t), &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pobj = (pPmObj_t)pchunk;
    OBJ_SET_TYPE(pobj, OBJ_TYPE_NON);
    gVmGlobal.pnone = pobj;

    /* Init "code" string obj */
    retval = string_new((uint8_t const **)&codestr, &pobj);
    PM_RETURN_IF_ERROR(retval);
    gVmGlobal.pcodeStr = (pPmString_t)pobj;

#ifdef HAVE_CLASSES
    /* Init "__init__" string obj */
    retval = string_new((uint8_t const **)&initstr, &pobj);
    PM_RETURN_IF_ERROR(retval);
    gVmGlobal.pinitStr = (pPmString_t)pobj;
#endif /* HAVE_CLASSES */

#ifdef HAVE_GENERATORS
    /* Init "Generator" string obj */
    retval = string_new((uint8_t const **)&genstr, &pobj);
    PM_RETURN_IF_ERROR(retval);
    gVmGlobal.pgenStr = (pPmString_t)pobj;
    
    /* Init "next" string obj */
    retval = string_new((uint8_t const **)&nextstr, &pobj);
    PM_RETURN_IF_ERROR(retval);
    gVmGlobal.pnextStr = (pPmString_t)pobj;
#endif /* HAVE_GENERATORS */

#ifdef HAVE_ASSERT
    /* Init "Exception" string obj */
    retval = string_new((uint8_t const **)&exnstr, &pobj);
    PM_RETURN_IF_ERROR(retval);
    gVmGlobal.pexnStr = (pPmString_t)pobj;
#endif /* HAVE_ASSERT */

#ifdef HAVE_BYTEARRAY
    /* Init "bytearray" string obj */
    retval = string_new((uint8_t const **)&pbastr, &pobj);
    PM_RETURN_IF_ERROR(retval);
    gVmGlobal.pbaStr = (pPmString_t)pobj;
#endif /* HAVE_BYTEARRAY */

    /* Init empty builtins */
    gVmGlobal.builtins = C_NULL;

    /* Init native frame */
    OBJ_SET_SIZE(&gVmGlobal.nativeframe, sizeof(PmNativeFrame_t));
    OBJ_SET_TYPE(&gVmGlobal.nativeframe, OBJ_TYPE_NFM);
    gVmGlobal.nativeframe.nf_func = C_NULL;
    gVmGlobal.nativeframe.nf_stack = C_NULL;
    gVmGlobal.nativeframe.nf_active = C_FALSE;
    gVmGlobal.nativeframe.nf_numlocals = 0;

    /* Create empty threadList */
    retval = list_new(&pobj);
    gVmGlobal.threadList = (pPmList_t)pobj;

    /* Init the PmImgPaths with std image info */
    gVmGlobal.imgPaths.memspace[0] = MEMSPACE_PROG;
    gVmGlobal.imgPaths.pimg[0] = (uint8_t *)&stdlib_img;
    gVmGlobal.imgPaths.pathcount = 1;

#ifdef HAVE_PRINT
    gVmGlobal.needSoftSpace = C_FALSE;
    gVmGlobal.somethingPrinted = C_FALSE;
#endif /* HAVE_PRINT */

    return retval;
}
Ejemplo n.º 15
0
PmReturn_t
frame_new(pPmObj_t pfunc, pPmObj_t *r_pobj)
{
    PmReturn_t retval = PM_RET_OK;
    int16_t fsize = 0;
    pPmCo_t pco = C_NULL;
    pPmFrame_t pframe = C_NULL;
    uint8_t *pchunk;

    /* Get fxn's code obj */
    pco = ((pPmFunc_t)pfunc)->f_co;

    /* TypeError if passed func's CO is not a true COB */
    if (OBJ_GET_TYPE(pco) != OBJ_TYPE_COB)
    {
        PM_RAISE(retval, PM_RET_EX_TYPE);
        return retval;
    }

#ifdef HAVE_GENERATORS
    /* #207: Initializing a Generator using CALL_FUNC needs extra stack slot */
    fsize = sizeof(PmFrame_t) + (pco->co_stacksize + pco->co_nlocals + 2) * sizeof(pPmObj_t);
#elif defined(HAVE_CLASSES)
    /* #230: Calling a class's __init__() takes two extra spaces on the stack */
    fsize = sizeof(PmFrame_t) + (pco->co_stacksize + pco->co_nlocals + 1) * sizeof(pPmObj_t);
#else
    fsize = sizeof(PmFrame_t) + (pco->co_stacksize + pco->co_nlocals - 1) * sizeof(pPmObj_t);
#endif /* HAVE_CLASSES */

#ifdef HAVE_CLOSURES
    /* #256: Add support for closures */
    fsize = fsize + pco->co_nfreevars
            + ((pco->co_cellvars == C_NULL) ? 0 : pco->co_cellvars->length);
#endif /* HAVE_CLOSURES */

    /* Allocate a frame */
    retval = heap_getChunk(fsize, &pchunk);
    PM_RETURN_IF_ERROR(retval);
    pframe = (pPmFrame_t)pchunk;

    /* Set frame fields */
    OBJ_SET_TYPE(pframe, OBJ_TYPE_FRM);
    pframe->fo_back = C_NULL;
    pframe->fo_func = (pPmFunc_t)pfunc;
    pframe->fo_memspace = pco->co_memspace;

    /* Init instruction pointer and block stack */
    pframe->fo_ip = pco->co_codeaddr;
    pframe->fo_blockstack = C_NULL;

    /* Get globals and attrs from the function object */
    pframe->fo_globals = ((pPmFunc_t)pfunc)->f_globals;
    pframe->fo_attrs = ((pPmFunc_t)pfunc)->f_attrs;

#ifndef HAVE_CLOSURES
    /* Empty stack points to one past locals */
    pframe->fo_sp = &(pframe->fo_locals[pco->co_nlocals]);
#else
    /* #256: Add support for closures */
    pframe->fo_sp = &(pframe->fo_locals[pco->co_nlocals + pco->co_nfreevars
        + ((pco->co_cellvars == C_NULL) ? 0 : pco->co_cellvars->length)]);
#endif /* HAVE_CLOSURES */

    /* By default, this is a normal frame, not an import or __init__ one */
    pframe->fo_isImport = 0;
#ifdef HAVE_CLASSES
    pframe->fo_isInit = 0;
#endif

    /* Clear the stack */
    sli_memset((unsigned char *)&(pframe->fo_locals), (char const)0,
               (unsigned int)fsize - sizeof(PmFrame_t));

    /* Return ptr to frame */
    *r_pobj = (pPmObj_t)pframe;
    return retval;
}
Ejemplo n.º 16
0
/*
 * Reclaims any object that doesn't have a current mark.
 * Puts it in the free list.  Coalesces all contiguous free chunks.
 */
static PmReturn_t
heap_gcSweep(void)
{
    PmReturn_t retval;
    pPmObj_t pobj;
    pPmHeapDesc_t pchunk;
    uint16_t totalchunksize;
    uint16_t additionalheapsize;

    /* Start at the base of the heap */
    pobj = (pPmObj_t)pmHeap.base;
    while ((uint8_t *)pobj < &pmHeap.base[HEAP_SIZE])
    {
        /* Skip to the next unmarked or free chunk within the heap */
        while (!OBJ_GET_FREE(pobj)
               && (OBJ_GET_GCVAL(pobj) == pmHeap.gcval)
               && ((uint8_t *)pobj < &pmHeap.base[HEAP_SIZE]))
        {
            pobj = (pPmObj_t)((uint8_t *)pobj + OBJ_GET_SIZE(pobj));
/*printf("Object is at addr <%x>\n",(uint32_t)pobj);*/
#if 0
printf("pobj=");obj_print(pobj,0);printf("; type=%x; size=%x\n",OBJ_GET_TYPE(pobj),OBJ_GET_SIZE(pobj));
#endif
        }

        /* Stop if reached the end of the heap */
        if ((uint8_t *)pobj >= &pmHeap.base[HEAP_SIZE])
        {
            break;
        }

        /* Accumulate the sizes of all consecutive unmarked or free chunks */
        totalchunksize = 0;
        additionalheapsize = 0;

        /* Coalesce all contiguous free chunks */
        pchunk = (pPmHeapDesc_t)pobj;
        while (OBJ_GET_FREE(pchunk)
               || (!OBJ_GET_FREE(pchunk)
                   && (OBJ_GET_GCVAL(pchunk) != pmHeap.gcval)))
        {
            totalchunksize += OBJ_GET_SIZE(pchunk);

            /*
             * If the chunk is already free, unlink it because its size
             * is about to change
             */
            if (OBJ_GET_FREE(pchunk))
            {
                retval = heap_unlinkFromFreelist(pchunk);
                PM_RETURN_IF_ERROR(retval);
            }

            /* Otherwise free and reclaim the unmarked chunk */
            else
            {
                OBJ_SET_TYPE(pchunk, 0);
                OBJ_SET_FREE(pchunk, 1);
                additionalheapsize += OBJ_GET_SIZE(pchunk);
            }

            C_DEBUG_PRINT(VERBOSITY_HIGH, "heap_gcSweep(), id=%p, s=%d\n",
                          pchunk, OBJ_GET_SIZE(pchunk));

#if 0
            /* It's possible for 0-sized chunks to exist (which makes no sense) TODO:solve */
            /* They result in infinite loops, so we must curtail them */
            if (OBJ_GET_SIZE(pchunk) == 0)
            {
                break;
            }
#endif

            /* Proceed to the next chunk */
            pchunk = (pPmHeapDesc_t)
                     ((uint8_t *)pchunk + OBJ_GET_SIZE(pchunk));

            /* Stop if it's past the end of the heap */
            if ((uint8_t *)pchunk >= &pmHeap.base[HEAP_SIZE])
            {
                break;
            }
        }

        /* Adjust the heap stats */
        pmHeap.avail += additionalheapsize;

        /* Set the heap descriptor data */
        OBJ_SET_FREE(pobj, 1);
        OBJ_SET_SIZE(pobj, totalchunksize);

#if 0
        /* avoid loops by breaking on 0-size */
        if (totalchunksize == 0)
        {
            break;
        }
#endif

        /* Insert chunk into free list */
        retval = heap_linkToFreelist((pPmHeapDesc_t)pobj);
        PM_RETURN_IF_ERROR(retval);

        /* Continue to the next chunk */
        pobj = (pPmObj_t)pchunk;
    }

    return PM_RET_OK;
}
Ejemplo n.º 17
0
/**
 * Obtains a chunk of memory from the free list
 *
 * Performs the Best Fit algorithm.
 * Iterates through the freelist to see if a chunk of suitable size exists.
 * Shaves a chunk to perfect size iff the remainder is greater than
 * the minimum chunk size.
 *
 * @param size Requested chunk size
 * @param r_pchunk Return ptr to chunk
 * @return Return status
 */
static PmReturn_t
heap_getChunkImpl(uint16_t size, uint8_t **r_pchunk)
{
    PmReturn_t retval;
    pPmHeapDesc_t pchunk;
    pPmHeapDesc_t premainderChunk;

    C_ASSERT(r_pchunk != C_NULL);

    /* Skip to the first chunk that can hold the requested size */
    pchunk = pmHeap.pfreelist;
    while ((pchunk != C_NULL) && (OBJ_GET_SIZE(pchunk) < size))
    {
        pchunk = pchunk->next;
    }

    /* No chunk of appropriate size was found, raise OutOfMemory exception */
    if (pchunk == C_NULL)
    {
        *r_pchunk = C_NULL;
        PM_RAISE(retval, PM_RET_EX_MEM);
        return retval;
    }

    /* Remove the chunk from the free list */
    retval = heap_unlinkFromFreelist(pchunk);
    PM_RETURN_IF_ERROR(retval);

    /* Check if a chunk should be carved from what is available */
    if (OBJ_GET_SIZE(pchunk) - size >= HEAP_MIN_CHUNK_SIZE)
    {
        /* Create the heap descriptor for the remainder chunk */
        premainderChunk = (pPmHeapDesc_t)((uint8_t *)pchunk + size);
        OBJ_SET_FREE(premainderChunk, 1);
        OBJ_SET_SIZE(premainderChunk, OBJ_GET_SIZE(pchunk) - size);

        /* Put the remainder chunk back in the free list */
        retval = heap_linkToFreelist(premainderChunk);
        PM_RETURN_IF_ERROR(retval);

        /* Convert the chunk from a heap descriptor to an object descriptor */
        OBJ_SET_SIZE(pchunk, 0);
        OBJ_SET_FREE(pchunk, 0);
        OBJ_SET_SIZE(pchunk, size);

        C_DEBUG_PRINT(VERBOSITY_HIGH,
                      "heap_getChunkImpl()carved, id=%p, s=%d\n", pchunk,
                      size);
    }
    else
    {
        /* Set chunk's type to none (overwrites size field's high byte) */
        OBJ_SET_TYPE((pPmObj_t)pchunk, OBJ_TYPE_NON);
        OBJ_SET_FREE(pchunk, 0);

        C_DEBUG_PRINT(VERBOSITY_HIGH,
                      "heap_getChunkImpl()exact, id=%p, s=%d\n", pchunk,
                      OBJ_GET_SIZE(pchunk));
    }

    /*
     * Set the chunk's GC mark so it will be collected during the next GC cycle
     * if it is not reachable
     */
    OBJ_SET_GCVAL(pchunk, pmHeap.gcval);

    /* Return the chunk */
    *r_pchunk = (uint8_t *)pchunk;

    return retval;
}