public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Get the previous root - we'll be changing it: Expression prevRoot = optimizationInfo.RootExpression; // Labelled is now the root: Labelled.SetRoot(optimizationInfo); if (Labelled.DefaultBreakStatementBehaviour) { // Set up the information needed by the break statement. ILLabel endOfStatement = generator.CreateLabel(); optimizationInfo.PushBreakOrContinueInfo(labels, endOfStatement, null, true); Labelled.GenerateCode(generator, optimizationInfo); // Revert the information needed by the break statement. generator.DefineLabelPosition(endOfStatement); optimizationInfo.PopBreakOrContinueInfo(); } else { // Loop, For-In, For-Of or Switch only. optimizationInfo.Labels = labels; Labelled.GenerateCode(generator, optimizationInfo); } // Restore root: optimizationInfo.RootExpression = prevRoot; }
/// <summary> /// Generates CIL for the statement. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Get the previous root - we'll be changing it: Expression prevRoot = optimizationInfo.RootExpression; // Set as root: Body.SetRoot(optimizationInfo); // Generate code for the body statements. Body.GenerateCode(generator, optimizationInfo); // Restore root: optimizationInfo.RootExpression = prevRoot; }
/// <summary> /// Generates CIL for the statement. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Parent root: Expression rootExpression = optimizationInfo.RootExpression; int max = Statements.Count; for (int i = 0; i < max; i++) { // Generate code for the statement. Statement statement = Statements[i]; // Apply the root: statement.SetRoot(optimizationInfo); // Generate the code: statement.GenerateCode(generator, optimizationInfo); } // Restore root: optimizationInfo.RootExpression = rootExpression; }
/// <summary> /// Generates CIL for the statement. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Get the previous root - we'll be changing it: Expression prevRoot = optimizationInfo.RootExpression; // Unlike in .NET, in javascript there are no restrictions on what can appear inside // try, catch and finally blocks. The one restriction which causes problems is the // inability to jump out of .NET finally blocks. This is required when break, continue // or return statements appear inside of a finally block. To work around this, when // inside a finally block these instructions throw an exception instead. // Setting the InsideTryCatchOrFinally flag converts BR instructions into LEAVE // instructions so that the finally block is executed correctly. var previousInsideTryCatchOrFinally = optimizationInfo.InsideTryCatchOrFinally; optimizationInfo.InsideTryCatchOrFinally = true; // Finally requires two exception nested blocks. if (this.FinallyBlock != null) { generator.BeginExceptionBlock(); } // Begin the exception block. generator.BeginExceptionBlock(); // Generate code for the try block. It's now the root. TryBlock.SetRoot(optimizationInfo); TryBlock.GenerateCode(generator, optimizationInfo); // Generate code for the catch block. if (this.CatchBlock != null) { // Begin a catch block. The exception is on the top of the stack. generator.BeginCatchBlock(typeof(Exception)); var catchVariable = new NameExpression(this.CatchScope, this.CatchVariableName); catchVariable.ApplyType(optimizationInfo, typeof(Exception)); catchVariable.GenerateSet(generator, optimizationInfo, false, typeof(Exception), delegate(bool two){ // Note that we always do nothing here. The value is already on the stack. }, false); // Emit code for the statements within the catch block. It's now the root. CatchBlock.SetRoot(optimizationInfo); CatchBlock.GenerateCode(generator, optimizationInfo); } // Generate code for the finally block. if (this.FinallyBlock != null) { generator.BeginFinallyBlock(); var branches = new List <ILLabel>(); var previousStackSize = optimizationInfo.LongJumpStackSizeThreshold; optimizationInfo.LongJumpStackSizeThreshold = optimizationInfo.BreakOrContinueStackSize; var previousCallback = optimizationInfo.LongJumpCallback; optimizationInfo.LongJumpCallback = delegate(ILGenerator generator2, ILLabel label) { // It is not possible to branch out of a finally block - therefore instead of // generating LEAVE instructions we throw an exception then catch it to transfer // control out of the finally block. generator2.LoadInt32(branches.Count); generator2.NewObject(ReflectionHelpers.LongJumpException_Constructor); generator2.Throw(); // Record any branches that are made within the finally code. branches.Add(label); }; // Emit code for the finally block. It's now the root. FinallyBlock.SetRoot(optimizationInfo); this.FinallyBlock.GenerateCode(generator, optimizationInfo); // End the main exception block. generator.EndExceptionBlock(); // Begin a catch block to catch any LongJumpExceptions. The exception object is on // the top of the stack. generator.BeginCatchBlock(typeof(LongJumpException)); if (branches.Count > 0) { // switch (exception.RouteID) // { // case 0: goto label1; // case 1: goto label2; // } ILLabel[] switchLabels = new ILLabel[branches.Count]; for (int i = 0; i < branches.Count; i++) { switchLabels[i] = generator.CreateLabel(); } generator.LoadField(ReflectionHelpers.LongJumpException_RouteID); generator.Switch(switchLabels); for (int i = 0; i < branches.Count; i++) { generator.DefineLabelPosition(switchLabels[i]); generator.Leave(branches[i]); } } // Reset the state we clobbered. optimizationInfo.LongJumpStackSizeThreshold = previousStackSize; optimizationInfo.LongJumpCallback = previousCallback; } // End the exception block. generator.EndExceptionBlock(); // Reset the InsideTryCatchOrFinally flag. optimizationInfo.InsideTryCatchOrFinally = previousInsideTryCatchOrFinally; // Restore root: optimizationInfo.RootExpression = prevRoot; }
/// <summary> /// Generates CIL for the statement. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Get the previous root - we'll be changing it: Expression prevRoot = optimizationInfo.RootExpression; List <string> labels = optimizationInfo.Labels; optimizationInfo.Labels = null; // Construct a loop expression. // var enumerator = TypeUtilities.EnumeratePropertyNames(rhs).GetEnumerator(); // while (true) { // continue-target: // if (enumerator.MoveNext() == false) // goto break-target; // lhs = enumerator.Current; // // <body statements> // } // break-target: // Call IEnumerable<string> EnumeratePropertyNames(ScriptEngine engine, object obj) // optimizationInfo.MarkSequencePoint(generator, this.TargetObjectSourceSpan); EmitHelpers.LoadEngine(generator); this.TargetObject.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, this.TargetObject.GetResultType(optimizationInfo)); generator.Call(ReflectionHelpers.TypeUtilities_EnumeratePropertyNames); // Store the enumerator in a temporary variable. var enumerator = generator.CreateTemporaryVariable(typeof(IEnumerator <string>)); generator.StoreVariable(enumerator); var breakTarget = generator.CreateLabel(); var continueTarget = generator.DefineLabelPosition(); // Emit debugging information. // if (optimizationInfo.DebugDocument != null) // generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.VariableSourceSpan); // if (enumerator.MoveNext() == false) // goto break-target; generator.LoadVariable(enumerator); generator.Call(ReflectionHelpers.IEnumerator_MoveNext); generator.BranchIfFalse(breakTarget); // lhs = enumerator.Current; this.Variable.GenerateSet(generator, optimizationInfo, false, typeof(string), delegate(bool two){ generator.LoadVariable(enumerator); generator.Call(ReflectionHelpers.IEnumerator_Current); if (two) { generator.Duplicate(); } }, false); // Emit the body statement(s). optimizationInfo.PushBreakOrContinueInfo(labels, breakTarget, continueTarget, false); // Mark the body as root: Body.SetRoot(optimizationInfo); Body.GenerateCode(generator, optimizationInfo); optimizationInfo.PopBreakOrContinueInfo(); generator.Branch(continueTarget); generator.DefineLabelPosition(breakTarget); // Restore root: optimizationInfo.RootExpression = prevRoot; }
/// <summary> /// Generates CIL for the statement. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Get the root: Expression prevRoot = optimizationInfo.RootExpression; // Is the condition constant? if (StaticResult != null) { // We have a compile-time constant (i.e. if(true) ) // Convert it to a bool: bool result = TypeConverter.ToBoolean(StaticResult); if (result) { // if(true) // Generate code for the if clause which is now the root: IfClause.SetRoot(optimizationInfo); IfClause.GenerateCode(generator, optimizationInfo); } else { // if(false) if (ElseClause != null) { // It's now the root: ElseClause.SetRoot(optimizationInfo); // Code for the else clause: ElseClause.GenerateCode(generator, optimizationInfo); } } // Restore root: optimizationInfo.RootExpression = prevRoot; return; } // Generate code for the condition and coerce to a boolean. this.Condition.GenerateCode(generator, optimizationInfo); EmitConversion.ToBool(generator, this.Condition.GetResultType(optimizationInfo)); // We will need a label at the end of the if statement. var endOfEverything = generator.CreateLabel(); if (this.ElseClause == null) { // Jump to the end if the condition is false. generator.BranchIfFalse(endOfEverything); // If clause is now the root: IfClause.SetRoot(optimizationInfo); // Generate code for the if clause. IfClause.GenerateCode(generator, optimizationInfo); } else { // Branch to the else clause if the condition is false. var startOfElseClause = generator.CreateLabel(); generator.BranchIfFalse(startOfElseClause); // If clause is now the root: IfClause.SetRoot(optimizationInfo); // Generate code for the if clause. IfClause.GenerateCode(generator, optimizationInfo); // Branch to the end of the if statement. generator.Branch(endOfEverything); // Else clause is now the root: ElseClause.SetRoot(optimizationInfo); // Generate code for the else clause. generator.DefineLabelPosition(startOfElseClause); ElseClause.GenerateCode(generator, optimizationInfo); } // Define the label at the end of the if statement. generator.DefineLabelPosition(endOfEverything); // Restore root: optimizationInfo.RootExpression = prevRoot; }
/// <summary> /// Generates CIL for the statement. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Get the previous root - we'll be changing it: Expression prevRoot = optimizationInfo.RootExpression; List <string> labels = optimizationInfo.Labels; optimizationInfo.Labels = null; // Emit the initialization statement. if (InitStatement != null) { // Init isn't in use. Mark it as root: InitStatement.SetRoot(optimizationInfo); InitStatement.GenerateCode(generator, optimizationInfo); // Restore root: optimizationInfo.RootExpression = prevRoot; } var startOfLoop = generator.DefineLabelPosition(); var continueTarget = generator.CreateLabel(); var endOfLoop = generator.CreateLabel(); bool conditionAtEnd = CheckConditionAtEnd; // AT END.. // top: // <body statements> // continue: // <increment> // if(condition) // <goto top> // break: // top: // if(!condition) // <goto break> // <body statements> // continue: // <increment> // <goto top> // break: if (!conditionAtEnd) { if (ConditionStatement != null) { Condition.GenerateCode(generator, optimizationInfo); EmitConversion.ToBool(generator, Condition.GetResultType(optimizationInfo)); generator.BranchIfFalse(endOfLoop); } } // Emit the loop body. optimizationInfo.PushBreakOrContinueInfo(labels, endOfLoop, continueTarget, false); // Mark the body as root: Body.SetRoot(optimizationInfo); Body.GenerateCode(generator, optimizationInfo); optimizationInfo.PopBreakOrContinueInfo(); generator.DefineLabelPosition(continueTarget); // Increment the loop variable. if (IncrementStatement != null) { // Increment isn't in use. Mark it as root: IncrementStatement.SetRoot(optimizationInfo); IncrementStatement.GenerateCode(generator, optimizationInfo); } // Restore root: optimizationInfo.RootExpression = prevRoot; if (conditionAtEnd) { if (ConditionStatement != null) { // Emit now: Condition.GenerateCode(generator, optimizationInfo); EmitConversion.ToBool(generator, Condition.GetResultType(optimizationInfo)); generator.BranchIfTrue(startOfLoop); } } else { generator.Branch(startOfLoop); } generator.DefineLabelPosition(endOfLoop); }