internal ContinuationJump(NativeContinuation c, Interpreter.CallFrame current) { this.capturedFrame = (Interpreter.CallFrame)c.GetImplementation(); 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. Interpreter.CallFrame chain1 = this.capturedFrame; Interpreter.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) { Kit.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) { Kit.CodeBug(); } } }
public static object RestartContinuation(NativeContinuation c, Context cx, Scriptable scope, object[] args) { if (!ScriptRuntime.HasTopCall(cx)) { return ScriptRuntime.DoTopCall(c, cx, scope, null, args); } object arg; if (args.Length == 0) { arg = Undefined.instance; } else { arg = args[0]; } Interpreter.CallFrame capturedFrame = (Interpreter.CallFrame)c.GetImplementation(); if (capturedFrame == null) { // No frames to restart return arg; } Interpreter.ContinuationJump cjump = new Interpreter.ContinuationJump(c, null); cjump.result = arg; return InterpretLoop(cx, null, cjump); }