public static LoadThis ( |
||
generator | The IL generator. | |
리턴 | void |
/// <summary> /// Generates CIL for a call to eval(). /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> private void GenerateEval(ILGenerator generator, OptimizationInfo optimizationInfo) { // engine EmitHelpers.LoadScriptEngine(generator); // code if (this.OperandCount < 2) { // No arguments were supplied. generator.LoadNull(); } else { // Take the first argument and convert it to a string. GenerateArgumentsArray(generator, optimizationInfo); generator.LoadInt32(0); generator.LoadArrayElement(typeof(object)); } // scope EmitHelpers.LoadScope(generator); // thisObject EmitHelpers.LoadThis(generator); // strictMode generator.LoadBoolean(optimizationInfo.StrictMode); // Call Global.Eval(engine, code, scope, thisValue, strictMode) generator.Call(ReflectionHelpers.Global_Eval); }
/// <summary> /// Generates IL for the script. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> protected override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Method signature: object FunctionDelegate(Compiler.Scope scope, object thisObject, Library.FunctionInstance functionObject, object[] arguments) // Initialize the scope (note: the initial scope for a function is always declarative). this.InitialScope.GenerateScopeCreation(generator, optimizationInfo); // Verify the scope is correct. VerifyScope(generator); // In ES3 the "this" value must be an object. See 10.4.3 in the spec. if (this.StrictMode == false && this.MethodOptimizationHints.HasThis == true) { // if (thisObject == null || thisObject == Null.Value || thisObject == Undefined.Value) EmitHelpers.LoadThis(generator); generator.LoadNull(); generator.CompareEqual(); EmitHelpers.LoadThis(generator); EmitHelpers.EmitNull(generator); generator.CompareEqual(); generator.BitwiseOr(); EmitHelpers.LoadThis(generator); EmitHelpers.EmitUndefined(generator); generator.CompareEqual(); generator.BitwiseOr(); // { var startOfFalse = generator.CreateLabel(); generator.BranchIfFalse(startOfFalse); // thisObject = engine.Global; EmitHelpers.LoadScriptEngine(generator); generator.Call(ReflectionHelpers.ScriptEngine_Global); // } else { var endOfIf = generator.CreateLabel(); generator.Branch(endOfIf); generator.DefineLabelPosition(startOfFalse); // thisObject = TypeConverter.ToObject(thisObject); EmitHelpers.LoadThis(generator); EmitConversion.ToObject(generator, PrimitiveType.Any, optimizationInfo); // } generator.DefineLabelPosition(endOfIf); EmitHelpers.StoreThis(generator); } // Transfer the function name into the scope. if (string.IsNullOrEmpty(this.Name) == false && this.IncludeNameInScope == true && this.ArgumentNames.Contains(this.Name) == false && optimizationInfo.MethodOptimizationHints.HasVariable(this.Name)) { EmitHelpers.LoadFunction(generator); var functionName = new NameExpression(this.InitialScope, this.Name); functionName.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false); } // Transfer the arguments object into the scope. if (this.MethodOptimizationHints.HasArguments == true && this.ArgumentNames.Contains("arguments") == false) { // prototype EmitHelpers.LoadScriptEngine(generator); generator.Call(ReflectionHelpers.ScriptEngine_Object); generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype); // callee EmitHelpers.LoadFunction(generator); generator.CastClass(typeof(Library.UserDefinedFunction)); // scope EmitHelpers.LoadScope(generator); generator.CastClass(typeof(DeclarativeScope)); // argumentValues EmitHelpers.LoadArgumentsArray(generator); generator.NewObject(ReflectionHelpers.Arguments_Constructor); var arguments = new NameExpression(this.InitialScope, "arguments"); arguments.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false); } // Transfer the argument values into the scope. // Note: the arguments array can be smaller than expected. if (this.ArgumentNames.Count > 0) { var endOfArguments = generator.CreateLabel(); for (int i = 0; i < this.ArgumentNames.Count; i++) { // Check if a duplicate argument name exists. bool duplicate = false; for (int j = i + 1; j < this.ArgumentNames.Count; j++) { if (this.ArgumentNames[i] == this.ArgumentNames[j]) { duplicate = true; break; } } if (duplicate == true) { continue; } // Check if an array element exists. EmitHelpers.LoadArgumentsArray(generator); generator.LoadArrayLength(); generator.LoadInt32(i); generator.BranchIfLessThanOrEqual(endOfArguments); // Store the array element in the scope. EmitHelpers.LoadArgumentsArray(generator); generator.LoadInt32(i); generator.LoadArrayElement(typeof(object)); var argument = new NameExpression(this.InitialScope, this.ArgumentNames[i]); argument.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false); } generator.DefineLabelPosition(endOfArguments); } // Initialize any declarations. this.InitialScope.GenerateDeclarations(generator, optimizationInfo); //EmitHelpers.LoadScope(generator); //EmitConversion.ToObject(generator, PrimitiveType.Any); //generator.Pop(); // Generate code for the body of the function. this.AbstractSyntaxTree.GenerateCode(generator, optimizationInfo); // Define the return target - this is where the return statement jumps to. // ReturnTarget can be null if there were no return statements. if (optimizationInfo.ReturnTarget != null) { generator.DefineLabelPosition(optimizationInfo.ReturnTarget); } // Load the return value. If the variable is null, there were no return statements. if (optimizationInfo.ReturnVariable != null) { // Return the value stored in the variable. Will be null if execution hits the end // of the function without encountering any return statements. generator.LoadVariable(optimizationInfo.ReturnVariable); } else { // There were no return statements - return null. generator.LoadNull(); } }
/// <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) { // Check if this is a direct call to eval(). if (this.Target is NameExpression && ((NameExpression)this.Target).Name == "eval") { GenerateEval(generator, optimizationInfo); return; } // Check if this is a super() call. if (this.Target is SuperExpression) { // executionContext.CallSuperClass(arguments) EmitHelpers.LoadExecutionContext(generator); GenerateArgumentsArray(generator, optimizationInfo); generator.Call(ReflectionHelpers.ExecutionContext_CallSuperClass); return; } // Emit the function instance first. ILLocalVariable targetBase = null; if (this.Target is MemberAccessExpression) { // The function is a member access expression (e.g. "Math.cos()"). // Evaluate the left part of the member access expression. var baseExpression = ((MemberAccessExpression)this.Target).Base; baseExpression.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, baseExpression.ResultType); targetBase = generator.CreateTemporaryVariable(typeof(object)); generator.StoreVariable(targetBase); // Evaluate the right part of the member access expression. var memberAccessExpression = new MemberAccessExpression(((MemberAccessExpression)this.Target).Operator); memberAccessExpression.Push(new TemporaryVariableExpression(targetBase)); memberAccessExpression.Push(((MemberAccessExpression)this.Target).GetOperand(1)); memberAccessExpression.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, this.Target.ResultType); } else { // Something else (e.g. "my_func()"). this.Target.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, this.Target.ResultType); } // Check the object really is a function - if not, throw an exception. generator.Duplicate(); generator.IsInstance(typeof(FunctionInstance)); var endOfTypeCheck = generator.CreateLabel(); generator.BranchIfTrue(endOfTypeCheck); // Throw an nicely formatted exception. generator.Pop(); EmitHelpers.EmitThrow(generator, ErrorType.TypeError, string.Format("'{0}' is not a function", this.Target.ToString()), optimizationInfo); generator.DefineLabelPosition(endOfTypeCheck); // Pass in the path, function name and line. generator.ReinterpretCast(typeof(FunctionInstance)); generator.LoadStringOrNull(optimizationInfo.Source.Path); generator.LoadStringOrNull(optimizationInfo.FunctionName); generator.LoadInt32(optimizationInfo.SourceSpan.StartLine); // Generate code to produce the "this" value. There are three cases. if (this.Target is NameExpression) { // 1. The function is a name expression (e.g. "parseInt()"). // If we are inside a with() block, then there is an implicit 'this' value, // otherwise 'this' is undefined. Scope.GenerateReference(generator, optimizationInfo); generator.Call(ReflectionHelpers.RuntimeScope_ImplicitThis); } else if (this.Target is MemberAccessExpression targetMemberAccessExpression) { // 2. The function is a member access expression (e.g. "Math.cos()"). // In this case this = Math. // Unless it's a super call like super.blah(). if (targetMemberAccessExpression.Base is SuperExpression) { EmitHelpers.LoadThis(generator); } else { generator.LoadVariable(targetBase); } } else { // 3. Neither of the above (e.g. "(function() { return 5 })()") // In this case this = undefined. EmitHelpers.EmitUndefined(generator); } // Emit an array containing the function arguments. GenerateArgumentsArray(generator, optimizationInfo); // Call FunctionInstance.CallLateBound(thisValue, argumentValues) generator.Call(ReflectionHelpers.FunctionInstance_CallWithStackTrace); // Allow reuse of the temporary variable. if (targetBase != null) { generator.ReleaseTemporaryVariable(targetBase); } }
/// <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 (optimizationInfo.SuppressReturnValue == true) // return; EmitHelpers.LoadThis(generator); }