davide carboni / Mbed 2 deprecated pymite_http_get

Dependencies:   mbed

Committer:
dadaista
Date:
Wed Jul 21 12:50:41 2010 +0000
Revision:
0:14e5e829dffe

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dadaista 0:14e5e829dffe 1 /*
dadaista 0:14e5e829dffe 2 # This file is Copyright 2003, 2006, 2007, 2009 Dean Hall.
dadaista 0:14e5e829dffe 3 #
dadaista 0:14e5e829dffe 4 # This file is part of the PyMite VM.
dadaista 0:14e5e829dffe 5 # The PyMite VM is free software: you can redistribute it and/or modify
dadaista 0:14e5e829dffe 6 # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2.
dadaista 0:14e5e829dffe 7 #
dadaista 0:14e5e829dffe 8 # The PyMite VM is distributed in the hope that it will be useful,
dadaista 0:14e5e829dffe 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
dadaista 0:14e5e829dffe 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
dadaista 0:14e5e829dffe 11 # A copy of the GNU GENERAL PUBLIC LICENSE Version 2
dadaista 0:14e5e829dffe 12 # is seen in the file COPYING in this directory.
dadaista 0:14e5e829dffe 13 */
dadaista 0:14e5e829dffe 14
dadaista 0:14e5e829dffe 15
dadaista 0:14e5e829dffe 16 #undef __FILE_ID__
dadaista 0:14e5e829dffe 17 #define __FILE_ID__ 0x06
dadaista 0:14e5e829dffe 18
dadaista 0:14e5e829dffe 19
dadaista 0:14e5e829dffe 20 /**
dadaista 0:14e5e829dffe 21 * \file
dadaista 0:14e5e829dffe 22 * \brief VM Heap
dadaista 0:14e5e829dffe 23 *
dadaista 0:14e5e829dffe 24 * VM heap operations.
dadaista 0:14e5e829dffe 25 * All of PyMite's dynamic memory is obtained from this heap.
dadaista 0:14e5e829dffe 26 * The heap provides dynamic memory on demand.
dadaista 0:14e5e829dffe 27 */
dadaista 0:14e5e829dffe 28
dadaista 0:14e5e829dffe 29
dadaista 0:14e5e829dffe 30 #include "pm.h"
dadaista 0:14e5e829dffe 31
dadaista 0:14e5e829dffe 32
dadaista 0:14e5e829dffe 33 /** Checks for heap size definition. */
dadaista 0:14e5e829dffe 34 #ifndef PM_HEAP_SIZE
dadaista 0:14e5e829dffe 35 #warning PM_HEAP_SIZE not defined in src/platform/<yourplatform>/pmfeatures.h
dadaista 0:14e5e829dffe 36 #elif PM_HEAP_SIZE & 3
dadaista 0:14e5e829dffe 37 #error PM_HEAP_SIZE is not a multiple of four
dadaista 0:14e5e829dffe 38 #endif
dadaista 0:14e5e829dffe 39
dadaista 0:14e5e829dffe 40
dadaista 0:14e5e829dffe 41 /**
dadaista 0:14e5e829dffe 42 * The maximum size a live chunk can be (a live chunk is one that is in use).
dadaista 0:14e5e829dffe 43 * The live chunk size is limited by the size field in the *object* descriptor.
dadaista 0:14e5e829dffe 44 * That field is nine bits with two assumed least significant bits (zeros):
dadaista 0:14e5e829dffe 45 * (0x1FF << 2) == 2044
dadaista 0:14e5e829dffe 46 */
dadaista 0:14e5e829dffe 47 #define HEAP_MAX_LIVE_CHUNK_SIZE 2044
dadaista 0:14e5e829dffe 48
dadaista 0:14e5e829dffe 49 /**
dadaista 0:14e5e829dffe 50 * The maximum size a free chunk can be (a free chunk is one that is not in use).
dadaista 0:14e5e829dffe 51 * The free chunk size is limited by the size field in the *heap* descriptor.
dadaista 0:14e5e829dffe 52 * That field is fourteen bits with two assumed least significant bits (zeros):
dadaista 0:14e5e829dffe 53 * (0x3FFF << 2) == 65532
dadaista 0:14e5e829dffe 54 */
dadaista 0:14e5e829dffe 55 #define HEAP_MAX_FREE_CHUNK_SIZE 65532
dadaista 0:14e5e829dffe 56
dadaista 0:14e5e829dffe 57 /** The minimum size a chunk can be (rounded up to a multiple of 4) */
dadaista 0:14e5e829dffe 58 #define HEAP_MIN_CHUNK_SIZE ((sizeof(PmHeapDesc_t) + 3) & ~3)
dadaista 0:14e5e829dffe 59
dadaista 0:14e5e829dffe 60
dadaista 0:14e5e829dffe 61 /**
dadaista 0:14e5e829dffe 62 * Gets the GC's mark bit for the object.
dadaista 0:14e5e829dffe 63 * This MUST NOT be called on objects that are free.
dadaista 0:14e5e829dffe 64 */
dadaista 0:14e5e829dffe 65 #define OBJ_GET_GCVAL(pobj) ((((pPmObj_t)pobj)->od >> OD_MARK_SHIFT) & 1)
dadaista 0:14e5e829dffe 66
dadaista 0:14e5e829dffe 67 /**
dadaista 0:14e5e829dffe 68 * Sets the GC's mark bit for the object
dadaista 0:14e5e829dffe 69 * This MUST NOT be called on objects that are free.
dadaista 0:14e5e829dffe 70 */
dadaista 0:14e5e829dffe 71 #ifdef HAVE_GC
dadaista 0:14e5e829dffe 72 #define OBJ_SET_GCVAL(pobj, gcval) \
dadaista 0:14e5e829dffe 73 do \
dadaista 0:14e5e829dffe 74 { \
dadaista 0:14e5e829dffe 75 ((pPmObj_t)pobj)->od = (gcval) ? ((pPmObj_t)pobj)->od | OD_MARK_BIT \
dadaista 0:14e5e829dffe 76 : ((pPmObj_t)pobj)->od & ~OD_MARK_BIT;\
dadaista 0:14e5e829dffe 77 } \
dadaista 0:14e5e829dffe 78 while (0)
dadaista 0:14e5e829dffe 79 #else
dadaista 0:14e5e829dffe 80 #define OBJ_SET_GCVAL(pobj, gcval)
dadaista 0:14e5e829dffe 81 #endif /* HAVE_GC */
dadaista 0:14e5e829dffe 82
dadaista 0:14e5e829dffe 83
dadaista 0:14e5e829dffe 84 /**
dadaista 0:14e5e829dffe 85 * The following is a diagram of the heap descriptor at the head of the chunk:
dadaista 0:14e5e829dffe 86 *
dadaista 0:14e5e829dffe 87 * MSb LSb
dadaista 0:14e5e829dffe 88 * 7 6 5 4 3 2 1 0
dadaista 0:14e5e829dffe 89 * pchunk-> +-+-+-+-+-+-+-+-+
dadaista 0:14e5e829dffe 90 * | S[9:2] | S := Size of the chunk (2 LSbs dropped)
dadaista 0:14e5e829dffe 91 * +-+-+-----------+ F := Chunk free bit (not in use)
dadaista 0:14e5e829dffe 92 * |F|R| S[15:10] | R := Bit reserved for future use
dadaista 0:14e5e829dffe 93 * +-+-+-----------+
dadaista 0:14e5e829dffe 94 * | P(L) | P := hd_prev: Pointer to previous node
dadaista 0:14e5e829dffe 95 * | P(H) | N := hd_next: Pointer to next node
dadaista 0:14e5e829dffe 96 * | N(L) |
dadaista 0:14e5e829dffe 97 * | N(H) | Theoretical min size == 6
dadaista 0:14e5e829dffe 98 * +---------------+ Effective min size == 8
dadaista 0:14e5e829dffe 99 * | unused space | (12 on 32-bit MCUs)
dadaista 0:14e5e829dffe 100 * ... ...
dadaista 0:14e5e829dffe 101 * | end chunk |
dadaista 0:14e5e829dffe 102 * +---------------+
dadaista 0:14e5e829dffe 103 */
dadaista 0:14e5e829dffe 104 typedef struct PmHeapDesc_s
dadaista 0:14e5e829dffe 105 {
dadaista 0:14e5e829dffe 106 /** Heap descriptor */
dadaista 0:14e5e829dffe 107 uint16_t hd;
dadaista 0:14e5e829dffe 108
dadaista 0:14e5e829dffe 109 /** Ptr to prev heap chunk */
dadaista 0:14e5e829dffe 110 struct PmHeapDesc_s *prev;
dadaista 0:14e5e829dffe 111
dadaista 0:14e5e829dffe 112 /** Ptr to next heap chunk */
dadaista 0:14e5e829dffe 113 struct PmHeapDesc_s *next;
dadaista 0:14e5e829dffe 114 } PmHeapDesc_t,
dadaista 0:14e5e829dffe 115 *pPmHeapDesc_t;
dadaista 0:14e5e829dffe 116
dadaista 0:14e5e829dffe 117 typedef struct PmHeap_s
dadaista 0:14e5e829dffe 118 {
dadaista 0:14e5e829dffe 119 /*
dadaista 0:14e5e829dffe 120 * WARNING: Leave 'base' field at the top of struct to increase chance
dadaista 0:14e5e829dffe 121 * of alignment when compiler doesn't recognize the aligned attribute
dadaista 0:14e5e829dffe 122 * which is specific to GCC
dadaista 0:14e5e829dffe 123 */
dadaista 0:14e5e829dffe 124 /** Global declaration of heap. */
dadaista 0:14e5e829dffe 125 uint8_t base[PM_HEAP_SIZE];
dadaista 0:14e5e829dffe 126
dadaista 0:14e5e829dffe 127 /** Ptr to list of free chunks; sorted smallest to largest. */
dadaista 0:14e5e829dffe 128 pPmHeapDesc_t pfreelist;
dadaista 0:14e5e829dffe 129
dadaista 0:14e5e829dffe 130 /** The amount of heap space available in free list */
dadaista 0:14e5e829dffe 131 #if PM_HEAP_SIZE > 65535
dadaista 0:14e5e829dffe 132 uint32_t avail;
dadaista 0:14e5e829dffe 133 #else
dadaista 0:14e5e829dffe 134 uint16_t avail;
dadaista 0:14e5e829dffe 135 #endif
dadaista 0:14e5e829dffe 136
dadaista 0:14e5e829dffe 137 #ifdef HAVE_GC
dadaista 0:14e5e829dffe 138 /** Garbage collection mark value */
dadaista 0:14e5e829dffe 139 uint8_t gcval;
dadaista 0:14e5e829dffe 140
dadaista 0:14e5e829dffe 141 /** Boolean to indicate if GC should run automatically */
dadaista 0:14e5e829dffe 142 uint8_t auto_gc;
dadaista 0:14e5e829dffe 143 #endif /* HAVE_GC */
dadaista 0:14e5e829dffe 144
dadaista 0:14e5e829dffe 145 } PmHeap_t,
dadaista 0:14e5e829dffe 146 *pPmHeap_t;
dadaista 0:14e5e829dffe 147
dadaista 0:14e5e829dffe 148
dadaista 0:14e5e829dffe 149 /** The PyMite heap */
dadaista 0:14e5e829dffe 150 static PmHeap_t pmHeap;
dadaista 0:14e5e829dffe 151
dadaista 0:14e5e829dffe 152
dadaista 0:14e5e829dffe 153 #if 0
dadaista 0:14e5e829dffe 154 static void
dadaista 0:14e5e829dffe 155 heap_gcPrintFreelist(void)
dadaista 0:14e5e829dffe 156 {
dadaista 0:14e5e829dffe 157 pPmHeapDesc_t pchunk = pmHeap.pfreelist;
dadaista 0:14e5e829dffe 158
dadaista 0:14e5e829dffe 159 printf("DEBUG: pmHeap.avail = %d\n", pmHeap.avail);
dadaista 0:14e5e829dffe 160 printf("DEBUG: freelist:\n");
dadaista 0:14e5e829dffe 161 while (pchunk != C_NULL)
dadaista 0:14e5e829dffe 162 {
dadaista 0:14e5e829dffe 163 printf("DEBUG: free chunk (%d bytes) @ 0x%0x\n",
dadaista 0:14e5e829dffe 164 OBJ_GET_SIZE(pchunk), (int)pchunk);
dadaista 0:14e5e829dffe 165 pchunk = pchunk->next;
dadaista 0:14e5e829dffe 166 }
dadaista 0:14e5e829dffe 167 }
dadaista 0:14e5e829dffe 168 #endif
dadaista 0:14e5e829dffe 169
dadaista 0:14e5e829dffe 170
dadaista 0:14e5e829dffe 171 #if 0
dadaista 0:14e5e829dffe 172 /** DEBUG: dumps the heap and roots list to a file */
dadaista 0:14e5e829dffe 173 static void
dadaista 0:14e5e829dffe 174 heap_dump(void)
dadaista 0:14e5e829dffe 175 {
dadaista 0:14e5e829dffe 176 static int n = 0;
dadaista 0:14e5e829dffe 177 int i;
dadaista 0:14e5e829dffe 178 char filename[32];
dadaista 0:14e5e829dffe 179 FILE *fp;
dadaista 0:14e5e829dffe 180
dadaista 0:14e5e829dffe 181 snprintf(filename, 32, "pmheapdump%02d.bin", n++);
dadaista 0:14e5e829dffe 182 fp = fopen(filename, "wb");
dadaista 0:14e5e829dffe 183
dadaista 0:14e5e829dffe 184 /* Write size of heap */
dadaista 0:14e5e829dffe 185 i = PM_HEAP_SIZE;
dadaista 0:14e5e829dffe 186 fwrite(&i, sizeof(int), 1, fp);
dadaista 0:14e5e829dffe 187
dadaista 0:14e5e829dffe 188 /* Write base address of heap */
dadaista 0:14e5e829dffe 189 i = (int)&pmHeap.base;
dadaista 0:14e5e829dffe 190 fwrite(&i, sizeof(int *), 1, fp);
dadaista 0:14e5e829dffe 191
dadaista 0:14e5e829dffe 192 /* Write contents of heap */
dadaista 0:14e5e829dffe 193 fwrite(&pmHeap.base, 1, PM_HEAP_SIZE, fp);
dadaista 0:14e5e829dffe 194
dadaista 0:14e5e829dffe 195 /* Write num roots*/
dadaista 0:14e5e829dffe 196 i = 10;
dadaista 0:14e5e829dffe 197 fwrite(&i, sizeof(int), 1, fp);
dadaista 0:14e5e829dffe 198
dadaista 0:14e5e829dffe 199 /* Write heap root ptrs */
dadaista 0:14e5e829dffe 200 fwrite((void *)&gVmGlobal.pnone, sizeof(intptr_t), 1, fp);
dadaista 0:14e5e829dffe 201 fwrite((void *)&gVmGlobal.pfalse, sizeof(intptr_t), 1, fp);
dadaista 0:14e5e829dffe 202 fwrite((void *)&gVmGlobal.ptrue, sizeof(intptr_t), 1, fp);
dadaista 0:14e5e829dffe 203 fwrite((void *)&gVmGlobal.pzero, sizeof(intptr_t), 1, fp);
dadaista 0:14e5e829dffe 204 fwrite((void *)&gVmGlobal.pone, sizeof(intptr_t), 1, fp);
dadaista 0:14e5e829dffe 205 fwrite((void *)&gVmGlobal.pnegone, sizeof(intptr_t), 1, fp);
dadaista 0:14e5e829dffe 206 fwrite((void *)&gVmGlobal.pcodeStr, sizeof(intptr_t), 1, fp);
dadaista 0:14e5e829dffe 207 fwrite((void *)&gVmGlobal.builtins, sizeof(intptr_t), 1, fp);
dadaista 0:14e5e829dffe 208 fwrite((void *)&gVmGlobal.nativeframe, sizeof(intptr_t), 1, fp);
dadaista 0:14e5e829dffe 209 fwrite((void *)&gVmGlobal.threadList, sizeof(intptr_t), 1, fp);
dadaista 0:14e5e829dffe 210 fclose(fp);
dadaista 0:14e5e829dffe 211 }
dadaista 0:14e5e829dffe 212 #endif
dadaista 0:14e5e829dffe 213
dadaista 0:14e5e829dffe 214
dadaista 0:14e5e829dffe 215 /* Removes the given chunk from the free list; leaves list in sorted order */
dadaista 0:14e5e829dffe 216 static PmReturn_t
dadaista 0:14e5e829dffe 217 heap_unlinkFromFreelist(pPmHeapDesc_t pchunk)
dadaista 0:14e5e829dffe 218 {
dadaista 0:14e5e829dffe 219 C_ASSERT(pchunk != C_NULL);
dadaista 0:14e5e829dffe 220
dadaista 0:14e5e829dffe 221 pmHeap.avail -= OBJ_GET_SIZE(pchunk);
dadaista 0:14e5e829dffe 222
dadaista 0:14e5e829dffe 223 if (pchunk->next != C_NULL)
dadaista 0:14e5e829dffe 224 {
dadaista 0:14e5e829dffe 225 pchunk->next->prev = pchunk->prev;
dadaista 0:14e5e829dffe 226 }
dadaista 0:14e5e829dffe 227
dadaista 0:14e5e829dffe 228 /* If pchunk was the first chunk in the free list, update the heap ptr */
dadaista 0:14e5e829dffe 229 if (pchunk->prev == C_NULL)
dadaista 0:14e5e829dffe 230 {
dadaista 0:14e5e829dffe 231 pmHeap.pfreelist = pchunk->next;
dadaista 0:14e5e829dffe 232 }
dadaista 0:14e5e829dffe 233 else
dadaista 0:14e5e829dffe 234 {
dadaista 0:14e5e829dffe 235 pchunk->prev->next = pchunk->next;
dadaista 0:14e5e829dffe 236 }
dadaista 0:14e5e829dffe 237
dadaista 0:14e5e829dffe 238 return PM_RET_OK;
dadaista 0:14e5e829dffe 239 }
dadaista 0:14e5e829dffe 240
dadaista 0:14e5e829dffe 241
dadaista 0:14e5e829dffe 242 /* Inserts in order a chunk into the free list. Caller adjusts heap state */
dadaista 0:14e5e829dffe 243 static PmReturn_t
dadaista 0:14e5e829dffe 244 heap_linkToFreelist(pPmHeapDesc_t pchunk)
dadaista 0:14e5e829dffe 245 {
dadaista 0:14e5e829dffe 246 uint16_t size;
dadaista 0:14e5e829dffe 247 pPmHeapDesc_t pscan;
dadaista 0:14e5e829dffe 248
dadaista 0:14e5e829dffe 249 /* Ensure the object is already free */
dadaista 0:14e5e829dffe 250 C_ASSERT(OBJ_GET_FREE(pchunk) != 0);
dadaista 0:14e5e829dffe 251
dadaista 0:14e5e829dffe 252 pmHeap.avail += OBJ_GET_SIZE(pchunk);
dadaista 0:14e5e829dffe 253
dadaista 0:14e5e829dffe 254 /* If free list is empty, add to head of list */
dadaista 0:14e5e829dffe 255 if (pmHeap.pfreelist == C_NULL)
dadaista 0:14e5e829dffe 256 {
dadaista 0:14e5e829dffe 257 pmHeap.pfreelist = pchunk;
dadaista 0:14e5e829dffe 258 pchunk->next = C_NULL;
dadaista 0:14e5e829dffe 259 pchunk->prev = C_NULL;
dadaista 0:14e5e829dffe 260
dadaista 0:14e5e829dffe 261 return PM_RET_OK;
dadaista 0:14e5e829dffe 262 }
dadaista 0:14e5e829dffe 263
dadaista 0:14e5e829dffe 264 /* Scan free list for insertion point */
dadaista 0:14e5e829dffe 265 pscan = pmHeap.pfreelist;
dadaista 0:14e5e829dffe 266 size = OBJ_GET_SIZE(pchunk);
dadaista 0:14e5e829dffe 267 while ((OBJ_GET_SIZE(pscan) < size) && (pscan->next != C_NULL))
dadaista 0:14e5e829dffe 268 {
dadaista 0:14e5e829dffe 269 pscan = pscan->next;
dadaista 0:14e5e829dffe 270 }
dadaista 0:14e5e829dffe 271
dadaista 0:14e5e829dffe 272 /*
dadaista 0:14e5e829dffe 273 * Insert chunk after the scan chunk (next is NULL).
dadaista 0:14e5e829dffe 274 * This is a slightly rare case where the last chunk in the free list
dadaista 0:14e5e829dffe 275 * is smaller than the chunk being freed.
dadaista 0:14e5e829dffe 276 */
dadaista 0:14e5e829dffe 277 if (size > OBJ_GET_SIZE(pscan))
dadaista 0:14e5e829dffe 278 {
dadaista 0:14e5e829dffe 279 pchunk->next = pscan->next;
dadaista 0:14e5e829dffe 280 pscan->next = pchunk;
dadaista 0:14e5e829dffe 281 pchunk->prev = pscan;
dadaista 0:14e5e829dffe 282 }
dadaista 0:14e5e829dffe 283
dadaista 0:14e5e829dffe 284 /* Insert chunk before the scan chunk */
dadaista 0:14e5e829dffe 285 else
dadaista 0:14e5e829dffe 286 {
dadaista 0:14e5e829dffe 287 pchunk->next = pscan;
dadaista 0:14e5e829dffe 288 pchunk->prev = pscan->prev;
dadaista 0:14e5e829dffe 289
dadaista 0:14e5e829dffe 290 /* If chunk will be first item in free list */
dadaista 0:14e5e829dffe 291 if (pscan->prev == C_NULL)
dadaista 0:14e5e829dffe 292 {
dadaista 0:14e5e829dffe 293 pmHeap.pfreelist = pchunk;
dadaista 0:14e5e829dffe 294 }
dadaista 0:14e5e829dffe 295 else
dadaista 0:14e5e829dffe 296 {
dadaista 0:14e5e829dffe 297 pscan->prev->next = pchunk;
dadaista 0:14e5e829dffe 298 }
dadaista 0:14e5e829dffe 299 pscan->prev = pchunk;
dadaista 0:14e5e829dffe 300 }
dadaista 0:14e5e829dffe 301
dadaista 0:14e5e829dffe 302 return PM_RET_OK;
dadaista 0:14e5e829dffe 303 }
dadaista 0:14e5e829dffe 304
dadaista 0:14e5e829dffe 305
dadaista 0:14e5e829dffe 306 /*
dadaista 0:14e5e829dffe 307 * Initializes the heap state variables
dadaista 0:14e5e829dffe 308 */
dadaista 0:14e5e829dffe 309 PmReturn_t
dadaista 0:14e5e829dffe 310 heap_init(void)
dadaista 0:14e5e829dffe 311 {
dadaista 0:14e5e829dffe 312 pPmHeapDesc_t pchunk;
dadaista 0:14e5e829dffe 313
dadaista 0:14e5e829dffe 314 #if PM_HEAP_SIZE > 65535
dadaista 0:14e5e829dffe 315 uint32_t hs;
dadaista 0:14e5e829dffe 316 #else
dadaista 0:14e5e829dffe 317 uint16_t hs;
dadaista 0:14e5e829dffe 318 #endif
dadaista 0:14e5e829dffe 319
dadaista 0:14e5e829dffe 320 /* Init heap globals */
dadaista 0:14e5e829dffe 321 pmHeap.pfreelist = C_NULL;
dadaista 0:14e5e829dffe 322 pmHeap.avail = 0;
dadaista 0:14e5e829dffe 323 #ifdef HAVE_GC
dadaista 0:14e5e829dffe 324 pmHeap.gcval = (uint8_t)0;
dadaista 0:14e5e829dffe 325 heap_gcSetAuto(C_TRUE);
dadaista 0:14e5e829dffe 326 #endif /* HAVE_GC */
dadaista 0:14e5e829dffe 327
dadaista 0:14e5e829dffe 328 /* Create as many max-sized chunks as possible in the freelist */
dadaista 0:14e5e829dffe 329 for (pchunk = (pPmHeapDesc_t)pmHeap.base, hs = PM_HEAP_SIZE;
dadaista 0:14e5e829dffe 330 hs >= HEAP_MAX_FREE_CHUNK_SIZE; hs -= HEAP_MAX_FREE_CHUNK_SIZE)
dadaista 0:14e5e829dffe 331 {
dadaista 0:14e5e829dffe 332 OBJ_SET_FREE(pchunk, 1);
dadaista 0:14e5e829dffe 333 OBJ_SET_SIZE(pchunk, HEAP_MAX_FREE_CHUNK_SIZE);
dadaista 0:14e5e829dffe 334 heap_linkToFreelist(pchunk);
dadaista 0:14e5e829dffe 335 pchunk =
dadaista 0:14e5e829dffe 336 (pPmHeapDesc_t)((uint8_t *)pchunk + HEAP_MAX_FREE_CHUNK_SIZE);
dadaista 0:14e5e829dffe 337 }
dadaista 0:14e5e829dffe 338
dadaista 0:14e5e829dffe 339 /* Add any leftover memory to the freelist */
dadaista 0:14e5e829dffe 340 if (hs >= HEAP_MIN_CHUNK_SIZE)
dadaista 0:14e5e829dffe 341 {
dadaista 0:14e5e829dffe 342 /* Round down to a multiple of four */
dadaista 0:14e5e829dffe 343 hs = hs & ~3;
dadaista 0:14e5e829dffe 344 OBJ_SET_FREE(pchunk, 1);
dadaista 0:14e5e829dffe 345 OBJ_SET_SIZE(pchunk, hs);
dadaista 0:14e5e829dffe 346 heap_linkToFreelist(pchunk);
dadaista 0:14e5e829dffe 347 }
dadaista 0:14e5e829dffe 348
dadaista 0:14e5e829dffe 349 C_DEBUG_PRINT(VERBOSITY_LOW, "heap_init(), id=%p, s=%d\n",
dadaista 0:14e5e829dffe 350 pmHeap.base, pmHeap.avail);
dadaista 0:14e5e829dffe 351
dadaista 0:14e5e829dffe 352 string_cacheInit();
dadaista 0:14e5e829dffe 353
dadaista 0:14e5e829dffe 354 return PM_RET_OK;
dadaista 0:14e5e829dffe 355 }
dadaista 0:14e5e829dffe 356
dadaista 0:14e5e829dffe 357
dadaista 0:14e5e829dffe 358 /**
dadaista 0:14e5e829dffe 359 * Obtains a chunk of memory from the free list
dadaista 0:14e5e829dffe 360 *
dadaista 0:14e5e829dffe 361 * Performs the Best Fit algorithm.
dadaista 0:14e5e829dffe 362 * Iterates through the freelist to see if a chunk of suitable size exists.
dadaista 0:14e5e829dffe 363 * Shaves a chunk to perfect size iff the remainder is greater than
dadaista 0:14e5e829dffe 364 * the minimum chunk size.
dadaista 0:14e5e829dffe 365 *
dadaista 0:14e5e829dffe 366 * @param size Requested chunk size
dadaista 0:14e5e829dffe 367 * @param r_pchunk Return ptr to chunk
dadaista 0:14e5e829dffe 368 * @return Return status
dadaista 0:14e5e829dffe 369 */
dadaista 0:14e5e829dffe 370 static PmReturn_t
dadaista 0:14e5e829dffe 371 heap_getChunkImpl(uint16_t size, uint8_t **r_pchunk)
dadaista 0:14e5e829dffe 372 {
dadaista 0:14e5e829dffe 373 PmReturn_t retval;
dadaista 0:14e5e829dffe 374 pPmHeapDesc_t pchunk;
dadaista 0:14e5e829dffe 375 pPmHeapDesc_t premainderChunk;
dadaista 0:14e5e829dffe 376
dadaista 0:14e5e829dffe 377 C_ASSERT(r_pchunk != C_NULL);
dadaista 0:14e5e829dffe 378
dadaista 0:14e5e829dffe 379 /* Skip to the first chunk that can hold the requested size */
dadaista 0:14e5e829dffe 380 pchunk = pmHeap.pfreelist;
dadaista 0:14e5e829dffe 381 while ((pchunk != C_NULL) && (OBJ_GET_SIZE(pchunk) < size))
dadaista 0:14e5e829dffe 382 {
dadaista 0:14e5e829dffe 383 pchunk = pchunk->next;
dadaista 0:14e5e829dffe 384 }
dadaista 0:14e5e829dffe 385
dadaista 0:14e5e829dffe 386 /* No chunk of appropriate size was found, raise OutOfMemory exception */
dadaista 0:14e5e829dffe 387 if (pchunk == C_NULL)
dadaista 0:14e5e829dffe 388 {
dadaista 0:14e5e829dffe 389 *r_pchunk = C_NULL;
dadaista 0:14e5e829dffe 390 PM_RAISE(retval, PM_RET_EX_MEM);
dadaista 0:14e5e829dffe 391 return retval;
dadaista 0:14e5e829dffe 392 }
dadaista 0:14e5e829dffe 393
dadaista 0:14e5e829dffe 394 /* Remove the chunk from the free list */
dadaista 0:14e5e829dffe 395 retval = heap_unlinkFromFreelist(pchunk);
dadaista 0:14e5e829dffe 396 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 397
dadaista 0:14e5e829dffe 398 /* Check if a chunk should be carved from what is available */
dadaista 0:14e5e829dffe 399 if (OBJ_GET_SIZE(pchunk) - size >= HEAP_MIN_CHUNK_SIZE)
dadaista 0:14e5e829dffe 400 {
dadaista 0:14e5e829dffe 401 /* Create the heap descriptor for the remainder chunk */
dadaista 0:14e5e829dffe 402 premainderChunk = (pPmHeapDesc_t)((uint8_t *)pchunk + size);
dadaista 0:14e5e829dffe 403 OBJ_SET_FREE(premainderChunk, 1);
dadaista 0:14e5e829dffe 404 OBJ_SET_SIZE(premainderChunk, OBJ_GET_SIZE(pchunk) - size);
dadaista 0:14e5e829dffe 405
dadaista 0:14e5e829dffe 406 /* Put the remainder chunk back in the free list */
dadaista 0:14e5e829dffe 407 retval = heap_linkToFreelist(premainderChunk);
dadaista 0:14e5e829dffe 408 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 409
dadaista 0:14e5e829dffe 410 /* Convert the chunk from a heap descriptor to an object descriptor */
dadaista 0:14e5e829dffe 411 OBJ_SET_SIZE(pchunk, 0);
dadaista 0:14e5e829dffe 412 OBJ_SET_FREE(pchunk, 0);
dadaista 0:14e5e829dffe 413 OBJ_SET_SIZE(pchunk, size);
dadaista 0:14e5e829dffe 414
dadaista 0:14e5e829dffe 415 C_DEBUG_PRINT(VERBOSITY_HIGH,
dadaista 0:14e5e829dffe 416 "heap_getChunkImpl()carved, id=%p, s=%d\n", pchunk,
dadaista 0:14e5e829dffe 417 size);
dadaista 0:14e5e829dffe 418 }
dadaista 0:14e5e829dffe 419 else
dadaista 0:14e5e829dffe 420 {
dadaista 0:14e5e829dffe 421 /* Set chunk's type to none (overwrites size field's high byte) */
dadaista 0:14e5e829dffe 422 OBJ_SET_TYPE((pPmObj_t)pchunk, OBJ_TYPE_NON);
dadaista 0:14e5e829dffe 423 OBJ_SET_FREE(pchunk, 0);
dadaista 0:14e5e829dffe 424
dadaista 0:14e5e829dffe 425 C_DEBUG_PRINT(VERBOSITY_HIGH,
dadaista 0:14e5e829dffe 426 "heap_getChunkImpl()exact, id=%p, s=%d\n", pchunk,
dadaista 0:14e5e829dffe 427 OBJ_GET_SIZE(pchunk));
dadaista 0:14e5e829dffe 428 }
dadaista 0:14e5e829dffe 429
dadaista 0:14e5e829dffe 430 /*
dadaista 0:14e5e829dffe 431 * Set the chunk's GC mark so it will be collected during the next GC cycle
dadaista 0:14e5e829dffe 432 * if it is not reachable
dadaista 0:14e5e829dffe 433 */
dadaista 0:14e5e829dffe 434 OBJ_SET_GCVAL(pchunk, pmHeap.gcval);
dadaista 0:14e5e829dffe 435
dadaista 0:14e5e829dffe 436 /* Return the chunk */
dadaista 0:14e5e829dffe 437 *r_pchunk = (uint8_t *)pchunk;
dadaista 0:14e5e829dffe 438
dadaista 0:14e5e829dffe 439 return retval;
dadaista 0:14e5e829dffe 440 }
dadaista 0:14e5e829dffe 441
dadaista 0:14e5e829dffe 442
dadaista 0:14e5e829dffe 443 /*
dadaista 0:14e5e829dffe 444 * Allocates chunk of memory.
dadaista 0:14e5e829dffe 445 * Filters out invalid sizes.
dadaista 0:14e5e829dffe 446 * Rounds the size up to the next multiple of 4.
dadaista 0:14e5e829dffe 447 * Obtains a chunk of at least the desired size.
dadaista 0:14e5e829dffe 448 */
dadaista 0:14e5e829dffe 449 PmReturn_t
dadaista 0:14e5e829dffe 450 heap_getChunk(uint16_t requestedsize, uint8_t **r_pchunk)
dadaista 0:14e5e829dffe 451 {
dadaista 0:14e5e829dffe 452 PmReturn_t retval;
dadaista 0:14e5e829dffe 453 uint16_t adjustedsize;
dadaista 0:14e5e829dffe 454
dadaista 0:14e5e829dffe 455 /* Ensure size request is valid */
dadaista 0:14e5e829dffe 456 if (requestedsize > HEAP_MAX_LIVE_CHUNK_SIZE)
dadaista 0:14e5e829dffe 457 {
dadaista 0:14e5e829dffe 458 PM_RAISE(retval, PM_RET_EX_MEM);
dadaista 0:14e5e829dffe 459 return retval;
dadaista 0:14e5e829dffe 460 }
dadaista 0:14e5e829dffe 461
dadaista 0:14e5e829dffe 462 else if (requestedsize < HEAP_MIN_CHUNK_SIZE)
dadaista 0:14e5e829dffe 463 {
dadaista 0:14e5e829dffe 464 requestedsize = HEAP_MIN_CHUNK_SIZE;
dadaista 0:14e5e829dffe 465 }
dadaista 0:14e5e829dffe 466
dadaista 0:14e5e829dffe 467 /*
dadaista 0:14e5e829dffe 468 * Round up the size to a multiple of 4 bytes.
dadaista 0:14e5e829dffe 469 * This maintains alignment on 32-bit platforms (required).
dadaista 0:14e5e829dffe 470 */
dadaista 0:14e5e829dffe 471 adjustedsize = ((requestedsize + 3) & ~3);
dadaista 0:14e5e829dffe 472
dadaista 0:14e5e829dffe 473 /* Attempt to get a chunk */
dadaista 0:14e5e829dffe 474 retval = heap_getChunkImpl(adjustedsize, r_pchunk);
dadaista 0:14e5e829dffe 475
dadaista 0:14e5e829dffe 476 #ifdef HAVE_GC
dadaista 0:14e5e829dffe 477 /* Perform GC if out of memory, gc is enabled and not in native session */
dadaista 0:14e5e829dffe 478 if ((retval == PM_RET_EX_MEM) && (pmHeap.auto_gc == C_TRUE)
dadaista 0:14e5e829dffe 479 && (gVmGlobal.nativeframe.nf_active == C_FALSE))
dadaista 0:14e5e829dffe 480 {
dadaista 0:14e5e829dffe 481 retval = heap_gcRun();
dadaista 0:14e5e829dffe 482 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 483
dadaista 0:14e5e829dffe 484 /* Attempt to get a chunk */
dadaista 0:14e5e829dffe 485 retval = heap_getChunkImpl(adjustedsize, r_pchunk);
dadaista 0:14e5e829dffe 486 }
dadaista 0:14e5e829dffe 487 #endif /* HAVE_GC */
dadaista 0:14e5e829dffe 488
dadaista 0:14e5e829dffe 489 /* Ensure that the pointer is 4-byte aligned */
dadaista 0:14e5e829dffe 490 if (retval == PM_RET_OK)
dadaista 0:14e5e829dffe 491 {
dadaista 0:14e5e829dffe 492 C_ASSERT(((intptr_t)*r_pchunk & 3) == 0);
dadaista 0:14e5e829dffe 493 }
dadaista 0:14e5e829dffe 494
dadaista 0:14e5e829dffe 495 return retval;
dadaista 0:14e5e829dffe 496 }
dadaista 0:14e5e829dffe 497
dadaista 0:14e5e829dffe 498
dadaista 0:14e5e829dffe 499 /* Releases chunk to the free list */
dadaista 0:14e5e829dffe 500 PmReturn_t
dadaista 0:14e5e829dffe 501 heap_freeChunk(pPmObj_t ptr)
dadaista 0:14e5e829dffe 502 {
dadaista 0:14e5e829dffe 503 PmReturn_t retval;
dadaista 0:14e5e829dffe 504
dadaista 0:14e5e829dffe 505 C_DEBUG_PRINT(VERBOSITY_HIGH, "heap_freeChunk(), id=%p, s=%d\n",
dadaista 0:14e5e829dffe 506 ptr, OBJ_GET_SIZE(ptr));
dadaista 0:14e5e829dffe 507
dadaista 0:14e5e829dffe 508 /* Ensure the chunk falls within the heap */
dadaista 0:14e5e829dffe 509 C_ASSERT(((uint8_t *)ptr >= pmHeap.base)
dadaista 0:14e5e829dffe 510 && ((uint8_t *)ptr < pmHeap.base + PM_HEAP_SIZE));
dadaista 0:14e5e829dffe 511
dadaista 0:14e5e829dffe 512 /* Insert the chunk into the freelist */
dadaista 0:14e5e829dffe 513 OBJ_SET_FREE(ptr, 1);
dadaista 0:14e5e829dffe 514
dadaista 0:14e5e829dffe 515 /* Clear type so that heap descriptor's size's upper byte is zero */
dadaista 0:14e5e829dffe 516 OBJ_SET_TYPE(ptr, 0);
dadaista 0:14e5e829dffe 517 retval = heap_linkToFreelist((pPmHeapDesc_t)ptr);
dadaista 0:14e5e829dffe 518 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 519
dadaista 0:14e5e829dffe 520 return retval;
dadaista 0:14e5e829dffe 521 }
dadaista 0:14e5e829dffe 522
dadaista 0:14e5e829dffe 523
dadaista 0:14e5e829dffe 524 /* Returns, by reference, the number of bytes available in the heap */
dadaista 0:14e5e829dffe 525 #if PM_HEAP_SIZE > 65535
dadaista 0:14e5e829dffe 526 uint32_t
dadaista 0:14e5e829dffe 527 #else
dadaista 0:14e5e829dffe 528 uint16_t
dadaista 0:14e5e829dffe 529 #endif
dadaista 0:14e5e829dffe 530 heap_getAvail(void)
dadaista 0:14e5e829dffe 531 {
dadaista 0:14e5e829dffe 532 return pmHeap.avail;
dadaista 0:14e5e829dffe 533 }
dadaista 0:14e5e829dffe 534
dadaista 0:14e5e829dffe 535
dadaista 0:14e5e829dffe 536 #ifdef HAVE_GC
dadaista 0:14e5e829dffe 537 /*
dadaista 0:14e5e829dffe 538 * Marks the given object and the objects it references.
dadaista 0:14e5e829dffe 539 *
dadaista 0:14e5e829dffe 540 * @param pobj Any non-free heap object
dadaista 0:14e5e829dffe 541 * @return Return code
dadaista 0:14e5e829dffe 542 */
dadaista 0:14e5e829dffe 543 static PmReturn_t
dadaista 0:14e5e829dffe 544 heap_gcMarkObj(pPmObj_t pobj)
dadaista 0:14e5e829dffe 545 {
dadaista 0:14e5e829dffe 546 PmReturn_t retval = PM_RET_OK;
dadaista 0:14e5e829dffe 547 int16_t i = 0;
dadaista 0:14e5e829dffe 548 PmType_t type;
dadaista 0:14e5e829dffe 549
dadaista 0:14e5e829dffe 550 /* Return if ptr is null or object is already marked */
dadaista 0:14e5e829dffe 551 if ((pobj == C_NULL) || (OBJ_GET_GCVAL(pobj) == pmHeap.gcval))
dadaista 0:14e5e829dffe 552 {
dadaista 0:14e5e829dffe 553 return retval;
dadaista 0:14e5e829dffe 554 }
dadaista 0:14e5e829dffe 555
dadaista 0:14e5e829dffe 556 /* The pointer must be within the heap (native frame is special case) */
dadaista 0:14e5e829dffe 557 C_ASSERT((((uint8_t *)pobj >= &pmHeap.base[0])
dadaista 0:14e5e829dffe 558 && ((uint8_t *)pobj <= &pmHeap.base[PM_HEAP_SIZE]))
dadaista 0:14e5e829dffe 559 || ((uint8_t *)pobj == (uint8_t *)&gVmGlobal.nativeframe));
dadaista 0:14e5e829dffe 560
dadaista 0:14e5e829dffe 561 /* The object must not already be free */
dadaista 0:14e5e829dffe 562 C_ASSERT(OBJ_GET_FREE(pobj) == 0);
dadaista 0:14e5e829dffe 563
dadaista 0:14e5e829dffe 564 type = (PmType_t)OBJ_GET_TYPE(pobj);
dadaista 0:14e5e829dffe 565 switch (type)
dadaista 0:14e5e829dffe 566 {
dadaista 0:14e5e829dffe 567 /* Objects with no references to other objects */
dadaista 0:14e5e829dffe 568 case OBJ_TYPE_NON:
dadaista 0:14e5e829dffe 569 case OBJ_TYPE_INT:
dadaista 0:14e5e829dffe 570 case OBJ_TYPE_FLT:
dadaista 0:14e5e829dffe 571 case OBJ_TYPE_STR:
dadaista 0:14e5e829dffe 572 case OBJ_TYPE_NOB:
dadaista 0:14e5e829dffe 573 case OBJ_TYPE_BOOL:
dadaista 0:14e5e829dffe 574 case OBJ_TYPE_CIO:
dadaista 0:14e5e829dffe 575 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 576 break;
dadaista 0:14e5e829dffe 577
dadaista 0:14e5e829dffe 578 case OBJ_TYPE_TUP:
dadaista 0:14e5e829dffe 579 i = ((pPmTuple_t)pobj)->length;
dadaista 0:14e5e829dffe 580
dadaista 0:14e5e829dffe 581 /* Mark tuple head */
dadaista 0:14e5e829dffe 582 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 583
dadaista 0:14e5e829dffe 584 /* Mark each obj in tuple */
dadaista 0:14e5e829dffe 585 while (--i >= 0)
dadaista 0:14e5e829dffe 586 {
dadaista 0:14e5e829dffe 587 retval = heap_gcMarkObj(((pPmTuple_t)pobj)->val[i]);
dadaista 0:14e5e829dffe 588 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 589 }
dadaista 0:14e5e829dffe 590 break;
dadaista 0:14e5e829dffe 591
dadaista 0:14e5e829dffe 592 case OBJ_TYPE_LST:
dadaista 0:14e5e829dffe 593
dadaista 0:14e5e829dffe 594 /* Mark the list */
dadaista 0:14e5e829dffe 595 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 596
dadaista 0:14e5e829dffe 597 /* Mark the seglist */
dadaista 0:14e5e829dffe 598 retval = heap_gcMarkObj((pPmObj_t)((pPmList_t)pobj)->val);
dadaista 0:14e5e829dffe 599 break;
dadaista 0:14e5e829dffe 600
dadaista 0:14e5e829dffe 601 case OBJ_TYPE_DIC:
dadaista 0:14e5e829dffe 602 /* Mark the dict head */
dadaista 0:14e5e829dffe 603 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 604
dadaista 0:14e5e829dffe 605 /* Mark the keys seglist */
dadaista 0:14e5e829dffe 606 retval = heap_gcMarkObj((pPmObj_t)((pPmDict_t)pobj)->d_keys);
dadaista 0:14e5e829dffe 607 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 608
dadaista 0:14e5e829dffe 609 /* Mark the vals seglist */
dadaista 0:14e5e829dffe 610 retval = heap_gcMarkObj((pPmObj_t)((pPmDict_t)pobj)->d_vals);
dadaista 0:14e5e829dffe 611 break;
dadaista 0:14e5e829dffe 612
dadaista 0:14e5e829dffe 613 case OBJ_TYPE_COB:
dadaista 0:14e5e829dffe 614 /* Mark the code obj head */
dadaista 0:14e5e829dffe 615 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 616
dadaista 0:14e5e829dffe 617 /* Mark the names tuple */
dadaista 0:14e5e829dffe 618 retval = heap_gcMarkObj((pPmObj_t)((pPmCo_t)pobj)->co_names);
dadaista 0:14e5e829dffe 619 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 620
dadaista 0:14e5e829dffe 621 /* Mark the consts tuple */
dadaista 0:14e5e829dffe 622 retval = heap_gcMarkObj((pPmObj_t)((pPmCo_t)pobj)->co_consts);
dadaista 0:14e5e829dffe 623 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 624
dadaista 0:14e5e829dffe 625 /* #122: Mark the code image if it is in RAM */
dadaista 0:14e5e829dffe 626 if (((pPmCo_t)pobj)->co_memspace == MEMSPACE_RAM)
dadaista 0:14e5e829dffe 627 {
dadaista 0:14e5e829dffe 628 retval = heap_gcMarkObj((pPmObj_t)
dadaista 0:14e5e829dffe 629 (((pPmCo_t)pobj)->co_codeimgaddr));
dadaista 0:14e5e829dffe 630 }
dadaista 0:14e5e829dffe 631
dadaista 0:14e5e829dffe 632 #ifdef HAVE_CLOSURES
dadaista 0:14e5e829dffe 633 /* #256: Add support for closures */
dadaista 0:14e5e829dffe 634 /* Mark the cellvars tuple */
dadaista 0:14e5e829dffe 635 retval = heap_gcMarkObj((pPmObj_t)((pPmCo_t)pobj)->co_cellvars);
dadaista 0:14e5e829dffe 636 #endif /* HAVE_CLOSURES */
dadaista 0:14e5e829dffe 637 break;
dadaista 0:14e5e829dffe 638
dadaista 0:14e5e829dffe 639 case OBJ_TYPE_MOD:
dadaista 0:14e5e829dffe 640 case OBJ_TYPE_FXN:
dadaista 0:14e5e829dffe 641 /* Module and Func objs are implemented via the PmFunc_t */
dadaista 0:14e5e829dffe 642 /* Mark the func obj head */
dadaista 0:14e5e829dffe 643 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 644
dadaista 0:14e5e829dffe 645 /* Mark the code obj */
dadaista 0:14e5e829dffe 646 retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_co);
dadaista 0:14e5e829dffe 647 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 648
dadaista 0:14e5e829dffe 649 /* Mark the attr dict */
dadaista 0:14e5e829dffe 650 retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_attrs);
dadaista 0:14e5e829dffe 651 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 652
dadaista 0:14e5e829dffe 653 #ifdef HAVE_DEFAULTARGS
dadaista 0:14e5e829dffe 654 /* Mark the default args tuple */
dadaista 0:14e5e829dffe 655 retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_defaultargs);
dadaista 0:14e5e829dffe 656 #endif /* HAVE_DEFAULTARGS */
dadaista 0:14e5e829dffe 657
dadaista 0:14e5e829dffe 658 #ifdef HAVE_CLOSURES
dadaista 0:14e5e829dffe 659 /* #256: Mark the closure tuple */
dadaista 0:14e5e829dffe 660 retval = heap_gcMarkObj((pPmObj_t)((pPmFunc_t)pobj)->f_closure);
dadaista 0:14e5e829dffe 661 #endif /* HAVE_CLOSURES */
dadaista 0:14e5e829dffe 662 break;
dadaista 0:14e5e829dffe 663
dadaista 0:14e5e829dffe 664 #ifdef HAVE_CLASSES
dadaista 0:14e5e829dffe 665 case OBJ_TYPE_CLI:
dadaista 0:14e5e829dffe 666 /* Mark the obj head */
dadaista 0:14e5e829dffe 667 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 668
dadaista 0:14e5e829dffe 669 /* Mark the class */
dadaista 0:14e5e829dffe 670 retval = heap_gcMarkObj((pPmObj_t)((pPmInstance_t)pobj)->cli_class);
dadaista 0:14e5e829dffe 671 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 672
dadaista 0:14e5e829dffe 673 /* Mark the attrs dict */
dadaista 0:14e5e829dffe 674 retval = heap_gcMarkObj((pPmObj_t)((pPmInstance_t)pobj)->cli_attrs);
dadaista 0:14e5e829dffe 675 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 676 break;
dadaista 0:14e5e829dffe 677
dadaista 0:14e5e829dffe 678 case OBJ_TYPE_MTH:
dadaista 0:14e5e829dffe 679 /* Mark the obj head */
dadaista 0:14e5e829dffe 680 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 681
dadaista 0:14e5e829dffe 682 /* Mark the instance */
dadaista 0:14e5e829dffe 683 retval = heap_gcMarkObj((pPmObj_t)((pPmMethod_t)pobj)->m_instance);
dadaista 0:14e5e829dffe 684 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 685
dadaista 0:14e5e829dffe 686 /* Mark the func */
dadaista 0:14e5e829dffe 687 retval = heap_gcMarkObj((pPmObj_t)((pPmMethod_t)pobj)->m_func);
dadaista 0:14e5e829dffe 688 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 689
dadaista 0:14e5e829dffe 690 /* Mark the attrs dict */
dadaista 0:14e5e829dffe 691 retval = heap_gcMarkObj((pPmObj_t)((pPmMethod_t)pobj)->m_attrs);
dadaista 0:14e5e829dffe 692 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 693 break;
dadaista 0:14e5e829dffe 694
dadaista 0:14e5e829dffe 695 case OBJ_TYPE_CLO:
dadaista 0:14e5e829dffe 696 /* Mark the obj head */
dadaista 0:14e5e829dffe 697 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 698
dadaista 0:14e5e829dffe 699 /* Mark the attrs dict */
dadaista 0:14e5e829dffe 700 retval = heap_gcMarkObj((pPmObj_t)((pPmClass_t)pobj)->cl_attrs);
dadaista 0:14e5e829dffe 701 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 702
dadaista 0:14e5e829dffe 703 /* Mark the base tuple */
dadaista 0:14e5e829dffe 704 retval = heap_gcMarkObj((pPmObj_t)((pPmClass_t)pobj)->cl_bases);
dadaista 0:14e5e829dffe 705 break;
dadaista 0:14e5e829dffe 706 #endif /* HAVE_CLASSES */
dadaista 0:14e5e829dffe 707
dadaista 0:14e5e829dffe 708 /*
dadaista 0:14e5e829dffe 709 * An obj in ram should not be of these types.
dadaista 0:14e5e829dffe 710 * Images arrive in RAM as string objects (image is array of bytes)
dadaista 0:14e5e829dffe 711 */
dadaista 0:14e5e829dffe 712 case OBJ_TYPE_CIM:
dadaista 0:14e5e829dffe 713 case OBJ_TYPE_NIM:
dadaista 0:14e5e829dffe 714 PM_RAISE(retval, PM_RET_EX_SYS);
dadaista 0:14e5e829dffe 715 return retval;
dadaista 0:14e5e829dffe 716
dadaista 0:14e5e829dffe 717 case OBJ_TYPE_FRM:
dadaista 0:14e5e829dffe 718 {
dadaista 0:14e5e829dffe 719 pPmObj_t *ppobj2 = C_NULL;
dadaista 0:14e5e829dffe 720
dadaista 0:14e5e829dffe 721 /* Mark the frame obj head */
dadaista 0:14e5e829dffe 722 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 723
dadaista 0:14e5e829dffe 724 /* Mark the previous frame */
dadaista 0:14e5e829dffe 725 retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_back);
dadaista 0:14e5e829dffe 726 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 727
dadaista 0:14e5e829dffe 728 /* Mark the fxn obj */
dadaista 0:14e5e829dffe 729 retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_func);
dadaista 0:14e5e829dffe 730 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 731
dadaista 0:14e5e829dffe 732 /* Mark the blockstack */
dadaista 0:14e5e829dffe 733 retval = heap_gcMarkObj((pPmObj_t)
dadaista 0:14e5e829dffe 734 ((pPmFrame_t)pobj)->fo_blockstack);
dadaista 0:14e5e829dffe 735 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 736
dadaista 0:14e5e829dffe 737 /* Mark the attrs dict */
dadaista 0:14e5e829dffe 738 retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_attrs);
dadaista 0:14e5e829dffe 739 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 740
dadaista 0:14e5e829dffe 741 /* Mark the globals dict */
dadaista 0:14e5e829dffe 742 retval = heap_gcMarkObj((pPmObj_t)((pPmFrame_t)pobj)->fo_globals);
dadaista 0:14e5e829dffe 743 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 744
dadaista 0:14e5e829dffe 745 /* Mark each obj in the locals list and the stack */
dadaista 0:14e5e829dffe 746 ppobj2 = ((pPmFrame_t)pobj)->fo_locals;
dadaista 0:14e5e829dffe 747 while (ppobj2 < ((pPmFrame_t)pobj)->fo_sp)
dadaista 0:14e5e829dffe 748 {
dadaista 0:14e5e829dffe 749 retval = heap_gcMarkObj(*ppobj2);
dadaista 0:14e5e829dffe 750 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 751 ppobj2++;
dadaista 0:14e5e829dffe 752 }
dadaista 0:14e5e829dffe 753 break;
dadaista 0:14e5e829dffe 754 }
dadaista 0:14e5e829dffe 755
dadaista 0:14e5e829dffe 756 case OBJ_TYPE_BLK:
dadaista 0:14e5e829dffe 757 /* Mark the block obj head */
dadaista 0:14e5e829dffe 758 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 759
dadaista 0:14e5e829dffe 760 /* Mark the next block in the stack */
dadaista 0:14e5e829dffe 761 retval = heap_gcMarkObj((pPmObj_t)((pPmBlock_t)pobj)->next);
dadaista 0:14e5e829dffe 762 break;
dadaista 0:14e5e829dffe 763
dadaista 0:14e5e829dffe 764 case OBJ_TYPE_SEG:
dadaista 0:14e5e829dffe 765 /* Mark the segment obj head */
dadaista 0:14e5e829dffe 766 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 767
dadaista 0:14e5e829dffe 768 /* Mark each obj in the segment */
dadaista 0:14e5e829dffe 769 for (i = 0; i < SEGLIST_OBJS_PER_SEG; i++)
dadaista 0:14e5e829dffe 770 {
dadaista 0:14e5e829dffe 771 retval = heap_gcMarkObj(((pSegment_t)pobj)->s_val[i]);
dadaista 0:14e5e829dffe 772 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 773 }
dadaista 0:14e5e829dffe 774
dadaista 0:14e5e829dffe 775 /* Mark the next segment */
dadaista 0:14e5e829dffe 776 retval = heap_gcMarkObj((pPmObj_t)((pSegment_t)pobj)->next);
dadaista 0:14e5e829dffe 777 break;
dadaista 0:14e5e829dffe 778
dadaista 0:14e5e829dffe 779 case OBJ_TYPE_SGL:
dadaista 0:14e5e829dffe 780 /* Mark the seglist obj head */
dadaista 0:14e5e829dffe 781 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 782
dadaista 0:14e5e829dffe 783 /* Mark the root segment */
dadaista 0:14e5e829dffe 784 retval = heap_gcMarkObj((pPmObj_t)((pSeglist_t)pobj)->sl_rootseg);
dadaista 0:14e5e829dffe 785 break;
dadaista 0:14e5e829dffe 786
dadaista 0:14e5e829dffe 787 case OBJ_TYPE_SQI:
dadaista 0:14e5e829dffe 788 /* Mark the sequence iterator obj head */
dadaista 0:14e5e829dffe 789 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 790
dadaista 0:14e5e829dffe 791 /* Mark the sequence */
dadaista 0:14e5e829dffe 792 retval = heap_gcMarkObj(((pPmSeqIter_t)pobj)->si_sequence);
dadaista 0:14e5e829dffe 793 break;
dadaista 0:14e5e829dffe 794
dadaista 0:14e5e829dffe 795 case OBJ_TYPE_THR:
dadaista 0:14e5e829dffe 796 /* Mark the thread obj head */
dadaista 0:14e5e829dffe 797 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 798
dadaista 0:14e5e829dffe 799 /* Mark the current frame */
dadaista 0:14e5e829dffe 800 retval = heap_gcMarkObj((pPmObj_t)((pPmThread_t)pobj)->pframe);
dadaista 0:14e5e829dffe 801 break;
dadaista 0:14e5e829dffe 802
dadaista 0:14e5e829dffe 803 case OBJ_TYPE_NFM:
dadaista 0:14e5e829dffe 804 /*
dadaista 0:14e5e829dffe 805 * Mark the obj desc. This doesn't really do much since the
dadaista 0:14e5e829dffe 806 * native frame is declared static (not from the heap), but this
dadaista 0:14e5e829dffe 807 * is here in case that ever changes
dadaista 0:14e5e829dffe 808 */
dadaista 0:14e5e829dffe 809 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 810
dadaista 0:14e5e829dffe 811 /* Mark the native frame's remaining fields if active */
dadaista 0:14e5e829dffe 812 if (gVmGlobal.nativeframe.nf_active)
dadaista 0:14e5e829dffe 813 {
dadaista 0:14e5e829dffe 814 /* Mark the frame stack */
dadaista 0:14e5e829dffe 815 retval = heap_gcMarkObj((pPmObj_t)
dadaista 0:14e5e829dffe 816 gVmGlobal.nativeframe.nf_back);
dadaista 0:14e5e829dffe 817 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 818
dadaista 0:14e5e829dffe 819 /* Mark the function object */
dadaista 0:14e5e829dffe 820 retval = heap_gcMarkObj((pPmObj_t)
dadaista 0:14e5e829dffe 821 gVmGlobal.nativeframe.nf_func);
dadaista 0:14e5e829dffe 822 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 823
dadaista 0:14e5e829dffe 824 /* Mark the stack object */
dadaista 0:14e5e829dffe 825 retval = heap_gcMarkObj(gVmGlobal.nativeframe.nf_stack);
dadaista 0:14e5e829dffe 826 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 827
dadaista 0:14e5e829dffe 828 /* Mark the args to the native func */
dadaista 0:14e5e829dffe 829 for (i = 0; i < NATIVE_GET_NUM_ARGS(); i++)
dadaista 0:14e5e829dffe 830 {
dadaista 0:14e5e829dffe 831 retval =
dadaista 0:14e5e829dffe 832 heap_gcMarkObj(gVmGlobal.nativeframe.nf_locals[i]);
dadaista 0:14e5e829dffe 833 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 834 }
dadaista 0:14e5e829dffe 835 }
dadaista 0:14e5e829dffe 836 break;
dadaista 0:14e5e829dffe 837
dadaista 0:14e5e829dffe 838 #ifdef HAVE_BYTEARRAY
dadaista 0:14e5e829dffe 839 case OBJ_TYPE_BYA:
dadaista 0:14e5e829dffe 840 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 841
dadaista 0:14e5e829dffe 842 retval = heap_gcMarkObj((pPmObj_t)((pPmBytearray_t)pobj)->val);
dadaista 0:14e5e829dffe 843 break;
dadaista 0:14e5e829dffe 844
dadaista 0:14e5e829dffe 845 case OBJ_TYPE_BYS:
dadaista 0:14e5e829dffe 846 OBJ_SET_GCVAL(pobj, pmHeap.gcval);
dadaista 0:14e5e829dffe 847 break;
dadaista 0:14e5e829dffe 848 #endif /* HAVE_BYTEARRAY */
dadaista 0:14e5e829dffe 849
dadaista 0:14e5e829dffe 850 default:
dadaista 0:14e5e829dffe 851 /* There should be no invalid types */
dadaista 0:14e5e829dffe 852 PM_RAISE(retval, PM_RET_EX_SYS);
dadaista 0:14e5e829dffe 853 break;
dadaista 0:14e5e829dffe 854 }
dadaista 0:14e5e829dffe 855 return retval;
dadaista 0:14e5e829dffe 856 }
dadaista 0:14e5e829dffe 857
dadaista 0:14e5e829dffe 858
dadaista 0:14e5e829dffe 859 /*
dadaista 0:14e5e829dffe 860 * Marks the root objects so they won't be collected during the sweep phase.
dadaista 0:14e5e829dffe 861 * Recursively marks all objects reachable from the roots.
dadaista 0:14e5e829dffe 862 */
dadaista 0:14e5e829dffe 863 static PmReturn_t
dadaista 0:14e5e829dffe 864 heap_gcMarkRoots(void)
dadaista 0:14e5e829dffe 865 {
dadaista 0:14e5e829dffe 866 PmReturn_t retval;
dadaista 0:14e5e829dffe 867
dadaista 0:14e5e829dffe 868 /* Toggle the GC marking value so it differs from the last run */
dadaista 0:14e5e829dffe 869 pmHeap.gcval ^= 1;
dadaista 0:14e5e829dffe 870
dadaista 0:14e5e829dffe 871 /* Mark the constant objects */
dadaista 0:14e5e829dffe 872 retval = heap_gcMarkObj(PM_NONE);
dadaista 0:14e5e829dffe 873 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 874 retval = heap_gcMarkObj(PM_FALSE);
dadaista 0:14e5e829dffe 875 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 876 retval = heap_gcMarkObj(PM_TRUE);
dadaista 0:14e5e829dffe 877 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 878 retval = heap_gcMarkObj(PM_ZERO);
dadaista 0:14e5e829dffe 879 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 880 retval = heap_gcMarkObj(PM_ONE);
dadaista 0:14e5e829dffe 881 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 882 retval = heap_gcMarkObj(PM_NEGONE);
dadaista 0:14e5e829dffe 883 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 884 retval = heap_gcMarkObj(PM_CODE_STR);
dadaista 0:14e5e829dffe 885 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 886
dadaista 0:14e5e829dffe 887 /* Mark the builtins dict */
dadaista 0:14e5e829dffe 888 retval = heap_gcMarkObj(PM_PBUILTINS);
dadaista 0:14e5e829dffe 889 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 890
dadaista 0:14e5e829dffe 891 /* Mark the native frame if it is active */
dadaista 0:14e5e829dffe 892 retval = heap_gcMarkObj((pPmObj_t)&gVmGlobal.nativeframe);
dadaista 0:14e5e829dffe 893 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 894
dadaista 0:14e5e829dffe 895 /* Mark the thread list */
dadaista 0:14e5e829dffe 896 retval = heap_gcMarkObj((pPmObj_t)gVmGlobal.threadList);
dadaista 0:14e5e829dffe 897
dadaista 0:14e5e829dffe 898 return retval;
dadaista 0:14e5e829dffe 899 }
dadaista 0:14e5e829dffe 900
dadaista 0:14e5e829dffe 901
dadaista 0:14e5e829dffe 902 #if USE_STRING_CACHE
dadaista 0:14e5e829dffe 903 /**
dadaista 0:14e5e829dffe 904 * Unlinks free objects from the string cache.
dadaista 0:14e5e829dffe 905 * This function must only be called by the GC after the heap has been marked
dadaista 0:14e5e829dffe 906 * and before the heap has been swept.
dadaista 0:14e5e829dffe 907 *
dadaista 0:14e5e829dffe 908 * This solves the problem where a string object would be collected
dadaista 0:14e5e829dffe 909 * but its chunk was still linked into the free list
dadaista 0:14e5e829dffe 910 *
dadaista 0:14e5e829dffe 911 * @param gcval The current value for chunks marked by the GC
dadaista 0:14e5e829dffe 912 */
dadaista 0:14e5e829dffe 913 static PmReturn_t
dadaista 0:14e5e829dffe 914 heap_purgeStringCache(uint8_t gcval)
dadaista 0:14e5e829dffe 915 {
dadaista 0:14e5e829dffe 916 PmReturn_t retval;
dadaista 0:14e5e829dffe 917 pPmString_t *ppstrcache;
dadaista 0:14e5e829dffe 918 pPmString_t pstr;
dadaista 0:14e5e829dffe 919
dadaista 0:14e5e829dffe 920 /* Update string cache pointer if the first string objs are not marked */
dadaista 0:14e5e829dffe 921 retval = string_getCache(&ppstrcache);
dadaista 0:14e5e829dffe 922 if (ppstrcache == C_NULL)
dadaista 0:14e5e829dffe 923 {
dadaista 0:14e5e829dffe 924 return retval;
dadaista 0:14e5e829dffe 925 }
dadaista 0:14e5e829dffe 926 while ((*ppstrcache != C_NULL) && (OBJ_GET_GCVAL(*ppstrcache) != gcval))
dadaista 0:14e5e829dffe 927 {
dadaista 0:14e5e829dffe 928 *ppstrcache = (*ppstrcache)->next;
dadaista 0:14e5e829dffe 929 }
dadaista 0:14e5e829dffe 930 if (*ppstrcache == C_NULL)
dadaista 0:14e5e829dffe 931 {
dadaista 0:14e5e829dffe 932 return retval;
dadaista 0:14e5e829dffe 933 }
dadaista 0:14e5e829dffe 934
dadaista 0:14e5e829dffe 935 /* Unlink remaining strings that are not marked */
dadaista 0:14e5e829dffe 936 for (pstr = *ppstrcache; pstr->next != C_NULL;)
dadaista 0:14e5e829dffe 937 {
dadaista 0:14e5e829dffe 938 /* Unlink consecutive non-marked strings */
dadaista 0:14e5e829dffe 939 while ((pstr->next != C_NULL) && (OBJ_GET_GCVAL(pstr->next) != gcval))
dadaista 0:14e5e829dffe 940 {
dadaista 0:14e5e829dffe 941 pstr->next = pstr->next->next;
dadaista 0:14e5e829dffe 942 }
dadaista 0:14e5e829dffe 943
dadaista 0:14e5e829dffe 944 /* If not at end of cache, string must be marked, skip it */
dadaista 0:14e5e829dffe 945 if (pstr->next != C_NULL)
dadaista 0:14e5e829dffe 946 {
dadaista 0:14e5e829dffe 947 pstr = pstr->next;
dadaista 0:14e5e829dffe 948 }
dadaista 0:14e5e829dffe 949 }
dadaista 0:14e5e829dffe 950
dadaista 0:14e5e829dffe 951 return retval;
dadaista 0:14e5e829dffe 952 }
dadaista 0:14e5e829dffe 953 #endif
dadaista 0:14e5e829dffe 954
dadaista 0:14e5e829dffe 955
dadaista 0:14e5e829dffe 956 /*
dadaista 0:14e5e829dffe 957 * Reclaims any object that does not have a current mark.
dadaista 0:14e5e829dffe 958 * Puts it in the free list. Coalesces all contiguous free chunks.
dadaista 0:14e5e829dffe 959 */
dadaista 0:14e5e829dffe 960 static PmReturn_t
dadaista 0:14e5e829dffe 961 heap_gcSweep(void)
dadaista 0:14e5e829dffe 962 {
dadaista 0:14e5e829dffe 963 PmReturn_t retval;
dadaista 0:14e5e829dffe 964 pPmObj_t pobj;
dadaista 0:14e5e829dffe 965 pPmHeapDesc_t pchunk;
dadaista 0:14e5e829dffe 966 uint16_t totalchunksize;
dadaista 0:14e5e829dffe 967
dadaista 0:14e5e829dffe 968 #if USE_STRING_CACHE
dadaista 0:14e5e829dffe 969 retval = heap_purgeStringCache(pmHeap.gcval);
dadaista 0:14e5e829dffe 970 #endif
dadaista 0:14e5e829dffe 971
dadaista 0:14e5e829dffe 972 /* Start at the base of the heap */
dadaista 0:14e5e829dffe 973 pobj = (pPmObj_t)pmHeap.base;
dadaista 0:14e5e829dffe 974 while ((uint8_t *)pobj < &pmHeap.base[PM_HEAP_SIZE])
dadaista 0:14e5e829dffe 975 {
dadaista 0:14e5e829dffe 976 /* Skip to the next unmarked or free chunk within the heap */
dadaista 0:14e5e829dffe 977 while (!OBJ_GET_FREE(pobj)
dadaista 0:14e5e829dffe 978 && (OBJ_GET_GCVAL(pobj) == pmHeap.gcval)
dadaista 0:14e5e829dffe 979 && ((uint8_t *)pobj < &pmHeap.base[PM_HEAP_SIZE]))
dadaista 0:14e5e829dffe 980 {
dadaista 0:14e5e829dffe 981 pobj = (pPmObj_t)((uint8_t *)pobj + OBJ_GET_SIZE(pobj));
dadaista 0:14e5e829dffe 982 }
dadaista 0:14e5e829dffe 983
dadaista 0:14e5e829dffe 984 /* Stop if reached the end of the heap */
dadaista 0:14e5e829dffe 985 if ((uint8_t *)pobj >= &pmHeap.base[PM_HEAP_SIZE])
dadaista 0:14e5e829dffe 986 {
dadaista 0:14e5e829dffe 987 break;
dadaista 0:14e5e829dffe 988 }
dadaista 0:14e5e829dffe 989
dadaista 0:14e5e829dffe 990 /* Accumulate the sizes of all consecutive unmarked or free chunks */
dadaista 0:14e5e829dffe 991 totalchunksize = 0;
dadaista 0:14e5e829dffe 992
dadaista 0:14e5e829dffe 993 /* Coalesce all contiguous free chunks */
dadaista 0:14e5e829dffe 994 pchunk = (pPmHeapDesc_t)pobj;
dadaista 0:14e5e829dffe 995 while (OBJ_GET_FREE(pchunk)
dadaista 0:14e5e829dffe 996 || (!OBJ_GET_FREE(pchunk)
dadaista 0:14e5e829dffe 997 && (OBJ_GET_GCVAL(pchunk) != pmHeap.gcval)))
dadaista 0:14e5e829dffe 998 {
dadaista 0:14e5e829dffe 999 if ((totalchunksize + OBJ_GET_SIZE(pchunk))
dadaista 0:14e5e829dffe 1000 > HEAP_MAX_FREE_CHUNK_SIZE)
dadaista 0:14e5e829dffe 1001 {
dadaista 0:14e5e829dffe 1002 break;
dadaista 0:14e5e829dffe 1003 }
dadaista 0:14e5e829dffe 1004 totalchunksize = totalchunksize + OBJ_GET_SIZE(pchunk);
dadaista 0:14e5e829dffe 1005
dadaista 0:14e5e829dffe 1006 /*
dadaista 0:14e5e829dffe 1007 * If the chunk is already free, unlink it because its size
dadaista 0:14e5e829dffe 1008 * is about to change
dadaista 0:14e5e829dffe 1009 */
dadaista 0:14e5e829dffe 1010 if (OBJ_GET_FREE(pchunk))
dadaista 0:14e5e829dffe 1011 {
dadaista 0:14e5e829dffe 1012 retval = heap_unlinkFromFreelist(pchunk);
dadaista 0:14e5e829dffe 1013 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 1014 }
dadaista 0:14e5e829dffe 1015
dadaista 0:14e5e829dffe 1016 /* Otherwise free and reclaim the unmarked chunk */
dadaista 0:14e5e829dffe 1017 else
dadaista 0:14e5e829dffe 1018 {
dadaista 0:14e5e829dffe 1019 OBJ_SET_TYPE(pchunk, 0);
dadaista 0:14e5e829dffe 1020 OBJ_SET_FREE(pchunk, 1);
dadaista 0:14e5e829dffe 1021 }
dadaista 0:14e5e829dffe 1022
dadaista 0:14e5e829dffe 1023 C_DEBUG_PRINT(VERBOSITY_HIGH, "heap_gcSweep(), id=%p, s=%d\n",
dadaista 0:14e5e829dffe 1024 pchunk, OBJ_GET_SIZE(pchunk));
dadaista 0:14e5e829dffe 1025
dadaista 0:14e5e829dffe 1026 /* Proceed to the next chunk */
dadaista 0:14e5e829dffe 1027 pchunk = (pPmHeapDesc_t)
dadaista 0:14e5e829dffe 1028 ((uint8_t *)pchunk + OBJ_GET_SIZE(pchunk));
dadaista 0:14e5e829dffe 1029
dadaista 0:14e5e829dffe 1030 /* Stop if it's past the end of the heap */
dadaista 0:14e5e829dffe 1031 if ((uint8_t *)pchunk >= &pmHeap.base[PM_HEAP_SIZE])
dadaista 0:14e5e829dffe 1032 {
dadaista 0:14e5e829dffe 1033 break;
dadaista 0:14e5e829dffe 1034 }
dadaista 0:14e5e829dffe 1035 }
dadaista 0:14e5e829dffe 1036
dadaista 0:14e5e829dffe 1037 /* Set the heap descriptor data */
dadaista 0:14e5e829dffe 1038 OBJ_SET_FREE(pobj, 1);
dadaista 0:14e5e829dffe 1039 OBJ_SET_SIZE(pobj, totalchunksize);
dadaista 0:14e5e829dffe 1040
dadaista 0:14e5e829dffe 1041 /* Insert chunk into free list */
dadaista 0:14e5e829dffe 1042 retval = heap_linkToFreelist((pPmHeapDesc_t)pobj);
dadaista 0:14e5e829dffe 1043 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 1044
dadaista 0:14e5e829dffe 1045 /* Continue to the next chunk */
dadaista 0:14e5e829dffe 1046 pobj = (pPmObj_t)pchunk;
dadaista 0:14e5e829dffe 1047 }
dadaista 0:14e5e829dffe 1048
dadaista 0:14e5e829dffe 1049 return PM_RET_OK;
dadaista 0:14e5e829dffe 1050 }
dadaista 0:14e5e829dffe 1051
dadaista 0:14e5e829dffe 1052
dadaista 0:14e5e829dffe 1053 /* Runs the mark-sweep garbage collector */
dadaista 0:14e5e829dffe 1054 PmReturn_t
dadaista 0:14e5e829dffe 1055 heap_gcRun(void)
dadaista 0:14e5e829dffe 1056 {
dadaista 0:14e5e829dffe 1057 PmReturn_t retval;
dadaista 0:14e5e829dffe 1058
dadaista 0:14e5e829dffe 1059 C_DEBUG_PRINT(VERBOSITY_LOW, "heap_gcRun()\n");
dadaista 0:14e5e829dffe 1060 /*heap_dump();*/
dadaista 0:14e5e829dffe 1061
dadaista 0:14e5e829dffe 1062 retval = heap_gcMarkRoots();
dadaista 0:14e5e829dffe 1063 PM_RETURN_IF_ERROR(retval);
dadaista 0:14e5e829dffe 1064
dadaista 0:14e5e829dffe 1065 retval = heap_gcSweep();
dadaista 0:14e5e829dffe 1066 /*heap_dump();*/
dadaista 0:14e5e829dffe 1067 return retval;
dadaista 0:14e5e829dffe 1068 }
dadaista 0:14e5e829dffe 1069
dadaista 0:14e5e829dffe 1070
dadaista 0:14e5e829dffe 1071 /* Enables or disables automatic garbage collection */
dadaista 0:14e5e829dffe 1072 PmReturn_t
dadaista 0:14e5e829dffe 1073 heap_gcSetAuto(uint8_t auto_gc)
dadaista 0:14e5e829dffe 1074 {
dadaista 0:14e5e829dffe 1075 pmHeap.auto_gc = auto_gc;
dadaista 0:14e5e829dffe 1076 return PM_RET_OK;
dadaista 0:14e5e829dffe 1077 }
dadaista 0:14e5e829dffe 1078 #endif /* HAVE_GC */