public object Invoke(ScriptMethodBase scriptMethod, object target, params object[] args) { var callArgs = args; if (scriptMethod.MethodDefinition.HasThis) { callArgs = new object[args.Length + 1]; callArgs[0] = target; Array.Copy(args, 0, callArgs, 1, args.Length); } _runtimeContext.PushCallStack(scriptMethod, callArgs); var instruction = scriptMethod.MethodDefinition.Body.Instructions[0]; while (true) { try { Execute(ref instruction); break; } catch (ScriptException ex) { if (HandleException(scriptMethod, ex.InnerException, ref instruction)) { _runtimeContext.PushToStack(ex.InnerException); continue; } _runtimeContext.PopCallStack(); throw; } catch (Exception ex) { if (HandleException(scriptMethod, ex, ref instruction)) { _runtimeContext.PushToStack(ex); continue; } _runtimeContext.PopCallStack(); throw; } } return(_runtimeContext.PopCallStack().Return()); }
private bool HandleException(ScriptMethodBase method, Exception ex, ref Instruction instruction) { if (method.MethodDefinition.Body.HasExceptionHandlers) { var inst = instruction; var handlers = method.MethodDefinition.Body.ExceptionHandlers .Where(_ => { if (_.HandlerType != ExceptionHandlerType.Catch) { return(false); } if (_.TryStart.Offset > inst.Offset) { return(false); } if (_.TryEnd.Offset < inst.Offset) { return(false); } return(true); }) .OrderBy(_ => _.TryEnd.Offset - _.TryStart.Offset); var handlerList = handlers.ToList(); var bestMatch = FindBestExceptionMatch(ex, handlerList); if (bestMatch == null) { return(false); } instruction = bestMatch.HandlerStart; return(true); } return(false); }
private StackFrame Init(ScriptMethodBase scriptMethod, params object[] param) { // init local vars _locals = scriptMethod.MethodDefinition.Body.Variables.Select(_ => { var type = _.VariableType; if (!type.IsValueType) { return(null); } var scriptType = ScriptContext.GetType(type); return(scriptType.IsHost ? Activator.CreateInstance(scriptType.HostType) : scriptType.CreateInstance()); }).ToArray(); // init arguments _arguments = param; ScriptMethod = scriptMethod; return(this); }
internal static StackFrame Alloc(ScriptMethodBase scriptMethod, params object[] param) { return(FreeList.Count == 0 ? new StackFrame().Init(scriptMethod, param) : FreeList.Pop().Init(scriptMethod, param)); }
internal void PushCallStack(ScriptMethodBase scriptMethod, params object[] param) { _stackFrames.Push(StackFrame.Alloc(scriptMethod, param)); }