예제 #1
0
 private void RewriteType(TypeDefinition type, ObserverReferences observer)
 {
     foreach (MethodDefinition method in type.Methods)
     {
         this.RewriteMethod(method, observer);
     }
 }
예제 #2
0
        /// <summary>
        /// Makes the <see cref="Observer"/> available to the given method as a variable and then
        /// applies all of the individual rewriters to the method.
        /// </summary>
        private void RewriteMethod(MethodDefinition methodDefinition, ObserverReferences observer)
        {
            if (methodDefinition.DeclaringType == observer.InstanceField.DeclaringType)
            {
                return; // don't inject on our injected type.
            }
            if (!methodDefinition.HasBody || methodDefinition.Body.Instructions.Count == 0)
            {
                return; // don't inject on method without a Body
            }
            // Inject observer instance to method.
            ILProcessor il = methodDefinition.Body.GetILProcessor();
            var         observerVariable = new VariableDefinition(observer.InstanceField.FieldType);

            il.Body.Variables.Add(observerVariable);
            Instruction start = methodDefinition.Body.Instructions[0];

            il.InsertBefore(start, il.Create(OpCodes.Ldsfld, observer.InstanceField));
            il.InsertBefore(start, il.CreateStlocBest(observerVariable));

            var context = new ObserverRewriterContext(observer, observerVariable);

            foreach (IObserverMethodRewriter rewriter in methodRewriters)
            {
                rewriter.Rewrite(methodDefinition, il, context);
            }
        }
예제 #3
0
        /// <summary>
        /// Adds a call to SpendGas from the RuntimeObserver before the given instruction.
        /// </summary>
        private static void AddSpendGasMethodBeforeInstruction(ILProcessor il, ObserverReferences observer, VariableDefinition variable, CodeSegment codeSegment)
        {
            Instruction first       = codeSegment.Instructions.First();
            Instruction newFirst    = il.CreateLdlocBest(variable);
            long        segmentCost = (long)codeSegment.CalculateGasCost().Value;

            il.Body.SimplifyMacros();
            il.InsertBefore(first, newFirst);                                         // load observer
            il.InsertBefore(first, il.Create(OpCodes.Ldc_I8, (long)segmentCost));     // load gas amount
            il.InsertBefore(first, il.Create(OpCodes.Call, observer.SpendGasMethod)); // trigger method
            il.Body.OptimizeMacros();
        }
        /// <summary>
        /// Completely rewrites a module with all of the code required to meter memory and gas.
        /// </summary>
        public ModuleDefinition Rewrite(ModuleDefinition module)
        {
            (FieldDefinition observerInstanceField, TypeDefinition observerType) = this.GetRuntimeInstance(module);
            var observer = new ObserverReferences(observerInstanceField, module);

            foreach (TypeDefinition type in module.GetTypes())
            {
                this.RewriteType(type, observer);
            }

            module.Types.Add(observerType);

            return(module);
        }
예제 #5
0
        public ModuleDefinition Rewrite(ModuleDefinition module)
        {
            Guid id = Guid.NewGuid();

            FieldDefinition observerInstanceField = GetObserverInstance(module, id);
            var             observer = new ObserverReferences(observerInstanceField, module);

            foreach (TypeDefinition type in module.Types)
            {
                RewriteType(type, observer);
            }

            ObserverInstances.Set(id, this.observerToInject);

            return(module);
        }
예제 #6
0
 public ObserverRewriterContext(ObserverReferences observer, VariableDefinition observerVariable)
 {
     this.Observer         = observer;
     this.ObserverVariable = observerVariable;
 }