LoadThis() 공개 정적인 메소드

Pushes the value of the this keyword onto the stack.
public static LoadThis ( ILGenerator generator ) : void
generator ILGenerator The IL generator.
리턴 void
예제 #1
0
        /// <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);
 }