1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/public/ProfilingStack.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,115 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef js_ProfilingStack_h 1.11 +#define js_ProfilingStack_h 1.12 + 1.13 +#include "mozilla/NullPtr.h" 1.14 + 1.15 +#include "jsbytecode.h" 1.16 +#include "jstypes.h" 1.17 + 1.18 +#include "js/Utility.h" 1.19 + 1.20 +struct JSRuntime; 1.21 + 1.22 +namespace js { 1.23 + 1.24 +// A call stack can be specified to the JS engine such that all JS entry/exits 1.25 +// to functions push/pop an entry to/from the specified stack. 1.26 +// 1.27 +// For more detailed information, see vm/SPSProfiler.h. 1.28 +// 1.29 +class ProfileEntry 1.30 +{ 1.31 + // All fields are marked volatile to prevent the compiler from re-ordering 1.32 + // instructions. Namely this sequence: 1.33 + // 1.34 + // entry[size] = ...; 1.35 + // size++; 1.36 + // 1.37 + // If the size modification were somehow reordered before the stores, then 1.38 + // if a sample were taken it would be examining bogus information. 1.39 + // 1.40 + // A ProfileEntry represents both a C++ profile entry and a JS one. Both use 1.41 + // the string as a description, but JS uses the sp as nullptr or (void*)1 to 1.42 + // indicate that it is a JS entry. The script_ is then only ever examined for 1.43 + // a JS entry, and the idx is used by both, but with different meanings. 1.44 + // 1.45 + const char * volatile string; // Descriptive string of this entry 1.46 + void * volatile sp; // Relevant stack pointer for the entry, 1.47 + // less than or equal to SCRIPT_OPT_STACKPOINTER for js 1.48 + // script entries, greater for non-js entries. 1.49 + JSScript * volatile script_; // if js(), non-null script which is running - low bit 1.50 + // indicates if script is optimized or not. 1.51 + int32_t volatile idx; // if js(), idx of pc, otherwise line number 1.52 + 1.53 + public: 1.54 + static const uintptr_t SCRIPT_OPT_STACKPOINTER = 0x1; 1.55 + 1.56 + // All of these methods are marked with the 'volatile' keyword because SPS's 1.57 + // representation of the stack is stored such that all ProfileEntry 1.58 + // instances are volatile. These methods would not be available unless they 1.59 + // were marked as volatile as well. 1.60 + 1.61 + bool js() const volatile { 1.62 + MOZ_ASSERT_IF(uintptr_t(sp) <= SCRIPT_OPT_STACKPOINTER, script_ != nullptr); 1.63 + return uintptr_t(sp) <= SCRIPT_OPT_STACKPOINTER; 1.64 + } 1.65 + 1.66 + uint32_t line() const volatile { MOZ_ASSERT(!js()); return idx; } 1.67 + JSScript *script() const volatile { MOZ_ASSERT(js()); return script_; } 1.68 + bool scriptIsOptimized() const volatile { 1.69 + MOZ_ASSERT(js()); 1.70 + return uintptr_t(sp) <= SCRIPT_OPT_STACKPOINTER; 1.71 + } 1.72 + void *stackAddress() const volatile { 1.73 + if (js()) 1.74 + return nullptr; 1.75 + return sp; 1.76 + } 1.77 + const char *label() const volatile { return string; } 1.78 + 1.79 + void setLine(uint32_t aLine) volatile { MOZ_ASSERT(!js()); idx = aLine; } 1.80 + void setLabel(const char *aString) volatile { string = aString; } 1.81 + void setStackAddress(void *aSp) volatile { sp = aSp; } 1.82 + void setScript(JSScript *aScript) volatile { script_ = aScript; } 1.83 + 1.84 + // We can't know the layout of JSScript, so look in vm/SPSProfiler.cpp. 1.85 + JS_FRIEND_API(jsbytecode *) pc() const volatile; 1.86 + JS_FRIEND_API(void) setPC(jsbytecode *pc) volatile; 1.87 + 1.88 + static size_t offsetOfString() { return offsetof(ProfileEntry, string); } 1.89 + static size_t offsetOfStackAddress() { return offsetof(ProfileEntry, sp); } 1.90 + static size_t offsetOfPCIdx() { return offsetof(ProfileEntry, idx); } 1.91 + static size_t offsetOfScript() { return offsetof(ProfileEntry, script_); } 1.92 + 1.93 + // The index used in the entry can either be a line number or the offset of 1.94 + // a pc into a script's code. To signify a nullptr pc, use a -1 index. This 1.95 + // is checked against in pc() and setPC() to set/get the right pc. 1.96 + static const int32_t NullPCIndex = -1; 1.97 + 1.98 + // This bit is added to the stack address to indicate that copying the 1.99 + // frame label is not necessary when taking a sample of the pseudostack. 1.100 + static const uintptr_t NoCopyBit = 1; 1.101 +}; 1.102 + 1.103 +JS_FRIEND_API(void) 1.104 +SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size, 1.105 + uint32_t max); 1.106 + 1.107 +JS_FRIEND_API(void) 1.108 +EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled); 1.109 + 1.110 +JS_FRIEND_API(void) 1.111 +RegisterRuntimeProfilingEventMarker(JSRuntime *rt, void (*fn)(const char *)); 1.112 + 1.113 +JS_FRIEND_API(jsbytecode*) 1.114 +ProfilingGetPC(JSRuntime *rt, JSScript *script, void *ip); 1.115 + 1.116 +} // namespace js 1.117 + 1.118 +#endif /* js_ProfilingStack_h */