예제 #1
0
        public CurveComponent(Component parent, OptimizationWorker optimizationWorker, Specification specification) : base(parent)
        {
            if (optimizationWorker == null)
            {
                throw new ArgumentNullException("optimizationWorker");
            }

            this.curveOptimizer = new CurveOptimizer(optimizationWorker, specification);
            this.curveOptimizer.CurveChanged += CurveChanged;

            this.curveStartComponent     = new FixedPositionComponent(this, this, 0);
            this.curveEndComponent       = new FixedPositionComponent(this, this, 1);
            this.specificationComponents = new List <SpecificationComponent>();
            this.segmentComponents       = new List <SegmentComponent>();

            nextSpecification = specification.BasicSpecification;
            curve             = null;

            RebuildSegmentComponents();

            curveOptimizer.Submit(nextSpecification);

            IEnumerable <SpecificationComponent> specificationComponents =
                (
                    from spec in nextSpecification.CurveSpecifications
                    orderby spec.Position ascending
                    group spec by spec.Position into specificationGroup
                    select new SpecificationComponent(this, this, specificationGroup.Key, specificationGroup)
                );

            foreach (SpecificationComponent component in specificationComponents)
            {
                AddSpecificationComponent(component);
            }
        }
        /// <summary>
        /// Performs the optimization starting at the current instruction.
        /// </summary>
        /// <param name="instruction">The instruction to target.</param>
        /// <param name="worker">The worker for optimization actions.</param>
        public override void OptimizeInstruction(Instruction instruction, OptimizationWorker worker)
        {
            // TODO: allow arguments
            // TODO: allow return values
            // TODO: allow generic methods
            // TODO: allow non-static methods
            var opCode = instruction.OpCode;
            if (opCode.FlowControl != FlowControl.Call)
            {
                return;
            }

            var methodRef = (MethodReference) instruction.Operand;
            var typeRef = methodRef.DeclaringType;
            var module = typeRef.Module;

            var type = module.Types[typeRef.FullName];
            if (type == null)
            {
                return;
            }

            var method = type.Methods.GetMethod(methodRef.Name, methodRef.Parameters);
            bool shouldInlineMethod;
            if (!this.shouldInline.TryGetValue(method, out shouldInlineMethod))
            {
                shouldInlineMethod = this.configuration.ShouldInline(method);
                this.shouldInline[method] = shouldInlineMethod;
            }

            if (shouldInlineMethod)
            {
                InlineMethod(instruction, worker, method);
            }
        }
예제 #3
0
 /// <summary>
 /// Performs the optimization starting at the current instruction.
 /// </summary>
 /// <param name="instruction">The instruction to target.</param>
 /// <param name="worker">The worker for optimization actions.</param>
 public override void OptimizeInstruction(Instruction instruction, OptimizationWorker worker)
 {
     var opCode = instruction.OpCode;
     if (opCode.Code == Code.Nop)
     {
         worker.DeleteInstruction(instruction);
     }
 }
예제 #4
0
        public CurveOptimizer(OptimizationWorker optimizationWorker, Specification specification)
        {
            if (optimizationWorker == null)
            {
                throw new ArgumentNullException("optimizationWorker");
            }

            this.optimizer          = new Optimizer();
            this.optimizationWorker = optimizationWorker;

            this.specification = specification;
        }
 /// <summary>
 /// Performs the optimization starting at the current instruction.
 /// </summary>
 /// <param name="instruction">The instruction to target.</param>
 /// <param name="worker">The worker for optimization actions.</param>
 public override void OptimizeInstruction(Instruction instruction, OptimizationWorker worker)
 {
     var opCode = instruction.OpCode;
     if (opCode.FlowControl == FlowControl.Branch ||
         opCode.FlowControl == FlowControl.Cond_Branch)
     {
         var target = (Instruction)instruction.Operand;
         if (target.OpCode.FlowControl == FlowControl.Branch)
         {
             instruction.Operand = target.Operand;
         }
     }
 }
예제 #6
0
        /// <summary>
        /// Performs the optimization starting at the current instruction.
        /// </summary>
        /// <param name="instruction">The instruction to target.</param>
        /// <param name="worker">The worker for optimization actions.</param>
        public override void OptimizeInstruction(Instruction instruction, OptimizationWorker worker)
        {
            // the first instruction in a method is not dead code
            if (instruction.Previous == null)
            {
                return;
            }

            var sources = worker.SourceInstructions(instruction);
            if (sources.Count == 0)
            {
                worker.DeleteInstruction(instruction);
            }
        }
예제 #7
0
 /// <summary>
 /// Performs the optimization starting at the current instruction.
 /// </summary>
 /// <param name="instruction">The instruction to target.</param>
 /// <param name="worker">The worker for optimization actions.</param>
 public override void OptimizeInstruction(Instruction instruction, OptimizationWorker worker)
 {
     var opCode = instruction.OpCode;
     if (opCode.FlowControl == FlowControl.Branch)
     {
         var target = (Instruction)instruction.Operand;
         var targetOpCode = target.OpCode;
         if (targetOpCode.FlowControl == FlowControl.Return ||
             targetOpCode.FlowControl == FlowControl.Throw)
         {
             var replacement = worker.CilWorker.Create(targetOpCode);
             worker.ReplaceInstruction(instruction, replacement);
         }
     }
 }
 /// <summary>
 /// Performs the optimization starting at the current instruction.
 /// </summary>
 /// <param name="instruction">The instruction to target.</param>
 /// <param name="worker">The worker for optimization actions.</param>
 public override void OptimizeInstruction(Instruction instruction, OptimizationWorker worker)
 {
     // TODO: currently if an optimization removes an instruction between a branch and its
     // target, this will not trigger, since the target instruction will be the one after the
     // branch.
     //   This can be solved by adding a property to the optimization indicating how many
     // instructions ahead can affect its application.
     var opCode = instruction.OpCode;
     if (opCode.FlowControl == FlowControl.Branch ||
         opCode.FlowControl == FlowControl.Cond_Branch)
     {
         var target = instruction.Operand as Instruction;
         if (target == instruction.Next)
         {
             worker.DeleteInstruction(instruction);
         }
     }
 }
예제 #9
0
        public RootComponent(Window parentWindow, IEnumerable <string> parameters)
        {
            if (parentWindow == null)
            {
                throw new ArgumentNullException("parentWindow");
            }

            if (parameters.Count() > 1)
            {
                throw new ArgumentException("parameter 'parameters' contained more than one item.");
            }

            this.parentWindow       = parentWindow;
            this.optimizationWorker = new OptimizationWorker();
            if (parameters.Count() == 1)
            {
                this.backgroundComponent = new BackgroundComponent(this, parameters.Single());
            }
            this.curveComponents = new List <CurveComponent>();
        }
예제 #10
0
        /// <summary>
        /// Inlines the supplied method.
        /// </summary>
        /// <param name="callInstruction">The call instruction.</param>
        /// <param name="worker">The worker to use to modify the caller, positioned at the call instruction.</param>
        /// <param name="method">The method to inline.</param>
        private static void InlineMethod(
            Instruction callInstruction,
            OptimizationWorker worker,
            MethodDefinition method)
        {
            worker.Optimize(method);

            // replace the call with a nop in order to preserve branches to this call.
            var nop = worker.CilWorker.Create(OpCodes.Nop);
            worker.ReplaceInstruction(callInstruction, nop);

            var nextInstruction = callInstruction.Next;

            var instructions = method.Body.Instructions;
            var instructionCount = instructions.Count;
            if (instructionCount == 0)
            {
                // TODO: can this happen?
                // do all methods end with a ret instruction?
                return;
            }

            var instruction = instructions[0];
            if (instruction.OpCode.FlowControl == FlowControl.Return)
            {
                return;
            }

            // Create local variables to be used by the inlined function
            var variables = method.Body.Variables;
            for (var i = 0; i < variables.Count; i++)
            {
                var variable = variables[i];
                worker.AddLocalVariable(variable);
            }

            // TODO: try to avoid this extra dictionary.

            // This mapping maps an instruction to the inlined version.  This is required in order to
            // patch up backwards branch instructions to reference an instruction in the current method.
            var copiedInstructions = new Dictionary<Instruction, Instruction>();

            for (var i = 0; i < instructionCount; i++)
            {
                var currentInstruction = instructions[i];
                int location;

                Instruction newInstruction;

                if (currentInstruction.OpCode.FlowControl == FlowControl.Return)
                {
                    // return instructions now just move execution to the instruction after the call

                    // TODO: create best form of br instruction
                    newInstruction = worker.CilWorker.Create(OpCodes.Br, nextInstruction);
                }
                else if (currentInstruction.OpCode.FlowControl == FlowControl.Branch ||
                         currentInstruction.OpCode.FlowControl == FlowControl.Cond_Branch)
                {
                    // if we are jumping to an earlier instruction in the method, then create a jump
                    // to the cloned version.
                    var target = (Instruction) currentInstruction.Operand;

                    Instruction inlinedTarget;
                    if (!copiedInstructions.TryGetValue(target, out inlinedTarget))
                    {
                        inlinedTarget = target;
                    }

                    // TODO: if this is a short branch this may need converting to a long branch
                    // as for example "ret" instructions may have been converted to branches in
                    // the intervening space.
                    newInstruction = worker.CilWorker.Create(currentInstruction.OpCode, inlinedTarget);
                }
                else if (currentInstruction.IsLdloc(out location))
                {
                    var variable = variables[location];

                    // TODO: create the best form of ldloc instruction
                    newInstruction = worker.CilWorker.Create(OpCodes.Ldloc, variable);
                }
                else if (currentInstruction.IsLdloca(out location))
                {
                    var variable = variables[location];

                    // TODO: create the best form of ldloca instruction
                    newInstruction = worker.CilWorker.Create(OpCodes.Ldloca, variable);
                }
                else if (currentInstruction.IsStloc(out location))
                {
                    var variable = variables[location];

                    // TODO: create the best form of ldloca instruction
                    newInstruction = worker.CilWorker.Create(OpCodes.Stloc, variable);
                }
                else
                {
                    newInstruction = worker.CopyInstruction(currentInstruction);
                }

                worker.InsertBefore(nextInstruction, newInstruction);

                copiedInstructions.Add(currentInstruction, newInstruction);
                worker.RetargetBranches(currentInstruction, newInstruction);
            }
        }