X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Ftype-checking.c;h=0fcd2f9679e85bf700d0c996b3017911cedce3bb;hb=191a5e37316948d66f86a6a949572fe470859aa1;hp=08be97e7151c8a70ea06cef1292c49199697c0f3;hpb=a2d8de9766cd7870aa0e727c4221e3367e6fa343;p=mono.git diff --git a/mono/mini/type-checking.c b/mono/mini/type-checking.c index 08be97e7151..0fcd2f9679e 100644 --- a/mono/mini/type-checking.c +++ b/mono/mini/type-checking.c @@ -357,8 +357,78 @@ handle_castclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context mini_save_cast_details (cfg, klass, obj_reg, FALSE); if (mono_class_is_interface (klass)) { - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - mini_emit_iface_cast (cfg, vtable_reg, klass, NULL, NULL); + int tmp_reg = alloc_preg (cfg); +#ifndef DISABLE_REMOTING + MonoBasicBlock *interface_fail_bb; + int klass_reg = alloc_preg (cfg); + + NEW_BBLOCK (cfg, interface_fail_bb); + + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); + mini_emit_iface_cast (cfg, tmp_reg, klass, interface_fail_bb, is_null_bb); + + // iface bitmap check failed + MONO_START_BB (cfg, interface_fail_bb); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); + + mini_emit_class_check (cfg, klass_reg, mono_defaults.transparent_proxy_class); + + tmp_reg = alloc_preg (cfg); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info)); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0); + MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException"); + + MonoInst *args [1] = { src }; + MonoInst *proxy_test_inst = mono_emit_method_call (cfg, mono_marshal_get_proxy_cancast (klass), args, NULL); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, proxy_test_inst->dreg, 0); + MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException"); + + MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, is_null_bb); +#else + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); + mini_emit_iface_cast (cfg, tmp_reg, klass, NULL, NULL); + MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, is_null_bb); +#endif + } else if (mono_class_is_marshalbyref (klass)) { +#ifndef DISABLE_REMOTING + MonoBasicBlock *no_proxy_bb, *fail_1_bb; + int tmp_reg = alloc_preg (cfg); + int klass_reg = alloc_preg (cfg); + + NEW_BBLOCK (cfg, no_proxy_bb); + + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); + mini_emit_class_check_branch (cfg, klass_reg, mono_defaults.transparent_proxy_class, OP_PBNE_UN, no_proxy_bb); + + tmp_reg = alloc_preg (cfg); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, remote_class)); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoRemoteClass, proxy_class)); + + tmp_reg = alloc_preg (cfg); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info)); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0); + MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, no_proxy_bb); + + NEW_BBLOCK (cfg, fail_1_bb); + + mini_emit_isninst_cast (cfg, klass_reg, klass, fail_1_bb, is_null_bb); + + MONO_START_BB (cfg, fail_1_bb); + + MonoInst *args [1] = { src }; + MonoInst *proxy_test_inst = mono_emit_method_call (cfg, mono_marshal_get_proxy_cancast (klass), args, NULL); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, proxy_test_inst->dreg, 0); + MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException"); + + MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, is_null_bb); + + MONO_START_BB (cfg, no_proxy_bb); + + mini_emit_castclass_inst (cfg, obj_reg, klass_reg, klass, klass_inst, is_null_bb); +#else + g_error ("Transparent proxy support is disabled while trying to JIT code that uses it"); +#endif } else { int klass_reg = alloc_preg (cfg); @@ -438,9 +508,37 @@ handle_isinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context_us MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); if (mono_class_is_interface (klass)) { - g_assert (!context_used); - /* the is_null_bb target simply copies the input register to the output */ + int tmp_reg, klass_reg; + +#ifndef DISABLE_REMOTING + MonoBasicBlock *interface_fail_bb, *call_proxy_isinst; + + NEW_BBLOCK (cfg, interface_fail_bb); + NEW_BBLOCK (cfg, call_proxy_isinst); +#endif + +#ifndef DISABLE_REMOTING + klass_reg = alloc_preg (cfg); + mini_emit_iface_cast (cfg, vtable_reg, klass, interface_fail_bb, is_null_bb); + MONO_START_BB (cfg, interface_fail_bb); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); + + mini_emit_class_check_branch (cfg, klass_reg, mono_defaults.transparent_proxy_class, OP_PBNE_UN, false_bb); + + tmp_reg = alloc_preg (cfg); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info)); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0); + MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, false_bb); + + MONO_START_BB (cfg, call_proxy_isinst); + + MonoInst *args [1] = { src }; + MonoInst *proxy_test_inst = mono_emit_method_call (cfg, mono_marshal_get_proxy_cancast (klass), args, NULL); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, proxy_test_inst->dreg, 0); + MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, is_null_bb); +#else mini_emit_iface_cast (cfg, vtable_reg, klass, false_bb, is_null_bb); +#endif } else { int klass_reg = alloc_preg (cfg); @@ -514,7 +612,7 @@ handle_isinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context_us MONO_START_BB (cfg, false_bb); - MONO_EMIT_NEW_PCONST (cfg, res_reg, 0); + MONO_EMIT_NEW_PCONST (cfg, res_reg, NULL); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb); MONO_START_BB (cfg, is_null_bb); @@ -567,20 +665,13 @@ mono_decompose_typecheck (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) else ret = emit_castclass_with_cache (cfg, klass, args); - } else if (!context_used && (mono_class_is_marshalbyref (klass) || mono_class_is_interface (klass))) { + } else if (!context_used && is_isinst && mono_class_is_marshalbyref (klass)) { MonoInst *iargs [1]; int costs; iargs [0] = source; - if (is_isinst) { - MonoMethod *wrapper = mono_marshal_get_isinst (klass); - costs = mini_inline_method (cfg, wrapper, mono_method_signature (wrapper), iargs, 0, 0, TRUE); - } else { - MonoMethod *wrapper = mono_marshal_get_castclass (klass); - mini_save_cast_details (cfg, klass, source->dreg, TRUE); - costs = mini_inline_method (cfg, wrapper, mono_method_signature (wrapper), iargs, 0, 0, TRUE); - mini_reset_cast_details (cfg); - } + MonoMethod *wrapper = mono_marshal_get_isinst (klass); + costs = mini_inline_method (cfg, wrapper, mono_method_signature (wrapper), iargs, 0, 0, TRUE); g_assert (costs > 0); ret = iargs [0]; } else { @@ -599,17 +690,22 @@ mono_decompose_typecheck (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) void mono_decompose_typechecks (MonoCompile *cfg) { + gboolean found_typetest = FALSE; for (MonoBasicBlock *bb = cfg->bb_entry; bb; bb = bb->next_bb) { MonoInst *ins; MONO_BB_FOR_EACH_INS (bb, ins) { switch (ins->opcode) { case OP_ISINST: case OP_CASTCLASS: + found_typetest = TRUE; mono_decompose_typecheck (cfg, bb, ins); break; } } } + if ((cfg->verbose_level > 2) && found_typetest) + mono_print_code (cfg, "AFTER DECOMPOSE TYPE_CHECKS"); + } //Those two functions will go away as we get rid of CEE_MONO_CISINST and CEE_MONO_CCASTCLASS. @@ -646,26 +742,7 @@ mini_emit_cisinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src) MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, false_bb); if (mono_class_is_interface (klass)) { -#ifndef DISABLE_REMOTING - NEW_BBLOCK (cfg, interface_fail_bb); -#endif - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); -#ifndef DISABLE_REMOTING - mini_emit_iface_cast (cfg, tmp_reg, klass, interface_fail_bb, true_bb); - MONO_START_BB (cfg, interface_fail_bb); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - - mini_emit_class_check_branch (cfg, klass_reg, mono_defaults.transparent_proxy_class, OP_PBNE_UN, false_bb); - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, false2_bb); -#else - mini_emit_iface_cast (cfg, tmp_reg, klass, false_bb, true_bb); -#endif + g_error ("not supported"); } else { #ifndef DISABLE_REMOTING tmp_reg = alloc_preg (cfg); @@ -719,109 +796,6 @@ mini_emit_cisinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src) return ins; } -MonoInst* -mini_emit_ccastclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src) -{ - /* This opcode takes as input an object reference and a class, and returns: - 0) if the object is an instance of the class, - 1) if the object is a proxy whose type cannot be determined - an InvalidCastException exception is thrown otherwhise*/ - - MonoInst *ins; -#ifndef DISABLE_REMOTING - MonoBasicBlock *end_bb, *ok_result_bb, *no_proxy_bb, *interface_fail_bb, *fail_1_bb; -#else - MonoBasicBlock *ok_result_bb; -#endif - int obj_reg = src->dreg; - int dreg = alloc_ireg (cfg); - int tmp_reg = alloc_preg (cfg); - -#ifndef DISABLE_REMOTING - int klass_reg = alloc_preg (cfg); - NEW_BBLOCK (cfg, end_bb); -#endif - - NEW_BBLOCK (cfg, ok_result_bb); - - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, ok_result_bb); - - mini_save_cast_details (cfg, klass, obj_reg, FALSE); - - if (mono_class_is_interface (klass)) { -#ifndef DISABLE_REMOTING - NEW_BBLOCK (cfg, interface_fail_bb); - - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - mini_emit_iface_cast (cfg, tmp_reg, klass, interface_fail_bb, ok_result_bb); - MONO_START_BB (cfg, interface_fail_bb); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - - mini_emit_class_check (cfg, klass_reg, mono_defaults.transparent_proxy_class); - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0); - MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException"); - - MONO_EMIT_NEW_ICONST (cfg, dreg, 1); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb); -#else - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - mini_emit_iface_cast (cfg, tmp_reg, klass, NULL, NULL); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, ok_result_bb); -#endif - } else { -#ifndef DISABLE_REMOTING - NEW_BBLOCK (cfg, no_proxy_bb); - - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - mini_emit_class_check_branch (cfg, klass_reg, mono_defaults.transparent_proxy_class, OP_PBNE_UN, no_proxy_bb); - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, remote_class)); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoRemoteClass, proxy_class)); - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, no_proxy_bb); - - NEW_BBLOCK (cfg, fail_1_bb); - - mini_emit_isninst_cast (cfg, klass_reg, klass, fail_1_bb, ok_result_bb); - - MONO_START_BB (cfg, fail_1_bb); - - MONO_EMIT_NEW_ICONST (cfg, dreg, 1); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb); - - MONO_START_BB (cfg, no_proxy_bb); - - mini_emit_castclass (cfg, obj_reg, klass_reg, klass, ok_result_bb); -#else - g_error ("Transparent proxy support is disabled while trying to JIT code that uses it"); -#endif - } - - MONO_START_BB (cfg, ok_result_bb); - - MONO_EMIT_NEW_ICONST (cfg, dreg, 0); - -#ifndef DISABLE_REMOTING - MONO_START_BB (cfg, end_bb); -#endif - - /* FIXME: */ - MONO_INST_NEW (cfg, ins, OP_ICONST); - ins->dreg = dreg; - ins->type = STACK_I4; - - return ins; -} - //API used by method-to-ir.c void mini_emit_class_check (MonoCompile *cfg, int klass_reg, MonoClass *klass)