mirror of
https://github.com/opensim/opensim.git
synced 2026-07-31 22:05:36 +08:00
add experimental script engine XMRengine donated by mrieker (DreamNation) And our Melanie. ***DANGER*** ***TESTONLY*** ***disable HG*** dont leave running when not looking... tp/crossing to Xengine will reset scripts. i do see a few issues but should be testable, so we can decide if we should invest more on it.
This commit is contained in:
256
OpenSim/Region/ScriptEngine/XMREngine/MMRScriptObjCode.cs
Normal file
256
OpenSim/Region/ScriptEngine/XMREngine/MMRScriptObjCode.cs
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using OpenSim.Region.ScriptEngine.XMREngine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace OpenSim.Region.ScriptEngine.XMREngine
|
||||
{
|
||||
public delegate void ScriptEventHandler (XMRInstAbstract instance);
|
||||
|
||||
/*
|
||||
* This object represents the output of the compilation.
|
||||
* Once the compilation is complete, its contents should be
|
||||
* considered 'read-only', so it can be shared among multiple
|
||||
* instances of the script.
|
||||
*
|
||||
* It gets created by ScriptCodeGen.
|
||||
* It gets used by XMRInstance to create script instances.
|
||||
*/
|
||||
public class ScriptObjCode
|
||||
{
|
||||
public string sourceHash; // source text hash code
|
||||
|
||||
public XMRInstArSizes glblSizes = new XMRInstArSizes ();
|
||||
// number of global variables of various types
|
||||
|
||||
public string[] stateNames; // convert state number to corresponding string
|
||||
|
||||
public ScriptEventHandler[,] scriptEventHandlerTable;
|
||||
// entrypoints to all event handler functions
|
||||
// 1st subscript = state code number (0=default)
|
||||
// 2nd subscript = event code number
|
||||
// null entry means no handler defined for that state,event
|
||||
|
||||
public Dictionary<string, TokenDeclSDType> sdObjTypesName;
|
||||
// all script-defined types by name
|
||||
public TokenDeclSDType[] sdObjTypesIndx;
|
||||
// all script-defined types by sdTypeIndex
|
||||
|
||||
public Dictionary<Type, string> sdDelTypes;
|
||||
// all script-defined delegates (including anonymous)
|
||||
|
||||
public Dictionary<string, DynamicMethod> dynamicMethods;
|
||||
// all dyanmic methods
|
||||
|
||||
public Dictionary<string, KeyValuePair<int, ScriptSrcLoc>[]> scriptSrcLocss;
|
||||
// method,iloffset -> source file,line,posn
|
||||
|
||||
public int refCount; // used by engine to keep track of number of
|
||||
// instances that are using this object code
|
||||
|
||||
public Dictionary<string,Dictionary<int,string>> globalVarNames = new Dictionary<string,Dictionary<int,string>> ();
|
||||
|
||||
public DateTime fileDateUtc;
|
||||
public int expiryDays = Int32.MaxValue;
|
||||
public bool IsExpired ()
|
||||
{
|
||||
return (DateTime.UtcNow.Ticks - fileDateUtc.Ticks) / 10000000 / 86400 >= expiryDays;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill in ScriptObjCode from an XMREngine object file.
|
||||
* 'objFileReader' is a serialized form of the CIL code we generated
|
||||
* 'asmFileWriter' is where we write the disassembly to (or null if not wanted)
|
||||
* 'srcFileWriter' is where we write the decompilation to (or null if not wanted)
|
||||
* Throws an exception if there is any error (theoretically).
|
||||
*/
|
||||
public ScriptObjCode (BinaryReader objFileReader, TextWriter asmFileWriter, TextWriter srcFileWriter)
|
||||
{
|
||||
/*
|
||||
* Check version number to make sure we know how to process file contents.
|
||||
*/
|
||||
char[] ocm = objFileReader.ReadChars (ScriptCodeGen.OBJECT_CODE_MAGIC.Length);
|
||||
if (new String (ocm) != ScriptCodeGen.OBJECT_CODE_MAGIC) {
|
||||
throw new Exception ("not an XMR object file (bad magic)");
|
||||
}
|
||||
int cvv = objFileReader.ReadInt32 ();
|
||||
if (cvv != ScriptCodeGen.COMPILED_VERSION_VALUE) {
|
||||
throw new CVVMismatchException (cvv, ScriptCodeGen.COMPILED_VERSION_VALUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in simple parts of scriptObjCode object.
|
||||
*/
|
||||
sourceHash = objFileReader.ReadString ();
|
||||
expiryDays = objFileReader.ReadInt32 ();
|
||||
glblSizes.ReadFromFile (objFileReader);
|
||||
|
||||
int nStates = objFileReader.ReadInt32 ();
|
||||
|
||||
stateNames = new string[nStates];
|
||||
for (int i = 0; i < nStates; i ++) {
|
||||
stateNames[i] = objFileReader.ReadString ();
|
||||
if (asmFileWriter != null) {
|
||||
asmFileWriter.WriteLine (" state[{0}] = {1}", i, stateNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (asmFileWriter != null) {
|
||||
glblSizes.WriteAsmFile (asmFileWriter, "numGbl");
|
||||
}
|
||||
|
||||
string gblName;
|
||||
while ((gblName = objFileReader.ReadString ()) != "") {
|
||||
string gblType = objFileReader.ReadString ();
|
||||
int gblIndex = objFileReader.ReadInt32 ();
|
||||
Dictionary<int,string> names;
|
||||
if (!globalVarNames.TryGetValue (gblType, out names)) {
|
||||
names = new Dictionary<int,string> ();
|
||||
globalVarNames.Add (gblType, names);
|
||||
}
|
||||
names.Add (gblIndex, gblName);
|
||||
if (asmFileWriter != null) {
|
||||
asmFileWriter.WriteLine (" {0} = {1}[{2}]", gblName, gblType, gblIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in script-defined types.
|
||||
*/
|
||||
sdObjTypesName = new Dictionary<string, TokenDeclSDType> ();
|
||||
sdDelTypes = new Dictionary<Type, string> ();
|
||||
int maxIndex = -1;
|
||||
while ((gblName = objFileReader.ReadString ()) != "") {
|
||||
TokenDeclSDType sdt = TokenDeclSDType.ReadFromFile (sdObjTypesName,
|
||||
gblName, objFileReader, asmFileWriter);
|
||||
sdObjTypesName.Add (gblName, sdt);
|
||||
if (maxIndex < sdt.sdTypeIndex) maxIndex = sdt.sdTypeIndex;
|
||||
if (sdt is TokenDeclSDTypeDelegate) {
|
||||
sdDelTypes.Add (sdt.GetSysType (), gblName);
|
||||
}
|
||||
}
|
||||
sdObjTypesIndx = new TokenDeclSDType[maxIndex+1];
|
||||
foreach (TokenDeclSDType sdt in sdObjTypesName.Values) {
|
||||
sdObjTypesIndx[sdt.sdTypeIndex] = sdt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now fill in the methods (the hard part).
|
||||
*/
|
||||
scriptEventHandlerTable = new ScriptEventHandler[nStates,(int)ScriptEventCode.Size];
|
||||
dynamicMethods = new Dictionary<string, DynamicMethod> ();
|
||||
scriptSrcLocss = new Dictionary<string, KeyValuePair<int, ScriptSrcLoc>[]> ();
|
||||
|
||||
ObjectTokens objectTokens = null;
|
||||
if (asmFileWriter != null) {
|
||||
objectTokens = new OTDisassemble (this, asmFileWriter);
|
||||
} else if (srcFileWriter != null) {
|
||||
objectTokens = new OTDecompile (this, srcFileWriter);
|
||||
}
|
||||
|
||||
try {
|
||||
ScriptObjWriter.CreateObjCode (sdObjTypesName, objFileReader, this, objectTokens);
|
||||
} finally {
|
||||
if (objectTokens != null) objectTokens.Close ();
|
||||
}
|
||||
|
||||
/*
|
||||
* We enter all script event handler methods in the ScriptEventHandler table.
|
||||
* They are named: <statename> <eventname>
|
||||
*/
|
||||
foreach (KeyValuePair<string, DynamicMethod> kvp in dynamicMethods) {
|
||||
string methName = kvp.Key;
|
||||
int i = methName.IndexOf (' ');
|
||||
if (i < 0) continue;
|
||||
string stateName = methName.Substring (0, i);
|
||||
string eventName = methName.Substring (++ i);
|
||||
int stateCode;
|
||||
for (stateCode = stateNames.Length; -- stateCode >= 0;) {
|
||||
if (stateNames[stateCode] == stateName) break;
|
||||
}
|
||||
int eventCode = (int)Enum.Parse (typeof (ScriptEventCode), eventName);
|
||||
scriptEventHandlerTable[stateCode,eventCode] =
|
||||
(ScriptEventHandler)kvp.Value.CreateDelegate (typeof (ScriptEventHandler));
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in all script-defined class vtables.
|
||||
*/
|
||||
foreach (TokenDeclSDType sdt in sdObjTypesIndx) {
|
||||
if ((sdt != null) && (sdt is TokenDeclSDTypeClass)) {
|
||||
TokenDeclSDTypeClass sdtc = (TokenDeclSDTypeClass)sdt;
|
||||
sdtc.FillVTables (this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called once for every method found in objFileReader file.
|
||||
* It enters the method in the ScriptObjCode object table so it can be called.
|
||||
*/
|
||||
public void EndMethod (DynamicMethod method, Dictionary<int, ScriptSrcLoc> srcLocs)
|
||||
{
|
||||
/*
|
||||
* Save method object code pointer.
|
||||
*/
|
||||
dynamicMethods.Add (method.Name, method);
|
||||
|
||||
/*
|
||||
* Build and sort iloffset -> source code location array.
|
||||
*/
|
||||
int n = srcLocs.Count;
|
||||
KeyValuePair<int, ScriptSrcLoc>[] srcLocArray = new KeyValuePair<int, ScriptSrcLoc>[n];
|
||||
n = 0;
|
||||
foreach (KeyValuePair<int, ScriptSrcLoc> kvp in srcLocs) srcLocArray[n++] = kvp;
|
||||
Array.Sort (srcLocArray, endMethodWrapper);
|
||||
|
||||
/*
|
||||
* Save sorted array.
|
||||
*/
|
||||
scriptSrcLocss.Add (method.Name, srcLocArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called once for every method found in objFileReader file.
|
||||
* It enters the method in the ScriptObjCode object table so it can be called.
|
||||
*/
|
||||
private static EndMethodWrapper endMethodWrapper = new EndMethodWrapper ();
|
||||
private class EndMethodWrapper : System.Collections.IComparer {
|
||||
public int Compare (object x, object y)
|
||||
{
|
||||
KeyValuePair<int, ScriptSrcLoc> kvpx = (KeyValuePair<int, ScriptSrcLoc>)x;
|
||||
KeyValuePair<int, ScriptSrcLoc> kvpy = (KeyValuePair<int, ScriptSrcLoc>)y;
|
||||
return kvpx.Key - kvpy.Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user