public abstract CallStatic ( System method ) : void | ||
method | System | The method to call. |
리턴 | void |
/// <summary> /// Generates an array containing the argument values for a tagged template literal. /// </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="templateLiteral"> The template literal expression containing the parameter /// values. </param> internal void GenerateTemplateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo, TemplateLiteralExpression templateLiteral) { // Generate an array containing the value of each argument. generator.LoadInt32(templateLiteral.Values.Count + 1); generator.NewArray(typeof(object)); // Load the first parameter. generator.Duplicate(); generator.LoadInt32(0); // The first parameter to the tag function is an array of strings. var stringsExpression = new List <Expression>(templateLiteral.Strings.Count); foreach (var templateString in templateLiteral.Strings) { stringsExpression.Add(new LiteralExpression(templateString)); } new LiteralExpression(stringsExpression).GenerateCode(generator, optimizationInfo); generator.Duplicate(); // Now we need the name of the property. generator.LoadString("raw"); // Now generate an array of raw strings. var rawStringsExpression = new List <Expression>(templateLiteral.RawStrings.Count); foreach (var rawString in templateLiteral.RawStrings) { rawStringsExpression.Add(new LiteralExpression(rawString)); } new LiteralExpression(rawStringsExpression).GenerateCode(generator, optimizationInfo); // Freeze array by calling ObjectInstance Freeze(ObjectInstance). generator.CallStatic(ReflectionHelpers.ObjectConstructor_Freeze); // Now store the raw strings as a property of the base strings array. generator.LoadBoolean(optimizationInfo.StrictMode); generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_Object); // Freeze array by calling ObjectInstance Freeze(ObjectInstance). generator.CallStatic(ReflectionHelpers.ObjectConstructor_Freeze); // Store in the array. generator.StoreArrayElement(typeof(object)); // Values are passed as subsequent parameters. for (int i = 0; i < templateLiteral.Values.Count; i++) { generator.Duplicate(); generator.LoadInt32(i + 1); templateLiteral.Values[i].GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, templateLiteral.Values[i].ResultType); generator.StoreArrayElement(typeof(object)); } }
/// <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) { // This code is only used for untagged template literals. // Tagged template literals are handled by FunctionCallExpression. // Load the values array onto the stack. generator.LoadInt32(this.Strings.Count + this.Values.Count); generator.NewArray(typeof(string)); for (int i = 0; i < this.Strings.Count; i++) { // Operands for StoreArrayElement() are: an array (string[]), index (int), value (string). // Store the string. generator.Duplicate(); generator.LoadInt32(i * 2); generator.LoadString(this.Strings[i]); generator.StoreArrayElement(typeof(string)); if (i == this.Strings.Count - 1) { break; } // Store the value. generator.Duplicate(); generator.LoadInt32(i * 2 + 1); this.Values[i].GenerateCode(generator, optimizationInfo); EmitConversion.ToString(generator, this.Values[i].ResultType); generator.StoreArrayElement(typeof(string)); } // Call String.Concat(string[]) generator.CallStatic(ReflectionHelpers.String_Concat); }
/// <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; * }*/ // Special case the addition operator. if (this.OperatorType == OperatorType.Add) { GenerateAdd(generator, optimizationInfo); return; } // Special case the instanceof operator. if (this.OperatorType == OperatorType.InstanceOf) { GenerateInstanceOf(generator, optimizationInfo); return; } // Special case the in operator. if (this.OperatorType == OperatorType.In) { GenerateIn(generator, optimizationInfo); return; } // Special case the relational operators. if (this.OperatorType == OperatorType.LessThan || this.OperatorType == OperatorType.LessThanOrEqual || this.OperatorType == OperatorType.GreaterThan || this.OperatorType == OperatorType.GreaterThanOrEqual) { GenerateRelational(generator, optimizationInfo); return; } // Special case the logical operators. if (this.OperatorType == OperatorType.LogicalAnd || this.OperatorType == OperatorType.LogicalOr) { GenerateLogical(generator, optimizationInfo); return; } // Load the left hand side onto the stack. this.Left.GenerateCode(generator, optimizationInfo); // Convert the left argument. switch (this.OperatorType) { // Arithmetic operations. case OperatorType.Subtract: case OperatorType.Multiply: case OperatorType.Divide: case OperatorType.Modulo: case OperatorType.Exponentiation: EmitConversion.ToNumber(generator, this.Left.ResultType); break; // Bitwise operations. case OperatorType.BitwiseAnd: case OperatorType.BitwiseOr: case OperatorType.BitwiseXor: case OperatorType.LeftShift: case OperatorType.SignedRightShift: case OperatorType.UnsignedRightShift: EmitConversion.ToInt32(generator, this.Left.ResultType); break; // Equality operations. case OperatorType.Equal: case OperatorType.StrictlyEqual: case OperatorType.NotEqual: case OperatorType.StrictlyNotEqual: EmitConversion.ToAny(generator, this.Left.ResultType); break; } // Load the right hand side onto the stack. this.Right.GenerateCode(generator, optimizationInfo); // Convert the right argument. switch (this.OperatorType) { // Arithmetic operations. case OperatorType.Subtract: case OperatorType.Multiply: case OperatorType.Divide: case OperatorType.Modulo: case OperatorType.Exponentiation: EmitConversion.ToNumber(generator, this.Right.ResultType); break; // Bitwise operations. case OperatorType.BitwiseAnd: case OperatorType.BitwiseOr: case OperatorType.BitwiseXor: EmitConversion.ToInt32(generator, this.Right.ResultType); break; case OperatorType.LeftShift: case OperatorType.SignedRightShift: case OperatorType.UnsignedRightShift: EmitConversion.ToUInt32(generator, this.Right.ResultType); generator.LoadInt32(0x1F); generator.BitwiseAnd(); break; // Equality operations. case OperatorType.Equal: case OperatorType.StrictlyEqual: case OperatorType.NotEqual: case OperatorType.StrictlyNotEqual: EmitConversion.ToAny(generator, this.Right.ResultType); break; } // Apply the operator. switch (this.OperatorType) { // Arithmetic operations. case OperatorType.Subtract: generator.Subtract(); break; case OperatorType.Multiply: generator.Multiply(); break; case OperatorType.Divide: generator.Divide(); break; case OperatorType.Modulo: generator.Remainder(); break; case OperatorType.Exponentiation: generator.CallStatic(ReflectionHelpers.Math_Pow); break; // Bitwise operations. case OperatorType.BitwiseAnd: generator.BitwiseAnd(); break; case OperatorType.BitwiseOr: generator.BitwiseOr(); break; case OperatorType.BitwiseXor: generator.BitwiseXor(); break; // Shift operations. case OperatorType.LeftShift: generator.ShiftLeft(); break; case OperatorType.SignedRightShift: generator.ShiftRight(); break; case OperatorType.UnsignedRightShift: generator.ShiftRightUnsigned(); EmitConversion.ToNumber(generator, PrimitiveType.UInt32); break; // Equality operations. case OperatorType.Equal: generator.Call(ReflectionHelpers.TypeComparer_Equals); break; case OperatorType.StrictlyEqual: generator.Call(ReflectionHelpers.TypeComparer_StrictEquals); break; case OperatorType.NotEqual: generator.Call(ReflectionHelpers.TypeComparer_Equals); generator.LoadBoolean(false); generator.CompareEqual(); break; case OperatorType.StrictlyNotEqual: generator.Call(ReflectionHelpers.TypeComparer_StrictEquals); generator.LoadBoolean(false); generator.CompareEqual(); break; default: throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType)); } }
/// <summary> /// Generates an array containing the argument values for a tagged template literal. /// </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="templateLiteral"> The template literal expression containing the parameter /// values. </param> internal void GenerateTemplateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo, TemplateLiteralExpression templateLiteral) { // Generate an array containing the value of each argument. generator.LoadInt32(templateLiteral.Values.Count + 1); generator.NewArray(typeof(object)); // Load the first parameter. generator.Duplicate(); generator.LoadInt32(0); // Generate a unique integer that is used as the cache key. int callSiteId = System.Threading.Interlocked.Increment(ref templateCallSiteId); // Call GetCachedTemplateStringsArray(ScriptEngine engine, int callSiteId) EmitHelpers.LoadScriptEngine(generator); generator.LoadInt32(callSiteId); generator.CallStatic(ReflectionHelpers.ReflectionHelpers_GetCachedTemplateStringsArray); // If that's null, do it the long way. var afterCreateTemplateStringsArray = generator.CreateLabel(); generator.Duplicate(); generator.BranchIfNotNull(afterCreateTemplateStringsArray); generator.Pop(); // Start emitting arguments for CreateTemplateStringsArray. EmitHelpers.LoadScriptEngine(generator); // int callSiteId generator.LoadInt32(callSiteId); // string[] strings generator.LoadInt32(templateLiteral.Strings.Count); generator.NewArray(typeof(string)); for (int i = 0; i < templateLiteral.Strings.Count; i++) { // strings[i] = templateLiteral.Strings[i] generator.Duplicate(); generator.LoadInt32(i); generator.LoadString(templateLiteral.Strings[i]); generator.StoreArrayElement(typeof(string)); } // string[] raw generator.LoadInt32(templateLiteral.RawStrings.Count); generator.NewArray(typeof(string)); for (int i = 0; i < templateLiteral.RawStrings.Count; i++) { // raw[i] = templateLiteral.RawStrings[i] generator.Duplicate(); generator.LoadInt32(i); generator.LoadString(templateLiteral.RawStrings[i]); generator.StoreArrayElement(typeof(string)); } // CreateTemplateStringsArray(ScriptEngine engine, int callSiteId, object[] strings, object[] rawStrings) generator.CallStatic(ReflectionHelpers.ReflectionHelpers_CreateTemplateStringsArray); generator.DefineLabelPosition(afterCreateTemplateStringsArray); // Store in the array. generator.StoreArrayElement(typeof(object)); // Values are passed as subsequent parameters. for (int i = 0; i < templateLiteral.Values.Count; i++) { generator.Duplicate(); generator.LoadInt32(i + 1); templateLiteral.Values[i].GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, templateLiteral.Values[i].ResultType); generator.StoreArrayElement(typeof(object)); } }
/// <summary> /// Generates an array containing the argument values for a tagged template literal. /// </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="templateLiteral"> The template literal expression containing the parameter /// values. </param> internal void GenerateTemplateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo, TemplateLiteralExpression templateLiteral) { // Generate an array containing the value of each argument. generator.LoadInt32(templateLiteral.Values.Count + 1); generator.NewArray(typeof(object)); // Load the first parameter. generator.Duplicate(); generator.LoadInt32(0); // The first parameter to the tag function is an array of strings. var stringsExpression = new List<Expression>(templateLiteral.Strings.Count); foreach (var templateString in templateLiteral.Strings) { stringsExpression.Add(new LiteralExpression(templateString)); } new LiteralExpression(stringsExpression).GenerateCode(generator, optimizationInfo); generator.Duplicate(); // Now we need the name of the property. generator.LoadString("raw"); // Now generate an array of raw strings. var rawStringsExpression = new List<Expression>(templateLiteral.RawStrings.Count); foreach (var rawString in templateLiteral.RawStrings) { rawStringsExpression.Add(new LiteralExpression(rawString)); } new LiteralExpression(rawStringsExpression).GenerateCode(generator, optimizationInfo); // Freeze array by calling ObjectInstance Freeze(ObjectInstance). generator.CallStatic(ReflectionHelpers.ObjectConstructor_Freeze); // Now store the raw strings as a property of the base strings array. generator.LoadBoolean(optimizationInfo.StrictMode); generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_Object); // Freeze array by calling ObjectInstance Freeze(ObjectInstance). generator.CallStatic(ReflectionHelpers.ObjectConstructor_Freeze); // Store in the array. generator.StoreArrayElement(typeof(object)); // Values are passed as subsequent parameters. for (int i = 0; i < templateLiteral.Values.Count; i++) { generator.Duplicate(); generator.LoadInt32(i + 1); templateLiteral.Values[i].GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, templateLiteral.Values[i].ResultType); generator.StoreArrayElement(typeof(object)); } }
/// <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) { // This code is only used for untagged template literals. // Tagged template literals are handled by FunctionCallExpression. // Load the values array onto the stack. generator.LoadInt32(this.Strings.Count + this.Values.Count); generator.NewArray(typeof(string)); for (int i = 0; i < this.Strings.Count; i++) { // Operands for StoreArrayElement() are: an array (string[]), index (int), value (string). // Store the string. generator.Duplicate(); generator.LoadInt32(i * 2); generator.LoadString(this.Strings[i]); generator.StoreArrayElement(typeof(string)); if (i == this.Strings.Count - 1) break; // Store the value. generator.Duplicate(); generator.LoadInt32(i * 2 + 1); this.Values[i].GenerateCode(generator, optimizationInfo); EmitConversion.ToString(generator, this.Values[i].ResultType); generator.StoreArrayElement(typeof(string)); } // Call String.Concat(string[]) generator.CallStatic(ReflectionHelpers.String_Concat); }
/// <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 the class was named, then we need to create a new scope to hold the name. if (Name != null) { Scope.GenerateScopeCreation(generator, optimizationInfo); } // engine EmitHelpers.LoadScriptEngine(generator); // name generator.LoadStringOrNull(this.Name); // extends if (Extends == null) { generator.LoadNull(); } else { Extends.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, Extends.ResultType); } // constructor if (Constructor == null) { generator.LoadNull(); } else { Constructor.GenerateCode(generator, optimizationInfo); } // ConstructClass(ScriptEngine engine, string name, object extends, FunctionInstance constructor) generator.CallStatic(ReflectionHelpers.ReflectionHelpers_ConstructClass); // Create a variable to hold the container instance value. var containerVariable = generator.CreateTemporaryVariable(typeof(ObjectInstance)); foreach (var member in this.Members) { // class.InstancePrototype generator.Duplicate(); if (!member.Name.IsStatic) { generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype); } // Store this in a variable so that FunctionExpression.GenerateCode can retrieve it. generator.Duplicate(); generator.StoreVariable(containerVariable); // The key can be a property name or an expression that evaluates to a name. if (member.Name.HasStaticName) { generator.LoadString(member.Name.StaticName); } else { member.Name.ComputedName.GenerateCode(generator, optimizationInfo); EmitConversion.ToPropertyKey(generator, member.Name.ComputedName.ResultType); } // Emit the function value. member.ContainerVariable = containerVariable; member.GenerateCode(generator, optimizationInfo); member.ContainerVariable = null; if (member.Name.IsGetter) { // Add a getter to the object. generator.Call(ReflectionHelpers.ReflectionHelpers_SetClassGetter); } else if (member.Name.IsSetter) { // Add a setter to the object. generator.Call(ReflectionHelpers.ReflectionHelpers_SetClassSetter); } else { // Add a new property to the object. generator.Call(ReflectionHelpers.ReflectionHelpers_SetClassValue); } } // Release the variable that we created above. generator.ReleaseTemporaryVariable(containerVariable); // Store the class name in the scope. if (Name != null) { generator.Duplicate(); new NameExpression(Scope, Name).GenerateSet(generator, optimizationInfo, PrimitiveType.Object); } }
/// <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) { // Generate a new method. this.context.GenerateCode(); // Add the generated method to the nested function list. if (optimizationInfo.NestedFunctions == null) { optimizationInfo.NestedFunctions = new List <GeneratedMethod>(); } optimizationInfo.NestedFunctions.Add(this.context.GeneratedMethod); // Add all the nested methods to the parent list. if (this.context.GeneratedMethod.Dependencies != null) { foreach (var nestedFunctionExpression in this.context.GeneratedMethod.Dependencies) { optimizationInfo.NestedFunctions.Add(nestedFunctionExpression); } } // Store the generated method in the cache. long generatedMethodID = GeneratedMethod.Save(this.context.GeneratedMethod); // Create a UserDefinedFunction. // prototype EmitHelpers.LoadScriptEngine(generator); generator.Call(ReflectionHelpers.ScriptEngine_Function); generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype); // name string prefix = null; if (Name.IsGetter) { prefix = "get "; } else if (Name.IsSetter) { prefix = "set "; } if (Name.HasStaticName) { generator.LoadString(prefix + Name.StaticName); } else { // Compute the name at runtime. if (prefix != null) { generator.LoadString(prefix); } Name.ComputedName.GenerateCode(generator, optimizationInfo); EmitConversion.ToString(generator, Name.ComputedName.ResultType); if (prefix != null) { generator.CallStatic(ReflectionHelpers.String_Concat_String_String); } } // argumentNames generator.LoadInt32(this.Arguments.Count); generator.NewArray(typeof(string)); for (int i = 0; i < this.Arguments.Count; i++) { generator.Duplicate(); generator.LoadInt32(i); generator.LoadString(this.Arguments[i].Name); generator.StoreArrayElement(typeof(string)); } // scope Scope.GenerateReference(generator, optimizationInfo); // bodyText generator.LoadString(this.BodyText); // body generator.LoadInt64(generatedMethodID); generator.Call(ReflectionHelpers.GeneratedMethod_Load); // strictMode generator.LoadBoolean(this.context.StrictMode); // container if (ContainerVariable != null) { generator.LoadVariable(ContainerVariable); } else { generator.LoadNull(); } // CreateFunction(ObjectInstance prototype, string name, IList<string> argumentNames, // RuntimeScope scope, Func<Scope, object, object[], object> body, // bool strictMode, FunctionInstance container) generator.CallStatic(ReflectionHelpers.ReflectionHelpers_CreateFunction); }
/// <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); } // Handle Nullable<>. var isNullable = fromType.IsGenericType && fromType.GetGenericTypeDefinition() == typeof(Nullable <>); if (isNullable) { endOfNullCheck = generator.CreateLabel(); var v = generator.CreateTemporaryVariable(fromType); generator.StoreVariable(v); generator.LoadAddressOfVariable(v); var hasValue = ReflectionHelpers.GetInstanceMethod(fromType, "get_HasValue"); generator.Call(hasValue); generator.BranchIfTrue(endOfNullCheck); // Return null. generator.LoadNull(); generator.Return(); // Jump here if it was NOT null. generator.DefineLabelPosition(endOfNullCheck); // Get the underlying value. generator.LoadAddressOfVariable(v); var getValue = ReflectionHelpers.GetInstanceMethod(fromType, "get_Value"); generator.Call(getValue); // Now let the normal conversion work. fromType = fromType.GenericTypeArguments[0]; } 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.CallStatic(ReflectionHelpers.ClrInstanceWrapper_Create); // 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; case TypeCode.UInt64: generator.ConvertUnsignedToDouble(); generator.Box(typeof(double)); break; } // Label the end of the null check. if (fromType.IsValueType == false) { generator.DefineLabelPosition(endOfNullCheck); } }