Beispiel #1
0
 public void Add(CILInstruction inst, uint offset)
 {
     Contract.Requires(inst != null);
     while (_current < _buffer.Length && _buffer[_current].offset < offset)
     {
         _debugBuffer.Add(_buffer[_current++]);
     }
     if (_debugBuffer.Count > 0 && offset >= ((CILInstruction)_debugBuffer[_debugBuffer.Count - 1]).offset)
     {
         inst.offset = offset;
         _debugBuffer.Add(inst);
     }
     else
     {
         int i;
         for (i = 0; i < _debugBuffer.Count; i++)
         {
             if (_debugBuffer[i].offset > offset)
             {
                 break;
             }
         }
         inst.offset = offset;
         _debugBuffer.Insert((i > 0 ? i - 1 : i), inst);
     }
 }
        private void PerformStaticAllocationOf(InstructionNode allocation, InstructionNode assignment)
        {
            var allocatedType   = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type;
            var assignmentField = assignment.MosaField;

            // Get size of type
            int typeSize = TypeLayout.GetTypeSize(allocatedType);

            // If instruction is newarr then get the size of the element, multiply it by array size, and add array header size
            // Also need to align to a 4-byte boundary
            if (allocation.Instruction is CIL.NewarrInstruction)
            {
                int elements = GetConstant(allocation.Operand1);
                typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3);
            }

            // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name.
            var symbolName = MethodCompiler.Linker.CreateSymbol(assignmentField.FullName + "<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize);

            // Try to get typeDefinitionSymbol if allocatedType isn't a value type
            string typeDefinitionSymbol = GetTypeDefinition(allocatedType);

            if (typeDefinitionSymbol != null)
            {
                MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbolName, 0, SectionKind.ROData, typeDefinitionSymbol, 0);
            }

            var staticAddress = Operand.CreateSymbol(assignmentField.FieldType, symbolName.Name);
            var result1       = AllocateVirtualRegister(assignmentField.FieldType);

            //Operand result2 = AllocateVirtualRegister(assignmentField.FieldType);

            // Issue a load request before the newobj and before the assignment.
            new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result1, staticAddress);
            assignment.Operand1 = result1;

            // If the instruction is a newarr
            if (allocation.Instruction is CIL.NewarrInstruction)
            {
                allocation.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), allocation.Result, result1);
                return;
            }

            //new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result2, staticAddress);

            // Change the newobj to a call and increase the operand count to include the this ptr.
            // If the instruction is a newarr, then just replace with a nop instead
            allocation.Result      = null;
            allocation.ResultCount = 0;
            allocation.OperandCount++;

            for (int i = allocation.OperandCount; i > 0; i--)
            {
                var op = allocation.GetOperand(i - 1);
                allocation.SetOperand(i, op);
            }

            allocation.Operand1    = result1;
            allocation.Instruction = CILInstruction.Get(OpCode.Call);
        }
Beispiel #3
0
        protected override void Finish()
        {
            if (counts == null)
            {
                return;
            }

            int total = 0;

            for (int op = 0; op < counts.Length; op++)
            {
                int count = counts[op];

                if (count == 0)
                {
                    continue;
                }

                var cil = CILInstruction.Get((OpCode)op);

                //UpdateCounter("CILDecodingStage.OpCode." + cil.FullName, count);

                total += count;
            }

            //UpdateCounter("CILDecodingStage.CILInstructions", total);

            instruction = null;
            block       = null;
            counts      = null;
        }
        private void PerformStaticAllocationOf(Context allocation, Context assignment)
        {
            MosaType  allocatedType   = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type;
            MosaField assignmentField = (assignment.Instruction is DupInstruction) ? FindStsfldForDup(assignment).MosaField : assignment.MosaField;

            // Get size of type
            int typeSize = TypeLayout.GetTypeSize(allocatedType);

            // If instruction is newarr then get the size of the element, multiply it by array size, and add array header size
            // Also need to align to a 4-byte boundry
            if (allocation.Instruction is NewarrInstruction)
            {
                typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * (int)allocation.Previous.Operand1.ConstantSignedLongInteger) + (TypeLayout.NativePointerSize * 3);
            }

            // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name.
            var symbolName = MethodCompiler.Linker.CreateSymbol(assignmentField.FullName + @"<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize);

            // Try to get typeDefinitionSymbol if allocatedType isn't a value type
            string typeDefinitionSymbol = GetTypeDefinition(allocatedType);

            if (typeDefinitionSymbol != null)
            {
                MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, BuiltInPatch.I4, symbolName, 0, 0, typeDefinitionSymbol, SectionKind.ROData, 0);
            }

            // Issue a load request before the newobj and before the assignment.
            Operand symbol1 = InsertLoadBeforeInstruction(assignment, symbolName.Name, assignmentField.FieldType);

            assignment.Operand1 = symbol1;

            // If the instruction is a newarr and the assignment instruction is a dup then we want to remove it
            if (allocation.Instruction is NewarrInstruction && assignment.Instruction is DupInstruction)
            {
                assignment.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), assignment.Result, assignment.Operand1);
            }

            // Change the newobj to a call and increase the operand count to include the this ptr.
            // If the instruction is a newarr, then just replace with a nop instead
            allocation.ResultCount = 0;
            if (allocation.Instruction is NewarrInstruction)
            {
                allocation.OperandCount = 0;
                allocation.SetInstruction(CILInstruction.Get(OpCode.Nop));
            }
            else
            {
                Operand symbol2           = InsertLoadBeforeInstruction(allocation, symbolName.Name, assignmentField.FieldType);
                IEnumerable <Operand> ops = allocation.Operands;
                allocation.OperandCount++;
                allocation.Operand1 = symbol2;
                int i = 0;
                foreach (Operand op in ops)
                {
                    i++;
                    allocation.SetOperand(i, op);
                }
                allocation.ReplaceInstructionOnly(CILInstruction.Get(OpCode.Call));
            }
        }
        private Operand InsertLoadBeforeInstruction(Context context, string symbolName, MosaType type)
        {
            var     before = context.InsertBefore();
            Operand result = MethodCompiler.CreateVirtualRegister(type);
            Operand op     = Operand.CreateManagedSymbol(type, symbolName);

            before.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result, op);

            return(result);
        }
Beispiel #6
0
        /// <summary>
        /// Decodes the instruction stream of the reader and populates the compiler.
        /// </summary>
        /// <exception cref="InvalidMetadataException"></exception>
        private void DecodeInstructions()
        {
            block = null;

            // Prefix instruction
            bool prefix = false;

            for (int i = 0; i < MethodCompiler.Method.Code.Count; i++)
            {
                instruction = MethodCompiler.Method.Code[i];

                block = BasicBlocks.GetByLabel(instruction.Offset) ?? block;

                var op = (OpCode)instruction.OpCode;

                var cil = CILInstruction.Get(op);

                if (cil == null)
                {
                    throw new InvalidMetadataException();
                }

                // Create and initialize the corresponding instruction
                var node = new InstructionNode();
                node.Label       = instruction.Offset;
                node.HasPrefix   = prefix;
                node.Instruction = cil;

                block.BeforeLast.Insert(node);

                cil.Decode(node, this);

                prefix = (cil is PrefixInstruction);
                instructionCount++;

                bool addjmp = false;

                var flow = node.Instruction.FlowControl;

                if (flow == FlowControl.Next || flow == FlowControl.Call || flow == FlowControl.ConditionalBranch || flow == FlowControl.Switch)
                {
                    var nextInstruction = MethodCompiler.Method.Code[i + 1];

                    if (BasicBlocks.GetByLabel(nextInstruction.Offset) != null)
                    {
                        var target = GetBlockByLabel(nextInstruction.Offset);

                        var jmpNode = new InstructionNode(IRInstruction.Jmp, target);
                        jmpNode.Label = instruction.Offset;
                        block.BeforeLast.Insert(jmpNode);
                    }
                }
            }
        }
Beispiel #7
0
        private void DecodeInstructionTargets()
        {
            bool branched = false;

            for (int i = 0; i < MethodCompiler.Method.Code.Count; i++)
            {
                instruction = MethodCompiler.Method.Code[i];

                if (branched)
                {
                    GetBlockByLabel(instruction.Offset);
                    branched = false;
                }

                var op = (OpCode)instruction.OpCode;

                var cil = CILInstruction.Get(op);

                branched = cil.DecodeTargets(this);
            }
        }
Beispiel #8
0
 public DummyDelayedAction(CILInstruction sourceInstruction)
 {
     this.sourceInstruction = sourceInstruction;
 }
Beispiel #9
0
 public DelayedWait(int obj, CILInstruction sourceInstruction, int lockCount)
 {
     this.sourceInstruction = sourceInstruction;
     this.obj = obj;
     this.lockCount = lockCount;
 }
Beispiel #10
0
 public ReturnAddress(CILMethod theMethod, CILInstruction thePC)
 {
     this.theMethod = theMethod;
     this.thePC = thePC;
 }
Beispiel #11
0
        /// <summary>
        /// Performs initialization of data structure for a newly created thread
        /// It sets up the environment for the first method that runs the thread
        /// </summary>
        /// <param name="threadID">Thread id, which is the guid of the thread object</param>
        /// <param name="startingObject">The object from which the thread is started</param>
        /// <param name="startingMethod">The thread function</param>
        private void InitializeThread(int threadID, VMValue_object startingObject, CILMethod startingMethod)
        {
            this.threadID = threadID;
            currentMethod = startingMethod;
            syncState = SyncState.RUNNING;

            localVariableBlocks.Push(new VMLocalVariableBlock(this, startingMethod));
            if(startingObject != null)
                localVariableBlocks.Peek().AddArgumentFront(startingObject);
            pc = currentMethod.GetFirstInstruction();
        }
Beispiel #12
0
 public DelayedPulse(int obj, CILInstruction sourceInstruction, bool isPulseAll)
 {
     this.sourceInstruction = sourceInstruction;
     this.obj = obj;
     this.isPulseAll = isPulseAll;
 }
Beispiel #13
0
 public DelayedUnlock(int obj, CILInstruction sourceInstruction)
 {
     this.sourceInstruction = sourceInstruction;
     this.obj = obj;
 }
Beispiel #14
0
 public MergeBuffer(CILInstruction[] buffer)
 {
     _debugBuffer = new List<CILInstruction>();
     Contract.Requires(buffer != null);
     _buffer = buffer;
 }
Beispiel #15
0
 public void AddInstruction(CILInstruction inst)
 {
     instructions.Add(inst);
     inst.ParentMethod = this;
 }
Beispiel #16
0
 public bool InsertInstruction(int locationID, CILInstruction newInst)
 {
     int i;
     for(i = 0; i < instructions.Count; i++)
         if(((CILInstruction)instructions[i]).ID == locationID)
             break;
     if(i < instructions.Count)
     {
         string tmpLabel = ((CILInstruction)instructions[i]).Label;
         ((CILInstruction)instructions[i]).Label = newInst.Label;
         newInst.Label = tmpLabel;
         instructions.Insert(i, newInst);
         newInst.ParentMethod = this;
         return true;
     }
     else
         return false;
 }
Beispiel #17
0
 public CILInstruction GetNextInstruction(CILInstruction thisInst)
 {
     int i;
     for(i = 0; i < instructions.Count; i++)
         if(((CILInstruction)instructions[i]).ID == thisInst.ID)
             break;
     if(i < instructions.Count)
         return (CILInstruction)instructions[i + 1];
     else
         throw new Exception("Cannot find the next instruction");
 }
Beispiel #18
0
 public int GetInstructionIndex(CILInstruction inst)
 {
     if(inst == null)
         return -1;
     for(int i = 0; i < instructions.Count; i++)
         if(((CILInstruction)instructions[i]).ID == inst.ID)
             return i;
     throw new Exception("The instruction is not from this method");
 }
Beispiel #19
0
 public DelayedVolatileRead(int destValue, int srcValue, CILInstruction sourceInstruction)
     : base(destValue, srcValue, sourceInstruction)
 {
 }
Beispiel #20
0
 public DelayedRead(int destValue, int srcValue, CILInstruction sourceInstruction)
 {
     this.destValue = destValue;
     this.srcValue = srcValue;
     this.sourceInstruction = sourceInstruction;
 }
Beispiel #21
0
 public void Add(CILInstruction inst, uint offset)
 {
     Contract.Requires(inst != null);
     while (_current < _buffer.Length && _buffer[_current].offset < offset)
         _debugBuffer.Add(_buffer[_current++]);
     if (_debugBuffer.Count > 0 && offset >= ((CILInstruction)_debugBuffer[_debugBuffer.Count - 1]).offset)
     {
         inst.offset = offset;
         _debugBuffer.Add(inst);
     }
     else
     {
         int i;
         for (i = 0; i < _debugBuffer.Count; i++)
             if (_debugBuffer[i].offset > offset)
                 break;
         inst.offset = offset;
         _debugBuffer.Insert((i > 0 ? i - 1 : i), inst);
     }
 }
Beispiel #22
0
        /// <summary>
        /// Transform to next state by choice in the order of
        ///  .Execute the current instruction
        ///  .Complete one of the pending actions
        /// </summary>
        /// <param name="choice">Indicate the index of the transition to execute</param>
        public void Forward(int choice)
        {
            if((syncState == SyncState.RUNNING) &&
                (pc != null) &&
                (pc.CanExecute(this)))
            {
                if(choice == 0)
                {
                    if(CheckerConfiguration.DoPrintExecution)
                        Console.WriteLine("Thread {0} executing {1}", currentMethod.ToString(), pc.ToString());
                    pc = pc.Execute(this);
                    GreedyPORExecution();
                    return;
                }
                else
                {
                    choice--;
                }
            }
            // we didn't have to execute the pc
            // instead now we have to execute one of the pending actions
            for(int i = 0; i < pendingActions.Count; i++)
                if(IsDelayedActionLocal(i) == false)
                    if(CanCompleteAction(i))
                    {
                        if(pendingActions[i] is DelayedPulse)
                        {
                            DelayedPulse dp = (DelayedPulse)pendingActions[i];
                            if(dp.isPulseAll)
                                choice--;
                            else
                            {
                                int ctwo = systemState.CountThreadWaitingOn(dp.obj);
                                if(ctwo == 0)
                                    ctwo = 1;
                                choice -= ctwo;
                            }
                        }
                        else
                            choice--;

                        if(choice < 0)
                        {
                            DelayedAction da = (DelayedAction)pendingActions[i];
                            if(da is DelayedWait)
                            {
                                DelayedWait dw = (DelayedWait)da;
                                DelayedLock dl = new DelayedLock(dw.obj, dw.SourceInstruction, dw.lockCount);
                                pendingActions[i] = dl;
                            }
                            else if(da is DelayedPulse)
                            {
                                DelayedPulse dp = (DelayedPulse)da;
                                if(dp.isPulseAll == true)
                                {
                                    foreach(ThreadState ts in systemState.threads)
                                        if((ts.syncState == ThreadState.SyncState.WAITING) &&
                                            (ts.waitingOn == dp.obj))
                                        {
                                            ts.syncState = ThreadState.SyncState.RUNNING;
                                            ts.waitingOn = -1;
                                        }
                                }
                                else
                                {
                                    // only if there is at least one thread waiting we resume it
                                    // else we don't do anything in completing this pulse
                                    // in another word, the pulse signal is lost
                                    int ctwo = systemState.CountThreadWaitingOn(dp.obj);
                                    if(ctwo > 0)
                                    {
                                        for(int j = 0; j < systemState.threads.Count; j++)
                                        {
                                            ThreadState ts = (ThreadState)systemState.threads[j];
                                            if((ts.syncState == SyncState.WAITING) &&
                                                (ts.waitingOn == dp.obj))
                                            {
                                                choice++;
                                                if(choice == 0)
                                                {
                                                    ts.syncState = SyncState.RUNNING;
                                                    ts.waitingOn = -1;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                                pendingActions.RemoveAt(i);
                            }
                            else
                            {
                                pendingActions.RemoveAt(i);
                                da.Complete(this);
                            }
                            GreedyPORExecution();
                            break;
                        }
                    }
        }
Beispiel #23
0
 public CILInstructionInstance(CILInstruction instruction, CILMethodInstance methodInstance)
 {
     Instruction    = instruction;
     MethodInstance = methodInstance;
 }
Beispiel #24
0
 public CILInstruction MethodReturn()
 {
     localVariableBlocks.Pop();
     if(returnAddresses.Count == 0)
     {
         return null;
     }
     else
     {
         ReturnAddress ra = returnAddresses.Pop();
         currentMethod = ra.theMethod;
         pc = currentMethod.GetNextInstruction(ra.thePC);
         return pc;
     }
 }
Beispiel #25
0
 /// <summary>
 /// Tries to execute as many actions that are locally visible to the thread as possible
 /// </summary>
 private void GreedyPORExecution()
 {
     bool found = true;
     while(found && (systemState.IsEndState == false))
     {
         found = false;
         if((syncState == SyncState.RUNNING) &&
             (pc != null) &&
             (pc.IsThreadLocal()) &&
             (pc.CanExecute(this)))
             {
                 if(CheckerConfiguration.DoPrintExecution)
                     Console.WriteLine("Thread {0} [POR] executing {1}", currentMethod.ToString(), pc.ToString());
                 pc = pc.Execute(this);
                 found = true;
             }
         for(int i = 0; i < pendingActions.Count; i++)
         {
             if(IsDelayedActionLocal(i) &&
                 (CanCompleteAction(i)))
             {
                 // TODO: we don't check for DelayedWait and DelayedPulse
                 // special conditions here because they are always local
                 // but becareful later when we use escape analysis
                 DelayedAction da = (DelayedAction)pendingActions[i];
                 pendingActions.RemoveAt(i);
                 if(CheckerConfiguration.DoPrintExecution)
                     Console.Write("Thread {0} [POR] ", currentMethod.ToString());
                 da.Complete(this);
                 found = true;
                 break;
             }
         }
     }
 }
Beispiel #26
0
 // For normal lock, we lock only once
 public DelayedLock(int obj, CILInstruction sourceInstruction)
 {
     this.sourceInstruction = sourceInstruction;
     this.obj = obj;
     this.nTimes = 1;
 }