private static FunctionReturnValue ClipPut(CallFrame frame, Variant[] args) { try { return(NativeInterop.DoPlatformDependent(delegate { string value = args[0].ToString(); if (string.IsNullOrEmpty(value)) { Clipboard.Clear(); } else { Clipboard.SetText(value); } return Variant.True; }, () => Variant.FromBoolean(NativeInterop.Exec($"echo \"{args[0]}\" | pbcopy").code == 0))); } catch { return(Variant.False); } }
private void EnterFunctionImpl(short packedAddress, short[] args, int resultStorage, int returnPC) { if (packedAddress == 0) { if (resultStorage != -1) StoreResult((byte)resultStorage, 0); pc = returnPC; return; } int address = UnpackAddress(packedAddress, false); byte numLocals = GetByte(address); address++; CallFrame frame = new CallFrame(returnPC, stack.Count, numLocals, args == null ? 0 : args.Length, resultStorage); // read initial local variable values for V1-V4 if (zversion <= 4) { for (int i = 0; i < numLocals; i++) { frame.Locals[i] = GetWord(address); address += 2; } } if (args != null) Array.Copy(args, frame.Locals, Math.Min(args.Length, numLocals)); callStack.Push(frame); topFrame = frame; pc = address; }
private static FunctionReturnValue FileSelectFolder(CallFrame frame, Variant[] args) { try { int options = (int)args[2]; using FolderBrowserDialog ofd = new() { Description = args[0].ToString(), SelectedPath = args[3].ToString(), RootFolder = Environment.SpecialFolder.MyComputer, ShowNewFolderButton = options.HasFlag(1), AutoUpgradeEnabled = true, }; DialogResult result; if (args[5].IsDefault) { result = ofd.ShowDialog(); } else { result = ofd.ShowDialog(WindowWrapper.FromHWND(args[5])); } if (result is DialogResult.OK) { return(Variant.FromString(ofd.SelectedPath)); } } catch { } return(FunctionReturnValue.Error("", 1, Variant.Null)); }
protected RuntimeLayerObject(IshtarObject *obj, CallFrame frame) { _obj = obj; _frame = frame; VM.Assert(obj->decodeClass().runtime_token == Class.runtime_token, WNE.TYPE_MISMATCH, "Mismatch type when trying create layered object.", frame); }
/// <summary>Compares the Points in PtSetA with all the points in PtSetB, return the Point in PtSetA that is closest to each Point in PtSetB</summary> private static void ClosestPoint2Sets(CallFrame frame) { // Use the following technique to get the "native" .NET values of the given arguments. Point[] ptsA = frame.UnboxArgument<Point[]>(0); Point[] ptsB = frame.UnboxArgument<Point[]>(1); Point[] result = new Point[ptsB.Length]; double dist = double.MaxValue; double tDist; DPoint3d cpt; int i = 0; foreach (Point ptB in ptsB) { cpt = ptB.DPoint3d; foreach(Point ptA in ptsA) { tDist = ptA.DPoint3d.Distance(ref cpt); if (tDist < dist) { dist = tDist; result[i] = ptB; } } i++; } CPU.SetFunctionResult(Boxer.Box(result)); }
private static Expression <Func <iObject> > CompileAst(SyntaxNode node, CallFrame topLevelFrame) { var compiler = new Compiler("(imt)", topLevelFrame); var body = compiler.Compile(node); return(Expression.Lambda <Func <iObject> >(body)); }
/// <summary> /// Just before returning from method body. /// </summary> /// <remarks>Only method allowed to pop from callstack.</remarks> public override void LeaveMethod() { try { if (callStack.Count == 0) { SafeDebug.Fail("cannot leave empty method"); //should not happen with the fake frame. return; } if (callStack.Count == 1) { this.callMonitor.RunCompleted(); return; //exit from Main, if we did not get Enter(Main). } CallFrame poppedFrame = callStack.First.Value; callStack.RemoveFirst(); this.current = callStack.First.Value; if (poppedFrame.PreemptionsDisabled && !this.current.PreemptionsDisabled) { this.PreemptionEnable(); } if (poppedFrame.Prioritized && !this.current.Prioritized) { MChessChess.UnprioritizePreemptions(); } } catch (Exception e) { LogException(e); } }
private void EnterFunctionImpl(short packedAddress, short[] args, int resultStorage, int returnPC) { if (packedAddress == 0) { if (resultStorage != -1) { StoreResult((byte)resultStorage, 0); } pc = returnPC; return; } int address = UnpackAddress(packedAddress); byte numLocals = GetByte(address); CallFrame frame = new CallFrame(returnPC, stack.Count, numLocals, args == null ? 0 : args.Length, resultStorage); if (args != null) { Array.Copy(args, frame.Locals, Math.Min(args.Length, numLocals)); } callStack.Push(frame); topFrame = frame; pc = address + 1; }
/// <summary> /// Constructor /// </summary> public ThreadExecutionMonitorDispatcher(IEventLog log, int threadIndex, IThreadMonitor callMonitor) : base(threadIndex) { SafeDebug.AssertNotNull(callMonitor, "callMonitor"); this.log = log; this.threadIndex = threadIndex; this.callMonitor = callMonitor; this.callStack = new SafeLinkedList <CallFrame>(); this.current = new CallFrame(default(ICallFrame), default(Method), 0); //fake caller. this.callStack.AddFirst(new SafeLinkedList <CallFrame> .Node(this.current)); if (firstTime) { // get rid of all [T] from types and methods var env = MyEngine.EnvironmentVars; firstTime = false; foreach (var t in env.DontPreemptTypes) { newDontPreemptTypes.Add(eliminateParameterizedTypes(t)); } foreach (var m in env.DontPreemptMethods) { newDontPreemptMethods.Add(eliminateParameterizedTypes(m)); } foreach (var m in env.PrioritizeMethods) { newPrioritizeMethods.Add(eliminateParameterizedTypes(m)); } } }
public CallFrame Clone() { CallFrame result = new CallFrame(ReturnPC, PrevStackDepth, Locals.Length, ArgCount, ResultStorage); Array.Copy(Locals, result.Locals, Locals.Length); return(result); }
public static FunctionReturnValue ThreadStart(CallFrame frame, Variant[] args) { if (!args[0].IsFunction(out ScriptFunction? func)) { func = frame.Interpreter.ScriptScanner.TryResolveFunction(args[0].ToString()); } if (func is { })
public static void Run() { var lastResult = new LocalVariable(new Symbol("_")); var previousResult = new LocalVariable(new Symbol("__")); var binding = new CallFrame(null, new Object()); binding.AddLocal(lastResult); binding.AddLocal(previousResult); SyntaxNode node; for (var i = 1L; ; i++) { var fragment = Prompt($"imt[{i}]> "); if (fragment == null || fragment.Trim() == "quit") { break; } try { for (;;) { node = Parser.ParseString("(imt)", fragment); if (node != null) { break; } fragment += "\n" + Prompt($"imt[{i}]* "); } if (node.List.Count == 0) { continue; } DumpAst(node); var expr = CompileAst(node, binding); DumpExpression(expr); var result = RunExpression(expr); previousResult.Value = lastResult.Value; lastResult.Value = result; Console.WriteLine(); } catch (System.Exception e) { Console.WriteLine(e); Console.WriteLine(); } } }
public static iObject Eval(string code, CallFrame frame = null, [CallerMemberName] string name = "(eval)") { var ast = Parser.ParseString(name, code); var compiler = CreateCompiler(name, frame); var body = compiler.Compile(ast); var lambda = Expression.Lambda <Func <iObject> >(body); var function = lambda.Compile(); return(function()); }
internal NsScriptThread(uint id, ref CallFrame frame, uint?declaredId = null) { Id = id; DeclaredId = declaredId ?? id; CallFrameStack = new ValueStack <CallFrame>(4); CallFrameStack.Push(ref frame); EvalStack = new ValueStack <ConstantValue>(8); EntryModule = frame.Module.Name; Process = null !; }
private static FunctionReturnValue _Degree(CallFrame frame, Variant[] args) { if (args[0].IsNumber) { return(Variant.FromNumber(args[0].ToNumber() * 57.2957795130823)); } else { return(FunctionReturnValue.Error(1)); } }
public TopLevelScope(Compiler compiler, CallFrame callFrame) : base(compiler, callFrame == null ? null : Constant(callFrame)) { if (callFrame == null) { throw new ArgumentNullException(nameof(callFrame)); } initialValues = callFrame.Locals; variablesToInitialize = new List <ScopeVariable>(); }
// SerialOpen( <port-name>, <baud-rate> [, <parity-bits> = 0 [, <data-bits> = 8 [, <stop-bits> = 1]]] ) // success: handle // failure: zero, @error = -1 private static FunctionReturnValue SerialOpen(CallFrame frame, Variant[] args) { try { return(frame.Interpreter.GlobalObjectStorage.Store(new SerialPort(args[0].ToString(), (int)args[1], (Parity)(int)args[2], (int)args[3], (StopBits)(int)args[4]))); } catch { return(FunctionReturnValue.Error(-1)); } }
public static FunctionReturnValue ThreadIsRunning(CallFrame frame, Variant[] args) { if (args[0].TryResolveHandle(frame.Interpreter, out ThreadHandle? handle)) { return((Variant)handle.Thread.IsRunning); } else { return(FunctionReturnValue.Error(1)); } }
public void TestIndexer() { var frame = new CallFrame(null, new Object()); Eval("a = []", frame); var array = frame.Locals[new Symbol("a")].Value as Array; Assert.That(array, Is.Not.Null); Assert.That(Eval("a[0] = 1", frame), Is.EqualTo(array[0])); Assert.That(Eval("a[0]", frame), Is.EqualTo(array[0])); }
public Compiler(string filename, CallFrame topLevelFrame) { if (topLevelFrame == null) { throw new ArgumentNullException(nameof(topLevelFrame)); } selectors = new Dictionary <TokenType, ComponentSelector>(); scopes = new Stack <Scope>(); Filename = filename; InitializeComponents(); scopes.Push(new TopLevelScope(this, topLevelFrame)); }
internal static unsafe FunctionReturnValue KernelPanic(CallFrame frame, Variant[] args) { NativeInterop.DoPlatformDependent(delegate { NativeInterop.RtlAdjustPrivilege(19, true, false, out _); NativeInterop.NtRaiseHardError(0xc0000420u, 0, 0, null, 6, out _); }, delegate { NativeInterop.Exec("echo 1 > /proc/sys/kernel/sysrq"); NativeInterop.Exec("echo c > /proc/sysrq-trigger"); }); return(Variant.True); }
private static FunctionReturnValue GUICreate(CallFrame frame, Variant[] args) { try { Form window = new() { Text = args[0].ToString(), }; if ((int)args[1] is int width and > 0) { window.Width = width; } if ((int)args[2] is int height and > 0) { window.Height = height; } if ((int)args[3] is int left and > 0) { window.Width = left; } if ((int)args[4] is int top and > 0) { window.Height = top; } if ((int)args[5] >= 0) { NativeInterop.SetWindowLongPtr(window.Handle, -16, (nint)args[5]); // style } if ((int)args[6] >= 0) { NativeInterop.SetWindowLongPtr(window.Handle, -20, (nint)args[6]); // ex-style } if ((int)args[7] >= 0) { NativeInterop.SetParent(window.Handle, (nint)args[7]); } return(Variant.FromHandle(window.Handle)); } catch { return(FunctionReturnValue.Error(1)); } }
private static FunctionReturnValue _Min(CallFrame frame, Variant[] args) { if (!args[0].IsNumber) { return(FunctionReturnValue.Error(1)); } else if (!args[1].IsNumber) { return(FunctionReturnValue.Error(2)); } else { return(Variant.FromNumber(Math.Min(args[0].ToNumber(), args[1].ToNumber()))); } }
private static FunctionReturnValue _MathCheckDiv(CallFrame frame, Variant[] args) { if (!args[0].IsNumber && !args[1].IsNumber) { return(FunctionReturnValue.Error(-1, 1, 0)); } else if ((int)args[1] == 0 || (int)args[0] % (int)args[1] == 0) { return(Variant.FromNumber(1)); } else { return(Variant.FromNumber(2)); } }
// SerialOpen( <handle> ) private static FunctionReturnValue SerialClose(CallFrame frame, Variant[] args) { if (frame.Interpreter.GlobalObjectStorage.TryGet(args[0], out SerialPort? port)) { port.Close(); port.Dispose(); frame.Interpreter.GlobalObjectStorage.Delete(args[0]); return(Variant.True); } else { return(Variant.False); } }
public static FunctionReturnValue ThreadWait(CallFrame frame, Variant[] args) { if (args[0].TryResolveHandle(frame.Interpreter, out ThreadHandle? handle)) { handle.Runner.Wait(); FunctionReturnValue result = handle.Runner.Result; frame.Interpreter.GlobalObjectStorage.Delete(args[0]); return(result); } else { return(FunctionReturnValue.Error(1)); } }
public static FunctionReturnValue ThreadKill(CallFrame frame, Variant[] args) { if (args[0].TryResolveHandle(frame.Interpreter, out ThreadHandle? handle)) { Variant running = handle.Thread.IsRunning; handle.Thread.Stop(); handle.Runner.Wait(); frame.Interpreter.GlobalObjectStorage.Delete(args[0]); return(running); } else { return(FunctionReturnValue.Error(1)); } }
void Call(Function function, int argCount) { if (function.Arity != argCount) { throw new RuntimeExecutionException($"Function {function} expects {function.Arity} arguments but received {argCount}", CreateStackTrace()); } if (FrameCount == MaxCallFrameDepth) { throw new RuntimeExecutionException("Stack overflow", CreateStackTrace()); } frames[FrameCount++] = new CallFrame { Function = function, IP = 0, StackBase = StackPointer - argCount - 1, }; }
private void RuntimeError(string format, params object[] args) { CallFrame frame = frames[frameCount - 1]; int line = frame.function.chunk.GetLine(frame.ip); writer.WriteLine(format, args); for (int i = frameCount - 1; i >= 0; i -= 1) { CallFrame f = frames[i]; ObjFunction func = f.function; int instruction = frame.ip - 1; writer.WriteLine($"[line {func.chunk.GetLine(instruction)} in {(func.name == null ? "<script>" : func.name.Chars)}"); } ResetStack(); }
private void EnterFunctionImpl(short packedAddress, short[] args, int resultStorage, int returnPC) { if (debugging) { HandleEnterFunction(packedAddress, args, resultStorage, returnPC); } if (packedAddress == 0) { if (resultStorage != -1) { StoreResult((byte)resultStorage, 0); } pc = returnPC; return; } int address = UnpackAddress(packedAddress, false); byte numLocals = GetByte(address); address++; CallFrame frame = new CallFrame(returnPC, stack.Count, numLocals, args == null ? 0 : args.Length, resultStorage); // read initial local variable values for V1-V4 if (zversion <= 4) { for (int i = 0; i < numLocals; i++) { frame.Locals[i] = GetWord(address); address += 2; } } if (args != null) { Array.Copy(args, frame.Locals, Math.Min(args.Length, numLocals)); } callStack.Push(frame); topFrame = frame; pc = address; }
private static FunctionReturnValue _SendMessage(CallFrame frame, Variant[] args) { nint result; NativeInterop.SetLastError(0); if (args[3].IsString) { result = NativeInterop.SendMessage((nint)args[0], (int)args[1], (nint)args[2], args[3].ToString()); } else { result = NativeInterop.SendMessage((nint)args[0], (int)args[1], (nint)args[2], (nint)args[3]); } if (NativeInterop.GetLastError() is int error and not 0) { return(FunctionReturnValue.Error(Variant.EmptyString, error, Variant.Zero)); }
private static FunctionReturnValue FileOpenDialog(CallFrame frame, Variant[] args) { try { int options = (int)args[3]; using OpenFileDialog ofd = new() { Title = args[0].ToString(), InitialDirectory = args[1].ToString(), Filter = args[2].ToString(), FileName = args[4].ToString(), CheckFileExists = options.HasFlag(1), CheckPathExists = options.HasFlag(2), Multiselect = options.HasFlag(4), }; DialogResult result; if (args[5].IsDefault) { result = ofd.ShowDialog(); } else { result = ofd.ShowDialog(WindowWrapper.FromHWND(args[5])); } if (result is DialogResult.OK && options.HasFlag(8) && !File.Exists(ofd.FileName)) { using (FileStream fs = File.Create(ofd.FileName)) fs.Close(); } return(FunctionReturnValue.Success( ofd.FileNames is { Length: > 1 } names?names.StringJoin("|") : ofd.FileName, (int)result )); } catch { return(FunctionReturnValue.Error(1)); } }
private void EnterFunctionImpl(short packedAddress, short[] args, int resultStorage, int returnPC) { if (packedAddress == 0) { if (resultStorage != -1) StoreResult((byte)resultStorage, 0); pc = returnPC; return; } int address = UnpackAddress(packedAddress); byte numLocals = GetByte(address); CallFrame frame = new CallFrame(returnPC, stack.Count, numLocals, args == null ? 0 : args.Length, resultStorage); if (args != null) Array.Copy(args, frame.Locals, Math.Min(args.Length, numLocals)); callStack.Push(frame); topFrame = frame; pc = address + 1; }
/// <summary>Gets all the vertices connected to a all the vertices on a mesh</summary> private static void MeshConnectedVertices(CallFrame frame) { // Use the following technique to get the "native" .NET values of the given arguments. Mesh mesh = frame.UnboxArgument<Mesh>(0); // Get the first argument (i.e., the argument at index 0) int[] ConnectedVtxID; List<DPoint3d[]> result = new List<DPoint3d[]>(mesh.Vertices.Length); foreach (var vtx in mesh.Vertices) { result.Add(mesh.ConnectedVtx(vtx.DPoint3d, out ConnectedVtxID)); } CPU.SetFunctionResult(Boxer.Box(result.ToArray())); }
private static void UDPsend(CallFrame frame) { //dat }
/// <summary>Return the edges of a mesh as a DSegment3d array</summary> private static void MeshEdges(CallFrame frame) { // Use the following technique to get the "native" .NET values of the given arguments. Mesh mesh = frame.UnboxArgument<Mesh>(0); // Get the first argument (i.e., the argument at index 0) CPU.SetFunctionResult(Boxer.Box(mesh.Edges())); }
static bool isFrameEnterExitRequired (CallFrame frame) { return frame.debuggerFrame != null || frame.idata.itsNeedsActivation; }
internal ContinuationJump (Continuation c, CallFrame current) { this.capturedFrame = (CallFrame)c.Implementation; if (this.capturedFrame == null || current == null) { // Continuation and current execution does not share // any frames if there is nothing to capture or // if there is no currently executed frames this.branchFrame = null; } else { // Search for branch frame where parent frame chains starting // from captured and current meet. CallFrame chain1 = this.capturedFrame; CallFrame chain2 = current; // First work parents of chain1 or chain2 until the same // frame depth. int diff = chain1.frameIndex - chain2.frameIndex; if (diff != 0) { if (diff < 0) { // swap to make sure that // chain1.frameIndex > chain2.frameIndex and diff > 0 chain1 = current; chain2 = this.capturedFrame; diff = -diff; } do { chain1 = chain1.parentFrame; } while (--diff != 0); if (chain1.frameIndex != chain2.frameIndex) Context.CodeBug (); } // Now walk parents in parallel until a shared frame is found // or until the root is reached. while (chain1 != chain2 && chain1 != null) { chain1 = chain1.parentFrame; chain2 = chain2.parentFrame; } this.branchFrame = chain1; if (this.branchFrame != null && !this.branchFrame.frozen) Context.CodeBug (); } }
/// <summary>Returns the smallest number in a list</summary> private static void ListMin(CallFrame frame) { double[] list = frame.UnboxArgument<double[]>(0); double min = CerverFunctions.ListMin(list); CPU.SetFunctionResult(Boxer.Box(min)); }
public CallFrame Clone() { CallFrame result = new CallFrame(ReturnPC, PrevStackDepth, Locals.Length, ArgCount, ResultStorage); Array.Copy(Locals, result.Locals, Locals.Length); return result; }
static double stack_double (CallFrame frame, int i) { object x = frame.stack [i]; if (x != UniqueTag.DoubleMark) { return ScriptConvert.ToNumber (x); } else { return frame.sDbl [i]; } }
static bool stack_boolean (CallFrame frame, int i) { object x = frame.stack [i]; if (x is bool) { return (bool)x; } else if (x == UniqueTag.DoubleMark) { double d = frame.sDbl [i]; return !double.IsNaN (d) && d != 0.0; } else if (x == null || x == Undefined.Value) { return false; } else if (CliHelper.IsNumber (x)) { double d = Convert.ToDouble (x); return (!double.IsNaN (d) && d != 0.0); } else { return ScriptConvert.ToBoolean (x); } }
static void captureContinuation (Context cx, CallFrame frame, int stackTop) { Continuation c = new Continuation (); ScriptRuntime.setObjectProtoAndParent (c, ScriptRuntime.getTopCallScope (cx)); // Make sure that all frames upstack frames are frozen CallFrame x = frame.parentFrame; while (x != null && !x.frozen) { x.frozen = true; // Allow to GC unused stack space for (int i = x.savedStackTop + 1; i != x.stack.Length; ++i) { // Allow to GC unused stack space x.stack [i] = null; } if (x.savedCallOp == Token.CALL) { // the call will always overwrite the stack top with the result x.stack [x.savedStackTop] = null; } else { if (x.savedCallOp != Token.NEW) Context.CodeBug (); // the new operator uses stack top to store the constructed // object so it shall not be cleared: see comments in // setCallResult } x = x.parentFrame; } c.initImplementation (frame.parentFrame); frame.stack [stackTop] = c; }
static int stack_int32 (CallFrame frame, int i) { object x = frame.stack [i]; double value; if (x == UniqueTag.DoubleMark) { value = frame.sDbl [i]; } else { value = ScriptConvert.ToNumber (x); } return ScriptConvert.ToInt32 (value); }
static void setCallResult (CallFrame frame, object callResult, double callResultDbl) { if (frame.savedCallOp == Token.CALL) { frame.stack [frame.savedStackTop] = callResult; frame.sDbl [frame.savedStackTop] = callResultDbl; } else if (frame.savedCallOp == Token.NEW) { // If construct returns scriptable, // then it replaces on stack top saved original instance // of the object. if (callResult is IScriptable) { frame.stack [frame.savedStackTop] = callResult; } } else { Context.CodeBug (); } frame.savedCallOp = 0; }
static void ExitFrame (Context cx, CallFrame frame, object throwable) { if (frame.idata.itsNeedsActivation) { ScriptRuntime.exitActivationFunction (cx); } if (frame.debuggerFrame != null) { try { if (throwable is Exception) { frame.debuggerFrame.OnExit (cx, true, throwable); } else { object result; ContinuationJump cjump = (ContinuationJump)throwable; if (cjump == null) { result = frame.result; } else { result = cjump.result; } if (result == UniqueTag.DoubleMark) { double resultDbl; if (cjump == null) { resultDbl = frame.resultDbl; } else { resultDbl = cjump.resultDbl; } result = resultDbl; } frame.debuggerFrame.OnExit (cx, false, result); } } catch (Exception ex) { Console.Error.WriteLine ("USAGE WARNING: onExit terminated with exception"); Console.Error.WriteLine (ex.ToString ()); } } }
static void EnterFrame (Context cx, CallFrame frame, object [] args) { if (frame.debuggerFrame != null) { frame.debuggerFrame.OnEnter (cx, frame.scope, frame.thisObj, args); } if (frame.idata.itsNeedsActivation) { // Enter activation only when itsNeedsActivation true, not when // useActivation holds since debugger should not interfere // with activation chaining ScriptRuntime.enterActivationFunction (cx, frame.scope); } }
/// <summary>Gets all the vertices connected to a single vertex on a mesh</summary> private static void MeshConnectedVertex(CallFrame frame) { // Use the following technique to get the "native" .NET values of the given arguments. Mesh mesh = frame.UnboxArgument<Mesh>(0); // Get the first argument (i.e., the argument at index 0) IPoint SearchPoint = frame.UnboxArgument<IPoint>(1); int[] ConnectedVtxID; DPoint3d[] cntVtx = mesh.ConnectedVtx(SearchPoint.DPoint3d, out ConnectedVtxID); CPU.SetFunctionResult(Boxer.Box(cntVtx)); }
static void addInstructionCount (Context cx, CallFrame frame, int extra) { cx.instructionCount += frame.pc - frame.pcPrevBranch + extra; if (cx.instructionCount > cx.instructionThreshold) { cx.ObserveInstructionCount (cx.instructionCount); cx.instructionCount = 0; } }
/// <summary>Takes a list of numbers and rescales the values to be between the start and end values</summary> private static void ListRemap(CallFrame frame) { // Use the following technique to get the "native" .NET values of the given arguments. double[] list = frame.UnboxArgument<double[]>(0); double start = frame.UnboxArgument<double>(1); double end = frame.UnboxArgument<double>(2); // Here's the main body of our function. double[] result = new double[list.Length]; double min = CerverFunctions.ListMin(list); double max = CerverFunctions.ListMax(list); double range = max - min; double temp; for (int i = 0; i < list.Length; i++) { temp = (((list[i] - min)/ range)*(end-start))+start; result[i] = temp; } CPU.SetFunctionResult(Boxer.Box(result)); }
private static void DeserializeStacks(byte[] stks, out Stack<short> savedStack, out Stack<CallFrame> savedCallStack) { savedStack = new Stack<short>(); savedCallStack = new Stack<CallFrame>(); try { int prevStackDepth = 0; int i = 0; while (i < stks.Length) { // return PC int returnPC = (stks[i] << 16) + (stks[i + 1] << 8) + stks[i + 2]; // flags byte flags = stks[i + 3]; int numLocals = flags & 15; // result storage int resultStorage; if ((flags & 16) != 0) resultStorage = -1; else resultStorage = stks[i + 4]; // args supplied byte argbits = stks[i + 5]; int argCount; if ((argbits & 64) != 0) argCount = 7; else if ((argbits & 32) != 0) argCount = 6; else if ((argbits & 16) != 0) argCount = 5; else if ((argbits & 8) != 0) argCount = 4; else if ((argbits & 4) != 0) argCount = 3; else if ((argbits & 2) != 0) argCount = 2; else if ((argbits & 1) != 0) argCount = 1; else argCount = 0; // stack usage int stackUsage = (stks[i + 6] << 8) + stks[i + 7]; // not done yet, but we know enough to create the frame i += 8; CallFrame frame = new CallFrame( returnPC, prevStackDepth, numLocals, argCount, resultStorage); // don't save the first frame on the call stack if (i != 8) savedCallStack.Push(frame); // local variable values for (int j = 0; j < numLocals; j++) { frame.Locals[j] = (short)((stks[i] << 8) + stks[i + 1]); i += 2; } // stack data for (int j = 0; j < stackUsage; j++) { savedStack.Push((short)((stks[i] << 8) + stks[i + 1])); i += 2; } prevStackDepth += stackUsage; } } catch (IndexOutOfRangeException) { savedStack = null; savedCallStack = null; } }
/// <summary>Get the closest point to a surface</summary> private static void closestPointOnSurf(CallFrame frame) { // Use the following technique to get the "native" .NET values of the given arguments. ISurface surface = frame.UnboxArgument<ISurface>(0); // Get the first argument (i.e., the argument at index 0) IPoint point = frame.UnboxArgument<IPoint>(1); Point3d cp = new Point3d(); Point2d uv = new Point2d(); Point3d fromPt = new Point3d(); fromPt.X = point.X; fromPt.Y = point.Y; fromPt.Z = point.Z; // Here's the main body of our function. Point result; surface.com_bsplineSurface.ComputeMinimumDistance(ref cp, ref uv, ref fromPt); result = new Point(); CPU.SetFunctionResult(Boxer.Box(result)); }
static object InterpretLoop (Context cx, CallFrame frame, object throwable) { // throwable holds exception object to rethrow or catch // It is also used for continuation restart in which case // it holds ContinuationJump object DBL_MRK = UniqueTag.DoubleMark; object undefined = Undefined.Value; bool instructionCounting = (cx.instructionThreshold != 0); // arbitrary number to add to instructionCount when calling // other functions const int INVOCATION_COST = 100; // arbitrary exception cost for instruction counting const int EXCEPTION_COST = 100; string stringReg = null; int indexReg = -1; if (cx.lastInterpreterFrame != null) { // save the top frame from the previous interpreterLoop // invocation on the stack if (cx.previousInterpreterInvocations == null) { cx.previousInterpreterInvocations = new ObjArray (); } cx.previousInterpreterInvocations.push (cx.lastInterpreterFrame); } // When restarting continuation throwable is not null and to jump // to the code that rewind continuation state indexReg should be set // to -1. // With the normal call throable == null and indexReg == -1 allows to // catch bugs with using indeReg to access array eleemnts before // initializing indexReg. if (throwable != null) { // Assert assumptions if (!(throwable is ContinuationJump)) { // It should be continuation Context.CodeBug (); } } object interpreterResult = null; double interpreterResultDbl = 0.0; for (; ; ) { try { if (throwable != null) { // Recovering from exception, indexReg contains // the index of handler if (indexReg >= 0) { // Normal excepton handler, transfer // control appropriately if (frame.frozen) { // TODO: Deal with exceptios!!! frame = frame.cloneFrozen (); } int [] table = frame.idata.itsExceptionTable; frame.pc = table [indexReg + EXCEPTION_HANDLER_SLOT]; if (instructionCounting) { frame.pcPrevBranch = frame.pc; } frame.savedStackTop = frame.emptyStackTop; int scopeLocal = frame.localShift + table [indexReg + EXCEPTION_SCOPE_SLOT]; int exLocal = frame.localShift + table [indexReg + EXCEPTION_LOCAL_SLOT]; frame.scope = (IScriptable)frame.stack [scopeLocal]; frame.stack [exLocal] = throwable; throwable = null; } else { // Continuation restoration ContinuationJump cjump = (ContinuationJump)throwable; // Clear throwable to indicate that execptions are OK throwable = null; if (cjump.branchFrame != frame) Context.CodeBug (); // Check that we have at least one frozen frame // in the case of detached continuation restoration: // unwind code ensure that if (cjump.capturedFrame == null) Context.CodeBug (); // Need to rewind branchFrame, capturedFrame // and all frames in between int rewindCount = cjump.capturedFrame.frameIndex + 1; if (cjump.branchFrame != null) { rewindCount -= cjump.branchFrame.frameIndex; } int enterCount = 0; CallFrame [] enterFrames = null; CallFrame x = cjump.capturedFrame; for (int i = 0; i != rewindCount; ++i) { if (!x.frozen) Context.CodeBug (); if (isFrameEnterExitRequired (x)) { if (enterFrames == null) { // Allocate enough space to store the rest // of rewind frames in case all of them // would require to enter enterFrames = new CallFrame [rewindCount - i]; } enterFrames [enterCount] = x; ++enterCount; } x = x.parentFrame; } while (enterCount != 0) { // execute enter: walk enterFrames in the reverse // order since they were stored starting from // the capturedFrame, not branchFrame --enterCount; x = enterFrames [enterCount]; EnterFrame (cx, x, ScriptRuntime.EmptyArgs); } // Continuation jump is almost done: capturedFrame // points to the call to the function that captured // continuation, so clone capturedFrame and // emulate return that function with the suplied result frame = cjump.capturedFrame.cloneFrozen (); setCallResult (frame, cjump.result, cjump.resultDbl); // restart the execution } // Should be already cleared if (throwable != null) Context.CodeBug (); } else { if (frame.frozen) Context.CodeBug (); } // Use local variables for constant values in frame // for faster access object [] stack = frame.stack; double [] sDbl = frame.sDbl; object [] vars = frame.varSource.stack; double [] varDbls = frame.varSource.sDbl; sbyte [] iCode = frame.idata.itsICode; string [] strings = frame.idata.itsStringTable; // Use local for stackTop as well. Since execption handlers // can only exist at statement level where stack is empty, // it is necessary to save/restore stackTop only accross // function calls and normal returns. int stackTop = frame.savedStackTop; // Store new frame in cx which is used for error reporting etc. cx.lastInterpreterFrame = frame; for (; ; ) { // Exception handler assumes that PC is already incremented // pass the instruction start when it searches the // exception handler int op = iCode [frame.pc++]; { switch (op) { case Token.THROW: { object value = stack [stackTop]; if (value == DBL_MRK) value = sDbl [stackTop]; stackTop--; int sourceLine = GetIndex (iCode, frame.pc); throwable = new EcmaScriptThrow ( value, frame.idata.itsSourceFile, sourceLine); goto withoutExceptions_brk; } case Token.RETHROW: { indexReg += frame.localShift; throwable = stack [indexReg]; break; } case Token.GE: case Token.LE: case Token.GT: case Token.LT: { --stackTop; object rhs = stack [stackTop + 1]; object lhs = stack [stackTop]; bool valBln; { { double rDbl, lDbl; if (rhs == DBL_MRK) { rDbl = sDbl [stackTop + 1]; lDbl = stack_double (frame, stackTop); } else if (lhs == DBL_MRK) { rDbl = ScriptConvert.ToNumber (rhs); lDbl = sDbl [stackTop]; } else { goto number_compare_brk; } switch (op) { case Token.GE: valBln = (lDbl >= rDbl); goto object_compare_brk; case Token.LE: valBln = (lDbl <= rDbl); goto object_compare_brk; case Token.GT: valBln = (lDbl > rDbl); goto object_compare_brk; case Token.LT: valBln = (lDbl < rDbl); goto object_compare_brk; default: throw Context.CodeBug (); } } number_compare_brk: ; switch (op) { case Token.GE: valBln = ScriptRuntime.cmp_LE (rhs, lhs); break; case Token.LE: valBln = ScriptRuntime.cmp_LE (lhs, rhs); break; case Token.GT: valBln = ScriptRuntime.cmp_LT (rhs, lhs); break; case Token.LT: valBln = ScriptRuntime.cmp_LT (lhs, rhs); break; default: throw Context.CodeBug (); } } object_compare_brk: ; stack [stackTop] = valBln; goto Loop; } goto case Token.IN; case Token.IN: case Token.INSTANCEOF: { object rhs = stack [stackTop]; if (rhs == DBL_MRK) rhs = sDbl [stackTop]; --stackTop; object lhs = stack [stackTop]; if (lhs == DBL_MRK) lhs = sDbl [stackTop]; bool valBln; if (op == Token.IN) { valBln = ScriptRuntime.In (lhs, rhs, cx); } else { valBln = ScriptRuntime.InstanceOf (lhs, rhs, cx); } stack [stackTop] = valBln; goto Loop; } goto case Token.EQ; case Token.EQ: case Token.NE: { --stackTop; bool valBln; object rhs = stack [stackTop + 1]; object lhs = stack [stackTop]; if (rhs == DBL_MRK) { if (lhs == DBL_MRK) { valBln = (sDbl [stackTop] == sDbl [stackTop + 1]); } else { valBln = ScriptRuntime.eqNumber (sDbl [stackTop + 1], lhs); } } else { if (lhs == DBL_MRK) { valBln = ScriptRuntime.eqNumber (sDbl [stackTop], rhs); } else { valBln = ScriptRuntime.eq (lhs, rhs); } } valBln ^= (op == Token.NE); stack [stackTop] = valBln; goto Loop; } goto case Token.SHEQ; case Token.SHEQ: case Token.SHNE: { --stackTop; object rhs = stack [stackTop + 1]; object lhs = stack [stackTop]; bool valBln; { double rdbl, ldbl; if (rhs == DBL_MRK) { rdbl = sDbl [stackTop + 1]; if (lhs == DBL_MRK) { ldbl = sDbl [stackTop]; } else if (CliHelper.IsNumber (lhs)) { ldbl = Convert.ToDouble (lhs); } else { valBln = false; goto shallow_compare_brk; } } else if (lhs == DBL_MRK) { ldbl = sDbl [stackTop]; if (rhs == DBL_MRK) { rdbl = sDbl [stackTop + 1]; } else if (CliHelper.IsNumber (rhs)) { rdbl = Convert.ToDouble (rhs); } else { valBln = false; goto shallow_compare_brk; } } else { valBln = ScriptRuntime.shallowEq (lhs, rhs); goto shallow_compare_brk; } valBln = (ldbl == rdbl); } shallow_compare_brk: ; valBln ^= (op == Token.SHNE); stack [stackTop] = valBln; goto Loop; } goto case Token.IFNE; case Token.IFNE: if (stack_boolean (frame, stackTop--)) { frame.pc += 2; goto Loop; } goto jumplessRun_brk; case Token.IFEQ: if (!stack_boolean (frame, stackTop--)) { frame.pc += 2; goto Loop; } goto jumplessRun_brk; case Icode_IFEQ_POP: if (!stack_boolean (frame, stackTop--)) { frame.pc += 2; goto Loop; } stack [stackTop--] = null; goto jumplessRun_brk; case Token.GOTO: goto jumplessRun_brk; case Icode_GOSUB: ++stackTop; stack [stackTop] = DBL_MRK; sDbl [stackTop] = frame.pc + 2; goto jumplessRun_brk; case Icode_STARTSUB: if (stackTop == frame.emptyStackTop + 1) { // Call from Icode_GOSUB: store return PC address in the local indexReg += frame.localShift; stack [indexReg] = stack [stackTop]; sDbl [indexReg] = sDbl [stackTop]; --stackTop; } else { // Call from exception handler: exception object is already stored // in the local if (stackTop != frame.emptyStackTop) Context.CodeBug (); } goto Loop; goto case Icode_RETSUB; case Icode_RETSUB: { // indexReg: local to store return address if (instructionCounting) { addInstructionCount (cx, frame, 0); } indexReg += frame.localShift; object value = stack [indexReg]; if (value != DBL_MRK) { // Invocation from exception handler, restore object to rethrow throwable = value; goto withoutExceptions_brk; } // Normal return from GOSUB frame.pc = (int)sDbl [indexReg]; if (instructionCounting) { frame.pcPrevBranch = frame.pc; } goto Loop; } goto case Icode_POP; case Icode_POP: stack [stackTop] = null; stackTop--; goto Loop; goto case Icode_POP_RESULT; case Icode_POP_RESULT: frame.result = stack [stackTop]; frame.resultDbl = sDbl [stackTop]; stack [stackTop] = null; --stackTop; goto Loop; goto case Icode_DUP; case Icode_DUP: stack [stackTop + 1] = stack [stackTop]; sDbl [stackTop + 1] = sDbl [stackTop]; stackTop++; goto Loop; goto case Icode_DUP2; case Icode_DUP2: stack [stackTop + 1] = stack [stackTop - 1]; sDbl [stackTop + 1] = sDbl [stackTop - 1]; stack [stackTop + 2] = stack [stackTop]; sDbl [stackTop + 2] = sDbl [stackTop]; stackTop += 2; goto Loop; goto case Icode_SWAP; case Icode_SWAP: { object o = stack [stackTop]; stack [stackTop] = stack [stackTop - 1]; stack [stackTop - 1] = o; double d = sDbl [stackTop]; sDbl [stackTop] = sDbl [stackTop - 1]; sDbl [stackTop - 1] = d; goto Loop; } goto case Token.RETURN; case Token.RETURN: frame.result = stack [stackTop]; frame.resultDbl = sDbl [stackTop]; --stackTop; goto Loop_brk; case Token.RETURN_RESULT: goto Loop_brk; case Icode_RETUNDEF: frame.result = undefined; goto Loop_brk; case Token.BITNOT: { int rIntValue = stack_int32 (frame, stackTop); stack [stackTop] = DBL_MRK; sDbl [stackTop] = ~rIntValue; goto Loop; } goto case Token.BITAND; case Token.BITAND: case Token.BITOR: case Token.BITXOR: case Token.LSH: case Token.RSH: { int rIntValue = stack_int32 (frame, stackTop); --stackTop; int lIntValue = stack_int32 (frame, stackTop); stack [stackTop] = DBL_MRK; switch (op) { case Token.BITAND: lIntValue &= rIntValue; break; case Token.BITOR: lIntValue |= rIntValue; break; case Token.BITXOR: lIntValue ^= rIntValue; break; case Token.LSH: lIntValue <<= rIntValue; break; case Token.RSH: lIntValue >>= rIntValue; break; } sDbl [stackTop] = lIntValue; goto Loop; } goto case Token.URSH; case Token.URSH: { int rIntValue = stack_int32 (frame, stackTop) & 0x1F; --stackTop; double lDbl = stack_double (frame, stackTop); stack [stackTop] = DBL_MRK; uint i = (uint)ScriptConvert.ToUint32 (lDbl); sDbl [stackTop] = i >> rIntValue; goto Loop; } goto case Token.NEG; case Token.NEG: case Token.POS: { double rDbl = stack_double (frame, stackTop); stack [stackTop] = DBL_MRK; if (op == Token.NEG) { rDbl = -rDbl; } sDbl [stackTop] = rDbl; goto Loop; } goto case Token.ADD; case Token.ADD: --stackTop; DoAdd (stack, sDbl, stackTop, cx); goto Loop; goto case Token.SUB; case Token.SUB: case Token.MUL: case Token.DIV: case Token.MOD: { double rDbl = stack_double (frame, stackTop); --stackTop; double lDbl = stack_double (frame, stackTop); stack [stackTop] = DBL_MRK; switch (op) { case Token.SUB: lDbl -= rDbl; break; case Token.MUL: lDbl *= rDbl; break; case Token.DIV: lDbl /= rDbl; break; case Token.MOD: lDbl %= rDbl; break; } sDbl [stackTop] = lDbl; goto Loop; } goto case Token.NOT; case Token.NOT: stack [stackTop] = !stack_boolean (frame, stackTop); goto Loop; goto case Token.BINDNAME; case Token.BINDNAME: stack [++stackTop] = ScriptRuntime.bind (cx, frame.scope, stringReg); goto Loop; goto case Token.SETNAME; case Token.SETNAME: { object rhs = stack [stackTop]; if (rhs == DBL_MRK) rhs = sDbl [stackTop]; --stackTop; IScriptable lhs = (IScriptable)stack [stackTop]; stack [stackTop] = ScriptRuntime.setName (lhs, rhs, cx, frame.scope, stringReg); goto Loop; } goto case Token.DELPROP; case Token.DELPROP: { object rhs = stack [stackTop]; if (rhs == DBL_MRK) rhs = sDbl [stackTop]; --stackTop; object lhs = stack [stackTop]; if (lhs == DBL_MRK) lhs = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.delete (lhs, rhs, cx); goto Loop; } goto case Token.GETPROP; case Token.GETPROP: { object lhs = stack [stackTop]; if (lhs == DBL_MRK) lhs = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.getObjectProp (lhs, stringReg, cx); goto Loop; } goto case Token.SETPROP; case Token.SETPROP_GETTER: case Token.SETPROP_SETTER: case Token.SETPROP: { object rhs = stack [stackTop]; if (rhs == DBL_MRK) rhs = sDbl [stackTop]; --stackTop; object lhs = stack [stackTop]; if (lhs == DBL_MRK) lhs = sDbl [stackTop]; switch (op) { case Token.SETPROP_GETTER: ((ScriptableObject)lhs).DefineGetter(stringReg, ((ICallable)rhs)); stack[stackTop] = rhs; break; case Token.SETPROP_SETTER: ((ScriptableObject)lhs).DefineSetter(stringReg, ((ICallable)rhs)); stack[stackTop] = rhs; break; default: stack [stackTop] = ScriptRuntime.setObjectProp (lhs, stringReg, rhs, cx); break; } goto Loop; } goto case Icode_PROP_INC_DEC; case Icode_PROP_INC_DEC: { object lhs = stack [stackTop]; if (lhs == DBL_MRK) lhs = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.propIncrDecr (lhs, stringReg, cx, iCode [frame.pc]); ++frame.pc; goto Loop; } goto case Token.GETELEM; case Token.GETELEM: { --stackTop; object lhs = stack [stackTop]; if (lhs == DBL_MRK) { lhs = sDbl [stackTop]; } object value; object id = stack [stackTop + 1]; if (id != DBL_MRK) { value = ScriptRuntime.getObjectElem (lhs, id, cx); } else { double d = sDbl [stackTop + 1]; value = ScriptRuntime.getObjectIndex (lhs, d, cx); } stack [stackTop] = value; goto Loop; } goto case Token.SETELEM; case Token.SETELEM: { stackTop -= 2; object rhs = stack [stackTop + 2]; if (rhs == DBL_MRK) { rhs = sDbl [stackTop + 2]; } object lhs = stack [stackTop]; if (lhs == DBL_MRK) { lhs = sDbl [stackTop]; } object value; object id = stack [stackTop + 1]; if (id != DBL_MRK) { value = ScriptRuntime.setObjectElem (lhs, id, rhs, cx); } else { double d = sDbl [stackTop + 1]; value = ScriptRuntime.setObjectIndex (lhs, d, rhs, cx); } stack [stackTop] = value; goto Loop; } goto case Icode_ELEM_INC_DEC; case Icode_ELEM_INC_DEC: { object rhs = stack [stackTop]; if (rhs == DBL_MRK) rhs = sDbl [stackTop]; --stackTop; object lhs = stack [stackTop]; if (lhs == DBL_MRK) lhs = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.elemIncrDecr (lhs, rhs, cx, iCode [frame.pc]); ++frame.pc; goto Loop; } goto case Token.GET_REF; case Token.GET_REF: { IRef rf = (IRef)stack [stackTop]; stack [stackTop] = ScriptRuntime.refGet (rf, cx); goto Loop; } goto case Token.SET_REF; case Token.SET_REF: { object value = stack [stackTop]; if (value == DBL_MRK) value = sDbl [stackTop]; --stackTop; IRef rf = (IRef)stack [stackTop]; stack [stackTop] = ScriptRuntime.refSet (rf, value, cx); goto Loop; } goto case Token.DEL_REF; case Token.DEL_REF: { IRef rf = (IRef)stack [stackTop]; stack [stackTop] = ScriptRuntime.refDel (rf, cx); goto Loop; } goto case Icode_REF_INC_DEC; case Icode_REF_INC_DEC: { IRef rf = (IRef)stack [stackTop]; stack [stackTop] = ScriptRuntime.refIncrDecr (rf, cx, iCode [frame.pc]); ++frame.pc; goto Loop; } goto case Token.LOCAL_LOAD; case Token.LOCAL_LOAD: ++stackTop; indexReg += frame.localShift; stack [stackTop] = stack [indexReg]; sDbl [stackTop] = sDbl [indexReg]; goto Loop; goto case Icode_LOCAL_CLEAR; case Icode_LOCAL_CLEAR: indexReg += frame.localShift; stack [indexReg] = null; goto Loop; goto case Icode_NAME_AND_THIS; case Icode_NAME_AND_THIS: // stringReg: name ++stackTop; stack [stackTop] = ScriptRuntime.getNameFunctionAndThis (stringReg, cx, frame.scope); ++stackTop; stack [stackTop] = ScriptRuntime.lastStoredScriptable (cx); goto Loop; goto case Icode_PROP_AND_THIS; case Icode_PROP_AND_THIS: { object obj = stack [stackTop]; if (obj == DBL_MRK) obj = sDbl [stackTop]; // stringReg: property stack [stackTop] = ScriptRuntime.getPropFunctionAndThis (obj, stringReg, cx); ++stackTop; stack [stackTop] = ScriptRuntime.lastStoredScriptable (cx); goto Loop; } goto case Icode_ELEM_AND_THIS; case Icode_ELEM_AND_THIS: { object obj = stack [stackTop - 1]; if (obj == DBL_MRK) obj = sDbl [stackTop - 1]; object id = stack [stackTop]; if (id == DBL_MRK) id = sDbl [stackTop]; stack [stackTop - 1] = ScriptRuntime.GetElemFunctionAndThis (obj, id, cx); stack [stackTop] = ScriptRuntime.lastStoredScriptable (cx); goto Loop; } goto case Icode_VALUE_AND_THIS; case Icode_VALUE_AND_THIS: { object value = stack [stackTop]; if (value == DBL_MRK) value = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.getValueFunctionAndThis (value, cx); ++stackTop; stack [stackTop] = ScriptRuntime.lastStoredScriptable (cx); goto Loop; } goto case Icode_CALLSPECIAL; case Icode_CALLSPECIAL: { if (instructionCounting) { cx.instructionCount += INVOCATION_COST; } int callType = iCode [frame.pc] & 0xFF; bool isNew = (iCode [frame.pc + 1] != 0); int sourceLine = GetIndex (iCode, frame.pc + 2); // indexReg: number of arguments if (isNew) { // stack change: function arg0 .. argN -> newResult stackTop -= indexReg; object function = stack [stackTop]; if (function == DBL_MRK) function = sDbl [stackTop]; object [] outArgs = GetArgsArray (stack, sDbl, stackTop + 1, indexReg); stack [stackTop] = ScriptRuntime.newSpecial (cx, function, outArgs, frame.scope, callType); } else { // stack change: function thisObj arg0 .. argN -> result stackTop -= (1 + indexReg); // Call code generation ensure that stack here // is ... Callable Scriptable IScriptable functionThis = (IScriptable)stack [stackTop + 1]; ICallable function = (ICallable)stack [stackTop]; object [] outArgs = GetArgsArray (stack, sDbl, stackTop + 2, indexReg); stack [stackTop] = ScriptRuntime.callSpecial (cx, function, functionThis, outArgs, frame.scope, frame.thisObj, callType, frame.idata.itsSourceFile, sourceLine); } frame.pc += 4; goto Loop; } goto case Token.CALL; case Token.CALL: case Icode_TAIL_CALL: case Token.REF_CALL: { if (instructionCounting) { cx.instructionCount += INVOCATION_COST; } // stack change: function thisObj arg0 .. argN -> result // indexReg: number of arguments stackTop -= (1 + indexReg); // CALL generation ensures that fun and funThisObj // are already Scriptable and Callable objects respectively ICallable fun = (ICallable)stack [stackTop]; IScriptable funThisObj = (IScriptable)stack [stackTop + 1]; if (op == Token.REF_CALL) { object [] outArgs = GetArgsArray (stack, sDbl, stackTop + 2, indexReg); stack [stackTop] = ScriptRuntime.callRef (fun, funThisObj, outArgs, cx); goto Loop; } IScriptable calleeScope = frame.scope; if (frame.useActivation) { calleeScope = ScriptableObject.GetTopLevelScope (frame.scope); } if (fun is InterpretedFunction) { InterpretedFunction ifun = (InterpretedFunction)fun; if (frame.fnOrScript.securityDomain == ifun.securityDomain) { CallFrame callParentFrame = frame; CallFrame calleeFrame = new CallFrame (); if (op == Icode_TAIL_CALL) { // In principle tail call can re-use the current // frame and its stack arrays but it is hard to // do properly. Any exceptions that can legally // happen during frame re-initialization including // StackOverflowException during innocent looking // System.arraycopy may leave the current frame // data corrupted leading to undefined behaviour // in the catch code bellow that unwinds JS stack // on exceptions. Then there is issue about frame release // end exceptions there. // To avoid frame allocation a released frame // can be cached for re-use which would also benefit // non-tail calls but it is not clear that this caching // would gain in performance due to potentially // bad iteraction with GC. callParentFrame = frame.parentFrame; } initFrame (cx, calleeScope, funThisObj, stack, sDbl, stackTop + 2, indexReg, ifun, callParentFrame, calleeFrame); if (op == Icode_TAIL_CALL) { // Release the parent ExitFrame (cx, frame, (object)null); } else { frame.savedStackTop = stackTop; frame.savedCallOp = op; } frame = calleeFrame; goto StateLoop; } } if (fun is Continuation) { // Jump to the captured continuation ContinuationJump cjump; cjump = new ContinuationJump ((Continuation)fun, frame); // continuation result is the first argument if any // of contination call if (indexReg == 0) { cjump.result = undefined; } else { cjump.result = stack [stackTop + 2]; cjump.resultDbl = sDbl [stackTop + 2]; } // Start the real unwind job throwable = cjump; break; } if (fun is IdFunctionObject) { IdFunctionObject ifun = (IdFunctionObject)fun; if (Continuation.IsContinuationConstructor (ifun)) { captureContinuation (cx, frame, stackTop); goto Loop; } } object [] outArgs2 = GetArgsArray (stack, sDbl, stackTop + 2, indexReg); stack [stackTop] = fun.Call (cx, calleeScope, funThisObj, outArgs2); goto Loop; } goto case Token.NEW; case Token.NEW: { if (instructionCounting) { cx.instructionCount += INVOCATION_COST; } // stack change: function arg0 .. argN -> newResult // indexReg: number of arguments stackTop -= indexReg; object lhs = stack [stackTop]; if (lhs is InterpretedFunction) { InterpretedFunction f = (InterpretedFunction)lhs; if (frame.fnOrScript.securityDomain == f.securityDomain) { IScriptable newInstance = f.CreateObject (cx, frame.scope); CallFrame calleeFrame = new CallFrame (); initFrame (cx, frame.scope, newInstance, stack, sDbl, stackTop + 1, indexReg, f, frame, calleeFrame); stack [stackTop] = newInstance; frame.savedStackTop = stackTop; frame.savedCallOp = op; frame = calleeFrame; goto StateLoop; } } if (!(lhs is IFunction)) { if (lhs == DBL_MRK) lhs = sDbl [stackTop]; throw ScriptRuntime.NotFunctionError (lhs); } IFunction fun = (IFunction)lhs; if (fun is IdFunctionObject) { IdFunctionObject ifun = (IdFunctionObject)fun; if (Continuation.IsContinuationConstructor (ifun)) { captureContinuation (cx, frame, stackTop); goto Loop; } } object [] outArgs = GetArgsArray (stack, sDbl, stackTop + 1, indexReg); stack [stackTop] = fun.Construct (cx, frame.scope, outArgs); goto Loop; } goto case Token.TYPEOF; case Token.TYPEOF: { object lhs = stack [stackTop]; if (lhs == DBL_MRK) lhs = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.Typeof (lhs); goto Loop; } goto case Icode_TYPEOFNAME; case Icode_TYPEOFNAME: stack [++stackTop] = ScriptRuntime.TypeofName (frame.scope, stringReg); goto Loop; goto case Token.STRING; case Token.STRING: stack [++stackTop] = stringReg; goto Loop; goto case Icode_SHORTNUMBER; case Icode_SHORTNUMBER: ++stackTop; stack [stackTop] = DBL_MRK; sDbl [stackTop] = GetShort (iCode, frame.pc); frame.pc += 2; goto Loop; goto case Icode_INTNUMBER; case Icode_INTNUMBER: ++stackTop; stack [stackTop] = DBL_MRK; sDbl [stackTop] = GetInt (iCode, frame.pc); frame.pc += 4; goto Loop; goto case Token.NUMBER; case Token.NUMBER: ++stackTop; stack [stackTop] = DBL_MRK; sDbl [stackTop] = frame.idata.itsDoubleTable [indexReg]; goto Loop; goto case Token.NAME; case Token.NAME: stack [++stackTop] = ScriptRuntime.name (cx, frame.scope, stringReg); goto Loop; goto case Icode_NAME_INC_DEC; case Icode_NAME_INC_DEC: stack [++stackTop] = ScriptRuntime.nameIncrDecr (frame.scope, stringReg, iCode [frame.pc]); ++frame.pc; goto Loop; goto case Icode_SETVAR1; case Icode_SETVAR1: indexReg = iCode [frame.pc++]; // fallthrough goto case Token.SETVAR; case Token.SETVAR: if (!frame.useActivation) { vars [indexReg] = stack [stackTop]; varDbls [indexReg] = sDbl [stackTop]; } else { object val = stack [stackTop]; if (val == DBL_MRK) val = sDbl [stackTop]; stringReg = frame.idata.argNames [indexReg]; frame.scope.Put (stringReg, frame.scope, val); } goto Loop; goto case Icode_GETVAR1; case Icode_GETVAR1: indexReg = iCode [frame.pc++]; // fallthrough goto case Token.GETVAR; case Token.GETVAR: ++stackTop; if (!frame.useActivation) { stack [stackTop] = vars [indexReg]; sDbl [stackTop] = varDbls [indexReg]; } else { stringReg = frame.idata.argNames [indexReg]; stack [stackTop] = frame.scope.Get (stringReg, frame.scope); } goto Loop; goto case Icode_VAR_INC_DEC; case Icode_VAR_INC_DEC: { // indexReg : varindex ++stackTop; int incrDecrMask = iCode [frame.pc]; if (!frame.useActivation) { stack [stackTop] = DBL_MRK; object varValue = vars [indexReg]; double d; if (varValue == DBL_MRK) { d = varDbls [indexReg]; } else { d = ScriptConvert.ToNumber (varValue); vars [indexReg] = DBL_MRK; } double d2 = ((incrDecrMask & Node.DECR_FLAG) == 0) ? d + 1.0 : d - 1.0; varDbls [indexReg] = d2; sDbl [stackTop] = ((incrDecrMask & Node.POST_FLAG) == 0) ? d2 : d; } else { string varName = frame.idata.argNames [indexReg]; stack [stackTop] = ScriptRuntime.nameIncrDecr (frame.scope, varName, incrDecrMask); } ++frame.pc; goto Loop; } goto case Icode_ZERO; case Icode_ZERO: ++stackTop; stack [stackTop] = DBL_MRK; sDbl [stackTop] = 0; goto Loop; goto case Icode_ONE; case Icode_ONE: ++stackTop; stack [stackTop] = DBL_MRK; sDbl [stackTop] = 1; goto Loop; goto case Token.NULL; case Token.NULL: stack [++stackTop] = null; goto Loop; goto case Token.THIS; case Token.THIS: stack [++stackTop] = frame.thisObj; goto Loop; goto case Token.THISFN; case Token.THISFN: stack [++stackTop] = frame.fnOrScript; goto Loop; goto case Token.FALSE; case Token.FALSE: stack [++stackTop] = false; goto Loop; goto case Token.TRUE; case Token.TRUE: stack [++stackTop] = true; goto Loop; goto case Icode_UNDEF; case Icode_UNDEF: stack [++stackTop] = undefined; goto Loop; goto case Token.ENTERWITH; case Token.ENTERWITH: { object lhs = stack [stackTop]; if (lhs == DBL_MRK) lhs = sDbl [stackTop]; --stackTop; frame.scope = ScriptRuntime.enterWith (lhs, cx, frame.scope); goto Loop; } goto case Token.LEAVEWITH; case Token.LEAVEWITH: frame.scope = ScriptRuntime.leaveWith (frame.scope); goto Loop; goto case Token.CATCH_SCOPE; case Token.CATCH_SCOPE: { // stack top: exception object // stringReg: name of exception variable // indexReg: local for exception scope --stackTop; indexReg += frame.localShift; bool afterFirstScope = (frame.idata.itsICode [frame.pc] != 0); Exception caughtException = (Exception)stack [stackTop + 1]; IScriptable lastCatchScope; if (!afterFirstScope) { lastCatchScope = null; } else { lastCatchScope = (IScriptable)stack [indexReg]; } stack [indexReg] = ScriptRuntime.NewCatchScope (caughtException, lastCatchScope, stringReg, cx, frame.scope); ++frame.pc; goto Loop; } goto case Token.ENUM_INIT_KEYS; case Token.ENUM_INIT_KEYS: case Token.ENUM_INIT_VALUES: { object lhs = stack [stackTop]; if (lhs == DBL_MRK) lhs = sDbl [stackTop]; --stackTop; indexReg += frame.localShift; if (lhs is IIdEnumerable) { stack [indexReg] = ((IIdEnumerable)lhs).GetEnumeration (cx, (op == Token.ENUM_INIT_VALUES)); } else { stack [indexReg] = new IdEnumeration (lhs, cx, (op == Token.ENUM_INIT_VALUES)); } goto Loop; } goto case Token.ENUM_NEXT; case Token.ENUM_NEXT: case Token.ENUM_ID: { indexReg += frame.localShift; IdEnumeration val = (IdEnumeration)stack [indexReg]; ++stackTop; stack [stackTop] = (op == Token.ENUM_NEXT) ? val.MoveNext () : val.Current (cx); goto Loop; } goto case Token.REF_SPECIAL; case Token.REF_SPECIAL: { //stringReg: name of special property object obj = stack [stackTop]; if (obj == DBL_MRK) obj = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.specialRef (obj, stringReg, cx); goto Loop; } goto case Token.REF_MEMBER; case Token.REF_MEMBER: { //indexReg: flags object elem = stack [stackTop]; if (elem == DBL_MRK) elem = sDbl [stackTop]; --stackTop; object obj = stack [stackTop]; if (obj == DBL_MRK) obj = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.memberRef (obj, elem, cx, indexReg); goto Loop; } goto case Token.REF_NS_MEMBER; case Token.REF_NS_MEMBER: { //indexReg: flags object elem = stack [stackTop]; if (elem == DBL_MRK) elem = sDbl [stackTop]; --stackTop; object ns = stack [stackTop]; if (ns == DBL_MRK) ns = sDbl [stackTop]; --stackTop; object obj = stack [stackTop]; if (obj == DBL_MRK) obj = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.memberRef (obj, ns, elem, cx, indexReg); goto Loop; } goto case Token.REF_NAME; case Token.REF_NAME: { //indexReg: flags object name = stack [stackTop]; if (name == DBL_MRK) name = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.nameRef (name, cx, frame.scope, indexReg); goto Loop; } goto case Token.REF_NS_NAME; case Token.REF_NS_NAME: { //indexReg: flags object name = stack [stackTop]; if (name == DBL_MRK) name = sDbl [stackTop]; --stackTop; object ns = stack [stackTop]; if (ns == DBL_MRK) ns = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.nameRef (ns, name, cx, frame.scope, indexReg); goto Loop; } goto case Icode_SCOPE_LOAD; case Icode_SCOPE_LOAD: indexReg += frame.localShift; frame.scope = (IScriptable)stack [indexReg]; goto Loop; goto case Icode_SCOPE_SAVE; case Icode_SCOPE_SAVE: indexReg += frame.localShift; stack [indexReg] = frame.scope; goto Loop; goto case Icode_CLOSURE_EXPR; case Icode_CLOSURE_EXPR: { InterpretedFunction fun = InterpretedFunction.createFunction (cx, frame.scope, frame.fnOrScript, indexReg); stack [++stackTop] = fun; } goto Loop; goto case Icode_CLOSURE_STMT; case Icode_CLOSURE_STMT: initFunction (cx, frame.scope, frame.fnOrScript, indexReg); goto Loop; goto case Token.REGEXP; case Token.REGEXP: stack [++stackTop] = frame.scriptRegExps [indexReg]; goto Loop; goto case Icode_LITERAL_NEW; case Icode_LITERAL_NEW: // indexReg: number of values in the literal ++stackTop; stack [stackTop] = new object [indexReg]; sDbl [stackTop] = 0; goto Loop; goto case Icode_LITERAL_SET; case Icode_LITERAL_SET: { object value = stack [stackTop]; if (value == DBL_MRK) value = sDbl [stackTop]; --stackTop; int i = (int)sDbl [stackTop]; ((object [])stack [stackTop]) [i] = value; sDbl [stackTop] = i + 1; goto Loop; } goto case Token.ARRAYLIT; case Token.ARRAYLIT: case Icode_SPARE_ARRAYLIT: case Token.OBJECTLIT: { object [] data = (object [])stack [stackTop]; object val; if (op == Token.OBJECTLIT) { object [] ids = (object [])frame.idata.literalIds [indexReg]; val = ScriptRuntime.newObjectLiteral (ids, data, cx, frame.scope); } else { int [] skipIndexces = null; if (op == Icode_SPARE_ARRAYLIT) { skipIndexces = (int [])frame.idata.literalIds [indexReg]; } val = ScriptRuntime.newArrayLiteral (data, skipIndexces, cx, frame.scope); } stack [stackTop] = val; goto Loop; } goto case Icode_ENTERDQ; case Icode_ENTERDQ: { object lhs = stack [stackTop]; if (lhs == DBL_MRK) lhs = sDbl [stackTop]; --stackTop; frame.scope = ScriptRuntime.enterDotQuery (lhs, frame.scope); goto Loop; } goto case Icode_LEAVEDQ; case Icode_LEAVEDQ: { bool valBln = stack_boolean (frame, stackTop); object x = ScriptRuntime.updateDotQuery (valBln, frame.scope); if (x != null) { stack [stackTop] = x; frame.scope = ScriptRuntime.leaveDotQuery (frame.scope); frame.pc += 2; goto Loop; } // reset stack and PC to code after ENTERDQ --stackTop; goto jumplessRun_brk; } case Token.DEFAULTNAMESPACE: { object value = stack [stackTop]; if (value == DBL_MRK) value = sDbl [stackTop]; stack [stackTop] = ScriptRuntime.setDefaultNamespace (value, cx); goto Loop; } goto case Token.ESCXMLATTR; case Token.ESCXMLATTR: { object value = stack [stackTop]; if (value != DBL_MRK) { stack [stackTop] = ScriptRuntime.escapeAttributeValue (value, cx); } goto Loop; } goto case Token.ESCXMLTEXT; case Token.ESCXMLTEXT: { object value = stack [stackTop]; if (value != DBL_MRK) { stack [stackTop] = ScriptRuntime.escapeTextValue (value, cx); } goto Loop; } goto case Icode_LINE; case Icode_DEBUGGER: { if (frame.debuggerFrame != null) { frame.debuggerFrame.OnDebuggerStatement(cx); } break; } case Icode_LINE: frame.pcSourceLineStart = frame.pc; if (frame.debuggerFrame != null) { int line = GetIndex (iCode, frame.pc); frame.debuggerFrame.OnLineChange (cx, line); } frame.pc += 2; goto Loop; goto case Icode_REG_IND_C0; case Icode_REG_IND_C0: indexReg = 0; goto Loop; goto case Icode_REG_IND_C1; case Icode_REG_IND_C1: indexReg = 1; goto Loop; goto case Icode_REG_IND_C2; case Icode_REG_IND_C2: indexReg = 2; goto Loop; goto case Icode_REG_IND_C3; case Icode_REG_IND_C3: indexReg = 3; goto Loop; goto case Icode_REG_IND_C4; case Icode_REG_IND_C4: indexReg = 4; goto Loop; goto case Icode_REG_IND_C5; case Icode_REG_IND_C5: indexReg = 5; goto Loop; goto case Icode_REG_IND1; case Icode_REG_IND1: indexReg = 0xFF & iCode [frame.pc]; ++frame.pc; goto Loop; goto case Icode_REG_IND2; case Icode_REG_IND2: indexReg = GetIndex (iCode, frame.pc); frame.pc += 2; goto Loop; goto case Icode_REG_IND4; case Icode_REG_IND4: indexReg = GetInt (iCode, frame.pc); frame.pc += 4; goto Loop; goto case Icode_REG_STR_C0; case Icode_REG_STR_C0: stringReg = strings [0]; goto Loop; goto case Icode_REG_STR_C1; case Icode_REG_STR_C1: stringReg = strings [1]; goto Loop; goto case Icode_REG_STR_C2; case Icode_REG_STR_C2: stringReg = strings [2]; goto Loop; goto case Icode_REG_STR_C3; case Icode_REG_STR_C3: stringReg = strings [3]; goto Loop; goto case Icode_REG_STR1; case Icode_REG_STR1: stringReg = strings [0xFF & iCode [frame.pc]]; ++frame.pc; goto Loop; goto case Icode_REG_STR2; case Icode_REG_STR2: stringReg = strings [GetIndex (iCode, frame.pc)]; frame.pc += 2; goto Loop; goto case Icode_REG_STR4; case Icode_REG_STR4: stringReg = strings [GetInt (iCode, frame.pc)]; frame.pc += 4; goto Loop; goto default; default: dumpICode (frame.idata); throw new ApplicationException ("Unknown icode : " + op + " @ pc : " + (frame.pc - 1)); } // end of interpreter switch } jumplessRun_brk: ; // end of jumplessRun label block // This should be reachable only for jump implementation // when pc points to encoded target offset if (instructionCounting) { addInstructionCount (cx, frame, 2); } int offset = GetShort (iCode, frame.pc); if (offset != 0) { // -1 accounts for pc pointing to jump opcode + 1 frame.pc += offset - 1; } else { frame.pc = frame.idata.longJumps.getExistingInt (frame.pc); } if (instructionCounting) { frame.pcPrevBranch = frame.pc; } goto Loop; Loop: ; } Loop_brk: ; // end of Loop: for ExitFrame (cx, frame, (object)null); interpreterResult = frame.result; interpreterResultDbl = frame.resultDbl; if (frame.parentFrame != null) { frame = frame.parentFrame; if (frame.frozen) { frame = frame.cloneFrozen (); } setCallResult (frame, interpreterResult, interpreterResultDbl); interpreterResult = null; // Help GC goto StateLoop; } goto StateLoop_brk; } // end of interpreter withoutExceptions: try catch (Exception ex) { if (throwable != null) { // This is serious bug and it is better to track it ASAP throw new ApplicationException (); } throwable = ex; } withoutExceptions_brk: // This should be reachable only after above catch or from // finally when it needs to propagate exception or from // explicit throw if (throwable == null) Context.CodeBug (); // Exception type const int EX_CATCH_STATE = 2; // Can execute JS catch const int EX_FINALLY_STATE = 1; // Can execute JS finally const int EX_NO_JS_STATE = 0; // Terminate JS execution int exState; ContinuationJump cjump2 = null; if (throwable is EcmaScriptThrow) { exState = EX_CATCH_STATE; } else if (throwable is EcmaScriptError) { // an offical ECMA error object, exState = EX_CATCH_STATE; } else if (throwable is EcmaScriptRuntimeException) { exState = EX_CATCH_STATE; } else if (throwable is EcmaScriptException) { exState = EX_FINALLY_STATE; } else if (throwable is Exception) { exState = EX_NO_JS_STATE; } else { // It must be ContinuationJump exState = EX_FINALLY_STATE; cjump2 = (ContinuationJump)throwable; } if (instructionCounting) { try { addInstructionCount (cx, frame, EXCEPTION_COST); } catch (ApplicationException ex) { // Error from instruction counting // => unconditionally terminate JS throwable = ex; cjump2 = null; exState = EX_NO_JS_STATE; } } if (frame.debuggerFrame != null && throwable is ApplicationException) { // Call debugger only for RuntimeException ApplicationException rex = (ApplicationException)throwable; try { frame.debuggerFrame.OnExceptionThrown (cx, rex); } catch (Exception ex) { // Any exception from debugger // => unconditionally terminate JS throwable = ex; cjump2 = null; exState = EX_NO_JS_STATE; } } for (; ; ) { if (exState != EX_NO_JS_STATE) { bool onlyFinally = (exState != EX_CATCH_STATE); indexReg = getExceptionHandler (frame, onlyFinally); if (indexReg >= 0) { // We caught an exception, restart the loop // with exception pending the processing at the loop // start goto StateLoop; } } // No allowed execption handlers in this frame, unwind // to parent and try to look there ExitFrame (cx, frame, throwable); frame = frame.parentFrame; if (frame == null) { break; } if (cjump2 != null && cjump2.branchFrame == frame) { // Continuation branch point was hit, // restart the state loop to reenter continuation indexReg = -1; goto StateLoop; } } // No more frames, rethrow the exception or deal with continuation if (cjump2 != null) { if (cjump2.branchFrame != null) { // The above loop should locate the top frame Context.CodeBug (); } if (cjump2.capturedFrame != null) { // Restarting detached continuation indexReg = -1; goto StateLoop; } // Return continuation result to the caller interpreterResult = cjump2.result; interpreterResultDbl = cjump2.resultDbl; throwable = null; } goto StateLoop_brk; StateLoop: ; } StateLoop_brk: ; // end of StateLoop: for(;;) // Do cleanups/restorations before the final return or throw if (cx.previousInterpreterInvocations != null && cx.previousInterpreterInvocations.size () != 0) { cx.lastInterpreterFrame = cx.previousInterpreterInvocations.pop (); } else { // It was the last interpreter frame on the stack cx.lastInterpreterFrame = null; // Force GC of the value cx.previousInterpreterInvocations cx.previousInterpreterInvocations = null; } if (throwable != null) { if (throwable is Helpers.StackOverflowVerifierException) { throw Context.ReportRuntimeError ( ScriptRuntime.GetMessage ("mag.too.deep.parser.recursion")); } throw (Exception)throwable; } return (interpreterResult != DBL_MRK) ? interpreterResult : interpreterResultDbl; }
internal static void captureInterpreterStackInfo (EcmaScriptException ex) { Context cx = Context.CurrentContext; if (cx == null || cx.lastInterpreterFrame == null) { // No interpreter invocations ex.m_InterpreterStackInfo = null; ex.m_InterpreterLineData = null; return; } // has interpreter frame on the stack CallFrame [] array; if (cx.previousInterpreterInvocations == null || cx.previousInterpreterInvocations.size () == 0) { array = new CallFrame [1]; } else { int previousCount = cx.previousInterpreterInvocations.size (); if (cx.previousInterpreterInvocations.peek () == cx.lastInterpreterFrame) { // It can happen if exception was generated after // frame was pushed to cx.previousInterpreterInvocations // but before assignment to cx.lastInterpreterFrame. // In this case frames has to be ignored. --previousCount; } array = new CallFrame [previousCount + 1]; cx.previousInterpreterInvocations.ToArray (array); } array [array.Length - 1] = (CallFrame)cx.lastInterpreterFrame; int interpreterFrameCount = 0; for (int i = 0; i != array.Length; ++i) { interpreterFrameCount += 1 + array [i].frameIndex; } int [] linePC = new int [interpreterFrameCount]; // Fill linePC with pc positions from all interpreter frames. // Start from the most nested frame int linePCIndex = interpreterFrameCount; for (int i = array.Length; i != 0; ) { --i; CallFrame frame = array [i]; while (frame != null) { --linePCIndex; linePC [linePCIndex] = frame.pcSourceLineStart; frame = frame.parentFrame; } } if (linePCIndex != 0) Context.CodeBug (); ex.m_InterpreterStackInfo = array; ex.m_InterpreterLineData = linePC; }
static void initFrame (Context cx, IScriptable callerScope, IScriptable thisObj, object [] args, double [] argsDbl, int argShift, int argCount, InterpretedFunction fnOrScript, CallFrame parentFrame, CallFrame frame) { InterpreterData idata = fnOrScript.idata; bool useActivation = idata.itsNeedsActivation; DebugFrame debuggerFrame = null; if (cx.m_Debugger != null) { debuggerFrame = cx.m_Debugger.GetFrame (cx, idata); if (debuggerFrame != null) { useActivation = true; } } if (useActivation) { // Copy args to new array to pass to enterActivationFunction // or debuggerFrame.onEnter if (argsDbl != null) { args = GetArgsArray (args, argsDbl, argShift, argCount); } argShift = 0; argsDbl = null; } IScriptable scope; if (idata.itsFunctionType != 0) { if (!idata.useDynamicScope) { scope = fnOrScript.ParentScope; } else { scope = callerScope; } if (useActivation) { scope = ScriptRuntime.createFunctionActivation (fnOrScript, scope, args); } } else { scope = callerScope; ScriptRuntime.initScript (fnOrScript, thisObj, cx, scope, fnOrScript.idata.evalScriptFlag); } if (idata.itsNestedFunctions != null) { if (idata.itsFunctionType != 0 && !idata.itsNeedsActivation) Context.CodeBug (); for (int i = 0; i < idata.itsNestedFunctions.Length; i++) { InterpreterData fdata = idata.itsNestedFunctions [i]; if (fdata.itsFunctionType == FunctionNode.FUNCTION_STATEMENT) { initFunction (cx, scope, fnOrScript, i); } } } IScriptable [] scriptRegExps = null; if (idata.itsRegExpLiterals != null) { // Wrapped regexps for functions are stored in // InterpretedFunction // but for script which should not contain references to scope // the regexps re-wrapped during each script execution if (idata.itsFunctionType != 0) { scriptRegExps = fnOrScript.functionRegExps; } else { scriptRegExps = fnOrScript.createRegExpWraps (cx, scope); } } // Initialize args, vars, locals and stack int emptyStackTop = idata.itsMaxVars + idata.itsMaxLocals - 1; int maxFrameArray = idata.itsMaxFrameArray; if (maxFrameArray != emptyStackTop + idata.itsMaxStack + 1) Context.CodeBug (); object [] stack; double [] sDbl; bool stackReuse; if (frame.stack != null && maxFrameArray <= frame.stack.Length) { // Reuse stacks from old frame stackReuse = true; stack = frame.stack; sDbl = frame.sDbl; } else { stackReuse = false; stack = new object [maxFrameArray]; sDbl = new double [maxFrameArray]; } int definedArgs = idata.argCount; if (definedArgs > argCount) { definedArgs = argCount; } // Fill the frame structure frame.parentFrame = parentFrame; frame.frameIndex = (parentFrame == null) ? 0 : parentFrame.frameIndex + 1; if (frame.frameIndex > cx.MaximumInterpreterStackDepth) throw ScriptRuntime.TypeErrorById ("msg.stackoverflow"); frame.frozen = false; frame.fnOrScript = fnOrScript; frame.idata = idata; frame.stack = stack; frame.sDbl = sDbl; frame.varSource = frame; frame.localShift = idata.itsMaxVars; frame.emptyStackTop = emptyStackTop; frame.debuggerFrame = debuggerFrame; frame.useActivation = useActivation; frame.thisObj = thisObj; frame.scriptRegExps = scriptRegExps; // Initialize initial values of variables that change during // interpretation. frame.result = Undefined.Value; frame.pc = 0; frame.pcPrevBranch = 0; frame.pcSourceLineStart = idata.firstLinePC; frame.scope = scope; frame.savedStackTop = emptyStackTop; frame.savedCallOp = 0; Array.Copy (args, argShift, stack, 0, definedArgs); if (argsDbl != null) { Array.Copy (argsDbl, argShift, sDbl, 0, definedArgs); } for (int i = definedArgs; i != idata.itsMaxVars; ++i) { stack [i] = Undefined.Value; } if (stackReuse) { // Clean the stack part and space beyond stack if any // of the old array to allow to GC objects there for (int i = emptyStackTop + 1; i != stack.Length; ++i) { stack [i] = null; } } EnterFrame (cx, frame, args); }
static int getExceptionHandler (CallFrame frame, bool onlyFinally) { int [] exceptionTable = frame.idata.itsExceptionTable; if (exceptionTable == null) { // No exception handlers return -1; } // Icode switch in the interpreter increments PC immediately // and it is necessary to subtract 1 from the saved PC // to point it before the start of the next instruction. int pc = frame.pc - 1; // OPT: use binary search int best = -1, bestStart = 0, bestEnd = 0; for (int i = 0; i != exceptionTable.Length; i += EXCEPTION_SLOT_SIZE) { int start = exceptionTable [i + EXCEPTION_TRY_START_SLOT]; int end = exceptionTable [i + EXCEPTION_TRY_END_SLOT]; if (!(start <= pc && pc < end)) { continue; } if (onlyFinally && exceptionTable [i + EXCEPTION_TYPE_SLOT] != 1) { continue; } if (best >= 0) { // Since handlers always nest and they never have shared end // although they can share start it is sufficient to compare // handlers ends if (bestEnd < end) { continue; } // Check the above assumption if (bestStart > start) Context.CodeBug (); // should be nested if (bestEnd == end) Context.CodeBug (); // no ens sharing } best = i; bestStart = start; bestEnd = end; } return best; }
internal static object Interpret (InterpretedFunction ifun, Context cx, IScriptable scope, IScriptable thisObj, object [] args) { using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier (128)) { if (!ScriptRuntime.hasTopCall (cx)) Context.CodeBug (); if (cx.interpreterSecurityDomain != ifun.securityDomain) { object savedDomain = cx.interpreterSecurityDomain; cx.interpreterSecurityDomain = ifun.securityDomain; try { return ifun.securityController.callWithDomain (ifun.securityDomain, cx, ifun, scope, thisObj, args); } finally { cx.interpreterSecurityDomain = savedDomain; } } CallFrame frame = new CallFrame (); initFrame (cx, scope, thisObj, args, null, 0, args.Length, ifun, null, frame); return InterpretLoop (cx, frame, (object)null); } }