日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

mono android 开机启动,浅析 Android 平台 mono执行机制 by郡墙

發布時間:2023/12/18 Android 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mono android 开机启动,浅析 Android 平台 mono执行机制 by郡墙 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在 Android平臺中采用Mono機制編譯、處理C#語言編寫的邏輯代碼,編譯之后本地存儲IL指令。在游戲運行階段存在代碼動態編譯的過程,原理為:利用 Unity3D引擎的 Mono jit機制將IL指令編譯為機器可識別的匯編指令。

Mono 是什么?

Sponsored by Microsoft, Mono is an open source implementation of Microsoft's .NET Framework based on the ECMA standards for C# and the Common Language Runtime. A growing family of solutions and an active and enthusiastic contributing community is helping position Mono to become the leading choice for development of cross platform applications.

引用官方的介紹,這部分不是本文的重點,有興趣的讀者可以自行前往官網了解。

Mono 的執行流程

首先我們從 mono的入口函數開始分析

大致運行流程如下

Main() => mono_main_with_optinos() => mono_main() => mini_init() => mono_assembly_open() => main_thread_handler() => mini_cleanup()

其中 main_thread_handler 函數主要負責編譯 & 處理 IL 指令,執行流程如下

main_thread_handler()

=> mono_jit_exec()

=> mono_assembly_get_image() 得倒 image 信息

=> mono_runtime_run_main()

=> mono_thread_set_main()

=> mono_assembly_set_main()

=> mono_runtime_exec_main()

....

mono_runtime_invoke 處理將要調用的方法,例如 ClassName::Main()。default_mono_runtime_invoke 函數實際調用 mono_jit_runtime_invoke 函數。mono_jit_runtime_invoke 函數調用來 mono_jit_compile_method_with_opt 實現編譯目標函數的代碼,調用mono_jit_compile_method 編譯目標函數的 runtime wrapper (運行時的上層封裝調用)。 runtime_invoke 函數調用編譯之后的目標函數,其中 info->compiled_method 參數為編譯之后目標函數代碼在內存中的地址信息。

通過以上分析,mono_jit_compile_method_with_opt 函數為C#函數代碼編譯為目標機器指令的關鍵函數,我們來分析以下這部分的執行流程

mono_jit_compile_method_with_opt()

mono_jit_compile_method_inner()

mini_method_compile()

....

其中 mini_method_compile 函數在內部通過 Mono的 JIT 機制實現動態編譯過程。

C#函數的執行過程

mono_runtime_invoke 函數實現與 mono \ object.c中,而實際調用 mono_jit_runtime_invoke 函數代碼則在 mini.c 文件中。mono_runtime_invoke 函數負責實現 C#函數的代碼編譯和執行。

/**

* mono_jit_runtime_invoke:

* \param method: the method to invoke

* \param obj: this pointer

* \param params: array of parameter values.

* \param exc: Set to the exception raised in the managed method.

* \param error: error or caught exception object

* If \p exc is NULL, \p error is thrown instead.

* If coop is enabled, \p exc argument is ignored -

* all exceptions are caught and propagated through \p error

*/

static MonoObject*

mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)

{

MonoMethod *invoke, *callee;

MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);

MonoDomain *domain = mono_domain_get ();

MonoJitDomainInfo *domain_info;

RuntimeInvokeInfo *info, *info2;

MonoJitInfo *ji = NULL;

gboolean callee_gsharedvt = FALSE;

if (mono_use_interpreter)

return mini_get_interp_callbacks ()->runtime_invoke (method, obj, params, exc, error);

error_init (error);

if (exc)

*exc = NULL;

if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) {

g_warning ("Ignoring invocation of an instance method on a NULL instance.\n");

return NULL;

}

domain_info = domain_jit_info (domain);

info = (RuntimeInvokeInfo *)mono_conc_hashtable_lookup (domain_info->runtime_invoke_hash, method);

//mono_jit_runtime_invoke 函數會先通過查找列表,判斷是否已創建對應的 info 信息,若不存在,則先進行編譯并得倒 info信息

if (!info) {

if (mono_security_core_clr_enabled ()) {

/*

* This might be redundant since mono_class_vtable () already does this,

* but keep it just in case for moonlight.

*/

mono_class_setup_vtable (method->klass);

if (mono_class_has_failure (method->klass)) {

mono_error_set_for_class_failure (error, method->klass);

if (exc)

*exc = (MonoObject*)mono_class_get_exception_for_failure (method->klass);

return NULL;

}

}

gpointer compiled_method;

callee = method;

if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&

(method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {

/*

* Array Get/Set/Address methods. The JIT implements them using inline code

* inside the runtime invoke wrappers, so no need to compile them.

*/

if (mono_aot_only) {

/*

* Call a wrapper, since the runtime invoke wrapper was not generated.

*/

MonoMethod *wrapper;

wrapper = mono_marshal_get_array_accessor_wrapper (method);

invoke = mono_marshal_get_runtime_invoke (wrapper, FALSE);

callee = wrapper;

} else {

callee = NULL;

}

}

if (callee) {

compiled_method = mono_jit_compile_method (callee, error);

if (!compiled_method) {

g_assert (!mono_error_ok (error));

return NULL;

}

if (mono_llvm_only) {

ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);

callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);

if (callee_gsharedvt)

callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));

}

if (!callee_gsharedvt)

compiled_method = mini_add_method_trampoline (callee, compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);

} else {

compiled_method = NULL;

}

info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt, error);

if (!mono_error_ok (error))

return NULL;

mono_domain_lock (domain);

info2 = (RuntimeInvokeInfo *)mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info);

mono_domain_unlock (domain);

if (info2) {

g_free (info);

info = info2;

}

}

/*

* We need this here because mono_marshal_get_runtime_invoke can place

* the helper method in System.Object and not the target class.

*/

if (!mono_runtime_class_init_full (info->vtable, error)) {

if (exc)

*exc = (MonoObject*) mono_error_convert_to_exception (error);

return NULL;

}

/* If coop is enabled, and the caller didn't ask for the exception to be caught separately,

we always catch the exception and propagate it through the MonoError */

gboolean catchExcInMonoError =

(exc == NULL) && mono_threads_is_coop_enabled ();

MonoObject *invoke_exc = NULL;

if (catchExcInMonoError)

exc = &invoke_exc;

/* The wrappers expect this to be initialized to NULL */

if (exc)

*exc = NULL;

#ifdef MONO_ARCH_DYN_CALL_SUPPORTED

if (info->dyn_call_info) {

MonoMethodSignature *sig = mono_method_signature (method);

gpointer *args;

static RuntimeInvokeDynamicFunction dyn_runtime_invoke;

int i, pindex, buf_size;

guint8 *buf;

guint8 retval [256];

if (!dyn_runtime_invoke) {

invoke = mono_marshal_get_runtime_invoke_dynamic ();

dyn_runtime_invoke = (RuntimeInvokeDynamicFunction)mono_jit_compile_method (invoke, error);

if (!mono_error_ok (error))

return NULL;

}

/* Convert the arguments to the format expected by start_dyn_call () */

args = (void **)g_alloca ((sig->param_count + sig->hasthis) * sizeof (gpointer));

pindex = 0;

if (sig->hasthis)

args [pindex ++] = &obj;

for (i = 0; i < sig->param_count; ++i) {

MonoType *t = sig->params [i];

if (t->byref) {

args [pindex ++] = &params [i];

} else if (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR) {

args [pindex ++] = &params [i];

} else {

args [pindex ++] = params [i];

}

}

//printf ("M: %s\n", mono_method_full_name (method, TRUE));

buf_size = mono_arch_dyn_call_get_buf_size (info->dyn_call_info);

buf = g_alloca (buf_size);

g_assert (buf);

mono_arch_start_dyn_call (info->dyn_call_info, (gpointer**)args, retval, buf);

dyn_runtime_invoke (buf, exc, info->compiled_method);

mono_arch_finish_dyn_call (info->dyn_call_info, buf);

if (catchExcInMonoError && *exc != NULL) {

mono_error_set_exception_instance (error, (MonoException*) *exc);

return NULL;

}

if (info->ret_box_class)

return mono_value_box_checked (domain, info->ret_box_class, retval, error);

else

return *(MonoObject**)retval;

}

#endif

MonoObject *result;

if (mono_llvm_only) {

result = mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);

if (!is_ok (error))

return NULL;

} else {

runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;

result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);

}

if (catchExcInMonoError && *exc != NULL)

mono_error_set_exception_instance (error, (MonoException*) *exc);

return result;

}

編譯完成(或之前已經編譯相同的 info 信息)后,則調用 info 自身的 runtime_invoke 函數實現對真正函數的調用。其中 runtime_invoke 函數的指針賦值。

compiled_method 變量存儲目標函數編譯之后所生成代碼的內存地址。在之前的代碼中,mono_jit_runtime_invoke 函數的第一個參數為 MonoMethod *method,在 MonoMethod 結構體中存儲來需要編譯和執行的 C# 函數的詳細信息,包括:方法名、方法所屬類的信息等。即根據 mono_jit_runtime_invoke 入口參數 method 可獲取 compiled_method 變量存儲的函數名,通過結構分析可以看到,在整個編譯和調用過程中, MonoMethod 函數都是相關關鍵的結構,其結構在 class_internal.h 文件中定義。

。。。

1)name 存儲 C# 函數名信息

2)klass 為 C# 函數所屬類的相關信息。

通過 mono_jit_runtime_invoke 函數可知道 C# 函數的調用過程,以及函數地址、函數名、函數所屬類等。

總結

以上是生活随笔為你收集整理的mono android 开机启动,浅析 Android 平台 mono执行机制 by郡墙的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。