aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs299
1 files changed, 299 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs
new file mode 100644
index 0000000..33eb8bf
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs
@@ -0,0 +1,299 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Reflection.Emit;
31
32using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
33using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
34using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
35using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
36using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
37using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
38using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
39
40namespace OpenSim.Region.ScriptEngine.Yengine
41{
42 /**
43 * One instance of this class for lsl base objects that take a variable
44 * amount of memory. They are what the script-visible list,object,string
45 * variables are declared as at the CIL level. Generally, temp vars used
46 * by the compiler get their basic type (list,object,string).
47 *
48 * Note that the xmr arrays and script-defined objects have their own
49 * heap tracking built in so do not need any of this stuff.
50 */
51 public class HeapTrackerBase
52 {
53 protected int usage; // num bytes used by object
54 protected XMRInstAbstract instance; // what script it is in
55
56 public HeapTrackerBase(XMRInstAbstract inst)
57 {
58 if(inst == null)
59 throw new ArgumentNullException("inst");
60 instance = inst;
61 }
62
63 ~HeapTrackerBase()
64 {
65 usage = instance.UpdateHeapUse(usage, 0);
66 }
67 }
68
69 /**
70 * Wrapper around lists to keep track of how much memory they use.
71 */
72 public class HeapTrackerList: HeapTrackerBase
73 {
74 private static FieldInfo listValueField = typeof(HeapTrackerList).GetField("value");
75 private static MethodInfo listSaveMethod = typeof(HeapTrackerList).GetMethod("Save");
76
77 public LSL_List value;
78
79 public HeapTrackerList(XMRInstAbstract inst) : base(inst) { }
80
81 // generate CIL code to pop the value from the CIL stack
82 // input:
83 // 'this' pointer already pushed on CIL stack
84 // new value pushed on CIL stack
85 // output:
86 // 'this' pointer popped from stack
87 // new value popped from CIL stack
88 // heap usage updated
89 public static void GenPop(Token errorAt, ScriptMyILGen ilGen)
90 {
91 ilGen.Emit(errorAt, OpCodes.Call, listSaveMethod);
92 }
93
94 // generate CIL code to push the value on the CIL stack
95 // input:
96 // 'this' pointer already pushed on CIL stack
97 // output:
98 // 'this' pointer popped from stack
99 // value pushed on CIL stack replacing 'this' pointer
100 // returns typeof value pushed on stack
101 public static Type GenPush(Token errorAt, ScriptMyILGen ilGen)
102 {
103 ilGen.Emit(errorAt, OpCodes.Ldfld, listValueField);
104 return typeof(LSL_List);
105 }
106
107 public void Save(LSL_List lis)
108 {
109 int newuse = Size(lis);
110 usage = instance.UpdateHeapUse(usage, newuse);
111 value = lis;
112 }
113
114 //private static int counter = 5;
115 public static int Size(LSL_List lis)
116 {
117 // VS2017 in debug mode seems to have a problem running this statement quickly:
118 //SLOW: return (!typeof(LSL_List).IsValueType && (lis == null)) ? 0 : lis.Size;
119
120 //FAST: return 33;
121 //SLOW: return (lis == null) ? 0 : 99;
122 //FAST: return ++ counter;
123
124 // VS2017 in debug mode seems content to run this quickly though:
125
126 try
127 {
128 return lis.Size;
129 }
130 catch
131 {
132 return 0;
133 }
134 }
135 }
136
137 /**
138 * Wrapper around objects to keep track of how much memory they use.
139 */
140 public class HeapTrackerObject: HeapTrackerBase
141 {
142 private static FieldInfo objectValueField = typeof(HeapTrackerObject).GetField("value");
143 private static MethodInfo objectSaveMethod = typeof(HeapTrackerObject).GetMethod("Save");
144
145 public const int HT_CHAR = 2;
146 public const int HT_DELE = 8;
147 public const int HT_DOUB = 8;
148 public const int HT_SING = 4;
149 public const int HT_SFLT = 4;
150 public const int HT_INT = 4;
151 public const int HT_VEC = HT_DOUB * 3;
152 public const int HT_ROT = HT_DOUB * 4;
153
154 public object value;
155
156 public HeapTrackerObject(XMRInstAbstract inst) : base(inst) { }
157
158 // generate CIL code to pop the value from the CIL stack
159 // input:
160 // 'this' pointer already pushed on CIL stack
161 // new value pushed on CIL stack
162 // output:
163 // 'this' pointer popped from stack
164 // new value popped from CIL stack
165 // heap usage updated
166 public static void GenPop(Token errorAt, ScriptMyILGen ilGen)
167 {
168 ilGen.Emit(errorAt, OpCodes.Call, objectSaveMethod);
169 }
170
171 // generate CIL code to push the value on the CIL stack
172 // input:
173 // 'this' pointer already pushed on CIL stack
174 // output:
175 // 'this' pointer popped from stack
176 // value pushed on CIL stack replacing 'this' pointer
177 // returns typeof value pushed on stack
178 public static Type GenPush(Token errorAt, ScriptMyILGen ilGen)
179 {
180 ilGen.Emit(errorAt, OpCodes.Ldfld, objectValueField);
181 return typeof(object);
182 }
183
184 public void Save(object obj)
185 {
186 int newuse = Size(obj);
187 usage = instance.UpdateHeapUse(usage, newuse);
188 value = obj;
189 }
190
191 // public so it can be used by XMRArray
192 public static int Size(object obj)
193 {
194 if(obj == null)
195 return 0;
196
197 if(obj is char)
198 return HT_CHAR;
199 if(obj is Delegate)
200 return HT_DELE;
201 if(obj is double)
202 return HT_DOUB;
203 if(obj is float)
204 return HT_SING;
205 if(obj is int)
206 return HT_INT;
207 if(obj is LSL_Float)
208 return HT_SFLT;
209 if(obj is LSL_Integer)
210 return HT_INT;
211 if(obj is LSL_List)
212 return ((LSL_List)obj).Size;
213 if(obj is LSL_Rotation)
214 return HT_ROT;
215 if(obj is LSL_String)
216 return ((LSL_String)obj).m_string.Length * HT_CHAR;
217 if(obj is LSL_Vector)
218 return HT_VEC;
219 if(obj is string)
220 return ((string)obj).Length * HT_CHAR;
221 if(obj is XMR_Array)
222 return 0;
223 if(obj is XMRArrayListKey)
224 return ((XMRArrayListKey)obj).Size;
225 if(obj is XMRSDTypeClObj)
226 return 0;
227
228 if(obj is Array)
229 {
230 Array ar = (Array)obj;
231 int len = ar.Length;
232 if(len == 0)
233 return 0;
234 Type et = ar.GetType().GetElementType();
235 if(et.IsValueType)
236 return Size(ar.GetValue(0)) * len;
237 int size = 0;
238 for(int i = 0; i < len; i++)
239 {
240 size += Size(ar.GetValue(i));
241 }
242 return size;
243 }
244
245 throw new Exception("unknown size of type " + obj.GetType().Name);
246 }
247 }
248
249 /**
250 * Wrapper around strings to keep track of how much memory they use.
251 */
252 public class HeapTrackerString: HeapTrackerBase
253 {
254 private static FieldInfo stringValueField = typeof(HeapTrackerString).GetField("value");
255 private static MethodInfo stringSaveMethod = typeof(HeapTrackerString).GetMethod("Save");
256
257 public string value;
258
259 public HeapTrackerString(XMRInstAbstract inst) : base(inst) { }
260
261 // generate CIL code to pop the value from the CIL stack
262 // input:
263 // 'this' pointer already pushed on CIL stack
264 // new value pushed on CIL stack
265 // output:
266 // 'this' pointer popped from stack
267 // new value popped from CIL stack
268 // heap usage updated
269 public static void GenPop(Token errorAt, ScriptMyILGen ilGen)
270 {
271 ilGen.Emit(errorAt, OpCodes.Call, stringSaveMethod);
272 }
273
274 // generate CIL code to push the value on the CIL stack
275 // input:
276 // 'this' pointer already pushed on CIL stack
277 // output:
278 // 'this' pointer popped from stack
279 // value pushed on CIL stack replacing 'this' pointer
280 // returns typeof value pushed on stack
281 public static Type GenPush(Token errorAt, ScriptMyILGen ilGen)
282 {
283 ilGen.Emit(errorAt, OpCodes.Ldfld, stringValueField);
284 return typeof(string);
285 }
286
287 public void Save(string str)
288 {
289 int newuse = Size(str);
290 usage = instance.UpdateHeapUse(usage, newuse);
291 value = str;
292 }
293
294 public static int Size(string str)
295 {
296 return (str == null) ? 0 : str.Length * HeapTrackerObject.HT_CHAR;
297 }
298 }
299}