protected override void ProcessMethod(MethodDefinition method) { if (!method.HasBody || method.IsCompilerControlled) { return; } try { MethodEditor.SimplifyMacros(method.Body); _collectionsStep.Process(method); if (!HasFieldAccesses(method)) { return; } InstrumentFieldAccesses(method); PatchBaseConstructorInvocationOrderIfRequired(method); } finally { MethodEditor.OptimizeMacros(method.Body); } }
private void InsertActivateCall(MethodEditor cil, Instruction insertionPoint, Instruction loadReferenceInstruction, ActivationPurpose activationPurpose) { cil.InsertBefore(insertionPoint, loadReferenceInstruction); cil.InsertBefore(insertionPoint, cil.Create(OpCodes.Ldc_I4, (int)activationPurpose)); cil.InsertBefore(insertionPoint, cil.Create(OpCodes.Callvirt, ActivateMethodRef())); }
private static VariableDefinition SaveStackTop(MethodEditor cil, Instruction instruction) { VariableDefinition oldStackTop = cil.AddVariable(Resolve(instruction).FieldType); cil.InsertBefore(GetInsertionPoint(instruction), cil.Create(OpCodes.Stloc, oldStackTop)); return(oldStackTop); }
private void ProcessFieldSetter(Instruction instruction, MethodEditor cil) { VariableDefinition oldStackTop = SaveStackTop(cil, instruction); Instruction insertionPoint = GetInsertionPoint(instruction); InsertActivateCall(cil, insertionPoint, ActivationPurpose.Write); cil.InsertBefore(insertionPoint, cil.Create(OpCodes.Ldloc, oldStackTop)); }
private void InstrumentFieldAccesses(MethodDefinition method) { MethodEditor editor = new MethodEditor(method); foreach (Instruction instruction in FieldAccesses(method.Body)) { ProcessFieldAccess(editor, instruction); } }
private void ProcessFieldAccess(MethodEditor cil, Instruction instruction) { if (IsFieldGetter(instruction)) { ProcessFieldGetter(instruction, cil); } else { ProcessFieldSetter(instruction, cil); } }
private void InsertActivateCall(MethodEditor cil, Instruction insertionPoint, ActivationPurpose activationPurpose) { Instruction previous = insertionPoint.Previous; if (previous.OpCode == OpCodes.Ldarg) { Instruction newLoadInstruction = cil.Create(previous.OpCode, (ParameterDefinition)previous.Operand); InsertActivateCall(cil, previous, newLoadInstruction, activationPurpose); } else { InsertActivateCall(cil, insertionPoint, cil.Create(OpCodes.Dup), activationPurpose); } }
private void ProcessFieldGetter(Instruction instruction, MethodEditor cil) { Instruction insertionPoint = GetInsertionPoint(instruction); InsertActivateCall(cil, insertionPoint, ActivationPurpose.Read); }