Ignore:
Timestamp:
Sep 14, 2011, 4:00:26 PM (14 years ago)
Author:
[email protected]
Message:

Tiered compilation heuristics do not account for value profile fullness
https://bugs.webkit.org/show_bug.cgi?id=68116

Reviewed by Oliver Hunt.

Tiered compilation avoids invoking the DFG JIT if it finds that value
profiles contain insufficient information. Instead, it produces a
prediction from the current value profile, and then clears the value
profile. This allows the value profile to heat up from scratch for
some number of additional executions. The new profiles will then be
merged with the previous prediction. Once the amount of information
in predictions is enough according to heuristics in CodeBlock.cpp,
DFG optimization is allowed to proceed.

(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::~CodeBlock):
(JSC::CodeBlock::visitAggregate):
(JSC::CodeBlock::visitWeakReferences):
(JSC::CodeBlock::shouldOptimizeNow):
(JSC::CodeBlock::dumpValueProfiles):

  • bytecode/CodeBlock.h:
  • bytecode/PredictedType.cpp:

(JSC::predictionToString):

  • bytecode/PredictedType.h:
  • bytecode/ValueProfile.cpp: Added.

(JSC::ValueProfile::computeStatistics):
(JSC::ValueProfile::computeUpdatedPrediction):

  • bytecode/ValueProfile.h:

(JSC::ValueProfile::ValueProfile):
(JSC::ValueProfile::classInfo):
(JSC::ValueProfile::numberOfSamples):
(JSC::ValueProfile::totalNumberOfSamples):
(JSC::ValueProfile::isLive):
(JSC::ValueProfile::numberOfInt32s):
(JSC::ValueProfile::numberOfDoubles):
(JSC::ValueProfile::numberOfBooleans):
(JSC::ValueProfile::dump):
(JSC::getValueProfileBytecodeOffset):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::stronglyPredict):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::predictArgumentTypes):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::exitSpeculativeWithOSR):
(JSC::DFG::JITCompiler::jumpFromSpeculativeToNonSpeculative):

  • jit/JIT.cpp:

(JSC::JIT::emitOptimizationCheck):

  • jit/JITInlineMethods.h:

(JSC::JIT::emitValueProfilingSite):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r95016 r95134  
    14291429    , m_symbolTable(symTab)
    14301430    , m_alternative(alternative)
     1431    , m_optimizationDelayCounter(0)
    14311432{
    14321433    ASSERT(m_source);
     
    14421443{
    14431444#if ENABLE(VERBOSE_VALUE_PROFILE)
    1444     fprintf(stderr, "ValueProfile for %p:\n", this);
    1445     for (unsigned i = 0; i < numberOfValueProfiles(); ++i) {
    1446         ValueProfile* profile = valueProfile(i);
    1447         if (profile->bytecodeOffset < 0) {
    1448             ASSERT(profile->bytecodeOffset == -1);
    1449             fprintf(stderr, "   arg = %u: ", i + 1);
    1450         } else
    1451             fprintf(stderr, "   bc = %d: ", profile->bytecodeOffset);
    1452         profile->dump(stderr);
    1453         fprintf(stderr, "\n");
    1454     }
     1445    dumpValueProfiles();
    14551446#endif
    14561447   
     
    15911582       
    15921583        for (unsigned index = 0; index < ValueProfile::numberOfBuckets; ++index) {
    1593             if (!profile->buckets[index]) {
    1594                 if (!!profile->weakBuckets[index])
     1584            if (!profile->m_buckets[index]) {
     1585                if (!!profile->m_weakBuckets[index])
    15951586                    handleWeakReferences = true;
    15961587                continue;
    15971588            }
    15981589           
    1599             if (!JSValue::decode(profile->buckets[index]).isCell()) {
    1600                 profile->weakBuckets[index] = ValueProfile::WeakBucket();
     1590            if (!JSValue::decode(profile->m_buckets[index]).isCell()) {
     1591                profile->m_weakBuckets[index] = ValueProfile::WeakBucket();
    16011592                continue;
    16021593            }
     
    16181609       
    16191610        for (unsigned index = 0; index < ValueProfile::numberOfBuckets; ++index) {
    1620             if (!!profile->buckets[index]) {
    1621                 JSValue value = JSValue::decode(profile->buckets[index]);
     1611            if (!!profile->m_buckets[index]) {
     1612                JSValue value = JSValue::decode(profile->m_buckets[index]);
    16221613                if (!value.isCell())
    16231614                    continue;
     
    16271618                    continue;
    16281619               
    1629                 profile->buckets[index] = JSValue::encode(JSValue());
    1630                 profile->weakBuckets[index] = cell->structure();
     1620                profile->m_buckets[index] = JSValue::encode(JSValue());
     1621                profile->m_weakBuckets[index] = cell->structure();
    16311622            }
    16321623           
    1633             ValueProfile::WeakBucket weak = profile->weakBuckets[index];
     1624            ValueProfile::WeakBucket weak = profile->m_weakBuckets[index];
    16341625            if (!weak || weak.isClassInfo())
    16351626                continue;
     
    16391630                continue;
    16401631           
    1641             profile->weakBuckets[index] = weak.asStructure()->classInfo();
     1632            profile->m_weakBuckets[index] = weak.asStructure()->classInfo();
    16421633        }
    16431634    }
     
    19471938#endif
    19481939
     1940#if ENABLE(VALUE_PROFILER)
     1941bool CodeBlock::shouldOptimizeNow()
     1942{
     1943#if ENABLE(JIT_VERBOSE_OSR)
     1944    printf("Considering optimizing %p...\n", this);
     1945#endif
     1946
     1947#if ENABLE(VERBOSE_VALUE_PROFILE)
     1948    dumpValueProfiles();
     1949#endif
     1950
     1951    if (m_optimizationDelayCounter >= 5)
     1952        return true;
     1953   
     1954    unsigned numberOfNonArgumentValueProfiles = 0;
     1955    unsigned numberOfLiveNonArgumentValueProfiles = 0;
     1956    unsigned numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
     1957    for (unsigned i = 0; i < numberOfValueProfiles(); ++i) {
     1958        ValueProfile* profile = valueProfile(i);
     1959        unsigned numSamples = profile->totalNumberOfSamples();
     1960        if (numSamples > ValueProfile::numberOfBuckets)
     1961            numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
     1962        numberOfSamplesInProfiles += numSamples;
     1963        if (profile->m_bytecodeOffset < 0) {
     1964            profile->computeUpdatedPrediction();
     1965            continue;
     1966        }
     1967        numberOfNonArgumentValueProfiles++;
     1968        if (profile->numberOfSamples() || profile->m_prediction != PredictNone)
     1969            numberOfLiveNonArgumentValueProfiles++;
     1970        profile->computeUpdatedPrediction();
     1971    }
     1972
     1973#if ENABLE(JIT_VERBOSE_OSR)
     1974    printf("Profile hotness: %lf, %lf\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles, (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles());
     1975#endif
     1976
     1977    if ((double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles >= 0.75
     1978        && (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles() >= 0.5)
     1979        return true;
     1980   
     1981    m_optimizationDelayCounter++;
     1982    optimizeAfterWarmUp();
     1983    return false;
     1984}
     1985#endif
     1986
     1987#if ENABLE(VERBOSE_VALUE_PROFILE)
     1988void CodeBlock::dumpValueProfiles()
     1989{
     1990    fprintf(stderr, "ValueProfile for %p:\n", this);
     1991    for (unsigned i = 0; i < numberOfValueProfiles(); ++i) {
     1992        ValueProfile* profile = valueProfile(i);
     1993        if (profile->m_bytecodeOffset < 0) {
     1994            ASSERT(profile->m_bytecodeOffset == -1);
     1995            fprintf(stderr, "   arg = %u: ", i + 1);
     1996        } else
     1997            fprintf(stderr, "   bc = %d: ", profile->m_bytecodeOffset);
     1998        if (!profile->numberOfSamples() && profile->m_prediction == PredictNone) {
     1999            fprintf(stderr, "<empty>\n");
     2000            continue;
     2001        }
     2002        profile->dump(stderr);
     2003        fprintf(stderr, "\n");
     2004    }
     2005}
     2006#endif
     2007
    19492008} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.