Support the type profiler in the DFG
https://bugs.webkit.org/show_bug.cgi?id=136712
Reviewed by Filip Pizlo.
This patch implements op_profile_type inside the DFG as the node: ProfileType.
The DFG will convert the ProfileType node into a Check node in the cases where
passing a type check is equivalent to writing to the TypeProfilerLog. This
gives the DFG the potential to optimize out multiple ProfileType nodes into
a single Check node.
When the DFG doesn't convert ProfileType into a Check node, it will generate
the same inline code as the baseline JIT does for writing an entry to the
TypeProfilerLog.
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGDriver.cpp:
(JSC::DFG::compileImpl):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNode.h:
(JSC::DFG::Node::typeLocation):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* runtime/TypeProfiler.cpp:
(JSC::TypeProfiler::logTypesForTypeLocation):
* runtime/TypeSet.cpp:
(JSC::TypeSet::dumpTypes):
(JSC::TypeSet::doesTypeConformTo):
Make this method public so others can reason about the types a TypeSet has seen.
(JSC::TypeSet::seenTypes): Deleted.
(JSC::TypeSet::dumpSeenTypes): Deleted.
Renamed to dumpTypes so the method seenTypes can be used as a public getter.
* runtime/TypeSet.h:
(JSC::TypeSet::seenTypes):
* tests/typeProfiler/dfg-jit-optimizations.js: Added.
(tierUpToDFG):
(funcs):
(.return):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@174167 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 498ef09..0b9501a 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -34,6 +34,7 @@
#include "DFGPredictionPropagationPhase.h"
#include "DFGVariableAccessDataDump.h"
#include "JSCInlines.h"
+#include "TypeLocation.h"
namespace JSC { namespace DFG {
@@ -1114,6 +1115,38 @@
fixEdge<KnownInt32Use>(node->child1());
break;
}
+ case ProfileType: {
+ // We want to insert type checks based on the instructionTypeSet of the TypeLocation, not the globalTypeSet.
+ // Because the instructionTypeSet is contained in globalTypeSet, if we produce a type check for
+ // type T for the instructionTypeSet, the global type set must also have information for type T.
+ // So if it the type check succeeds for type T in the instructionTypeSet, a type check for type T
+ // in the globalTypeSet would've also succeeded.
+ // (The other direction does not hold in general).
+
+ RefPtr<TypeSet> typeSet = node->typeLocation()->m_instructionTypeSet;
+ uint32_t seenTypes = typeSet->seenTypes();
+ if (typeSet->doesTypeConformTo(TypeMachineInt)) {
+ node->convertToCheck();
+ if (node->child1()->shouldSpeculateInt32())
+ fixEdge<Int32Use>(node->child1());
+ else
+ fixEdge<MachineIntUse>(node->child1());
+ } else if (typeSet->doesTypeConformTo(TypeNumber | TypeMachineInt)) {
+ node->convertToCheck();
+ fixEdge<NumberUse>(node->child1());
+ } else if (typeSet->doesTypeConformTo(TypeString)) {
+ node->convertToCheck();
+ fixEdge<StringUse>(node->child1());
+ } else if (typeSet->doesTypeConformTo(TypeBoolean)) {
+ node->convertToCheck();
+ fixEdge<BooleanUse>(node->child1());
+ } else if (typeSet->doesTypeConformTo(TypeUndefined | TypeNull) && (seenTypes & TypeUndefined) && (seenTypes & TypeNull)) {
+ node->convertToCheck();
+ fixEdge<OtherUse>(node->child1());
+ }
+
+ break;
+ }
#if !ASSERT_DISABLED
// Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.