Commit 806b5821 authored by fpizlo@apple.com's avatar fpizlo@apple.com

Rationalize closure call heuristics and profiling

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

Source/JavaScriptCore: 

Reviewed by Oliver Hunt.
        
Did a number of things:
        
- CallLinkInfo now remembers if it was ever a closure call, and CallLinkStatus uses
  this. Reduces the likelihood that we will inline a closure call as if it was a
  normal call.
        
- Made InlineCallFrame print inferred function names, and refactored
  CodeBlock::inferredName() to better use FunctionExecutable's API.
        
- Made bytecode dumping print frequent exit sites that led to recompilation.
        
- Made bytecode dumping for op_call and op_construct print what the CallLinkStatus
  saw.
        
* bytecode/CallLinkInfo.h:
(JSC::CallLinkInfo::CallLinkInfo):
(CallLinkInfo):
* bytecode/CallLinkStatus.cpp:
(JSC::CallLinkStatus::computeFor):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::inferredName):
(JSC::CodeBlock::dumpBytecodeCommentAndNewLine):
(JSC::CodeBlock::printCallOp):
* bytecode/CodeOrigin.cpp:
(JSC::CodeOrigin::dump):
(JSC::InlineCallFrame::inferredName):
(JSC):
(JSC::InlineCallFrame::dumpBriefFunctionInformation):
(JSC::InlineCallFrame::dump):
* bytecode/CodeOrigin.h:
(InlineCallFrame):
* bytecode/DFGExitProfile.cpp:
(JSC::DFG::ExitProfile::exitSitesFor):
(DFG):
* bytecode/DFGExitProfile.h:
(ExitProfile):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):

Source/WTF: 

Reviewed by Oliver Hunt.
        
Add a macro to add a method to a class that returns a dumper. Allows you to have
secondary dump() methods for dumping either more or less information.

* wtf/PrintStream.h:
(WTF):

Tools: 

Reviewed by Oliver Hunt.
        
Add ability to use display-profiler-output via a pipe, and add the ability to dump
all generated code ('display *' or 'd *').

* Scripts/display-profiler-output:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@139021 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b7dbb73d
2013-01-07 Filip Pizlo <fpizlo@apple.com>
Rationalize closure call heuristics and profiling
https://bugs.webkit.org/show_bug.cgi?id=106270
Reviewed by Oliver Hunt.
Did a number of things:
- CallLinkInfo now remembers if it was ever a closure call, and CallLinkStatus uses
this. Reduces the likelihood that we will inline a closure call as if it was a
normal call.
- Made InlineCallFrame print inferred function names, and refactored
CodeBlock::inferredName() to better use FunctionExecutable's API.
- Made bytecode dumping print frequent exit sites that led to recompilation.
- Made bytecode dumping for op_call and op_construct print what the CallLinkStatus
saw.
* bytecode/CallLinkInfo.h:
(JSC::CallLinkInfo::CallLinkInfo):
(CallLinkInfo):
* bytecode/CallLinkStatus.cpp:
(JSC::CallLinkStatus::computeFor):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::inferredName):
(JSC::CodeBlock::dumpBytecodeCommentAndNewLine):
(JSC::CodeBlock::printCallOp):
* bytecode/CodeOrigin.cpp:
(JSC::CodeOrigin::dump):
(JSC::InlineCallFrame::inferredName):
(JSC):
(JSC::InlineCallFrame::dumpBriefFunctionInformation):
(JSC::InlineCallFrame::dump):
* bytecode/CodeOrigin.h:
(InlineCallFrame):
* bytecode/DFGExitProfile.cpp:
(JSC::DFG::ExitProfile::exitSitesFor):
(DFG):
* bytecode/DFGExitProfile.h:
(ExitProfile):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
2013-01-07 Ryosuke Niwa <rniwa@webkit.org>
Sorted the xcodeproj file.
......
......@@ -57,6 +57,7 @@ struct CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> {
CallLinkInfo()
: hasSeenShouldRepatch(false)
, isDFG(false)
, hasSeenClosure(false)
, callType(None)
{
}
......@@ -80,7 +81,8 @@ struct CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> {
RefPtr<ClosureCallStubRoutine> stub;
bool hasSeenShouldRepatch : 1;
bool isDFG : 1;
CallType callType : 6;
bool hasSeenClosure : 1;
CallType callType : 5;
unsigned calleeGPR : 8;
CodeOrigin codeOrigin;
......
......@@ -112,6 +112,9 @@ CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned byt
JSFunction* target = callLinkInfo.lastSeenCallee.get();
if (!target)
return computeFromLLInt(profiledBlock, bytecodeIndex);
if (callLinkInfo.hasSeenClosure)
return CallLinkStatus(target->executable(), target->structure());
return CallLinkStatus(target);
#else
......
......@@ -31,6 +31,7 @@
#include "CodeBlock.h"
#include "BytecodeGenerator.h"
#include "CallLinkStatus.h"
#include "DFGCapabilities.h"
#include "DFGCommon.h"
#include "DFGNode.h"
......@@ -48,6 +49,7 @@
#include "RepatchBuffer.h"
#include "SlotVisitorInlines.h"
#include <stdio.h>
#include <wtf/CommaPrinter.h>
#include <wtf/StringExtras.h>
#include <wtf/StringPrintStream.h>
#include <wtf/UnusedParam.h>
......@@ -72,7 +74,7 @@ String CodeBlock::inferredName() const
case EvalCode:
return "<eval>";
case FunctionCode:
return jsCast<FunctionExecutable*>(ownerExecutable())->unlinkedExecutable()->inferredName().string();
return jsCast<FunctionExecutable*>(ownerExecutable())->inferredName().string();
default:
CRASH();
return String();
......@@ -155,6 +157,15 @@ static CString idName(int id0, const Identifier& ident)
void CodeBlock::dumpBytecodeCommentAndNewLine(PrintStream& out, int location)
{
#if ENABLE(DFG_JIT)
Vector<FrequentExitSite> exitSites = exitProfile().exitSitesFor(location);
if (!exitSites.isEmpty()) {
out.print(" !! frequent exits: ");
CommaPrinter comma;
for (unsigned i = 0; i < exitSites.size(); ++i)
out.print(comma, exitSites[i].kind());
}
#endif // ENABLE(DFG_JIT)
#if ENABLE(BYTECODE_COMMENTS)
const char* comment = commentForBytecodeOffset(location);
if (comment)
......@@ -473,6 +484,7 @@ void CodeBlock::printCallOp(PrintStream& out, ExecState* exec, int location, con
out.printf(" jit(%p, exec %p)", target, target->executable());
}
#endif
out.print(" status(", CallLinkStatus::computeFor(this, location), ")");
}
it += 2;
}
......
......@@ -62,8 +62,11 @@ void CodeOrigin::dump(PrintStream& out) const
if (i)
out.print(" --> ");
if (InlineCallFrame* frame = stack[i].inlineCallFrame)
out.print("#", frame->hash(), ":<", RawPointer(frame->executable.get()), "> ");
if (InlineCallFrame* frame = stack[i].inlineCallFrame) {
out.print(frame->briefFunctionInformation(), ":<", RawPointer(frame->executable.get()), "> ");
if (frame->isClosureCall())
out.print("(closure) ");
}
out.print("bc#", stack[i].bytecodeIndex);
}
......@@ -74,18 +77,29 @@ CodeBlockHash InlineCallFrame::hash() const
return executable->hashFor(specializationKind());
}
String InlineCallFrame::inferredName() const
{
return jsCast<FunctionExecutable*>(executable.get())->inferredName().string();
}
CodeBlock* InlineCallFrame::baselineCodeBlock() const
{
return jsCast<FunctionExecutable*>(executable.get())->baselineCodeBlockFor(specializationKind());
}
void InlineCallFrame::dumpBriefFunctionInformation(PrintStream& out) const
{
out.print(inferredName(), "#", hash());
}
void InlineCallFrame::dump(PrintStream& out) const
{
out.print("#", hash(), ":<", RawPointer(executable.get()), ", bc#", caller.bytecodeIndex, ", ", specializationKind());
out.print(briefFunctionInformation(), ":<", RawPointer(executable.get()), ", bc#", caller.bytecodeIndex, ", ", specializationKind());
if (callee)
out.print(", known callee: ", JSValue(callee.get()));
else
out.print(", closure call");
out.print(", numArgs+this = ", arguments.size());
out.print(", stack >= r", stackOffset);
out.print(">");
}
......
......@@ -110,11 +110,15 @@ struct InlineCallFrame {
bool isClosureCall() const { return !callee; }
String inferredName() const;
CodeBlockHash hash() const;
CodeBlock* baselineCodeBlock() const;
void dumpBriefFunctionInformation(PrintStream&) const;
void dump(PrintStream&) const;
MAKE_PRINT_METHOD(InlineCallFrame, dumpBriefFunctionInformation, briefFunctionInformation);
};
struct CodeOriginAtCallReturnOffset {
......
......@@ -55,6 +55,21 @@ bool ExitProfile::add(const FrequentExitSite& site)
return true;
}
Vector<FrequentExitSite> ExitProfile::exitSitesFor(unsigned bytecodeIndex)
{
Vector<FrequentExitSite> result;
if (!m_frequentExitSites)
return result;
for (unsigned i = 0; i < m_frequentExitSites->size(); ++i) {
if (m_frequentExitSites->at(i).bytecodeOffset() == bytecodeIndex)
result.append(m_frequentExitSites->at(i));
}
return result;
}
QueryableExitProfile::QueryableExitProfile(const ExitProfile& profile)
{
if (!profile.m_frequentExitSites)
......
......@@ -129,6 +129,10 @@ public:
// anyway.
bool add(const FrequentExitSite&);
// Get the frequent exit sites for a bytecode index. This is O(n), and is
// meant to only be used from debugging/profiling code.
Vector<FrequentExitSite> exitSitesFor(unsigned bytecodeIndex);
private:
friend class QueryableExitProfile;
......
......@@ -2222,6 +2222,7 @@ DEFINE_STUB_FUNCTION(void*, vm_lazyLinkClosureCall)
if (shouldLink) {
ASSERT(codePtr);
JIT::compileClosureCall(globalData, callLinkInfo, callerCodeBlock, calleeCodeBlock, structure, executable, codePtr);
callLinkInfo->hasSeenClosure = true;
} else
JIT::linkSlowCall(callerCodeBlock, callLinkInfo);
......
2013-01-07 Filip Pizlo <fpizlo@apple.com>
Rationalize closure call heuristics and profiling
https://bugs.webkit.org/show_bug.cgi?id=106270
Reviewed by Oliver Hunt.
Add a macro to add a method to a class that returns a dumper. Allows you to have
secondary dump() methods for dumping either more or less information.
* wtf/PrintStream.h:
(WTF):
2013-01-07 Ryosuke Niwa <rniwa@webkit.org>
Sorted the xcodeproj file.
......
......@@ -258,9 +258,13 @@ void printInternal(PrintStream& out, const T& value)
m_value.method(out); \
} \
private: \
Type m_value; \
const Type& m_value; \
}
#define MAKE_PRINT_METHOD(Type, dumpMethod, method) \
MAKE_PRINT_METHOD_ADAPTOR(DumperFor_##method, Type, dumpMethod); \
DumperFor_##method method() const { return DumperFor_##method(*this); }
// Use an adaptor-based dumper for characters to avoid situations where
// you've "compressed" an integer to a character and it ends up printing
// as ASCII when you wanted it to print as a number.
......
2013-01-07 Filip Pizlo <fpizlo@apple.com>
Rationalize closure call heuristics and profiling
https://bugs.webkit.org/show_bug.cgi?id=106270
Reviewed by Oliver Hunt.
Add ability to use display-profiler-output via a pipe, and add the ability to dump
all generated code ('display *' or 'd *').
* Scripts/display-profiler-output:
2013-01-07 Ryosuke Niwa <rniwa@webkit.org>
Sorted more xcodeproj files.
......
......@@ -460,7 +460,11 @@ def sourceOnOneLine(source, limit)
end
def screenWidth
HighLine::SystemExtensions.terminal_size[0]
if $stdin.tty?
HighLine::SystemExtensions.terminal_size[0]
else
200
end
end
def summary(mode)
......@@ -763,7 +767,11 @@ def executeCommand(*commandArray)
case args.length
when 1
hash = args[0]
if args[0] == "*"
hash = nil
else
hash = args[0]
end
engine = nil
when 2
if mayBeHash(args[0])
......@@ -778,7 +786,7 @@ def executeCommand(*commandArray)
return
end
if hash =~ /-([0-9]+)-/
if hash and hash =~ /-([0-9]+)-/
hash = $~.pre_match
engine = $~.post_match
compilationIndex = $1.to_i
......@@ -807,7 +815,7 @@ def executeCommand(*commandArray)
first = true
$compilations.each {
| compilation |
next unless compilation.bytecode.matches(hash)
next if hash and not compilation.bytecode.matches(hash)
next if engine and compilation.engine != engine
next if compilationIndex and compilation.compilationIndex != compilationIndex
......@@ -899,7 +907,9 @@ def executeCommand(*commandArray)
end
end
executeCommand("full")
if $stdin.tty?
executeCommand("full")
end
while commandLine = Readline.readline("> ", true)
executeCommand(*commandLine.split)
......
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