internal LockReplacer(SourceMethodBody sourceMethodBody) { Contract.Requires(sourceMethodBody != null); this.host = sourceMethodBody.host; Contract.Assume(sourceMethodBody.host != null); this.sourceLocationProvider = sourceMethodBody.sourceLocationProvider; this.numberOfReferencesToLocal = sourceMethodBody.numberOfReferencesToLocal; Contract.Assume(sourceMethodBody.numberOfReferencesToLocal != null); this.numberOfAssignmentsToLocal = sourceMethodBody.numberOfAssignmentsToLocal; Contract.Assume(sourceMethodBody.numberOfAssignmentsToLocal != null); this.bindingsThatMakeALastUseOfALocalVersion = sourceMethodBody.bindingsThatMakeALastUseOfALocalVersion; Contract.Assume(sourceMethodBody.bindingsThatMakeALastUseOfALocalVersion != null); var systemThreading = new Immutable.NestedUnitNamespaceReference(this.host.PlatformType.SystemObject.ContainingUnitNamespace, this.host.NameTable.GetNameFor("Threading")); var systemThreadingMonitor = new Immutable.NamespaceTypeReference(this.host, systemThreading, this.host.NameTable.GetNameFor("Monitor"), 0, isEnum: false, isValueType: false, typeCode: PrimitiveTypeCode.NotPrimitive); var parameters = new IParameterTypeInformation[2]; this.monitorEnter = new MethodReference(this.host, systemThreadingMonitor, CallingConvention.Default, this.host.PlatformType.SystemVoid, this.host.NameTable.GetNameFor("Enter"), 0, parameters); parameters[0] = new SimpleParameterTypeInformation(monitorEnter, 0, this.host.PlatformType.SystemObject); parameters[1] = new SimpleParameterTypeInformation(monitorEnter, 1, this.host.PlatformType.SystemBoolean, isByReference: true); this.monitorExit = new MethodReference(this.host, systemThreadingMonitor, CallingConvention.Default, this.host.PlatformType.SystemVoid, this.host.NameTable.GetNameFor("Exit"), 0, this.host.PlatformType.SystemObject); }
/// <summary> /// Generates IL for the specified lock statement. /// </summary> /// <param name="lockStatement">The lock statement.</param> public override void TraverseChildren(ILockStatement lockStatement) { if (this.host.SystemCoreAssemblySymbolicIdentity.Version.Major < 4) { this.GenerateDownLevelLockStatement(lockStatement); return; } var systemThreading = new NestedUnitNamespaceReference(this.host.PlatformType.SystemObject.ContainingUnitNamespace, this.host.NameTable.GetNameFor("Threading")); var systemThreadingMonitor = new NamespaceTypeReference(this.host, systemThreading, this.host.NameTable.GetNameFor("Monitor"), 0, isEnum: false, isValueType: false, typeCode: PrimitiveTypeCode.NotPrimitive); var parameters = new IParameterTypeInformation[2]; var monitorEnter = new MethodReference(this.host, systemThreadingMonitor, CallingConvention.Default, this.host.PlatformType.SystemVoid, this.host.NameTable.GetNameFor("Enter"), 0, parameters); parameters[0] = new SimpleParameterTypeInformation(monitorEnter, 0, this.host.PlatformType.SystemObject); parameters[1] = new SimpleParameterTypeInformation(monitorEnter, 1, this.host.PlatformType.SystemBoolean, isByReference: true); var monitorExit = new MethodReference(this.host, systemThreadingMonitor, CallingConvention.Default, this.host.PlatformType.SystemVoid, this.host.NameTable.GetNameFor("Exit"), 0, this.host.PlatformType.SystemObject); this.EmitSequencePoint(lockStatement.Locations); var guardObject = new TemporaryVariable(lockStatement.Guard.Type, this.method); var lockTaken = new TemporaryVariable(this.host.PlatformType.SystemBoolean, this.method); //try var savedCurrentTryCatch = this.currentTryCatch; this.currentTryCatch = lockStatement; var savedCurrentTryCatchFinallyEnd = this.currentTryCatchFinallyEnd; this.currentTryCatchFinallyEnd = new ILGeneratorLabel(); this.generator.BeginTryBody(); this.Traverse(lockStatement.Guard); this.generator.Emit(OperationCode.Dup); this.StackSize++; this.VisitAssignmentTo(guardObject); this.LoadAddressOf(lockTaken, null); this.generator.Emit(OperationCode.Call, monitorEnter); this.StackSize-=2; this.Traverse(lockStatement.Body); if (!this.lastStatementWasUnconditionalTransfer) this.generator.Emit(OperationCode.Leave, this.currentTryCatchFinallyEnd); //finally this.generator.BeginFinallyBlock(); //if (status) var endIf = new ILGeneratorLabel(); this.LoadLocal(lockTaken); this.generator.Emit(OperationCode.Brfalse_S, endIf); this.StackSize--; this.LoadLocal(guardObject); this.generator.Emit(OperationCode.Call, monitorExit); this.StackSize--; this.generator.MarkLabel(endIf); //monitor exit this.generator.Emit(OperationCode.Endfinally); this.generator.EndTryBody(); this.generator.MarkLabel(this.currentTryCatchFinallyEnd); this.currentTryCatchFinallyEnd = savedCurrentTryCatchFinallyEnd; this.currentTryCatch = savedCurrentTryCatch; this.lastStatementWasUnconditionalTransfer = false; }