static void * init_perf_counter (const char *category, const char *counter) { MonoString *category_str; MonoString *counter_str; MonoString *machine; MonoDomain *root; MonoBoolean custom; int type; if (category == NULL || counter == NULL) return NULL; root = mono_get_root_domain (); category_str = mono_string_new (root, category); counter_str = mono_string_new (root, counter); machine = mono_string_new (root, "."); return mono_perfcounter_get_impl (category_str, counter_str, NULL, machine, &type, &custom); }
static gboolean threadpool_start_thread (ThreadPool *tp) { gint n; guint32 stack_size; stack_size = (!tp->is_io) ? 0 : SMALL_STACK; while (!mono_runtime_is_shutting_down () && (n = tp->nthreads) < tp->max_threads) { if (InterlockedCompareExchange (&tp->nthreads, n + 1, n) == n) { #ifndef DISABLE_PERFCOUNTERS mono_perfcounter_update_value (tp->pc_nthreads, TRUE, 1); #endif mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size); return TRUE; } } return FALSE; }
gpointer mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean aot) { guint8 *tramp; guint8 *code, *buf; static int byte_offset = -1; static guint8 bitmask; guint8 *jump; gint32 displace; int tramp_size; GSList *unwind_ops = NULL; MonoJumpInfo *ji = NULL; tramp_size = 48; code = buf = mono_global_codeman_reserve (tramp_size); unwind_ops = mono_arch_get_cie_program (); if (byte_offset < 0) mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask); s390_llgc(code, s390_r0, 0, MONO_ARCH_VTABLE_REG, byte_offset); s390_nill(code, s390_r0, bitmask); s390_bnzr(code, s390_r14); tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_GENERIC_CLASS_INIT, mono_get_root_domain (), NULL); /* jump to the actual trampoline */ displace = (tramp - code) / 2; s390_jg (code, displace); mono_arch_flush_icache (buf, code - buf); g_assert (code - buf <= tramp_size); if (info) *info = mono_tramp_info_create ("generic_class_init_trampoline", buf, code - buf, ji, unwind_ops); return(buf); }
static void threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs) { static int job_counter; MonoObject *ar; gint i; if (mono_runtime_is_shutting_down ()) return; if (tp->pool_status == 0 && InterlockedCompareExchange (&tp->pool_status, 1, 0) == 0) { if (!tp->is_io) { mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK); threadpool_start_thread (tp); } /* Create on demand up to min_threads to avoid startup penalty for apps that don't use * the threadpool that much * mono_thread_create_internal (mono_get_root_domain (), threadpool_start_idle_threads, tp, TRUE, SMALL_STACK); */ } for (i = 0; i < njobs; i++) { ar = jobs [i]; if (ar == NULL || mono_domain_is_unloading (ar->vtable->domain)) continue; /* Might happen when cleaning domain jobs */ if (!tp->is_io && (InterlockedIncrement (&job_counter) % 10) == 0) { MonoAsyncResult *o = (MonoAsyncResult *) ar; o->add_time = mono_100ns_ticks (); } threadpool_jobs_inc (ar); #ifndef DISABLE_PERFCOUNTERS mono_perfcounter_update_value (tp->pc_nitems, TRUE, 1); #endif if (!tp->is_io && mono_wsq_local_push (ar)) continue; mono_cq_enqueue (tp->queue, ar); } for (i = 0; tp->waiting > 0 && i < MIN(njobs, tp->max_threads); i++) pulse_on_new_job (tp); }
void mono_runtime_setup_stat_profiler (void) { /* * Use a real-time signal when possible. This gives us roughly a 99% signal * delivery rate in all cases. On the other hand, using a regular signal * tends to result in awful delivery rates when the application is heavily * loaded. * * We avoid real-time signals on Android as they're super broken in certain * API levels (too small sigset_t, nonsensical SIGRTMIN/SIGRTMAX values, * etc). * * TODO: On Mac, we should explore using the Mach thread suspend/resume * functions and doing the stack walk from the sampling thread. This would * get us a 100% sampling rate. However, this may interfere with the GC's * STW logic. Could perhaps be solved by taking the suspend lock. */ #if defined (USE_POSIX_BACKEND) && defined (SIGRTMIN) && !defined (HOST_ANDROID) /* Just take the first real-time signal we can get. */ profiler_signal = mono_threads_suspend_search_alternative_signal (); #else profiler_signal = SIGPROF; #endif add_signal_handler (profiler_signal, profiler_signal_handler, SA_RESTART); mono_counters_register ("Sampling signals sent", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_signals_sent); mono_counters_register ("Sampling signals received", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_signals_received); mono_counters_register ("Sampling signals accepted", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_signals_accepted); mono_counters_register ("Shutdown signals received", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_interrupt_signals_received); mono_os_event_init (&sampling_thread_exited, FALSE); mono_atomic_store_i32 (&sampling_thread_running, 1); MonoError error; MonoInternalThread *thread = mono_thread_create_internal (mono_get_root_domain (), sampling_thread_func, NULL, MONO_THREAD_CREATE_FLAGS_NONE, &error); mono_error_assert_ok (&error); sampling_thread = MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid); }
static void threadpool_start_idle_threads (ThreadPool *tp) { int n; guint32 stack_size; stack_size = (!tp->is_io) ? 0 : SMALL_STACK; do { while (1) { n = tp->nthreads; if (n >= tp->min_threads) return; if (InterlockedCompareExchange (&tp->nthreads, n + 1, n) == n) break; } mono_perfcounter_update_value (tp->pc_nthreads, TRUE, 1); mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size); SleepEx (100, TRUE); } while (1); }
CScriptDomain::~CScriptDomain() { m_bDestroying = true; for each(auto assembly in m_assemblies) delete assembly; m_assemblies.clear(); if(m_bRootDomain) mono_jit_cleanup(m_pDomain); else { if(IsActive()) mono_domain_set(mono_get_root_domain(), false); mono_domain_finalize(m_pDomain, 2000); MonoObject *pException; try { mono_domain_try_unload(m_pDomain, &pException); } catch(char *ex) { MonoWarning("An exception was raised during ScriptDomain unload: %s", ex); } if(pException) { MonoWarning("An exception was raised during ScriptDomain unload:"); MonoMethod *pExceptionMethod = mono_method_desc_search_in_class(mono_method_desc_new("::ToString()", false),mono_get_exception_class()); MonoString *exceptionString = (MonoString *)mono_runtime_invoke(pExceptionMethod, pException, nullptr, nullptr); CryLogAlways(ToCryString((mono::string)exceptionString)); } } g_pScriptSystem->OnDomainReleased(this); }
void MonoManager::unloadScriptDomain() { if (mScriptDomain != nullptr) { onDomainUnload(); mono_domain_set(mono_get_root_domain(), false); mono_domain_finalize(mScriptDomain, 2000); MonoObject* exception = nullptr; mono_domain_try_unload(mScriptDomain, &exception); if (exception != nullptr) MonoUtil::throwIfException(exception); mono_gc_collect(mono_gc_max_generation()); mScriptDomain = nullptr; } for (auto& assemblyEntry : mAssemblies) { assemblyEntry.second->unload(); // Metas hold references to various assembly objects that were just deleted, so clear them Vector<ScriptMeta*>& typeMetas = getScriptMetaData()[assemblyEntry.first]; for (auto& entry : typeMetas) { entry->scriptClass = nullptr; entry->thisPtrField = nullptr; } } mAssemblies.clear(); mIsCoreLoaded = false; }
gpointer mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot) { guint8 *tramp, *code, *buf; gint16 *jump_obj_null, *jump_have_waiters, *jump_sync_null, *jump_not_owned, *jump_cs_failed, *jump_next, *jump_sync_thin_hash = NULL; int tramp_size, status_offset, nest_offset; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; int obj_reg = s390_r2, sync_reg = s390_r3, status_reg = s390_r4; g_assert (obj_reg == MONO_ARCH_MONITOR_OBJECT_REG); mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset); g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32)); g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (nest_offset) == sizeof (guint32)); status_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (status_offset); nest_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (nest_offset); tramp_size = 160; code = buf = mono_global_codeman_reserve (tramp_size); unwind_ops = mono_arch_get_cie_program (); if (mono_thread_get_tls_offset () != -1) { /* MonoObject* obj is in obj_reg */ /* is obj null? */ s390_ltgr (code, obj_reg, obj_reg); /* if yes, jump to actual trampoline */ s390_jz (code, 0); CODEPTR(code, jump_obj_null); /* load obj->synchronization to RCX */ s390_lg (code, sync_reg, 0, obj_reg, MONO_STRUCT_OFFSET (MonoObject, synchronisation)); if (mono_gc_is_moving ()) { /*if bit zero is set it's a thin hash*/ s390_tmll (code, sync_reg, 1); s390_jo (code, 0); CODEPTR(code, jump_sync_thin_hash); /* Clear bits used by the gc */ s390_nill (code, sync_reg, ~0x3); } /* is synchronization null? */ s390_ltgr (code, sync_reg, sync_reg); /* if yes, jump to actual trampoline */ s390_jz (code, 0); CODEPTR(code, jump_sync_null); /* next case: synchronization is not null */ /* load MonoInternalThread* into r5 */ s390_ear (code, s390_r5, 0); s390_sllg(code, s390_r5, s390_r5, 0, 32); s390_ear (code, s390_r5, 1); /* load TID into r1 */ s390_lg (code, s390_r1, 0, s390_r5, mono_thread_get_tls_offset ()); s390_lgf (code, s390_r1, 0, s390_r1, MONO_STRUCT_OFFSET (MonoInternalThread, small_id)); /* is synchronization->owner == TID */ s390_lgf (code, status_reg, 0, sync_reg, status_offset); s390_xr (code, s390_r1, status_reg); s390_tmlh (code, s390_r1, OWNER_MASK); /* if not, jump to actual trampoline */ s390_jno (code, 0); CODEPTR(code, jump_not_owned); /* next case: synchronization->owner == TID */ /* is synchronization->nest == 1 */ s390_lgf (code, s390_r0, 0, sync_reg, nest_offset); s390_chi (code, s390_r0, 1); /* if not, jump to next case */ s390_jne (code, 0); CODEPTR(code, jump_next); /* if yes, is synchronization->entry_count greater than zero */ s390_cfi (code, status_reg, ENTRY_COUNT_WAITERS); /* if not, jump to actual trampoline */ s390_jnz (code, 0); CODEPTR(code, jump_have_waiters); /* if yes, try to set synchronization->owner to null and return */ /* old status in s390_r0 */ s390_lgfr (code, s390_r0, status_reg); /* form new status */ s390_nilf (code, status_reg, ENTRY_COUNT_MASK); /* compare and exchange */ s390_cs (code, s390_r0, status_reg, sync_reg, status_offset); /* if not successful, jump to actual trampoline */ s390_jnz (code, 0); CODEPTR(code, jump_cs_failed); s390_br (code, s390_r14); /* next case: synchronization->nest is not 1 */ PTRSLOT (code, jump_next); /* decrease synchronization->nest and return */ s390_lgf (code, s390_r0, 0, sync_reg, nest_offset); s390_ahi (code, s390_r0, -1); s390_st (code, s390_r0, 0, sync_reg, nest_offset); s390_br (code, s390_r14); PTRSLOT (code, jump_obj_null); if (jump_sync_thin_hash) PTRSLOT (code, jump_sync_thin_hash); PTRSLOT (code, jump_have_waiters); PTRSLOT (code, jump_not_owned); PTRSLOT (code, jump_cs_failed); PTRSLOT (code, jump_sync_null); } /* jump to the actual trampoline */ tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_EXIT, mono_get_root_domain (), NULL); S390_SET (code, s390_r1, tramp); s390_br (code, s390_r1); mono_arch_flush_icache (code, code - buf); mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_MONITOR, NULL); g_assert (code - buf <= tramp_size); if (info) *info = mono_tramp_info_create ("monitor_exit_trampoline", buf, code - buf, ji, unwind_ops); return buf; }
static void async_invoke_thread (gpointer data) { MonoDomain *domain; MonoInternalThread *thread; MonoWSQ *wsq; ThreadPool *tp; gboolean must_die; const gchar *name; tp = data; wsq = NULL; if (!tp->is_io) wsq = add_wsq (); thread = mono_thread_internal_current (); mono_profiler_thread_start (thread->tid); name = (tp->is_io) ? "IO Threadpool worker" : "Threadpool worker"; mono_thread_set_name_internal (thread, mono_string_new (mono_domain_get (), name), FALSE); if (tp_start_func) tp_start_func (tp_hooks_user_data); data = NULL; for (;;) { MonoAsyncResult *ar; MonoClass *klass; gboolean is_io_task; gboolean is_socket; int n_naps = 0; is_io_task = FALSE; ar = (MonoAsyncResult *) data; if (ar) { InterlockedIncrement (&tp->busy_threads); domain = ((MonoObject *)ar)->vtable->domain; #ifndef DISABLE_SOCKETS klass = ((MonoObject *) data)->vtable->klass; is_io_task = !is_corlib_asyncresult (domain, klass); is_socket = FALSE; if (is_io_task) { MonoSocketAsyncResult *state = (MonoSocketAsyncResult *) data; is_socket = is_socketasyncresult (domain, klass); ar = state->ares; switch (state->operation) { case AIO_OP_RECEIVE: state->total = ICALL_RECV (state); break; case AIO_OP_SEND: state->total = ICALL_SEND (state); break; } } #endif /* worker threads invokes methods in different domains, * so we need to set the right domain here */ g_assert (domain); if (mono_domain_is_unloading (domain) || mono_runtime_is_shutting_down ()) { threadpool_jobs_dec ((MonoObject *)ar); data = NULL; ar = NULL; InterlockedDecrement (&tp->busy_threads); } else { mono_thread_push_appdomain_ref (domain); if (threadpool_jobs_dec ((MonoObject *)ar)) { data = NULL; ar = NULL; mono_thread_pop_appdomain_ref (); InterlockedDecrement (&tp->busy_threads); continue; } if (mono_domain_set (domain, FALSE)) { MonoObject *exc; if (tp_item_begin_func) tp_item_begin_func (tp_item_user_data); if (!is_io_task && ar->add_time > 0) process_idle_times (tp, ar->add_time); exc = mono_async_invoke (tp, ar); if (tp_item_end_func) tp_item_end_func (tp_item_user_data); if (exc) mono_internal_thread_unhandled_exception (exc); if (is_socket && tp->is_io) { MonoSocketAsyncResult *state = (MonoSocketAsyncResult *) data; if (state->completed && state->callback) { MonoAsyncResult *cb_ares; cb_ares = create_simple_asyncresult ((MonoObject *) state->callback, (MonoObject *) state); icall_append_job ((MonoObject *) cb_ares); } } mono_domain_set (mono_get_root_domain (), TRUE); } mono_thread_pop_appdomain_ref (); InterlockedDecrement (&tp->busy_threads); /* If the callee changes the background status, set it back to TRUE */ mono_thread_clr_state (thread , ~ThreadState_Background); if (!mono_thread_test_state (thread , ThreadState_Background)) ves_icall_System_Threading_Thread_SetState (thread, ThreadState_Background); } } ar = NULL; data = NULL; must_die = should_i_die (tp); if (!must_die && (tp->is_io || !mono_wsq_local_pop (&data))) dequeue_or_steal (tp, &data, wsq); n_naps = 0; while (!must_die && !data && n_naps < 4) { gboolean res; InterlockedIncrement (&tp->waiting); // Another thread may have added a job into its wsq since the last call to dequeue_or_steal // Check all the queues again before entering the wait loop dequeue_or_steal (tp, &data, wsq); if (data) { InterlockedDecrement (&tp->waiting); break; } mono_gc_set_skip_thread (TRUE); #if defined(__OpenBSD__) while (mono_cq_count (tp->queue) == 0 && (res = mono_sem_wait (&tp->new_job, TRUE)) == -1) {// && errno == EINTR) { #else while (mono_cq_count (tp->queue) == 0 && (res = mono_sem_timedwait (&tp->new_job, 2000, TRUE)) == -1) {// && errno == EINTR) { #endif if (mono_runtime_is_shutting_down ()) break; if (THREAD_WANTS_A_BREAK (thread)) mono_thread_interruption_checkpoint (); } InterlockedDecrement (&tp->waiting); mono_gc_set_skip_thread (FALSE); if (mono_runtime_is_shutting_down ()) break; must_die = should_i_die (tp); dequeue_or_steal (tp, &data, wsq); n_naps++; } if (!data && !tp->is_io && !mono_runtime_is_shutting_down ()) { mono_wsq_local_pop (&data); if (data && must_die) { InterlockedCompareExchange (&tp->destroy_thread, 1, 0); pulse_on_new_job (tp); } } if (!data) { gint nt; gboolean down; while (1) { nt = tp->nthreads; down = mono_runtime_is_shutting_down (); if (!down && nt <= tp->min_threads) break; if (down || InterlockedCompareExchange (&tp->nthreads, nt - 1, nt) == nt) { mono_perfcounter_update_value (tp->pc_nthreads, TRUE, -1); if (!tp->is_io) { remove_wsq (wsq); } mono_profiler_thread_end (thread->tid); if (tp_finish_func) tp_finish_func (tp_hooks_user_data); return; } } } } g_assert_not_reached (); } void ves_icall_System_Threading_ThreadPool_GetAvailableThreads (gint *workerThreads, gint *completionPortThreads) { *workerThreads = async_tp.max_threads - async_tp.busy_threads; *completionPortThreads = async_io_tp.max_threads - async_io_tp.busy_threads; }
static gsize sampling_thread_func (gpointer unused) { MonoInternalThread *thread = mono_thread_internal_current (); thread->flags |= MONO_THREAD_FLAG_DONT_MANAGE; ERROR_DECL (error); MonoString *name = mono_string_new_checked (mono_get_root_domain (), "Profiler Sampler", error); mono_error_assert_ok (error); mono_thread_set_name_internal (thread, name, FALSE, FALSE, error); mono_error_assert_ok (error); mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE); int old_policy; struct sched_param old_sched; pthread_getschedparam (pthread_self (), &old_policy, &old_sched); /* * Attempt to switch the thread to real time scheduling. This will not * necessarily work on all OSs; for example, most Linux systems will give * us EPERM here unless configured to allow this. * * TODO: This does not work on Mac (and maybe some other OSs). On Mac, we * have to use the Mach thread policy routines to switch to real-time * scheduling. This is quite tricky as we need to specify how often we'll * be doing work (easy), the normal processing time needed (also easy), * and the maximum amount of processing time needed (hard). This is * further complicated by the fact that if we misbehave and take too long * to do our work, the kernel may knock us back down to the normal thread * scheduling policy without telling us. */ struct sched_param sched = { .sched_priority = sched_get_priority_max (SCHED_FIFO) }; pthread_setschedparam (pthread_self (), SCHED_FIFO, &sched); MonoProfilerSampleMode mode; init: mono_profiler_get_sample_mode (NULL, &mode, NULL); if (mode == MONO_PROFILER_SAMPLE_MODE_NONE) { mono_profiler_sampling_thread_wait (); if (!mono_atomic_load_i32 (&sampling_thread_running)) goto done; goto init; } clock_init (mode); for (guint64 sleep = clock_get_time_ns (); mono_atomic_load_i32 (&sampling_thread_running); clock_sleep_ns_abs (sleep)) { uint32_t freq; MonoProfilerSampleMode new_mode; mono_profiler_get_sample_mode (NULL, &new_mode, &freq); if (new_mode != mode) { clock_cleanup (); goto init; } sleep += 1000000000 / freq; FOREACH_THREAD_SAFE_EXCLUDE (info, MONO_THREAD_INFO_FLAGS_NO_SAMPLE) { g_assert (mono_thread_info_get_tid (info) != sampling_thread); /* * Require an ack for the last sampling signal sent to the thread * so that we don't overflow the signal queue, leading to all sorts * of problems (e.g. GC STW failing). */ if (profiler_signal != SIGPROF && !mono_atomic_cas_i32 (&info->profiler_signal_ack, 0, 1)) continue; mono_threads_pthread_kill (info, profiler_signal); mono_atomic_inc_i32 (&profiler_signals_sent); } FOREACH_THREAD_SAFE_END }
gboolean mono_domain_finalize (MonoDomain *domain, guint32 timeout) { DomainFinalizationReq *req; MonoInternalThread *thread = mono_thread_internal_current (); gint res; gboolean ret; gint64 start; #if defined(__native_client__) return FALSE; #endif if (mono_thread_internal_current () == gc_thread) /* We are called from inside a finalizer, not much we can do here */ return FALSE; /* * No need to create another thread 'cause the finalizer thread * is still working and will take care of running the finalizers */ if (gc_disabled) return TRUE; /* We don't support domain finalization without a GC */ if (mono_gc_is_null ()) return FALSE; mono_gc_collect (mono_gc_max_generation ()); req = g_new0 (DomainFinalizationReq, 1); req->ref = 2; req->domain = domain; mono_coop_sem_init (&req->done, 0); if (domain == mono_get_root_domain ()) finalizing_root_domain = TRUE; mono_finalizer_lock (); domains_to_finalize = g_slist_append (domains_to_finalize, req); mono_finalizer_unlock (); /* Tell the finalizer thread to finalize this appdomain */ mono_gc_finalize_notify (); if (timeout == -1) timeout = INFINITE; if (timeout != INFINITE) start = mono_msec_ticks (); ret = TRUE; for (;;) { if (timeout == INFINITE) { res = mono_coop_sem_wait (&req->done, MONO_SEM_FLAGS_ALERTABLE); } else { gint64 elapsed = mono_msec_ticks () - start; if (elapsed >= timeout) { ret = FALSE; break; } res = mono_coop_sem_timedwait (&req->done, timeout - elapsed, MONO_SEM_FLAGS_ALERTABLE); } if (res == MONO_SEM_TIMEDWAIT_RET_SUCCESS) { break; } else if (res == MONO_SEM_TIMEDWAIT_RET_ALERTED) { if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0) { ret = FALSE; break; } } else if (res == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) { ret = FALSE; break; } else { g_error ("%s: unknown result %d", __func__, res); } } if (!ret) { /* Try removing the req from domains_to_finalize: * - if it's not found: the domain is being finalized, * so we the ref count is already decremented * - if it's found: the domain is not yet being finalized, * so we can safely decrement the ref */ gboolean found; mono_finalizer_lock (); found = g_slist_index (domains_to_finalize, req) != -1; if (found) domains_to_finalize = g_slist_remove (domains_to_finalize, req); mono_finalizer_unlock (); if (found) { /* We have to decrement it wherever we * remove it from domains_to_finalize */ if (InterlockedDecrement (&req->ref) != 1) g_error ("%s: req->ref should be 1, as we are the first one to decrement it", __func__); } goto done; } if (domain == mono_get_root_domain ()) { mono_threadpool_ms_cleanup (); mono_gc_finalize_threadpool_threads (); } done: if (InterlockedDecrement (&req->ref) == 0) { mono_coop_sem_destroy (&req->done); g_free (req); } return ret; }
gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot) { guint8 *tramp; guint8 *code, *buf; guint8 **rgctx_null_jumps; int tramp_size; int depth, index; int i; gboolean mrgctx; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; unwind_ops = mono_arch_get_cie_program (); mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot); index = MONO_RGCTX_SLOT_INDEX (slot); if (mrgctx) index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (target_mgreg_t); for (depth = 0; ; ++depth) { int size = mono_class_rgctx_get_array_size (depth, mrgctx); if (index < size - 1) break; index -= size - 1; } tramp_size = (aot ? 64 : 36) + 6 * depth; code = buf = mono_global_codeman_reserve (tramp_size); rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2)); /* load vtable/mrgctx ptr */ x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4); if (!mrgctx) { /* load rgctx ptr from vtable */ x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context), 4); /* is the rgctx ptr null? */ x86_test_reg_reg (code, X86_EAX, X86_EAX); /* if yes, jump to actual trampoline */ rgctx_null_jumps [0] = code; x86_branch8 (code, X86_CC_Z, -1, 1); } for (i = 0; i < depth; ++i) { /* load ptr to next array */ if (mrgctx && i == 0) x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT, 4); else x86_mov_reg_membase (code, X86_EAX, X86_EAX, 0, 4); /* is the ptr null? */ x86_test_reg_reg (code, X86_EAX, X86_EAX); /* if yes, jump to actual trampoline */ rgctx_null_jumps [i + 1] = code; x86_branch8 (code, X86_CC_Z, -1, 1); } /* fetch slot */ x86_mov_reg_membase (code, X86_EAX, X86_EAX, sizeof (target_mgreg_t) * (index + 1), 4); /* is the slot null? */ x86_test_reg_reg (code, X86_EAX, X86_EAX); /* if yes, jump to actual trampoline */ rgctx_null_jumps [depth + 1] = code; x86_branch8 (code, X86_CC_Z, -1, 1); /* otherwise return */ x86_ret (code); for (i = mrgctx ? 1 : 0; i <= depth + 1; ++i) x86_patch (rgctx_null_jumps [i], code); g_free (rgctx_null_jumps); x86_mov_reg_membase (code, MONO_ARCH_VTABLE_REG, X86_ESP, 4, 4); if (aot) { code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR, GUINT_TO_POINTER (slot)); x86_jump_reg (code, X86_EAX); } else { tramp = (guint8*)mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL); /* jump to the actual trampoline */ x86_jump_code (code, tramp); } mono_arch_flush_icache (buf, code - buf); MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL)); g_assert (code - buf <= tramp_size); char *name = mono_get_rgctx_fetch_trampoline_name (slot); *info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops); g_free (name); return buf; }
bool VdsViewEventHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us) { if (!_eventClass) return false; int x = ea.getX(); int y = ea.getY(); MonoImage* monoImage = NULL; MonoClass* eventClass = NULL; MonoObject* eventClassObject = NULL; MonoMethod* mousePushMethod = NULL; MonoMethod* mouseReleaseMethod = NULL; MonoMethod* mouseMoveMethod = NULL; MonoMethod* mouseDoubleClickMethod = NULL; MonoMethod* mouseZoomMethod = NULL; MonoMethod* keyDownMethod = NULL; MonoMethod* keyUpMethod = NULL; MonoMethod* layerInSceneChangedMethod = NULL; MonoMethod* gameManagerAddActorEventMethod = NULL; MonoMethod* gameManagerRemoveActorEventMethod = NULL; MonoMethod* gameManagerPlayPlotEventMethod = NULL; MonoMethod* gameManagerStopPlotEventMethod = NULL; MonoMethod* gameManagerPausePlotEventMethod = NULL; MonoMethod* uiEventMethod = NULL; { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_pMutex); monoImage = _monoImage; eventClass = _eventClass; eventClassObject = _eventClassObject; mousePushMethod = _mousePushMethod; mouseReleaseMethod = _mouseReleaseMethod; mouseMoveMethod = _mouseMoveMethod; mouseDoubleClickMethod = _mouseDoubleClickMethod; mouseZoomMethod = _mouseZoomMethod; keyDownMethod = _keyDownMethod; keyUpMethod = _keyUpMethod; layerInSceneChangedMethod = _layerInSceneChangedMethod; gameManagerAddActorEventMethod = _gameManagerAddActorEventMethod; gameManagerRemoveActorEventMethod = _gameManagerRemoveActorEventMethod; gameManagerPlayPlotEventMethod = _gameManagerPlayPlotEventMethod; gameManagerStopPlotEventMethod = _gameManagerStopPlotEventMethod; gameManagerPausePlotEventMethod = _gameManagerPausePlotEventMethod; uiEventMethod = _uiEventMethod; } switch (ea.getEventType()) { case osgGA::GUIEventAdapter::MOVE: { if (!mouseMoveMethod) mouseMoveMethod = mono_class_get_method_from_name(eventClass, "MouseMoveEvent", 3); MonoObject* exception = NULL; void* args[3]; args[0] = &_viewID; args[1] = &x; args[2] = &y; _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(mouseMoveMethod, eventClassObject, args, &exception); break; } case osgGA::GUIEventAdapter::PUSH: { if (!mousePushMethod) mousePushMethod = mono_class_get_method_from_name(eventClass, "MouseButtonPressEvent", 4); MonoObject* exception = NULL; int arg0 = 1; void* args[4]; args[0] = &_viewID; if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) arg0 = 1; else if (ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) arg0 = 2; else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) arg0 = 3; args[1] = &arg0; args[2] = &x; args[3] = &y; _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(mousePushMethod, eventClassObject, args, &exception); break; } case osgGA::GUIEventAdapter::RELEASE: { if (!mouseReleaseMethod) mouseReleaseMethod = mono_class_get_method_from_name(eventClass, "MouseButtonReleaseEvent", 4); MonoObject* exception = NULL; int arg0 = 1; void* args[4]; args[0] = &_viewID; if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) arg0 = 1; else if (ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) arg0 = 2; else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) arg0 = 3; args[1] = &arg0; args[2] = &x; args[3] = &y; _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(mouseReleaseMethod, eventClassObject, args, &exception); break; } case osgGA::GUIEventAdapter::DOUBLECLICK: { if (!mouseDoubleClickMethod) mouseDoubleClickMethod = mono_class_get_method_from_name(eventClass, "MouseDoubleClickEvent", 4); MonoObject* exception = NULL; int arg0 = 1; void* args[4]; args[0] = &_viewID; if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) arg0 = 1; else if (ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) arg0 = 2; else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) arg0 = 3; args[1] = &arg0; args[2] = &x; args[3] = &y; _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(mouseDoubleClickMethod, eventClassObject, args, &exception); break; } case osgGA::GUIEventAdapter::KEYDOWN: { if (!keyDownMethod) keyDownMethod = mono_class_get_method_from_name(eventClass, "KeyboardDownEvent", 2); MonoObject* exception = NULL; void* args[2]; args[0] = &_viewID; int keyValue = ea.getKey(); args[1] = &keyValue; _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(keyDownMethod, eventClassObject, args, &exception); break; } case osgGA::GUIEventAdapter::KEYUP: { if (!keyUpMethod) keyUpMethod = mono_class_get_method_from_name(eventClass, "KeyboardUpEvent", 2); MonoObject* exception = NULL; void* args[2]; args[0] = &_viewID; int keyValue = ea.getKey(); args[1] = &keyValue; _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(keyUpMethod, eventClassObject, args, &exception); break; } case osgGA::GUIEventAdapter::SCROLL: { if (!mouseZoomMethod) mouseZoomMethod = mono_class_get_method_from_name(eventClass, "MouseZoomEvent", 2); MonoObject* exception = NULL; void* args[2]; args[0] = &_viewID; osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion(); int zoomValue = 0; if (sm == osgGA::GUIEventAdapter::SCROLL_DOWN) zoomValue = 1; args[1] = &zoomValue; _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(mouseZoomMethod, eventClassObject, args, &exception); break; } case osgGA::GUIEventAdapter::USER: { osg::ref_ptr<osg::Referenced> userData = const_cast<osg::Referenced*>(ea.getUserData()); UserEventData* data = static_cast<UserEventData*>(userData.get()); switch (data->_eventType) { case UserEventData::LAYERCHANGED: { if (!layerInSceneChangedMethod) layerInSceneChangedMethod = mono_class_get_method_from_name(eventClass, "LayerInSceneChangedEvent", 1); MonoObject* exception = NULL; void* args[1]; args[0] = &_viewID; _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(layerInSceneChangedMethod, eventClassObject, args, &exception); break; } case UserEventData::UI_EVENT: { if (!uiEventMethod) uiEventMethod = mono_class_get_method_from_name(eventClass, "UIEvent", 3); void* widthData = data->_data; std::vector<std::string>* dList = (std::vector<std::string>*)widthData; MonoDomain* domain = mono_object_get_domain(eventClassObject); MonoObject* exception = NULL; void* args[3]; args[0] = &_viewID; args[1] = mono_string_new(domain, dList->at(0).c_str()); args[2] = mono_string_new(domain, dList->at(1).c_str()); _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(uiEventMethod, eventClassObject, args, &exception); break; } case UserEventData::GAMEMANAGER_ACTORADD: { if (!gameManagerAddActorEventMethod) gameManagerAddActorEventMethod = mono_class_get_method_from_name(eventClass, "GameLayerAddActorEvent", 2); MonoDomain* domain = mono_object_get_domain(eventClassObject); MonoObject* exception = NULL; void* args[2]; args[0] = &_viewID; args[1] = mono_string_new(domain, dynamic_cast<VirtualDataSceneBase::ActorBase*>(data->_eventObject.get())->getId().c_str()); _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(gameManagerAddActorEventMethod, eventClassObject, args, &exception); break; } case UserEventData::GAMEMANAGER_ACTORREMOVE: { if (!gameManagerRemoveActorEventMethod) gameManagerRemoveActorEventMethod = mono_class_get_method_from_name(eventClass, "GameLayerRemoveActorEvent", 2); MonoDomain* domain = mono_object_get_domain(eventClassObject); MonoObject* exception = NULL; void* args[2]; args[0] = &_viewID; args[1] = mono_string_new(domain, dynamic_cast<VirtualDataSceneBase::ActorBase*>(data->_eventObject.get())->getId().c_str()); _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(gameManagerRemoveActorEventMethod, eventClassObject, args, &exception); break; } case UserEventData::GAMEMANAGER_PLAYPLOT: { if (!gameManagerPlayPlotEventMethod) gameManagerPlayPlotEventMethod = mono_class_get_method_from_name(eventClass, "PlayPlotScriptEvent", 3); void* widthData = data->_data; std::vector<std::string>* dList = (std::vector<std::string>*)widthData; MonoDomain* domain = mono_object_get_domain(eventClassObject); MonoObject* exception = NULL; void* args[3]; args[0] = &_viewID; args[1] = mono_string_new(domain, dList->at(0).c_str()); args[2] = mono_string_new(domain, dList->at(1).c_str()); _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(gameManagerPlayPlotEventMethod, eventClassObject, args, &exception); break; } case UserEventData::GAMEMANAGER_STOPPLOT: { if (!gameManagerStopPlotEventMethod) gameManagerStopPlotEventMethod = mono_class_get_method_from_name(eventClass, "StopPlotScriptEvent", 2); MonoDomain* domain = mono_object_get_domain(eventClassObject); MonoObject* exception = NULL; void* args[2]; args[0] = &_viewID; args[1] = mono_string_new(domain, dynamic_cast<VirtualDataSceneBase::ActorBase*>(data->_eventObject.get())->getId().c_str()); _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(gameManagerStopPlotEventMethod, eventClassObject, args, &exception); break; } case UserEventData::GAMEMANAGER_PAUSEPLOT: { if (!gameManagerPausePlotEventMethod) gameManagerPausePlotEventMethod = mono_class_get_method_from_name(eventClass, "PausePlotScriptEvent", 2); MonoDomain* domain = mono_object_get_domain(eventClassObject); MonoObject* exception = NULL; void* args[2]; args[0] = &_viewID; args[1] = mono_string_new(domain, dynamic_cast<VirtualDataSceneBase::ActorBase*>(data->_eventObject.get())->getId().c_str()); _eventThread = mono_thread_attach(mono_get_root_domain()); mono_runtime_invoke(gameManagerPausePlotEventMethod, eventClassObject, args, &exception); break; } default: break; } break; } case osgGA::GUIEventAdapter::CLOSE_WINDOW: case osgGA::GUIEventAdapter::QUIT_APPLICATION: { //mono_thread_detach(_eventThread); break; } default: break; } return false; }
void * mono_arch_create_method_pointer (MonoMethod *method) { MonoMethodSignature *sig; MonoJitInfo *ji; guint8 *p, *code_buffer; guint i, align = 0, simple_type, retSize, reg_save = 0, stackval_arg_pos, local_pos, float_pos, local_start, reg_param = 0, stack_param, this_flag, arg_pos, fpr_param, parSize; guint32 simpletype; size_data sz; int *vtbuf, cpos, vt_cur; sz.code_size = 1024; sz.stack_size = 1024; stack_param = 0; fpr_param = 0; arg_pos = 0; sig = method->signature; p = code_buffer = g_malloc (sz.code_size); DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n", method->name,p)); /*----------------------------------------------------------*/ /* prolog */ /*----------------------------------------------------------*/ s390_stmg(p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET); s390_lg (p, s390_r7, 0, STK_BASE, MINV_POS); s390_lgr (p, s390_r0, STK_BASE); s390_aghi(p, STK_BASE, -(sz.stack_size+MINV_POS)); s390_stg (p, s390_r0, 0, STK_BASE, 0); s390_la (p, s390_r8, 0, STK_BASE, 4); s390_lgr (p, s390_r10, s390_r8); s390_lghi(p, s390_r9, sz.stack_size+92); s390_lghi(p, s390_r11, 0); s390_mvcl(p, s390_r8, s390_r10); /*----------------------------------------------------------*/ /* Let's fill MonoInvocation - first zero some fields */ /*----------------------------------------------------------*/ s390_lghi (p, s390_r0, 0); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex))); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler))); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent))); s390_lghi (p, s390_r0, 1); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, invoke_trap))); /*----------------------------------------------------------*/ /* set method pointer */ /*----------------------------------------------------------*/ s390_bras (p, s390_r13, 4); s390_llong(p, method); s390_lg (p, s390_r0, 0, s390_r13, 0); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method))); local_start = local_pos = MINV_POS + sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval); this_flag = (sig->hasthis ? 1 : 0); /*----------------------------------------------------------*/ /* if we are returning a structure, checks it's length to */ /* see if there's a "hidden" parameter that points to the */ /* area. If necessary save this hidden parameter for later */ /*----------------------------------------------------------*/ if (MONO_TYPE_ISSTRUCT(sig->ret)) { if (sig->pinvoke) retSize = mono_class_native_size (sig->ret->data.klass, &align); else retSize = mono_class_value_size (sig->ret->data.klass, &align); switch(retSize) { case 0: case 1: case 2: case 4: case 8: sz.retStruct = 0; break; default: sz.retStruct = 1; s390_lgr(p, s390_r8, s390_r2); reg_save = 1; } } else { reg_save = 0; } if (this_flag) { s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj))); reg_param++; } else { s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, local_pos); local_pos += sizeof(int); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj))); } s390_stmg (p, s390_r3 + reg_param, s390_r6, STK_BASE, local_pos); local_pos += 4 * sizeof(long); float_pos = local_pos; s390_std (p, s390_f0, 0, STK_BASE, local_pos); local_pos += sizeof(double); s390_std (p, s390_f2, 0, STK_BASE, local_pos); local_pos += sizeof(double); /*----------------------------------------------------------*/ /* prepare space for valuetypes */ /*----------------------------------------------------------*/ vt_cur = local_pos; vtbuf = alloca (sizeof(int)*sig->param_count); cpos = 0; for (i = 0; i < sig->param_count; i++) { MonoType *type = sig->params [i]; vtbuf [i] = -1; DEBUG(printf("par: %d type: %d ref: %d\n",i,type->type,type->byref)); if (type->type == MONO_TYPE_VALUETYPE) { MonoClass *klass = type->data.klass; gint size; if (klass->enumtype) continue; size = mono_class_native_size (klass, &align); cpos += align - 1; cpos &= ~(align - 1); vtbuf [i] = cpos; cpos += size; } } cpos += 3; cpos &= ~3; local_pos += cpos; /*----------------------------------------------------------*/ /* set MonoInvocation::stack_args */ /*----------------------------------------------------------*/ stackval_arg_pos = MINV_POS + sizeof (MonoInvocation); s390_la (p, s390_r0, 0, STK_BASE, stackval_arg_pos); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args))); /*----------------------------------------------------------*/ /* add stackval arguments */ /*----------------------------------------------------------*/ for (i = 0; i < sig->param_count; ++i) { if (sig->params [i]->byref) { ADD_ISTACK_PARM(0, 1); } else { simple_type = sig->params [i]->type; enum_savechk: switch (simple_type) { case MONO_TYPE_I8: ADD_ISTACK_PARM(-1, 2); break; case MONO_TYPE_R4: ADD_RSTACK_PARM(1); break; case MONO_TYPE_R8: ADD_RSTACK_PARM(2); break; case MONO_TYPE_VALUETYPE: if (sig->params [i]->data.klass->enumtype) { simple_type = sig->params [i]->data.klass->enum_basetype->type; goto enum_savechk; } if (sig->pinvoke) parSize = mono_class_native_size (sig->params [i]->data.klass, &align); else parSize = mono_class_value_size (sig->params [i]->data.klass, &align); switch(parSize) { case 0: case 1: case 2: case 4: ADD_PSTACK_PARM(0, 1); break; case 8: ADD_PSTACK_PARM(-1, 2); break; default: ADD_TSTACK_PARM; } break; default: ADD_ISTACK_PARM(0, 1); } } if (vtbuf [i] >= 0) { s390_la (p, s390_r3, 0, STK_BASE, vt_cur); s390_stg (p, s390_r3, 0, STK_BASE, stackval_arg_pos); s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos); vt_cur += vtbuf [i]; } else { s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos); } /*--------------------------------------*/ /* Load the parameter registers for the */ /* call to stackval_from_data */ /*--------------------------------------*/ s390_bras (p, s390_r13, 8); s390_llong(p, sig->params [i]); s390_llong(p, sig->pinvoke); s390_llong(p, stackval_from_data); s390_lg (p, s390_r2, 0, s390_r13, 0); s390_lg (p, s390_r5, 0, s390_r13, 4); s390_lg (p, s390_r1, 0, s390_r13, 8); s390_basr (p, s390_r14, s390_r1); stackval_arg_pos += sizeof(stackval); /* fixme: alignment */ DEBUG (printf ("arg_pos %d --> ", arg_pos)); if (sig->pinvoke) arg_pos += mono_type_native_stack_size (sig->params [i], &align); else arg_pos += mono_type_stack_size (sig->params [i], &align); DEBUG (printf ("%d\n", stackval_arg_pos)); } /*----------------------------------------------------------*/ /* Set return area pointer. */ /*----------------------------------------------------------*/ s390_la (p, s390_r10, 0, STK_BASE, stackval_arg_pos); s390_stg(p, s390_r10, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { MonoClass *klass = sig->ret->data.klass; if (!klass->enumtype) { s390_la (p, s390_r9, 0, s390_r10, sizeof(stackval)); s390_st (p, s390_r9, 0,STK_BASE, stackval_arg_pos); stackval_arg_pos += sizeof(stackval); } } /*----------------------------------------------------------*/ /* call ves_exec_method */ /*----------------------------------------------------------*/ s390_bras (p, s390_r13, 4); s390_llong(p, ves_exec_method); s390_lg (p, s390_r1, 0, s390_r13, 0); s390_la (p, s390_r2, 0, STK_BASE, MINV_POS); s390_basr (p, s390_r14, s390_r1); /*----------------------------------------------------------*/ /* move retval from stackval to proper place (r3/r4/...) */ /*----------------------------------------------------------*/ DEBUG(printf("retType: %d byRef: %d\n",sig->ret->type,sig->ret->byref)); if (sig->ret->byref) { DEBUG (printf ("ret by ref\n")); s390_stg(p, s390_r2, 0, s390_r10, 0); } else { enum_retvalue: switch (sig->ret->type) { case MONO_TYPE_VOID: break; case MONO_TYPE_BOOLEAN: case MONO_TYPE_U1: s390_lghi(p, s390_r2, 0); s390_ic (p, s390_r2, 0, s390_r10, 0); break; case MONO_TYPE_I2: case MONO_TYPE_U2: s390_lh (p, s390_r2, 0,s390_r10, 0); break; case MONO_TYPE_I4: case MONO_TYPE_U4: case MONO_TYPE_I: case MONO_TYPE_U: s390_lgf(p, s390_r2, 0, s390_r10, 0); break; case MONO_TYPE_OBJECT: case MONO_TYPE_STRING: case MONO_TYPE_CLASS: case MONO_TYPE_I8: s390_lg (p, s390_r2, 0, s390_r10, 0); break; case MONO_TYPE_R4: s390_le (p, s390_f0, 0, s390_r10, 0); break; case MONO_TYPE_R8: s390_ld (p, s390_f0, 0, s390_r10, 0); break; case MONO_TYPE_VALUETYPE: if (sig->ret->data.klass->enumtype) { simpletype = sig->ret->data.klass->enum_basetype->type; goto enum_retvalue; } /*---------------------------------*/ /* Call stackval_to_data to return */ /* the structure */ /*---------------------------------*/ s390_bras (p, s390_r13, 8); s390_llong(p, sig->ret); s390_llong(p, sig->pinvoke); s390_llong(p, stackval_to_data); s390_lg (p, s390_r2, 0, s390_r13, 0); s390_lg (p, s390_r3, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); if (sz.retStruct) { /*------------------------------------------*/ /* Get stackval_to_data to set result area */ /*------------------------------------------*/ s390_lgr (p, s390_r4, s390_r8); } else { /*------------------------------------------*/ /* Give stackval_to_data a temp result area */ /*------------------------------------------*/ s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos); } s390_lg (p, s390_r5, 0,s390_r13, 4); s390_lg (p, s390_r1, 0, s390_r13, 8); s390_basr (p, s390_r14, s390_r1); switch (retSize) { case 0: break; case 1: s390_lghi(p, s390_r2, 0); s390_ic (p, s390_r2, 0, s390_r10, 0); break; case 2: s390_lh (p, s390_r2, 0, s390_r10, 0); break; case 4: s390_lgf(p, s390_r2, 0, s390_r10, 0); break; case 8: s390_lg (p, s390_r2, 0, s390_r10, 0); break; default: ; /*-------------------------------------------------*/ /* stackval_to_data has placed data in result area */ /*-------------------------------------------------*/ } break; default: g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type); break; } } /*----------------------------------------------------------*/ /* epilog */ /*----------------------------------------------------------*/ s390_lg (p, STK_BASE, 0, STK_BASE, 0); s390_lg (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET); s390_lmg (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET); s390_br (p, s390_r4); DEBUG (printf ("emited code size: %d\n", p - code_buffer)); DEBUG (printf ("Delegate [end emiting]\n")); ji = g_new0 (MonoJitInfo, 1); ji->method = method; ji->code_size = p - code_buffer; ji->code_start = code_buffer; mono_jit_info_table_add (mono_get_root_domain (), ji); return ji->code_start; }
gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot) { #ifdef MONO_ARCH_VTABLE_REG guint8 *tramp; guint8 *code, *buf; guint8 **rgctx_null_jumps; gint32 displace; int tramp_size, depth, index, iPatch = 0, i; gboolean mrgctx; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot); index = MONO_RGCTX_SLOT_INDEX (slot); if (mrgctx) index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer); for (depth = 0; ; ++depth) { int size = mono_class_rgctx_get_array_size (depth, mrgctx); if (index < size - 1) break; index -= size - 1; } tramp_size = 48 + 16 * depth; if (mrgctx) tramp_size += 4; else tramp_size += 12; code = buf = mono_global_codeman_reserve (tramp_size); unwind_ops = mono_arch_get_cie_program (); rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2)); if (mrgctx) { /* get mrgctx ptr */ s390_lgr (code, s390_r1, s390_r2); } else { /* load rgctx ptr from vtable */ s390_lg (code, s390_r1, 0, s390_r2, G_STRUCT_OFFSET(MonoVTable, runtime_generic_context)); /* is the rgctx ptr null? */ s390_ltgr (code, s390_r1, s390_r1); /* if yes, jump to actual trampoline */ rgctx_null_jumps [iPatch++] = code; s390_jge (code, 0); } for (i = 0; i < depth; ++i) { /* load ptr to next array */ if (mrgctx && i == 0) s390_lg (code, s390_r1, 0, s390_r1, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT); else s390_lg (code, s390_r1, 0, s390_r1, 0); s390_ltgr (code, s390_r1, s390_r1); /* if the ptr is null then jump to actual trampoline */ rgctx_null_jumps [iPatch++] = code; s390_jge (code, 0); } /* fetch slot */ s390_lg (code, s390_r1, 0, s390_r1, (sizeof (gpointer) * (index + 1))); /* is the slot null? */ s390_ltgr (code, s390_r1, s390_r1); /* if yes, jump to actual trampoline */ rgctx_null_jumps [iPatch++] = code; s390_jge (code, 0); /* otherwise return r1 */ s390_lgr (code, s390_r2, s390_r1); s390_br (code, s390_r14); for (i = 0; i < iPatch; i++) { displace = ((uintptr_t) code - (uintptr_t) rgctx_null_jumps[i]) / 2; s390_patch_rel ((rgctx_null_jumps [i] + 2), displace); } g_free (rgctx_null_jumps); /* move the rgctx pointer to the VTABLE register */ s390_lgr (code, MONO_ARCH_VTABLE_REG, s390_r2); tramp = mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL); /* jump to the actual trampoline */ displace = (tramp - code) / 2; s390_jg (code, displace); mono_arch_flush_icache (buf, code - buf); g_assert (code - buf <= tramp_size); if (info) { char *name = mono_get_rgctx_fetch_trampoline_name (slot); *info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops); g_free (name); } return(buf); #else g_assert_not_reached (); #endif return(NULL); }
MonoDomain* JniManager::getMonoDomain() { MonoDomain* monoDomain = mono_get_root_domain(); mono_thread_attach(monoDomain); return monoDomain; }
gpointer mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot) { guint8 *tramp, *code, *buf; gint16 *jump_obj_null, *jump_sync_null, *jump_cs_failed, *jump_other_owner, *jump_tid, *jump_sync_thin_hash = NULL, *jump_lock_taken_true = NULL; int tramp_size, status_reg = s390_r0, lock_taken_reg = s390_r1, obj_reg = s390_r2, sync_reg = s390_r3, tid_reg = s390_r4, status_offset, nest_offset; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; g_assert (MONO_ARCH_MONITOR_OBJECT_REG == obj_reg); #ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG g_assert (MONO_ARCH_MONITOR_LOCK_TAKEN_REG == lock_taken_reg); #else g_assert (!is_v4); #endif mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset); g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32)); g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (nest_offset) == sizeof (guint32)); status_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (status_offset); nest_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (nest_offset); tramp_size = 160; code = buf = mono_global_codeman_reserve (tramp_size); unwind_ops = mono_arch_get_cie_program (); if (mono_thread_get_tls_offset () != -1) { /* MonoObject* obj is in obj_reg */ /* is obj null? */ s390_ltgr (code, obj_reg, obj_reg); /* if yes, jump to actual trampoline */ s390_jz (code, 0); CODEPTR(code, jump_obj_null); if (is_v4) { s390_cli (code, lock_taken_reg, 0, 1); /* if *lock_taken is 1, jump to actual trampoline */ s390_je (code, 0); CODEPTR(code, jump_lock_taken_true); } /* load obj->synchronization to sync_reg */ s390_lg (code, sync_reg, 0, obj_reg, MONO_STRUCT_OFFSET (MonoObject, synchronisation)); if (mono_gc_is_moving ()) { /*if bit zero is set it's a thin hash*/ s390_tmll (code, sync_reg, 1); s390_jo (code, 0); CODEPTR(code, jump_sync_thin_hash); /* Clear bits used by the gc */ s390_nill (code, sync_reg, ~0x3); } /* is synchronization null? */ s390_ltgr (code, sync_reg, sync_reg); /* if yes, jump to actual trampoline */ s390_jz (code, 0); CODEPTR(code, jump_sync_null); /* load MonoInternalThread* into tid_reg */ s390_ear (code, s390_r5, 0); s390_sllg(code, s390_r5, s390_r5, 0, 32); s390_ear (code, s390_r5, 1); /* load tid */ s390_lg (code, tid_reg, 0, s390_r5, mono_thread_get_tls_offset ()); s390_lgf (code, tid_reg, 0, tid_reg, MONO_STRUCT_OFFSET (MonoInternalThread, small_id)); /* is synchronization->owner free */ s390_lgf (code, status_reg, 0, sync_reg, status_offset); s390_nilf (code, status_reg, OWNER_MASK); /* if not, jump to next case */ s390_jnz (code, 0); CODEPTR(code, jump_tid); /* if yes, try a compare-exchange with the TID */ /* Form new status in tid_reg */ s390_xr (code, tid_reg, status_reg); /* compare and exchange */ s390_cs (code, status_reg, tid_reg, sync_reg, status_offset); s390_jnz (code, 0); CODEPTR(code, jump_cs_failed); /* if successful, return */ if (is_v4) s390_mvi (code, lock_taken_reg, 0, 1); s390_br (code, s390_r14); /* next case: synchronization->owner is not null */ PTRSLOT(code, jump_tid); /* is synchronization->owner == TID? */ s390_nilf (code, status_reg, OWNER_MASK); s390_cr (code, status_reg, tid_reg); /* if not, jump to actual trampoline */ s390_jnz (code, 0); CODEPTR(code, jump_other_owner); /* if yes, increment nest */ s390_lgf (code, s390_r5, 0, sync_reg, nest_offset); s390_ahi (code, s390_r5, 1); s390_st (code, s390_r5, 0, sync_reg, nest_offset); /* return */ if (is_v4) s390_mvi (code, lock_taken_reg, 0, 1); s390_br (code, s390_r14); PTRSLOT (code, jump_obj_null); if (jump_sync_thin_hash) PTRSLOT (code, jump_sync_thin_hash); PTRSLOT (code, jump_sync_null); PTRSLOT (code, jump_cs_failed); PTRSLOT (code, jump_other_owner); if (is_v4) PTRSLOT (code, jump_lock_taken_true); } /* jump to the actual trampoline */ if (is_v4) tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER_V4, mono_get_root_domain (), NULL); else tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER, mono_get_root_domain (), NULL); /* jump to the actual trampoline */ S390_SET (code, s390_r1, tramp); s390_br (code, s390_r1); mono_arch_flush_icache (code, code - buf); mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_MONITOR, NULL); g_assert (code - buf <= tramp_size); if (info) { if (is_v4) *info = mono_tramp_info_create ("monitor_enter_v4_trampoline", buf, code - buf, ji, unwind_ops); else *info = mono_tramp_info_create ("monitor_enter_trampoline", buf, code - buf, ji, unwind_ops); } return buf; }
gboolean mono_domain_finalize (MonoDomain *domain, guint32 timeout) { DomainFinalizationReq *req; guint32 res; HANDLE done_event; MonoInternalThread *thread = mono_thread_internal_current (); if (mono_thread_internal_current () == gc_thread) /* We are called from inside a finalizer, not much we can do here */ return FALSE; /* * No need to create another thread 'cause the finalizer thread * is still working and will take care of running the finalizers */ #ifndef HAVE_NULL_GC if (gc_disabled) return TRUE; mono_gc_collect (mono_gc_max_generation ()); done_event = CreateEvent (NULL, TRUE, FALSE, NULL); if (done_event == NULL) { return FALSE; } req = g_new0 (DomainFinalizationReq, 1); req->domain = domain; req->done_event = done_event; if (domain == mono_get_root_domain ()) finalizing_root_domain = TRUE; mono_finalizer_lock (); domains_to_finalize = g_slist_append (domains_to_finalize, req); mono_finalizer_unlock (); /* Tell the finalizer thread to finalize this appdomain */ mono_gc_finalize_notify (); if (timeout == -1) timeout = INFINITE; while (TRUE) { res = WaitForSingleObjectEx (done_event, timeout, TRUE); /* printf ("WAIT RES: %d.\n", res); */ if (res == WAIT_IO_COMPLETION) { if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0) return FALSE; } else if (res == WAIT_TIMEOUT) { /* We leak the handle here */ return FALSE; } else { break; } } CloseHandle (done_event); if (domain == mono_get_root_domain ()) { mono_thread_pool_cleanup (); mono_gc_finalize_threadpool_threads (); } return TRUE; #else /* We don't support domain finalization without a GC */ return FALSE; #endif }
void * mono_arch_create_method_pointer (MonoMethod *method) { MonoMethodSignature *sig; MonoJitInfo *ji; guint stack_size, code_size, stackval_arg_pos, local_pos; guint i, local_start, reg_param = 0, stack_param, cpos, vt_cur; guint32 align = 0; guint32 *p, *code_buffer; gint *vtbuf; gint32 simpletype; code_size = 1024; /* these should be calculated... */ stack_size = 1024; stack_param = 0; sig = method->signature; p = code_buffer = g_malloc (code_size); DEBUG(fprintf(stderr, "Delegate [start emiting] %s\n", method->name)); DEBUG(fprintf(stderr, "%s\n", sig_to_name(sig, FALSE))); p = emit_prolog (p, sig, stack_size); /* fill MonoInvocation */ sparc_st_imm_ptr (p, sparc_g0, sparc_sp, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex))); sparc_st_imm_ptr (p, sparc_g0, sparc_sp, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler))); sparc_st_imm_ptr (p, sparc_g0, sparc_sp, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent))); sparc_set_ptr (p, (void *)method, sparc_l0); sparc_st_imm_ptr (p, sparc_l0, sparc_sp, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method))); stackval_arg_pos = MINV_POS + sizeof (MonoInvocation); local_start = local_pos = stackval_arg_pos + (sig->param_count + 1) * sizeof (stackval); if (sig->hasthis) { sparc_st_imm_ptr (p, sparc_i0, sparc_sp, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj))); reg_param = 1; } if (sig->param_count) { gint save_count = MIN (OUT_REGS, sig->param_count + sig->hasthis); for (i = reg_param; i < save_count; i++) { sparc_st_imm_ptr (p, sparc_i0 + i, sparc_sp, local_pos); local_pos += SLOT_SIZE; } } /* prepare space for valuetypes */ vt_cur = local_pos; vtbuf = alloca (sizeof(int)*sig->param_count); cpos = 0; for (i = 0; i < sig->param_count; i++) { MonoType *type = sig->params [i]; vtbuf [i] = -1; if (!sig->params[i]->byref && type->type == MONO_TYPE_VALUETYPE) { MonoClass *klass = type->data.klass; gint size; if (klass->enumtype) continue; size = mono_class_native_size (klass, &align); cpos += align - 1; cpos &= ~(align - 1); vtbuf [i] = cpos; cpos += size; } } cpos += SLOT_SIZE - 1; cpos &= ~(SLOT_SIZE - 1); local_pos += cpos; /* set MonoInvocation::stack_args */ sparc_add_imm (p, 0, sparc_sp, stackval_arg_pos, sparc_l0); sparc_st_imm_ptr (p, sparc_l0, sparc_sp, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args))); /* add stackval arguments */ for (i=0; i < sig->param_count; i++) { int stack_offset; int type; if (reg_param < OUT_REGS) { stack_offset = local_start + i * SLOT_SIZE; reg_param++; } else { stack_offset = stack_size + 8 + stack_param; stack_param++; } if (!sig->params[i]->byref) { type = sig->params[i]->type; enum_arg: switch (type) { case MONO_TYPE_I8: case MONO_TYPE_U8: case MONO_TYPE_I: case MONO_TYPE_U: case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_CLASS: case MONO_TYPE_SZARRAY: case MONO_TYPE_PTR: case MONO_TYPE_R8: break; case MONO_TYPE_I4: case MONO_TYPE_U4: stack_offset += SLOT_SIZE - 4; break; case MONO_TYPE_CHAR: case MONO_TYPE_I2: case MONO_TYPE_U2: stack_offset += SLOT_SIZE - 2; break; case MONO_TYPE_I1: case MONO_TYPE_U1: case MONO_TYPE_BOOLEAN: stack_offset += SLOT_SIZE - 1; break; case MONO_TYPE_VALUETYPE: if (sig->params[i]->data.klass->enumtype) { type = sig->params[i]->data.klass->enum_basetype->type; goto enum_arg; } g_assert(vtbuf[i] >= 0); break; default: g_error ("can not cope with delegate arg type %d", type); } } sparc_add_imm (p, 0, sparc_sp, stack_offset, sparc_o2); if (vtbuf[i] >= 0) { sparc_add_imm (p, 0, sparc_sp, vt_cur, sparc_o1); sparc_st_imm_ptr (p, sparc_o1, sparc_sp, stackval_arg_pos); sparc_add_imm (p, 0, sparc_sp, stackval_arg_pos, sparc_o1); sparc_ld_imm_ptr (p, sparc_o2, 0, sparc_o2); vt_cur += vtbuf[i]; } else { sparc_add_imm (p, 0, sparc_sp, stackval_arg_pos, sparc_o1); } sparc_set_ptr (p, (void *)sig->params[i], sparc_o0); sparc_set (p, (guint32)sig->pinvoke, sparc_o3); /* YOU make the CALL! */ sparc_set_ptr (p, (void *)stackval_from_data, sparc_l0); sparc_jmpl_imm (p, sparc_l0, 0, sparc_callsite); sparc_nop (p); stackval_arg_pos += sizeof(stackval); } /* return value storage */ /* Align to dword */ stackval_arg_pos = (stackval_arg_pos + (8 - 1)) & (~(8 -1)); if (sig->param_count) { sparc_add_imm (p, 0, sparc_sp, stackval_arg_pos, sparc_l0); } if (!sig->ret->byref && sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->data.klass->enumtype) { #if !SPARCV9 /* pass on callers buffer */ sparc_ld_imm_ptr (p, sparc_fp, 64, sparc_l1); sparc_st_imm_ptr (p, sparc_l1, sparc_l0, 0); #else sparc_add_imm (p, 0, sparc_l0, sizeof(stackval), sparc_l1); sparc_st_imm_ptr (p, sparc_l1, sparc_l0, 0); #endif } sparc_st_imm_ptr (p, sparc_l0, sparc_sp, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); /* call ves_exec_method */ sparc_add_imm (p, 0, sparc_sp, MINV_POS, sparc_o0); sparc_set_ptr (p, (void *)ves_exec_method, sparc_l0); sparc_jmpl_imm (p, sparc_l0, 0, sparc_callsite); sparc_nop (p); /* move retval from stackval to proper place (r3/r4/...) */ if (sig->ret->byref) { sparc_ld_imm_ptr (p, sparc_sp, stackval_arg_pos, sparc_i0 ); } else { enum_retvalue: switch (sig->ret->type) { case MONO_TYPE_VOID: break; case MONO_TYPE_BOOLEAN: case MONO_TYPE_I1: case MONO_TYPE_U1: case MONO_TYPE_I2: case MONO_TYPE_U2: case MONO_TYPE_I4: case MONO_TYPE_U4: sparc_ld_imm (p, sparc_sp, stackval_arg_pos, sparc_i0); break; case MONO_TYPE_I: case MONO_TYPE_U: case MONO_TYPE_OBJECT: case MONO_TYPE_STRING: case MONO_TYPE_CLASS: sparc_ld_imm_ptr (p, sparc_sp, stackval_arg_pos, sparc_i0); break; case MONO_TYPE_I8: case MONO_TYPE_U8: #if SPARCV9 sparc_ldx_imm (p, sparc_sp, stackval_arg_pos, sparc_i0); #else sparc_ld_imm (p, sparc_sp, stackval_arg_pos, sparc_i0); sparc_ld_imm (p, sparc_sp, stackval_arg_pos + 4, sparc_i1); #endif break; case MONO_TYPE_R4: sparc_lddf_imm (p, sparc_sp, stackval_arg_pos, sparc_f0); sparc_fdtos(p, sparc_f0, sparc_f0); break; case MONO_TYPE_R8: sparc_lddf_imm (p, sparc_sp, stackval_arg_pos, sparc_f0); break; case MONO_TYPE_VALUETYPE: { gint size; gint reg = sparc_i0; if (sig->ret->data.klass->enumtype) { simpletype = sig->ret->data.klass->enum_basetype->type; goto enum_retvalue; } #if SPARCV9 size = mono_class_native_size (sig->ret->data.klass, NULL); sparc_ldx_imm (p, sparc_sp, stackval_arg_pos, sparc_l0); if (size <= 16) { gint off = 0; if (size >= 8) { sparc_ldx_imm (p, sparc_l0, 0, reg); size -= 8; off += 8; reg++; } if (size > 0) sparc_ldx_imm (p, sparc_l0, off, reg); } else NOT_IMPL("value type as ret val from delegate"); #endif break; } default: g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type); break; } } p = emit_epilog (p, sig, stack_size); for (i = 0; i < ((p - code_buffer)/2); i++) flushi((code_buffer + (i*8))); ji = g_new0 (MonoJitInfo, 1); ji->method = method; ji->code_size = p - code_buffer; ji->code_start = code_buffer; mono_jit_info_table_add (mono_get_root_domain (), ji); DEBUG(sparc_disassemble_code (code_buffer, p, method->name)); DEBUG(fprintf(stderr, "Delegate [end emiting] %s\n", method->name)); return ji->code_start; }
/* Entry point called by LdrLoadDll of ntdll.dll after _CorValidateImage. */ BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved) { MonoAssembly* assembly; MonoImage* image; gchar* file_name; gchar* error; switch (dwReason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls (hInst); file_name = mono_get_module_file_name (hInst); if (mono_get_root_domain ()) { image = mono_image_open_from_module_handle (hInst, mono_path_resolve_symlinks (file_name), TRUE, NULL); } else { init_from_coree = TRUE; mono_runtime_load (file_name, NULL); error = (gchar*) mono_check_corlib_version (); if (error) { g_free (error); g_free (file_name); mono_runtime_quit (); return FALSE; } image = mono_image_open (file_name, NULL); if (image) { image->has_entry_point = TRUE; mono_close_exe_image (); /* Decrement reference count to zero. (Image will not be closed.) */ mono_image_close (image); } } if (!image) { g_free (file_name); return FALSE; } /* * FIXME: Find a better way to call mono_image_fixup_vtable. Only * loader trampolines should be used and assembly loading should * probably be delayed until the first call to an exported function. */ if (image->tables [MONO_TABLE_ASSEMBLY].rows && ((MonoCLIImageInfo*) image->image_info)->cli_cli_header.ch_vtable_fixups.rva) assembly = mono_assembly_open (file_name, NULL); g_free (file_name); break; case DLL_PROCESS_DETACH: if (lpReserved != NULL) /* The process is terminating. */ return TRUE; file_name = mono_get_module_file_name (hInst); image = mono_image_loaded (file_name); if (image) mono_image_close (image); g_free (file_name); break; } return TRUE; }
void CPipeServer::InitMono() { HMODULE hMono=GetModuleHandle(L"mono.dll"); if (!hMono) { //this process doesn't use mono.dll Perhaps it's renamed. Find a module that exports mono_thread_attach HANDLE ths=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); if (ths != INVALID_HANDLE_VALUE) { MODULEENTRY32 me; me.dwSize = sizeof(me); if (Module32First(ths, &me)) { do { if (GetProcAddress(me.hModule, "mono_thread_attach")) { hMono = me.hModule; break; } } while (Module32Next(ths, &me)); } CloseHandle(ths); } } WriteQword((UINT64)hMono); if (hMono) { std::stringstream x; x.clear(); x << "Mono dll found at " << std::hex << hMono <<"\n"; OutputDebugStringA(x.str().c_str()); if (attached==FALSE) { g_free=(G_FREE)GetProcAddress(hMono, "g_free"); mono_get_root_domain=(MONO_GET_ROOT_DOMAIN)GetProcAddress(hMono, "mono_get_root_domain"); mono_thread_attach=(MONO_THREAD_ATTACH)GetProcAddress(hMono, "mono_thread_attach"); mono_thread_detach=(MONO_THREAD_DETACH)GetProcAddress(hMono, "mono_thread_detach"); mono_object_get_class=(MONO_OBJECT_GET_CLASS)GetProcAddress(hMono, "mono_object_get_class"); mono_domain_foreach=(MONO_DOMAIN_FOREACH)GetProcAddress(hMono, "mono_domain_foreach"); mono_domain_set=(MONO_DOMAIN_SET)GetProcAddress(hMono, "mono_domain_set"); mono_assembly_foreach=(MONO_ASSEMBLY_FOREACH)GetProcAddress(hMono, "mono_assembly_foreach"); mono_assembly_get_image=(MONO_ASSEMBLY_GET_IMAGE)GetProcAddress(hMono, "mono_assembly_get_image"); mono_image_get_name=(MONO_IMAGE_GET_NAME)GetProcAddress(hMono, "mono_image_get_name"); mono_image_get_table_info=(MONO_IMAGE_GET_TABLE_INFO)GetProcAddress(hMono, "mono_image_get_table_info"); mono_image_rva_map=(MONO_IMAGE_RVA_MAP)GetProcAddress(hMono, "mono_image_rva_map"); mono_table_info_get_rows=(MONO_TABLE_INFO_GET_ROWS)GetProcAddress(hMono, "mono_table_info_get_rows"); mono_metadata_decode_row_col=(MONO_METADATA_DECODE_ROW_COL)GetProcAddress(hMono, "mono_metadata_decode_row_col"); mono_metadata_string_heap=(MONO_METADATA_STRING_HEAP)GetProcAddress(hMono, "mono_metadata_string_heap"); mono_class_get=(MONO_CLASS_GET)GetProcAddress(hMono, "mono_class_get"); mono_class_from_name_case=(MONO_CLASS_FROM_NAME_CASE)GetProcAddress(hMono, "mono_class_from_name_case"); mono_class_get_name=(MONO_CLASS_GET_NAME)GetProcAddress(hMono, "mono_class_get_name"); mono_class_get_namespace=(MONO_CLASS_GET_NAMESPACE)GetProcAddress(hMono, "mono_class_get_namespace"); mono_class_get_methods=(MONO_CLASS_GET_METHODS)GetProcAddress(hMono, "mono_class_get_methods"); mono_class_get_method_from_name=(MONO_CLASS_GET_METHOD_FROM_NAME)GetProcAddress(hMono, "mono_class_get_method_from_name"); mono_class_get_fields=(MONO_CLASS_GET_FIELDS)GetProcAddress(hMono, "mono_class_get_fields"); mono_class_get_parent=(MONO_CLASS_GET_PARENT)GetProcAddress(hMono, "mono_class_get_parent"); mono_class_vtable=(MONO_CLASS_VTABLE)GetProcAddress(hMono, "mono_class_vtable"); mono_class_num_fields=(MONO_CLASS_NUM_FIELDS)GetProcAddress(hMono, "mono_class_num_fields"); mono_class_num_methods=(MONO_CLASS_NUM_METHODS)GetProcAddress(hMono, "mono_class_num_methods"); mono_field_get_name=(MONO_FIELD_GET_NAME)GetProcAddress(hMono, "mono_field_get_name"); mono_field_get_type=(MONO_FIELD_GET_TYPE)GetProcAddress(hMono, "mono_field_get_type"); mono_field_get_parent=(MONO_FIELD_GET_PARENT)GetProcAddress(hMono, "mono_field_get_parent"); mono_field_get_offset=(MONO_FIELD_GET_OFFSET)GetProcAddress(hMono, "mono_field_get_offset"); mono_field_get_flags = (MONO_FIELD_GET_FLAGS)GetProcAddress(hMono, "mono_field_get_flags"); mono_type_get_name=(MONO_TYPE_GET_NAME)GetProcAddress(hMono, "mono_type_get_name"); mono_type_get_type=(MONO_TYPE_GET_TYPE)GetProcAddress(hMono, "mono_type_get_type"); mono_method_get_name=(MONO_METHOD_GET_NAME)GetProcAddress(hMono, "mono_method_get_name"); mono_method_get_class=(MONO_METHOD_GET_CLASS)GetProcAddress(hMono, "mono_method_get_class"); mono_method_get_header=(MONO_METHOD_GET_HEADER)GetProcAddress(hMono, "mono_method_get_header"); mono_method_signature=(MONO_METHOD_SIG)GetProcAddress(hMono, "mono_method_signature"); mono_method_get_param_names = (MONO_METHOD_GET_PARAM_NAMES)GetProcAddress(hMono, "mono_method_get_param_names"); mono_signature_get_desc = (MONO_SIGNATURE_GET_DESC)GetProcAddress(hMono, "mono_signature_get_desc"); mono_signature_get_param_count = (MONO_SIGNATURE_GET_PARAM_COUNT)GetProcAddress(hMono, "mono_signature_get_param_count"); mono_signature_get_return_type = (MONO_SIGNATURE_GET_RETURN_TYPE)GetProcAddress(hMono, "mono_signature_get_return_type"); mono_compile_method=(MONO_COMPILE_METHOD)GetProcAddress(hMono, "mono_compile_method"); mono_free_method=(MONO_FREE_METHOD)GetProcAddress(hMono, "mono_free_method"); mono_jit_info_table_find=(MONO_JIT_INFO_TABLE_FIND)GetProcAddress(hMono, "mono_jit_info_table_find"); mono_jit_info_get_method=(MONO_JIT_INFO_GET_METHOD)GetProcAddress(hMono, "mono_jit_info_get_method"); mono_jit_info_get_code_start=(MONO_JIT_INFO_GET_CODE_START)GetProcAddress(hMono, "mono_jit_info_get_code_start"); mono_jit_info_get_code_size=(MONO_JIT_INFO_GET_CODE_SIZE)GetProcAddress(hMono, "mono_jit_info_get_code_size"); mono_method_header_get_code=(MONO_METHOD_HEADER_GET_CODE)GetProcAddress(hMono, "mono_method_header_get_code"); mono_disasm_code=(MONO_DISASM_CODE)GetProcAddress(hMono, "mono_disasm_code"); mono_vtable_get_static_field_data = (MONO_VTABLE_GET_STATIC_FIELD_DATA)GetProcAddress(hMono, "mono_vtable_get_static_field_data"); if (mono_get_root_domain==NULL) OutputDebugStringA("mono_get_root_domain not assigned"); if (mono_thread_attach==NULL) OutputDebugStringA("mono_thread_attach not assigned"); if (mono_object_get_class==NULL) OutputDebugStringA("mono_object_get_class not assigned"); if (mono_class_get_name==NULL) OutputDebugStringA("mono_class_get_name not assigned"); if (mono_domain_foreach==NULL) OutputDebugStringA("mono_domain_foreach not assigned"); if (mono_domain_set==NULL) OutputDebugStringA("mono_domain_set not assigned"); if (mono_assembly_foreach==NULL) OutputDebugStringA("mono_assembly_foreach not assigned"); if (mono_assembly_get_image==NULL) OutputDebugStringA("mono_assembly_get_image not assigned"); if (mono_image_get_name==NULL) OutputDebugStringA("mono_image_get_name not assigned"); mono_selfthread=mono_thread_attach(mono_get_root_domain()); attached=TRUE; } else OutputDebugStringA("Already attached"); } }