Esempio n. 1
0
        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;
        }
Esempio n. 2
0
        /// <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;
        }
Esempio n. 3
0
        /// <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;
        }
Esempio n. 4
0
        /// <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;
        }
Esempio n. 5
0
        /// <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;
        }
Esempio n. 6
0
        /// <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;
        }
Esempio n. 7
0
        /// <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);
        }