本文整理汇总了C#中Jurassic.Compiler.ILGenerator.Branch方法的典型用法代码示例。如果您正苦于以下问题:C# ILGenerator.Branch方法的具体用法?C# ILGenerator.Branch怎么用?C# ILGenerator.Branch使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Jurassic.Compiler.ILGenerator
的用法示例。
在下文中一共展示了ILGenerator.Branch方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: GenerateCode
/// <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);
// Generate code for the condition and coerce to a boolean.
this.Condition.GenerateCode(generator, optimizationInfo);
EmitConversion.ToBool(generator, this.Condition.ResultType);
// 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);
// Generate code for the if clause.
this.IfClause.GenerateCode(generator, optimizationInfo);
}
else
{
// Branch to the else clause if the condition is false.
var startOfElseClause = generator.CreateLabel();
generator.BranchIfFalse(startOfElseClause);
// Generate code for the if clause.
this.IfClause.GenerateCode(generator, optimizationInfo);
// Branch to the end of the if statement.
generator.Branch(endOfEverything);
// Generate code for the else clause.
generator.DefineLabelPosition(startOfElseClause);
this.ElseClause.GenerateCode(generator, optimizationInfo);
}
// Define the label at the end of the if statement.
generator.DefineLabelPosition(endOfEverything);
// Generate code for the end of the statement.
GenerateEndOfStatement(generator, optimizationInfo, statementLocals);
}
示例2: GenerateGet
/// <summary>
/// Pushes the value of the reference onto the stack.
/// </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="throwIfUnresolvable"> <c>true</c> to throw a ReferenceError exception if
/// the name is unresolvable; <c>false</c> to output <c>null</c> instead. </param>
public void GenerateGet(ILGenerator generator, OptimizationInfo optimizationInfo, bool throwIfUnresolvable)
{
string propertyName = null;
bool isArrayIndex = false;
// Right-hand-side can be a property name (a.b)
if (this.OperatorType == OperatorType.MemberAccess)
{
var rhs = this.GetOperand(1) as NameExpression;
if (rhs == null)
throw new JavaScriptException(optimizationInfo.Engine, "SyntaxError", "Invalid member access", optimizationInfo.SourceSpan.StartLine, optimizationInfo.Source.Path, optimizationInfo.FunctionName);
propertyName = rhs.Name;
}
// Or a constant indexer (a['b'])
if (this.OperatorType == OperatorType.Index)
{
var rhs = this.GetOperand(1) as LiteralExpression;
if (rhs != null && (PrimitiveTypeUtilities.IsNumeric(rhs.ResultType) || rhs.ResultType == PrimitiveType.String))
{
propertyName = TypeConverter.ToString(rhs.Value);
// Or a array index (a[0])
if (rhs.ResultType == PrimitiveType.Int32 || (propertyName != null && Library.ArrayInstance.ParseArrayIndex(propertyName) != uint.MaxValue))
isArrayIndex = true;
}
}
if (isArrayIndex == true)
{
// Array indexer
// -------------
// xxx = object[index]
// Load the left-hand side and convert to an object instance.
var lhs = this.GetOperand(0);
lhs.GenerateCode(generator, optimizationInfo);
EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);
// Load the right-hand side and convert to a uint32.
var rhs = this.GetOperand(1);
rhs.GenerateCode(generator, optimizationInfo);
EmitConversion.ToUInt32(generator, rhs.ResultType);
// Call the indexer.
generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_Int);
}
else if (propertyName != null)
{
//// Load the left-hand side and convert to an object instance.
//var lhs = this.GetOperand(0);
//lhs.GenerateCode(generator, optimizationInfo);
//EmitConversion.ToObject(generator, lhs.ResultType);
//// Call Get(string)
//generator.LoadString(propertyName);
//generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_String);
// Named property access (e.g. x = y.property)
// -------------------------------------------
// __object_cacheKey = null;
// __object_property_cachedIndex = 0;
// ...
// if (__object_cacheKey != object.InlineCacheKey)
// xxx = object.InlineGetPropertyValue("property", out __object_property_cachedIndex, out __object_cacheKey)
// else
// xxx = object.InlinePropertyValues[__object_property_cachedIndex];
// Load the left-hand side and convert to an object instance.
var lhs = this.GetOperand(0);
lhs.GenerateCode(generator, optimizationInfo);
EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);
// TODO: share these variables somehow.
var cacheKey = generator.DeclareVariable(typeof(object));
var cachedIndex = generator.DeclareVariable(typeof(int));
// Store the object into a temp variable.
var objectInstance = generator.DeclareVariable(PrimitiveType.Object);
generator.StoreVariable(objectInstance);
// if (__object_cacheKey != object.InlineCacheKey)
generator.LoadVariable(cacheKey);
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlineCacheKey);
var elseClause = generator.CreateLabel();
generator.BranchIfEqual(elseClause);
// value = object.InlineGetProperty("property", out __object_property_cachedIndex, out __object_cacheKey)
generator.LoadVariable(objectInstance);
generator.LoadString(propertyName);
//.........这里部分代码省略.........
示例3: GenerateCode
/// <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);
}
示例4: GenerateCode
/// <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);
// <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)
{
optimizationInfo.MarkSequencePoint(generator, this.ConditionStatement.SourceSpan);
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.
//.........这里部分代码省略.........
示例5: GenerateSet
//.........这里部分代码省略.........
// The variable exists, but is read-only.
// Pop the value off the stack (if it is still there).
if (value == null)
generator.Pop();
}
// The variable was found - no need to search any more parent scopes.
break;
}
else
{
// The variable was not defined at compile time, but may have been
// introduced by an eval() statement.
if (optimizationInfo.MethodOptimizationHints.HasEval == true)
{
if (value == null)
{
// The value to store is on the top of the stack - convert it to an
// object and store it in a temporary variable.
EmitConversion.Convert(generator, valueType, PrimitiveType.Any, optimizationInfo);
value = generator.CreateTemporaryVariable(typeof(object));
generator.StoreVariable(value);
}
// Check the variable exists: if (scope.HasValue(variableName) == true) {
if (scopeVariable == null)
EmitHelpers.LoadScope(generator);
else
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.Scope_HasValue);
var hasValueClause = generator.CreateLabel();
generator.BranchIfFalse(hasValueClause);
// Set the value of the variable.
if (scopeVariable == null)
EmitHelpers.LoadScope(generator);
else
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.LoadVariable(value);
generator.Call(ReflectionHelpers.Scope_SetValue);
generator.Branch(endOfSet);
// }
generator.DefineLabelPosition(hasValueClause);
}
}
}
else
{
if (value == null)
{
// The value to store is on the top of the stack - convert it to an
// object and store it in a temporary variable.
EmitConversion.Convert(generator, valueType, PrimitiveType.Any, optimizationInfo);
value = generator.CreateTemporaryVariable(typeof(object));
generator.StoreVariable(value);
}
if (scope.ParentScope == null)
{
// Optimization: if this is the global scope, use hidden classes to
// optimize variable access.
示例6: GenerateSet
//.........这里部分代码省略.........
// Call the indexer.
generator.LoadVariable(value);
generator.LoadBoolean(optimizationInfo.StrictMode);
generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_Int);
}
else if (propertyName != null)
{
//// Load the left-hand side and convert to an object instance.
//var lhs = this.GetOperand(0);
//lhs.GenerateCode(generator, optimizationInfo);
//EmitConversion.ToObject(generator, lhs.ResultType);
//// Call the indexer.
//generator.LoadString(propertyName);
//generator.LoadVariable(value);
//generator.LoadBoolean(optimizationInfo.StrictMode);
//generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_String);
// Named property modification (e.g. x.property = y)
// -------------------------------------------------
// __object_cacheKey = null;
// __object_property_cachedIndex = 0;
// ...
// if (__object_cacheKey != object.InlineCacheKey)
// object.InlineSetPropertyValue("property", value, strictMode, out __object_property_cachedIndex, out __object_cacheKey)
// else
// object.InlinePropertyValues[__object_property_cachedIndex] = value;
// Load the left-hand side and convert to an object instance.
var lhs = this.GetOperand(0);
lhs.GenerateCode(generator, optimizationInfo);
EmitConversion.ToObject(generator, lhs.ResultType);
// TODO: share these variables somehow.
var cacheKey = generator.DeclareVariable(typeof(object));
var cachedIndex = generator.DeclareVariable(typeof(int));
// Store the object into a temp variable.
var objectInstance = generator.DeclareVariable(PrimitiveType.Object);
generator.StoreVariable(objectInstance);
// if (__object_cacheKey != object.InlineCacheKey)
generator.LoadVariable(cacheKey);
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlineCacheKey);
var elseClause = generator.CreateLabel();
generator.BranchIfEqual(elseClause);
// xxx = object.InlineSetPropertyValue("property", value, strictMode, out __object_property_cachedIndex, out __object_cacheKey)
generator.LoadVariable(objectInstance);
generator.LoadString(propertyName);
generator.LoadVariable(value);
generator.LoadBoolean(optimizationInfo.StrictMode);
generator.LoadAddressOfVariable(cachedIndex);
generator.LoadAddressOfVariable(cacheKey);
generator.Call(ReflectionHelpers.ObjectInstance_InlineSetPropertyValue);
var endOfIf = generator.CreateLabel();
generator.Branch(endOfIf);
// else
generator.DefineLabelPosition(elseClause);
// object.InlinePropertyValues[__object_property_cachedIndex] = value;
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlinePropertyValues);
generator.LoadVariable(cachedIndex);
generator.LoadVariable(value);
generator.StoreArrayElement(typeof(object));
// End of the if statement
generator.DefineLabelPosition(endOfIf);
}
else
{
// Dynamic property access
// -----------------------
// xxx = object.Get(x)
// Load the left-hand side and convert to an object instance.
var lhs = this.GetOperand(0);
lhs.GenerateCode(generator, optimizationInfo);
EmitConversion.ToObject(generator, lhs.ResultType);
// Load the property name and convert to a string.
var rhs = this.GetOperand(1);
rhs.GenerateCode(generator, optimizationInfo);
EmitConversion.ToString(generator, rhs.ResultType);
// Call the indexer.
generator.LoadVariable(value);
generator.LoadBoolean(optimizationInfo.StrictMode);
generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_String);
}
// The temporary variable is no longer needed.
generator.ReleaseTemporaryVariable(value);
}
示例7: GenerateStub
/// <summary>
/// Generates a method that does type conversion and calls the bound method.
/// </summary>
/// <param name="generator"> The ILGenerator used to output the body of the method. </param>
/// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
/// <returns> A delegate that does type conversion and calls the method represented by this
/// object. </returns>
protected override void GenerateStub(ILGenerator generator, int argumentCount)
{
// Determine the methods that have the correct number of arguments.
var candidateMethods = new List<BinderMethod>();
foreach (var candidateMethod in this.targetMethods)
{
if (candidateMethod.IsArgumentCountCompatible(argumentCount) == true)
candidateMethods.Add(candidateMethod);
}
// Zero candidates means no overload had the correct number of arguments.
if (candidateMethods.Count == 0)
{
EmitHelpers.EmitThrow(generator, "TypeError", string.Format("No overload for method '{0}' takes {1} arguments", this.Name, argumentCount));
EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
generator.Complete();
return;
}
// Select the method to call at run time.
generator.LoadInt32(candidateMethods.Count);
generator.NewArray(typeof(RuntimeMethodHandle));
for (int i = 0; i < candidateMethods.Count; i ++)
{
generator.Duplicate();
generator.LoadInt32(i);
generator.LoadToken(candidateMethods[i]);
generator.StoreArrayElement(typeof(RuntimeMethodHandle));
}
generator.LoadArgument(0);
generator.LoadArgument(1);
generator.LoadArgument(2);
generator.Call(ReflectionHelpers.BinderUtilities_ResolveOverloads);
var endOfMethod = generator.CreateLabel();
for (int i = 0; i < candidateMethods.Count; i++)
{
// Check if this is the selected method.
ILLabel endOfIf = null;
if (i < candidateMethods.Count - 1)
{
generator.Duplicate();
generator.LoadInt32(i);
endOfIf = generator.CreateLabel();
generator.BranchIfNotEqual(endOfIf);
}
generator.Pop();
var targetMethod = candidateMethods[i];
// Convert the arguments.
foreach (var argument in targetMethod.GenerateArguments(generator, argumentCount))
{
// Load the input parameter value.
switch (argument.Source)
{
case BinderArgumentSource.ScriptEngine:
generator.LoadArgument(0);
break;
case BinderArgumentSource.ThisValue:
generator.LoadArgument(1);
break;
case BinderArgumentSource.InputParameter:
generator.LoadArgument(2);
generator.LoadInt32(argument.InputParameterIndex);
generator.LoadArrayElement(typeof(object));
break;
}
// Convert to the target type.
EmitConversionToType(generator, argument.Type, convertToAddress: argument.Source == BinderArgumentSource.ThisValue);
}
// Call the target method.
targetMethod.GenerateCall(generator);
// Convert the return value.
if (targetMethod.ReturnType == typeof(void))
EmitHelpers.EmitUndefined(generator);
else
EmitConversionToObject(generator, targetMethod.ReturnType);
// Branch to the end of the method if this was the selected method.
if (endOfIf != null)
{
generator.Branch(endOfMethod);
generator.DefineLabelPosition(endOfIf);
}
}
generator.DefineLabelPosition(endOfMethod);
generator.Complete();
}
示例8: GenerateDelete
/// <summary>
/// Deletes the reference and pushes <c>true</c> if the delete succeeded, or <c>false</c>
/// if the delete failed.
/// </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 void GenerateDelete(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Deleting a variable is not allowed in strict mode.
if (optimizationInfo.StrictMode == true)
throw new JavaScriptException(optimizationInfo.Engine, ErrorType.SyntaxError, string.Format("Cannot delete {0} because deleting a variable or argument is not allowed in strict mode", this.Name), optimizationInfo.SourceSpan.StartLine, optimizationInfo.Source.Path, optimizationInfo.FunctionName);
var endOfDelete = generator.CreateLabel();
var scope = this.Scope;
ILLocalVariable scopeVariable = generator.CreateTemporaryVariable(typeof(Scope));
EmitHelpers.LoadScope(generator);
generator.StoreVariable(scopeVariable);
do
{
if (scope is DeclarativeScope)
{
var variable = scope.GetDeclaredVariable(this.Name);
if (variable != null)
{
// The variable is known at compile-time.
if (variable.Deletable == false)
{
// The variable cannot be deleted - return false.
generator.LoadBoolean(false);
}
else
{
// The variable can be deleted (it was declared inside an eval()).
// Delete the variable.
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.Scope_Delete);
}
break;
}
else
{
// The variable was not defined at compile time, but may have been
// introduced by an eval() statement.
if (optimizationInfo.MethodOptimizationHints.HasEval == true)
{
// Check the variable exists: if (scope.HasValue(variableName) == true) {
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.Scope_HasValue);
var hasValueClause = generator.CreateLabel();
generator.BranchIfFalse(hasValueClause);
// If the variable does exist, return true.
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.Scope_Delete);
generator.Branch(endOfDelete);
// }
generator.DefineLabelPosition(hasValueClause);
}
}
}
else
{
// Check if the property exists by calling scope.ScopeObject.HasProperty(propertyName)
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(ObjectScope));
generator.Call(ReflectionHelpers.ObjectScope_ScopeObject);
generator.Duplicate();
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.ObjectInstance_HasProperty);
// Jump past the delete if the property doesn't exist.
var endOfExistsCheck = generator.CreateLabel();
generator.BranchIfFalse(endOfExistsCheck);
// Call scope.ScopeObject.Delete(key, false)
generator.LoadString(this.Name);
generator.LoadBoolean(false);
generator.Call(ReflectionHelpers.ObjectInstance_Delete);
generator.Branch(endOfDelete);
generator.DefineLabelPosition(endOfExistsCheck);
generator.Pop();
// If the name is not defined, return true.
if (scope.ParentScope == null)
{
generator.LoadBoolean(true);
}
}
// Try the parent scope.
if (scope.ParentScope != null && scope.ExistsAtRuntime == true)
{
//.........这里部分代码省略.........
示例9: EmitConversionToType
/// <summary>
/// Pops the value on the stack, converts it from an object to the given type, then pushes
/// the result onto the stack.
/// </summary>
/// <param name="generator"> The IL generator. </param>
/// <param name="toType"> The type to convert to. </param>
/// <param name="convertToAddress"> <c>true</c> if the value is intended for use as an
/// instance pointer; <c>false</c> otherwise. </param>
internal static void EmitConversionToType(ILGenerator generator, Type toType, bool convertToAddress)
{
// Convert Null.Value to null if the target type is a reference type.
ILLabel endOfNullCheck = null;
if (toType.IsValueType == false)
{
var startOfElse = generator.CreateLabel();
endOfNullCheck = generator.CreateLabel();
generator.Duplicate();
EmitHelpers.EmitNull(generator);
generator.BranchIfNotEqual(startOfElse);
generator.Pop();
generator.LoadNull();
generator.Branch(endOfNullCheck);
generator.DefineLabelPosition(startOfElse);
}
switch (Type.GetTypeCode(toType))
{
case TypeCode.Boolean:
EmitConversion.ToBool(generator, PrimitiveType.Any);
break;
case TypeCode.Byte:
EmitConversion.ToInt32(generator, PrimitiveType.Any);
break;
case TypeCode.Char:
EmitConversion.ToString(generator, PrimitiveType.Any);
generator.Duplicate();
generator.Call(ReflectionHelpers.String_Length);
generator.LoadInt32(1);
var endOfCharCheck = generator.CreateLabel();
generator.BranchIfEqual(endOfCharCheck);
EmitHelpers.EmitThrow(generator, "TypeError", "Cannot convert string to char - the string must be exactly one character long");
generator.DefineLabelPosition(endOfCharCheck);
generator.LoadInt32(0);
generator.Call(ReflectionHelpers.String_GetChars);
break;
case TypeCode.DBNull:
throw new NotSupportedException("DBNull is not a supported parameter type.");
case TypeCode.Decimal:
EmitConversion.ToNumber(generator, PrimitiveType.Any);
generator.NewObject(ReflectionHelpers.Decimal_Constructor_Double);
break;
case TypeCode.Double:
EmitConversion.ToNumber(generator, PrimitiveType.Any);
break;
case TypeCode.Empty:
throw new NotSupportedException("Empty is not a supported return type.");
case TypeCode.Int16:
EmitConversion.ToInt32(generator, PrimitiveType.Any);
break;
case TypeCode.Int32:
EmitConversion.ToInt32(generator, PrimitiveType.Any);
break;
case TypeCode.Int64:
EmitConversion.ToNumber(generator, PrimitiveType.Any);
generator.ConvertToInt64();
break;
case TypeCode.DateTime:
case TypeCode.Object:
// Check if the type must be unwrapped.
generator.Duplicate();
generator.IsInstance(typeof(Jurassic.Library.ClrInstanceWrapper));
var endOfUnwrapCheck = generator.CreateLabel();
generator.BranchIfFalse(endOfUnwrapCheck);
// Unwrap the wrapped instance.
generator.Call(ReflectionHelpers.ClrInstanceWrapper_GetWrappedInstance);
generator.DefineLabelPosition(endOfUnwrapCheck);
// Value types must be unboxed.
if (toType.IsValueType == true)
{
if (convertToAddress == true)
// Unbox.
generator.Unbox(toType);
else
// Unbox and copy to the stack.
generator.UnboxAny(toType);
//// Calling methods on value required the address of the value type, not the value type itself.
//if (argument.Source == BinderArgumentSource.ThisValue && argument.Type.IsValueType == true)
//{
// var temp = generator.CreateTemporaryVariable(argument.Type);
// generator.StoreVariable(temp);
// generator.LoadAddressOfVariable(temp);
// generator.ReleaseTemporaryVariable(temp);
//}
}
//.........这里部分代码省略.........
示例10: EmitConversionToObject
/// <summary>
/// Pops the value on the stack, converts it to an object, then pushes the result onto the
/// stack.
/// </summary>
/// <param name="generator"> The IL generator. </param>
/// <param name="fromType"> The type to convert from. </param>
internal static void EmitConversionToObject(ILGenerator generator, Type fromType)
{
// If the from type is a reference type, check for null.
ILLabel endOfNullCheck = null;
if (fromType.IsValueType == false)
{
var startOfElse = generator.CreateLabel();
endOfNullCheck = generator.CreateLabel();
generator.Duplicate();
generator.BranchIfNotNull(startOfElse);
generator.Pop();
EmitHelpers.EmitNull(generator);
generator.Branch(endOfNullCheck);
generator.DefineLabelPosition(startOfElse);
}
switch (Type.GetTypeCode(fromType))
{
case TypeCode.Boolean:
generator.Box(typeof(bool));
break;
case TypeCode.Byte:
generator.Box(typeof(int));
break;
case TypeCode.Char:
generator.LoadInt32(1);
generator.NewObject(ReflectionHelpers.String_Constructor_Char_Int);
break;
case TypeCode.DBNull:
throw new NotSupportedException("DBNull is not a supported return type.");
case TypeCode.Decimal:
generator.Call(ReflectionHelpers.Decimal_ToDouble);
generator.Box(typeof(double));
break;
case TypeCode.Double:
generator.Box(typeof(double));
break;
case TypeCode.Empty:
throw new NotSupportedException("Empty is not a supported return type.");
case TypeCode.Int16:
generator.Box(typeof(int));
break;
case TypeCode.Int32:
generator.Box(typeof(int));
break;
case TypeCode.Int64:
generator.ConvertToDouble();
generator.Box(typeof(double));
break;
case TypeCode.DateTime:
case TypeCode.Object:
// Check if the type must be wrapped with a ClrInstanceWrapper.
// Note: if the type is a value type it cannot be a primitive or it would
// have been handled elsewhere in the switch.
ILLabel endOfWrapCheck = null;
if (fromType.IsValueType == false)
{
generator.Duplicate();
generator.Call(ReflectionHelpers.TypeUtilities_IsPrimitiveOrObject);
endOfWrapCheck = generator.CreateLabel();
generator.BranchIfTrue(endOfWrapCheck);
}
// The type must be wrapped.
var temp = generator.CreateTemporaryVariable(fromType);
generator.StoreVariable(temp);
generator.LoadArgument(0);
generator.LoadVariable(temp);
if (fromType.IsValueType == true)
generator.Box(fromType);
generator.ReleaseTemporaryVariable(temp);
generator.NewObject(ReflectionHelpers.ClrInstanceWrapper_Constructor);
// End of wrap check.
if (fromType.IsValueType == false)
generator.DefineLabelPosition(endOfWrapCheck);
break;
case TypeCode.SByte:
generator.Box(typeof(int));
break;
case TypeCode.Single:
generator.Box(typeof(double));
break;
case TypeCode.String:
break;
case TypeCode.UInt16:
generator.Box(typeof(int));
break;
case TypeCode.UInt32:
generator.Box(typeof(uint));
break;
//.........这里部分代码省略.........
示例11: GenerateCode
/// <summary>
/// Generates CIL for the expression.
/// </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)
{
// If a return value is not expected, generate only the side-effects.
/*if (optimizationInfo.SuppressReturnValue == true)
{
this.GenerateSideEffects(generator, optimizationInfo);
return;
}*/
// Emit the condition.
var condition = this.GetOperand(0);
condition.GenerateCode(generator, optimizationInfo);
// Convert the condition to a boolean.
EmitConversion.ToBool(generator, condition.ResultType);
// Branch if the condition is false.
var startOfElse = generator.CreateLabel();
generator.BranchIfFalse(startOfElse);
// Calculate the result type.
var outputType = this.ResultType;
// Emit the second operand and convert it to the result type.
var operand2 = this.GetOperand(1);
operand2.GenerateCode(generator, optimizationInfo);
EmitConversion.Convert(generator, operand2.ResultType, outputType);
// Branch to the end.
var end = generator.CreateLabel();
generator.Branch(end);
generator.DefineLabelPosition(startOfElse);
// Emit the third operand and convert it to the result type.
var operand3 = this.GetOperand(2);
operand3.GenerateCode(generator, optimizationInfo);
EmitConversion.Convert(generator, operand3.ResultType, outputType);
// Define the end label.
generator.DefineLabelPosition(end);
}
示例12: GenerateSet
/// <summary>
/// Stores the value on the top of the stack in the reference.
/// </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="valueType"> The primitive type of the value that is on the top of the stack. </param>
/// <param name="throwIfUnresolvable"> <c>true</c> to throw a ReferenceError exception if
/// the name is unresolvable; <c>false</c> to create a new property instead. </param>
public void GenerateSet(ILGenerator generator, OptimizationInfo optimizationInfo, PrimitiveType valueType, bool throwIfUnresolvable)
{
string propertyName = null;
TypeOfMemberAccess memberAccessType = DetermineTypeOfMemberAccess(optimizationInfo, out propertyName);
if (memberAccessType == TypeOfMemberAccess.ArrayIndex)
{
// Array indexer
// -------------
// xxx = object[index]
// Call the indexer.
EmitConversion.ToAny(generator, valueType);
generator.LoadBoolean(optimizationInfo.StrictMode);
generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_Int);
}
else if (memberAccessType == TypeOfMemberAccess.Static)
{
// Named property modification (e.g. x.property = y)
// -------------------------------------------------
// __object_cacheKey = null;
// __object_property_cachedIndex = 0;
// ...
// if (__object_cacheKey != object.InlineCacheKey)
// object.InlineSetPropertyValue("property", value, strictMode, out __object_property_cachedIndex, out __object_cacheKey)
// else
// object.InlinePropertyValues[__object_property_cachedIndex] = value;
// Convert the value to an object and store it in a temporary variable.
var value = generator.CreateTemporaryVariable(typeof(object));
EmitConversion.ToAny(generator, valueType);
generator.StoreVariable(value);
// TODO: share these variables somehow.
var cacheKey = generator.DeclareVariable(typeof(object));
var cachedIndex = generator.DeclareVariable(typeof(int));
// Store the object into a temp variable.
var objectInstance = generator.DeclareVariable(PrimitiveType.Object);
generator.StoreVariable(objectInstance);
// if (__object_cacheKey != object.InlineCacheKey)
generator.LoadVariable(cacheKey);
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlineCacheKey);
var elseClause = generator.CreateLabel();
generator.BranchIfEqual(elseClause);
// xxx = object.InlineSetPropertyValue("property", value, strictMode, out __object_property_cachedIndex, out __object_cacheKey)
generator.LoadVariable(objectInstance);
generator.LoadString(propertyName);
generator.LoadVariable(value);
generator.LoadBoolean(optimizationInfo.StrictMode);
generator.LoadAddressOfVariable(cachedIndex);
generator.LoadAddressOfVariable(cacheKey);
generator.Call(ReflectionHelpers.ObjectInstance_InlineSetPropertyValue);
var endOfIf = generator.CreateLabel();
generator.Branch(endOfIf);
// else
generator.DefineLabelPosition(elseClause);
// object.InlinePropertyValues[__object_property_cachedIndex] = value;
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlinePropertyValues);
generator.LoadVariable(cachedIndex);
generator.LoadVariable(value);
generator.StoreArrayElement(typeof(object));
// End of the if statement
generator.DefineLabelPosition(endOfIf);
// The temporary variable is no longer needed.
generator.ReleaseTemporaryVariable(value);
}
else
{
// Dynamic property access
// -----------------------
// xxx = object.Get(x)
// Call the indexer.
EmitConversion.ToAny(generator, valueType);
generator.LoadBoolean(optimizationInfo.StrictMode);
generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_Object);
}
}
示例13: GenerateGet
/// <summary>
/// Pushes the value of the reference onto the stack.
/// </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="throwIfUnresolvable"> <c>true</c> to throw a ReferenceError exception if
/// the name is unresolvable; <c>false</c> to output <c>null</c> instead. </param>
public void GenerateGet(ILGenerator generator, OptimizationInfo optimizationInfo, bool throwIfUnresolvable)
{
string propertyName = null;
TypeOfMemberAccess memberAccessType = DetermineTypeOfMemberAccess(optimizationInfo, out propertyName);
if (memberAccessType == TypeOfMemberAccess.ArrayIndex)
{
// Array indexer
// -------------
// xxx = object[index]
// Call the indexer.
generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_Int);
}
else if (memberAccessType == TypeOfMemberAccess.Static)
{
// Named property access (e.g. x = y.property)
// -------------------------------------------
// __object_cacheKey = null;
// __object_property_cachedIndex = 0;
// ...
// if (__object_cacheKey != object.InlineCacheKey)
// xxx = object.InlineGetPropertyValue("property", out __object_property_cachedIndex, out __object_cacheKey)
// else
// xxx = object.InlinePropertyValues[__object_property_cachedIndex];
// TODO: share these variables somehow.
var cacheKey = generator.DeclareVariable(typeof(object));
var cachedIndex = generator.DeclareVariable(typeof(int));
// Store the object into a temp variable.
var objectInstance = generator.DeclareVariable(PrimitiveType.Object);
generator.StoreVariable(objectInstance);
// if (__object_cacheKey != object.InlineCacheKey)
generator.LoadVariable(cacheKey);
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlineCacheKey);
var elseClause = generator.CreateLabel();
generator.BranchIfEqual(elseClause);
// value = object.InlineGetProperty("property", out __object_property_cachedIndex, out __object_cacheKey)
generator.LoadVariable(objectInstance);
generator.LoadString(propertyName);
generator.LoadAddressOfVariable(cachedIndex);
generator.LoadAddressOfVariable(cacheKey);
generator.Call(ReflectionHelpers.ObjectInstance_InlineGetPropertyValue);
var endOfIf = generator.CreateLabel();
generator.Branch(endOfIf);
// else
generator.DefineLabelPosition(elseClause);
// value = object.InlinePropertyValues[__object_property_cachedIndex];
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlinePropertyValues);
generator.LoadVariable(cachedIndex);
generator.LoadArrayElement(typeof(object));
// End of the if statement
generator.DefineLabelPosition(endOfIf);
}
else
{
// Dynamic property access
// -----------------------
// xxx = object.Get(x)
// Call Get(object)
generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_Object);
}
}
示例14: GenerateCode
/// <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 };
GenerateStartOfStatement(generator, optimizationInfo, statementLocals);
// We need a label for each case clause and one for the default case.
var jumpTargets = new ILLabel[this.CaseClauses.Count];
int defaultIndex = -1;
ILLabel endOfSwitch = generator.CreateLabel();
// Generate code for the switch value.
var startOfSwitch = generator.CreateLabel();
this.Value.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, this.Value.ResultType);
// Save the switch value in a variable.
var switchValue = generator.CreateTemporaryVariable(typeof(object));
generator.StoreVariable(switchValue);
for (int i = 0; i < this.CaseClauses.Count; i ++)
{
var caseClause = this.CaseClauses[i];
// Create a label for each clause.
jumpTargets[i] = generator.CreateLabel();
if (caseClause.Value == null)
{
// This is a default clause.
defaultIndex = i;
continue;
}
// TypeComparer.StrictEquals(switchValue, caseValue)
generator.LoadVariable(switchValue);
caseClause.Value.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, caseClause.Value.ResultType);
generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);
// if (TypeComparer.StrictEquals(switchValue, caseValue) == true)
// goto case i
generator.BranchIfTrue(jumpTargets[i]);
}
// None of the cases matched, jump to the default clause or the end of the switch.
if (defaultIndex >= 0)
generator.Branch(jumpTargets[defaultIndex]);
else
generator.Branch(endOfSwitch);
for (int i = 0; i < this.CaseClauses.Count; i++)
{
// Define a label at the start of the case clause.
generator.DefineLabelPosition(jumpTargets[i]);
// Set up the information needed by the break statement.
optimizationInfo.PushBreakOrContinueInfo(this.Labels, endOfSwitch, null, labelledOnly: false);
// Emit the case clause statements.
foreach (var statement in this.CaseClauses[i].BodyStatements)
statement.GenerateCode(generator, optimizationInfo);
// Revert the information needed by the break statement.
optimizationInfo.PopBreakOrContinueInfo();
}
// Define a label for the end of the switch statement.
generator.DefineLabelPosition(endOfSwitch);
// Release the switch value variable for use elsewhere.
generator.ReleaseTemporaryVariable(switchValue);
// Generate code for the end of the statement.
GenerateEndOfStatement(generator, optimizationInfo, statementLocals);
}
示例15: ToString
/// <summary>
/// Pops the value on the stack, converts it to a string, then pushes the result onto the
/// stack.
/// </summary>
/// <param name="generator"> The IL generator. </param>
/// <param name="fromType"> The type to convert from. </param>
public static void ToString(ILGenerator generator, PrimitiveType fromType)
{
// Check that a conversion is actually necessary.
if (fromType == PrimitiveType.String)
return;
switch (fromType)
{
case PrimitiveType.Undefined:
// Converting from undefined produces "undefined".
generator.Pop();
generator.LoadString("undefined");
break;
case PrimitiveType.Null:
// Converting from null produces "null".
generator.Pop();
generator.LoadString("null");
break;
case PrimitiveType.Bool:
// Converting from a boolean produces "false" if the boolean is false, or "true" if the boolean is true.
var elseClause = generator.CreateLabel();
var endOfIf = generator.CreateLabel();
generator.BranchIfFalse(elseClause);
generator.LoadString("true");
generator.Branch(endOfIf);
generator.DefineLabelPosition(elseClause);
generator.LoadString("false");
generator.DefineLabelPosition(endOfIf);
break;
case PrimitiveType.ConcatenatedString:
generator.Call(ReflectionHelpers.ConcatenatedString_ToString);
break;
case PrimitiveType.Int32:
case PrimitiveType.UInt32:
case PrimitiveType.Number:
case PrimitiveType.Any:
case PrimitiveType.Object:
// Otherwise, fall back to calling TypeConverter.ToString()
if (PrimitiveTypeUtilities.IsValueType(fromType))
generator.Box(fromType);
generator.Call(ReflectionHelpers.TypeConverter_ToString);
break;
default:
throw new NotImplementedException(string.Format("Unsupported primitive type: {0}", fromType));
}
}