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); }
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); }
/// <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); } } } }
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); } }
public DummyDelayedAction(CILInstruction sourceInstruction) { this.sourceInstruction = sourceInstruction; }
public DelayedWait(int obj, CILInstruction sourceInstruction, int lockCount) { this.sourceInstruction = sourceInstruction; this.obj = obj; this.lockCount = lockCount; }
public ReturnAddress(CILMethod theMethod, CILInstruction thePC) { this.theMethod = theMethod; this.thePC = thePC; }
/// <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(); }
public DelayedPulse(int obj, CILInstruction sourceInstruction, bool isPulseAll) { this.sourceInstruction = sourceInstruction; this.obj = obj; this.isPulseAll = isPulseAll; }
public DelayedUnlock(int obj, CILInstruction sourceInstruction) { this.sourceInstruction = sourceInstruction; this.obj = obj; }
public MergeBuffer(CILInstruction[] buffer) { _debugBuffer = new List<CILInstruction>(); Contract.Requires(buffer != null); _buffer = buffer; }
public void AddInstruction(CILInstruction inst) { instructions.Add(inst); inst.ParentMethod = this; }
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; }
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"); }
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"); }
public DelayedVolatileRead(int destValue, int srcValue, CILInstruction sourceInstruction) : base(destValue, srcValue, sourceInstruction) { }
public DelayedRead(int destValue, int srcValue, CILInstruction sourceInstruction) { this.destValue = destValue; this.srcValue = srcValue; this.sourceInstruction = sourceInstruction; }
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); } }
/// <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; } } }
public CILInstructionInstance(CILInstruction instruction, CILMethodInstance methodInstance) { Instruction = instruction; MethodInstance = methodInstance; }
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; } }
/// <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; } } } }
// For normal lock, we lock only once public DelayedLock(int obj, CILInstruction sourceInstruction) { this.sourceInstruction = sourceInstruction; this.obj = obj; this.nTimes = 1; }