public ResolutionException (MemberReference member) : base ("Failed to resolve " + member.FullName) { if (member == null) throw new ArgumentNullException ("member"); this.member = member; }
public void AddMemberReference (MemberReference member) { MemberReferences [member.token.RID - 1] = member; }
private void ExecuteMethod(out ObjectInstance retVal, out bool doJmpCall, out MemberReference jmpCallToken) { jmpCallToken = null; doJmpCall = false; retVal = null; EvalLoop: try { this.ExecuteMethodCore(out retVal, out doJmpCall, out jmpCallToken); } catch (InazumaRuntimeException ex) { // TODO: check throwable // TODO: isuncatchable (ThreadAbort) var handleEx = false; if (_methInfo2.Body.HasExceptionHandlers) { var curOffset = _instructions[_instructionPtr].Offset; // Perform a filter scan or regular walk of the EH Table. Filter scan is performed when // we are evaluating a series of filters to handle the exception until the first handler // (filter's or otherwise) that will handle the exception. foreach (var exceptionHandler in _methInfo2.Body.ExceptionHandlers) { var handlerOffset = 0; // First, is the current offset in the try block? if (exceptionHandler.TryStart.Offset <= curOffset && exceptionHandler.TryEnd.Offset >= curOffset) { // CORINFO_EH_CLAUSE_NONE represents 'catch' blocks if (exceptionHandler.FilterStart == null) { // Now, does the catch block handle the thrown exception type? var excType = _classLoader.LoadTypeFromTypeRef(exceptionHandler.CatchType); if (ex.ExceptionObject.MethodTable == excType) { _opStack.Clear(); _opStack.Push(ex.ExceptionObject); handlerOffset = _instructions.Select((x, i) => new { Index = i, IsMatched = x == exceptionHandler.HandlerStart }).First(x => x.IsMatched).Index; // TODO: FIXME handleEx = true; //_filterNextScan = 0; } } else { throw ThrowHelper.NotImplementedYet; } // Reset the interpreter loop in preparation of calling the handler. if (handleEx) { // Set the IL offset of the handler. _instructionPtr = handlerOffset; // If an exception occurs while attempting to leave a protected scope, // we empty the 'leave' info stack upon entering the handler. // TODO: infoStack // Some things are set up before a call, and must be cleared on an exception caught be the caller. // A method that returns a struct allocates local space for the return value, and "registers" that // space and the type so that it's scanned if a GC happens. "Unregister" it if we throw an exception // in the call, and handle it in the caller. (If it's not handled by the caller, the Interpreter is // deallocated, so it's value doesn't matter.) _callThisArg = null; _args.Clear(); break; } } } } if (handleEx) { goto EvalLoop; } else { throw; } } }
private void ExecuteMethodCore(out ObjectInstance retVal, out bool doJmpCall, out MemberReference jmpCallToken) { jmpCallToken = null; doJmpCall = false; retVal = null; for (; _instructions.Length > _instructionPtr; _instructionPtr++) { var inst = _instructions[_instructionPtr]; if (inst.OpCode == OpCodes.Nop) { continue; } else if (inst.OpCode == OpCodes.Break) { continue; } else if (inst.OpCode == OpCodes.Ldarg_0) { LdArg(0); continue; } else if (inst.OpCode == OpCodes.Ldarg_1) { LdArg(1); continue; } else if (inst.OpCode == OpCodes.Ldarg_2) { LdArg(2); continue; } else if (inst.OpCode == OpCodes.Ldarg_3) { LdArg(3); continue; } else if (inst.OpCode == OpCodes.Ldloc_0) { LdLoc(0); continue; } else if (inst.OpCode == OpCodes.Ldloc_1) { LdLoc(1); continue; } else if (inst.OpCode == OpCodes.Ldloc_2) { LdLoc(2); continue; } else if (inst.OpCode == OpCodes.Ldloc_3) { LdLoc(3); continue; } else if (inst.OpCode == OpCodes.Stloc_0) { StLoc(0); continue; } else if (inst.OpCode == OpCodes.Stloc_1) { StLoc(1); continue; } else if (inst.OpCode == OpCodes.Stloc_2) { StLoc(2); continue; } else if (inst.OpCode == OpCodes.Stloc_3) { StLoc(3); continue; } else if (inst.OpCode == OpCodes.Ldarg_S) { // TODO: get index directly var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index; LdArg(index); continue; } else if (inst.OpCode == OpCodes.Ldarga_S) { // TODO: get index directly var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index; LdArgA(index); continue; } else if (inst.OpCode == OpCodes.Starg_S) { // TODO: get index directly var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index; StArg(index); continue; } else if (inst.OpCode == OpCodes.Ldloc_S) { // TODO: get index directly var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index; LdLoc(index); continue; } else if (inst.OpCode == OpCodes.Ldloca_S) { // TODO: get index directly var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index; LdLocA(index); continue; } else if (inst.OpCode == OpCodes.Stloc_S) { // TODO: get index directly var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index; StLoc(index); continue; } else if (inst.OpCode == OpCodes.Ldnull) { Ldnull(); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_M1) { LdIcon(-1); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_0) { LdIcon(0); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_1) { LdIcon(1); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_2) { LdIcon(2); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_3) { LdIcon(3); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_4) { LdIcon(4); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_5) { LdIcon(5); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_6) { LdIcon(6); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_7) { LdIcon(7); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_8) { LdIcon(8); continue; } else if (inst.OpCode == OpCodes.Ldc_I4_S) { LdIcon(inst.Operand); continue; } else if (inst.OpCode == OpCodes.Ldc_I4) { LdIcon(inst.Operand); continue; } else if (inst.OpCode == OpCodes.Ldstr) { LdStr(); continue; } else if (inst.OpCode == OpCodes.Ldfld) { LdFld(); continue; } else if (inst.OpCode == OpCodes.Ldflda) { LdFldA(); continue; } else if (inst.OpCode == OpCodes.Stfld) { StFld(); continue; } else if (inst.OpCode == OpCodes.Ldsfld) { LdSFld(); continue; } else if (inst.OpCode == OpCodes.Ldsflda) { LdSFldA(); continue; } else if (inst.OpCode == OpCodes.Stsfld) { StSFld(); continue; } else if (inst.OpCode == OpCodes.Stobj) { StObj(); continue; } // ... else if (inst.OpCode == OpCodes.Add) { Add(checkOverflow: false, unsigned: false); continue; } else if (inst.OpCode == OpCodes.Add_Ovf) { Add(checkOverflow: true, unsigned: false); continue; } else if (inst.OpCode == OpCodes.Add_Ovf_Un) { Add(checkOverflow: true, unsigned: true); continue; } else if (inst.OpCode == OpCodes.Sub) { Sub(checkOverflow: false, unsigned: false); continue; } else if (inst.OpCode == OpCodes.Sub_Ovf) { Sub(checkOverflow: true, unsigned: false); continue; } else if (inst.OpCode == OpCodes.Sub_Ovf_Un) { Sub(checkOverflow: true, unsigned: true); continue; } else if (inst.OpCode == OpCodes.Mul) { Mul(checkOverflow: false, unsigned: false); continue; } else if (inst.OpCode == OpCodes.Mul_Ovf) { Mul(checkOverflow: true, unsigned: false); continue; } else if (inst.OpCode == OpCodes.Mul_Ovf_Un) { Mul(checkOverflow: true, unsigned: true); continue; } else if (inst.OpCode == OpCodes.Div) { Div(checkOverflow: true, unsigned: false); continue; } else if (inst.OpCode == OpCodes.Div_Un) { Div(checkOverflow: true, unsigned: true); continue; } else if (inst.OpCode == OpCodes.Rem) { Rem(checkOverflow: true, unsigned: false); continue; } else if (inst.OpCode == OpCodes.Rem_Un) { Rem(checkOverflow: true, unsigned: true); continue; } else if (inst.OpCode == OpCodes.Newobj) { NewObj(); continue; } else if (inst.OpCode == OpCodes.Box) { // TODO: not implemented yet continue; } else if (inst.OpCode == OpCodes.Call) { Call(virtualCall: false); continue; } else if (inst.OpCode == OpCodes.Callvirt) { Call(virtualCall: true); continue; } else if (inst.OpCode == OpCodes.Ret) { // TODO: use reference or type if (_methInfo2.ReturnType.Namespace == "System" && _methInfo2.ReturnType.Name == "Void") { Debug.Assert(_opStack.Count == 0); } else { Debug.Assert(_opStack.Count != 0); retVal = _opStack.Pop(); } return; // goto ExitEvalLoop; } else if (inst.OpCode == OpCodes.Br_S) { // TODO: below code is too slow _instructionPtr = _instructions.Select((x, i) => new { Index = i, IsMatched = x == inst.Operand }).First(x => x.IsMatched).Index - 1; // increments ops ptr after "continue;". ptr must be subtracted here. continue; } else if (inst.OpCode == OpCodes.Leave_S) { _opStack.Clear(); throw ThrowHelper.NotImplementedYet; } else if (inst.OpCode == OpCodes.Brfalse_S) { // TODO: below code is too slow var value = _opStack.Pop(); if ((value.IsReference && value.IsNull) || value.I == 0) { _instructionPtr = _instructions.Select((x, i) => new { Index = i, IsMatched = x == inst.Operand }).First(x => x.IsMatched).Index - 1; // increments ops ptr after "continue;". ptr must be subtracted here. } continue; } else if (inst.OpCode == OpCodes.Brtrue_S) { // TODO: below code is too slow var value = _opStack.Pop(); if ((value.IsReference && !value.IsNull) || value.I != 0) { _instructionPtr = _instructions.Select((x, i) => new { Index = i, IsMatched = x == inst.Operand }).First(x => x.IsMatched).Index - 1; // increments ops ptr after "continue;". ptr must be subtracted here. } continue; } // case CEE_PREFIX1: else if (inst.OpCode == OpCodes.Arglist) { throw ThrowHelper.NotImplementedYet; } else if (inst.OpCode == OpCodes.Ceq) { var value2 = _opStack.Pop(); var value1 = _opStack.Pop(); if (value1.Type == CorInfoType.Class) { _opStack.Push(ObjectInstance.FromClrObject((value1 == value2) ? 1 : 0)); } else if (value1.Type == CorInfoType.String) { _opStack.Push(ObjectInstance.FromClrObject((value1.ObjectRef == value2.ObjectRef) ? 1 : 0)); } else { _opStack.Push(ObjectInstance.FromClrObject((value1.I == value2.I) ? 1 : 0)); } continue; } else if (inst.OpCode == OpCodes.Cgt) { var value2 = _opStack.Pop().I; var value1 = _opStack.Pop().I; _opStack.Push(ObjectInstance.FromClrObject((value1 > value2) ? 1 : 0)); continue; } else if (inst.OpCode == OpCodes.Cgt_Un) { var value2 = _opStack.Pop(); var value1 = _opStack.Pop(); if (value1.Type == CorInfoType.Class) { _opStack.Push(ObjectInstance.FromClrObject((value1 != value2) ? 1 : 0)); } else if (value1.Type == CorInfoType.String) { _opStack.Push(ObjectInstance.FromClrObject((value1.ObjectRef != value2.ObjectRef) ? 1 : 0)); } else { _opStack.Push(ObjectInstance.FromClrObject(((ulong)value1.I > (ulong)value2.I) ? 1 : 0)); } continue; } else if (inst.OpCode == OpCodes.Clt) { var value2 = _opStack.Pop().I; var value1 = _opStack.Pop().I; _opStack.Push(ObjectInstance.FromClrObject((value1 < value2) ? 1 : 0)); continue; } else if (inst.OpCode == OpCodes.Clt_Un) { var value2 = (ulong)_opStack.Pop().I; var value1 = (ulong)_opStack.Pop().I; _opStack.Push(ObjectInstance.FromClrObject((value1 < value2) ? 1 : 0)); continue; } else if (inst.OpCode == OpCodes.Throw) { Throw(); continue; } throw new InazumaExecutionException("Unknown OpCode: " + inst.OpCode.ToString()); } }