public MarkSequencePoint ( System document, Jurassic.Compiler.SourceCodeSpan span ) : void | ||
document | System | The document for which the sequence point is being defined. |
span | Jurassic.Compiler.SourceCodeSpan | The start and end positions which define the sequence point. |
리턴 | void |
/// <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) { // Generate code for the start of the statement. var statementLocals = new StatementLocals(); GenerateStartOfStatement(generator, optimizationInfo, statementLocals); foreach (var declaration in this.Declarations) { if (declaration.InitExpression != null) { // Create a new assignment expression and generate code for it. if (optimizationInfo.DebugDocument != null) { generator.MarkSequencePoint(optimizationInfo.DebugDocument, declaration.DebugInfo); } var initializationStatement = new ExpressionStatement( new AssignmentExpression(this.Scope, declaration.VariableName, declaration.InitExpression)); initializationStatement.GenerateCode(generator, optimizationInfo); } } // Generate code for the end of the statement. GenerateEndOfStatement(generator, optimizationInfo, statementLocals); }
/// <summary> /// Emits a sequence point, and sets the SourceSpan property. /// </summary> /// <param name="generator"> The IL generator used to emit the sequence point. </param> /// <param name="span"> The source code span. </param> public void MarkSequencePoint(ILGenerator generator, SourceCodeSpan span) { if (span == null) { throw new ArgumentNullException(nameof(span)); } if (this.DebugDocument != null) { generator.MarkSequencePoint(this.DebugDocument, span); } this.SourceSpan = span; }
/// <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) { // Generate code for the start of the statement. var statementLocals = new StatementLocals(); GenerateStartOfStatement(generator, optimizationInfo, statementLocals); foreach (var declaration in this.Declarations) { if (declaration.InitExpression != null) { // Create a new assignment expression and generate code for it. if (optimizationInfo.DebugDocument != null) generator.MarkSequencePoint(optimizationInfo.DebugDocument, declaration.DebugInfo); var initializationStatement = new ExpressionStatement( new AssignmentExpression(this.Scope, declaration.VariableName, declaration.InitExpression)); initializationStatement.GenerateCode(generator, optimizationInfo); } } // Generate code for the end of the statement. GenerateEndOfStatement(generator, optimizationInfo, statementLocals); }
/// <summary> /// Generates CIL for the start of every 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> /// <param name="locals"> Variables common to both GenerateStartOfStatement() and GenerateEndOfStatement(). </param> public void GenerateStartOfStatement(ILGenerator generator, OptimizationInfo optimizationInfo, StatementLocals locals) { #if DEBUG && !SILVERLIGHT // Statements must not produce or consume any values on the stack. if (generator is DynamicILGenerator) { locals.OriginalStackSize = ((DynamicILGenerator)generator).StackSize; } #endif if (locals.NonDefaultBreakStatementBehavior == false && this.HasLabels == true) { // Set up the information needed by the break statement. locals.EndOfStatement = generator.CreateLabel(); optimizationInfo.PushBreakOrContinueInfo(this.Labels, locals.EndOfStatement, null, labelledOnly: true); } // Emit debugging information. if (locals.NonDefaultDebugInfoBehavior == false && optimizationInfo.DebugDocument != null && this.DebugInfo != null) { generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.DebugInfo); } }
/// <summary> /// Generates CIL for the start of every 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> /// <param name="locals"> Variables common to both GenerateStartOfStatement() and GenerateEndOfStatement(). </param> public void GenerateStartOfStatement(ILGenerator generator, OptimizationInfo optimizationInfo, StatementLocals locals) { #if DEBUG && !SILVERLIGHT // Statements must not produce or consume any values on the stack. if (generator is DynamicILGenerator) locals.OriginalStackSize = ((DynamicILGenerator)generator).StackSize; #endif if (locals.NonDefaultBreakStatementBehavior == false && this.HasLabels == true) { // Set up the information needed by the break statement. locals.EndOfStatement = generator.CreateLabel(); optimizationInfo.PushBreakOrContinueInfo(this.Labels, locals.EndOfStatement, null, labelledOnly: true); } // Emit debugging information. if (locals.NonDefaultDebugInfoBehavior == false && optimizationInfo.DebugDocument != null && this.DebugInfo != null) generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.DebugInfo); }
/// <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) { // Generate code for the start of the statement. var statementLocals = new StatementLocals() { NonDefaultBreakStatementBehavior = true, NonDefaultSourceSpanBehavior = true }; GenerateStartOfStatement(generator, optimizationInfo, statementLocals); // Construct a loop expression. // var iterator = TypeUtilities.GetIterator(obj); // while (true) { // continue-target: // if (enumerator.MoveNext() == false) // goto break-target; // lhs = enumerator.Current; // // <body statements> // } // break-target: // Call: ObjectInstance GetIterator(ScriptEngine engine, ObjectInstance iterable) // Then call: IEnumerable<object> Iterate(ScriptEngine engine, ObjectInstance iterator) optimizationInfo.MarkSequencePoint(generator, this.TargetObjectSourceSpan); EmitHelpers.LoadScriptEngine(generator); this.TargetObject.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, this.TargetObject.ResultType); generator.Call(ReflectionHelpers.TypeUtilities_ForOf); // Call IEnumerable<object>.GetEnumerator() generator.Call(ReflectionHelpers.IEnumerable_Object_GetEnumerator); // Store the enumerator in a temporary variable. var enumerator = generator.CreateTemporaryVariable(typeof(IEnumerator <object>)); 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.GenerateReference(generator, optimizationInfo); generator.LoadVariable(enumerator); generator.Call(ReflectionHelpers.IEnumerator_Object_Current); this.Variable.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false); // Emit the body statement(s). optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget, continueTarget, labelledOnly: false); this.Body.GenerateCode(generator, optimizationInfo); optimizationInfo.PopBreakOrContinueInfo(); generator.Branch(continueTarget); generator.DefineLabelPosition(breakTarget); // Generate code for the end of the statement. GenerateEndOfStatement(generator, optimizationInfo, statementLocals); }
/// <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) { // Generate code for the start of the statement. var statementLocals = new StatementLocals() { NonDefaultBreakStatementBehavior = true, NonDefaultDebugInfoBehavior = true }; GenerateStartOfStatement(generator, optimizationInfo, statementLocals); // <initializer> // if (<condition>) // { // <loop body> // <increment> // while (true) { // if (<condition> == false) // break; // // <body statements> // // continue-target: // <increment> // } // } // break-target: // Set up some labels. var continueTarget = generator.CreateLabel(); var breakTarget1 = generator.CreateLabel(); var breakTarget2 = generator.CreateLabel(); // Emit the initialization statement. if (this.InitStatement != null) { this.InitStatement.GenerateCode(generator, optimizationInfo); } // Check the condition and jump to the end if it is false. if (this.CheckConditionAtEnd == false && this.ConditionStatement != null) { #if !XBOX if (optimizationInfo.DebugDocument != null) { generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.ConditionStatement.DebugInfo); } #endif this.Condition.GenerateCode(generator, optimizationInfo); EmitConversion.ToBool(generator, this.Condition.ResultType); generator.BranchIfFalse(breakTarget1); } // Emit the loop body. optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget1, continueTarget, false); this.Body.GenerateCode(generator, optimizationInfo); optimizationInfo.PopBreakOrContinueInfo(); // Increment the loop variable. if (this.IncrementStatement != null) { this.IncrementStatement.GenerateCode(generator, optimizationInfo); } // Strengthen the variable types. List <KeyValuePair <Scope.DeclaredVariable, RevertInfo> > previousVariableTypes = null; var previousInsideTryCatchOrFinally = optimizationInfo.InsideTryCatchOrFinally; if (optimizationInfo.OptimizeInferredTypes == true) { // Keep a record of the variable types before strengthening. previousVariableTypes = new List <KeyValuePair <Scope.DeclaredVariable, RevertInfo> >(); var typedVariables = FindTypedVariables(); foreach (var variableAndType in typedVariables) { var variable = variableAndType.Key; var variableInfo = variableAndType.Value; if (variableInfo.Conditional == false && variableInfo.Type != variable.Type) { // Save the previous type so we can restore it later. var previousType = variable.Type; previousVariableTypes.Add(new KeyValuePair <Scope.DeclaredVariable, RevertInfo>(variable, new RevertInfo() { Type = previousType, Variable = variable.Store })); // Load the existing value. var nameExpression = new NameExpression(variable.Scope, variable.Name); nameExpression.GenerateGet(generator, optimizationInfo, false); // Store the typed value. variable.Store = generator.DeclareVariable(variableInfo.Type); variable.Type = variableInfo.Type; nameExpression.GenerateSet(generator, optimizationInfo, previousType, false); } } // The variables must be reverted even in the presence of exceptions. if (previousVariableTypes.Count > 0) { generator.BeginExceptionBlock(); // Setting the InsideTryCatchOrFinally flag converts BR instructions into LEAVE // instructions so that the finally block is executed correctly. optimizationInfo.InsideTryCatchOrFinally = true; } } // The inner loop starts here. var startOfLoop = generator.DefineLabelPosition(); // Check the condition and jump to the end if it is false. if (this.ConditionStatement != null) { #if !XBOX if (optimizationInfo.DebugDocument != null) { generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.ConditionStatement.DebugInfo); } #endif this.Condition.GenerateCode(generator, optimizationInfo); EmitConversion.ToBool(generator, this.Condition.ResultType); generator.BranchIfFalse(breakTarget2); } // Emit the loop body. optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget2, continueTarget, labelledOnly: false); this.Body.GenerateCode(generator, optimizationInfo); optimizationInfo.PopBreakOrContinueInfo(); // The continue statement jumps here. generator.DefineLabelPosition(continueTarget); // Increment the loop variable. if (this.IncrementStatement != null) { this.IncrementStatement.GenerateCode(generator, optimizationInfo); } // Unconditionally branch back to the start of the loop. generator.Branch(startOfLoop); // Define the end of the loop (actually just after). generator.DefineLabelPosition(breakTarget2); // Revert the variable types. if (previousVariableTypes != null && previousVariableTypes.Count > 0) { // Revert the InsideTryCatchOrFinally flag. optimizationInfo.InsideTryCatchOrFinally = previousInsideTryCatchOrFinally; // Revert the variable types within a finally block. generator.BeginFinallyBlock(); foreach (var previousVariableAndType in previousVariableTypes) { var variable = previousVariableAndType.Key; var variableRevertInfo = previousVariableAndType.Value; // Load the existing value. var nameExpression = new NameExpression(variable.Scope, variable.Name); nameExpression.GenerateGet(generator, optimizationInfo, false); // Store the typed value. var previousType = variable.Type; variable.Store = variableRevertInfo.Variable; variable.Type = variableRevertInfo.Type; nameExpression.GenerateSet(generator, optimizationInfo, previousType, false); } // End the exception block. generator.EndExceptionBlock(); } // Define the end of the loop (actually just after). generator.DefineLabelPosition(breakTarget1); // Generate code for the end of the statement. GenerateEndOfStatement(generator, optimizationInfo, statementLocals); }
/// <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) { // Generate code for the start of the statement. var statementLocals = new StatementLocals() { NonDefaultBreakStatementBehavior = true, NonDefaultDebugInfoBehavior = true }; GenerateStartOfStatement(generator, optimizationInfo, statementLocals); // 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) EmitHelpers.LoadScriptEngine(generator); this.TargetObject.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, this.TargetObject.ResultType); generator.Call(ReflectionHelpers.TypeUtilities_EnumeratePropertyNames); // Call IEnumerable<string>.GetEnumerator() generator.Call(ReflectionHelpers.IEnumerable_GetEnumerator); // 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(); #if !XBOX // Emit debugging information. if (optimizationInfo.DebugDocument != null) generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.VariableDebugInfo); #endif // if (enumerator.MoveNext() == false) // goto break-target; generator.LoadVariable(enumerator); generator.Call(ReflectionHelpers.IEnumerator_MoveNext); generator.BranchIfFalse(breakTarget); // lhs = enumerator.Current; generator.LoadVariable(enumerator); generator.Call(ReflectionHelpers.IEnumerator_Current); this.Variable.GenerateSet(generator, optimizationInfo, PrimitiveType.String, false); // Emit the body statement(s). optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget, continueTarget, labelledOnly: false); this.Body.GenerateCode(generator, optimizationInfo); optimizationInfo.PopBreakOrContinueInfo(); generator.Branch(continueTarget); generator.DefineLabelPosition(breakTarget); // Generate code for the end of the statement. GenerateEndOfStatement(generator, optimizationInfo, statementLocals); }
/// <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) { // Generate code for the start of the statement. var statementLocals = new StatementLocals() { NonDefaultBreakStatementBehavior = true, NonDefaultDebugInfoBehavior = true }; GenerateStartOfStatement(generator, optimizationInfo, statementLocals); // <initializer> // if (<condition>) // { // <loop body> // <increment> // while (true) { // if (<condition> == false) // break; // // <body statements> // // continue-target: // <increment> // } // } // break-target: // Set up some labels. var continueTarget = generator.CreateLabel(); var breakTarget1 = generator.CreateLabel(); var breakTarget2 = generator.CreateLabel(); // Emit the initialization statement. if (this.InitStatement != null) this.InitStatement.GenerateCode(generator, optimizationInfo); // Check the condition and jump to the end if it is false. if (this.CheckConditionAtEnd == false && this.ConditionStatement != null) { #if !XBOX if (optimizationInfo.DebugDocument != null) generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.ConditionStatement.DebugInfo); #endif this.Condition.GenerateCode(generator, optimizationInfo); EmitConversion.ToBool(generator, this.Condition.ResultType); generator.BranchIfFalse(breakTarget1); } // Emit the loop body. optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget1, continueTarget, false); this.Body.GenerateCode(generator, optimizationInfo); optimizationInfo.PopBreakOrContinueInfo(); // Increment the loop variable. if (this.IncrementStatement != null) this.IncrementStatement.GenerateCode(generator, optimizationInfo); // Strengthen the variable types. List<KeyValuePair<Scope.DeclaredVariable, RevertInfo>> previousVariableTypes = null; var previousInsideTryCatchOrFinally = optimizationInfo.InsideTryCatchOrFinally; if (optimizationInfo.OptimizeInferredTypes == true) { // Keep a record of the variable types before strengthening. previousVariableTypes = new List<KeyValuePair<Scope.DeclaredVariable, RevertInfo>>(); var typedVariables = FindTypedVariables(); foreach (var variableAndType in typedVariables) { var variable = variableAndType.Key; var variableInfo = variableAndType.Value; if (variableInfo.Conditional == false && variableInfo.Type != variable.Type) { // Save the previous type so we can restore it later. var previousType = variable.Type; previousVariableTypes.Add(new KeyValuePair<Scope.DeclaredVariable, RevertInfo>(variable, new RevertInfo() { Type = previousType, Variable = variable.Store })); // Load the existing value. var nameExpression = new NameExpression(variable.Scope, variable.Name); nameExpression.GenerateGet(generator, optimizationInfo, false); // Store the typed value. variable.Store = generator.DeclareVariable(variableInfo.Type); variable.Type = variableInfo.Type; nameExpression.GenerateSet(generator, optimizationInfo, previousType, false); } } // The variables must be reverted even in the presence of exceptions. if (previousVariableTypes.Count > 0) { generator.BeginExceptionBlock(); // Setting the InsideTryCatchOrFinally flag converts BR instructions into LEAVE // instructions so that the finally block is executed correctly. optimizationInfo.InsideTryCatchOrFinally = true; } } // The inner loop starts here. var startOfLoop = generator.DefineLabelPosition(); // Check the condition and jump to the end if it is false. if (this.ConditionStatement != null) { #if !XBOX if (optimizationInfo.DebugDocument != null) generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.ConditionStatement.DebugInfo); #endif this.Condition.GenerateCode(generator, optimizationInfo); EmitConversion.ToBool(generator, this.Condition.ResultType); generator.BranchIfFalse(breakTarget2); } // Emit the loop body. optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget2, continueTarget, labelledOnly: false); this.Body.GenerateCode(generator, optimizationInfo); optimizationInfo.PopBreakOrContinueInfo(); // The continue statement jumps here. generator.DefineLabelPosition(continueTarget); // Increment the loop variable. if (this.IncrementStatement != null) this.IncrementStatement.GenerateCode(generator, optimizationInfo); // Unconditionally branch back to the start of the loop. generator.Branch(startOfLoop); // Define the end of the loop (actually just after). generator.DefineLabelPosition(breakTarget2); // Revert the variable types. if (previousVariableTypes != null && previousVariableTypes.Count > 0) { // Revert the InsideTryCatchOrFinally flag. optimizationInfo.InsideTryCatchOrFinally = previousInsideTryCatchOrFinally; // Revert the variable types within a finally block. generator.BeginFinallyBlock(); foreach (var previousVariableAndType in previousVariableTypes) { var variable = previousVariableAndType.Key; var variableRevertInfo = previousVariableAndType.Value; // Load the existing value. var nameExpression = new NameExpression(variable.Scope, variable.Name); nameExpression.GenerateGet(generator, optimizationInfo, false); // Store the typed value. var previousType = variable.Type; variable.Store = variableRevertInfo.Variable; variable.Type = variableRevertInfo.Type; nameExpression.GenerateSet(generator, optimizationInfo, previousType, false); } // End the exception block. generator.EndExceptionBlock(); } // Define the end of the loop (actually just after). generator.DefineLabelPosition(breakTarget1); // Generate code for the end of the statement. GenerateEndOfStatement(generator, optimizationInfo, statementLocals); }
/// <summary> /// Emits a sequence point, and sets the SourceSpan property. /// </summary> /// <param name="generator"> The IL generator used to emit the sequence point. </param> /// <param name="span"> The source code span. </param> public void MarkSequencePoint(ILGenerator generator, SourceCodeSpan span) { if (span == null) throw new ArgumentNullException("span"); if (this.DebugDocument != null) generator.MarkSequencePoint(this.DebugDocument, span); this.SourceSpan = span; }