Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (201989 => 201990)
--- trunk/Source/_javascript_Core/ChangeLog 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-06-13 15:53:42 UTC (rev 201990)
@@ -1,3 +1,75 @@
+2016-06-13 Mark Lam <[email protected]>
+
+ Add a mechanism for collecting LLINT stats.
+ https://bugs.webkit.org/show_bug.cgi?id=158668
+
+ Reviewed by Filip Pizlo.
+
+ 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:
+ a. we won't have to rebuild the world when we want to enable that #define flag
+ to make that Configurable option available.
+ b. 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.
+
+ 2. 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.
+
+ 3. 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.
+
+ 4. Added s_opcodeStatsArray to LLInt::Data. This is where the stats are
+ recorded and stored.
+
+ 5. 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):
+
2016-06-11 Mark Lam <[email protected]>
Minimize the amount of memcpy done for allocating Error stacks.
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.h (201989 => 201990)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.h 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.h 2016-06-13 15:53:42 UTC (rev 201990)
@@ -35,7 +35,6 @@
#include "JSCell.h"
#include "JSObject.h"
#include "JSStack.h"
-#include "LLIntData.h"
#include "Opcode.h"
#include "SourceProvider.h"
#include "StackAlignment.h"
Modified: trunk/Source/_javascript_Core/jsc.cpp (201989 => 201990)
--- trunk/Source/_javascript_Core/jsc.cpp 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/jsc.cpp 2016-06-13 15:53:42 UTC (rev 201990)
@@ -51,6 +51,7 @@
#include "JSProxy.h"
#include "JSString.h"
#include "JSWASMModule.h"
+#include "LLIntData.h"
#include "ProfilerDatabase.h"
#include "SamplingProfiler.h"
#include "ShadowChicken.h"
@@ -1983,6 +1984,8 @@
EXCEPT(res = 3)
if (Options::logHeapStatisticsAtExit())
HeapStatistics::reportSuccess();
+ if (Options::reportLLIntStats())
+ LLInt::Data::dumpStats();
#if PLATFORM(EFL)
ecore_shutdown();
Modified: trunk/Source/_javascript_Core/llint/LLIntCommon.h (201989 => 201990)
--- trunk/Source/_javascript_Core/llint/LLIntCommon.h 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/llint/LLIntCommon.h 2016-06-13 15:53:42 UTC (rev 201990)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2013, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,6 +26,9 @@
#ifndef LLIntCommon_h
#define LLIntCommon_h
+// Enables LLINT stats collection.
+#define ENABLE_LLINT_STATS 0
+
// Print every instruction executed.
#define LLINT_EXECUTION_TRACING 0
Modified: trunk/Source/_javascript_Core/llint/LLIntData.cpp (201989 => 201990)
--- trunk/Source/_javascript_Core/llint/LLIntData.cpp 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/llint/LLIntData.cpp 2016-06-13 15:53:42 UTC (rev 201990)
@@ -25,12 +25,14 @@
#include "config.h"
#include "LLIntData.h"
+
#include "BytecodeConventions.h"
#include "CodeBlock.h"
#include "CodeType.h"
#include "Instruction.h"
#include "JSScope.h"
#include "LLIntCLoop.h"
+#include "LLIntCommon.h"
#include "MaxFrameExtentForSlowPathCall.h"
#include "Opcode.h"
#include "PropertyOffset.h"
@@ -43,6 +45,7 @@
Instruction* Data::s_exceptionInstructions = 0;
Opcode Data::s_opcodeMap[numOpcodeIDs] = { };
+OpcodeStatsArray* Data::s_opcodeStatsArray = nullptr;
#if ENABLE(JIT)
extern "C" void llint_entry(void*);
@@ -62,6 +65,13 @@
Data::s_exceptionInstructions[i].u.pointer =
LLInt::getCodePtr(llint_throw_from_slow_path_trampoline);
#endif // ENABLE(JIT)
+
+#if ENABLE(LLINT_STATS)
+ Data::s_opcodeStatsArray = new OpcodeStatsArray();
+ unsigned i = 0;
+ for (auto& stats : *Data::s_opcodeStatsArray)
+ stats.id = static_cast<OpcodeID>(i++);
+#endif
}
#if COMPILER(CLANG)
@@ -217,4 +227,25 @@
#pragma clang diagnostic pop
#endif
+void Data::dumpStats()
+{
+#if ENABLE(LLINT_STATS)
+ if (!Options::reportLLIntStats())
+ return;
+
+ auto statsCopy = *s_opcodeStatsArray;
+ std::sort(statsCopy.begin(), statsCopy.end(), [] (OpcodeStats& a, OpcodeStats& b) -> bool {
+ return a.count > b.count;
+ });
+
+ dataLog("Opcode stats:\n");
+ unsigned i = 0;
+ for (auto& stats : statsCopy) {
+ if (stats.count)
+ dataLog(" [", i++, "]: fast:", stats.count, " ", opcodeNames[stats.id], "\n");
+ }
+#endif
+}
+
+
} } // namespace JSC::LLInt
Modified: trunk/Source/_javascript_Core/llint/LLIntData.h (201989 => 201990)
--- trunk/Source/_javascript_Core/llint/LLIntData.h 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/llint/LLIntData.h 2016-06-13 15:53:42 UTC (rev 201990)
@@ -28,6 +28,7 @@
#include "JSCJSValue.h"
#include "Opcode.h"
+#include <array>
namespace JSC {
@@ -42,13 +43,24 @@
namespace LLInt {
+struct OpcodeStats {
+ OpcodeID id;
+ size_t count { 0 };
+};
+typedef std::array<OpcodeStats, numOpcodeIDs> OpcodeStatsArray;
+
class Data {
public:
+
static void performAssertions(VM&);
+ static OpcodeStats& opcodeStats(OpcodeID id) { return (*s_opcodeStatsArray)[id]; }
+ JS_EXPORT_PRIVATE static void dumpStats();
+
private:
static Instruction* s_exceptionInstructions;
static Opcode s_opcodeMap[numOpcodeIDs];
+ static OpcodeStatsArray* s_opcodeStatsArray;
friend void initialize();
Modified: trunk/Source/_javascript_Core/llint/LLIntOfflineAsmConfig.h (201989 => 201990)
--- trunk/Source/_javascript_Core/llint/LLIntOfflineAsmConfig.h 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/llint/LLIntOfflineAsmConfig.h 2016-06-13 15:53:42 UTC (rev 201990)
@@ -155,6 +155,12 @@
#define OFFLINE_ASM_BIG_ENDIAN 0
#endif
+#if ENABLE(LLINT_STATS)
+#define OFFLINE_ASM_COLLECT_STATS 1
+#else
+#define OFFLINE_ASM_COLLECT_STATS 0
+#endif
+
#if LLINT_EXECUTION_TRACING
#define OFFLINE_ASM_EXECUTION_TRACING 1
#else
Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (201989 => 201990)
--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp 2016-06-13 15:53:42 UTC (rev 201990)
@@ -49,6 +49,7 @@
#include "JSString.h"
#include "JSWithScope.h"
#include "LLIntCommon.h"
+#include "LLIntData.h"
#include "LLIntExceptions.h"
#include "LowLevelInterpreter.h"
#include "ObjectConstructor.h"
@@ -1623,4 +1624,15 @@
CRASH();
}
+#if ENABLE(LLINT_STATS)
+
+LLINT_SLOW_PATH_DECL(count_opcode)
+{
+ OpcodeID opcodeID = exec->vm().interpreter->getOpcodeID(pc[0].u.opcode);
+ Data::opcodeStats(opcodeID).count++;
+ LLINT_END_IMPL();
+}
+
+#endif // ENABLE(LLINT_STATS)
+
} } // namespace JSC::LLInt
Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h (201989 => 201990)
--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h 2016-06-13 15:53:42 UTC (rev 201990)
@@ -54,6 +54,7 @@
LLINT_SLOW_PATH_HIDDEN_DECL(trace_arityCheck_for_construct);
LLINT_SLOW_PATH_HIDDEN_DECL(trace);
LLINT_SLOW_PATH_HIDDEN_DECL(special_trace);
+LLINT_SLOW_PATH_HIDDEN_DECL(count_opcode);
LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr);
LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr_function_for_call);
LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr_function_for_construct);
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (201989 => 201990)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2016-06-13 15:53:42 UTC (rev 201990)
@@ -726,6 +726,9 @@
end
macro traceExecution()
+ if COLLECT_STATS
+ callSlowPath(_llint_count_opcode)
+ end
if EXECUTION_TRACING
callSlowPath(_llint_trace)
end
Modified: trunk/Source/_javascript_Core/runtime/Options.cpp (201989 => 201990)
--- trunk/Source/_javascript_Core/runtime/Options.cpp 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/runtime/Options.cpp 2016-06-13 15:53:42 UTC (rev 201990)
@@ -26,6 +26,7 @@
#include "config.h"
#include "Options.h"
+#include "LLIntCommon.h"
#include <algorithm>
#include <limits>
#include <math.h>
@@ -123,16 +124,31 @@
return false;
}
+bool Options::isAvailable(Options::ID id, Options::Availability availability)
+{
+ if (availability == Availability::Restricted)
+ return allowRestrictedOptions();
+ ASSERT(availability == Availability::Configurable);
+
+ UNUSED_PARAM(id);
+#if ENABLE(LLINT_STATS)
+ if (id == reportLLIntStatsID)
+ return true;
+#endif
+ return false;
+}
+
template<typename T>
-bool overrideOptionWithHeuristic(T& variable, const char* name, Options::Availability availability)
+bool overrideOptionWithHeuristic(T& variable, Options::ID id, const char* name, Options::Availability availability)
{
- bool isAvailable = (availability != Options::Availability::Restricted) || allowRestrictedOptions();
+ bool available = (availability == Options::Availability::Normal)
+ || Options::isAvailable(id, availability);
const char* stringValue = getenv(name);
if (!stringValue)
return false;
- if (isAvailable && parse(stringValue, variable))
+ if (available && parse(stringValue, variable))
return true;
fprintf(stderr, "WARNING: failed to parse %s=%s\n", name, stringValue);
@@ -258,7 +274,7 @@
scaleFactor = 0.0;
struct OptionToScale {
- Options::OptionID id;
+ Options::ID id;
int32_t minVal;
};
@@ -406,7 +422,7 @@
CRASH();
#else // PLATFORM(COCOA)
#define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
- overrideOptionWithHeuristic(name_(), "JSC_" #name_, Availability::availability_);
+ overrideOptionWithHeuristic(name_(), name_##ID, "JSC_" #name_, Availability::availability_);
JSC_OPTIONS(FOR_EACH_OPTION)
#undef FOR_EACH_OPTION
#endif // PLATFORM(COCOA)
@@ -573,7 +589,8 @@
#define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
if (strlen(#name_) == static_cast<size_t>(equalStr - arg) \
&& !strncmp(arg, #name_, equalStr - arg)) { \
- if (Availability::availability_ == Availability::Restricted && !allowRestrictedOptions()) \
+ if (Availability::availability_ != Availability::Normal \
+ && !isAvailable(name_##ID, Availability::availability_)) \
return false; \
type_ value; \
value = (defaultValue_); \
@@ -667,7 +684,7 @@
for (int id = 0; id < numberOfOptions; id++) {
if (separator && id)
builder.append(separator);
- dumpOption(builder, level, static_cast<OptionID>(id), optionHeader, optionFooter, dumpDefaultsOption);
+ dumpOption(builder, level, static_cast<ID>(id), optionHeader, optionFooter, dumpDefaultsOption);
}
}
@@ -683,14 +700,15 @@
fprintf(stream, "%s", builder.toString().utf8().data());
}
-void Options::dumpOption(StringBuilder& builder, DumpLevel level, OptionID id,
+void Options::dumpOption(StringBuilder& builder, DumpLevel level, Options::ID id,
const char* header, const char* footer, DumpDefaultsOption dumpDefaultsOption)
{
if (id >= numberOfOptions)
return; // Illegal option.
Option option(id);
- if (option.availability() == Availability::Restricted && !allowRestrictedOptions())
+ Availability availability = option.availability();
+ if (availability != Availability::Normal && !isAvailable(id, availability))
return;
bool wasOverridden = option.isOverridden();
Modified: trunk/Source/_javascript_Core/runtime/Options.h (201989 => 201990)
--- trunk/Source/_javascript_Core/runtime/Options.h 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/_javascript_Core/runtime/Options.h 2016-06-13 15:53:42 UTC (rev 201990)
@@ -371,7 +371,9 @@
v(bool, dumpAirAsJSBeforeAllocateStack, false, Normal, nullptr) \
v(bool, dumpAirAfterAllocateStack, false, Normal, nullptr) \
\
- v(bool, useSuperSampler, false, Normal, nullptr)
+ v(bool, useSuperSampler, false, Normal, nullptr) \
+ \
+ v(bool, reportLLIntStats, false, Configurable, "Reports LLInt statistics")
enum OptionEquivalence {
SameOption,
@@ -421,7 +423,8 @@
enum class Availability {
Normal = 0,
- Restricted
+ Restricted,
+ Configurable
};
// This typedef is to allow us to eliminate the '_' in the field name in
@@ -429,7 +432,7 @@
typedef int32_t int32;
// Declare the option IDs:
- enum OptionID {
+ enum ID {
#define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
name_##ID,
JSC_OPTIONS(FOR_EACH_OPTION)
@@ -470,6 +473,8 @@
JSC_OPTIONS(FOR_EACH_OPTION)
#undef FOR_EACH_OPTION
+ static bool isAvailable(ID, Availability);
+
private:
// For storing for an option value:
union Entry {
@@ -499,7 +504,7 @@
static void dumpOptionsIfNeeded();
static void dumpAllOptions(StringBuilder&, DumpLevel, const char* title,
const char* separator, const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
- static void dumpOption(StringBuilder&, DumpLevel, OptionID,
+ static void dumpOption(StringBuilder&, DumpLevel, ID,
const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
static bool setOptionWithoutAlias(const char* arg);
@@ -516,7 +521,7 @@
class Option {
public:
- Option(Options::OptionID id)
+ Option(Options::ID id)
: m_id(id)
, m_entry(Options::s_options[m_id])
{
@@ -527,6 +532,7 @@
bool operator==(const Option& other) const;
bool operator!=(const Option& other) const { return !(*this == other); }
+ Options::ID id() const { return m_id; }
const char* name() const;
const char* description() const;
Options::Type type() const;
@@ -544,13 +550,13 @@
private:
// Only used for constructing default Options.
- Option(Options::OptionID id, Options::Entry& entry)
+ Option(Options::ID id, Options::Entry& entry)
: m_id(id)
, m_entry(entry)
{
}
- Options::OptionID m_id;
+ Options::ID m_id;
Options::Entry& m_entry;
};
Modified: trunk/Tools/ChangeLog (201989 => 201990)
--- trunk/Tools/ChangeLog 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Tools/ChangeLog 2016-06-13 15:53:42 UTC (rev 201990)
@@ -1,3 +1,13 @@
+2016-06-13 Mark Lam <[email protected]>
+
+ Add a mechanism for collecting LLINT stats.
+ https://bugs.webkit.org/show_bug.cgi?id=158668
+
+ Reviewed by Filip Pizlo.
+
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (DumpRenderTreeMain):
+
2016-06-13 Romain Bellessort <[email protected]>
[GTK] Enabling Shadow DOM by default
Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm (201989 => 201990)
--- trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm 2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm 2016-06-13 15:53:42 UTC (rev 201990)
@@ -57,6 +57,7 @@
#import "WorkQueueItem.h"
#import <CoreFoundation/CoreFoundation.h>
#import <_javascript_Core/HeapStatistics.h>
+#import <_javascript_Core/LLIntData.h>
#import <_javascript_Core/Options.h>
#import <WebCore/Logging.h>
#import <WebKit/DOMElement.h>
@@ -1442,6 +1443,8 @@
[WebCoreStatistics emptyCache]; // Otherwise SVGImages trigger false positives for Frame/Node counts
if (JSC::Options::logHeapStatisticsAtExit())
JSC::HeapStatistics::reportSuccess();
+ if (JSC::Options::reportLLIntStats())
+ JSC::LLInt::Data::dumpStats();
[pool release];
returningFromMain = true;
return 0;