ip++;
break;
case CEE_CPOBJ:
- g_error ("opcode 0x%02x not handled", *ip);
+ CHECK_STACK (2);
+ token = read32 (ip + 1);
+ if (method->wrapper_type != MONO_WRAPPER_NONE)
+ klass = mono_method_get_wrapper_data (method, token);
+ else
+ klass = mono_class_get (image, token);
+
+ mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+ sp -= 2;
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ MonoInst *store, *load;
+ MONO_INST_NEW (cfg, load, CEE_LDIND_REF);
+ load->cil_code = ip;
+ load->inst_i0 = sp [1];
+ load->type = ldind_type [CEE_LDIND_REF];
+ load->flags |= ins_flag;
+ MONO_INST_NEW (cfg, store, CEE_STIND_REF);
+ store->cil_code = ip;
+ handle_loaded_temps (cfg, bblock, stack_start, sp);
+ MONO_ADD_INS (bblock, store);
+ store->inst_i0 = sp [0];
+ store->inst_i1 = load;
+ store->flags |= ins_flag;
+ } else {
+ n = mono_class_value_size (klass, NULL);
+ if ((cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 5) {
+ MonoInst *copy;
+ MONO_INST_NEW (cfg, copy, OP_MEMCPY);
+ copy->inst_left = sp [0];
+ copy->inst_right = sp [1];
+ copy->cil_code = ip;
+ copy->unused = n;
+ MONO_ADD_INS (bblock, copy);
+ } else {
+ MonoInst *iargs [3];
+ iargs [0] = sp [0];
+ iargs [1] = sp [1];
+ NEW_ICONST (cfg, iargs [2], n);
+ iargs [2]->cil_code = ip;
+
+ mono_emit_jit_icall (cfg, bblock, helper_memcpy, iargs, ip);
+ }
+ }
+ ins_flag = 0;
+ ip += 5;
break;
case CEE_LDOBJ: {
MonoInst *iargs [3];
mono_class_init (klass);
if (klass->byval_arg.type == MONO_TYPE_VAR)
klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
+ ins->cil_code = ip;
+ ins->inst_i0 = sp [0];
+ ins->type = ldind_type [CEE_LDIND_REF];
+ ins->flags |= ins_flag;
+ ins_flag = 0;
+ *sp++ = ins;
+ ip += 5;
+ break;
+ }
n = mono_class_value_size (klass, NULL);
ins = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
NEW_TEMPLOADA (cfg, iargs [0], ins->inst_c0);
NEW_TEMPLOAD (cfg, *sp, ins->inst_c0);
++sp;
ip += 5;
+ ins_flag = 0;
inline_costs += 1;
break;
}
ip += 5;
*sp++ = ins;
break;
+ case CEE_UNBOX_ANY: {
+ MonoInst *add, *vtoffset;
+ MonoInst *iargs [3];
+
+ CHECK_STACK (1);
+ --sp;
+ token = read32 (ip + 1);
+ if (method->wrapper_type != MONO_WRAPPER_NONE)
+ klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
+ else
+ klass = mono_class_get (image, token);
+ mono_class_init (klass);
+
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ /* CASTCLASS */
+ MONO_INST_NEW (cfg, ins, CEE_CASTCLASS);
+ ins->type = STACK_OBJ;
+ ins->inst_left = *sp;
+ ins->klass = klass;
+ ins->inst_newa_class = klass;
+ ins->cil_code = ip;
+ *sp++ = ins;
+ ip += 5;
+ break;
+ }
+
+ MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
+ ins->type = STACK_OBJ;
+ ins->inst_left = *sp;
+ ins->klass = klass;
+ ins->inst_newa_class = klass;
+ ins->cil_code = ip;
+
+ MONO_INST_NEW (cfg, add, CEE_ADD);
+ NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
+ add->inst_left = ins;
+ add->inst_right = vtoffset;
+ add->type = STACK_MP;
+ *sp = add;
+ ip += 5;
+ /* LDOBJ impl */
+ n = mono_class_value_size (klass, NULL);
+ ins = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
+ NEW_TEMPLOADA (cfg, iargs [0], ins->inst_c0);
+ if ((cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 5) {
+ MonoInst *copy;
+ MONO_INST_NEW (cfg, copy, OP_MEMCPY);
+ copy->inst_left = iargs [0];
+ copy->inst_right = *sp;
+ copy->cil_code = ip;
+ copy->unused = n;
+ MONO_ADD_INS (bblock, copy);
+ } else {
+ iargs [1] = *sp;
+ NEW_ICONST (cfg, iargs [2], n);
+ iargs [2]->cil_code = ip;
+
+ mono_emit_jit_icall (cfg, bblock, helper_memcpy, iargs, ip);
+ }
+ NEW_TEMPLOAD (cfg, *sp, ins->inst_c0);
+ ++sp;
+ inline_costs += 2;
+ break;
+ }
case CEE_UNBOX: {
MonoInst *add, *vtoffset;
if (klass->byval_arg.type == MONO_TYPE_VAR)
klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ *sp = val;
+ ip += 5;
+ break;
+ }
/* much like NEWOBJ */
if ((cfg->opt & MONO_OPT_SHARED) || mono_compile_aot) {
NEW_DOMAINCONST (cfg, iargs [0]);
klass = mono_class_get (image, token);
if (klass->byval_arg.type == MONO_TYPE_VAR)
klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
- handle_initobj (cfg, bblock, *sp, NULL, klass, stack_start, sp);
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ MonoInst *store, *load;
+ NEW_PCONST (cfg, load, NULL);
+ load->cil_code = ip;
+ load->type = STACK_OBJ;
+ MONO_INST_NEW (cfg, store, CEE_STIND_REF);
+ store->cil_code = ip;
+ handle_loaded_temps (cfg, bblock, stack_start, sp);
+ MONO_ADD_INS (bblock, store);
+ store->inst_i0 = sp [0];
+ store->inst_i1 = load;
+ break;
+ } else {
+ handle_initobj (cfg, bblock, *sp, NULL, klass, stack_start, sp);
+ }
ip += 6;
inline_costs += 1;
break;
case CEE_SIZEOF:
CHECK_STACK_OVF (1);
token = read32 (ip + 2);
+ /* FIXXME: handle generics. */
if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
MonoType *type = mono_type_create_from_typespec (image, token);
token = mono_type_size (type, &align);
{
MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
- g_free (jit_tls);
+ /* handle_remove should be eventually called for this thread, too
+ g_free (jit_tls);*/
ExitThread (-1);
}
static void
-mono_thread_start_cb (guint32 tid, gpointer stack_start, gpointer func)
+setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
{
MonoJitTlsData *jit_tls;
MonoLMF *lmf;
+ MonoThread *thread;
jit_tls = g_new0 (MonoJitTlsData, 1);
TlsSetValue (mono_jit_tls_id, jit_tls);
- jit_tls->abort_func = mono_thread_abort;
+ jit_tls->abort_func = abort_func;
jit_tls->end_of_stack = stack_start;
lmf = g_new0 (MonoLMF, 1);
lmf->ebp = -1;
- jit_tls->lmf = lmf;
+ jit_tls->lmf = jit_tls->first_lmf = lmf;
+
+ thread = mono_thread_current ();
+ if (thread)
+ thread->jit_data = jit_tls;
+}
+
+static void
+mono_thread_start_cb (guint32 tid, gpointer stack_start, gpointer func)
+{
+ setup_jit_tls_data (stack_start, mono_thread_abort);
}
void (*mono_thread_attach_aborted_cb ) (MonoObject *obj) = NULL;
static void
mono_thread_attach_cb (guint32 tid, gpointer stack_start)
{
- MonoJitTlsData *jit_tls;
- MonoLMF *lmf;
-
- jit_tls = g_new0 (MonoJitTlsData, 1);
-
- TlsSetValue (mono_jit_tls_id, jit_tls);
-
- jit_tls->abort_func = mono_thread_abort_dummy;
- jit_tls->end_of_stack = stack_start;
+ setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
+}
- lmf = g_new0 (MonoLMF, 1);
- lmf->ebp = -1;
+static void
+mini_thread_cleanup (MonoThread *thread)
+{
+ MonoJitTlsData *jit_tls = thread->jit_data;
- jit_tls->lmf = lmf;
+ if (jit_tls) {
+ g_free (jit_tls->first_lmf);
+ g_free (jit_tls);
+ thread->jit_data = NULL;
+ }
}
void
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
//g_assert (syscall (SYS_sigaction, SIGILL, &sa, NULL) != -1);
- //g_assert (sigaction (mono_thread_get_abort_signal (), &sa, NULL) != -1);
+ g_assert (sigaction (mono_thread_get_abort_signal (), &sa, NULL) != -1);
#if 1
/* catch SIGSEGV */
mono_burg_init ();
mono_runtime_install_handlers ();
+ mono_threads_install_cleanup (mini_thread_cleanup);
mono_install_compile_method (mono_jit_compile_method);
mono_install_trampoline (mono_arch_create_jit_trampoline);