PageRenderTime 25ms CodeModel.GetById 10ms app.highlight 12ms RepoModel.GetById 1ms 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
  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
 27#ifndef LL_LSCRIPT_ALLOC_H
 28#define LL_LSCRIPT_ALLOC_H
 29// #define at top of file accelerates gcc compiles
 30// Under gcc 2.9, the manual is unclear if comments can appear above #ifndef
 31// Under gcc 3, the manual explicitly states comments can appear above the #ifndef
 32
 33#include "lscript_byteconvert.h"
 34#include "lscript_library.h"
 35
 36void reset_hp_to_safe_spot(const U8 *buffer);
 37
 38
 39// supported data types
 40
 41//	basic types
 42//	integer			4 bytes of integer data
 43//	float			4 bytes of float data
 44//	string data		null terminated 1 byte string
 45//	key data		null terminated 1 byte string
 46//	vector data		12 bytes of 3 floats
 47//	quaternion data	16 bytes of 4 floats
 48
 49//	list type
 50//	list data		4 bytes of number of entries followed by followed by pointer
 51
 52//	string pointer		4 bytes of address of string data on the heap (only used in list data)
 53//  key pointer			4 bytes of address of key data on the heap (only used in list data)
 54
 55// heap format
 56// 
 57// 4 byte offset to next block (in bytes)
 58// 1 byte of type of variable or empty
 59// 2 bytes of reference count
 60// nn bytes of data
 61
 62const S32 MAX_HEAP_SIZE = TOP_OF_MEMORY;
 63
 64class LLScriptAllocEntry
 65{
 66public:
 67	LLScriptAllocEntry() : mSize(0), mType(LST_NULL), mReferenceCount(0) {}
 68	LLScriptAllocEntry(S32 offset, U8 type) : mSize(offset), mType(type), mReferenceCount(1) {}
 69	friend std::ostream&	 operator<<(std::ostream& s, const LLScriptAllocEntry &a)
 70	{
 71		s << "Size: " << a.mSize << " Type: " << LSCRIPTTypeNames[a.mType] << " Count: " << a.mReferenceCount;
 72		return s;
 73	}
 74
 75	S32 mSize;
 76	U8	mType;
 77	S16 mReferenceCount;
 78};
 79
 80// this is only OK because we only load/save via accessors below
 81const S32 SIZEOF_SCRIPT_ALLOC_ENTRY = 7;
 82
 83inline void alloc_entry2bytestream(U8 *buffer, S32 &offset, const LLScriptAllocEntry &entry)
 84{
 85	if (  (offset < 0)
 86		||(offset > MAX_HEAP_SIZE))
 87	{
 88		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
 89	}
 90	else
 91	{
 92		integer2bytestream(buffer, offset, entry.mSize);
 93		byte2bytestream(buffer, offset, entry.mType);
 94		s162bytestream(buffer, offset, entry.mReferenceCount);
 95	}
 96}
 97
 98inline void bytestream2alloc_entry(LLScriptAllocEntry &entry, U8 *buffer, S32 &offset)
 99{
100	if (  (offset < 0)
101		||(offset > MAX_HEAP_SIZE))
102	{
103		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
104		reset_hp_to_safe_spot(buffer);
105	}
106	else
107	{
108		entry.mSize = bytestream2integer(buffer, offset);
109		entry.mType = bytestream2byte(buffer, offset);
110		entry.mReferenceCount = bytestream2s16(buffer, offset);
111	}
112}
113
114// create a heap from the HR to TM
115BOOL lsa_create_heap(U8 *heap_start, S32 size);
116void lsa_fprint_heap(U8 *buffer, LLFILE *fp);
117
118void lsa_print_heap(U8 *buffer);
119
120// adding to heap
121//	if block is empty
122//		if block is at least block size + 4 larger than data
123//			split block
124//			insert data into first part
125//			return address
126//		else
127//			insert data into block
128//			return address
129//	else
130//		if next block is >= SP 
131//			set Stack-Heap collision
132//			return NULL
133//		if next block is empty
134//			merge next block with current block
135//			go to start of algorithm
136//		else
137//			move to next block
138//			go to start of algorithm
139
140S32 lsa_heap_add_data(U8 *buffer, LLScriptLibData *data, S32 heapsize, BOOL b_delete);
141
142S32 lsa_heap_top(U8 *heap_start, S32 maxsize);
143
144// split block
145//	set offset to point to new block
146//	set offset of new block to point to original offset - block size - data size
147//	set new block to empty
148//	set new block reference count to 0
149void lsa_split_block(U8 *buffer, S32 &offset, S32 size, LLScriptAllocEntry &entry);
150
151// insert data
152//	if data is non-list type
153//		set type to basic type, set reference count to 1, copy data, return address
154//	else
155//		set type to list data type, set reference count to 1
156//		for each list entry
157//			insert data
158//			return address
159
160void lsa_insert_data(U8 *buffer, S32 &offset, LLScriptLibData *data, LLScriptAllocEntry &entry, S32 heapsize);
161
162S32 lsa_create_data_block(U8 **buffer, LLScriptLibData *data, S32 base_offset);
163
164// increase reference count
165//		increase reference count by 1
166
167void lsa_increase_ref_count(U8 *buffer, S32 offset);
168
169// decrease reference count
170//		decrease reference count by 1
171//		if reference count == 0
172//			set type to empty
173
174void lsa_decrease_ref_count(U8 *buffer, S32 offset);
175
176inline S32 get_max_heap_size(U8 *buffer)
177{
178	return get_register(buffer, LREG_SP) - get_register(buffer, LREG_HR);
179}
180
181
182LLScriptLibData *lsa_get_data(U8 *buffer, S32 &offset, BOOL b_dec_ref);
183LLScriptLibData *lsa_get_list_ptr(U8 *buffer, S32 &offset, BOOL b_dec_ref);
184
185S32 lsa_cat_strings(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize);
186S32 lsa_cmp_strings(U8 *buffer, S32 offset1, S32 offset2);
187
188S32 lsa_cat_lists(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize);
189S32 lsa_cmp_lists(U8 *buffer, S32 offset1, S32 offset2);
190S32 lsa_preadd_lists(U8 *buffer, LLScriptLibData *data, S32 offset2, S32 heapsize);
191S32 lsa_postadd_lists(U8 *buffer, S32 offset1, LLScriptLibData *data, S32 heapsize);
192
193// modifying a list
194//	insert new list that is modified
195//	store returned address in original list's variable
196//	decrease reference count on old list
197
198//	list l1 = [10];
199//	list l2 = l1;
200//	l1 = [11];
201
202//	we want l2 == [10];
203
204// more complicated example:
205//	list l1 = [10, 11];
206//	list l2 = l1;
207//	l1[0] = 12
208
209// I think that we want l2 = [10, 11];
210
211// one option would be to use syntax like:
212//	l1 = llSetList(l1, 0, 12);
213// but this would require variable argument list matching
214// which maybe is ok, but would be work
215// the other option would be changes to lists that have multiple references causes a copy to occur
216
217// popl @l1, 0, integer, 12
218//
219// would cause l1 to be copied, 12 to replace the 0th entry, and the address of the new list to be saved in l1
220//
221
222inline LLScriptLibData *lsa_bubble_sort(LLScriptLibData *src, S32 stride, S32 ascending)
223{
224	S32 number = src->getListLength();
225
226	if (number <= 0)
227	{
228		return NULL;
229	}
230
231	if (stride <= 0)
232	{
233		stride = 1;
234	}
235
236	S32 i = 0;
237
238	if (number % stride)
239	{
240		LLScriptLibData *retval = src->mListp;
241		src->mListp = NULL;
242		return retval;
243	}
244
245	LLScriptLibData **sortarray = new LLScriptLibData*[number];
246
247	LLScriptLibData *temp = src->mListp;
248	while (temp)
249	{
250		sortarray[i] = temp;
251		i++;
252		temp = temp->mListp;
253	}
254
255	S32 j, s;
256
257	for (i = 0; i < number; i += stride)
258	{
259		for (j = i; j < number; j += stride)
260		{
261			if (  ((*sortarray[i]) <= (*sortarray[j]))
262				!= (ascending == TRUE))
263			{
264				for (s = 0; s < stride; s++)
265				{
266					temp = sortarray[i + s];
267					sortarray[i + s] = sortarray[j + s];
268					sortarray[j + s] = temp;
269				}
270			}
271		}
272	}
273
274	i = 1;
275	temp = sortarray[0];
276	while (i < number)
277	{
278		temp->mListp = sortarray[i++];
279		temp = temp->mListp;
280	}
281	temp->mListp = NULL;
282
283	src->mListp = NULL;
284
285	temp = sortarray[0];
286	delete[] sortarray;
287	return temp;
288}
289
290
291LLScriptLibData* lsa_randomize(LLScriptLibData* src, S32 stride);
292
293#endif