js/public/ProfilingStack.h

changeset 0
6474c204b198
     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 */

mercurial