public override BoundStatement InstrumentLockTargetCapture(BoundLockStatement original, BoundStatement lockTargetCapture) { LockStatementSyntax lockSyntax = (LockStatementSyntax)original.Syntax; return(new BoundSequencePointWithSpan(lockSyntax, base.InstrumentLockTargetCapture(original, lockTargetCapture), TextSpan.FromBounds(lockSyntax.LockKeyword.SpanStart, lockSyntax.CloseParenToken.Span.End))); }
public virtual BoundStatement InstrumentLockTargetCapture(BoundLockStatement original, BoundStatement lockTargetCapture) { Debug.Assert(!original.WasCompilerGenerated); Debug.Assert(original.Syntax.Kind() == SyntaxKind.LockStatement); return(lockTargetCapture); }
public override BoundStatement InstrumentLockTargetCapture(BoundLockStatement original, BoundStatement lockTargetCapture) { return(AddDynamicAnalysis(original, base.InstrumentLockTargetCapture(original, lockTargetCapture))); }
public override BoundStatement InstrumentLockTargetCapture(BoundLockStatement original, BoundStatement lockTargetCapture) { return(Previous.InstrumentLockTargetCapture(original, lockTargetCapture)); }
private BoundStatement InstrumentLockTargetCapture(BoundLockStatement original, BoundStatement lockTargetCapture) { return(this.Instrument ? _instrumenter.InstrumentLockTargetCapture(original, lockTargetCapture) : lockTargetCapture); }
/// <summary> /// Lowers a lock statement to a try-finally block that calls Monitor.Enter and Monitor.Exit /// before and after the body, respectively. /// </summary> public override BoundNode VisitLockStatement(BoundLockStatement node) { LockStatementSyntax lockSyntax = (LockStatementSyntax)node.Syntax; BoundExpression rewrittenArgument = VisitExpression(node.Argument); BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body); TypeSymbol argumentType = rewrittenArgument.Type; if ((object)argumentType == null) { // This isn't particularly elegant, but hopefully locking on null is // not very common. Debug.Assert(rewrittenArgument.ConstantValue == ConstantValue.Null); argumentType = _compilation.GetSpecialType(SpecialType.System_Object); rewrittenArgument = MakeLiteral( rewrittenArgument.Syntax, rewrittenArgument.ConstantValue, argumentType); //need to have a non-null type here for TempHelpers.StoreToTemp. } BoundAssignmentOperator assignmentToLockTemp; BoundLocal boundLockTemp = _factory.StoreToTemp(rewrittenArgument, out assignmentToLockTemp, syntaxOpt: lockSyntax, kind: SynthesizedLocalKind.Lock); BoundStatement boundLockTempInit = new BoundExpressionStatement(lockSyntax, assignmentToLockTemp); BoundExpression exitCallExpr; MethodSymbol exitMethod; if (TryGetWellKnownTypeMember(lockSyntax, WellKnownMember.System_Threading_Monitor__Exit, out exitMethod)) { exitCallExpr = BoundCall.Synthesized( lockSyntax, null, exitMethod, boundLockTemp); } else { exitCallExpr = new BoundBadExpression(lockSyntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundExpression>(boundLockTemp), ErrorTypeSymbol.UnknownResultType); } BoundStatement exitCall = new BoundExpressionStatement(lockSyntax, exitCallExpr); MethodSymbol enterMethod; if ((TryGetWellKnownTypeMember(lockSyntax, WellKnownMember.System_Threading_Monitor__Enter2, out enterMethod, isOptional: true) || TryGetWellKnownTypeMember(lockSyntax, WellKnownMember.System_Threading_Monitor__Enter, out enterMethod)) && // If we didn't find the overload introduced in .NET 4.0, then use the older one. enterMethod.ParameterCount == 2) { // C# 4.0+ version // L $lock = `argument`; // sequence point // bool $lockTaken = false; // try // { // Monitor.Enter($lock, ref $lockTaken); // `body` // sequence point // } // finally // { // hidden sequence point // if ($lockTaken) Monitor.Exit($lock); // } TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean); BoundAssignmentOperator assignmentToLockTakenTemp; BoundLocal boundLockTakenTemp = _factory.StoreToTemp( MakeLiteral(rewrittenArgument.Syntax, ConstantValue.False, boolType), store: out assignmentToLockTakenTemp, syntaxOpt: lockSyntax, kind: SynthesizedLocalKind.LockTaken); BoundStatement boundLockTakenTempInit = new BoundExpressionStatement(lockSyntax, assignmentToLockTakenTemp); BoundStatement enterCall = new BoundExpressionStatement( lockSyntax, BoundCall.Synthesized( lockSyntax, null, enterMethod, boundLockTemp, boundLockTakenTemp)); exitCall = RewriteIfStatement( lockSyntax, boundLockTakenTemp, exitCall, null, node.HasErrors); return(new BoundBlock( lockSyntax, ImmutableArray.Create(boundLockTemp.LocalSymbol, boundLockTakenTemp.LocalSymbol), ImmutableArray.Create( InstrumentLockTargetCapture(node, boundLockTempInit), boundLockTakenTempInit, new BoundTryStatement( lockSyntax, BoundBlock.SynthesizedNoLocals(lockSyntax, ImmutableArray.Create( enterCall, rewrittenBody)), ImmutableArray <BoundCatchBlock> .Empty, BoundBlock.SynthesizedNoLocals(lockSyntax, exitCall))))); } else { // Pre-4.0 version // L $lock = `argument`; // sequence point // Monitor.Enter($lock); // NB: before try-finally so we don't Exit if an exception prevents us from acquiring the lock. // try // { // `body` // sequence point // } // finally // { // Monitor.Exit($lock); // hidden sequence point // } BoundExpression enterCallExpr; if ((object)enterMethod != null) { Debug.Assert(enterMethod.ParameterCount == 1); enterCallExpr = BoundCall.Synthesized( lockSyntax, null, enterMethod, boundLockTemp); } else { enterCallExpr = new BoundBadExpression(lockSyntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundExpression>(boundLockTemp), ErrorTypeSymbol.UnknownResultType); } BoundStatement enterCall = new BoundExpressionStatement( lockSyntax, enterCallExpr); return(new BoundBlock( lockSyntax, ImmutableArray.Create(boundLockTemp.LocalSymbol), ImmutableArray.Create( InstrumentLockTargetCapture(node, boundLockTempInit), enterCall, new BoundTryStatement( lockSyntax, BoundBlock.SynthesizedNoLocals(lockSyntax, rewrittenBody), ImmutableArray <BoundCatchBlock> .Empty, BoundBlock.SynthesizedNoLocals(lockSyntax, exitCall))))); } }
public override object VisitLockStatement(BoundLockStatement node, object arg) { VisitExpression(node.Argument); VisitStatement(node.Body); return(null); }