LCOV - code coverage report
Current view: top level - js/src/vtune - VTuneWrapper.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 21 86 24.4 %
Date: 2017-07-14 16:53:18 Functions: 6 11 54.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "vtune/VTuneWrapper.h"
       8             : 
       9             : #include "mozilla/Sprintf.h"
      10             : 
      11             : #include "jscntxt.h"
      12             : #include "jscompartment.h"
      13             : #include "jsgc.h"
      14             : 
      15             : #include "threading/LockGuard.h"
      16             : #include "threading/Mutex.h"
      17             : #include "vm/MutexIDs.h"
      18             : #include "vm/Shape.h"
      19             : 
      20             : #ifdef MOZ_VTUNE
      21             : 
      22             : namespace js {
      23             : namespace vtune {
      24             : 
      25             : // VTune internals are not known to be threadsafe.
      26             : static Mutex* VTuneMutex = nullptr;
      27             : 
      28             : // Firefox must be launched from within VTune. Then the profiler
      29             : // status never changes, and we can avoid shared library checks.
      30             : static bool VTuneLoaded(false);
      31             : 
      32             : // Initialization is called from a single-threaded context.
      33             : bool
      34           3 : Initialize()
      35             : {
      36           3 :     VTuneMutex = js_new<Mutex>(mutexid::VTuneLock);
      37           3 :     if (!VTuneMutex)
      38           0 :         return false;
      39             : 
      40             :     // Load the VTune shared library, if present.
      41           3 :     int loaded = loadiJIT_Funcs();
      42           3 :     if (loaded == 1)
      43           0 :         VTuneLoaded = true;
      44             : 
      45           3 :     return true;
      46             : }
      47             : 
      48             : // Shutdown is called froma single-threaded context.
      49             : void
      50           0 : Shutdown()
      51             : {
      52           0 :     js_delete(VTuneMutex);
      53           0 :     VTuneMutex = nullptr;
      54           0 : }
      55             : 
      56             : bool
      57        1776 : IsProfilingActive()
      58             : {
      59             :     // Checking VTuneLoaded guards against VTune internals attempting
      60             :     // to load the VTune library upon their invocation.
      61        1776 :     return VTuneLoaded && iJIT_IsProfilingActive() == iJIT_SAMPLING_ON;
      62             : }
      63             : 
      64             : uint32_t
      65       24857 : GenerateUniqueMethodID()
      66             : {
      67             :     // iJIT_GetNewMethodID() is explicitly not threadsafe.
      68       24857 :     MOZ_ASSERT(VTuneMutex);
      69       49714 :     LockGuard<Mutex> guard(*VTuneMutex);
      70       49714 :     return (uint32_t)iJIT_GetNewMethodID();
      71             : }
      72             : 
      73             : static int
      74           0 : SafeNotifyEvent(iJIT_JVM_EVENT event_type, void* data)
      75             : {
      76           0 :     MOZ_ASSERT(VTuneMutex);
      77           0 :     LockGuard<Mutex> guard(*VTuneMutex);
      78           0 :     return iJIT_NotifyEvent(event_type, data);
      79             : }
      80             : 
      81             : // Stubs and trampolines are created on engine initialization and are never unloaded.
      82             : void
      83        1104 : MarkStub(const js::jit::JitCode* code, const char* name)
      84             : {
      85        1104 :     if (!IsProfilingActive())
      86        1104 :         return;
      87             : 
      88           0 :     iJIT_Method_Load_V2 method = {0};
      89           0 :     method.method_id = GenerateUniqueMethodID();
      90           0 :     method.method_name = const_cast<char*>(name);
      91           0 :     method.method_load_address = code->raw();
      92           0 :     method.method_size = code->instructionsSize();
      93           0 :     method.module_name = const_cast<char*>("jitstubs");
      94             : 
      95           0 :     int ok = SafeNotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2, (void*)&method);
      96           0 :     if (ok != 1)
      97           0 :         printf("[!] VTune Integration: Failed to load method.\n");
      98             : }
      99             : 
     100             : void
     101          40 : MarkRegExp(const js::jit::JitCode* code, bool match_only)
     102             : {
     103          40 :     if (!IsProfilingActive())
     104          40 :         return;
     105             : 
     106           0 :     iJIT_Method_Load_V2 method = {0};
     107           0 :     method.method_id = GenerateUniqueMethodID();
     108           0 :     method.method_load_address = code->raw();
     109           0 :     method.method_size = code->instructionsSize();
     110             : 
     111           0 :     if (match_only)
     112           0 :         method.method_name = const_cast<char*>("regexp (match-only)");
     113             :     else
     114           0 :         method.method_name = const_cast<char*>("regexp (normal)");
     115             : 
     116           0 :     method.module_name = const_cast<char*>("irregexp");
     117             : 
     118           0 :     int ok = SafeNotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2, (void*)&method);
     119           0 :     if (ok != 1)
     120           0 :         printf("[!] VTune Integration: Failed to load method.\n");
     121             : }
     122             : 
     123             : void
     124         632 : MarkScript(const js::jit::JitCode* code, const JSScript* script, const char* module)
     125             : {
     126         632 :     if (!IsProfilingActive())
     127         632 :         return;
     128             : 
     129           0 :     iJIT_Method_Load_V2 method = {0};
     130           0 :     method.method_id = script->vtuneMethodID();
     131           0 :     method.method_load_address = code->raw();
     132           0 :     method.method_size = code->instructionsSize();
     133           0 :     method.module_name = const_cast<char*>(module);
     134             : 
     135             :     // Line numbers begin at 1, but columns begin at 0.
     136             :     // Text editors start at 1,1 so fixup is performed to match.
     137             :     char namebuf[512];
     138           0 :     SprintfLiteral(namebuf, "%s:%zu:%zu",
     139           0 :                    script->filename(), script->lineno(), script->column() + 1);
     140             : 
     141           0 :     method.method_name = &namebuf[0];
     142             : 
     143           0 :     int ok = SafeNotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2, (void*)&method);
     144           0 :     if (ok != 1)
     145           0 :         printf("[!] VTune Integration: Failed to load method.\n");
     146             : }
     147             : 
     148             : void
     149           0 : MarkWasm(unsigned methodId, const char* name, void* start, uintptr_t size)
     150             : {
     151           0 :     if (!IsProfilingActive())
     152           0 :         return;
     153             : 
     154           0 :     iJIT_Method_Load_V2 method = {0};
     155           0 :     method.method_id = methodId;
     156           0 :     method.method_name = const_cast<char*>(name);
     157           0 :     method.method_load_address = start;
     158           0 :     method.method_size = (unsigned)size;
     159           0 :     method.module_name = const_cast<char*>("wasm");
     160             : 
     161           0 :     int ok = SafeNotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2, (void*)&method);
     162           0 :     if (ok != 1)
     163           0 :         printf("[!] VTune Integration: Failed to load method.\n");
     164             : }
     165             : 
     166             : void
     167           0 : UnmarkCode(const js::jit::JitCode* code)
     168             : {
     169           0 :     UnmarkBytes(code->raw(), (unsigned)code->instructionsSize());
     170           0 : }
     171             : 
     172             : void
     173           0 : UnmarkBytes(void* bytes, unsigned size)
     174             : {
     175           0 :     if (!IsProfilingActive())
     176           0 :         return;
     177             : 
     178             :     // It appears that the method_id is not required for unloading.
     179           0 :     iJIT_Method_Load method = {0};
     180           0 :     method.method_load_address = bytes;
     181           0 :     method.method_size = size;
     182             : 
     183             :     // The iJVM_EVENT_TYPE_METHOD_UNLOAD_START event is undocumented.
     184             :     // VTune appears to happily accept unload events even for untracked JitCode.
     185           0 :     int ok = SafeNotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, (void*)&method);
     186             : 
     187             :     // Assertions aren't reported in VTune: instead, they immediately end profiling
     188             :     // with no warning that a crash occurred. This can generate misleading profiles.
     189             :     // So instead, print out a message to stdout (which VTune does not redirect).
     190           0 :     if (ok != 1)
     191           0 :         printf("[!] VTune Integration: Failed to unload method.\n");
     192             : }
     193             : 
     194             : } // namespace vtune
     195             : } // namespace js
     196             : 
     197             : #endif // MOZ_VTUNE

Generated by: LCOV version 1.13