Changeset 201990 in webkit


Ignore:
Timestamp:
Jun 13, 2016 8:53:42 AM (8 years ago)
Author:
mark.lam@apple.com
Message:

Add a mechanism for collecting LLINT stats.
https://bugs.webkit.org/show_bug.cgi?id=158668

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

This patch will add a mechanism for collecting the stats on LLINT opcode
execution counts. The changes made to enable this are:

  1. Refactored how Options availability work so that we can add a new category: Configurable (in addition to the pre-existing Normal and Restricted availability).

Normal options - always available.
Restricted options - only available on debug builds.
Configurable options - depends on #define flag options.

This change is necessary so that:

  1. we won't have to rebuild the world when we want to enable that #define flag to make that Configurable option available.
  2. when the #define flag is disabled, the option will be invisible to the user.

With this, we add our first configurable option, JSC_reportLLIntStats, which
is dependent on the ENABLE_LLINT_STATS flag. See next.

  1. Added the ENABLE_LLINT_STATS flag in LLIntCommon.h. To enable LLINT stats collection, we'll need to set this flag to a non-zero value, and rebuilding the project. By design, this will only require a minimal set of files to be rebuilt.

ENABLE_LLINT_STATS is 0 (i.e. disabled) by default.

  1. Added a slow path callback to the LLINT's traceExecution() macro, to call _llint_count_opcode(), which in turns counts the opcode. This callback will only be built into the LLINT if ENABLE_LLINT_STATS is non-zero.
  1. Added s_opcodeStatsArray to LLInt::Data. This is where the stats are recorded and stored.
  1. Added calls to LLInt::Data::dumpStats() in jsc.cpp and DumpRenderTree.mm to dump the LLINT stats if enabled. If enabled, the LLINT stats will be sorted and dumped (via dataLog) before the programs terminate.
  • interpreter/Interpreter.h:
  • jsc.cpp:

(main):

  • llint/LLIntCommon.h:
  • llint/LLIntData.cpp:

(JSC::LLInt::initialize):
(JSC::LLInt::Data::dumpStats):

  • llint/LLIntData.h:

(JSC::LLInt::Data::opcodeStats):

  • llint/LLIntOfflineAsmConfig.h:
  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::llint_crash):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LLIntSlowPaths.h:
  • llint/LowLevelInterpreter.asm:
  • runtime/Options.cpp:

(JSC::parse):
(JSC::Options::isAvailable):
(JSC::overrideOptionWithHeuristic):
(JSC::scaleJITPolicy):
(JSC::Options::initialize):
(JSC::Options::setOptionWithoutAlias):
(JSC::Options::dumpAllOptions):
(JSC::Options::dumpOption):

  • runtime/Options.h:

(JSC::Option::Option):
(JSC::Option::operator!=):
(JSC::Option::id):

Tools:

  • DumpRenderTree/mac/DumpRenderTree.mm:

(DumpRenderTreeMain):

Location:
trunk
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r201976 r201990  
     12016-06-13  Mark Lam  <mark.lam@apple.com>
     2
     3        Add a mechanism for collecting LLINT stats.
     4        https://bugs.webkit.org/show_bug.cgi?id=158668
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch will add a mechanism for collecting the stats on LLINT opcode
     9        execution counts.  The changes made to enable this are:
     10
     11        1. Refactored how Options availability work so that we can add a new category:
     12           Configurable (in addition to the pre-existing Normal and Restricted
     13           availability).
     14               Normal options - always available.
     15               Restricted options - only available on debug builds.
     16               Configurable options - depends on #define flag options.
     17
     18           This change is necessary so that:
     19           a. we won't have to rebuild the world when we want to enable that #define flag
     20              to make that Configurable option available.
     21           b. when the #define flag is disabled, the option will be invisible to the user.
     22
     23           With this, we add our first configurable option, JSC_reportLLIntStats, which
     24           is dependent on the ENABLE_LLINT_STATS flag.  See next.
     25
     26        2. Added the ENABLE_LLINT_STATS flag in LLIntCommon.h.  To enable LLINT stats
     27           collection, we'll need to set this flag to a non-zero value, and rebuilding
     28           the project.  By design, this will only require a minimal set of files to
     29           be rebuilt.
     30
     31           ENABLE_LLINT_STATS is 0 (i.e. disabled) by default.
     32
     33        3. Added a slow path callback to the LLINT's traceExecution() macro, to call
     34           _llint_count_opcode(), which in turns counts the opcode.  This callback will
     35           only be built into the LLINT if ENABLE_LLINT_STATS is non-zero.
     36
     37        4. Added s_opcodeStatsArray to LLInt::Data.  This is where the stats are
     38           recorded and stored.
     39
     40        5. Added calls to LLInt::Data::dumpStats() in jsc.cpp and DumpRenderTree.mm
     41           to dump the LLINT stats if enabled.  If enabled, the LLINT stats will be
     42           sorted and dumped (via dataLog) before the programs terminate.
     43
     44        * interpreter/Interpreter.h:
     45        * jsc.cpp:
     46        (main):
     47        * llint/LLIntCommon.h:
     48        * llint/LLIntData.cpp:
     49        (JSC::LLInt::initialize):
     50        (JSC::LLInt::Data::dumpStats):
     51        * llint/LLIntData.h:
     52        (JSC::LLInt::Data::opcodeStats):
     53        * llint/LLIntOfflineAsmConfig.h:
     54        * llint/LLIntSlowPaths.cpp:
     55        (JSC::LLInt::llint_crash):
     56        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     57        * llint/LLIntSlowPaths.h:
     58        * llint/LowLevelInterpreter.asm:
     59        * runtime/Options.cpp:
     60        (JSC::parse):
     61        (JSC::Options::isAvailable):
     62        (JSC::overrideOptionWithHeuristic):
     63        (JSC::scaleJITPolicy):
     64        (JSC::Options::initialize):
     65        (JSC::Options::setOptionWithoutAlias):
     66        (JSC::Options::dumpAllOptions):
     67        (JSC::Options::dumpOption):
     68        * runtime/Options.h:
     69        (JSC::Option::Option):
     70        (JSC::Option::operator!=):
     71        (JSC::Option::id):
     72
    1732016-06-11  Mark Lam  <mark.lam@apple.com>
    274
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.h

    r201976 r201990  
    3636#include "JSObject.h"
    3737#include "JSStack.h"
    38 #include "LLIntData.h"
    3938#include "Opcode.h"
    4039#include "SourceProvider.h"
  • trunk/Source/JavaScriptCore/jsc.cpp

    r201783 r201990  
    5252#include "JSString.h"
    5353#include "JSWASMModule.h"
     54#include "LLIntData.h"
    5455#include "ProfilerDatabase.h"
    5556#include "SamplingProfiler.h"
     
    19841985    if (Options::logHeapStatisticsAtExit())
    19851986        HeapStatistics::reportSuccess();
     1987    if (Options::reportLLIntStats())
     1988        LLInt::Data::dumpStats();
    19861989
    19871990#if PLATFORM(EFL)
  • trunk/Source/JavaScriptCore/llint/LLIntCommon.h

    r161356 r201990  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012-2013, 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#define LLIntCommon_h
    2828
     29// Enables LLINT stats collection.
     30#define ENABLE_LLINT_STATS 0
     31
    2932// Print every instruction executed.
    3033#define LLINT_EXECUTION_TRACING 0
  • trunk/Source/JavaScriptCore/llint/LLIntData.cpp

    r201335 r201990  
    2626#include "config.h"
    2727#include "LLIntData.h"
     28
    2829#include "BytecodeConventions.h"
    2930#include "CodeBlock.h"
     
    3233#include "JSScope.h"
    3334#include "LLIntCLoop.h"
     35#include "LLIntCommon.h"
    3436#include "MaxFrameExtentForSlowPathCall.h"
    3537#include "Opcode.h"
     
    4446Instruction* Data::s_exceptionInstructions = 0;
    4547Opcode Data::s_opcodeMap[numOpcodeIDs] = { };
     48OpcodeStatsArray* Data::s_opcodeStatsArray = nullptr;
    4649
    4750#if ENABLE(JIT)
     
    6366            LLInt::getCodePtr(llint_throw_from_slow_path_trampoline);
    6467#endif // ENABLE(JIT)
     68
     69#if ENABLE(LLINT_STATS)
     70    Data::s_opcodeStatsArray = new OpcodeStatsArray();
     71    unsigned i = 0;
     72    for (auto& stats : *Data::s_opcodeStatsArray)
     73        stats.id = static_cast<OpcodeID>(i++);
     74#endif
    6575}
    6676
     
    218228#endif
    219229
     230void Data::dumpStats()
     231{
     232#if ENABLE(LLINT_STATS)
     233    if (!Options::reportLLIntStats())
     234        return;
     235
     236    auto statsCopy = *s_opcodeStatsArray;
     237    std::sort(statsCopy.begin(), statsCopy.end(), [] (OpcodeStats& a, OpcodeStats& b) -> bool {
     238        return a.count > b.count;
     239    });
     240   
     241    dataLog("Opcode stats:\n");
     242    unsigned i = 0;
     243    for (auto& stats : statsCopy) {
     244        if (stats.count)
     245            dataLog("   [", i++, "]: fast:", stats.count, " ", opcodeNames[stats.id], "\n");
     246    }
     247#endif
     248}
     249
     250
    220251} } // namespace JSC::LLInt
  • trunk/Source/JavaScriptCore/llint/LLIntData.h

    r170147 r201990  
    2929#include "JSCJSValue.h"
    3030#include "Opcode.h"
     31#include <array>
    3132
    3233namespace JSC {
     
    4344namespace LLInt {
    4445
     46struct OpcodeStats {
     47    OpcodeID id;
     48    size_t count { 0 };
     49};
     50typedef std::array<OpcodeStats, numOpcodeIDs> OpcodeStatsArray;
     51
    4552class Data {
    4653public:
     54
    4755    static void performAssertions(VM&);
     56    static OpcodeStats& opcodeStats(OpcodeID id) { return (*s_opcodeStatsArray)[id]; }
     57
     58    JS_EXPORT_PRIVATE static void dumpStats();
    4859
    4960private:
    5061    static Instruction* s_exceptionInstructions;
    5162    static Opcode s_opcodeMap[numOpcodeIDs];
     63    static OpcodeStatsArray* s_opcodeStatsArray;
    5264
    5365    friend void initialize();
  • trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h

    r190129 r201990  
    156156#endif
    157157
     158#if ENABLE(LLINT_STATS)
     159#define OFFLINE_ASM_COLLECT_STATS 1
     160#else
     161#define OFFLINE_ASM_COLLECT_STATS 0
     162#endif
     163
    158164#if LLINT_EXECUTION_TRACING
    159165#define OFFLINE_ASM_EXECUTION_TRACING 1
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r201703 r201990  
    5050#include "JSWithScope.h"
    5151#include "LLIntCommon.h"
     52#include "LLIntData.h"
    5253#include "LLIntExceptions.h"
    5354#include "LowLevelInterpreter.h"
     
    16241625}
    16251626
     1627#if ENABLE(LLINT_STATS)
     1628
     1629LLINT_SLOW_PATH_DECL(count_opcode)
     1630{
     1631    OpcodeID opcodeID = exec->vm().interpreter->getOpcodeID(pc[0].u.opcode);
     1632    Data::opcodeStats(opcodeID).count++;
     1633    LLINT_END_IMPL();
     1634}
     1635
     1636#endif // ENABLE(LLINT_STATS)
     1637
    16261638} } // namespace JSC::LLInt
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h

    r201542 r201990  
    5555LLINT_SLOW_PATH_HIDDEN_DECL(trace);
    5656LLINT_SLOW_PATH_HIDDEN_DECL(special_trace);
     57LLINT_SLOW_PATH_HIDDEN_DECL(count_opcode);
    5758LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr);
    5859LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr_function_for_call);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r201542 r201990  
    727727
    728728macro traceExecution()
     729    if COLLECT_STATS
     730        callSlowPath(_llint_count_opcode)
     731    end
    729732    if EXECUTION_TRACING
    730733        callSlowPath(_llint_trace)
  • trunk/Source/JavaScriptCore/runtime/Options.cpp

    r201848 r201990  
    2727#include "Options.h"
    2828
     29#include "LLIntCommon.h"
    2930#include <algorithm>
    3031#include <limits>
     
    124125}
    125126
     127bool Options::isAvailable(Options::ID id, Options::Availability availability)
     128{
     129    if (availability == Availability::Restricted)
     130        return allowRestrictedOptions();
     131    ASSERT(availability == Availability::Configurable);
     132   
     133    UNUSED_PARAM(id);
     134#if ENABLE(LLINT_STATS)
     135    if (id == reportLLIntStatsID)
     136        return true;
     137#endif
     138    return false;
     139}
     140
    126141template<typename T>
    127 bool overrideOptionWithHeuristic(T& variable, const char* name, Options::Availability availability)
    128 {
    129     bool isAvailable = (availability != Options::Availability::Restricted) || allowRestrictedOptions();
     142bool overrideOptionWithHeuristic(T& variable, Options::ID id, const char* name, Options::Availability availability)
     143{
     144    bool available = (availability == Options::Availability::Normal)
     145        || Options::isAvailable(id, availability);
    130146
    131147    const char* stringValue = getenv(name);
     
    133149        return false;
    134150   
    135     if (isAvailable && parse(stringValue, variable))
     151    if (available && parse(stringValue, variable))
    136152        return true;
    137153   
     
    259275
    260276    struct OptionToScale {
    261         Options::OptionID id;
     277        Options::ID id;
    262278        int32_t minVal;
    263279    };
     
    407423#else // PLATFORM(COCOA)
    408424#define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
    409             overrideOptionWithHeuristic(name_(), "JSC_" #name_, Availability::availability_);
     425            overrideOptionWithHeuristic(name_(), name_##ID, "JSC_" #name_, Availability::availability_);
    410426            JSC_OPTIONS(FOR_EACH_OPTION)
    411427#undef FOR_EACH_OPTION
     
    574590    if (strlen(#name_) == static_cast<size_t>(equalStr - arg)      \
    575591        && !strncmp(arg, #name_, equalStr - arg)) {                \
    576         if (Availability::availability_ == Availability::Restricted && !allowRestrictedOptions()) \
     592        if (Availability::availability_ != Availability::Normal     \
     593            && !isAvailable(name_##ID, Availability::availability_)) \
    577594            return false;                                          \
    578595        type_ value;                                               \
     
    668685        if (separator && id)
    669686            builder.append(separator);
    670         dumpOption(builder, level, static_cast<OptionID>(id), optionHeader, optionFooter, dumpDefaultsOption);
     687        dumpOption(builder, level, static_cast<ID>(id), optionHeader, optionFooter, dumpDefaultsOption);
    671688    }
    672689}
     
    684701}
    685702
    686 void Options::dumpOption(StringBuilder& builder, DumpLevel level, OptionID id,
     703void Options::dumpOption(StringBuilder& builder, DumpLevel level, Options::ID id,
    687704    const char* header, const char* footer, DumpDefaultsOption dumpDefaultsOption)
    688705{
     
    691708
    692709    Option option(id);
    693     if (option.availability() == Availability::Restricted && !allowRestrictedOptions())
     710    Availability availability = option.availability();
     711    if (availability != Availability::Normal && !isAvailable(id, availability))
    694712        return;
    695713
  • trunk/Source/JavaScriptCore/runtime/Options.h

    r201866 r201990  
    372372    v(bool, dumpAirAfterAllocateStack, false, Normal, nullptr) \
    373373    \
    374     v(bool, useSuperSampler, false, Normal, nullptr)
     374    v(bool, useSuperSampler, false, Normal, nullptr) \
     375    \
     376    v(bool, reportLLIntStats, false, Configurable, "Reports LLInt statistics")
    375377
    376378enum OptionEquivalence {
     
    422424    enum class Availability {
    423425        Normal = 0,
    424         Restricted
     426        Restricted,
     427        Configurable
    425428    };
    426429
     
    430433
    431434    // Declare the option IDs:
    432     enum OptionID {
     435    enum ID {
    433436#define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
    434437        name_##ID,
     
    470473    JSC_OPTIONS(FOR_EACH_OPTION)
    471474#undef FOR_EACH_OPTION
     475
     476    static bool isAvailable(ID, Availability);
    472477
    473478private:
     
    500505    static void dumpAllOptions(StringBuilder&, DumpLevel, const char* title,
    501506        const char* separator, const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
    502     static void dumpOption(StringBuilder&, DumpLevel, OptionID,
     507    static void dumpOption(StringBuilder&, DumpLevel, ID,
    503508        const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
    504509
     
    517522class Option {
    518523public:
    519     Option(Options::OptionID id)
     524    Option(Options::ID id)
    520525        : m_id(id)
    521526        , m_entry(Options::s_options[m_id])
     
    528533    bool operator!=(const Option& other) const { return !(*this == other); }
    529534   
     535    Options::ID id() const { return m_id; }
    530536    const char* name() const;
    531537    const char* description() const;
     
    545551private:
    546552    // Only used for constructing default Options.
    547     Option(Options::OptionID id, Options::Entry& entry)
     553    Option(Options::ID id, Options::Entry& entry)
    548554        : m_id(id)
    549555        , m_entry(entry)
     
    551557    }
    552558   
    553     Options::OptionID m_id;
     559    Options::ID m_id;
    554560    Options::Entry& m_entry;
    555561};
  • trunk/Tools/ChangeLog

    r201989 r201990  
     12016-06-13  Mark Lam  <mark.lam@apple.com>
     2
     3        Add a mechanism for collecting LLINT stats.
     4        https://bugs.webkit.org/show_bug.cgi?id=158668
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * DumpRenderTree/mac/DumpRenderTree.mm:
     9        (DumpRenderTreeMain):
     10
    1112016-06-13  Romain Bellessort  <romain.bellessort@crf.canon.fr>
    212
  • trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm

    r201981 r201990  
    5858#import <CoreFoundation/CoreFoundation.h>
    5959#import <JavaScriptCore/HeapStatistics.h>
     60#import <JavaScriptCore/LLIntData.h>
    6061#import <JavaScriptCore/Options.h>
    6162#import <WebCore/Logging.h>
     
    14431444    if (JSC::Options::logHeapStatisticsAtExit())
    14441445        JSC::HeapStatistics::reportSuccess();
     1446    if (JSC::Options::reportLLIntStats())
     1447        JSC::LLInt::Data::dumpStats();
    14451448    [pool release];
    14461449    returningFromMain = true;
Note: See TracChangeset for help on using the changeset viewer.