Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (103383 => 103384)
--- trunk/Source/_javascript_Core/ChangeLog 2011-12-21 02:02:19 UTC (rev 103383)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-12-21 02:29:15 UTC (rev 103384)
@@ -1,3 +1,32 @@
+2011-12-20 Filip Pizlo <fpi...@apple.com>
+
+ Value Profiles for arguments should be more easily accessible to the interpreter
+ https://bugs.webkit.org/show_bug.cgi?id=74984
+ <rdar://problem/10611364>
+
+ Reviewed by Gavin Barraclough.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::stronglyVisitStrongReferences):
+ (JSC::CodeBlock::shouldOptimizeNow):
+ (JSC::CodeBlock::dumpValueProfiles):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::setArgumentValueProfileSize):
+ (JSC::CodeBlock::numberOfArgumentValueProfiles):
+ (JSC::CodeBlock::valueProfileForArgument):
+ (JSC::CodeBlock::addValueProfile):
+ (JSC::CodeBlock::valueProfile):
+ (JSC::CodeBlock::valueProfileForBytecodeOffset):
+ (JSC::CodeBlock::totalNumberOfValueProfiles):
+ (JSC::CodeBlock::getFromAllValueProfiles):
+ * bytecode/ValueProfile.h:
+ (JSC::ValueProfile::ValueProfile):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompile):
+ * jit/JIT.h:
+ * jit/JITInlineMethods.h:
+ (JSC::JIT::emitValueProfilingSite):
+
2011-12-20 Gavin Barraclough <barraclo...@apple.com>
JSC shell should accept utf8 input.
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (103383 => 103384)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2011-12-21 02:02:19 UTC (rev 103383)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2011-12-21 02:29:15 UTC (rev 103384)
@@ -1835,6 +1835,8 @@
#endif
#if ENABLE(VALUE_PROFILER)
+ for (unsigned profileIndex = 0; profileIndex < numberOfArgumentValueProfiles(); ++profileIndex)
+ valueProfileForArgument(profileIndex)->computeUpdatedPrediction();
for (unsigned profileIndex = 0; profileIndex < numberOfValueProfiles(); ++profileIndex)
valueProfile(profileIndex)->computeUpdatedPrediction();
#endif
@@ -2206,11 +2208,10 @@
if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay)
return true;
- unsigned numberOfNonArgumentValueProfiles = 0;
unsigned numberOfLiveNonArgumentValueProfiles = 0;
unsigned numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
- for (unsigned i = 0; i < numberOfValueProfiles(); ++i) {
- ValueProfile* profile = ""
+ for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
+ ValueProfile* profile = ""
unsigned numSamples = profile->totalNumberOfSamples();
if (numSamples > ValueProfile::numberOfBuckets)
numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
@@ -2219,18 +2220,17 @@
profile->computeUpdatedPrediction();
continue;
}
- numberOfNonArgumentValueProfiles++;
if (profile->numberOfSamples() || profile->m_prediction != PredictNone)
numberOfLiveNonArgumentValueProfiles++;
profile->computeUpdatedPrediction();
}
#if ENABLE(JIT_VERBOSE_OSR)
- printf("Profile hotness: %lf, %lf\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles, (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles());
+ printf("Profile hotness: %lf, %lf\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles());
#endif
- if ((!numberOfNonArgumentValueProfiles || (double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles >= Options::desiredProfileLivenessRate)
- && (!numberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles() >= Options::desiredProfileFullnessRate)
+ if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate)
+ && (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() >= Options::desiredProfileFullnessRate)
&& static_cast<unsigned>(m_optimizationDelayCounter) + 1 >= Options::minimumOptimizationDelay)
return true;
@@ -2267,8 +2267,8 @@
void CodeBlock::dumpValueProfiles()
{
fprintf(stderr, "ValueProfile for %p:\n", this);
- for (unsigned i = 0; i < numberOfValueProfiles(); ++i) {
- ValueProfile* profile = ""
+ for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
+ ValueProfile* profile = ""
if (profile->m_bytecodeOffset < 0) {
ASSERT(profile->m_bytecodeOffset == -1);
fprintf(stderr, " arg = %u: ", i);
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (103383 => 103384)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2011-12-21 02:02:19 UTC (rev 103383)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2011-12-21 02:29:15 UTC (rev 103384)
@@ -657,28 +657,52 @@
#endif
#if ENABLE(VALUE_PROFILER)
+ void setArgumentValueProfileSize(unsigned size)
+ {
+ m_argumentValueProfiles.resize(size);
+ }
+ unsigned numberOfArgumentValueProfiles()
+ {
+ return m_argumentValueProfiles.size();
+ }
+ ValueProfile* valueProfileForArgument(unsigned argumentIndex)
+ {
+ ValueProfile* result = &m_argumentValueProfiles[argumentIndex];
+ ASSERT(result->m_bytecodeOffset == -1);
+ return result;
+ }
+
ValueProfile* addValueProfile(int bytecodeOffset)
{
+ ASSERT(bytecodeOffset != -1);
m_valueProfiles.append(ValueProfile(bytecodeOffset));
return &m_valueProfiles.last();
}
unsigned numberOfValueProfiles() { return m_valueProfiles.size(); }
- ValueProfile* valueProfile(int index) { return &m_valueProfiles[index]; }
- ValueProfile* valueProfileForBytecodeOffset(int bytecodeOffset)
+ ValueProfile* valueProfile(int index)
{
- return WTF::genericBinarySearch<ValueProfile, int, getValueProfileBytecodeOffset>(m_valueProfiles, m_valueProfiles.size(), bytecodeOffset);
+ ValueProfile* result = &m_valueProfiles[index];
+ ASSERT(result->m_bytecodeOffset != -1);
+ return result;
}
- ValueProfile* valueProfileForArgument(int argument)
+ ValueProfile* valueProfileForBytecodeOffset(int bytecodeOffset)
{
- size_t index = argument;
- if (index >= m_valueProfiles.size())
- return 0;
- ValueProfile* result = valueProfile(index);
- if (result->m_bytecodeOffset != -1)
- return 0;
+ ValueProfile* result = WTF::genericBinarySearch<ValueProfile, int, getValueProfileBytecodeOffset>(m_valueProfiles, m_valueProfiles.size(), bytecodeOffset);
+ ASSERT(result->m_bytecodeOffset != -1);
return result;
}
+ unsigned totalNumberOfValueProfiles()
+ {
+ return numberOfArgumentValueProfiles() + numberOfValueProfiles();
+ }
+ ValueProfile* getFromAllValueProfiles(unsigned index)
+ {
+ if (index < numberOfArgumentValueProfiles())
+ return valueProfileForArgument(index);
+ return valueProfile(index - numberOfArgumentValueProfiles());
+ }
+
RareCaseProfile* addRareCaseProfile(int bytecodeOffset)
{
m_rareCaseProfiles.append(RareCaseProfile(bytecodeOffset));
@@ -1251,6 +1275,7 @@
DFG::ExitProfile m_exitProfile;
#endif
#if ENABLE(VALUE_PROFILER)
+ Vector<ValueProfile> m_argumentValueProfiles;
SegmentedVector<ValueProfile, 8> m_valueProfiles;
SegmentedVector<RareCaseProfile, 8> m_rareCaseProfiles;
SegmentedVector<RareCaseProfile, 8> m_specialFastCaseProfiles;
Modified: trunk/Source/_javascript_Core/bytecode/ValueProfile.h (103383 => 103384)
--- trunk/Source/_javascript_Core/bytecode/ValueProfile.h 2011-12-21 02:02:19 UTC (rev 103383)
+++ trunk/Source/_javascript_Core/bytecode/ValueProfile.h 2011-12-21 02:29:15 UTC (rev 103384)
@@ -44,6 +44,15 @@
static const unsigned bucketIndexMask = numberOfBuckets - 1;
static const unsigned totalNumberOfBuckets = numberOfBuckets + numberOfSpecFailBuckets;
+ ValueProfile()
+ : m_bytecodeOffset(-1)
+ , m_prediction(PredictNone)
+ , m_numberOfSamplesInPrediction(0)
+ {
+ for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
+ m_buckets[i] = JSValue::encode(JSValue());
+ }
+
ValueProfile(int bytecodeOffset)
: m_bytecodeOffset(bytecodeOffset)
, m_prediction(PredictNone)
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (103383 => 103384)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2011-12-21 02:02:19 UTC (rev 103383)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2011-12-21 02:29:15 UTC (rev 103384)
@@ -557,21 +557,20 @@
#if ENABLE(VALUE_PROFILER)
ASSERT(m_bytecodeOffset == (unsigned)-1);
if (shouldEmitProfiling()) {
+ m_codeBlock->setArgumentValueProfileSize(m_codeBlock->m_numParameters);
for (int argument = 0; argument < m_codeBlock->m_numParameters; ++argument) {
// If this is a constructor, then we want to put in a dummy profiling site (to
// keep things consistent) but we don't actually want to record the dummy value.
if (m_codeBlock->m_isConstructor && !argument)
- m_codeBlock->addValueProfile(-1);
- else {
- int offset = CallFrame::argumentOffsetIncludingThis(argument) * static_cast<int>(sizeof(Register));
+ continue;
+ int offset = CallFrame::argumentOffsetIncludingThis(argument) * static_cast<int>(sizeof(Register));
#if USE(JSVALUE64)
- loadPtr(Address(callFrameRegister, offset), regT0);
+ loadPtr(Address(callFrameRegister, offset), regT0);
#elif USE(JSVALUE32_64)
- load32(Address(callFrameRegister, offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
- load32(Address(callFrameRegister, offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+ load32(Address(callFrameRegister, offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+ load32(Address(callFrameRegister, offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
#endif
- emitValueProfilingSite(FirstProfilingSite);
- }
+ emitValueProfilingSite(m_codeBlock->valueProfileForArgument(argument));
}
}
#endif
Modified: trunk/Source/_javascript_Core/jit/JIT.h (103383 => 103384)
--- trunk/Source/_javascript_Core/jit/JIT.h 2011-12-21 02:02:19 UTC (rev 103383)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2011-12-21 02:29:15 UTC (rev 103384)
@@ -337,6 +337,7 @@
#if ENABLE(VALUE_PROFILER)
// This assumes that the value to profile is in regT0 and that regT3 is available for
// scratch.
+ void emitValueProfilingSite(ValueProfile*);
void emitValueProfilingSite(ValueProfilingSiteKind);
#else
void emitValueProfilingSite(ValueProfilingSiteKind) { }
Modified: trunk/Source/_javascript_Core/jit/JITInlineMethods.h (103383 => 103384)
--- trunk/Source/_javascript_Core/jit/JITInlineMethods.h 2011-12-21 02:02:19 UTC (rev 103383)
+++ trunk/Source/_javascript_Core/jit/JITInlineMethods.h 2011-12-21 02:29:15 UTC (rev 103384)
@@ -448,27 +448,17 @@
}
#if ENABLE(VALUE_PROFILER)
-inline void JIT::emitValueProfilingSite(ValueProfilingSiteKind siteKind)
+inline void JIT::emitValueProfilingSite(ValueProfile* valueProfile)
{
- if (!shouldEmitProfiling())
- return;
-
+ ASSERT(shouldEmitProfiling());
+ ASSERT(valueProfile);
+
const RegisterID value = regT0;
#if USE(JSVALUE32_64)
const RegisterID valueTag = regT1;
#endif
const RegisterID scratch = regT3;
- ValueProfile* valueProfile;
- if (siteKind == FirstProfilingSite)
- valueProfile = m_codeBlock->addValueProfile(m_bytecodeOffset);
- else {
- ASSERT(siteKind == SubsequentProfilingSite);
- valueProfile = m_codeBlock->valueProfileForBytecodeOffset(m_bytecodeOffset);
- }
-
- ASSERT(valueProfile);
-
if (ValueProfile::numberOfBuckets == 1) {
// We're in a simple configuration: only one bucket, so we can just do a direct
// store.
@@ -495,6 +485,22 @@
store32(valueTag, BaseIndex(scratch, bucketCounterRegister, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
#endif
}
+
+inline void JIT::emitValueProfilingSite(ValueProfilingSiteKind siteKind)
+{
+ if (!shouldEmitProfiling())
+ return;
+
+ ValueProfile* valueProfile;
+ if (siteKind == FirstProfilingSite)
+ valueProfile = m_codeBlock->addValueProfile(m_bytecodeOffset);
+ else {
+ ASSERT(siteKind == SubsequentProfilingSite);
+ valueProfile = m_codeBlock->valueProfileForBytecodeOffset(m_bytecodeOffset);
+ }
+
+ emitValueProfilingSite(valueProfile);
+}
#endif
#if USE(JSVALUE32_64)