00001 /* 00002 # This file is Copyright 2003, 2006, 2007, 2009, 2010 Dean Hall. 00003 # 00004 # This file is part of the PyMite VM. 00005 # The PyMite VM is free software: you can redistribute it and/or modify 00006 # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2. 00007 # 00008 # The PyMite VM is distributed in the hope that it will be useful, 00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00011 # A copy of the GNU GENERAL PUBLIC LICENSE Version 2 00012 # is seen in the file COPYING in this directory. 00013 */ 00014 00015 00016 #undef __FILE_ID__ 00017 #define __FILE_ID__ 0x03 00018 00019 00028 #include "pm.h" 00029 00030 00031 PmReturn_t 00032 frame_new(pPmObj_t pfunc, pPmObj_t *r_pobj) 00033 { 00034 PmReturn_t retval = PM_RET_OK; 00035 int16_t fsize = 0; 00036 pPmCo_t pco = C_NULL; 00037 pPmFrame_t pframe = C_NULL; 00038 uint8_t *pchunk; 00039 00040 /* Get fxn's code obj */ 00041 pco = ((pPmFunc_t)pfunc)->f_co; 00042 00043 /* TypeError if passed func's CO is not a true COB */ 00044 if (OBJ_GET_TYPE(pco) != OBJ_TYPE_COB) 00045 { 00046 PM_RAISE(retval, PM_RET_EX_TYPE); 00047 return retval; 00048 } 00049 00050 #ifdef HAVE_GENERATORS 00051 /* #207: Initializing a Generator using CALL_FUNC needs extra stack slot */ 00052 fsize = sizeof(PmFrame_t) + (pco->co_stacksize + pco->co_nlocals + 2) * sizeof(pPmObj_t); 00053 #elif defined(HAVE_CLASSES) 00054 /* #230: Calling a class's __init__() takes two extra spaces on the stack */ 00055 fsize = sizeof(PmFrame_t) + (pco->co_stacksize + pco->co_nlocals + 1) * sizeof(pPmObj_t); 00056 #else 00057 fsize = sizeof(PmFrame_t) + (pco->co_stacksize + pco->co_nlocals - 1) * sizeof(pPmObj_t); 00058 #endif /* HAVE_CLASSES */ 00059 00060 #ifdef HAVE_CLOSURES 00061 /* #256: Add support for closures */ 00062 fsize = fsize + pco->co_nfreevars 00063 + ((pco->co_cellvars == C_NULL) ? 0 : pco->co_cellvars->length); 00064 #endif /* HAVE_CLOSURES */ 00065 00066 /* Allocate a frame */ 00067 retval = heap_getChunk(fsize, &pchunk); 00068 PM_RETURN_IF_ERROR(retval); 00069 pframe = (pPmFrame_t)pchunk; 00070 00071 /* Set frame fields */ 00072 OBJ_SET_TYPE(pframe, OBJ_TYPE_FRM); 00073 pframe->fo_back = C_NULL; 00074 pframe->fo_func = (pPmFunc_t)pfunc; 00075 pframe->fo_memspace = pco->co_memspace; 00076 00077 /* Init instruction pointer and block stack */ 00078 pframe->fo_ip = pco->co_codeaddr; 00079 pframe->fo_blockstack = C_NULL; 00080 00081 /* Get globals and attrs from the function object */ 00082 pframe->fo_globals = ((pPmFunc_t)pfunc)->f_globals; 00083 pframe->fo_attrs = ((pPmFunc_t)pfunc)->f_attrs; 00084 00085 #ifndef HAVE_CLOSURES 00086 /* Empty stack points to one past locals */ 00087 pframe->fo_sp = &(pframe->fo_locals[pco->co_nlocals]); 00088 #else 00089 /* #256: Add support for closures */ 00090 pframe->fo_sp = &(pframe->fo_locals[pco->co_nlocals + pco->co_nfreevars 00091 + ((pco->co_cellvars == C_NULL) ? 0 : pco->co_cellvars->length)]); 00092 #endif /* HAVE_CLOSURES */ 00093 00094 /* By default, this is a normal frame, not an import or __init__ one */ 00095 pframe->fo_isImport = 0; 00096 #ifdef HAVE_CLASSES 00097 pframe->fo_isInit = 0; 00098 #endif 00099 00100 /* Clear the stack */ 00101 sli_memset((unsigned char *)&(pframe->fo_locals), (char const)0, 00102 (unsigned int)fsize - sizeof(PmFrame_t)); 00103 00104 /* Return ptr to frame */ 00105 *r_pobj = (pPmObj_t)pframe; 00106 return retval; 00107 }