HRESULT Library_corlib_native_System_Reflection_RuntimeFieldInfo::GetValue___OBJECT__OBJECT( CLR_RT_StackFrame& stack ) { NATIVE_PROFILE_CLR_CORE(); TINYCLR_HEADER(); CLR_RT_HeapBlock* argObj = &stack.Arg1(); CLR_RT_FieldDef_Instance instFD; CLR_RT_TypeDef_Instance instTD; const CLR_RECORD_FIELDDEF* fd; CLR_RT_HeapBlock* obj; CLR_RT_HeapBlock dst; 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); } { dst.Assign( *obj ); #if defined(TINYCLR_APPDOMAINS) //Marshal if necessary. if(argObj->IsTransparentProxy()) { _ASSERTE(argObj->DataType() == DATATYPE_OBJECT); argObj = argObj->Dereference(); _ASSERTE(argObj != NULL && argObj->DataType() == DATATYPE_TRANSPARENT_PROXY); TINYCLR_CHECK_HRESULT(argObj->TransparentProxyValidate()); TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->MarshalObject( *obj, dst, argObj->TransparentProxyAppDomain() )); } #endif CLR_RT_HeapBlock& res = stack.PushValueAndAssign( dst ); TINYCLR_CHECK_HRESULT(res.PerformBoxingIfNeeded()); } 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 CLR_RT_HeapBlock_Delegate_List::Change( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateTarget, bool fCombine, bool fWeak ) { NATIVE_PROFILE_CLR_CORE(); TINYCLR_HEADER(); CLR_RT_HeapBlock_Delegate_List* dlgListSrc; CLR_RT_HeapBlock_Delegate_List* dlgListDst; CLR_RT_HeapBlock_Delegate* dlg; CLR_RT_HeapBlock* newDlgs; CLR_RT_HeapBlock* oldDlgs; CLR_UINT32 oldNum; CLR_UINT32 newNum; CLR_UINT32 num = 0; reference.SetObjectReference( NULL ); if(delegateSrc .DataType() != DATATYPE_OBJECT || delegateTarget.DataType() != DATATYPE_OBJECT ) { TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } dlg = delegateTarget.DereferenceDelegate(); if(dlg == NULL) { reference.SetObjectReference( delegateSrc.DereferenceDelegate() ); TINYCLR_SET_AND_LEAVE(S_OK); } if(dlg->DataType() == DATATYPE_DELEGATELIST_HEAD) { CLR_RT_HeapBlock intermediate; intermediate.Assign( delegateSrc ); CLR_RT_ProtectFromGC gc( intermediate ); dlgListDst = (CLR_RT_HeapBlock_Delegate_List*)dlg; newDlgs = dlgListDst->GetDelegates(); for(num=0; num<dlgListDst->m_length; num++, newDlgs++) { if(newDlgs->DataType() == DATATYPE_OBJECT && newDlgs->DereferenceDelegate() != NULL) // The delegate could have been GC'ed. { TINYCLR_CHECK_HRESULT(Change( reference, intermediate, *newDlgs, fCombine, fWeak )); intermediate.Assign( reference ); } } } else { dlgListSrc = delegateSrc.DereferenceDelegateList(); if(dlgListSrc == NULL) { oldDlgs = NULL; oldNum = 0; } else { switch(dlgListSrc->DataType()) { case DATATYPE_DELEGATE_HEAD: oldDlgs = &delegateSrc; oldNum = 1; break; case DATATYPE_DELEGATELIST_HEAD: oldDlgs = dlgListSrc->GetDelegates(); oldNum = dlgListSrc->m_length; break; default: TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } } if(fCombine) { if(oldNum == 0 && fWeak == false) { // // Empty input list, copy the delegate. // reference.Assign( delegateTarget ); TINYCLR_SET_AND_LEAVE(S_OK); } //--// newNum = oldNum + 1; } else { for(num=0, newDlgs=oldDlgs; num<oldNum; num++, newDlgs++) { CLR_RT_HeapBlock_Delegate* ptr = newDlgs->DereferenceDelegate(); if(ptr) { if( ptr->DelegateFtn().m_data == dlg->DelegateFtn().m_data && ptr->m_object.Dereference() == dlg->m_object.Dereference() ) { break; } } } if(num == oldNum) { reference.Assign( delegateSrc ); // Nothing to remove. TINYCLR_SET_AND_LEAVE(S_OK); } if(oldNum == 2 && (dlgListSrc->m_flags & CLR_RT_HeapBlock_Delegate_List::c_Weak) == 0) { reference.Assign( oldDlgs[ 1-num ] ); // Convert from a list to delegate. TINYCLR_SET_AND_LEAVE(S_OK); } if(oldNum == 1) { reference.SetObjectReference( NULL ); // Oops, empty delegate... TINYCLR_SET_AND_LEAVE(S_OK); } //--// newNum = oldNum - 1; } TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate_List::CreateInstance( dlgListDst, newNum )); dlgListDst->m_cls = dlg->m_cls; newDlgs = dlgListDst->GetDelegates(); if(fCombine) { newDlgs = dlgListDst->CopyAndCompress( oldDlgs, newDlgs, oldNum ); newDlgs->Assign( delegateTarget ); } else { newDlgs = dlgListDst->CopyAndCompress( oldDlgs , newDlgs, num++ ); newDlgs = dlgListDst->CopyAndCompress( oldDlgs + num, newDlgs, oldNum - num ); } dlgListDst->m_flags = (dlgListSrc && oldNum > 1) ? dlgListSrc->m_flags : 0; if(fWeak) dlgListDst->m_flags |= CLR_RT_HeapBlock_Delegate_List::c_Weak; reference.SetObjectReference( dlgListDst ); } 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 ); }
HRESULT CLR_RT_StackFrame::FixCall() { NATIVE_PROFILE_CLR_CORE(); TINYCLR_HEADER(); const CLR_RECORD_METHODDEF* target = m_call.m_target; CLR_UINT8 numArgs = target->numArgs; // // The copy of ValueTypes is delayed as much as possible. // // If an argument is a ValueType, now it's a good time to clone it. // if(numArgs) { CLR_RT_SignatureParser parser; parser.Initialize_MethodSignature( m_call.m_assm, target ); CLR_RT_SignatureParser::Element res; CLR_RT_HeapBlock* args = m_arguments; if(parser.m_flags & PIMAGE_CEE_CS_CALLCONV_HASTHIS) { args++; } // // Skip return value. // TINYCLR_CHECK_HRESULT(parser.Advance( res )); for(; parser.Available() > 0; args++) { TINYCLR_CHECK_HRESULT(parser.Advance( res )); if(res.m_levels > 0) continue; // Array, no need to fix. if(args->DataType() == DATATYPE_OBJECT) { CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( res.m_cls ); CLR_DataType dtT = (CLR_DataType)inst.m_target->dataType; const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dtT ]; if(dtl.m_flags & (CLR_RT_DataTypeLookup::c_OptimizedValueType | CLR_RT_DataTypeLookup::c_ValueType)) { CLR_RT_HeapBlock* value = args->FixBoxingReference(); FAULT_ON_NULL(value); if(value->DataType() == dtT) { // It's a boxed primitive/enum type. args->Assign( *value ); } else if(args->Dereference()->ObjectCls().m_data == res.m_cls.m_data) { TINYCLR_CHECK_HRESULT(args->PerformUnboxing( inst )); } else { TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } } } if(res.m_dt == DATATYPE_VALUETYPE && res.m_fByRef == false) { if(args->IsAReferenceOfThisType( DATATYPE_VALUETYPE )) { TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( *args, *args )); } } } } TINYCLR_NOCLEANUP(); }