PageRenderTime 39ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/lscript/lscript_alloc.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 293 lines | 130 code | 55 blank | 108 comment | 13 complexity | 118d6e66a1d1d5056fbb430ffab12e94 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lscript_alloc.h
  3. * @brief General heap management for scripting system
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef LL_LSCRIPT_ALLOC_H
  27. #define LL_LSCRIPT_ALLOC_H
  28. // #define at top of file accelerates gcc compiles
  29. // Under gcc 2.9, the manual is unclear if comments can appear above #ifndef
  30. // Under gcc 3, the manual explicitly states comments can appear above the #ifndef
  31. #include "lscript_byteconvert.h"
  32. #include "lscript_library.h"
  33. void reset_hp_to_safe_spot(const U8 *buffer);
  34. // supported data types
  35. // basic types
  36. // integer 4 bytes of integer data
  37. // float 4 bytes of float data
  38. // string data null terminated 1 byte string
  39. // key data null terminated 1 byte string
  40. // vector data 12 bytes of 3 floats
  41. // quaternion data 16 bytes of 4 floats
  42. // list type
  43. // list data 4 bytes of number of entries followed by followed by pointer
  44. // string pointer 4 bytes of address of string data on the heap (only used in list data)
  45. // key pointer 4 bytes of address of key data on the heap (only used in list data)
  46. // heap format
  47. //
  48. // 4 byte offset to next block (in bytes)
  49. // 1 byte of type of variable or empty
  50. // 2 bytes of reference count
  51. // nn bytes of data
  52. const S32 MAX_HEAP_SIZE = TOP_OF_MEMORY;
  53. class LLScriptAllocEntry
  54. {
  55. public:
  56. LLScriptAllocEntry() : mSize(0), mType(LST_NULL), mReferenceCount(0) {}
  57. LLScriptAllocEntry(S32 offset, U8 type) : mSize(offset), mType(type), mReferenceCount(1) {}
  58. friend std::ostream& operator<<(std::ostream& s, const LLScriptAllocEntry &a)
  59. {
  60. s << "Size: " << a.mSize << " Type: " << LSCRIPTTypeNames[a.mType] << " Count: " << a.mReferenceCount;
  61. return s;
  62. }
  63. S32 mSize;
  64. U8 mType;
  65. S16 mReferenceCount;
  66. };
  67. // this is only OK because we only load/save via accessors below
  68. const S32 SIZEOF_SCRIPT_ALLOC_ENTRY = 7;
  69. inline void alloc_entry2bytestream(U8 *buffer, S32 &offset, const LLScriptAllocEntry &entry)
  70. {
  71. if ( (offset < 0)
  72. ||(offset > MAX_HEAP_SIZE))
  73. {
  74. set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
  75. }
  76. else
  77. {
  78. integer2bytestream(buffer, offset, entry.mSize);
  79. byte2bytestream(buffer, offset, entry.mType);
  80. s162bytestream(buffer, offset, entry.mReferenceCount);
  81. }
  82. }
  83. inline void bytestream2alloc_entry(LLScriptAllocEntry &entry, U8 *buffer, S32 &offset)
  84. {
  85. if ( (offset < 0)
  86. ||(offset > MAX_HEAP_SIZE))
  87. {
  88. set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
  89. reset_hp_to_safe_spot(buffer);
  90. }
  91. else
  92. {
  93. entry.mSize = bytestream2integer(buffer, offset);
  94. entry.mType = bytestream2byte(buffer, offset);
  95. entry.mReferenceCount = bytestream2s16(buffer, offset);
  96. }
  97. }
  98. // create a heap from the HR to TM
  99. BOOL lsa_create_heap(U8 *heap_start, S32 size);
  100. void lsa_fprint_heap(U8 *buffer, LLFILE *fp);
  101. void lsa_print_heap(U8 *buffer);
  102. // adding to heap
  103. // if block is empty
  104. // if block is at least block size + 4 larger than data
  105. // split block
  106. // insert data into first part
  107. // return address
  108. // else
  109. // insert data into block
  110. // return address
  111. // else
  112. // if next block is >= SP
  113. // set Stack-Heap collision
  114. // return NULL
  115. // if next block is empty
  116. // merge next block with current block
  117. // go to start of algorithm
  118. // else
  119. // move to next block
  120. // go to start of algorithm
  121. S32 lsa_heap_add_data(U8 *buffer, LLScriptLibData *data, S32 heapsize, BOOL b_delete);
  122. S32 lsa_heap_top(U8 *heap_start, S32 maxsize);
  123. // split block
  124. // set offset to point to new block
  125. // set offset of new block to point to original offset - block size - data size
  126. // set new block to empty
  127. // set new block reference count to 0
  128. void lsa_split_block(U8 *buffer, S32 &offset, S32 size, LLScriptAllocEntry &entry);
  129. // insert data
  130. // if data is non-list type
  131. // set type to basic type, set reference count to 1, copy data, return address
  132. // else
  133. // set type to list data type, set reference count to 1
  134. // for each list entry
  135. // insert data
  136. // return address
  137. void lsa_insert_data(U8 *buffer, S32 &offset, LLScriptLibData *data, LLScriptAllocEntry &entry, S32 heapsize);
  138. S32 lsa_create_data_block(U8 **buffer, LLScriptLibData *data, S32 base_offset);
  139. // increase reference count
  140. // increase reference count by 1
  141. void lsa_increase_ref_count(U8 *buffer, S32 offset);
  142. // decrease reference count
  143. // decrease reference count by 1
  144. // if reference count == 0
  145. // set type to empty
  146. void lsa_decrease_ref_count(U8 *buffer, S32 offset);
  147. inline S32 get_max_heap_size(U8 *buffer)
  148. {
  149. return get_register(buffer, LREG_SP) - get_register(buffer, LREG_HR);
  150. }
  151. LLScriptLibData *lsa_get_data(U8 *buffer, S32 &offset, BOOL b_dec_ref);
  152. LLScriptLibData *lsa_get_list_ptr(U8 *buffer, S32 &offset, BOOL b_dec_ref);
  153. S32 lsa_cat_strings(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize);
  154. S32 lsa_cmp_strings(U8 *buffer, S32 offset1, S32 offset2);
  155. S32 lsa_cat_lists(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize);
  156. S32 lsa_cmp_lists(U8 *buffer, S32 offset1, S32 offset2);
  157. S32 lsa_preadd_lists(U8 *buffer, LLScriptLibData *data, S32 offset2, S32 heapsize);
  158. S32 lsa_postadd_lists(U8 *buffer, S32 offset1, LLScriptLibData *data, S32 heapsize);
  159. // modifying a list
  160. // insert new list that is modified
  161. // store returned address in original list's variable
  162. // decrease reference count on old list
  163. // list l1 = [10];
  164. // list l2 = l1;
  165. // l1 = [11];
  166. // we want l2 == [10];
  167. // more complicated example:
  168. // list l1 = [10, 11];
  169. // list l2 = l1;
  170. // l1[0] = 12
  171. // I think that we want l2 = [10, 11];
  172. // one option would be to use syntax like:
  173. // l1 = llSetList(l1, 0, 12);
  174. // but this would require variable argument list matching
  175. // which maybe is ok, but would be work
  176. // the other option would be changes to lists that have multiple references causes a copy to occur
  177. // popl @l1, 0, integer, 12
  178. //
  179. // would cause l1 to be copied, 12 to replace the 0th entry, and the address of the new list to be saved in l1
  180. //
  181. inline LLScriptLibData *lsa_bubble_sort(LLScriptLibData *src, S32 stride, S32 ascending)
  182. {
  183. S32 number = src->getListLength();
  184. if (number <= 0)
  185. {
  186. return NULL;
  187. }
  188. if (stride <= 0)
  189. {
  190. stride = 1;
  191. }
  192. S32 i = 0;
  193. if (number % stride)
  194. {
  195. LLScriptLibData *retval = src->mListp;
  196. src->mListp = NULL;
  197. return retval;
  198. }
  199. LLScriptLibData **sortarray = new LLScriptLibData*[number];
  200. LLScriptLibData *temp = src->mListp;
  201. while (temp)
  202. {
  203. sortarray[i] = temp;
  204. i++;
  205. temp = temp->mListp;
  206. }
  207. S32 j, s;
  208. for (i = 0; i < number; i += stride)
  209. {
  210. for (j = i; j < number; j += stride)
  211. {
  212. if ( ((*sortarray[i]) <= (*sortarray[j]))
  213. != (ascending == TRUE))
  214. {
  215. for (s = 0; s < stride; s++)
  216. {
  217. temp = sortarray[i + s];
  218. sortarray[i + s] = sortarray[j + s];
  219. sortarray[j + s] = temp;
  220. }
  221. }
  222. }
  223. }
  224. i = 1;
  225. temp = sortarray[0];
  226. while (i < number)
  227. {
  228. temp->mListp = sortarray[i++];
  229. temp = temp->mListp;
  230. }
  231. temp->mListp = NULL;
  232. src->mListp = NULL;
  233. temp = sortarray[0];
  234. delete[] sortarray;
  235. return temp;
  236. }
  237. LLScriptLibData* lsa_randomize(LLScriptLibData* src, S32 stride);
  238. #endif