/// <summary> /// Pops the value from the top of the stack and stores it in the given local variable. /// </summary> /// <param name="variable"> The variable to store the value. </param> public override void StoreVariable(ILLocalVariable variable) { if (variable as ReflectionEmitILLocalVariable == null) { throw new ArgumentNullException("variable"); } this.generator.Emit(OpCodes.Stloc, ((ReflectionEmitILLocalVariable)variable).UnderlyingLocal); }
/// <summary> /// Outputs an instruction and a variable to the log. /// </summary> /// <param name="instruction"> The instruction to output. </param> /// <param name="variable"> The variable to output. </param> private void Log(string instruction, ILLocalVariable variable) { if (variable.Name == null) { LogInstruction(instruction, string.Format("V{0}", variable.Index)); } else { LogInstruction(instruction, string.Format("V{0} ({1})", variable.Index, variable.Name)); } }
/// <summary> /// Indicates that the given temporary variable is no longer needed. /// </summary> /// <param name="temporaryVariable"> The temporary variable created using CreateTemporaryVariable(). </param> public void ReleaseTemporaryVariable(ILLocalVariable temporaryVariable) { if (temporaryVariable == null) { throw new ArgumentNullException("temporaryVariable"); } if (this.temporaryVariables == null) { this.temporaryVariables = new List <ILLocalVariable>(); } this.temporaryVariables.Add(temporaryVariable); }
/// <summary> /// Pops the value from the top of the stack and stores it in the given local variable. /// </summary> /// <param name="variable"> The variable to store the value. </param> public override void StoreVariable(ILLocalVariable variable) { Log("stloc", variable); this.generator.StoreVariable(variable); }
/// <summary> /// Pushes the address of the given variable onto the stack. /// </summary> /// <param name="variable"> The variable whose address will be pushed. </param> public override void LoadAddressOfVariable(ILLocalVariable variable) { Log("ldloca", variable); this.generator.LoadAddressOfVariable(variable); }
public TemporaryVariableExpression(ILLocalVariable variable) { this.variable = variable; }
/// <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, bool rIU, Type valueType, SetValueMethod value, bool throwIfUnresolvable) { if (ResolvedProperty == null) { // Dynamic property access // ----------------------- // xxx = object.Set(x) // Load the left-hand side: var lhs = this.GetOperand(0); // -- Begin args for Prototype.SetPropertyValue -- // Script engine (engine): EmitHelpers.LoadEngine(generator); // Put LHS object onto stack now (thisObj): lhs.GenerateCode(generator, optimizationInfo); // What type have we now got on the stack? Typically expected to be 'object'. Type lhsType = lhs.GetResultType(optimizationInfo); // Ensure it's boxed (still thisObj): EmitConversion.ToAny(generator, lhsType); // Load the property name and convert to a string. var rhs = this.GetOperand(1); rhs.GenerateCode(generator, optimizationInfo); EmitConversion.ToString(generator, rhs.GetResultType(optimizationInfo)); if (rIU) { // Output the value now (twice): value(true); // We now have [obj][value][value] on the stack. // Calling the set method would fail (as it'll operate on the duplicated value). // So, we have to pop one off and re-add it after. // In order for SetValue to work, we need to shove the 2nd copy into a temp variable. ILLocalVariable localVar = generator.DeclareVariable(valueType); // Store into the local: generator.StoreVariable(localVar); // Set the value: generator.Call(ReflectionHelpers.Object_SetPropertyValue); // Load from the local: generator.LoadVariable(localVar); } else { // Output the value now: value(false); // Set the value: generator.Call(ReflectionHelpers.Object_SetPropertyValue); } } else if (isArrayIndex) { // Array indexer // ------------- // object[index] = x // Load the left-hand side and convert to an object instance. var lhs = this.GetOperand(0); lhs.GenerateCode(generator, optimizationInfo); // Load the right-hand side and convert to int32/uint32/whatever the indexer function wants. var rhs = this.GetOperand(1); rhs.GenerateCode(generator, optimizationInfo); // Convert the index: EmitConversion.Convert(generator, rhs.GetResultType(optimizationInfo), ResolvedProperty.FirstIndexType); // Call set: ResolvedProperty.Set(generator, optimizationInfo, rIU, valueType, value); } else { // Named property modification (e.g. x.property = y) // ------------------------------------------------- if (ResolvedProperty.HasEngine) { // Emit the engine ref: EmitHelpers.LoadEngine(generator); } if (ResolvedProperty.HasAccessor) { // Load the left-hand side: var lhs = GetOperand(0); lhs.GenerateCode(generator, optimizationInfo); } // Target object is now on the stack. // Set it: ResolvedProperty.Set(generator, optimizationInfo, rIU, valueType, value); } }
/// <summary> /// Pops the value from the top of the stack and stores it in the given local variable. /// </summary> /// <param name="variable"> The variable to store the value. </param> public abstract void StoreVariable(ILLocalVariable variable);
/// <summary> /// Pushes the address of the given variable onto the stack. /// </summary> /// <param name="variable"> The variable whose address will be pushed. </param> public abstract void LoadAddressOfVariable(ILLocalVariable variable);
/// <summary> /// Pushes the value of the given variable onto the stack. /// </summary> /// <param name="variable"> The variable whose value will be pushed. </param> public abstract void LoadVariable(ILLocalVariable variable);