Merge pull request #5288 from lambdageek/bug-58454
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Tue, 1 Aug 2017 16:08:56 +0000 (12:08 -0400)
committerGitHub <noreply@github.com>
Tue, 1 Aug 2017 16:08:56 +0000 (12:08 -0400)
[sre] Pass declaring type to GetMethodFromHandle in GenericTypeParameterBuilder:InternalResolve (Fixes #58454)

46 files changed:
CODEOWNERS
mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs
mcs/errors/cs1525-23.cs
mcs/mcs/cs-parser.jay
mcs/tests/test-expression-bodied-04.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_x.xml
mcs/tools/mono-symbolicate/Makefile
mono/metadata/Makefile.am
mono/metadata/loader.c
mono/metadata/profiler-events.h
mono/metadata/profiler-legacy.c [deleted file]
mono/metadata/profiler-private.h
mono/metadata/profiler.c
mono/metadata/profiler.h
mono/mini/Makefile.am.in
mono/mini/aot-tests.cs
mono/mini/cpu-amd64.md
mono/mini/cpu-arm.md
mono/mini/cpu-arm64.md
mono/mini/cpu-x86.md
mono/mini/debug-mini.c
mono/mini/driver.c
mono/mini/interp/interp-internals.h
mono/mini/interp/interp.c
mono/mini/interp/mintops.def
mono/mini/interp/transform.c
mono/mini/jit.h
mono/mini/method-to-ir.c
mono/mini/mini-amd64.c
mono/mini/mini-arm.c
mono/mini/mini-arm64.c
mono/mini/mini-exceptions.c
mono/mini/mini-ops.h
mono/mini/mini-profiler.c [new file with mode: 0644]
mono/mini/mini-runtime.c
mono/mini/mini-x86.c
mono/mini/mini.c
mono/mini/mini.h
mono/profiler/log.c
msvc/libmono-static.vcxproj
msvc/libmono-static.vcxproj.filters
msvc/libmonoruntime.vcxproj
msvc/libmonoruntime.vcxproj.filters
msvc/mono.def
msvc/monosgen.def
scripts/ci/run-test-default.sh

index d835c00f0b24bb3565f087fed231fb43c1b5f2d9..5f20375bb92b34b7c6e5ef37cbf1b3c2b42ff9c5 100644 (file)
@@ -29,10 +29,11 @@ mcs/class/corlib/System.Reflection*/ @vargaz @lambdageek
 mcs/class/Mono.Debugger.Soft @vargaz
 mcs/class/Mono.Options @jonpryor
 mcs/class/Mono.Profiler.Log @alexrp
-mono/metadata/profiler* @alexrp
+mono/metadata/*profiler* @alexrp
 mono/metadata/threads* @luhenry @kumpera
 mono/metadata/threadpool* @luhenry
 mono/metadata/w32* @luhenry
+mono/mini/*profiler* @alexrp
 mono/profiler @alexrp
 mono/utils/atomic* @alexrp
 mono/utils/mono-hwcap* @alexrp
index 77ffc4c02c8eb4d3574dceafad466db792dd28ed..7d31bda158c8478b08750514dc6aad113f499e43 100644 (file)
@@ -47,10 +47,11 @@ namespace System.Runtime.ExceptionServices {
             // Copy over the details we need to save.
             m_Exception = exception;
 #if MONO
-                       var count = exception.captured_traces == null ? 0 : exception.captured_traces.Length;
+                       var traces = exception.captured_traces;
+                       var count = traces == null ? 0 : traces.Length;
                        var stack_traces = new System.Diagnostics.StackTrace [count + 1];
                        if (count != 0)
-                               Array.Copy (exception.captured_traces, 0, stack_traces, 0, count);
+                               Array.Copy (traces, 0, stack_traces, 0, count);
 
                        stack_traces [count] = new System.Diagnostics.StackTrace (exception, 0, true);
                        m_stackTrace = stack_traces;
index 8a97e05efb17d661c307723d41b8d7a9424a36ce..aa5ffc64e486a002b8d36427f830c9e9a4e05120 100644 (file)
@@ -1,4 +1,4 @@
-// CS1525: Unexpected symbol `public', expecting `:', `;', or `{'
+// CS1525: Unexpected symbol `public', expecting `:', `;', `{', or `=>'
 // Line: 5
 
 class TorrentEditor {
index 64652ccfcdad7e6f15f700c97b393608e04acad9..5f885a77763b8ccebc07be47fb643c310be926f5 100644 (file)
@@ -1337,7 +1337,7 @@ method_declaration
 
                // Was added earlier in the case of body being eof for full ast
          }
-         method_body_expression_block
+         method_body
          {
                Method method = (Method) $1;
                method.Block = (ToplevelBlock) $3;
@@ -1492,16 +1492,38 @@ method_header
          }
        ;
 
-method_body_expression_block
-       : method_body
-       | expression_block
-       ;
-
 method_body
        : block
+       | expression_block
        | SEMICOLON             { $$ = null; }
        ;
 
+destructor_body
+       : method_body
+       ;
+
+constructor_body
+       : block_prepared
+       | SEMICOLON             { current_block = null; $$ = null; }
+       | ARROW
+        {
+               if (lang_version < LanguageVersion.V_7) {
+                       FeatureIsNotAvailable (GetLocation ($1), "expression body constructor");
+               }
+
+               ++lexer.parsing_block;
+        }
+        expression SEMICOLON
+        {
+               lexer.parsing_block = 0;
+               current_block.AddStatement (new ContextualReturn ((Expression) $3));
+               var b = end_block (GetLocation ($4));
+               b.IsCompilerGenerated = true;
+               $$ = b;
+               current_block = null;
+        }
+       ;
+
 expression_block
        : ARROW
         {
@@ -2197,7 +2219,7 @@ operator_declaration
        : opt_attributes opt_modifiers operator_declarator 
          {
          }
-         method_body_expression_block
+         method_body
          {
                OperatorDeclaration decl = (OperatorDeclaration) $3;
                if (decl != null) {
@@ -2464,11 +2486,6 @@ constructor_declarator
          }
        ;
 
-constructor_body
-       : block_prepared
-       | SEMICOLON             { current_block = null; $$ = null; }
-       ;
-
 opt_constructor_initializer
        : /* Empty */
        | constructor_initializer
@@ -2518,7 +2535,7 @@ destructor_declaration
                
                current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters;
          }
-         IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body
+         IDENTIFIER OPEN_PARENS CLOSE_PARENS destructor_body
          {
                var lt = (LocatedToken) $5;
                if (lt.Value != current_container.MemberName.Name){
@@ -4547,7 +4564,7 @@ additive_expression
          }
        | additive_expression IS pattern_type_expr opt_identifier
          {
-               var is_expr = new Is ((Expression) $1, (Expression) $3, GetLocation ($2));
+               var is_expr = new Is ((Expression) $1, ((FullNamedExpression) $3), GetLocation ($2));
                if ($4 != null) {
                        if (lang_version < LanguageVersion.V_7)
                                FeatureIsNotAvailable (GetLocation ($4), "pattern matching");
@@ -6194,6 +6211,18 @@ switch_label
                lbag.AddLocation ($$, GetLocation ($3));
          }
 */
+
+       | CASE pattern_type_expr IDENTIFIER COLON
+         {
+               if (lang_version < LanguageVersion.V_7)
+                       FeatureIsNotAvailable (GetLocation ($1), "pattern matching");
+
+//             $$ = new SwitchLabel ((FullNamedExpression) $2), GetLocation ($1)) {
+//                     PatternMatching = true
+//             };
+
+               throw new NotImplementedException ("type pattern matching");
+         }
        | DEFAULT_COLON
          {
                $$ = new SwitchLabel (null, GetLocation ($1));
diff --git a/mcs/tests/test-expression-bodied-04.cs b/mcs/tests/test-expression-bodied-04.cs
new file mode 100644 (file)
index 0000000..815eabc
--- /dev/null
@@ -0,0 +1,16 @@
+// Introduced in C#7
+
+class VV
+{
+    VV () => Test ();
+
+    ~VV () => Test ();
+
+    void Test ()
+    {
+    }
+
+    public static void Main ()
+    {
+    }
+}
\ No newline at end of file
index 5eac11969e1220f675083b69ce0a2e414135e6e0..221283df2e4e6f62662a6dcc4d17c30a2e5428bc 100644 (file)
       </method>
     </type>
   </test>
+  <test name="test-expression-bodied-04.cs">
+    <type name="VV">
+      <method name="Void Finalize()" attrs="196">
+        <size>19</size>
+      </method>
+      <method name="Void Test()" attrs="129">
+        <size>2</size>
+      </method>
+      <method name="Void Main()" attrs="150">
+        <size>2</size>
+      </method>
+      <method name="Void .ctor()" attrs="6273">
+        <size>13</size>
+      </method>
+    </type>
+  </test>
   <test name="test-externalias-01.cs">
     <type name="Test">
       <method name="Int32 Main()" attrs="150">
index ddc254ec1138a5e495d354fb37b9bef64cabba9a..ea774840c110573a7faebc0f4caabb47c2eaf3e1 100644 (file)
@@ -45,21 +45,21 @@ COMPILE = \
        $(MONO) $(LIB_PATH)/$(PROGRAM) store-symbols $(MSYM_DIR) $(OUT_DIR); \
        $(MONO) $(LIB_PATH)/$(PROGRAM) store-symbols $(MSYM_DIR) $(LIB_PATH);
 
-check: test-local
+check: run-test
 
 AOT_SUPPORTED = $(shell $(MONO) --aot 2>&1 | grep -q "AOT compilation is not supported" && echo 0 || echo 1)
 
-test-local: test-without-aot test-with-aot test-with-aot-msym
+run-test-local: run-test-without-aot run-test-with-aot run-test-with-aot-msym
 
-test-without-aot: OUT_DIR = Test/without_aot
-test-without-aot: all
+run-test-without-aot: OUT_DIR = Test/without_aot
+run-test-without-aot: all
        @echo "Checking $(TEST_EXE) without AOT in $(OUT_DIR)"
        $(PREPARE_OUTDIR)
        $(COMPILE)
        $(CHECK_DIFF)
 
-test-with-aot: OUT_DIR = Test/with_aot
-test-with-aot: all
+run-test-with-aot: OUT_DIR = Test/with_aot
+run-test-with-aot: all
 ifeq ($(AOT_SUPPORTED), 1)
        @echo "Checking $(TEST_EXE) with AOT in $(OUT_DIR)"
        $(PREPARE_OUTDIR)
@@ -68,8 +68,8 @@ ifeq ($(AOT_SUPPORTED), 1)
        $(CHECK_DIFF)
 endif
 
-test-with-aot-msym: OUT_DIR = Test/with_aot_msym
-test-with-aot-msym: all
+run-test-with-aot-msym: OUT_DIR = Test/with_aot_msym
+run-test-with-aot-msym: all
 ifeq ($(AOT_SUPPORTED), 1)
        @echo "Checking $(TEST_EXE) with AOT (using .msym) in $(OUT_DIR)"
        $(PREPARE_OUTDIR)
index 76abb73aaa7ac4e1350685934fd0e3b9b8baf009..d90f9200ab0417b4178689dd293208d5e47ace00 100644 (file)
@@ -224,7 +224,6 @@ common_sources = \
        w32process-internals.h          \
        profiler.c              \
        profiler-events.h       \
-       profiler-legacy.c       \
        profiler-private.h      \
        rand.h                  \
        rand.c                  \
index e685ac227abfc4693a2fedb33903a57e6a56d574..61a6f94146588d2f175fdc83e83e760e0ea9c805 100644 (file)
@@ -1887,7 +1887,7 @@ mono_get_method_constrained_checked (MonoImage *image, guint32 token, MonoClass
 {
        error_init (error);
 
-       *cil_method = mono_get_method_from_token (image, token, NULL, context, NULL, error);
+       *cil_method = mono_get_method_checked (image, token, NULL, context, error);
        if (!*cil_method)
                return NULL;
 
index 7b85f00fb0c1a5512fd4a29f4dfa8708bf6def33..1a7e0b25ef9e3cb2178565ca4e84b5cb4bf36318 100644 (file)
@@ -54,8 +54,8 @@ MONO_PROFILER_EVENT_1(assembly_loaded, AssemblyLLoaded, MonoAssembly *, assembly
 MONO_PROFILER_EVENT_1(assembly_unloading, AssemblyLUnloading, MonoAssembly *, assembly)
 MONO_PROFILER_EVENT_1(assembly_unloaded, AssemblyLUnloaded, MonoAssembly *, assembly)
 
-MONO_PROFILER_EVENT_1(method_enter, MethodEnter, MonoMethod *, method)
-MONO_PROFILER_EVENT_1(method_leave, MethodLeave, MonoMethod *, method)
+MONO_PROFILER_EVENT_2(method_enter, MethodEnter, MonoMethod *, method, MonoProfilerCallContext *, context)
+MONO_PROFILER_EVENT_2(method_leave, MethodLeave, MonoMethod *, method, MonoProfilerCallContext *, context)
 MONO_PROFILER_EVENT_2(method_exception_leave, MethodExceptionLeave, MonoMethod *, method, MonoObject *, exception)
 MONO_PROFILER_EVENT_1(method_free, MethodFree, MonoMethod *, method)
 MONO_PROFILER_EVENT_1(method_begin_invoke, MethodBeginInvoke, MonoMethod *, method)
diff --git a/mono/metadata/profiler-legacy.c b/mono/metadata/profiler-legacy.c
deleted file mode 100644 (file)
index 31ddd48..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Licensed to the .NET Foundation under one or more agreements.
- * The .NET Foundation licenses this file to you under the MIT license.
- * See the LICENSE file in the project root for more information.
- */
-
-#include <mono/metadata/profiler-private.h>
-
-/*
- * The point of this file is to maintain compatibility with a few profiler API
- * functions used by Xamarin.{Android,iOS,Mac} so that they keep working
- * regardless of which system Mono version is used.
- *
- * TODO: Remove this some day if we're OK with breaking compatibility.
- */
-
-typedef void *MonoLegacyProfiler;
-
-typedef void (*MonoProfileFunc) (MonoLegacyProfiler *prof);
-typedef void (*MonoProfileThreadFunc) (MonoLegacyProfiler *prof, uintptr_t tid);
-typedef void (*MonoProfileGCFunc) (MonoLegacyProfiler *prof, MonoProfilerGCEvent event, int generation);
-typedef void (*MonoProfileGCResizeFunc) (MonoLegacyProfiler *prof, int64_t new_size);
-typedef void (*MonoProfileJitResult) (MonoLegacyProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result);
-
-struct _MonoProfiler {
-       MonoProfilerHandle handle;
-       MonoLegacyProfiler *profiler;
-       MonoProfileFunc shutdown_callback;
-       MonoProfileThreadFunc thread_start, thread_end;
-       MonoProfileGCFunc gc_event;
-       MonoProfileGCResizeFunc gc_heap_resize;
-       MonoProfileJitResult jit_end2;
-};
-
-static MonoProfiler *current;
-
-MONO_API void mono_profiler_install (MonoLegacyProfiler *prof, MonoProfileFunc callback);
-MONO_API void mono_profiler_install_thread (MonoProfileThreadFunc start, MonoProfileThreadFunc end);
-MONO_API void mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback);
-MONO_API void mono_profiler_install_jit_end (MonoProfileJitResult end);
-MONO_API void mono_profiler_set_events (int flags);
-
-static void
-shutdown_cb (MonoProfiler *prof)
-{
-       prof->shutdown_callback (prof->profiler);
-}
-
-void
-mono_profiler_install (MonoLegacyProfiler *prof, MonoProfileFunc callback)
-{
-       current = g_new0 (MonoProfiler, 1);
-       current->handle = mono_profiler_create (current);
-       current->profiler = prof;
-       current->shutdown_callback = callback;
-
-       if (callback)
-               mono_profiler_set_runtime_shutdown_end_callback (current->handle, shutdown_cb);
-}
-
-static void
-thread_start_cb (MonoProfiler *prof, uintptr_t tid)
-{
-       prof->thread_start (prof->profiler, tid);
-}
-
-static void
-thread_stop_cb (MonoProfiler *prof, uintptr_t tid)
-{
-       prof->thread_end (prof->profiler, tid);
-}
-
-void
-mono_profiler_install_thread (MonoProfileThreadFunc start, MonoProfileThreadFunc end)
-{
-       current->thread_start = start;
-       current->thread_end = end;
-
-       if (start)
-               mono_profiler_set_thread_started_callback (current->handle, thread_start_cb);
-
-       if (end)
-               mono_profiler_set_thread_stopped_callback (current->handle, thread_stop_cb);
-}
-
-static void
-gc_event_cb (MonoProfiler *prof, MonoProfilerGCEvent event, uint32_t generation)
-{
-       prof->gc_event (prof->profiler, event, generation);
-}
-
-static void
-gc_resize_cb (MonoProfiler *prof, uintptr_t size)
-{
-       prof->gc_heap_resize (prof->profiler, size);
-}
-
-void
-mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback)
-{
-       current->gc_event = callback;
-       current->gc_heap_resize = heap_resize_callback;
-
-       if (callback)
-               mono_profiler_set_gc_event_callback (current->handle, gc_event_cb);
-
-       if (heap_resize_callback)
-               mono_profiler_set_gc_resize_callback (current->handle, gc_resize_cb);
-}
-
-static void
-jit_done_cb (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
-{
-       prof->jit_end2 (prof->profiler, method, jinfo, 0);
-}
-
-static void
-jit_failed_cb (MonoProfiler *prof, MonoMethod *method)
-{
-       prof->jit_end2 (prof->profiler, method, NULL, 1);
-}
-
-void
-mono_profiler_install_jit_end (MonoProfileJitResult end)
-{
-       current->jit_end2 = end;
-
-       if (end) {
-               mono_profiler_set_jit_done_callback (current->handle, jit_done_cb);
-               mono_profiler_set_jit_failed_callback (current->handle, jit_failed_cb);
-       }
-}
-
-void
-mono_profiler_set_events (int flags)
-{
-       /* Do nothing. */
-}
index e087be07eb604fbfa0dc320637dfec8bd333998c..38e353b5b35b30f08789a6804df6fff176775f5e 100644 (file)
@@ -9,6 +9,7 @@
 
 #define MONO_PROFILER_UNSTABLE_GC_ROOTS
 #include <mono/metadata/profiler.h>
+#include <mono/utils/mono-context.h>
 #include <mono/utils/mono-lazy-init.h>
 #include <mono/utils/mono-os-mutex.h>
 #include <mono/utils/mono-os-semaphore.h>
@@ -42,16 +43,28 @@ struct _MonoProfilerDesc {
 
 typedef struct {
        gboolean startup_done;
+
        MonoProfilerHandle profilers;
+
        mono_lazy_init_t coverage_status;
        mono_mutex_t coverage_mutex;
        GHashTable *coverage_hash;
+
        MonoProfilerHandle sampling_owner;
        MonoSemType sampling_semaphore;
        MonoProfilerSampleMode sample_mode;
        guint32 sample_freq;
+
        gboolean allocations;
 
+       gboolean call_contexts;
+       void (*context_enable) (void);
+       gpointer (*context_get_this) (MonoProfilerCallContext *);
+       gpointer (*context_get_argument) (MonoProfilerCallContext *, guint32);
+       gpointer (*context_get_local) (MonoProfilerCallContext *, guint32);
+       gpointer (*context_get_result) (MonoProfilerCallContext *);
+       gpointer (*context_free_buffer) (gpointer);
+
 #define _MONO_PROFILER_EVENT(name) \
        volatile gint32 name ## _count;
 #define MONO_PROFILER_EVENT_0(name, type) \
@@ -95,7 +108,25 @@ mono_profiler_installed (void)
 MonoProfilerCoverageInfo *mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries);
 void mono_profiler_coverage_free (MonoMethod *method);
 
-gboolean mono_profiler_should_instrument_method (MonoMethod *method, gboolean entry);
+struct _MonoProfilerCallContext {
+       /*
+        * Must be the first field (the JIT relies on it). Only filled out if this
+        * is a JIT frame; otherwise, zeroed.
+        */
+       MonoContext context;
+       /*
+        * A non-NULL MonoInterpFrameHandle if this is an interpreter frame.
+        */
+       gpointer interp_frame;
+       MonoMethod *method;
+       /*
+        * Points to the return value for an epilogue context. For a prologue, this
+        * is set to NULL.
+        */
+       gpointer return_value;
+};
+
+MonoProfilerCallInstrumentationFlags mono_profiler_get_call_instrumentation_flags (MonoMethod *method);
 
 gboolean mono_profiler_sampling_enabled (void);
 void mono_profiler_sampling_thread_post (void);
index ccdb022a14fda51e6538da06f85329867d83e6eb..fa3f4eec9d1a6dfff683034165b8f94baaaba0b8 100644 (file)
@@ -361,9 +361,7 @@ mono_profiler_enable_allocations (void)
        if (mono_profiler_state.startup_done)
                return FALSE;
 
-       mono_profiler_state.allocations = TRUE;
-
-       return TRUE;
+       return mono_profiler_state.allocations = TRUE;
 }
 
 void
@@ -372,8 +370,61 @@ mono_profiler_set_call_instrumentation_filter_callback (MonoProfilerHandle handl
        InterlockedWritePointer (&handle->call_instrumentation_filter, (gpointer) cb);
 }
 
-gboolean
-mono_profiler_should_instrument_method (MonoMethod *method, gboolean entry)
+mono_bool
+mono_profiler_enable_call_context_introspection (void)
+{
+       if (mono_profiler_state.startup_done)
+               return FALSE;
+
+       mono_profiler_state.context_enable ();
+
+       return mono_profiler_state.call_contexts = TRUE;
+}
+
+void *
+mono_profiler_call_context_get_this (MonoProfilerCallContext *context)
+{
+       if (!mono_profiler_state.call_contexts)
+               return NULL;
+
+       return mono_profiler_state.context_get_this (context);
+}
+
+void *
+mono_profiler_call_context_get_argument (MonoProfilerCallContext *context, uint32_t position)
+{
+       if (!mono_profiler_state.call_contexts)
+               return NULL;
+
+       return mono_profiler_state.context_get_argument (context, position);
+}
+
+void *
+mono_profiler_call_context_get_local (MonoProfilerCallContext *context, uint32_t position)
+{
+       if (!mono_profiler_state.call_contexts)
+               return NULL;
+
+       return mono_profiler_state.context_get_local (context, position);
+}
+
+void *
+mono_profiler_call_context_get_result (MonoProfilerCallContext *context)
+{
+       if (!mono_profiler_state.call_contexts)
+               return NULL;
+
+       return mono_profiler_state.context_get_result (context);
+}
+
+void
+mono_profiler_call_context_free_buffer (void *buffer)
+{
+       mono_profiler_state.context_free_buffer (buffer);
+}
+
+MonoProfilerCallInstrumentationFlags
+mono_profiler_get_call_instrumentation_flags (MonoMethod *method)
 {
        MonoProfilerCallInstrumentationFlags flags = MONO_PROFILER_CALL_INSTRUMENTATION_NONE;
 
@@ -384,10 +435,7 @@ mono_profiler_should_instrument_method (MonoMethod *method, gboolean entry)
                        flags |= cb (handle->prof, method);
        }
 
-       if (entry)
-               return flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE;
-       else
-               return flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
+       return flags;
 }
 
 void
@@ -519,3 +567,134 @@ update_callback (volatile gpointer *location, gpointer new_, volatile gint32 *co
 #undef MONO_PROFILER_EVENT_3
 #undef MONO_PROFILER_EVENT_4
 #undef _MONO_PROFILER_EVENT
+
+/*
+ * The following code is here to maintain compatibility with a few profiler API
+ * functions used by Xamarin.{Android,iOS,Mac} so that they keep working
+ * regardless of which system Mono version is used.
+ *
+ * TODO: Remove this some day if we're OK with breaking compatibility.
+ */
+
+typedef void *MonoLegacyProfiler;
+
+typedef void (*MonoLegacyProfileFunc) (MonoLegacyProfiler *prof);
+typedef void (*MonoLegacyProfileThreadFunc) (MonoLegacyProfiler *prof, uintptr_t tid);
+typedef void (*MonoLegacyProfileGCFunc) (MonoLegacyProfiler *prof, MonoProfilerGCEvent event, int generation);
+typedef void (*MonoLegacyProfileGCResizeFunc) (MonoLegacyProfiler *prof, int64_t new_size);
+typedef void (*MonoLegacyProfileJitResult) (MonoLegacyProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result);
+
+struct _MonoProfiler {
+       MonoProfilerHandle handle;
+       MonoLegacyProfiler *profiler;
+       MonoLegacyProfileFunc shutdown_callback;
+       MonoLegacyProfileThreadFunc thread_start, thread_end;
+       MonoLegacyProfileGCFunc gc_event;
+       MonoLegacyProfileGCResizeFunc gc_heap_resize;
+       MonoLegacyProfileJitResult jit_end2;
+};
+
+static MonoProfiler *current;
+
+MONO_API void mono_profiler_install (MonoLegacyProfiler *prof, MonoLegacyProfileFunc callback);
+MONO_API void mono_profiler_install_thread (MonoLegacyProfileThreadFunc start, MonoLegacyProfileThreadFunc end);
+MONO_API void mono_profiler_install_gc (MonoLegacyProfileGCFunc callback, MonoLegacyProfileGCResizeFunc heap_resize_callback);
+MONO_API void mono_profiler_install_jit_end (MonoLegacyProfileJitResult end);
+MONO_API void mono_profiler_set_events (int flags);
+
+static void
+shutdown_cb (MonoProfiler *prof)
+{
+       prof->shutdown_callback (prof->profiler);
+}
+
+void
+mono_profiler_install (MonoLegacyProfiler *prof, MonoLegacyProfileFunc callback)
+{
+       current = g_new0 (MonoProfiler, 1);
+       current->handle = mono_profiler_create (current);
+       current->profiler = prof;
+       current->shutdown_callback = callback;
+
+       if (callback)
+               mono_profiler_set_runtime_shutdown_end_callback (current->handle, shutdown_cb);
+}
+
+static void
+thread_start_cb (MonoProfiler *prof, uintptr_t tid)
+{
+       prof->thread_start (prof->profiler, tid);
+}
+
+static void
+thread_stop_cb (MonoProfiler *prof, uintptr_t tid)
+{
+       prof->thread_end (prof->profiler, tid);
+}
+
+void
+mono_profiler_install_thread (MonoLegacyProfileThreadFunc start, MonoLegacyProfileThreadFunc end)
+{
+       current->thread_start = start;
+       current->thread_end = end;
+
+       if (start)
+               mono_profiler_set_thread_started_callback (current->handle, thread_start_cb);
+
+       if (end)
+               mono_profiler_set_thread_stopped_callback (current->handle, thread_stop_cb);
+}
+
+static void
+gc_event_cb (MonoProfiler *prof, MonoProfilerGCEvent event, uint32_t generation)
+{
+       prof->gc_event (prof->profiler, event, generation);
+}
+
+static void
+gc_resize_cb (MonoProfiler *prof, uintptr_t size)
+{
+       prof->gc_heap_resize (prof->profiler, size);
+}
+
+void
+mono_profiler_install_gc (MonoLegacyProfileGCFunc callback, MonoLegacyProfileGCResizeFunc heap_resize_callback)
+{
+       current->gc_event = callback;
+       current->gc_heap_resize = heap_resize_callback;
+
+       if (callback)
+               mono_profiler_set_gc_event_callback (current->handle, gc_event_cb);
+
+       if (heap_resize_callback)
+               mono_profiler_set_gc_resize_callback (current->handle, gc_resize_cb);
+}
+
+static void
+jit_done_cb (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
+{
+       prof->jit_end2 (prof->profiler, method, jinfo, 0);
+}
+
+static void
+jit_failed_cb (MonoProfiler *prof, MonoMethod *method)
+{
+       prof->jit_end2 (prof->profiler, method, NULL, 1);
+}
+
+void
+mono_profiler_install_jit_end (MonoLegacyProfileJitResult end)
+{
+       current->jit_end2 = end;
+
+       if (end) {
+               mono_profiler_set_jit_done_callback (current->handle, jit_done_cb);
+               mono_profiler_set_jit_failed_callback (current->handle, jit_failed_cb);
+       }
+}
+
+void
+mono_profiler_set_events (int flags)
+{
+       /* Do nothing. */
+}
index 0bbc0fe00612d7200d00f1516d5eb847827ce883..08929a5d23142639a349b3d5c8129a6920cf226b 100644 (file)
@@ -67,7 +67,7 @@ typedef mono_bool (*MonoProfilerCoverageFilterCallback) (MonoProfiler *prof, Mon
  * Sets a code coverage filter function. The profiler API will invoke filter
  * functions from all installed profilers. If any of them return TRUE, then the
  * given method will be instrumented for coverage analysis. All filters are
- * guaranteed to be called exactly once per method, even if an earlier filter
+ * guaranteed to be called at least once per method, even if an earlier filter
  * has already returned TRUE.
  *
  * Note that filter functions must be installed before a method is compiled in
@@ -170,8 +170,12 @@ typedef enum {
        MONO_PROFILER_CALL_INSTRUMENTATION_NONE = 1 << 0,
        /* Instrument method prologues. */
        MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE = 1 << 1,
+       /* Also capture a call context for prologues. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE_CONTEXT = 1 << 2,
        /* Instrument method epilogues. */
-       MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE = 1 << 2,
+       MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE = 1 << 3,
+       /* Also capture a call context for epilogues. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE_CONTEXT = 1 << 4,
 } MonoProfilerCallInstrumentationFlags;
 
 typedef MonoProfilerCallInstrumentationFlags (*MonoProfilerCallInstrumentationFilterCallback) (MonoProfiler *prof, MonoMethod *method);
@@ -181,21 +185,119 @@ typedef MonoProfilerCallInstrumentationFlags (*MonoProfilerCallInstrumentationFi
  * filter functions from all installed profilers. If any of them return flags
  * other than MONO_PROFILER_CALL_INSTRUMENTATION_NONE, then the given method
  * will be instrumented as requested. All filters are guaranteed to be called
- * at least once (possibly more) per method entry and exit, even if earlier
- * filters have already specified all flags.
+ * exactly once per method, even if earlier filters have already specified all
+ * flags.
  *
  * Note that filter functions must be installed before a method is compiled in
  * order to have any effect, i.e. you should register your filter function in
- * your profiler's init function.
+ * your profiler's init function. Also, if you want to instrument a method
+ * that's going to be AOT-compiled, you must attach your profiler and install a
+ * call instrumentation filter function at AOT time. This can be done in
+ * exactly the same way as you would normally, i.e. by passing the --profile
+ * option on the command line, by calling mono_profiler_load, or simply by
+ * using the profiler API as an embedder.
  *
- * Keep in mind that method instrumentation is extremely heavy and will slow
- * down most applications to a crawl. Consider using sampling instead if it
- * would work for your use case.
+ * Keep in mind that indiscriminate method instrumentation is extremely heavy
+ * and will slow down most applications to a crawl. Consider using sampling
+ * instead if it would work for your use case.
  *
  * This function is async safe.
  */
 MONO_API void mono_profiler_set_call_instrumentation_filter_callback (MonoProfilerHandle handle, MonoProfilerCallInstrumentationFilterCallback cb);
 
+/*
+ * Enables support for retrieving stack frame data from a call context. At the
+ * moment, this means enabling the debug info subsystem. If you do not call
+ * this function, you will not be able to use the call context introspection
+ * functions (they will simply return NULL). Returns TRUE if call context
+ * introspection was enabled, or FALSE if the function was called too late for
+ * this to be possible.
+ *
+ * Please note: Mono's LLVM backend does not support this feature. This means
+ * that methods with call context instrumentation will be handled by Mono's
+ * JIT even in LLVM mode. There is also a special case when Mono is compiling
+ * in LLVM-only mode: Since LLVM does not provide a way to implement call
+ * contexts, a NULL context will always be passed to enter/leave events even
+ * though this method returns TRUE.
+ *
+ * This function may only be called from your profiler's init function.
+ *
+ * This function is not async safe.
+ */
+MONO_API mono_bool mono_profiler_enable_call_context_introspection (void);
+
+typedef struct _MonoProfilerCallContext MonoProfilerCallContext;
+
+/*
+ * Given a valid call context from an enter/leave event, retrieves a pointer to
+ * the this reference for the method. Returns NULL if none exists (i.e. it's a
+ * static method) or if call context introspection was not enabled.
+ *
+ * The buffer returned by this function must be freed with
+ * mono_profiler_call_context_free_buffer.
+ *
+ * Please note that a call context is only valid for the duration of the
+ * enter/leave callback it was passed to.
+ *
+ * This function is not async safe.
+ */
+MONO_API void *mono_profiler_call_context_get_this (MonoProfilerCallContext *context);
+
+/*
+ * Given a valid call context from an enter/leave event, retrieves a pointer to
+ * the method argument at the given position. Returns NULL if position is out
+ * of bounds or if call context introspection was not enabled.
+ *
+ * The buffer returned by this function must be freed with
+ * mono_profiler_call_context_free_buffer.
+ *
+ * Please note that a call context is only valid for the duration of the
+ * enter/leave callback it was passed to.
+ *
+ * This function is not async safe.
+ */
+MONO_API void *mono_profiler_call_context_get_argument (MonoProfilerCallContext *context, uint32_t position);
+
+/*
+ * Given a valid call context from an enter/leave event, retrieves a pointer to
+ * the local variable at the given position. Returns NULL if position is out of
+ * bounds or if call context introspection was not enabled.
+ *
+ * The buffer returned by this function must be freed with
+ * mono_profiler_call_context_free_buffer.
+ *
+ * Please note that a call context is only valid for the duration of the
+ * enter/leave callback it was passed to.
+ *
+ * This function is not async safe.
+ */
+MONO_API void *mono_profiler_call_context_get_local (MonoProfilerCallContext *context, uint32_t position);
+
+/*
+ * Given a valid call context from an enter/leave event, retrieves a pointer to
+ * return value of a method. Returns NULL if the method has no return value
+ * (i.e. it returns void), if the leave event was the result of a tail call, if
+ * the function is called on a context from an enter event, or if call context
+ * introspection was not enabled.
+ *
+ * The buffer returned by this function must be freed with
+ * mono_profiler_call_context_free_buffer.
+ *
+ * Please note that a call context is only valid for the duration of the
+ * enter/leave callback it was passed to.
+ *
+ * This function is not async safe.
+ */
+MONO_API void *mono_profiler_call_context_get_result (MonoProfilerCallContext *context);
+
+/*
+ * Frees a buffer returned by one of the call context introspection functions.
+ * Passing a NULL buffer is allowed, which makes this function a no-op.
+ *
+ * This function is not async safe.
+ */
+MONO_API void mono_profiler_call_context_free_buffer (void *buffer);
+
 #ifdef MONO_PROFILER_UNSTABLE_GC_ROOTS
 typedef enum {
        /* Upper 2 bytes. */
index 5e68273c645802bda1d003397f4fc15f0e7f8e28..848f75d3fe1544ed2dedbd459355d7c30a563280 100755 (executable)
@@ -488,7 +488,8 @@ common_sources = \
        type-checking.c \
        lldb.h                  \
        lldb.c  \
-       memory-access.c
+       memory-access.c \
+       mini-profiler.c
 
 test_sources =                         \
        basic-calls.cs          \
index 36c7a15a3e8fe91e1c44ebe8d40cf6546c441994..7f3dafea5c602ab31d1db9590fca9253b7f2a265 100644 (file)
@@ -4,6 +4,7 @@ using System.Linq;
 using System.Reflection;
 using System.Runtime.InteropServices;
 using System.Runtime.CompilerServices;
+using System.Collections;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 
@@ -485,4 +486,16 @@ class Tests
                m.Invoke (arr, null);
                return 0;
        }
+
+       public static int test_0_fault_clauses () {
+               object [] data = { 1, 2, 3 };
+               int [] expected = { 1, 2, 3 };
+
+               try {
+                       Action d = delegate () { data.Cast<IEnumerable> ().GetEnumerator ().MoveNext (); };
+                       d ();
+               } catch (Exception ex) {
+               }
+               return 0;
+       }
 }
index f1dfac557bc157bf11c15acfe64b25f2242c580b..d35a867778fe49e99c74ab07296a3d58d6bc935b 100755 (executable)
@@ -792,3 +792,5 @@ gc_param_slot_liveness_def: len:0
 
 generic_class_init: src1:A len:32 clob:c
 get_last_error: dest:i len:32
+
+fill_prof_call_ctx: src1:i len:128
index 25e5f931118c65462120eb35e4050e4535ad5f88..e6a91fc176d13fc9474efdeb53841cdfb7097ec4 100644 (file)
@@ -404,3 +404,5 @@ atomic_store_r4: dest:b src1:f len:80
 atomic_store_r8: dest:b src1:f len:32
 
 generic_class_init: src1:a len:44 clob:c
+
+fill_prof_call_ctx: src1:i len:128
index c0651233eb50b02114232ec6ebf5e84ce6bcfea0..230a975dbe348bc43711c24276613744530c5e0f 100644 (file)
@@ -480,3 +480,5 @@ atomic_store_r8: dest:b src1:f len:24
 
 generic_class_init: src1:a len:44 clob:c
 gc_safe_point: src1:i len:12 clob:c
+
+fill_prof_call_ctx: src1:i len:128
index 280eda7c0ac58340e2b49a6bc15e289592bbf1b3..870b10b2397506dfdbfb087005e84c8e459018e7 100644 (file)
@@ -651,3 +651,5 @@ gc_spill_slot_liveness_def: len:0
 gc_param_slot_liveness_def: len:0
 get_sp: dest:i len:6
 set_sp: src1:i len:6
+
+fill_prof_call_ctx: src1:i len:128
index 8c1a71e147fe75ddbeaae4af024179139d90d1fd..30874eb3cf3572ab48f24d98b7a058e13ce5b8a0 100644 (file)
@@ -241,7 +241,7 @@ mono_debug_close_method (MonoCompile *cfg)
        jit->code_start = cfg->native_code;
        jit->epilogue_begin = cfg->epilog_begin;
        jit->code_size = cfg->code_len;
-       jit->has_var_info = debug_options.mdb_optimizations != 0;
+       jit->has_var_info = debug_options.mdb_optimizations || MONO_CFG_PROFILE_CALL_CONTEXT (cfg);
 
        if (jit->epilogue_begin)
                   record_line_number (info, jit->epilogue_begin, header->code_size);
index f8287c722d2a462f3f10a99c512813323156895f..f8d485292afd01fb50f4b7e7fc14c08e261704bd 100644 (file)
@@ -2378,6 +2378,12 @@ mono_jit_set_aot_mode (MonoAotMode mode)
        }
 }
 
+mono_bool
+mono_jit_aot_compiling (void)
+{
+       return mono_compile_aot;
+}
+
 /**
  * mono_jit_set_trace_options:
  * \param options string representing the trace options
index e566f535a6eeada977e7abffc27839e953a10125..894747e23d0880ad15f6705c40a2dde3d49d6a84 100644 (file)
@@ -96,6 +96,7 @@ typedef struct _InterpMethod
        MonoType **param_types;
        MonoJitInfo *jinfo;
        MonoDomain *domain;
+       MonoProfilerCallInstrumentationFlags prof_flags;
 } InterpMethod;
 
 struct _InterpFrame {
index e5d50d5aa5e98a0f17b0234f1c03fe5174f08c64..fdbbe262ba4f2bb6d3e0fb1b6617b0a84511abdf 100644 (file)
@@ -173,8 +173,6 @@ debug_enter (InterpFrame *frame, int *tracing)
                g_print  ("%s)\n", args);
                g_free (args);
        }
-       if (mono_profiler_should_instrument_method (frame->imethod->method, TRUE))
-               MONO_PROFILER_RAISE (method_enter, (frame->imethod->method));
 }
 
 
@@ -190,9 +188,7 @@ debug_enter (InterpFrame *frame, int *tracing)
                g_free (args);  \
                debug_indent_level--;   \
                if (tracing == 3) global_tracing = 0; \
-       }       \
-       if (mono_profiler_should_instrument_method (frame->imethod->method, FALSE)) \
-               MONO_PROFILER_RAISE (method_leave, (frame->imethod->method));
+       }
 
 #else
 
@@ -297,6 +293,8 @@ mono_interp_get_imethod (MonoDomain *domain, MonoMethod *method, MonoError *erro
                mono_internal_hash_table_insert (&info->interp_code_hash, method, rtm);
        mono_domain_jit_code_hash_unlock (domain);
 
+       rtm->prof_flags = mono_profiler_get_call_instrumentation_flags (rtm->method);
+
        return rtm;
 }
 
@@ -603,6 +601,7 @@ fill_in_trace (MonoException *exception, InterpFrame *frame)
                if (!rethrow) { \
                        FILL_IN_TRACE(frame->ex, frame);        \
                } \
+               MONO_PROFILER_RAISE (exception_throw, ((MonoObject *) exception));      \
                goto handle_exception;  \
        } while (0)
 
@@ -4764,6 +4763,26 @@ array_constructed:
                        MINT_IN_BREAK;
                }
 
+               MINT_IN_CASE(MINT_PROF_ENTER) {
+                       ip += 1;
+
+                       if (MONO_PROFILER_ENABLED (method_enter)) {
+                               MonoProfilerCallContext *prof_ctx = NULL;
+
+                               if (frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE_CONTEXT) {
+                                       prof_ctx = g_new0 (MonoProfilerCallContext, 1);
+                                       prof_ctx->interp_frame = frame;
+                                       prof_ctx->method = frame->imethod->method;
+                               }
+
+                               MONO_PROFILER_RAISE (method_enter, (frame->imethod->method, prof_ctx));
+
+                               g_free (prof_ctx);
+                       }
+
+                       MINT_IN_BREAK;
+               }
+
                MINT_IN_CASE(MINT_LDARGA)
                        sp->data.p = frame->args + * (guint16 *)(ip + 1);
                        ip += 2;
@@ -5120,6 +5139,37 @@ die_on_ex:
                goto exit_frame;
        }
 exit_frame:
+
+       if (!frame->ex) {
+               if (MONO_PROFILER_ENABLED (method_leave) && frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE) {
+                       MonoProfilerCallContext *prof_ctx = NULL;
+
+                       if (frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE_CONTEXT) {
+                               prof_ctx = g_new0 (MonoProfilerCallContext, 1);
+                               prof_ctx->interp_frame = frame;
+                               prof_ctx->method = frame->imethod->method;
+
+                               MonoType *rtype = mono_method_signature (frame->imethod->method)->ret;
+
+                               switch (rtype->type) {
+                               case MONO_TYPE_VOID:
+                                       break;
+                               case MONO_TYPE_VALUETYPE:
+                                       prof_ctx->return_value = frame->retval->data.p;
+                                       break;
+                               default:
+                                       prof_ctx->return_value = frame->retval;
+                                       break;
+                               }
+                       }
+
+                       MONO_PROFILER_RAISE (method_leave, (frame->imethod->method, prof_ctx));
+
+                       g_free (prof_ctx);
+               }
+       } else
+               MONO_PROFILER_RAISE (method_exception_leave, (frame->imethod->method, (MonoObject *) frame->ex));
+
        DEBUG_LEAVE ();
 }
 
index c270a2b18e47796337c5ce59b4807b4de8c31294..869c5f2df74e1102dce76f33694854b28f18719f 100644 (file)
@@ -526,3 +526,9 @@ OPDEF(MINT_JIT_CALL, "mono_jit_call", 2, MintOpNoArgs)
 OPDEF(MINT_SDB_INTR_LOC, "sdb_intr_loc", 1, MintOpNoArgs)
 OPDEF(MINT_SDB_SEQ_POINT, "sdb_seq_point", 1, MintOpNoArgs)
 OPDEF(MINT_SDB_BREAKPOINT, "sdb_breakpoint", 1, MintOpNoArgs)
+
+/*
+ * This needs to be an opcode because we need to trigger the enter event after
+ * the STINARG* opcodes have executed.
+ */
+OPDEF(MINT_PROF_ENTER, "prof_enter", 1, MintOpNoArgs)
index 1d98608c61ca84c4c12910b02bd66d932228f271..790f8b191d2ea048eeeaf1424f6d45477ea57212 100644 (file)
@@ -1514,6 +1514,9 @@ generate (MonoMethod *method, InterpMethod *rtm, unsigned char *is_bb_start, Mon
                }
        }
 
+       if (rtm->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE)
+               ADD_CODE (td, MINT_PROF_ENTER);
+
        if (sym_seq_points) {
                InterpBasicBlock *cbb = td->offset_to_bb [0];
                g_assert (cbb);
index 302b28b69e2d7393f036a55141ac6de893df55dc..408fead304ef2f95073bbe518c329125f519ea24 100644 (file)
@@ -63,6 +63,13 @@ typedef enum {
 MONO_API void
 mono_jit_set_aot_mode      (MonoAotMode mode);
 
+/*
+ * Returns whether the runtime was invoked for the purpose of AOT-compiling an
+ * assembly, i.e. no managed code will run.
+ */
+MONO_API mono_bool
+mono_jit_aot_compiling (void);
+
 /* Allow embedders to decide wherther to actually obey breakpoint instructions
  * in specific methods (works for both break IL instructions and Debugger.Break ()
  * method calls).
@@ -87,14 +94,6 @@ mono_jit_parse_options     (int argc, char * argv[]);
 
 MONO_API char*       mono_get_runtime_build_info    (void);
 
-/* The following APIs are not stable. Avoid if possible. */
-
-MONO_API MonoJitInfo *
-mono_get_jit_info_from_method (MonoDomain *domain, MonoMethod *method);
-
-MONO_API MONO_RT_EXTERNAL_ONLY void *
-mono_aot_get_method (MonoDomain *domain, MonoMethod *method);
-
 MONO_END_DECLS
 
 #endif
index a74291148e889e440358f663f257094636ad6807..84c019460517374d6282b9245232d5c246680b22 100644 (file)
@@ -1764,24 +1764,6 @@ emit_pop_lmf (MonoCompile *cfg)
        EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_addr_reg, 0, prev_lmf_reg);
 }
 
-static void
-emit_instrumentation_call (MonoCompile *cfg, void *func, gboolean entry)
-{
-       MonoInst *iargs [1];
-
-       /*
-        * Avoid instrumenting inlined methods since it can
-        * distort profiling results.
-        */
-       if (cfg->method != cfg->current_method)
-               return;
-
-       if (mono_profiler_should_instrument_method (cfg->method, entry)) {
-               EMIT_NEW_METHODCONST (cfg, iargs [0], cfg->method);
-               mono_emit_jit_icall (cfg, func, iargs);
-       }
-}
-
 static int
 ret_type_to_call_opcode (MonoCompile *cfg, MonoType *type, int calli, int virt)
 {
@@ -2247,7 +2229,7 @@ mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig,
                tail = FALSE;
 
        if (tail) {
-               emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
+               mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, NULL, NULL);
 
                MONO_INST_NEW_CALL (cfg, call, OP_TAILCALL);
        } else
@@ -4362,6 +4344,9 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        if (g_list_find (cfg->dont_inline, method))
                return FALSE;
 
+       if (mono_profiler_get_call_instrumentation_flags (method))
+               return FALSE;
+
        return TRUE;
 }
 
@@ -8045,7 +8030,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (cfg->gshared && mono_method_check_context_used (cmethod))
                                GENERIC_SHARING_FAILURE (CEE_JMP);
 
-                       emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
+                       mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, NULL, NULL);
 
                        fsig = mono_method_signature (cmethod);
                        n = fsig->param_count + fsig->hasthis;
@@ -8987,7 +8972,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        /* Handle tail calls similarly to normal calls */
                                        tail_call = TRUE;
                                } else {
-                                       emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
+                                       mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, NULL, NULL);
 
                                        MONO_INST_NEW_CALL (cfg, call, OP_JMP);
                                        call->tail_call = TRUE;
@@ -9098,6 +9083,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        break;
                }
                case CEE_RET:
+                       mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, sp - 1, sig->ret);
+
                        if (cfg->method != method) {
                                /* return from inlined method */
                                /* 
@@ -9121,8 +9108,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        cfg->ret_var_set = TRUE;
                                } 
                        } else {
-                               emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
-
                                if (cfg->lmf_var && cfg->cbb->in_count && !cfg->llvm_only)
                                        emit_pop_lmf (cfg);
 
@@ -12650,7 +12635,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        }
 
        cfg->cbb = init_localsbb;
-       emit_instrumentation_call (cfg, mono_profiler_raise_method_enter, TRUE);
+       mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_enter, TRUE, NULL, NULL);
 
        if (seq_points) {
                MonoBasicBlock *bb;
index 5a376b8945017f49fa82fb49d444b81c8b19cc0e..d544ee34445c4d41e7f6bb05ab44c6a254480291 100644 (file)
@@ -6419,6 +6419,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_GET_LAST_ERROR:
                        emit_get_last_error(code, ins->dreg);
                        break;
+               case OP_FILL_PROF_CALL_CTX:
+                       for (int i = 0; i < AMD64_NREG; i++)
+                               if (AMD64_IS_CALLEE_SAVED_REG (i) || i == AMD64_RSP)
+                                       amd64_mov_membase_reg (code, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, gregs) + i * sizeof (mgreg_t), i, sizeof (mgreg_t));
+                       break;
                default:
                        g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
                        g_assert_not_reached ();
index e61e7b00c7123020d41e26f9b156f2e739882bf2..a304dbef08062a83bfc9b907a6840ee00e42cdcb 100644 (file)
@@ -5890,7 +5890,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        arm_patch (buf [0], code);
                        break;
                }
-
+               case OP_FILL_PROF_CALL_CTX:
+                       for (int i = 0; i < ARMREG_MAX; i++)
+                               if ((MONO_ARCH_CALLEE_SAVED_REGS & (1 << i)) || i == ARMREG_SP || i == ARMREG_FP)
+                                       ARM_STR_IMM (code, i, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, regs) + i * sizeof (mgreg_t));
+                       break;
                default:
                        g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
                        g_assert_not_reached ();
index aacdd599afcd8003aecb9cba419b6ec55a977172..46fb083b2823efaf6034aa894bf141418bb2b31d 100644 (file)
@@ -4329,7 +4329,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 #endif
                        break;
                }
-
+               case OP_FILL_PROF_CALL_CTX:
+                       for (int i = 0; i < MONO_MAX_IREGS; i++)
+                               if ((MONO_ARCH_CALLEE_SAVED_REGS & (1 << i)) || i == ARMREG_SP || i == ARMREG_FP)
+                                       arm_strx (code, i, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, regs) + i * sizeof (mgreg_t));
+                       break;
                default:
                        g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
                        g_assert_not_reached ();
index c8a71c69378dac317a72716a0aa8cccb1182bc29..348bc3948c5a30575db3dc0836e9b501c5a12380 100644 (file)
@@ -2186,8 +2186,6 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                        jit_tls->orig_ex_ctx_set = TRUE;
                                        MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
                                        jit_tls->orig_ex_ctx_set = FALSE;
-                                       mini_set_abort_threshold (ctx);
-                                       call_filter (ctx, ei->handler_start);
                                }
                                if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
                                        if (mono_trace_is_enabled () && mono_trace_eval (method))
@@ -2198,6 +2196,8 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
 #ifndef DISABLE_PERFCOUNTERS
                                        mono_perfcounters->exceptions_finallys++;
 #endif
+                               }
+                               if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
                                        mono_set_lmf (lmf);
                                        if (ji->from_llvm) {
                                                /* 
index ae9165e1174792376a3a602cdc75ba758692f012..29d8cb09fb77e0b2d84586309f48dc85243afc26 100644 (file)
@@ -1305,3 +1305,10 @@ MINI_OP(OP_GET_SP, "get_sp", IREG, NONE, NONE)
 MINI_OP(OP_SET_SP, "set_sp", NONE, IREG, NONE)
 
 MINI_OP(OP_GET_LAST_ERROR, "get_last_error", IREG, NONE, NONE)
+
+/*
+ * Fill out a MonoContext contained in a MonoProfilerCallContext. This only
+ * stores the stack pointer, frame pointer, and callee-saved registers. This
+ * should be enough to locate arguments and variables.
+ */
+MINI_OP(OP_FILL_PROF_CALL_CTX, "fill_prof_call_ctx", NONE, IREG, NONE)
diff --git a/mono/mini/mini-profiler.c b/mono/mini/mini-profiler.c
new file mode 100644 (file)
index 0000000..3b6149d
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Licensed to the .NET Foundation under one or more agreements.
+ * The .NET Foundation licenses this file to you under the MIT license.
+ * See the LICENSE file in the project root for more information.
+ */
+
+#include <mono/metadata/abi-details.h>
+#include <mono/metadata/mono-debug.h>
+
+#include "interp/interp.h"
+#include "ir-emit.h"
+#include "mini.h"
+
+void
+mini_profiler_emit_instrumentation_call (MonoCompile *cfg, void *func, gboolean entry, MonoInst **ret, MonoType *rtype)
+{
+       gboolean instrument, capture;
+
+       if (entry) {
+               instrument = cfg->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE;
+               capture = cfg->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE_CONTEXT;
+       } else {
+               instrument = cfg->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
+               capture = cfg->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE_CONTEXT;
+       }
+
+       if (!instrument)
+               return;
+
+       g_assert (cfg->current_method == cfg->method);
+
+       MonoInst *iargs [2];
+
+       EMIT_NEW_METHODCONST (cfg, iargs [0], cfg->method);
+
+       if (capture && !cfg->llvm_only) {
+               cfg->flags |= MONO_CFG_HAS_ALLOCA;
+
+               MonoInst *size, *fill_ctx;
+
+               EMIT_NEW_ICONST (cfg, size, sizeof (MonoProfilerCallContext));
+               MONO_INST_NEW (cfg, iargs [1], OP_LOCALLOC);
+               iargs [1]->dreg = alloc_preg (cfg);
+               iargs [1]->sreg1 = size->dreg;
+               iargs [1]->flags |= MONO_INST_INIT;
+               MONO_ADD_INS (cfg->cbb, iargs [1]);
+               MONO_INST_NEW (cfg, fill_ctx, OP_FILL_PROF_CALL_CTX);
+               fill_ctx->sreg1 = iargs [1]->dreg;
+               MONO_ADD_INS (cfg->cbb, fill_ctx);
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, iargs [1]->dreg, MONO_STRUCT_OFFSET (MonoProfilerCallContext, method), iargs [0]->dreg);
+
+               if (rtype && rtype->type != MONO_TYPE_VOID) {
+                       MonoInst *var = mono_compile_create_var (cfg, rtype, OP_LOCAL);
+
+                       MonoInst *store, *addr;
+
+                       EMIT_NEW_TEMPSTORE (cfg, store, var->inst_c0, *ret);
+                       EMIT_NEW_VARLOADA (cfg, addr, var, NULL);
+                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, iargs [1]->dreg, MONO_STRUCT_OFFSET (MonoProfilerCallContext, return_value), addr->dreg);
+               }
+       } else
+               EMIT_NEW_PCONST (cfg, iargs [1], NULL);
+
+       mono_emit_jit_icall (cfg, func, iargs);
+}
+
+void
+mini_profiler_context_enable (void)
+{
+       if (!mono_debug_enabled ())
+               mono_debug_init (MONO_DEBUG_FORMAT_MONO);
+}
+
+static gpointer
+memdup_with_type (gpointer data, MonoType *t)
+{
+       int dummy;
+
+       return g_memdup (data, mono_type_size (t, &dummy));
+}
+
+static guint8 *
+get_int_reg (MonoContext *ctx, guint32 reg)
+{
+       return (guint8 *) mono_arch_context_get_int_reg (ctx, reg);
+}
+
+static gpointer
+get_variable_buffer (MonoDebugMethodJitInfo *jit, MonoDebugVarInfo *var, MonoContext *ctx)
+{
+       guint32 flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+       guint32 reg = var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+
+       switch (flags) {
+       case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER: {
+               /*
+                * This is kind of a special case: All other address modes ultimately
+                * produce an address to where the actual value is located, but this
+                * address mode gets us the value itself as an mgreg_t value.
+                */
+               mgreg_t value = (mgreg_t) get_int_reg (ctx, reg);
+
+               return memdup_with_type (&value, var->type);
+       }
+       case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
+               return memdup_with_type (get_int_reg (ctx, reg) + (gint32) var->offset, var->type);
+       case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR:
+       case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR:
+               return memdup_with_type (*(guint8 **) (get_int_reg (ctx, reg) + (gint32) var->offset), var->type);
+       case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL: {
+               guint32 idx = reg;
+
+               MonoDebugVarInfo *info_var = jit->gsharedvt_info_var;
+
+               flags = info_var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+               reg = info_var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+
+               MonoGSharedVtMethodRuntimeInfo *info;
+
+               switch (flags) {
+               case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
+                       info = (MonoGSharedVtMethodRuntimeInfo *) get_int_reg (ctx, reg);
+                       break;
+               case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
+                       info = *(MonoGSharedVtMethodRuntimeInfo **) (get_int_reg (ctx, reg) + (gint32) info_var->offset);
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+
+               MonoDebugVarInfo *locals_var = jit->gsharedvt_locals_var;
+
+               flags = locals_var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+               reg = locals_var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+
+               guint8 *locals;
+
+               switch (flags) {
+               case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
+                       locals = get_int_reg (ctx, reg);
+                       break;
+               case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
+                       locals = *(guint8 **) (get_int_reg (ctx, reg) + (gint32) info_var->offset);
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+
+               return memdup_with_type (locals + (gsize) info->entries [idx], var->type);
+       }
+       default:
+               g_assert_not_reached ();
+               return NULL;
+       }
+}
+
+gpointer
+mini_profiler_context_get_this (MonoProfilerCallContext *ctx)
+{
+       if (!mono_method_signature (ctx->method)->hasthis)
+               return NULL;
+
+       if (ctx->interp_frame)
+               return memdup_with_type (mono_interp_frame_get_this (ctx->interp_frame), &ctx->method->klass->this_arg);
+
+       MonoDebugMethodJitInfo *info = mono_debug_find_method (ctx->method, mono_domain_get ());
+
+       if (!info)
+               return NULL;
+
+       return get_variable_buffer (info, info->this_var, &ctx->context);
+}
+
+gpointer
+mini_profiler_context_get_argument (MonoProfilerCallContext *ctx, guint32 pos)
+{
+       MonoMethodSignature *sig = mono_method_signature (ctx->method);
+
+       if (pos >= sig->param_count)
+               return NULL;
+
+       if (ctx->interp_frame)
+               return memdup_with_type (mono_interp_frame_get_arg (ctx->interp_frame, pos), sig->params [pos]);
+
+       MonoDebugMethodJitInfo *info = mono_debug_find_method (ctx->method, mono_domain_get ());
+
+       if (!info)
+               return NULL;
+
+       return get_variable_buffer (info, &info->params [pos], &ctx->context);
+}
+
+gpointer
+mini_profiler_context_get_local (MonoProfilerCallContext *ctx, guint32 pos)
+{
+       MonoError error;
+       MonoMethodHeader *header = mono_method_get_header_checked (ctx->method, &error);
+       mono_error_assert_ok (&error); // Must be a valid method at this point.
+
+       if (pos >= header->num_locals) {
+               mono_metadata_free_mh (header);
+               return NULL;
+       }
+
+       MonoType *t = header->locals [pos];
+
+       mono_metadata_free_mh (header);
+
+       if (ctx->interp_frame)
+               return memdup_with_type (mono_interp_frame_get_local (ctx->interp_frame, pos), t);
+
+       MonoDebugMethodJitInfo *info = mono_debug_find_method (ctx->method, mono_domain_get ());
+
+       if (!info)
+               return NULL;
+
+       return get_variable_buffer (info, &info->locals [pos], &ctx->context);
+}
+
+gpointer
+mini_profiler_context_get_result (MonoProfilerCallContext *ctx)
+{
+       if (!ctx->return_value)
+               return NULL;
+
+       return memdup_with_type (ctx->return_value, mono_method_signature (ctx->method)->ret);
+}
+
+void
+mini_profiler_context_free_buffer (void *buffer)
+{
+       g_free (buffer);
+}
index 7c22cc941575da3682a32aa27975058995aefc6f..af88efa4abd17461d5d55f6a8530c57bd737542f 100644 (file)
@@ -3938,6 +3938,13 @@ mini_init (const char *filename, const char *runtime_version)
        mono_install_get_class_from_name (mono_aot_get_class_from_name);
        mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
 
+       mono_profiler_state.context_enable = mini_profiler_context_enable;
+       mono_profiler_state.context_get_this = mini_profiler_context_get_this;
+       mono_profiler_state.context_get_argument = mini_profiler_context_get_argument;
+       mono_profiler_state.context_get_local = mini_profiler_context_get_local;
+       mono_profiler_state.context_get_result = mini_profiler_context_get_result;
+       mono_profiler_state.context_free_buffer = mini_profiler_context_free_buffer;
+
        if (profile_options)
                for (guint i = 0; i < profile_options->len; i++)
                        mono_profiler_load ((const char *) g_ptr_array_index (profile_options, i));
@@ -4056,8 +4063,8 @@ register_icalls (void)
         * the wrapper would call the icall which would call the wrapper and
         * so on.
         */
-       register_icall (mono_profiler_raise_method_enter, "mono_profiler_raise_method_enter", "void ptr", TRUE);
-       register_icall (mono_profiler_raise_method_leave, "mono_profiler_raise_method_leave", "void ptr", TRUE);
+       register_icall (mono_profiler_raise_method_enter, "mono_profiler_raise_method_enter", "void ptr ptr", TRUE);
+       register_icall (mono_profiler_raise_method_leave, "mono_profiler_raise_method_leave", "void ptr ptr", TRUE);
 
        register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
        register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
index 54966b1dc8f39bbbafc7fe04dcfe581c4781e90d..a3e893a1e2b79a4d8ca8f10dd559b9a592b64ba3 100644 (file)
@@ -4927,6 +4927,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_SET_SP:
                        x86_mov_reg_reg (code, X86_ESP, ins->sreg1, sizeof (mgreg_t));
                        break;
+               case OP_FILL_PROF_CALL_CTX:
+                       x86_mov_membase_reg (code, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, esp), X86_ESP, sizeof (mgreg_t));
+                       x86_mov_membase_reg (code, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, ebp), X86_EBP, sizeof (mgreg_t));
+                       x86_mov_membase_reg (code, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, ebx), X86_EBX, sizeof (mgreg_t));
+                       x86_mov_membase_reg (code, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, esi), X86_ESI, sizeof (mgreg_t));
+                       x86_mov_membase_reg (code, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, edi), X86_EDI, sizeof (mgreg_t));
+                       break;
                default:
                        g_warning ("unknown opcode %s\n", mono_inst_name (ins->opcode));
                        g_assert_not_reached ();
index 5374f9a3653704f39cb982c8ea524013044de012..5e6e718486f8b7c29b519017b2acf237b41b8e58 100644 (file)
@@ -3294,8 +3294,10 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        }
 #endif
 
+       cfg->prof_flags = mono_profiler_get_call_instrumentation_flags (cfg->method);
+
        /* The debugger has no liveness information, so avoid sharing registers/stack slots */
-       if (debug_options.mdb_optimizations) {
+       if (debug_options.mdb_optimizations || MONO_CFG_PROFILE_CALL_CONTEXT (cfg)) {
                cfg->disable_reuse_registers = TRUE;
                cfg->disable_reuse_stack_slots = TRUE;
                /* 
index a8bd6f70221f2d606c6589a2756eda6430432ec6..7d681122d43c3b3aa212a18cc74e77f265966a02 100644 (file)
@@ -1916,8 +1916,13 @@ typedef struct {
        int stat_inlineable_methods;
        int stat_inlined_methods;
        int stat_code_reallocs;
+
+       MonoProfilerCallInstrumentationFlags prof_flags;
 } MonoCompile;
 
+#define MONO_CFG_PROFILE_CALL_CONTEXT(cfg) \
+       ((cfg)->prof_flags & (MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE_CONTEXT | MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE_CONTEXT))
+
 typedef enum {
        MONO_CFG_HAS_ALLOCA = 1 << 0,
        MONO_CFG_HAS_CALLS  = 1 << 1,
@@ -2353,6 +2358,13 @@ void        mini_cleanup                   (MonoDomain *domain);
 MONO_API MonoDebugOptions *mini_get_debug_options   (void);
 MONO_API gboolean    mini_parse_debug_option (const char *option);
 void        mini_add_profiler_argument (const char *desc);
+void        mini_profiler_emit_instrumentation_call (MonoCompile *cfg, void *func, gboolean entry, MonoInst **ret, MonoType *rtype);
+void        mini_profiler_context_enable (void);
+gpointer    mini_profiler_context_get_this (MonoProfilerCallContext *ctx);
+gpointer    mini_profiler_context_get_argument (MonoProfilerCallContext *ctx, guint32 pos);
+gpointer    mini_profiler_context_get_local (MonoProfilerCallContext *ctx, guint32 pos);
+gpointer    mini_profiler_context_get_result (MonoProfilerCallContext *ctx);
+void        mini_profiler_context_free_buffer (gpointer buffer);
 
 /* graph dumping */
 void mono_cfg_dump_create_context (MonoCompile *cfg);
index ed7a21226593e44c5ad4137d27df819c8b10f031..90f7309884796a55ac57dfb19aa89a76a192bffd 100644 (file)
@@ -1760,7 +1760,7 @@ class_loaded (MonoProfiler *prof, MonoClass *klass)
 }
 
 static void
-method_enter (MonoProfiler *prof, MonoMethod *method)
+method_enter (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *ctx)
 {
        if (get_thread ()->call_depth++ <= log_config.max_call_depth) {
                ENTER_LOG (&method_entries_ctr, logbuffer,
@@ -1776,7 +1776,7 @@ method_enter (MonoProfiler *prof, MonoMethod *method)
 }
 
 static void
-method_leave (MonoProfiler *prof, MonoMethod *method)
+method_leave (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *ctx)
 {
        if (--get_thread ()->call_depth <= log_config.max_call_depth) {
                ENTER_LOG (&method_exits_ctr, logbuffer,
index 70dc4b0554c6eb8d780d1a2c8dcd7feb348ab91a..b23daec250520a61e23c30e04a16991f9cb7426b 100644 (file)
     <ClCompile Include="..\mono\mini\type-checking.c" />\r
     <ClCompile Include="..\mono\mini\lldb.c" />\r
     <ClCompile Include="..\mono\mini\interp\interp-stubs.c" />\r
+    <ClCompile Include="..\mono\mini\mini-profiler.c" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{CB0D9E92-293C-439C-9AC7-C5F59B6E0772}</ProjectGuid>\r
index 029b9d162c15144f2740162e2726bb56fb2572ac..672e6052f41a69606d0d2f407964fa33ee1a5dd1 100644 (file)
     <ClCompile Include="..\mono\mini\interp\interp-stubs.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\mono\mini\mini-profiler.c">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="..\mono\mini\abcremoval.h">\r
index a5dcc676a18464f773cdbdf0910a7009c1ed4d68..d2e5ad512cd78a353af0e1e05eb4308b9bd287b6 100644 (file)
@@ -82,7 +82,6 @@
     <ClCompile Include="..\mono\metadata\number-ms.c" />\r
     <ClCompile Include="..\mono\metadata\object.c" />\r
     <ClCompile Include="..\mono\metadata\opcodes.c" />\r
-    <ClCompile Include="..\mono\metadata\profiler-legacy.c" />\r
     <ClCompile Include="..\mono\metadata\profiler.c" />\r
     <ClCompile Include="..\mono\metadata\rand.c" />\r
     <ClCompile Include="..\mono\metadata\reflection.c" />\r
index 1655d562e23610215c7d9f051e0bb5e99db3b582..554e61985bdb1745ac9df6d44d0c7d1423bdd6f3 100644 (file)
     <ClCompile Include="..\mono\metadata\w32process-win32.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\mono\metadata\profiler-legacy.c">\r
-      <Filter>Source Files</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\mono\metadata\profiler.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
index 884457efa69cda149667fdb60977632946687a3f..acf9e59d1b4bf8c64de4aec4425b8817984a5076 100644 (file)
@@ -704,8 +704,14 @@ mono_print_method_from_ip
 mono_print_thread_dump
 mono_print_thread_dump_from_ctx
 mono_print_unhandled_exception
+mono_profiler_call_context_free_buffer
+mono_profiler_call_context_get_argument
+mono_profiler_call_context_get_local
+mono_profiler_call_context_get_result
+mono_profiler_call_context_get_this
 mono_profiler_create
 mono_profiler_enable_allocations
+mono_profiler_enable_call_context_introspection
 mono_profiler_enable_sampling
 mono_profiler_get_coverage_data
 mono_profiler_get_sample_mode
index 64c8c16f7b3ae7d6fb4565578e1fca8ca6c259f7..513e2eda72ede1b1ecfbce1ade7d77bd7f090909 100644 (file)
@@ -706,8 +706,14 @@ mono_print_method_from_ip
 mono_print_thread_dump
 mono_print_thread_dump_from_ctx
 mono_print_unhandled_exception
+mono_profiler_call_context_free_buffer
+mono_profiler_call_context_get_argument
+mono_profiler_call_context_get_local
+mono_profiler_call_context_get_result
+mono_profiler_call_context_get_this
 mono_profiler_create
 mono_profiler_enable_allocations
+mono_profiler_enable_call_context_introspection
 mono_profiler_enable_sampling
 mono_profiler_get_coverage_data
 mono_profiler_get_sample_mode
index 1529f2cf391800ea750bc0543531f4b4dca5c0d1..acf299859ccb556f50df7eb0ffa50e5d3b3beadc 100755 (executable)
@@ -5,6 +5,7 @@ if [[ ${label} == w* ]]
 then ${TESTCMD} --label=aot-test --skip;
 else ${TESTCMD} --label=aot-test --timeout=30m make -w -C mono/tests -j4 -k test-aot
 fi
+${TESTCMD} --label=compile-bcl-tests --timeout=40m make -i -w -C runtime -j4 test
 ${TESTCMD} --label=compile-runtime-tests --timeout=40m make -w -C mono/tests -j4 tests
 ${TESTCMD} --label=runtime --timeout=160m make -w -C mono/tests -k test-wrench V=1 CI=1 CI_PR=${ghprbPullId}
 ${TESTCMD} --label=runtime-unit-tests --timeout=5m make -w -C mono/unit-tests -k check