HRESULT Library_corlib_native_System_Reflection_RuntimeMethodInfo::get_ReturnType___SystemType( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    CLR_RT_MethodDef_Instance md;
    CLR_RT_SignatureParser    parser;
    CLR_RT_TypeDescriptor     desc;
    CLR_RT_HeapBlock*         hbMeth = stack.Arg0().Dereference();

    TINYCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_MethodBase::GetMethodDescriptor( stack, *hbMeth, md ));

    parser.Initialize_MethodSignature( md.m_assm, md.m_target );

    TINYCLR_CHECK_HRESULT(desc.InitializeFromSignatureParser( parser ));

    {
        CLR_RT_HeapBlock& top = stack.PushValue();
        CLR_RT_HeapBlock* hbObj;
        
        TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic));
        hbObj = top.Dereference();
        hbObj->SetReflection( desc.m_reflex );
    }

    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_Reflection_RuntimeFieldInfo::get_FieldType___SystemType( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    CLR_RT_TypeDescriptor desc;
    CLR_RT_FieldDef_Instance fd;

    if(GetFieldDescriptor( stack, stack.Arg0(), fd ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE);

    TINYCLR_CHECK_HRESULT(desc.InitializeFromFieldDefinition( fd ));

    stack.PushValue().SetReflection( desc.m_handlerCls );

    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_RuntimeType::GetElementType___SystemType( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();
                
    CLR_RT_TypeDescriptor   desc;
    CLR_RT_TypeDescriptor   descSub;    
    CLR_RT_HeapBlock& top = stack.PushValueAndClear();

    TINYCLR_CHECK_HRESULT(desc.InitializeFromReflection( stack.Arg0().ReflectionDataConst() ));

    if(desc.GetElementType( descSub ))
    {
        top.SetReflection( descSub.m_reflex );
    }
        
    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_Reflection_RuntimeMethodInfo::get_ReturnType___SystemType( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    CLR_RT_MethodDef_Instance md;
    CLR_RT_SignatureParser    parser;
    CLR_RT_TypeDescriptor     desc;

    TINYCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_MethodBase::GetMethodDescriptor( stack, stack.Arg0(), md ));

    parser.Initialize_MethodSignature( md.m_assm, md.m_target );

    TINYCLR_CHECK_HRESULT(desc.InitializeFromSignatureParser( parser ));

    stack.PushValue().SetReflection( desc.m_reflex );

    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_Object::GetType___SystemType( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    CLR_RT_TypeDescriptor desc;
    CLR_RT_ReflectionDef_Index idx;
    CLR_RT_HeapBlock& arg0 = stack.Arg0();
    CLR_RT_HeapBlock* pObj;

    TINYCLR_CHECK_HRESULT(desc.InitializeFromObject( arg0 ));

    pObj = arg0.Dereference();

    if(pObj && pObj->DataType() == DATATYPE_REFLECTION)
    {
        idx.m_kind               = REFLECTION_TYPE;
        idx.m_levels             = 0;
        idx.m_data.m_type.m_data = desc.m_handlerCls.m_data;
    }
    else
    {
        idx = desc.m_reflex;
    }

    {
        CLR_RT_HeapBlock& top = stack.PushValue();
        CLR_RT_HeapBlock* hbObj;

        TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic));
        
        hbObj = top.Dereference();
        hbObj->SetReflection( idx );
    }

    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_Reflection_FieldInfo::SetValue___VOID__OBJECT__OBJECT( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    CLR_RT_FieldDef_Instance   instFD;
    CLR_RT_TypeDef_Instance    instTD;
    CLR_RT_TypeDescriptor      instTDescObj;
    CLR_RT_TypeDef_Instance    instTDField;
    const CLR_RECORD_FIELDDEF* fd;
    CLR_RT_HeapBlock*          obj;
    bool                       fValueType;
    CLR_RT_HeapBlock&          srcVal = stack.Arg2();        
    CLR_RT_HeapBlock&          srcObj = stack.Arg1();        
    CLR_RT_HeapBlock           val; val.Assign( srcVal );    
    CLR_RT_ProtectFromGC       gc( val );


    TINYCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_FieldInfo::Initialize( stack, instFD, instTD, obj ));

    fd = instFD.m_target;
    
    if(fd->flags & CLR_RECORD_FIELDDEF::FD_NoReflection) // don't allow reflection for fields with NoReflection attribute
    {
        TINYCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
    }

    TINYCLR_CHECK_HRESULT(instTDescObj.InitializeFromFieldDefinition(instFD));

    // make sure the right side object is of the same type as the left side        
    if(NULL != val.Dereference() && !CLR_RT_ExecutionEngine::IsInstanceOf(val, instTDescObj.m_handlerCls)) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);

    fValueType = obj->IsAValueType();
    if(fValueType || (c_CLR_RT_DataTypeLookup[ obj->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType))
    {
        if(val.Dereference() == NULL || !val.Dereference()->IsBoxed()) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
    
        if(fValueType)
        {
            _ASSERTE(NULL != obj->Dereference());
            if(NULL == obj->Dereference()) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
            instTDField.InitializeFromIndex( obj->Dereference()->ObjectCls() );
        }
        else
        {
            instTDField.InitializeFromIndex( *c_CLR_RT_DataTypeLookup[ obj->DataType() ].m_cls );
        }
                    
        TINYCLR_CHECK_HRESULT(val.PerformUnboxing( instTDField ));
    }
    else
    {
#if defined(TINYCLR_APPDOMAINS)
        if(srcObj.IsTransparentProxy())
        {
            _ASSERTE(srcObj.DataType() == DATATYPE_OBJECT);
            _ASSERTE(srcObj.Dereference() != NULL && srcObj.Dereference()->DataType() == DATATYPE_TRANSPARENT_PROXY);

            TINYCLR_CHECK_HRESULT(srcObj.Dereference()->TransparentProxyValidate());
            TINYCLR_CHECK_HRESULT(srcObj.Dereference()->TransparentProxyAppDomain()->MarshalObject( val, val ));
        }
#endif
    }

    switch(obj->DataType())
    {
    case DATATYPE_DATETIME: // Special case.
    case DATATYPE_TIMESPAN: // Special case.
        obj->NumericByRef().s8 = val.NumericByRefConst().s8;
        break;

    default:
        obj->Assign( val );
        break;
    }

    TINYCLR_NOCLEANUP();
}
HRESULT MethodCompiler::Opcode::Initialize( MethodCompiler* mc, CLR_OFFSET offset, CLR_OFFSET* targets )
{
    TINYCLR_HEADER();

    CLR_PMETADATA ip = mc->m_ipStart + offset;

    //--//

    memset( this, 0, sizeof(*this) );

    m_op        = CLR_ReadNextOpcodeCompressed( ip );
    m_ol        = &c_CLR_RT_OpcodeLookup[ m_op ];

    m_ipOffset  = offset;

    m_stackPop  = m_ol->StackPop ();
    m_stackPush = m_ol->StackPush();

    m_token     = CLR_EmptyToken;
    m_value.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FIRST_INVALID, 0, 1) );

    //--//

    switch(m_ol->m_opParam)
    {
    case CLR_OpcodeParam_Field:
        {
            FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip);

            m_token = arg;
        }
        break;

    case CLR_OpcodeParam_Method:
        {
            FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip);

            m_token = arg;
        }
        break;

    case CLR_OpcodeParam_Type:
        {
            FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip);

            m_token = arg;
        }
        break;

    case CLR_OpcodeParam_String:
        {
            FETCH_ARG_COMPRESSED_STRINGTOKEN(arg,ip);

            m_token = arg;
        }
        break;

    case CLR_OpcodeParam_Tok:
        {
            FETCH_ARG_TOKEN(arg,ip);

            m_token = arg;
        }
        break;

    case CLR_OpcodeParam_Sig:
        TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_UNSUPPORTED);

    case CLR_OpcodeParam_BrTarget:
        {
            FETCH_ARG_INT16(arg,ip);

            m_numTargets = 1;

            if(targets)
            {
                *targets++ = (CLR_OFFSET)(ip - mc->m_ipStart + arg);
            }
        }
        break;

    case CLR_OpcodeParam_ShortBrTarget:
        {
            FETCH_ARG_INT8(arg,ip);

            m_numTargets = 1;

            if(targets)
            {
                *targets++ = (CLR_OFFSET)(ip - mc->m_ipStart + arg);
            }
        }
        break;

    case CLR_OpcodeParam_I:
        {
            FETCH_ARG_INT32(arg,ip);

            m_value.SetInteger( arg );
        }
        break;

    case CLR_OpcodeParam_I8:
        {
            FETCH_ARG_INT64(arg,ip);

            m_value.SetInteger( arg );
        }
        break;

    case CLR_OpcodeParam_None:
        if(m_ol->m_flags & CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX)
        {
            m_value.SetInteger( (CLR_UINT32)m_ol->m_index );
        }

        if(m_ol->m_flags & CLR_RT_OpcodeLookup::ATTRIB_HAS_I4)
        {
            m_value.SetInteger( (CLR_INT32)m_ol->m_index );
        }
        break;

    case CLR_OpcodeParam_R:
        {
            FETCH_ARG_UINT64(arg,ip);

            m_value.SetDoubleFromBits( arg );
        }
        break;

    case CLR_OpcodeParam_Switch:
        {
            FETCH_ARG_UINT8(arg,ip);

            m_numTargets = arg;

            CLR_UINT32 base = (CLR_UINT32)(ip - mc->m_ipStart + arg * sizeof(CLR_INT16));

            while(arg--)
            {
                CLR_INT32 offset; TINYCLR_READ_UNALIGNED_INT16( offset, ip );

                if(targets)
                {
                    *targets++ = (CLR_OFFSET)(base + offset);
                }
            }
        }
        break;

    case CLR_OpcodeParam_Var:
        {
            FETCH_ARG_UINT16(arg,ip);

            m_value.SetInteger( (CLR_UINT32)m_ol->m_index );
        }
        break;

    case CLR_OpcodeParam_ShortI:
        {
            FETCH_ARG_INT8(arg,ip);

            m_value.SetInteger( (CLR_INT32)arg );
        }
        break;

    case CLR_OpcodeParam_ShortR:
        {
            FETCH_ARG_UINT32(arg,ip);

            m_value.SetFloatFromBits( arg );
        }
        break;

    case CLR_OpcodeParam_ShortVar:
        {
            FETCH_ARG_UINT8(arg,ip);

            m_value.SetInteger( (CLR_UINT32)arg );
        }
        break;
    }

    if(m_token != CLR_EmptyToken)
    {
        CLR_RT_Assembly* assm = mc->m_mdInst.m_assm;

        switch(CLR_TypeFromTk( m_token ))
        {
        case TBL_TypeRef:
        case TBL_TypeDef:
            {
                if(m_tdInst.ResolveToken( m_token, assm ) == false)
                {
                    TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_INVALID_TOKEN__TYPE);
                }
            }
            break;

        case TBL_MethodRef:
        case TBL_MethodDef:
            {
                if(m_mdInst.ResolveToken( m_token, assm ) == false)
                {
                    TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_INVALID_TOKEN__METHOD);
                }

                if(m_ol->m_flowCtrl == CLR_FlowControl_CALL)
                {
                    m_stackPop += m_mdInst.m_target->numArgs;

                    if(m_ol->m_logicalOpcode == LO_NewObject)
                    {
                        m_stackPop -= 1;
                    }

                    if(m_mdInst.m_target->retVal != DATATYPE_VOID)
                    {
                        m_stackPush += 1;
                    }
                }
            }
            break;

        case TBL_FieldRef:
        case TBL_FieldDef:
            {
                if(m_fdInst.ResolveToken( m_token, assm ) == false)
                {
                    TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_INVALID_TOKEN__FIELD);
                }
            }
            break;

        case TBL_TypeSpec:
            {
                CLR_RT_TypeSpec_Instance sig;
                CLR_RT_TypeDescriptor    desc;

                if(sig.ResolveToken( m_token, assm ) == false)
                {
                    TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_INVALID_TOKEN__TYPE);
                }

                TINYCLR_CHECK_HRESULT(desc.InitializeFromTypeSpec( sig ));

                m_tdInst.InitializeFromIndex( desc.m_reflex.m_data.m_type );
                m_tdInstLevels =              desc.m_reflex.m_levels;
            }
            break;

        case TBL_Strings:
            break;

        default:
            TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_INVALID_SIGNATURE);
        }
    }

    m_ipLength  = (CLR_OFFSET)(ip - mc->m_ipStart - m_ipOffset);

    TINYCLR_NOCLEANUP();
}
HRESULT CLR_RT_HeapBlock_Array::Copy( CLR_RT_HeapBlock_Array* arraySrc, int indexSrc, CLR_RT_HeapBlock_Array* arrayDst, int indexDst, int length )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    if(length)
    {
        int numElemSrc = arraySrc->m_numOfElements;
        int numElemDst = arrayDst->m_numOfElements;

        if(length   < 0                   ||
           indexSrc < 0                   ||
           indexDst < 0                   ||
           length + indexSrc > numElemSrc ||
           length + indexDst > numElemDst  )
        {
            TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
        }

        //
        // Copy of an array on itself.
        //
        if(arraySrc == arrayDst && indexSrc == indexDst) TINYCLR_SET_AND_LEAVE(S_OK);

        if(arraySrc->SameHeader( *arrayDst ))
        {
            CLR_UINT8* dataSrc  = arraySrc->GetFirstElement();
            CLR_UINT8* dataDst  = arrayDst->GetFirstElement();
            CLR_UINT8  sizeElem = arraySrc->m_sizeOfElement;

            dataSrc += indexSrc * sizeElem;
            dataDst += indexDst * sizeElem;

            if(!arraySrc->m_fReference)
            {
                memmove( dataDst, dataSrc, length * sizeElem );
            }
            else
            {
                CLR_RT_HeapBlock* ptrSrc = (CLR_RT_HeapBlock*)dataSrc;
                CLR_RT_HeapBlock* ptrDst = (CLR_RT_HeapBlock*)dataDst;
                int               incr;

                if(arraySrc == arrayDst && ptrSrc < ptrDst)
                {
                    incr    =       -1;
                    ptrSrc += length-1;
                    ptrDst += length-1;
                }
                else
                {
                    incr = 1;
                }

                for(int i=0; i<length; i++, ptrSrc += incr, ptrDst += incr)
                {
                    TINYCLR_CHECK_HRESULT(ptrDst->Reassign( *ptrSrc ));
                }
            }
        }
        else if(arraySrc->m_fReference && arrayDst->m_fReference)
        {
            CLR_RT_TypeDescriptor descSrc;
            CLR_RT_TypeDescriptor descDst;
            CLR_RT_HeapBlock*     ptrSrc   = (CLR_RT_HeapBlock*)arraySrc->GetElement( indexSrc );
            CLR_RT_HeapBlock*     ptrDst   = (CLR_RT_HeapBlock*)arrayDst->GetElement( indexDst );
            
            TINYCLR_CHECK_HRESULT(descDst.InitializeFromObject( *arrayDst )); descDst.GetElementType( descDst );

            for(int i=0; i<length; i++, ptrSrc++, ptrDst++)
            {
                if(ptrSrc->DataType() == DATATYPE_OBJECT && ptrSrc->Dereference() == NULL)
                {
                    ;
                }
                else
                {
                    TINYCLR_CHECK_HRESULT(descSrc.InitializeFromObject( *ptrSrc ));

                    if(CLR_RT_ExecutionEngine::IsInstanceOf( descSrc, descDst ) == false)
                    {
                        TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST);
                    }
                }

                TINYCLR_CHECK_HRESULT(ptrDst->Reassign( *ptrSrc ));
            }
        }
        else
        {
            CLR_RT_TypeDescriptor descSrc;
            CLR_RT_TypeDescriptor descDst;
            CLR_RT_HeapBlock      ref;
            CLR_RT_HeapBlock      elem; elem.SetObjectReference( NULL );
            CLR_RT_ProtectFromGC  gc( elem ); 

            TINYCLR_CHECK_HRESULT(descDst.InitializeFromObject( *arrayDst )); descDst.GetElementType( descDst );

            for(int i=0; i<length; i++)
            {
                ref.InitializeArrayReferenceDirect( *arraySrc, indexSrc++ ); TINYCLR_CHECK_HRESULT(elem.LoadFromReference( ref ));

                if(elem.DataType() == DATATYPE_OBJECT && elem.Dereference() == NULL)
                {
                    ;
                }
                else
                {
                    TINYCLR_CHECK_HRESULT(descSrc.InitializeFromObject( elem ));

                    if(CLR_RT_ExecutionEngine::IsInstanceOf( descSrc, descDst ) == false)
                    {
                        TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST);
                    }
                }

                ref.InitializeArrayReferenceDirect( *arrayDst, indexDst++ ); TINYCLR_CHECK_HRESULT(elem.StoreToReference( ref, 0 ));
            }
        }
    }

    TINYCLR_NOCLEANUP();
}
void CLR_RT_StackFrame::Pop()
{
    NATIVE_PROFILE_CLR_CORE();

#if defined(TINYCLR_PROFILE_NEW_CALLS)
    {
        //
        // This passivates any outstanding handler.
        //
        CLR_PROF_HANDLER_CALLCHAIN(pm2,m_callchain);

        m_callchain.Leave();
    }
#endif

#if defined(TINYCLR_PROFILE_NEW_CALLS)
    g_CLR_PRF_Profiler.RecordFunctionReturn( m_owningThread, m_callchain );
#endif

#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING)
    if(m_owningThread->m_fHasJMCStepper || (m_flags & c_HasBreakpoint))
    {
        g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Pop( this, false );
    }
#endif

    const CLR_UINT32 c_flagsToCheck = CLR_RT_StackFrame::c_CallOnPop | CLR_RT_StackFrame::c_Synchronized | CLR_RT_StackFrame::c_SynchronizedGlobally | CLR_RT_StackFrame::c_NativeProfiled;

    if(m_flags & c_flagsToCheck)
    {
        if(m_flags & CLR_RT_StackFrame::c_CallOnPop)
        {
            m_flags |= CLR_RT_StackFrame::c_CalledOnPop;

            if(m_nativeMethod)
            {
                (void)m_nativeMethod( *this );
            }
        }

        if(m_flags & CLR_RT_StackFrame::c_Synchronized)
        {
            m_flags &= ~CLR_RT_StackFrame::c_Synchronized;

            (void)HandleSynchronized( false, false );
        }

        if(m_flags & CLR_RT_StackFrame::c_SynchronizedGlobally)
        {
            m_flags &= ~CLR_RT_StackFrame::c_SynchronizedGlobally;

            (void)HandleSynchronized( false, true );
        }

#if defined(ENABLE_NATIVE_PROFILER)
        if(m_flags & CLR_RT_StackFrame::c_NativeProfiled)
        {
            m_owningThread->m_fNativeProfiled = false;
            m_flags &= ~CLR_RT_StackFrame::c_NativeProfiled;
            Native_Profiler_Stop();
        }
#endif
    }

    CLR_RT_StackFrame* caller = Caller();

    if(caller->Prev() != NULL)
    {
#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING)
        if(caller->m_flags & CLR_RT_StackFrame::c_HasBreakpoint)
        {
            g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( caller, caller->m_IP );
        }
#endif

        //
        // Constructors are slightly different, they push the 'this' pointer back into the caller stack.
        //
        // This is to enable the special case for strings, where the object can be recreated by the constructor...
        //
        if(caller->m_flags & CLR_RT_StackFrame::c_ExecutingConstructor)
        {
            CLR_RT_HeapBlock& src = this  ->Arg0              (     );
            CLR_RT_HeapBlock& dst = caller->PushValueAndAssign( src );

            dst.Promote();

            //
            // Undo the special "object -> reference" hack done by CEE_NEWOBJ.
            //
            if(dst.DataType() == DATATYPE_BYREF)
            {
                dst.ChangeDataType( DATATYPE_OBJECT );
            }

            caller->m_flags &= ~CLR_RT_StackFrame::c_ExecutingConstructor;

            _ASSERTE((m_flags & CLR_RT_StackFrame::c_AppDomainTransition) == 0);
        }
        else
        {   //Note that ExecutingConstructor is checked on 'caller', whereas the other two flags are checked on 'this'
            const CLR_UINT32 c_moreFlagsToCheck = CLR_RT_StackFrame::c_PseudoStackFrameForFilter | CLR_RT_StackFrame::c_AppDomainTransition;

            if(m_flags & c_moreFlagsToCheck)
            {
                if(m_flags & CLR_RT_StackFrame::c_PseudoStackFrameForFilter)
                {
                    //Do nothing here. Pushing return values onto stack frames that don't expect them are a bad idea.
                }
#if defined(TINYCLR_APPDOMAINS)
                else if((m_flags & CLR_RT_StackFrame::c_AppDomainTransition) != 0)
                {
                    (void)PopAppDomainTransition();
                }
#endif
            }
            else //!c_moreFlagsToCheck
            {
                //
                // Push the return, if any.
                //
                if(m_call.m_target->retVal != DATATYPE_VOID)
                {
                    if(m_owningThread->m_currentException.Dereference() == NULL)
                    {
                        CLR_RT_HeapBlock& src = this  ->TopValue          (     );
                        CLR_RT_HeapBlock& dst = caller->PushValueAndAssign( src );

                        dst.Promote();
                    }
                }
            }
        }
    }
#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING)
    else
    {
        int idx = m_owningThread->m_scratchPad;

        if(idx >= 0)
        {
            CLR_RT_HeapBlock_Array* array = g_CLR_RT_ExecutionEngine.m_scratchPadArray;

            if(array && array->m_numOfElements > (CLR_UINT32)idx)
            {
                CLR_RT_HeapBlock* dst       = (CLR_RT_HeapBlock*)array->GetElement( (CLR_UINT32)idx );
                CLR_RT_HeapBlock* exception = m_owningThread->m_currentException.Dereference();

                dst->SetObjectReference( NULL );

                if(exception != NULL)
                {
                    dst->SetObjectReference( exception );
                }
                else if(m_call.m_target->retVal != DATATYPE_VOID)
                {
                    CLR_RT_SignatureParser sig;
                    sig.Initialize_MethodSignature( this->m_call.m_assm, this->m_call.m_target );
                    CLR_RT_SignatureParser::Element res;
                    CLR_RT_TypeDescriptor           desc;

                    dst->Assign( this->TopValue() );

                    //Perform boxing, if needed.

                    //Box to the return value type
                    _SIDE_ASSERTE(SUCCEEDED(sig.Advance( res )));
                    _SIDE_ASSERTE(SUCCEEDED(desc.InitializeFromType( res.m_cls )));


                    if(c_CLR_RT_DataTypeLookup[ this->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType
                            || desc.m_handlerCls.m_target->IsEnum()
                      )
                    {
                        if(FAILED(dst->PerformBoxing( desc.m_handlerCls )))
                        {
                            dst->SetObjectReference( NULL );
                        }
                    }
                }
            }
        }
    }
#endif

    //
    // We could be jumping outside of a nested exception handler.
    //

    m_owningThread->PopEH( this, NULL );


    //
    // If this StackFrame owns a SubThread, kill it.
    //
    {
        CLR_RT_SubThread* sth = (CLR_RT_SubThread*)m_owningSubThread->Next();

        if(sth->Next() && sth->m_owningStackFrame == this)
        {
            CLR_RT_SubThread::DestroyInstance( sth->m_owningThread, sth, CLR_RT_SubThread::MODE_IncludeSelf );
        }
    }

    g_CLR_RT_EventCache.Append_Node( this );
}