PageRenderTime 88ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/vm/vmheap.c

http://jwik.codeplex.com
C | 459 lines | 256 code | 65 blank | 138 comment | 42 complexity | b3a47b2edd4001a5cfb90679fc4a154a MD5 | raw file
Possible License(s): MIT
  1. // Java VM for small microcontrollers
  2. //
  3. // (c) 2012, Digital Six Laboratories LLC
  4. // All Rights Reserved
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
  7. // and associated documentation files (the "Software"), to deal in the Software without restriction,
  8. // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. // and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
  10. // subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in all copies or substantial
  13. // portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  16. // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  17. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  18. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  19. // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. //
  21. // Original work based on NanoVM (http://www.harbaum.org/till/nanovm/index.shtml) for AVR microcontroller
  22. //=========================================================================================================
  23. //
  24. // heap.c
  25. //
  26. // Heap management
  27. #include "vmtypes.h"
  28. #include "vmerror.h"
  29. #include "vm.h"
  30. #include "utils.h"
  31. #include "vmheap.h"
  32. #include "vmstack.h"
  33. // allocate static heap
  34. U8 xdata heap[HEAPSIZE];
  35. // this is an offset to the base of the available heap. It changes as the heap is managed.
  36. U16 xdata heapBase = 0;
  37. // ***************************************************************************************************************
  38. // Internal Functions
  39. void HeapCopyMemory(U8 xdata *dst, U8 xdata *src, U16 xdata len)
  40. {
  41. dst += len;
  42. src += len;
  43. while(len--)
  44. *--dst = *--src;
  45. }
  46. void HeapShow(void)
  47. {
  48. U16 xdata current = heapBase;
  49. while(current < sizeof(heap))
  50. {
  51. tHeapFrame *h = (tHeapFrame*)&heap[current];
  52. if(h->id == kHeapIdFree)
  53. {
  54. }
  55. else
  56. {
  57. if(h->len > sizeof(heap))
  58. HandleError(kErrorHeapIllegalChunkSize);
  59. }
  60. if(h->len+sizeof(tHeapFrame) > sizeof(heap) - current)
  61. {
  62. HandleError(kErrorHeapCorrupted);
  63. }
  64. current += h->len + sizeof(tHeapFrame);
  65. }
  66. }
  67. tHeapFrame xdata *HeapSearch(tHeapId xdata id)
  68. {
  69. U16 xdata current = heapBase;
  70. while(current < sizeof(heap))
  71. {
  72. tHeapFrame xdata *h = (tHeapFrame*)&heap[current];
  73. if(h->id == id)
  74. return h;
  75. current += h->len + sizeof(tHeapFrame);
  76. }
  77. return NULL;
  78. }
  79. tHeapId HeapNewId(void)
  80. {
  81. tHeapId xdata id;
  82. for(id=1;id;id++)
  83. if(HeapSearch(id) == NULL)
  84. return id;
  85. return 0;
  86. }
  87. BOOL HeapInternalAlloc(tHeapId xdata id, BOOL xdata fieldref, U16 xdata size)
  88. {
  89. U16 xdata req = size + sizeof(tHeapFrame); // total mem required
  90. // search for free block
  91. tHeapFrame *h = (tHeapFrame*)&heap[heapBase];
  92. if(h->len >= req)
  93. {
  94. // We are going to start pulling new heaps from the end of heap memory so we
  95. // need to reduce the size of the free block, which is always immediately after the stack
  96. // to make room.
  97. h->len -= req;
  98. // The new one is going to be at the end of the free block. To find the end, we
  99. // add up the base of the heap (1+stack bottom) plus the size of the heap frame struct
  100. // plus the len of the free block. That gives us the first byte of our newly allocated
  101. // section. So we point 'h' to that.
  102. h = (tHeapFrame*)&heap[heapBase + sizeof(tHeapFrame) + (unsigned int)(h->len)];
  103. h->id = id;
  104. h->fieldref = fieldref;
  105. h->len = size;
  106. #ifdef NVM_INITIALIZE_ALLOCATED
  107. // fill memory with zero
  108. U8 * ptr = (void*)(h+1);
  109. while(size--)
  110. *ptr++=0;
  111. #endif
  112. return TRUE;
  113. }
  114. return FALSE;
  115. }
  116. U16 HeapGetLength(tHeapId xdata id)
  117. {
  118. tHeapFrame xdata *h = HeapSearch(id);
  119. if(!h)
  120. HandleError(kErrorHeapChunkMissing);
  121. return h->len;
  122. }
  123. BOOL HeapGetFieldReference(tHeapId xdata id)
  124. {
  125. tVmReference xdata id16 = id | VM_TYPE_HEAP;
  126. U16 xdata current = heapBase;
  127. tHeapFrame xdata *h;
  128. // walk through the entire heap
  129. while(current < sizeof(heap))
  130. {
  131. h = (tHeapFrame*)&heap[current];
  132. // check for entries with the fieldref flag
  133. if(h->fieldref)
  134. {
  135. U8 j;
  136. // check all entries in the heap element for
  137. // the reference we are searching for
  138. for(j=0;j<h->len/sizeof(tVmReference);j++)
  139. {
  140. if(((tVmReference*)(h+1))[j] == id16)
  141. return TRUE;
  142. }
  143. }
  144. current += h->len + sizeof(tHeapFrame);
  145. }
  146. return FALSE;
  147. }
  148. // ***************************************************************************************************************
  149. // Public API
  150. // U8 *GetHeapBase(void)
  151. //
  152. // Arguments:
  153. // void - nothing
  154. //
  155. // Returns:
  156. // U8* - Actual base of heap ( pointer )
  157. U8 xdata *GetHeapBase(void)
  158. {
  159. return heap;
  160. }
  161. #ifdef DEBUG_JVM
  162. // void HeapCheck(void)
  163. //
  164. // Check heap and throw an error if start element is not free
  165. //
  166. // Args;
  167. // Returns:
  168. // Nothing
  169. void HeapCheck(void)
  170. {
  171. U16 xdata current = heapBase;
  172. tHeapFrame xdata *h = (tHeapFrame*)&heap[current];
  173. if(h->id != kHeapIdFree)
  174. {
  175. HandleError(kErrorHeapCorrupted);
  176. }
  177. current += h->len + sizeof(tHeapFrame);
  178. while(current < sizeof(heap))
  179. {
  180. h = (tHeapFrame*)&heap[current];
  181. if(h->id != kHeapIdFree)
  182. {
  183. if(h->len > sizeof(heap))
  184. {
  185. HeapShow();
  186. error(kErrorHeapIllegalChunkSize);
  187. }
  188. }
  189. else
  190. {
  191. HeapShow();
  192. HandleError(kErrorHeapCorrupted);
  193. }
  194. if(h->len+sizeof(tHeapFrame) > sizeof(heap) - current)
  195. {
  196. HeapShow();
  197. HandleError(kErrorHeapCorrupted);
  198. }
  199. current += h->len + sizeof(tHeapFrame);
  200. }
  201. if(current != sizeof(heap))
  202. {
  203. HeapShow();
  204. HandleError(kErrorHeapCorrupted);
  205. }
  206. }
  207. #endif
  208. // tHeapId HeapAlloc(BOOL fieldref, U16 size)
  209. //
  210. // Allocate a new heap frame and return the id.
  211. //
  212. // Args:
  213. // bool fieldref - field reference
  214. // U16 size - size to allocate
  215. // Returns;
  216. // tHeapId Id of heap frame
  217. tHeapId HeapAlloc(BOOL xdata fieldref, U16 xdata size)
  218. {
  219. tHeapId xdata id = HeapNewId();
  220. if(!HeapInternalAlloc(id, fieldref, size))
  221. {
  222. HeapCollectGarbage();
  223. // we need to reallocate heap id, gc. threw away the old one..
  224. if(!HeapInternalAlloc(id, fieldref, size))
  225. HandleError(kErrorHeapOutOfMemory);
  226. }
  227. return id;
  228. }
  229. // void HeapRealloc(tHeapId id, U16 size)
  230. //
  231. // Reallocate heap space for an existing frame
  232. //
  233. // Args:
  234. // tHeapId id - id of existing frame
  235. // U16 size - size to reallocate to
  236. // Returns:
  237. // nothing
  238. void HeapRealloc(tHeapId xdata id, U16 xdata size)
  239. {
  240. tHeapFrame xdata *h_new;
  241. tHeapFrame xdata *h;
  242. // check free mem and call garbage collection if required
  243. h = (tHeapFrame*)&heap[heapBase];
  244. if(h->len >= size + sizeof(tHeapFrame))
  245. HeapCollectGarbage();
  246. // get info on old chunk
  247. h = HeapSearch(id);
  248. // allocate space for bigger one
  249. if(!HeapInternalAlloc(id, h->fieldref, size))
  250. HandleError(kErrorHeapOutOfMemory);
  251. h_new = HeapSearch(id);
  252. UtilsCopyMemory(h_new+1, h+1, h->len);
  253. h->id = 0xff; // unused id to make garbage collection delete
  254. // this chunk next time
  255. }
  256. // void *HeapGetAddress(tHeapid id)
  257. //
  258. // Get the physical address in RAM for the start of a heap frame
  259. //
  260. // Args;
  261. // tHeapId id - id of heap frame
  262. // Returns:
  263. // void* pointer to heap frame start in RAM
  264. void xdata *HeapGetAddress(tHeapId xdata id)
  265. {
  266. tHeapFrame xdata *h = HeapSearch(id);
  267. if(!h) HandleError(kErrorHeapChunkMissing);
  268. // we need to get past the heap frame to the first byte of the heap.
  269. // By adding 1 we are really adding sizeof(tHeapFrame)
  270. h+=1;
  271. return h;
  272. }
  273. // void HeapInitialize(void)
  274. //
  275. // Initialize the heap
  276. //
  277. // Args:
  278. // Returns:
  279. // nothing
  280. void HeapInitialize(void)
  281. {
  282. unsigned int a;
  283. unsigned int b;
  284. unsigned int c;
  285. //DEBUGF("heap_init()\n");
  286. // just one big free block
  287. tHeapFrame xdata *h = (tHeapFrame xdata *)&heap[0];
  288. h->id = (tHeapId)kHeapIdFree;
  289. a = sizeof(heap);
  290. b = sizeof(tHeapFrame);
  291. c=a-b;
  292. //heap[0] = 0;
  293. //heap[1] = 0;
  294. //heap[4] = c & 0xff;
  295. //heap[5] = (c>>8) &0xff;
  296. h->fieldref = FALSE;
  297. h->len = c;
  298. }
  299. // void HeapCollectGarbage(void)
  300. //
  301. // Walk the heap and dump any objects not being used
  302. //
  303. // Args:
  304. // Returns:
  305. // nothing
  306. void HeapCollectGarbage(void)
  307. {
  308. U16 xdata current = heapBase;
  309. U16 xdata len;
  310. tHeapFrame xdata *h;
  311. // set current to stack-top
  312. // walk through the entire heap
  313. while(current < sizeof(heap))
  314. {
  315. h = (tHeapFrame xdata*)&heap[current];
  316. len = h->len + sizeof(tHeapFrame);
  317. // found an entry
  318. if(h->id != kHeapIdFree)
  319. {
  320. // check if it's still used
  321. if((!StackIsHeapIdInUse(h->id))&&(!HeapGetFieldReference(h->id)))
  322. {
  323. // it is not used, remove it
  324. // move everything before to the top
  325. HeapCopyMemory(heap+heapBase+len, heap+heapBase, current-heapBase);
  326. // add freed mem to free-chunk
  327. h = (tHeapFrame*)&heap[heapBase];
  328. h->len += len;
  329. }
  330. }
  331. current += len;
  332. }
  333. if(current != sizeof(heap))
  334. {
  335. HandleError(kErrorHeapCorrupted);
  336. }
  337. }
  338. // void HeapSteal(U16 byteCount)
  339. //
  340. // Steal bytes from the base of the heap
  341. //
  342. // Args:
  343. // U16 byteCount - number of bytes to steal
  344. // Returns:
  345. // Nothing
  346. void HeapSteal(U16 xdata byteCount)
  347. {
  348. tHeapFrame xdata *h = (tHeapFrame*)&heap[heapBase];
  349. U16 xdata len;
  350. if(h->id != kHeapIdFree)
  351. {
  352. HandleError(kErrorHeapCorrupted);
  353. }
  354. // try to make space if necessary
  355. len = h->len;
  356. if(len < byteCount)
  357. HeapCollectGarbage();
  358. len = h->len;
  359. if(len < byteCount)
  360. HandleError(kErrorHeapOutOfStackMemory);
  361. // finally steal ...
  362. heapBase += byteCount;
  363. h = (tHeapFrame xdata*)&heap[heapBase];
  364. h->id = kHeapIdFree;
  365. h->fieldref=0;
  366. h->len = len - byteCount;
  367. }
  368. // void HeapUnsteal(U16 byteCount)
  369. //
  370. // Return bytes to the heap
  371. //
  372. // Args:
  373. // U16 byteCount - number of bytes
  374. // Returns:
  375. // nothing
  376. void HeapUnsteal(U16 xdata byteCount)
  377. {
  378. tHeapFrame xdata *h = (tHeapFrame*)&heap[heapBase];
  379. U16 xdata len;
  380. if(h->id != kHeapIdFree)
  381. {
  382. HandleError(kErrorHeapCorrupted);
  383. }
  384. if(heapBase < byteCount)
  385. {
  386. HandleError(kErrorHeapStackUnderrun);
  387. }
  388. // finally unsteal ...
  389. len = h->len;
  390. heapBase -= byteCount;
  391. h = (tHeapFrame xdata*)&heap[heapBase];
  392. h->id = kHeapIdFree;
  393. h->len = len + byteCount;
  394. }