private static NativeContinuation CaptureContinuation(Context cx, Interpreter.CallFrame frame, bool requireContinuationsTopFrame) { NativeContinuation c = new NativeContinuation(); ScriptRuntime.SetObjectProtoAndParent(c, ScriptRuntime.GetTopCallScope(cx)); // Make sure that all frames are frozen Interpreter.CallFrame x = frame; Interpreter.CallFrame outermost = frame; 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; x.stackAttributes[i] = ScriptableObject.EMPTY; } 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) { Kit.CodeBug(); } } // the new operator uses stack top to store the constructed // object so it shall not be cleared: see comments in // setCallResult outermost = x; x = x.parentFrame; } if (requireContinuationsTopFrame) { while (outermost.parentFrame != null) { outermost = outermost.parentFrame; } if (!outermost.isContinuationsTopFrame) { throw new InvalidOperationException("Cannot capture continuation " + "from JavaScript code not called directly by " + "executeScriptWithContinuations or " + "callFunctionWithContinuations"); } } c.InitImplementation(frame); return c; }
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(); } } }
/// <summary>Construct a ContinuationPending exception.</summary> /// <remarks> /// Construct a ContinuationPending exception. Internal call only; /// users of the API should get continuations created on their behalf by /// calling /// <see cref="Context.ExecuteScriptWithContinuations(Script, Scriptable)">Context.ExecuteScriptWithContinuations(Script, Scriptable)</see> /// and /// <see cref="Context.CallFunctionWithContinuations(Callable, Scriptable, object[])">Context.CallFunctionWithContinuations(Callable, Scriptable, object[])</see> /// </remarks> /// <param name="continuationState">Internal Continuation object</param> internal ContinuationPending(NativeContinuation continuationState) { this.continuationState = continuationState; }
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); }
public static void Init(Context cx, Scriptable scope, bool @sealed) { NativeContinuation obj = new NativeContinuation(); obj.ExportAsJSClass(MAX_PROTOTYPE_ID, scope, @sealed); }