Esempio n. 1
0
        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;
                }
            }
        }