mantis 8551: Simplify Yengine heap usage control

0.9.1.1
UbitUmarov 2019-11-18 17:33:02 +00:00
parent 496a2228f5
commit bf0697d5f4
5 changed files with 66 additions and 108 deletions

View File

@ -66,7 +66,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
{ {
public static readonly string OBJECT_CODE_MAGIC = "YObjectCode"; public static readonly string OBJECT_CODE_MAGIC = "YObjectCode";
// reserve positive version values for original xmr // reserve positive version values for original xmr
public static int COMPILED_VERSION_VALUE = -2; // decremented when compiler or object file changes public static int COMPILED_VERSION_VALUE = -3; // decremented when compiler or object file changes
public static readonly int CALL_FRAME_MEMUSE = 64; public static readonly int CALL_FRAME_MEMUSE = 64;
public static readonly int STRING_LEN_TO_MEMUSE = 2; public static readonly int STRING_LEN_TO_MEMUSE = 2;
@ -110,6 +110,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
private static FieldInfo rotationSFieldInfo = typeof(LSL_Rotation).GetField("s"); private static FieldInfo rotationSFieldInfo = typeof(LSL_Rotation).GetField("s");
private static FieldInfo sdtXMRInstFieldInfo = typeof(XMRSDTypeClObj).GetField("xmrInst"); private static FieldInfo sdtXMRInstFieldInfo = typeof(XMRSDTypeClObj).GetField("xmrInst");
private static FieldInfo stackLeftFieldInfo = typeof(XMRInstAbstract).GetField("m_StackLeft"); private static FieldInfo stackLeftFieldInfo = typeof(XMRInstAbstract).GetField("m_StackLeft");
private static FieldInfo heapUsedFieldInfo = typeof(XMRInstAbstract).GetField("m_heapUsed");
private static FieldInfo vectorXFieldInfo = typeof(LSL_Vector).GetField("x"); private static FieldInfo vectorXFieldInfo = typeof(LSL_Vector).GetField("x");
private static FieldInfo vectorYFieldInfo = typeof(LSL_Vector).GetField("y"); private static FieldInfo vectorYFieldInfo = typeof(LSL_Vector).GetField("y");
private static FieldInfo vectorZFieldInfo = typeof(LSL_Vector).GetField("z"); private static FieldInfo vectorZFieldInfo = typeof(LSL_Vector).GetField("z");
@ -133,19 +134,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
private static MethodInfo stringConcat2MethodInfo = GetStaticMethod(typeof(String), "Concat", new Type[] { typeof(string), typeof(string) }); private static MethodInfo stringConcat2MethodInfo = GetStaticMethod(typeof(String), "Concat", new Type[] { typeof(string), typeof(string) });
private static MethodInfo stringConcat3MethodInfo = GetStaticMethod(typeof(String), "Concat", new Type[] { typeof(string), typeof(string), typeof(string) }); private static MethodInfo stringConcat3MethodInfo = GetStaticMethod(typeof(String), "Concat", new Type[] { typeof(string), typeof(string), typeof(string) });
private static MethodInfo stringConcat4MethodInfo = GetStaticMethod(typeof(String), "Concat", new Type[] { typeof(string), typeof(string), typeof(string), typeof(string) }); private static MethodInfo stringConcat4MethodInfo = GetStaticMethod(typeof(String), "Concat", new Type[] { typeof(string), typeof(string), typeof(string), typeof(string) });
private static MethodInfo lslRotationNegateMethodInfo = GetStaticMethod(typeof(ScriptCodeGen), private static MethodInfo lslRotationNegateMethodInfo = GetStaticMethod(typeof(ScriptCodeGen), "LSLRotationNegate", new Type[] { typeof(LSL_Rotation) });
"LSLRotationNegate", private static MethodInfo lslVectorNegateMethodInfo = GetStaticMethod(typeof(ScriptCodeGen), "LSLVectorNegate", new Type[] { typeof(LSL_Vector) });
new Type[] { typeof(LSL_Rotation) });
private static MethodInfo lslVectorNegateMethodInfo = GetStaticMethod(typeof(ScriptCodeGen),
"LSLVectorNegate",
new Type[] { typeof(LSL_Vector) });
private static MethodInfo scriptRestoreCatchExceptionUnwrap = GetStaticMethod(typeof(ScriptRestoreCatchException), "Unwrap", new Type[] { typeof(Exception) }); private static MethodInfo scriptRestoreCatchExceptionUnwrap = GetStaticMethod(typeof(ScriptRestoreCatchException), "Unwrap", new Type[] { typeof(Exception) });
private static MethodInfo thrownExceptionWrapMethodInfo = GetStaticMethod(typeof(ScriptThrownException), "Wrap", new Type[] { typeof(object) }); private static MethodInfo thrownExceptionWrapMethodInfo = GetStaticMethod(typeof(ScriptThrownException), "Wrap", new Type[] { typeof(object) });
private static MethodInfo catchExcToStrMethodInfo = GetStaticMethod(typeof(ScriptCodeGen), "CatchExcToStr", new Type[] { typeof(Exception) });
private static MethodInfo catchExcToStrMethodInfo = GetStaticMethod(typeof(ScriptCodeGen),
"CatchExcToStr",
new Type[] { typeof(Exception) });
private static MethodInfo consoleWriteMethodInfo = GetStaticMethod(typeof(ScriptCodeGen), "ConsoleWrite", new Type[] { typeof(object) }); private static MethodInfo consoleWriteMethodInfo = GetStaticMethod(typeof(ScriptCodeGen), "ConsoleWrite", new Type[] { typeof(object) });
public static void ConsoleWrite(object o) public static void ConsoleWrite(object o)
{ {
@ -186,6 +179,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
// These get cleared at beginning of every function definition // These get cleared at beginning of every function definition
private ScriptMyLocal instancePointer; // holds XMRInstanceSuperType pointer private ScriptMyLocal instancePointer; // holds XMRInstanceSuperType pointer
private ScriptMyLocal curHeapSize;
private ScriptMyLabel retLabel = null; // where to jump to exit function private ScriptMyLabel retLabel = null; // where to jump to exit function
private ScriptMyLocal retValue = null; private ScriptMyLocal retValue = null;
private ScriptMyLocal actCallNo = null; // for the active try/catch/finally stack or the big one outside them all private ScriptMyLocal actCallNo = null; // for the active try/catch/finally stack or the big one outside them all
@ -194,7 +188,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
public CallLabel openCallLabel = null; // only one call label can be open at a time public CallLabel openCallLabel = null; // only one call label can be open at a time
// - the call label is open from the time of CallPre() until corresponding CallPost() // - the call label is open from the time of CallPre() until corresponding CallPost()
// - so no non-trivial pushes/pops etc allowed between a CallPre() and a CallPost() // - so no non-trivial pushes/pops etc allowed between a CallPre() and a CallPost()
public List<ScriptMyLocal> HeapLocals = new List<ScriptMyLocal>();
private ScriptMyILGen _ilGen; private ScriptMyILGen _ilGen;
public ScriptMyILGen ilGen public ScriptMyILGen ilGen
{ {
@ -969,9 +962,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
string eventname = declFunc.GetSimpleName(); string eventname = declFunc.GetSimpleName();
TokenArgDecl argDecl = declFunc.argDecl; TokenArgDecl argDecl = declFunc.argDecl;
HeapLocals.Clear(); // Make sure event handler name is valid and that number and type of arguments is correct.
// Make sure event handler name is valid and that number and type of arguments is correct.
// Apparently some scripts exist with fewer than correct number of args in their declaration // Apparently some scripts exist with fewer than correct number of args in their declaration
// so allow for that. It is ok because the handlers are called with the arguments in an // so allow for that. It is ok because the handlers are called with the arguments in an
// object[] array, and we just won't access the missing argments in the vector. But the // object[] array, and we just won't access the missing argments in the vector. But the
@ -1000,8 +991,16 @@ namespace OpenSim.Region.ScriptEngine.Yengine
ilGen.Emit(declFunc, OpCodes.Castclass, xmrInstSuperType); ilGen.Emit(declFunc, OpCodes.Castclass, xmrInstSuperType);
ilGen.Emit(declFunc, OpCodes.Stloc, instancePointer); ilGen.Emit(declFunc, OpCodes.Stloc, instancePointer);
// Output args as variable definitions and initialize each from __sw.ehArgs[]. if (curDeclFunc.fullName != "$globalvarinit()")
// If the script writer goofed, the typecast will complain. {
PushXMRInst();
ilGen.Emit(curDeclFunc, OpCodes.Ldfld, heapUsedFieldInfo);
curHeapSize = ilGen.DeclareLocal(typeof(int), "__curHeap");
ilGen.Emit(curDeclFunc, OpCodes.Stloc, curHeapSize);
}
// Output args as variable definitions and initialize each from __sw.ehArgs[].
// If the script writer goofed, the typecast will complain.
int nArgs = argDecl.vars.Length; int nArgs = argDecl.vars.Length;
for(int i = 0; i < nArgs; i++) for(int i = 0; i < nArgs; i++)
{ {
@ -1112,19 +1111,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine
*/ */
private void GenerateMethodBody(TokenDeclVar declFunc) private void GenerateMethodBody(TokenDeclVar declFunc)
{ {
HeapLocals.Clear();
// Set up code generator for the function's contents. // Set up code generator for the function's contents.
_ilGen = declFunc.ilGen; _ilGen = declFunc.ilGen;
StartFunctionBody(declFunc); StartFunctionBody(declFunc);
// Create a temp to hold XMRInstanceSuperType version of arg 0. // Create a temp to hold XMRInstanceSuperType version of arg 0.
// For most functions, arg 0 is already XMRInstanceSuperType. // For most functions, arg 0 is already XMRInstanceSuperType.
// But for script-defined class instance methods, arg 0 holds // But for script-defined class instance methods, arg 0 holds
// the XMRSDTypeClObj pointer and so we read the XMRInstAbstract // the XMRSDTypeClObj pointer and so we read the XMRInstAbstract
// pointer from its XMRSDTypeClObj.xmrInst field then cast it to // pointer from its XMRSDTypeClObj.xmrInst field then cast it to
// XMRInstanceSuperType. // XMRInstanceSuperType.
if(IsSDTInstMethod()) if (IsSDTInstMethod())
{ {
instancePointer = ilGen.DeclareLocal(xmrInstSuperType, "__xmrinst"); instancePointer = ilGen.DeclareLocal(xmrInstSuperType, "__xmrinst");
ilGen.Emit(declFunc, OpCodes.Ldarg_0); ilGen.Emit(declFunc, OpCodes.Ldarg_0);
@ -1133,9 +1130,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine
ilGen.Emit(declFunc, OpCodes.Stloc, instancePointer); ilGen.Emit(declFunc, OpCodes.Stloc, instancePointer);
} }
// Define location of all script-level arguments so script body can access them. if (curDeclFunc.fullName != "$globalvarinit()")
// The argument indices need to have +1 added to them because XMRInstance or {
// XMRSDTypeClObj is spliced in at arg 0. PushXMRInst();
ilGen.Emit(curDeclFunc, OpCodes.Ldfld, heapUsedFieldInfo);
curHeapSize = ilGen.DeclareLocal(typeof(int), "__curHeap");
ilGen.Emit(curDeclFunc, OpCodes.Stloc, curHeapSize);
}
// Define location of all script-level arguments so script body can access them.
// The argument indices need to have +1 added to them because XMRInstance or
// XMRSDTypeClObj is spliced in at arg 0.
TokenArgDecl argDecl = declFunc.argDecl; TokenArgDecl argDecl = declFunc.argDecl;
int nArgs = argDecl.vars.Length; int nArgs = argDecl.vars.Length;
for(int i = 0; i < nArgs; i++) for(int i = 0; i < nArgs; i++)
@ -1251,7 +1256,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
// an infinite loop. If it is, we don't need any CheckRun() // an infinite loop. If it is, we don't need any CheckRun()
// stuff or any of the frame save/restore stuff. // stuff or any of the frame save/restore stuff.
bool isTrivial = curDeclFunc.IsFuncTrivial(this); bool isTrivial = curDeclFunc.IsFuncTrivial(this);
bool doheap = curDeclFunc.fullName != "$globalvarinit()";
// Clear list of all call labels. // Clear list of all call labels.
// A call label is inserted just before every call that can possibly // A call label is inserted just before every call that can possibly
// call CheckRun(), including any direct calls to CheckRun(). // call CheckRun(), including any direct calls to CheckRun().
@ -1286,7 +1291,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
// if (instance.callMode != CallMode_NORMAL) goto __cmRestore; // if (instance.callMode != CallMode_NORMAL) goto __cmRestore;
actCallNo = null; actCallNo = null;
ScriptMyLabel cmRestore = null; ScriptMyLabel cmRestore = null;
if(!isTrivial)
if (!isTrivial)
{ {
actCallNo = ilGen.DeclareLocal(typeof(int), "__mainCallNo"); actCallNo = ilGen.DeclareLocal(typeof(int), "__mainCallNo");
SetCallNo(curDeclFunc, actCallNo, -1); SetCallNo(curDeclFunc, actCallNo, -1);
@ -1378,10 +1384,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine
// Output code body. // Output code body.
GenerateStmtBlock(curDeclFunc.body); GenerateStmtBlock(curDeclFunc.body);
// If code falls through to this point, means they are missing if (doheap)
// a return statement. And that is legal only if the function {
// returns 'void'. PushXMRInst();
if(mightGetHere) ilGen.Emit(curDeclFunc, OpCodes.Ldloc, curHeapSize);
ilGen.Emit(curDeclFunc, OpCodes.Stfld, heapUsedFieldInfo);
}
// If code falls through to this point, means they are missing
// a return statement. And that is legal only if the function
// returns 'void'.
if (mightGetHere)
{ {
if(!(curDeclFunc.retType is TokenTypeVoid)) if(!(curDeclFunc.retType is TokenTypeVoid))
{ {
@ -1414,6 +1427,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
} }
} }
} }
if(doheap)
activeTemps.Add(curHeapSize);
// Output code to restore the args, locals and temps then jump to // Output code to restore the args, locals and temps then jump to
// the call label that we were interrupted at. // the call label that we were interrupted at.
@ -1450,35 +1465,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine
ilGen.EndExceptionBlock(); ilGen.EndExceptionBlock();
} }
// Output the 'real' return opcode. // Output the 'real' return opcode.
// push return value // push return value
ilGen.MarkLabel(retLabel); ilGen.MarkLabel(retLabel);
if (!(curDeclFunc.retType is TokenTypeVoid)) if (!(curDeclFunc.retType is TokenTypeVoid))
{ {
ilGen.Emit(curDeclFunc, OpCodes.Ldloc, retValue); ilGen.Emit(curDeclFunc, OpCodes.Ldloc, retValue);
} }
// pseudo free memory usage
foreach (ScriptMyLocal sml in HeapLocals)
{
Type t = sml.type;
if (t == typeof(HeapTrackerList))
{
ilGen.Emit(curDeclFunc, OpCodes.Ldloc, sml);
HeapTrackerList.GenFree(curDeclFunc, ilGen);
}
else if (t == typeof(HeapTrackerString))
{
ilGen.Emit(curDeclFunc, OpCodes.Ldloc, sml);
HeapTrackerString.GenFree(curDeclFunc, ilGen);
}
else if (t == typeof(HeapTrackerObject))
{
ilGen.Emit(curDeclFunc, OpCodes.Ldloc, sml);
HeapTrackerObject.GenFree(curDeclFunc, ilGen);
}
}
ilGen.Emit(curDeclFunc, OpCodes.Ret); ilGen.Emit(curDeclFunc, OpCodes.Ret);
retLabel = null; retLabel = null;
retValue = null; retValue = null;

View File

@ -1484,7 +1484,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
if(type.ToHeapTrackerType() != null) if(type.ToHeapTrackerType() != null)
{ {
localBuilder = scg.ilGen.DeclareLocal(type.ToHeapTrackerType(), name); localBuilder = scg.ilGen.DeclareLocal(type.ToHeapTrackerType(), name);
scg.HeapLocals.Add(localBuilder);
scg.PushXMRInst(); scg.PushXMRInst();
scg.ilGen.Emit(type, OpCodes.Newobj, type.GetHeapTrackerCtor()); scg.ilGen.Emit(type, OpCodes.Newobj, type.GetHeapTrackerCtor());
scg.ilGen.Emit(type, OpCodes.Stloc, localBuilder); scg.ilGen.Emit(type, OpCodes.Stloc, localBuilder);
@ -1548,11 +1547,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
scg.ilGen.Emit(errorAt, OpCodes.Ldloc, localBuilder); scg.ilGen.Emit(errorAt, OpCodes.Ldloc, localBuilder);
scg.ilGen.Emit(errorAt, OpCodes.Ldloc, htpop); scg.ilGen.Emit(errorAt, OpCodes.Ldloc, htpop);
type.CallHeapTrackerPopMeth(errorAt, scg.ilGen); type.CallHeapTrackerPopMeth(errorAt, scg.ilGen);
scg.HeapLocals.Add(htpop); }
}
else else
{ {
/* /*
* Not a heap-tracked local var, just pop directly into it. * Not a heap-tracked local var, just pop directly into it.
*/ */

View File

@ -70,7 +70,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
private static FieldInfo listValueField = typeof(HeapTrackerList).GetField("value"); private static FieldInfo listValueField = typeof(HeapTrackerList).GetField("value");
private static MethodInfo listSaveMethod = typeof(HeapTrackerList).GetMethod("Save"); private static MethodInfo listSaveMethod = typeof(HeapTrackerList).GetMethod("Save");
private static MethodInfo listRestoreMethod = typeof(HeapTrackerList).GetMethod("Restore"); private static MethodInfo listRestoreMethod = typeof(HeapTrackerList).GetMethod("Restore");
private static MethodInfo listFreeMethod = typeof(HeapTrackerList).GetMethod("Free");
public LSL_List value; public LSL_List value;
@ -91,11 +90,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
ilGen.Emit(errorAt, OpCodes.Call, listRestoreMethod); ilGen.Emit(errorAt, OpCodes.Call, listRestoreMethod);
} }
public static void GenFree(Token errorAt, ScriptMyILGen ilGen)
{
ilGen.Emit(errorAt, OpCodes.Call, listFreeMethod);
}
// generate CIL code to push the value on the CIL stack // generate CIL code to push the value on the CIL stack
// input: // input:
// 'this' pointer already pushed on CIL stack // 'this' pointer already pushed on CIL stack
@ -127,13 +121,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
usage = 0; usage = 0;
} }
public void Free()
{
usage = instance.UpdateHeapUse(usage, 0);
value = null;
instance = null;
}
//private static int counter = 5; //private static int counter = 5;
public static int Size(LSL_List lis) public static int Size(LSL_List lis)
{ {
@ -156,7 +143,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
private static FieldInfo objectValueField = typeof(HeapTrackerObject).GetField("value"); private static FieldInfo objectValueField = typeof(HeapTrackerObject).GetField("value");
private static MethodInfo objectSaveMethod = typeof(HeapTrackerObject).GetMethod("Save"); private static MethodInfo objectSaveMethod = typeof(HeapTrackerObject).GetMethod("Save");
private static MethodInfo objectRestoreMethod = typeof(HeapTrackerObject).GetMethod("Restore"); private static MethodInfo objectRestoreMethod = typeof(HeapTrackerObject).GetMethod("Restore");
private static MethodInfo objectFreeMethod = typeof(HeapTrackerObject).GetMethod("Free");
public const int HT_CHAR = 2; public const int HT_CHAR = 2;
public const int HT_DELE = 8; public const int HT_DELE = 8;
@ -189,11 +175,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
ilGen.Emit(errorAt, OpCodes.Call, objectRestoreMethod); ilGen.Emit(errorAt, OpCodes.Call, objectRestoreMethod);
} }
public static void GenFree(Token errorAt, ScriptMyILGen ilGen)
{
ilGen.Emit(errorAt, OpCodes.Call, objectFreeMethod);
}
// generate CIL code to push the value on the CIL stack // generate CIL code to push the value on the CIL stack
// input: // input:
// 'this' pointer already pushed on CIL stack // 'this' pointer already pushed on CIL stack
@ -220,13 +201,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
usage = Size(obj); usage = Size(obj);
} }
public void Free()
{
usage = instance.UpdateHeapUse(usage, 0);
value = null;
instance = null;
}
// public so it can be used by XMRArray // public so it can be used by XMRArray
public static int Size(object obj) public static int Size(object obj)
{ {
@ -293,7 +267,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
private static FieldInfo stringValueField = typeof(HeapTrackerString).GetField("value"); private static FieldInfo stringValueField = typeof(HeapTrackerString).GetField("value");
private static MethodInfo stringRestoreMethod = typeof(HeapTrackerString).GetMethod("Restore"); private static MethodInfo stringRestoreMethod = typeof(HeapTrackerString).GetMethod("Restore");
private static MethodInfo stringSaveMethod = typeof(HeapTrackerString).GetMethod("Save"); private static MethodInfo stringSaveMethod = typeof(HeapTrackerString).GetMethod("Save");
private static MethodInfo stringFreeMethod = typeof(HeapTrackerString).GetMethod("Free");
public string value; public string value;
@ -317,11 +290,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
ilGen.Emit(errorAt, OpCodes.Call, stringRestoreMethod); ilGen.Emit(errorAt, OpCodes.Call, stringRestoreMethod);
} }
public static void GenFree(Token errorAt, ScriptMyILGen ilGen)
{
ilGen.Emit(errorAt, OpCodes.Call, stringFreeMethod);
}
// generate CIL code to push the value on the CIL stack // generate CIL code to push the value on the CIL stack
// input: // input:
// 'this' pointer already pushed on CIL stack // 'this' pointer already pushed on CIL stack
@ -348,13 +316,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
usage = Size(str); usage = Size(str);
} }
public void Free()
{
usage = instance.UpdateHeapUse(usage, 0);
value = null;
instance = null;
}
public static int Size(string str) public static int Size(string str)
{ {
return (str == null) ? 0 : str.Length * HeapTrackerObject.HT_CHAR; return (str == null) ? 0 : str.Length * HeapTrackerObject.HT_CHAR;

View File

@ -453,11 +453,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
\**************************************************/ \**************************************************/
protected int heapLimit; protected int heapLimit;
protected int heapUsed; public int m_heapUsed;
public virtual int UpdateHeapUse(int olduse, int newuse) public virtual int UpdateHeapUse(int olduse, int newuse)
{ {
int newtotal = Interlocked.Add(ref heapUsed, newuse - olduse); if (m_heapUsed < 0)
m_heapUsed = 0;
int newtotal = Interlocked.Add(ref m_heapUsed, newuse - olduse);
if(newtotal > heapLimit) if(newtotal > heapLimit)
throw new OutOfHeapException(newtotal + olduse - newuse, newtotal, heapLimit); throw new OutOfHeapException(newtotal + olduse - newuse, newtotal, heapLimit);
return newuse; return newuse;
@ -465,17 +467,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine
public virtual void AddHeapUse(int delta) public virtual void AddHeapUse(int delta)
{ {
Interlocked.Add(ref heapUsed, delta); Interlocked.Add(ref m_heapUsed, delta);
} }
public int xmrHeapLeft() public int xmrHeapLeft()
{ {
return heapLimit - heapUsed; if (m_heapUsed < 0)
m_heapUsed = 0;
return heapLimit - m_heapUsed;
} }
public int xmrHeapUsed() public int xmrHeapUsed()
{ {
return heapUsed; if(m_heapUsed < 0)
m_heapUsed = 0;
return m_heapUsed;
} }
/** /**

View File

@ -888,7 +888,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
m_SleepUntil = DateTime.MinValue; // not doing llSleep() m_SleepUntil = DateTime.MinValue; // not doing llSleep()
m_ResetCount++; // has been reset once more m_ResetCount++; // has been reset once more
heapUsed = 0; m_heapUsed = 0;
glblVars.Clear(); glblVars.Clear();
// Tell next call to 'default state_entry()' to reset all global // Tell next call to 'default state_entry()' to reset all global