Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelsavara committed Oct 25, 2022
1 parent c4341d4 commit 1df3637
Show file tree
Hide file tree
Showing 27 changed files with 535 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@
<PlatformManifestFileEntry Include="libmono-icall-table.a" IsNative="true" />
<PlatformManifestFileEntry Include="libmono-ilgen.a" IsNative="true" />
<PlatformManifestFileEntry Include="libmono-profiler-aot.a" IsNative="true" />
<PlatformManifestFileEntry Include="libmono-profiler-browser.a" IsNative="true" />
<PlatformManifestFileEntry Include="libmono-wasm-eh-js.a" IsNative="true" />
<PlatformManifestFileEntry Include="libmono-wasm-eh-wasm.a" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.js" IsNative="true" />
Expand Down
3 changes: 3 additions & 0 deletions src/mono/mono.proj
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,9 @@
<_MonoRuntimeArtifacts Condition="'$(TargetsBrowser)' == 'true' and '$(BuildMonoAOTCrossCompilerOnly)' != 'true'" Include="$(MonoObjDir)out\lib\libmono-profiler-aot.a">
<Destination>$(RuntimeBinDir)libmono-profiler-aot.a</Destination>
</_MonoRuntimeArtifacts>
<_MonoRuntimeArtifacts Condition="'$(TargetsBrowser)' == 'true' and '$(BuildMonoAOTCrossCompilerOnly)' != 'true'" Include="$(MonoObjDir)out\lib\libmono-profiler-browser.a">
<Destination>$(RuntimeBinDir)libmono-profiler-browser.a</Destination>
</_MonoRuntimeArtifacts>
<_MonoRuntimeArtifacts Condition="'$(TargetsBrowser)' == 'true' and '$(BuildMonoAOTCrossCompilerOnly)' != 'true'" Include="$(MonoObjDir)out\lib\libmono-wasm-eh-js.a">
<Destination>$(RuntimeBinDir)libmono-wasm-eh-js.a</Destination>
</_MonoRuntimeArtifacts>
Expand Down
12 changes: 12 additions & 0 deletions src/mono/mono/metadata/profiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ typedef void (*MonoProfilerInitializer) (const char *);
#define OLD_INITIALIZER_NAME "mono_profiler_startup"
#define NEW_INITIALIZER_NAME "mono_profiler_init"

#if defined(TARGET_WASM) && defined(MONO_CROSS_COMPILE)
MONO_API void mono_profiler_init_browser (const char *desc);
#endif

static gboolean
load_profiler (MonoDl *module, const char *name, const char *desc)
{
Expand Down Expand Up @@ -171,6 +175,14 @@ mono_profiler_load (const char *desc)
mname = g_strdup (desc);
}

#if defined(TARGET_WASM) && defined(MONO_CROSS_COMPILE)
printf ("mono_profiler_load %s\n", mname);
if(strcmp (mname, "browser") == 0){
mono_profiler_init_browser (desc);
goto done;
}
#endif

if (load_profiler_from_executable (mname, desc))
goto done;

Expand Down
8 changes: 7 additions & 1 deletion src/mono/mono/mini/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,13 @@ else()
set(llvm_runtime_sources)
endif()

set(mini_sources "main-core.c;${mini_common_sources};${arch_sources};${os_sources};${mini_interp_sources};${llvm_sources};${debugger_sources};${llvm_runtime_sources}")
if(TARGET_WASM AND MONO_CROSS_COMPILE)
set(profiler_sources ../profiler/browser.c)
else()
set(profiler_sources "")
endif()

set(mini_sources "main-core.c;${mini_common_sources};${arch_sources};${os_sources};${mini_interp_sources};${llvm_sources};${debugger_sources};${profiler_sources};${llvm_runtime_sources}")

if(LLVM_INCLUDEDIR)
include_directories(BEFORE SYSTEM "${LLVM_INCLUDEDIR}")
Expand Down
7 changes: 7 additions & 0 deletions src/mono/mono/profiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,11 @@ if(NOT DISABLE_LIBS)
set_target_properties(mono-profiler-aot-static PROPERTIES OUTPUT_NAME mono-profiler-aot)
install(TARGETS mono-profiler-aot-static LIBRARY)
endif()

if(HOST_WASM)
add_library(mono-profiler-browser-static STATIC browser.c)
target_link_libraries(mono-profiler-browser-static monoapi)
set_target_properties(mono-profiler-browser-static PROPERTIES OUTPUT_NAME mono-profiler-browser)
install(TARGETS mono-profiler-browser-static LIBRARY)
endif()
endif()
246 changes: 246 additions & 0 deletions src/mono/mono/profiler/browser.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
/*
* browser.c: Exporting profiler events to browser dev tools.
* Copyright 2022 Microsoft Corporation
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/

#include <config.h>

#include "browser.h"
#include "helper.h"

#include <mono/metadata/profiler.h>
#include <mono/utils/mono-logger-internals.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <glib.h>

#include <mono/metadata/object-internals.h>
#include <mono/metadata/tokentype.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/class-internals.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/utils/mono-publib.h>
#include <mono/jit/jit.h>
/*
#include <mono/utils/mono-os-mutex.h>
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-proclib.h>
*/

#ifdef TARGET_WASM


struct _MonoProfiler {
/* TODO config
int max_call_depth;
gboolean disable;
*/
int duration;
gboolean verbose;
};

static MonoProfiler browser_profiler;

static gboolean
match_option (const char *arg, const char *opt_name, const char **rval)
{
if (rval) {
const char *end = strchr (arg, '=');

*rval = NULL;
if (!end)
return !strcmp (arg, opt_name);

if (strncmp (arg, opt_name, strlen (opt_name)) || (end - arg) > GSIZE_TO_SSIZE(strlen (opt_name)) + 1)
return FALSE;
*rval = end + 1;
return TRUE;
} else {
//FIXME how should we handle passing a value to an arg that doesn't expect it?
return !strcmp (arg, opt_name);
}
}

static void
parse_arg (const char *arg)
{
const char *val;

if (match_option (arg, "duration", &val)) {
char *end;
browser_profiler.duration = strtoul (val, &end, 10);
} else if (match_option (arg, "verbose", NULL)) {
browser_profiler.verbose = TRUE;
} else {
mono_profiler_printf_err ("Could not parse argument: %s", arg);
}
}

static void
parse_args (const char *desc)
{
const char *p;
gboolean in_quotes = FALSE;
char quote_char = '\0';
char *buffer = g_malloc (strlen (desc) + 1);
int buffer_pos = 0;

for (p = desc; *p; p++){
switch (*p){
case ',':
if (!in_quotes) {
if (buffer_pos != 0){
buffer [buffer_pos] = 0;
parse_arg (buffer);
buffer_pos = 0;
}
} else {
buffer [buffer_pos++] = *p;
}
break;

case '\\':
if (p [1]) {
buffer [buffer_pos++] = p[1];
p++;
}
break;
case '\'':
case '"':
if (in_quotes) {
if (quote_char == *p)
in_quotes = FALSE;
else
buffer [buffer_pos++] = *p;
} else {
in_quotes = TRUE;
quote_char = *p;
}
break;
default:
buffer [buffer_pos++] = *p;
break;
}
}

if (buffer_pos != 0) {
buffer [buffer_pos] = 0;
parse_arg (buffer);
}

g_free (buffer);
}

#ifdef HOST_WASM

static void
runtime_initialized (MonoProfiler *profiler)
{
mono_profiler_printf ("runtime_initialized");
}

static void
prof_jit_done (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
{
mono_profiler_printf ("prof_jit_done %s", mono_method_full_name (method, 1));
}

static void
prof_inline_method (MonoProfiler *prof, MonoMethod *method, MonoMethod *inlined_method)
{
prof_jit_done (prof, inlined_method, NULL);
}

static void
method_enter (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *ctx)
{
mono_wasm_profiler_enter ();
//mono_profiler_printf ("method_enter %s", mono_method_full_name (method, 1));
}

static void
method_leave (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *ctx)
{
mono_wasm_profiler_leave (method);
// mono_profiler_printf ("method_leave %s", mono_method_full_name (method, 1));
}

static void
tail_call (MonoProfiler *prof, MonoMethod *method, MonoMethod *target)
{
method_leave (prof, method, NULL);
}

static void
method_exc_leave (MonoProfiler *prof, MonoMethod *method, MonoObject *exc)
{
method_leave (prof, method, NULL);
}

#endif /* HOST_WASM */

static MonoProfilerCallInstrumentationFlags
method_filter (MonoProfiler *prof, MonoMethod *method)
{
// TODO filter by namespace ?
mono_profiler_printf_err ("method_filter");

return MONO_PROFILER_CALL_INSTRUMENTATION_ENTER |
MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE |
MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL |
MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE;
}


MONO_API void
mono_profiler_init_browser (const char *desc);

/**
* mono_profiler_init_browser:
* the entry point
*/
void
mono_profiler_init_browser (const char *desc)
{
browser_profiler.duration = -1;

parse_args (desc [strlen ("browser")] == ':' ? desc + strlen ("browser") + 1 : "");

MonoProfilerHandle handle = mono_profiler_create (&browser_profiler);

mono_profiler_set_call_instrumentation_filter_callback (handle, method_filter);

if (mono_jit_aot_compiling ()) {
return;
}

#ifdef HOST_WASM
mono_profiler_set_runtime_initialized_callback (handle, runtime_initialized);
mono_profiler_set_jit_done_callback (handle, prof_jit_done);
mono_profiler_set_inline_method_callback (handle, prof_inline_method);
mono_profiler_set_method_enter_callback (handle, method_enter);
mono_profiler_set_method_leave_callback (handle, method_leave);
mono_profiler_set_method_tail_call_callback (handle, tail_call);
mono_profiler_set_method_exception_leave_callback (handle, method_exc_leave);

// TODO
// MONO_PROFILER_RAISE (assembly_loading, (ass));
// MONO_PROFILER_RAISE (assembly_loaded, (ass));

// MONO_PROFILER_RAISE (class_loading, (klass));
// MONO_PROFILER_RAISE (class_failed, (klass));
// MONO_PROFILER_RAISE (class_failed, (klass));

// MONO_PROFILER_RAISE (gc_finalizing, ());
// MONO_PROFILER_RAISE (gc_finalized, ());

// MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_END
#endif /* HOST_WASM */
}

#endif /* TARGET_WASM */
17 changes: 17 additions & 0 deletions src/mono/mono/profiler/browser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef __MONO_PROFILER_BROWSER_H__
#define __MONO_PROFILER_BROWSER_H__

#include <config.h>
#include <glib.h>
#include <mono/metadata/profiler.h>

#ifdef HOST_WASM

void
mono_wasm_profiler_enter ();

void
mono_wasm_profiler_leave (MonoMethod *method);

#endif /* HOST_WASM */
#endif /* __MONO_PROFILER_BROWSER_H__ */
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<EmccExtraLDFlags> -s USE_CLOSURE_COMPILER=1 -s LEGACY_GL_EMULATION=1 -lGL -lSDL -lidbfs.js</EmccExtraLDFlags>
<!-- just to prove we don't do JS eval() -->
<_ServeHeaders>$(_ServeHeaders) -h &quot;Content-Security-Policy: default-src 'self' 'wasm-unsafe-eval'&quot;</_ServeHeaders>
<!-- enable reporting to profiler in browser dev tools -->
<WasmProfilers>browser;</WasmProfilers>
</PropertyGroup>
<ItemGroup>
<!-- add export GL object from Module -->
Expand Down
3 changes: 2 additions & 1 deletion src/mono/sample/wasm/browser-advanced/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ try {
// This is called during emscripten `dotnet.wasm` instantiation, after we fetched config.
console.log('user code Module.onConfigLoaded');
// config is loaded and could be tweaked before the rest of the runtime startup sequence
config.environmentVariables["MONO_LOG_LEVEL"] = "debug"
config.environmentVariables["MONO_LOG_LEVEL"] = "debug";
config.browserProfilerOptions = {};
},
preInit: () => { console.log('user code Module.preInit'); },
preRun: () => { console.log('user code Module.preRun'); },
Expand Down
2 changes: 1 addition & 1 deletion src/mono/sample/wasm/browser-profile/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ TOP=../../../../..
include ../wasm.mk

PROJECT_NAME=Wasm.BrowserProfile.Sample.csproj
BUILD_ARGS=/p:WasmBuildNative=true /p:EnableProfiler=true
BUILD_ARGS=/p:WasmBuildNative=true
BUILD_PROFILED_ARGS=/p:RunAOTCompilation=true /p:AOTProfilePath=$(PROFILE_PATH)

run: run-browser
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
<WasmMainJSPath>main.js</WasmMainJSPath>
<WasmProfilers>aot;</WasmProfilers>
<WasmBuildNative>true</WasmBuildNative>
<WasmNativeStrip>false</WasmNativeStrip>
</PropertyGroup>

<ItemGroup>
<WasmExtraConfig Include="enableProfiler" Value="true" />
<WasmExtraFilesToDeploy Include="index.html" />
</ItemGroup>

Expand Down
3 changes: 3 additions & 0 deletions src/mono/wasm/build/WasmApp.Native.targets
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@
<_EmccCFlags Include="-DINVARIANT_GLOBALIZATION=1" Condition="'$(InvariantGlobalization)' == 'true'" />
<_EmccCFlags Include="-DLINK_ICALLS=1" Condition="'$(WasmLinkIcalls)' == 'true'" />
<_EmccCFlags Include="-DENABLE_AOT_PROFILER=1" Condition="$(WasmProfilers.Contains('aot'))" />
<_EmccCFlags Include="-DENABLE_BROWSER_PROFILER=1" Condition="$(WasmProfilers.Contains('browser'))" />
<_EmccCFlags Include="-DENABLE_COVERAGE_PROFILER=1" Condition="$(WasmProfilers.Contains('coverage'))" />
<_EmccCFlags Include="-DCORE_BINDINGS" />
<_EmccCFlags Include="-DGEN_PINVOKE=1" />
<_EmccCFlags Include="-emit-llvm" />
Expand Down Expand Up @@ -598,6 +600,7 @@
AOTProfilePath="$(AOTProfilePath)"
AotModulesTablePath="$(_DriverGenCPath)"
UseLLVM="true"
Profilers="$(WasmProfilers)"
DisableParallelAot="$(DisableParallelAot)"
DedupAssembly="$(_WasmDedupAssembly)"
CacheFilePath="$(_AOTCompilerCacheFile)"
Expand Down
Loading

0 comments on commit 1df3637

Please sign in to comment.