GetFinally() public method

public GetFinally ( ) : Node
return Node
示例#1
0
			/// <summary>Push a new try block onto the exception information stack.</summary>
			/// <remarks>Push a new try block onto the exception information stack.</remarks>
			/// <param name="node">
			/// an exception handling node (node.getType() ==
			/// Token.TRY)
			/// </param>
			internal virtual void PushExceptionInfo(Jump node)
			{
				Node fBlock = this._enclosing.GetFinallyAtTarget(node.GetFinally());
				BodyCodegen.ExceptionManager.ExceptionInfo ei = new BodyCodegen.ExceptionManager.ExceptionInfo(this, node, fBlock);
				this.exceptionInfo.Add(ei);
			}
示例#2
0
		private void VisitTryCatchFinally(Jump node, Node child)
		{
			// OPT we only need to do this if there are enclosed WITH
			// statements; could statically check and omit this if there aren't any.
			// XXX OPT Maybe instead do syntactic transforms to associate
			// each 'with' with a try/finally block that does the exitwith.
			short savedVariableObject = GetNewWordLocal();
			cfw.AddALoad(variableObjectLocal);
			cfw.AddAStore(savedVariableObject);
			int startLabel = cfw.AcquireLabel();
			cfw.MarkLabel(startLabel, (short)0);
			Node catchTarget = node.target;
			Node finallyTarget = node.GetFinally();
			int[] handlerLabels = new int[EXCEPTION_MAX];
			exceptionManager.PushExceptionInfo(node);
			if (catchTarget != null)
			{
				handlerLabels[JAVASCRIPT_EXCEPTION] = cfw.AcquireLabel();
				handlerLabels[EVALUATOR_EXCEPTION] = cfw.AcquireLabel();
				handlerLabels[ECMAERROR_EXCEPTION] = cfw.AcquireLabel();
				Context cx = Context.GetCurrentContext();
				if (cx != null && cx.HasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS))
				{
					handlerLabels[THROWABLE_EXCEPTION] = cfw.AcquireLabel();
				}
			}
			if (finallyTarget != null)
			{
				handlerLabels[FINALLY_EXCEPTION] = cfw.AcquireLabel();
			}
			exceptionManager.SetHandlers(handlerLabels, startLabel);
			// create a table for the equivalent of JSR returns
			if (isGenerator && finallyTarget != null)
			{
				BodyCodegen.FinallyReturnPoint ret = new BodyCodegen.FinallyReturnPoint();
				if (finallys == null)
				{
					finallys = new Dictionary<Node, BodyCodegen.FinallyReturnPoint>();
				}
				// add the finally target to hashtable
				finallys.Put(finallyTarget, ret);
				// add the finally node as well to the hash table
				finallys.Put(finallyTarget.GetNext(), ret);
			}
			while (child != null)
			{
				if (child == catchTarget)
				{
					int catchLabel = GetTargetLabel(catchTarget);
					exceptionManager.RemoveHandler(JAVASCRIPT_EXCEPTION, catchLabel);
					exceptionManager.RemoveHandler(EVALUATOR_EXCEPTION, catchLabel);
					exceptionManager.RemoveHandler(ECMAERROR_EXCEPTION, catchLabel);
					exceptionManager.RemoveHandler(THROWABLE_EXCEPTION, catchLabel);
				}
				GenerateStatement(child);
				child = child.GetNext();
			}
			// control flow skips the handlers
			int realEnd = cfw.AcquireLabel();
			cfw.Add(ByteCode.GOTO, realEnd);
			int exceptionLocal = GetLocalBlockRegister(node);
			// javascript handler; unwrap exception and GOTO to javascript
			// catch area.
			if (catchTarget != null)
			{
				// get the label to goto
				int catchLabel = catchTarget.LabelId();
				// If the function is a generator, then handlerLabels will consist
				// of zero labels. generateCatchBlock will create its own label
				// in this case. The extra parameter for the label is added for
				// the case of non-generator functions that inline finally blocks.
				GenerateCatchBlock(JAVASCRIPT_EXCEPTION, savedVariableObject, catchLabel, exceptionLocal, handlerLabels[JAVASCRIPT_EXCEPTION]);
				GenerateCatchBlock(EVALUATOR_EXCEPTION, savedVariableObject, catchLabel, exceptionLocal, handlerLabels[EVALUATOR_EXCEPTION]);
				GenerateCatchBlock(ECMAERROR_EXCEPTION, savedVariableObject, catchLabel, exceptionLocal, handlerLabels[ECMAERROR_EXCEPTION]);
				Context cx = Context.GetCurrentContext();
				if (cx != null && cx.HasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS))
				{
					GenerateCatchBlock(THROWABLE_EXCEPTION, savedVariableObject, catchLabel, exceptionLocal, handlerLabels[THROWABLE_EXCEPTION]);
				}
			}
			// finally handler; catch all exceptions, store to a local; JSR to
			// the finally, then re-throw.
			if (finallyTarget != null)
			{
				int finallyHandler = cfw.AcquireLabel();
				int finallyEnd = cfw.AcquireLabel();
				cfw.MarkHandler(finallyHandler);
				if (!isGenerator)
				{
					cfw.MarkLabel(handlerLabels[FINALLY_EXCEPTION]);
				}
				cfw.AddAStore(exceptionLocal);
				// reset the variable object local
				cfw.AddALoad(savedVariableObject);
				cfw.AddAStore(variableObjectLocal);
				// get the label to JSR to
				int finallyLabel = finallyTarget.LabelId();
				if (isGenerator)
				{
					AddGotoWithReturn(finallyTarget);
				}
				else
				{
					InlineFinally(finallyTarget, handlerLabels[FINALLY_EXCEPTION], finallyEnd);
				}
				// rethrow
				cfw.AddALoad(exceptionLocal);
				if (isGenerator)
				{
					cfw.Add(ByteCode.CHECKCAST, "java/lang/Throwable");
				}
				cfw.Add(ByteCode.ATHROW);
				cfw.MarkLabel(finallyEnd);
				// mark the handler
				if (isGenerator)
				{
					cfw.AddExceptionHandler(startLabel, finallyLabel, finallyHandler, null);
				}
			}
			// catch any
			ReleaseWordLocal(savedVariableObject);
			cfw.MarkLabel(realEnd);
			if (!isGenerator)
			{
				exceptionManager.PopExceptionInfo();
			}
		}