Example #1
0
        private Task <MethodBody> OptimizeBodyOrWaitAsync(
            IMethod requestedDef,
            MethodBodyHolder requestedHolder)
        {
            lock (graphLock)
            {
                if (IsActive(requestedDef) || IsComplete(requestedDef))
                {
                    // If the method is already being optimized then we can just
                    // wait for it to finish. If the method has already been optimized,
                    // then we're already done.
                    return(Start(requestedDef));
                }
                else
                {
                    // The method's not being optimized yet. Claim it by starting its
                    // optimization process. We'll actually optimize the method once
                    // we get out of the lock.
                    Start(requestedDef);
                }
            }

            // Actually optimize the method's body.
            return(OptimizeBodyAsync(requestedDef, requestedHolder));
        }
Example #2
0
        private async Task <MethodBody> OptimizeBodyAsync(
            IMethod requestedDef,
            MethodBodyHolder requestedHolder)
        {
            // Get the method's initial body.
            var body = requestedHolder.Body;

            // Create optimization state.
            var state = new OptimizationState(requestedDef, this);

            // Apply passes from the pipeline until we're done.
            foreach (var pass in pipeline)
            {
                body = await pass.ApplyAsync(body, state);

                if (pass.IsCheckpoint)
                {
                    // Update the method body for the method if we've
                    // reached a checkpoint.
                    requestedHolder.Body = body;
                }
            }
            requestedHolder.Body = body;
            return(body);
        }
Example #3
0
        private Task <MethodBody> OptimizeBodyOrWaitAsync(
            IMethod requestedDef,
            IMethod requestingDef,
            MethodBodyHolder requestedHolder)
        {
            lock (graphLock)
            {
                // Make sure that the method that's requesting the dependency
                // is marked as started.
                Start(requestingDef);

                // Get the dependency set for the requesting method.
                var requestingDependencies = dependencies[requestingDef];

                if (requestingDependencies.Contains(requestedDef) ||
                    IsComplete(requestedDef))
                {
                    // If the requesting method is already dependent on the
                    // requested method, then we can just proceed. Ditto for
                    // methods that are fully optimized already.
                    return(Start(requestedDef));
                }
                else if (!IsActive(requestedDef))
                {
                    // Looks like the method simply isn't being optimized yet.
                    // This will work to our advantage.
                    requestingDependencies.Add(requestedDef);

                    // "Start" the requested method's optimization to avoid
                    // race conditions where two threads try to optimize the
                    // same method.
                    Start(requestedDef);
                }
                else
                {
                    // Okay, so both methods are currently being optimized and the
                    // requesting method is not yet dependent on the requesting
                    // method. What we need to figure out now is whether introducing
                    // a dependency on the requested method would introduce a cycle
                    // in the dependency graph. Such a cycle means a deadlock, so we
                    // absolutely cannot let that happen.
                    if (IsDependentOn(requestingDef, requestedDef))
                    {
                        // Introducing a dependency would create a cycle. Return
                        // the latest version of the requested method's body and
                        // call it a day.
                        return(Task.FromResult(requestedHolder.Body));
                    }
                    else
                    {
                        // Introducing a dependency would not create a cycle. Add the
                        // dependency and wait for the other method to finish.
                        requestingDependencies.Add(requestedDef);
                        return(Start(requestedDef));
                    }
                }
            }

            // The requested method isn't active yet. We'll just optimize it ourselves.
            return(OptimizeBodyAsync(requestedDef, requestedHolder));
        }