Ignore:
Timestamp:
Sep 14, 2011, 1:35:43 PM (14 years ago)
Author:
[email protected]
Message:

Prediction tracking is not precise enough
https://bugs.webkit.org/show_bug.cgi?id=67993

Reviewed by Oliver Hunt.

Added a richer set of type predictions, including JSFinalObject, JSString,
object that is not a JSFinalObject or JSArray (ObjectOther), some object
but we don't or care know what kind (SomeObject), definitely an object,
cell that is not an object or JSString, an value that is none of the above
(so either Undefined or Null). Made the propagator and value profiler work
with the new types.

Performance is neutral, because the DFG JIT does not take advantage of this
new knowledge yet.

In the process of writing predictionToString() (which is now considerably
more complex) I decided to finally add a BoundsCheckedPointer, which
should come in handy in other places, like at least the OSR scratch buffer
and the CompactJITCodeMap. It's great for cases where you want to
do pointer arithmetic, you want to have assertions about the
pointer not going out of bounds, but you don't want to write those
assertions yourself.

This also required refactoring inherits(), since the ValueProfiler may
want to do the equivalent of inherits() but given two ClassInfo's.

(JSC::predictionToString):
(JSC::makePrediction):
(JSC::predictionFromValue):

  • bytecode/PredictedType.h:

(JSC::isCellPrediction):
(JSC::isObjectPrediction):
(JSC::isFinalObjectPrediction):
(JSC::isStringPrediction):
(JSC::mergePredictions):

  • bytecode/ValueProfile.h:

(JSC::ValueProfile::numberOfObjects):
(JSC::ValueProfile::numberOfFinalObjects):
(JSC::ValueProfile::numberOfStrings):
(JSC::ValueProfile::probabilityOfObject):
(JSC::ValueProfile::probabilityOfFinalObject):
(JSC::ValueProfile::probabilityOfString):
(JSC::ValueProfile::dump):
(JSC::ValueProfile::Statistics::Statistics):
(JSC::ValueProfile::computeStatistics):

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGGraph.cpp:

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

  • dfg/DFGNode.h:

(JSC::DFG::Node::predict):

  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::propagateNode):

  • runtime/ClassInfo.h:

(JSC::ClassInfo::isSubClassOf):

  • runtime/JSObject.h:

(JSC::JSCell::inherits):

  • wtf/BoundsCheckedPointer.h: Added.

(WTF::BoundsCheckedPointer::BoundsCheckedPointer):
(WTF::BoundsCheckedPointer::operator=):
(WTF::BoundsCheckedPointer::operator+=):
(WTF::BoundsCheckedPointer::operator-=):
(WTF::BoundsCheckedPointer::operator+):
(WTF::BoundsCheckedPointer::operator-):
(WTF::BoundsCheckedPointer::operator++):
(WTF::BoundsCheckedPointer::operator--):
(WTF::BoundsCheckedPointer::operator<):
(WTF::BoundsCheckedPointer::operator<=):
(WTF::BoundsCheckedPointer::operator>):
(WTF::BoundsCheckedPointer::operator>=):
(WTF::BoundsCheckedPointer::operator==):
(WTF::BoundsCheckedPointer::operator!=):
(WTF::BoundsCheckedPointer::operator!):
(WTF::BoundsCheckedPointer::get):
(WTF::BoundsCheckedPointer::operator*):
(WTF::BoundsCheckedPointer::operator[]):
(WTF::BoundsCheckedPointer::strcat):
(WTF::BoundsCheckedPointer::validate):

  • wtf/CMakeLists.txt:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecode/ValueProfile.h

    r94629 r95115  
    109109    }
    110110   
     111    unsigned numberOfObjects() const
     112    {
     113        unsigned result = 0;
     114        for (unsigned i = 0; i < numberOfBuckets; ++i) {
     115            const ClassInfo* ci = classInfo(i);
     116            if (!!ci && ci->isSubClassOf(&JSObject::s_info))
     117                result++;
     118        }
     119        return result;
     120    }
     121   
     122    unsigned numberOfFinalObjects() const
     123    {
     124        unsigned result = 0;
     125        for (unsigned i = 0; i < numberOfBuckets; ++i) {
     126            if (classInfo(i) == &JSFinalObject::s_info)
     127                result++;
     128        }
     129        return result;
     130    }
     131   
     132    unsigned numberOfStrings() const
     133    {
     134        unsigned result = 0;
     135        for (unsigned i = 0; i < numberOfBuckets; ++i) {
     136            if (classInfo(i) == &JSString::s_info)
     137                result++;
     138        }
     139        return result;
     140    }
     141   
    111142    unsigned numberOfArrays() const
    112143    {
     
    149180    }
    150181   
     182    unsigned probabilityOfObject() const
     183    {
     184        return computeProbability(numberOfObjects(), numberOfSamples());
     185    }
     186   
     187    unsigned probabilityOfFinalObject() const
     188    {
     189        return computeProbability(numberOfFinalObjects(), numberOfSamples());
     190    }
     191   
    151192    unsigned probabilityOfArray() const
    152193    {
    153194        return computeProbability(numberOfArrays(), numberOfSamples());
     195    }
     196   
     197    unsigned probabilityOfString() const
     198    {
     199        return computeProbability(numberOfStrings(), numberOfSamples());
    154200    }
    155201   
     
    163209    {
    164210        fprintf(out,
    165                 "samples = %u, int32 = %u (%u), double = %u (%u), cell = %u (%u), array = %u (%u), boolean = %u (%u)",
     211                "samples = %u, int32 = %u (%u), double = %u (%u), cell = %u (%u), object = %u (%u), final object = %u (%u), array = %u (%u), string = %u (%u), boolean = %u (%u)",
    166212                numberOfSamples(),
    167213                probabilityOfInt32(), numberOfInt32s(),
    168214                probabilityOfDouble(), numberOfDoubles(),
    169215                probabilityOfCell(), numberOfCells(),
     216                probabilityOfObject(), numberOfObjects(),
     217                probabilityOfFinalObject(), numberOfFinalObjects(),
    170218                probabilityOfArray(), numberOfArrays(),
     219                probabilityOfString(), numberOfStrings(),
    171220                probabilityOfBoolean(), numberOfBooleans());
    172221        bool first = true;
     
    194243        unsigned doubles;
    195244        unsigned cells;
     245        unsigned objects;
     246        unsigned finalObjects;
    196247        unsigned arrays;
     248        unsigned strings;
    197249        unsigned booleans;
     250       
     251        Statistics()
     252        {
     253            bzero(this, sizeof(Statistics));
     254        }
    198255    };
     256   
     257    // Method for incrementing all relevant statistics for a ClassInfo, except for
     258    // incrementing the number of samples, which the caller is responsible for
     259    // doing.
     260    static void computeStatistics(const ClassInfo* classInfo, Statistics& statistics)
     261    {
     262        statistics.cells++;
     263       
     264        if (classInfo == &JSFinalObject::s_info) {
     265            statistics.finalObjects++;
     266            statistics.objects++;
     267            return;
     268        }
     269       
     270        if (classInfo == &JSArray::s_info) {
     271            statistics.arrays++;
     272            statistics.objects++;
     273            return;
     274        }
     275       
     276        if (classInfo == &JSString::s_info) {
     277            statistics.strings++;
     278            return;
     279        }
     280       
     281        if (classInfo->isSubClassOf(&JSObject::s_info))
     282            statistics.objects++;
     283    }
    199284
    200285    // Optimized method for getting all counts at once.
    201     void computeStatistics(JSGlobalData& globalData, Statistics& statistics) const
    202     {
    203         unsigned samples  = 0;
    204         unsigned int32s   = 0;
    205         unsigned doubles  = 0;
    206         unsigned cells    = 0;
    207         unsigned arrays   = 0;
    208         unsigned booleans = 0;
    209        
     286    void computeStatistics(Statistics& statistics) const
     287    {
    210288        for (unsigned i = 0; i < numberOfBuckets; ++i) {
    211289            if (!buckets[i]) {
    212290                WeakBucket weakBucket = weakBuckets[i];
    213291                if (!!weakBucket) {
    214                     samples++;
    215                     cells++;
    216                     if (weakBucket.getClassInfo() == &JSArray::s_info)
    217                         arrays++;
     292                    statistics.samples++;
     293                    computeStatistics(weakBucket.getClassInfo(), statistics);
    218294                }
    219295               
     
    221297            }
    222298           
    223             samples++;
     299            statistics.samples++;
    224300           
    225301            JSValue value = JSValue::decode(buckets[i]);
    226302            if (value.isInt32())
    227                 int32s++;
     303                statistics.int32s++;
    228304            else if (value.isDouble())
    229                 doubles++;
    230             else if (value.isCell()) {
    231                 cells++;
    232                 if (isJSArray(&globalData, value.asCell()))
    233                     arrays++;
    234             } else if (value.isBoolean())
    235                 booleans++;
    236         }
    237        
    238         statistics.samples  = samples;
    239         statistics.int32s   = int32s;
    240         statistics.doubles  = doubles;
    241         statistics.cells    = cells;
    242         statistics.arrays   = arrays;
    243         statistics.booleans = booleans;
     305                statistics.doubles++;
     306            else if (value.isCell())
     307                computeStatistics(value.asCell()->structure()->classInfo(), statistics);
     308            else if (value.isBoolean())
     309                statistics.booleans++;
     310        }
    244311    }
    245312   
Note: See TracChangeset for help on using the changeset viewer.