public MethodTable BuildMethodTable() { _halfBakedMethodTable = new MethodTable() { MdToken = _typeDefinition.MetadataToken, ClassName = _typeDefinition.FullName, ParentMethodTable = (_typeDefinition.BaseType != null) ? _classLoader.LoadTypeFromTypeRef(_typeDefinition.BaseType) : null, EEClass = null, Interfaces = CreateInterfacesFromTypeDef(), MethodSlots = CreateMethodSlotsFromTypeDef(_typeDefinition), InterfaceMethodSlotMap = _typeDefinition.HasInterfaces ? new Dictionary <MethodReference, int>() : null, }; _halfBakedMethodTable.EEClass = new EEClass() { ParentMethodTable = ParentMethodTable, }; if (_typeDefinition.HasInterfaces) { CreateInterfaceVtableMap(); } // Go thru all fields and initialize their FieldDescs. InitializeFieldDescs(); // Place regular static fields PlaceRegularStaticFields(); // Place thread static fields PlaceThreadStaticFields(); // Create static field slots _halfBakedMethodTable.StaticFields = new ObjectInstance[HalfBakedClass.NumStaticFields + HalfBakedClass.NumThreadStaticFields]; for (var i = 0; i < _halfBakedMethodTable.StaticFields.Length; i++) { _halfBakedMethodTable.StaticFields[i] = ObjectInstance.Null; } if (false /* IsBlittable || IsManagedSequential */) { // TODO: not implemented yet } else { // HandleExplicitLayout fails for the GenericTypeDefinition when // it will succeed for some particular instantiations. // Thus we only do explicit layout for real instantiations, e.g. C<int>, not // the open types such as the GenericTypeDefinition C<!0> or any // of the "fake" types involving generic type variables which are // used for reflection and verification, e.g. C<List<!0>>. // if (false /* !bmtGenerics->fContainsGenericVariables && HasExplicitFieldOffsetLayout */) { //HandleExplicitLayout(pByValueClassCache); // TODO: not implemented yet } else { // Place instance fields PlaceInstanceFields(); } } return(_halfBakedMethodTable); }
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; } } }