Commit 1a6da216 authored by fpizlo@apple.com's avatar fpizlo@apple.com

JSC profiling and debug dump code should use inferred names when possible

https://bugs.webkit.org/show_bug.cgi?id=104519

Reviewed by Oliver Hunt.

Source/JavaScriptCore: 

This does as advertised: the profiler now knows the inferred name of all code blocks,
and all uses of CodeBlock::dump() dump it along with the hash.
        
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::inferredName):
(JSC::CodeBlock::dumpAssumingJITType):
* bytecode/CodeBlock.h:
* profiler/ProfilerBytecodes.cpp:
(JSC::Profiler::Bytecodes::Bytecodes):
(JSC::Profiler::Bytecodes::toJS):
* profiler/ProfilerBytecodes.h:
(JSC::Profiler::Bytecodes::inferredName):
* profiler/ProfilerDatabase.cpp:
(JSC::Profiler::Database::addBytecodes):
(JSC::Profiler::Database::ensureBytecodesFor):
* profiler/ProfilerDatabase.h:
* runtime/CommonIdentifiers.h:

Tools: 

The format I'm using for referring to a code block is now name#hash. For example,
v8-crypto has something called bnpSquareTo#B5QFbU. The profiler allows you to use
either the hash, the inferred name, or the combined hash and full name when referring
to blocks.

* Scripts/display-profiler-output:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@137179 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent c7039b18
2012-12-10 Filip Pizlo <fpizlo@apple.com>
JSC profiling and debug dump code should use inferred names when possible
https://bugs.webkit.org/show_bug.cgi?id=104519
Reviewed by Oliver Hunt.
This does as advertised: the profiler now knows the inferred name of all code blocks,
and all uses of CodeBlock::dump() dump it along with the hash.
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::inferredName):
(JSC::CodeBlock::dumpAssumingJITType):
* bytecode/CodeBlock.h:
* profiler/ProfilerBytecodes.cpp:
(JSC::Profiler::Bytecodes::Bytecodes):
(JSC::Profiler::Bytecodes::toJS):
* profiler/ProfilerBytecodes.h:
(JSC::Profiler::Bytecodes::inferredName):
* profiler/ProfilerDatabase.cpp:
(JSC::Profiler::Database::addBytecodes):
(JSC::Profiler::Database::ensureBytecodesFor):
* profiler/ProfilerDatabase.h:
* runtime/CommonIdentifiers.h:
2012-12-09 Filip Pizlo <fpizlo@apple.com>
Profiler should say things about OSR exits
......
......@@ -64,6 +64,21 @@ namespace JSC {
using namespace DFG;
#endif
String CodeBlock::inferredName() const
{
switch (codeType()) {
case GlobalCode:
return "<global>";
case EvalCode:
return "<eval>";
case FunctionCode:
return jsCast<FunctionExecutable*>(ownerExecutable())->unlinkedExecutable()->inferredName().string();
default:
CRASH();
return String();
}
}
CodeBlockHash CodeBlock::hash() const
{
return CodeBlockHash(ownerExecutable()->source(), specializationKind());
......@@ -95,7 +110,7 @@ String CodeBlock::sourceCodeOnOneLine() const
void CodeBlock::dumpAssumingJITType(PrintStream& out, JITCode::JITType jitType) const
{
out.print("#", hash(), ":[", RawPointer(this), "->", RawPointer(ownerExecutable()), ", ", jitType, codeType());
out.print(inferredName(), "#", hash(), ":[", RawPointer(this), "->", RawPointer(ownerExecutable()), ", ", jitType, codeType());
if (codeType() == FunctionCode)
out.print(specializationKind());
out.print("]");
......
......@@ -131,7 +131,8 @@ namespace JSC {
JS_EXPORT_PRIVATE virtual ~CodeBlock();
UnlinkedCodeBlock* unlinkedCodeBlock() const { return m_unlinkedCode.get(); }
String inferredName() const;
CodeBlockHash hash() const;
String sourceCodeForTools() const; // Not quite the actual source we parsed; this will do things like prefix the source for a function with a reified signature.
String sourceCodeOnOneLine() const; // As sourceCodeForTools(), but replaces all whitespace runs with a single space.
......
......@@ -31,8 +31,10 @@
namespace JSC { namespace Profiler {
Bytecodes::Bytecodes(size_t id, const String& sourceCode, CodeBlockHash hash)
Bytecodes::Bytecodes(
size_t id, const String& inferredName, const String& sourceCode, CodeBlockHash hash)
: m_id(id)
, m_inferredName(inferredName)
, m_sourceCode(sourceCode)
, m_hash(hash)
{
......@@ -60,6 +62,7 @@ JSValue Bytecodes::toJS(ExecState* exec) const
JSObject* result = constructEmptyObject(exec);
result->putDirect(exec->globalData(), exec->propertyNames().bytecodesID, jsNumber(m_id));
result->putDirect(exec->globalData(), exec->propertyNames().inferredName, jsString(exec, m_inferredName));
result->putDirect(exec->globalData(), exec->propertyNames().sourceCode, jsString(exec, m_sourceCode));
result->putDirect(exec->globalData(), exec->propertyNames().hash, jsString(exec, String::fromUTF8(toCString(m_hash))));
......
......@@ -36,12 +36,13 @@ namespace JSC { namespace Profiler {
class Bytecodes {
public:
Bytecodes(size_t id, const String& sourceCode, CodeBlockHash);
Bytecodes(size_t id, const String& inferredName, const String& sourceCode, CodeBlockHash);
~Bytecodes();
void append(const Bytecode& bytecode) { m_bytecode.append(bytecode); }
size_t id() const { return m_id; }
const String& inferredName() const { return m_inferredName; }
const String& sourceCode() const { return m_sourceCode; }
CodeBlockHash hash() const { return m_hash; }
......@@ -58,6 +59,7 @@ public:
private:
size_t m_id;
String m_inferredName;
String m_sourceCode;
CodeBlockHash m_hash;
Vector<Bytecode> m_bytecode;
......
......@@ -41,9 +41,10 @@ Database::~Database()
{
}
Bytecodes* Database::addBytecodes(CodeBlockHash hash, const String& sourceCode)
Bytecodes* Database::addBytecodes(
CodeBlockHash hash, const String& inferredName, const String& sourceCode)
{
m_bytecodes.append(Bytecodes(m_bytecodes.size(), sourceCode, hash));
m_bytecodes.append(Bytecodes(m_bytecodes.size(), inferredName, sourceCode, hash));
return &m_bytecodes.last();
}
......@@ -57,7 +58,8 @@ Bytecodes* Database::ensureBytecodesFor(CodeBlock* codeBlock)
if (iter != m_bytecodesMap.end())
return iter->value;
Bytecodes* result = addBytecodes(codeBlock->hash(), codeBlock->sourceCodeForTools());
Bytecodes* result = addBytecodes(
codeBlock->hash(), codeBlock->inferredName(), codeBlock->sourceCodeForTools());
for (unsigned bytecodeIndex = 0; bytecodeIndex < codeBlock->instructions().size();) {
out.reset();
......
......@@ -66,7 +66,7 @@ public:
JS_EXPORT_PRIVATE bool save(const char* filename) const;
private:
Bytecodes* addBytecodes(CodeBlockHash, const String& sourceCode);
Bytecodes* addBytecodes(CodeBlockHash, const String& inferredName, const String& sourceCode);
JSGlobalData& m_globalData;
SegmentedVector<Bytecodes> m_bytecodes;
......
......@@ -60,6 +60,7 @@
macro(id) \
macro(ignoreCase) \
macro(index) \
macro(inferredName) \
macro(input) \
macro(isArray) \
macro(isPrototypeOf) \
......
2012-12-10 Filip Pizlo <fpizlo@apple.com>
JSC profiling and debug dump code should use inferred names when possible
https://bugs.webkit.org/show_bug.cgi?id=104519
Reviewed by Oliver Hunt.
The format I'm using for referring to a code block is now name#hash. For example,
v8-crypto has something called bnpSquareTo#B5QFbU. The profiler allows you to use
either the hash, the inferred name, or the combined hash and full name when referring
to blocks.
* Scripts/display-profiler-output:
2012-12-09 Filip Pizlo <fpizlo@apple.com>
Profiler should say things about OSR exits
......
......@@ -133,10 +133,11 @@ class Bytecode
end
class Bytecodes
attr_accessor :codeHash, :source, :machineInlineSites, :compilations
attr_accessor :codeHash, :inferredName, :source, :machineInlineSites, :compilations
def initialize(json)
@codeHash = json["hash"].to_s
@inferredName = json["inferredName"].to_s
@source = json["sourceCode"].to_s
@bytecode = {}
json["bytecode"].each {
......@@ -148,6 +149,28 @@ class Bytecodes
@compilations = []
end
def name(limit)
if to_s.size > limit
"\##{@codeHash}"
else
to_s
end
end
def to_s
"#{@inferredName}\##{@codeHash}"
end
def matches(pattern)
if pattern =~ /^#/
$~.post_match == @codeHash
elsif pattern =~ /#/
pattern == to_s
else
pattern == @inferredName or pattern == @codeHash
end
end
def each
@bytecode.values.sort{|a, b| a.bytecodeIndex <=> b.bytecodeIndex}.each {
| value |
......@@ -318,7 +341,7 @@ class Compilation
end
def to_s
"\##{bytecode.codeHash}-#{compilationIndex}-#{engine}"
"#{bytecode}-#{compilationIndex}-#{engine}"
end
end
......@@ -388,15 +411,7 @@ def center(str, chars)
end
def mayBeHash(hash)
hash =~ /^#/ or hash.size == 6
end
def getHash(hash)
if hash =~ /^#/
$~.post_match
else
hash
end
hash =~ /#/ or hash.size == 6
end
def sourceOnOneLine(source, limit)
......@@ -410,7 +425,7 @@ end
def summary(mode)
remaining = screenWidth
hashCols = 11
hashCols = 20
remaining -= hashCols + 1
countCols = 9 * $engines.size
......@@ -460,7 +475,7 @@ def summary(mode)
b.totalMaxTopExecutionCount <=> a.totalMaxTopExecutionCount
}.each {
| bytecode |
print(center("#" + bytecode.codeHash, hashCols) + " " +
print(center(bytecode.name(hashCols), hashCols) + " " +
center($engines.map {
| engine |
bytecode.maxTopExecutionCount(engine).to_s
......@@ -507,7 +522,7 @@ def executeCommand(*commandArray)
end
$bytecodes.each {
| bytecode |
if bytecode.codeHash == args[0]
if bytecode.matches(args[0])
puts bytecode.source
end
}
......@@ -526,12 +541,12 @@ def executeCommand(*commandArray)
pad += 1
end
puts(center("Source Counts", countCols) + " " + center("Machine Counts", machineCols) +
(" " * pad) + center("Bytecode for #{hash}", screenWidth - pad - countCols - 1 - machineCols))
puts(center("Base/DFG", countCols) + " " + center("Base/DFG", countCols))
$bytecodes.each {
| bytecodes |
next if bytecodes.codeHash != hash
next unless bytecodes.matches(hash)
puts(center("Source Counts", countCols) + " " + center("Machine Counts", machineCols) +
(" " * pad) + center("Bytecode for #{bytecodes}", screenWidth - pad - countCols - 1 - machineCols))
puts(center("Base/DFG", countCols) + " " + center("Base/DFG", countCols))
bytecodes.each {
| bytecode |
if bytecode.shouldHaveCounts?
......@@ -565,7 +580,7 @@ def executeCommand(*commandArray)
$bytecodes.each {
| bytecodes |
next if bytecodes.codeHash != hash
next unless bytecodes.matches(hash)
# FIXME: print something useful to say more about which code block this is.
......@@ -601,7 +616,7 @@ def executeCommand(*commandArray)
def originToPrintStack(origin)
(0...(origin.size - 1)).map {
| index |
"bc\##{origin[index].bytecodeIndex} --> \##{origin[index + 1].bytecodes.codeHash}"
"bc\##{origin[index].bytecodeIndex} --> #{origin[index + 1].bytecodes}"
}
end
......@@ -674,15 +689,13 @@ def executeCommand(*commandArray)
engine = trueEngine
end
hash = getHash(hash)
actualCountCols = 13
sourceCountCols = 10 * $engines.size
first = true
$compilations.each {
| compilation |
next if compilation.bytecode.codeHash != hash
next unless compilation.bytecode.matches(hash)
next if engine and compilation.engine != engine
next if compilationIndex and compilation.compilationIndex != compilationIndex
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment