Commit 77ef0e33 authored by fpizlo@apple.com's avatar fpizlo@apple.com

Profiler should show bytecode dumps as they would have been visible to the...

Profiler should show bytecode dumps as they would have been visible to the JITs, including the profiling data that the JITs would see
https://bugs.webkit.org/show_bug.cgi?id=104647

Reviewed by Oliver Hunt.

Source/JavaScriptCore: 

Adds more profiling data to bytecode dumps, and adds the ability to do a secondary
bytecode dump for each JIT compilation of a code block. This is relevant because both
the bytecodes, and the profiling data, may change after some number of executions.
        
Also fixes some random dumping code to use PrintStream& rather than
static const char[thingy].

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/ArrayProfile.cpp:
(JSC::dumpArrayModes):
(JSC::ArrayProfile::briefDescription):
* bytecode/ArrayProfile.h:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printGetByIdOp):
(JSC::CodeBlock::printGetByIdCacheStatus):
(JSC::CodeBlock::printCallOp):
(JSC::CodeBlock::dumpValueProfiling):
(JSC::CodeBlock::dumpArrayProfiling):
(JSC::CodeBlock::dumpBytecode):
* bytecode/CodeBlock.h:
* bytecode/ValueProfile.h:
(JSC::ValueProfileBase::briefDescription):
* dfg/DFGAbstractValue.h:
(JSC::DFG::AbstractValue::dump):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseCodeBlock):
* jit/JIT.cpp:
(JSC::JIT::privateCompile):
* profiler/ProfilerBytecodeSequence.cpp: Added.
(JSC::Profiler::BytecodeSequence::BytecodeSequence):
(JSC::Profiler::BytecodeSequence::~BytecodeSequence):
(JSC::Profiler::BytecodeSequence::indexForBytecodeIndex):
(JSC::Profiler::BytecodeSequence::forBytecodeIndex):
(JSC::Profiler::BytecodeSequence::addSequenceProperties):
* profiler/ProfilerBytecodeSequence.h: Added.
(JSC::Profiler::BytecodeSequence::size):
(JSC::Profiler::BytecodeSequence::at):
* profiler/ProfilerBytecodes.cpp:
(JSC::Profiler::Bytecodes::Bytecodes):
(JSC::Profiler::Bytecodes::toJS):
* profiler/ProfilerBytecodes.h:
(JSC::Profiler::Bytecodes::instructionCount):
* profiler/ProfilerCompilation.cpp:
(JSC::Profiler::Compilation::addProfiledBytecodes):
(JSC::Profiler::Compilation::toJS):
* profiler/ProfilerCompilation.h:
(JSC::Profiler::Compilation::profiledBytecodesSize):
(JSC::Profiler::Compilation::profiledBytecodesAt):
* profiler/ProfilerDatabase.cpp:
(JSC::Profiler::Database::ensureBytecodesFor):
* profiler/ProfilerDatabase.h:
* profiler/ProfilerProfiledBytecodes.cpp: Added.
(JSC::Profiler::ProfiledBytecodes::ProfiledBytecodes):
(JSC::Profiler::ProfiledBytecodes::~ProfiledBytecodes):
(JSC::Profiler::ProfiledBytecodes::toJS):
* profiler/ProfilerProfiledBytecodes.h: Added.
(JSC::Profiler::ProfiledBytecodes::bytecodes):
* runtime/CommonIdentifiers.h:

Tools: 

Added a "profiling" (or "p") command to show the profiling data that the JITs saw
for each JIT compilation of a code block.
        
Also added instruction counts in the "full" display and made the "full" display the
default thing you see.

* Scripts/display-profiler-output:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@137379 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 61ec48d3
......@@ -176,6 +176,7 @@ set(JavaScriptCore_SOURCES
profiler/ProfilerBytecode.cpp
profiler/ProfilerBytecode.h
profiler/ProfilerBytecodeSequence.cpp
profiler/ProfilerBytecodes.cpp
profiler/ProfilerBytecodes.h
profiler/ProfilerCompilation.cpp
......@@ -193,6 +194,7 @@ set(JavaScriptCore_SOURCES
profiler/ProfilerOriginStack.h
profiler/ProfilerOSRExit.cpp
profiler/ProfilerOSRExitSite.cpp
profiler/ProfilerProfiledBytecodes.cpp
profiler/Profile.cpp
profiler/ProfileGenerator.cpp
profiler/ProfileNode.cpp
......
2012-12-11 Filip Pizlo <fpizlo@apple.com>
Profiler should show bytecode dumps as they would have been visible to the JITs, including the profiling data that the JITs would see
https://bugs.webkit.org/show_bug.cgi?id=104647
Reviewed by Oliver Hunt.
Adds more profiling data to bytecode dumps, and adds the ability to do a secondary
bytecode dump for each JIT compilation of a code block. This is relevant because both
the bytecodes, and the profiling data, may change after some number of executions.
Also fixes some random dumping code to use PrintStream& rather than
static const char[thingy].
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/ArrayProfile.cpp:
(JSC::dumpArrayModes):
(JSC::ArrayProfile::briefDescription):
* bytecode/ArrayProfile.h:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printGetByIdOp):
(JSC::CodeBlock::printGetByIdCacheStatus):
(JSC::CodeBlock::printCallOp):
(JSC::CodeBlock::dumpValueProfiling):
(JSC::CodeBlock::dumpArrayProfiling):
(JSC::CodeBlock::dumpBytecode):
* bytecode/CodeBlock.h:
* bytecode/ValueProfile.h:
(JSC::ValueProfileBase::briefDescription):
* dfg/DFGAbstractValue.h:
(JSC::DFG::AbstractValue::dump):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseCodeBlock):
* jit/JIT.cpp:
(JSC::JIT::privateCompile):
* profiler/ProfilerBytecodeSequence.cpp: Added.
(JSC::Profiler::BytecodeSequence::BytecodeSequence):
(JSC::Profiler::BytecodeSequence::~BytecodeSequence):
(JSC::Profiler::BytecodeSequence::indexForBytecodeIndex):
(JSC::Profiler::BytecodeSequence::forBytecodeIndex):
(JSC::Profiler::BytecodeSequence::addSequenceProperties):
* profiler/ProfilerBytecodeSequence.h: Added.
(JSC::Profiler::BytecodeSequence::size):
(JSC::Profiler::BytecodeSequence::at):
* profiler/ProfilerBytecodes.cpp:
(JSC::Profiler::Bytecodes::Bytecodes):
(JSC::Profiler::Bytecodes::toJS):
* profiler/ProfilerBytecodes.h:
(JSC::Profiler::Bytecodes::instructionCount):
* profiler/ProfilerCompilation.cpp:
(JSC::Profiler::Compilation::addProfiledBytecodes):
(JSC::Profiler::Compilation::toJS):
* profiler/ProfilerCompilation.h:
(JSC::Profiler::Compilation::profiledBytecodesSize):
(JSC::Profiler::Compilation::profiledBytecodesAt):
* profiler/ProfilerDatabase.cpp:
(JSC::Profiler::Database::ensureBytecodesFor):
* profiler/ProfilerDatabase.h:
* profiler/ProfilerProfiledBytecodes.cpp: Added.
(JSC::Profiler::ProfiledBytecodes::ProfiledBytecodes):
(JSC::Profiler::ProfiledBytecodes::~ProfiledBytecodes):
(JSC::Profiler::ProfiledBytecodes::toJS):
* profiler/ProfilerProfiledBytecodes.h: Added.
(JSC::Profiler::ProfiledBytecodes::bytecodes):
* runtime/CommonIdentifiers.h:
2012-12-11 Oswald Buddenhagen <oswald.buddenhagen@digia.com>
[Qt] delete dead include paths
......
......@@ -479,6 +479,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/profiler/CallIdentifier.h \
Source/JavaScriptCore/profiler/ProfilerBytecode.cpp \
Source/JavaScriptCore/profiler/ProfilerBytecode.h \
Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp \
Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.h \
Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp \
Source/JavaScriptCore/profiler/ProfilerBytecodes.h \
Source/JavaScriptCore/profiler/ProfilerCompilation.cpp \
......@@ -498,6 +500,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/profiler/ProfilerOSRExit.h \
Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp \
Source/JavaScriptCore/profiler/ProfilerOSRExitSite.h \
Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp \
Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.h \
Source/JavaScriptCore/profiler/Profile.cpp \
Source/JavaScriptCore/profiler/ProfileGenerator.cpp \
Source/JavaScriptCore/profiler/ProfileGenerator.h \
......
......@@ -1533,6 +1533,14 @@
RelativePath="..\..\profiler\ProfilerBytecode.h"
>
</File>
<File
RelativePath="..\..\profiler\ProfilerBytecodeSequence.cpp"
>
</File>
<File
RelativePath="..\..\profiler\ProfilerBytecodeSequence.h"
>
</File>
<File
RelativePath="..\..\profiler\ProfilerBytecodes.cpp"
>
......@@ -1609,6 +1617,14 @@
RelativePath="..\..\profiler\ProfilerOSRExitSite.h"
>
</File>
<File
RelativePath="..\..\profiler\ProfilerProfiledBytecodes.cpp"
>
</File>
<File
RelativePath="..\..\profiler\ProfilerProfiledBytecodes.h"
>
</File>
<File
RelativePath="..\..\profiler\Profile.cpp"
>
......
......@@ -73,6 +73,10 @@
0F0CD4C215F1A6070032F1C0 /* PutDirectIndexMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0CD4C015F1A6040032F1C0 /* PutDirectIndexMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0CD4C415F6B6BB0032F1C0 /* SparseArrayValueMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0CD4C315F6B6B50032F1C0 /* SparseArrayValueMap.cpp */; };
0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F13912916771C33009CCB07 /* ProfilerBytecodeSequence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13912416771C30009CCB07 /* ProfilerBytecodeSequence.cpp */; };
0F13912A16771C36009CCB07 /* ProfilerBytecodeSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13912516771C30009CCB07 /* ProfilerBytecodeSequence.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */; };
0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */; };
0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F16015D156198C900C2587C /* DFGArgumentsSimplificationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16015A156198BF00C2587C /* DFGArgumentsSimplificationPhase.cpp */; };
......@@ -902,6 +906,10 @@
0F0CD4C015F1A6040032F1C0 /* PutDirectIndexMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutDirectIndexMode.h; sourceTree = "<group>"; };
0F0CD4C315F6B6B50032F1C0 /* SparseArrayValueMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SparseArrayValueMap.cpp; sourceTree = "<group>"; };
0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntCallLinkInfo.h; sourceTree = "<group>"; };
0F13912416771C30009CCB07 /* ProfilerBytecodeSequence.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerBytecodeSequence.cpp; path = profiler/ProfilerBytecodeSequence.cpp; sourceTree = "<group>"; };
0F13912516771C30009CCB07 /* ProfilerBytecodeSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerBytecodeSequence.h; path = profiler/ProfilerBytecodeSequence.h; sourceTree = "<group>"; };
0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerProfiledBytecodes.cpp; path = profiler/ProfilerProfiledBytecodes.cpp; sourceTree = "<group>"; };
0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerProfiledBytecodes.h; path = profiler/ProfilerProfiledBytecodes.h; sourceTree = "<group>"; };
0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexingType.cpp; sourceTree = "<group>"; };
0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
0F16015A156198BF00C2587C /* DFGArgumentsSimplificationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGArgumentsSimplificationPhase.cpp; path = dfg/DFGArgumentsSimplificationPhase.cpp; sourceTree = "<group>"; };
......@@ -2578,6 +2586,8 @@
0FF72993166AD347000F5BA3 /* ProfilerBytecode.h */,
0FF72994166AD347000F5BA3 /* ProfilerBytecodes.cpp */,
0FF72995166AD347000F5BA3 /* ProfilerBytecodes.h */,
0F13912416771C30009CCB07 /* ProfilerBytecodeSequence.cpp */,
0F13912516771C30009CCB07 /* ProfilerBytecodeSequence.h */,
0FF72996166AD347000F5BA3 /* ProfilerCompilation.cpp */,
0FF72997166AD347000F5BA3 /* ProfilerCompilation.h */,
0FF72998166AD347000F5BA3 /* ProfilerCompilationKind.cpp */,
......@@ -2595,6 +2605,8 @@
0FB105881675482E00F8AB6E /* ProfilerOSRExit.h */,
0FB105891675482E00F8AB6E /* ProfilerOSRExitSite.cpp */,
0FB1058A1675482E00F8AB6E /* ProfilerOSRExitSite.h */,
0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */,
0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */,
);
name = profiler;
sourceTree = "<group>";
......@@ -3165,6 +3177,8 @@
0FB1058C1675483300F8AB6E /* ProfilerOSRExit.h in Headers */,
0FB1058E1675483A00F8AB6E /* ProfilerOSRExitSite.h in Headers */,
0FF60AC216740F8300029779 /* ReduceWhitespace.h in Headers */,
0F13912A16771C36009CCB07 /* ProfilerBytecodeSequence.h in Headers */,
0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -3765,6 +3779,8 @@
0FB1058B1675483100F8AB6E /* ProfilerOSRExit.cpp in Sources */,
0FB1058D1675483700F8AB6E /* ProfilerOSRExitSite.cpp in Sources */,
0FF60AC316740F8800029779 /* ReduceWhitespace.cpp in Sources */,
0F13912916771C33009CCB07 /* ProfilerBytecodeSequence.cpp in Sources */,
0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -186,6 +186,7 @@ SOURCES += \
parser/SourceProviderCache.cpp \
profiler/ProfilerBytecode.cpp \
profiler/ProfilerBytecode.h \
profiler/ProfilerBytecodeSequence.cpp \
profiler/ProfilerBytecodes.cpp \
profiler/ProfilerBytecodes.h \
profiler/ProfilerCompilation.cpp \
......@@ -203,6 +204,7 @@ SOURCES += \
profiler/ProfilerOriginStack.h \
profiler/ProfilerOSRExit.cpp \
profiler/ProfilerOSRExitSite.cpp \
profiler/ProfilerProfiledBytecodes.cpp \
profiler/Profile.cpp \
profiler/ProfileGenerator.cpp \
profiler/ProfileNode.cpp \
......
......@@ -28,41 +28,50 @@
#include "CodeBlock.h"
#include <wtf/StringExtras.h>
#include <wtf/StringPrintStream.h>
namespace JSC {
const char* arrayModesToString(ArrayModes arrayModes)
void dumpArrayModes(PrintStream& out, ArrayModes arrayModes)
{
if (!arrayModes)
return "0:<empty>";
if (!arrayModes) {
out.print("0:<empty>");
return;
}
if (arrayModes == ALL_ARRAY_MODES)
return "TOP";
bool isNonArray = !!(arrayModes & asArrayModes(NonArray));
bool isNonArrayWithContiguous = !!(arrayModes & asArrayModes(NonArrayWithContiguous));
bool isNonArrayWithArrayStorage = !!(arrayModes & asArrayModes(NonArrayWithArrayStorage));
bool isNonArrayWithSlowPutArrayStorage = !!(arrayModes & asArrayModes(NonArrayWithSlowPutArrayStorage));
bool isArray = !!(arrayModes & asArrayModes(ArrayClass));
bool isArrayWithContiguous = !!(arrayModes & asArrayModes(ArrayWithContiguous));
bool isArrayWithArrayStorage = !!(arrayModes & asArrayModes(ArrayWithArrayStorage));
bool isArrayWithSlowPutArrayStorage = !!(arrayModes & asArrayModes(ArrayWithSlowPutArrayStorage));
if (arrayModes == ALL_ARRAY_MODES) {
out.print("TOP");
return;
}
static char result[256];
snprintf(
result, sizeof(result),
"%u:%s%s%s%s%s%s%s%s",
arrayModes,
isNonArray ? "NonArray" : "",
isNonArrayWithContiguous ? "NonArrayWithContiguous" : "",
isNonArrayWithArrayStorage ? " NonArrayWithArrayStorage" : "",
isNonArrayWithSlowPutArrayStorage ? "NonArrayWithSlowPutArrayStorage" : "",
isArray ? "ArrayClass" : "",
isArrayWithContiguous ? "ArrayWithContiguous" : "",
isArrayWithArrayStorage ? " ArrayWithArrayStorage" : "",
isArrayWithSlowPutArrayStorage ? "ArrayWithSlowPutArrayStorage" : "");
out.print(arrayModes, ":");
return result;
if (arrayModes & asArrayModes(NonArray))
out.print("NonArray");
if (arrayModes & asArrayModes(NonArrayWithInt32))
out.print("NonArrayWithInt32");
if (arrayModes & asArrayModes(NonArrayWithDouble))
out.print("NonArrayWithDouble");
if (arrayModes & asArrayModes(NonArrayWithContiguous))
out.print("NonArrayWithContiguous");
if (arrayModes & asArrayModes(NonArrayWithArrayStorage))
out.print("NonArrayWithArrayStorage");
if (arrayModes & asArrayModes(NonArrayWithSlowPutArrayStorage))
out.print("NonArrayWithSlowPutArrayStorage");
if (arrayModes & asArrayModes(ArrayClass))
out.print("ArrayClass");
if (arrayModes & asArrayModes(ArrayWithUndecided))
out.print("ArrayWithUndecided");
if (arrayModes & asArrayModes(ArrayWithInt32))
out.print("ArrayWithInt32");
if (arrayModes & asArrayModes(ArrayWithDouble))
out.print("ArrayWithDouble");
if (arrayModes & asArrayModes(ArrayWithContiguous))
out.print("ArrayWithContiguous");
if (arrayModes & asArrayModes(ArrayWithArrayStorage))
out.print("ArrayWithArrayStorage");
if (arrayModes & asArrayModes(ArrayWithSlowPutArrayStorage))
out.print("ArrayWithSlowPutArrayStorage");
}
ArrayModes ArrayProfile::updatedObservedArrayModes() const
......@@ -104,5 +113,58 @@ void ArrayProfile::computeUpdatedPrediction(CodeBlock* codeBlock, OperationInPro
}
}
CString ArrayProfile::briefDescription(CodeBlock* codeBlock)
{
computeUpdatedPrediction(codeBlock);
StringPrintStream out;
bool hasPrinted = false;
if (m_observedArrayModes) {
if (hasPrinted)
out.print(", ");
out.print(ArrayModesDump(m_observedArrayModes));
hasPrinted = true;
}
if (m_structureIsPolymorphic) {
if (hasPrinted)
out.print(", ");
out.print("struct = TOP");
hasPrinted = true;
} else if (m_expectedStructure) {
if (hasPrinted)
out.print(", ");
out.print("struct = ", RawPointer(m_expectedStructure));
hasPrinted = true;
}
if (m_mayStoreToHole) {
if (hasPrinted)
out.print(", ");
out.print("Hole");
hasPrinted = true;
}
if (m_mayInterceptIndexedAccesses) {
if (hasPrinted)
out.print(", ");
out.print("Intercept");
hasPrinted = true;
}
if (m_usesOriginalArrayStructures) {
if (hasPrinted)
out.print(", ");
out.print("Original");
hasPrinted = true;
}
UNUSED_PARAM(hasPrinted);
return out.toCString();
}
} // namespace JSC
......@@ -67,7 +67,8 @@ inline ArrayModes arrayModeFromStructure(Structure* structure)
return asArrayModes(structure->indexingType());
}
const char* arrayModesToString(ArrayModes);
void dumpArrayModes(PrintStream&, ArrayModes);
MAKE_PRINT_ADAPTOR(ArrayModesDump, ArrayModes, dumpArrayModes);
inline bool mergeArrayModes(ArrayModes& left, ArrayModes right)
{
......@@ -170,6 +171,8 @@ public:
bool usesOriginalArrayStructures() const { return m_usesOriginalArrayStructures; }
CString briefDescription(CodeBlock*);
private:
friend class LLIntOffsetsExtractor;
......
......@@ -303,7 +303,7 @@ void CodeBlock::printGetByIdOp(PrintStream& out, ExecState* exec, int location,
int r1 = (++it)->u.operand;
int id0 = (++it)->u.operand;
out.printf("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
it += 5;
it += 4; // Increment up to the value profiler.
}
#if ENABLE(JIT) || ENABLE(LLINT) // unused in some configurations
......@@ -349,8 +349,7 @@ void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int l
#if ENABLE(LLINT)
if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length)
out.printf(" llint(array_length)");
else {
Structure* structure = instruction[4].u.structure.get();
else if (Structure* structure = instruction[4].u.structure.get()) {
out.printf(" llint(");
dumpStructure(out, "struct", exec, structure, ident);
out.printf(")");
......@@ -359,11 +358,10 @@ void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int l
#if ENABLE(JIT)
if (numberOfStructureStubInfos()) {
out.printf(" jit(");
StructureStubInfo& stubInfo = getStubInfo(location);
if (!stubInfo.seen)
out.printf("not seen");
else {
if (stubInfo.seen) {
out.printf(" jit(");
Structure* baseStructure = 0;
Structure* prototypeStructure = 0;
StructureChain* chain = 0;
......@@ -449,8 +447,8 @@ void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int l
}
out.printf("]");
}
out.printf(")");
}
out.printf(")");
}
#endif
}
......@@ -469,16 +467,13 @@ void CodeBlock::printCallOp(PrintStream& out, ExecState* exec, int location, con
" llint(%p, exec %p)",
callLinkInfo->lastSeenCallee.get(),
callLinkInfo->lastSeenCallee->executable());
} else
out.printf(" llint(not set)");
}
#endif
#if ENABLE(JIT)
if (numberOfCallLinkInfos()) {
JSFunction* target = getCallLinkInfo(location).lastSeenCallee.get();
if (target)
out.printf(" jit(%p, exec %p)", target, target->executable());
else
out.printf(" jit(not set)");
}
#endif
}
......@@ -667,6 +662,32 @@ void CodeBlock::dumpBytecode(PrintStream& out)
out.printf("\n");
}
void CodeBlock::dumpValueProfiling(PrintStream& out, const Instruction*& it)
{
++it;
#if ENABLE(VALUE_PROFILER)
CString description = it->u.profile->briefDescription();
if (!description.length())
return;
out.print(" ", description);
#else
UNUSED_PARAM(out);
#endif
}
void CodeBlock::dumpArrayProfiling(PrintStream& out, const Instruction*& it)
{
++it;
#if ENABLE(VALUE_PROFILER)
CString description = it->u.arrayProfile->briefDescription(this);
if (!description.length())
return;
out.print(" ", description);
#else
UNUSED_PARAM(out);
#endif
}
void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instruction* begin, const Instruction*& it)
{
int location = it - begin;
......@@ -956,8 +977,8 @@ void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instructio
int id0 = (++it)->u.operand;
int resolveInfo = (++it)->u.operand;
out.printf("[%4d] resolve\t\t %s, %s, %d", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo);
dumpValueProfiling(out, it);
dumpBytecodeCommentAndNewLine(out, location);
it++;
break;
}
case op_init_global_const_nop: {
......@@ -998,8 +1019,8 @@ void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instructio
int resolveInfo = (++it)->u.operand;
int putToBaseInfo = (++it)->u.operand;
out.printf("[%4d] resolve_base%s\t %s, %s, %d, %d", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo);
dumpValueProfiling(out, it);
dumpBytecodeCommentAndNewLine(out, location);
it++;
break;
}
case op_ensure_property_exists: {
......@@ -1016,8 +1037,8 @@ void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instructio
int resolveInfo = (++it)->u.operand;
int putToBaseInfo = (++it)->u.operand;
out.printf("[%4d] resolve_with_base %s, %s, %s, %d, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo);
dumpValueProfiling(out, it);
dumpBytecodeCommentAndNewLine(out, location);
it++;
break;
}
case op_resolve_with_this: {
......@@ -1026,8 +1047,8 @@ void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instructio
int id0 = (++it)->u.operand;
int resolveInfo = (++it)->u.operand;
out.printf("[%4d] resolve_with_this %s, %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo);
dumpValueProfiling(out, it);
dumpBytecodeCommentAndNewLine(out, location);
it++;
break;
}
case op_get_by_id:
......@@ -1046,6 +1067,7 @@ void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instructio
case op_get_string_length: {
printGetByIdOp(out, exec, location, it);
printGetByIdCacheStatus(out, exec, location);
dumpValueProfiling(out, it);
dumpBytecodeCommentAndNewLine(out, location);
break;
}
......@@ -1112,9 +1134,9 @@ void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instructio
int r1 = (++it)->u.operand;
int r2 = (++it)->u.operand;
out.printf("[%4d] get_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
dumpArrayProfiling(out, it);
dumpValueProfiling(out, it);
dumpBytecodeCommentAndNewLine(out, location);
it++;
it++;
break;
}
case op_get_argument_by_val: {
......@@ -1122,9 +1144,9 @@ void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instructio
int r1 = (++it)->u.operand;
int r2 = (++it)->u.operand;
out.printf("[%4d] get_argument_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
dumpBytecodeCommentAndNewLine(out, location);
++it;
++it;
dumpValueProfiling(out, it);
dumpBytecodeCommentAndNewLine(out, location);
break;
}
case op_get_by_pname: {
......@@ -1143,8 +1165,8 @@ void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instructio
int r1 = (++it)->u.operand;
int r2 = (++it)->u.operand;
out.printf("[%4d] put_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
dumpArrayProfiling(out, it);
dumpBytecodeCommentAndNewLine(out, location);
++it;
break;
}
case op_del_by_val: {
......@@ -1386,8 +1408,8 @@ void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instructio
case op_call_put_result: {
int r0 = (++it)->u.operand;
out.printf("[%4d] call_put_result\t\t %s", location, registerName(exec, r0).data());
dumpValueProfiling(out, it);
dumpBytecodeCommentAndNewLine(out, location);
it++;
break;
}
case op_ret_object_or_this: {
......
......@@ -1187,6 +1187,9 @@ namespace JSC {
enum CacheDumpMode { DumpCaches, DontDumpCaches };
void printCallOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op, CacheDumpMode);
void printPutByIdOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
void dumpValueProfiling(PrintStream&, const Instruction*&);
void dumpArrayProfiling(PrintStream&, const Instruction*&);
void visitStructures(SlotVisitor&, Instruction* vPC);
#if ENABLE(DFG_JIT)
......
......@@ -39,6 +39,7 @@
#include "Structure.h"
#include "WriteBarrier.h"
#include <wtf/PrintStream.h>
#include <wtf/StringPrintStream.h>
namespace JSC {
......@@ -110,6 +111,20 @@ struct ValueProfileBase {
return false;
}
CString briefDescription()
{
computeUpdatedPrediction();
StringPrintStream out;
if (m_singletonValueIsTop)
out.print("predicting ", SpeculationDump(m_prediction));
else if (m_singletonValue)
out.print("predicting ", m_singletonValue);
return out.toCString();
}
void dump(PrintStream& out)
{
out.print("samples = ", totalNumberOfSamples(), " prediction = ", SpeculationDump(m_prediction));
......
......@@ -374,7 +374,7 @@ struct AbstractValue {
void dump(PrintStream& out) const
{
out.print(
"(", SpeculationDump(m_type), ", ", arrayModesToString(m_arrayModes), ", ",
"(", SpeculationDump(m_type), ", ", ArrayModesDump(m_arrayModes), ", ",
m_currentKnownStructure, ", ", m_futurePossibleStructure);
if (!!m_value)
out.print(", ", m_value);
......
......@@ -3666,6 +3666,11 @@ void ByteCodeParser::parseCodeBlock()
{
CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
if (m_graph.m_compilation) {
m_graph.m_compilation->addProfiledBytecodes(