[llvmonly] Implement Assembly.GetCallingAssembly () in llvmonly mode by saving the...
authorZoltan Varga <vargaz@gmail.com>
Thu, 14 Jan 2016 16:26:22 +0000 (11:26 -0500)
committerZoltan Varga <vargaz@gmail.com>
Thu, 14 Jan 2016 16:26:27 +0000 (11:26 -0500)
mono/metadata/icall.c
mono/mini/jit-icalls.c
mono/mini/jit-icalls.h
mono/mini/method-to-ir.c
mono/mini/mini-runtime.c
mono/mini/mini.h

index cc0d7c957fe09e9e73df56fe94edbd18a5d4ab67..150a2814115b7928b70e0e1059f939854de3f4f0 100644 (file)
@@ -4663,6 +4663,8 @@ ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
        mono_stack_walk_no_il (get_caller_no_reflection, &dest);
        if (!dest)
                dest = m;
+       if (!m)
+               mono_raise_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
        return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
 }
 
index ef3e7a4e45a0d0f2973cdcbd960bc3768e0840e1..643a07e821d0049198a15a5661e203880a030a65 100644 (file)
@@ -1686,3 +1686,25 @@ mono_ckfinite (double d)
                mono_set_pending_exception (mono_get_exception_arithmetic ());
        return d;
 }
+
+void
+mono_llvmonly_set_calling_assembly (MonoImage *image)
+{
+       MonoJitTlsData *jit_tls = NULL;
+
+       jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+       g_assert (jit_tls);
+       jit_tls->calling_image = image;
+}
+
+MonoObject*
+mono_llvmonly_get_calling_assembly (void)
+{
+       MonoJitTlsData *jit_tls = NULL;
+
+       jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+       g_assert (jit_tls);
+       if (!jit_tls->calling_image)
+               mono_raise_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
+       return (MonoObject*)mono_assembly_get_object (mono_domain_get (), jit_tls->calling_image->assembly);
+}
index 2edf5759cd482d803cd2e6f2f881994dd100af93..0a27fea0c78ee5ff39db918bdc30209b95858c13 100644 (file)
@@ -213,4 +213,8 @@ MonoObject* mono_get_assembly_object (MonoImage *image);
 
 double mono_ckfinite (double d);
 
+void mono_llvmonly_set_calling_assembly (MonoImage *image);
+
+MonoObject* mono_llvmonly_get_calling_assembly (void);
+
 #endif /* __MONO_JIT_ICALLS_H__ */
index 96787ddd9999187c300dc4440e3bc3b4bc0edf87..13385f646949e6ffe0b66b99b3ed8bffe033c3d7 100644 (file)
@@ -4445,6 +4445,22 @@ icall_is_direct_callable (MonoCompile *cfg, MonoMethod *cmethod)
        return FALSE;
 }
 
+/* Return whenever METHOD calls Assembly.GetCallingAssembly () */
+// FIXME: It would be better to generalize this using some kind of method attribute
+// or automatic detection
+static gboolean
+method_needs_calling_assembly (MonoMethod *method)
+{
+       MonoClass *klass = method->klass;
+
+       if (klass->image != mono_defaults.corlib)
+               return FALSE;
+       if (!strcmp (klass->name_space, "System") && !strcmp (klass->name, "Activator") &&
+               !strcmp (method->name, "CreateInstance"))
+               return TRUE;
+       return FALSE;
+}
+
 #define is_complex_isinst(klass) ((klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
 
 static MonoInst*
@@ -6710,6 +6726,11 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        ins = mono_emit_jit_icall (cfg, mono_get_assembly_object, &assembly_ins);
                        return ins;
                }
+               if (cfg->llvm_only && !strcmp (cmethod->name, "GetCallingAssembly")) {
+                       /* No stack walks are currently available, so implement this as an intrinsic */
+                       ins = mono_emit_jit_icall (cfg, mono_llvmonly_get_calling_assembly, NULL);
+                       return ins;
+               }
        } else if (cmethod->klass == mono_defaults.math_class) {
                /* 
                 * There is general branchless code for Min/Max, but it does not work for 
@@ -9127,6 +9148,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        gboolean delegate_invoke = FALSE;
                        gboolean direct_icall = FALSE;
                        gboolean constrained_partial_call = FALSE;
+                       gboolean needs_calling_assembly = FALSE;
                        MonoMethod *cil_method;
 
                        CHECK_OPSIZE (5);
@@ -9245,6 +9267,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                }
                        }
 
+                       /*
+                        * Stack walks are not supported in llvmonly mode, so
+                        * when calling methods which call GetCallingAssembly (), save the
+                        * current assembly in the caller. The call to GetCallingAssembly ()
+                        * will be turned into an icall which will retrieve the value.
+                        */
+                       if (cfg->llvm_only && cmethod && method_needs_calling_assembly (cmethod)) {
+                               needs_calling_assembly = TRUE;
+
+                               MonoInst *assembly_ins;
+
+                               EMIT_NEW_AOTCONST (cfg, assembly_ins, MONO_PATCH_INFO_IMAGE, cfg->method->klass->image);
+                               ins = mono_emit_jit_icall (cfg, mono_llvmonly_set_calling_assembly, &assembly_ins);
+                       }
+
                        mono_save_token_info (cfg, image, token, cil_method);
 
                        if (!(seq_point_locs && mono_bitset_test_fast (seq_point_locs, ip + 5 - header->code)))
@@ -9943,6 +9980,18 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                EMIT_NEW_DUMMY_USE (cfg, dummy_use, keep_this_alive);
                        }
 
+                       if (needs_calling_assembly) {
+                               /*
+                                * Clear the calling assembly.
+                                * This is not EH safe, but this is not a problem in practice, since
+                                * the null value is only used for error checking.
+                                */
+                               MonoInst *assembly_ins;
+
+                               EMIT_NEW_PCONST (cfg, assembly_ins, NULL);
+                               ins = mono_emit_jit_icall (cfg, mono_llvmonly_set_calling_assembly, &assembly_ins);
+                       }
+
                        CHECK_CFG_EXCEPTION;
 
                        ip += 5;
index a11f89d5c3a0ee37a174d1ff6ba2261c66e1d3aa..886d6d0540f770c825360849db44e59d928f58c2 100644 (file)
@@ -3863,6 +3863,8 @@ register_icalls (void)
        register_icall_no_wrapper (mono_resolve_vcall_gsharedvt, "mono_resolve_vcall_gsharedvt", "ptr object int ptr ptr");
        register_icall_no_wrapper (mono_resolve_generic_virtual_call, "mono_resolve_generic_virtual_call", "ptr ptr int ptr");
        register_icall_no_wrapper (mono_resolve_generic_virtual_iface_call, "mono_resolve_generic_virtual_iface_call", "ptr ptr int ptr");
+       register_icall_no_wrapper (mono_llvmonly_set_calling_assembly, "mono_llvmonly_set_calling_assembly", "void ptr");
+       register_icall_no_wrapper (mono_llvmonly_get_calling_assembly, "mono_llvmonly_get_calling_assembly", "object");
        /* This needs a wrapper so it can have a preserveall cconv */
        register_icall (mono_init_vtable_slot, "mono_init_vtable_slot", "ptr ptr int", FALSE);
        register_icall (mono_init_delegate, "mono_init_delegate", "void object object ptr", TRUE);
index 3c75f2c8b897544ba09ac8d569ad8620773311f3..f28b32eaf6ce24076704bab95df50cdec19288dd 100644 (file)
@@ -1158,6 +1158,11 @@ typedef struct {
         * The current exception in flight
         */
        guint32 thrown_exc;
+
+       /*
+        * The calling assembly in llvmonly mode.
+        */
+       MonoImage *calling_image;
 } MonoJitTlsData;
 
 /*