Changeset 95115 in webkit


Ignore:
Timestamp:
Sep 14, 2011 1:35:43 PM (13 years ago)
Author:
fpizlo@apple.com
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:
Location:
trunk/Source/JavaScriptCore
Files:
2 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r95110 r95115  
     12011-09-13  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Prediction tracking is not precise enough
     4        https://bugs.webkit.org/show_bug.cgi?id=67993
     5
     6        Reviewed by Oliver Hunt.
     7       
     8        Added a richer set of type predictions, including JSFinalObject, JSString,
     9        object that is not a JSFinalObject or JSArray (ObjectOther), some object
     10        but we don't or care know what kind (SomeObject), definitely an object,
     11        cell that is not an object or JSString, an value that is none of the above
     12        (so either Undefined or Null). Made the propagator and value profiler work
     13        with the new types.
     14       
     15        Performance is neutral, because the DFG JIT does not take advantage of this
     16        new knowledge yet.
     17       
     18        In the process of writing predictionToString() (which is now considerably
     19        more complex) I decided to finally add a BoundsCheckedPointer, which
     20        should come in handy in other places, like at least the OSR scratch buffer
     21        and the CompactJITCodeMap. It's great for cases where you want to
     22        do pointer arithmetic, you want to have assertions about the
     23        pointer not going out of bounds, but you don't want to write those
     24        assertions yourself.
     25       
     26        This also required refactoring inherits(), since the ValueProfiler may
     27        want to do the equivalent of inherits() but given two ClassInfo's.
     28
     29        * GNUmakefile.list.am:
     30        * JavaScriptCore.vcproj/WTF/WTF.vcproj:
     31        * JavaScriptCore.xcodeproj/project.pbxproj:
     32        * bytecode/PredictedType.cpp: Added.
     33        (JSC::predictionToString):
     34        (JSC::makePrediction):
     35        (JSC::predictionFromValue):
     36        * bytecode/PredictedType.h:
     37        (JSC::isCellPrediction):
     38        (JSC::isObjectPrediction):
     39        (JSC::isFinalObjectPrediction):
     40        (JSC::isStringPrediction):
     41        (JSC::mergePredictions):
     42        * bytecode/ValueProfile.h:
     43        (JSC::ValueProfile::numberOfObjects):
     44        (JSC::ValueProfile::numberOfFinalObjects):
     45        (JSC::ValueProfile::numberOfStrings):
     46        (JSC::ValueProfile::probabilityOfObject):
     47        (JSC::ValueProfile::probabilityOfFinalObject):
     48        (JSC::ValueProfile::probabilityOfString):
     49        (JSC::ValueProfile::dump):
     50        (JSC::ValueProfile::Statistics::Statistics):
     51        (JSC::ValueProfile::computeStatistics):
     52        * dfg/DFGByteCodeParser.cpp:
     53        (JSC::DFG::ByteCodeParser::stronglyPredict):
     54        * dfg/DFGGraph.cpp:
     55        (JSC::DFG::Graph::dump):
     56        (JSC::DFG::Graph::predictArgumentTypes):
     57        * dfg/DFGNode.h:
     58        (JSC::DFG::Node::predict):
     59        * dfg/DFGPropagator.cpp:
     60        (JSC::DFG::Propagator::propagateNode):
     61        * runtime/ClassInfo.h:
     62        (JSC::ClassInfo::isSubClassOf):
     63        * runtime/JSObject.h:
     64        (JSC::JSCell::inherits):
     65        * wtf/BoundsCheckedPointer.h: Added.
     66        (WTF::BoundsCheckedPointer::BoundsCheckedPointer):
     67        (WTF::BoundsCheckedPointer::operator=):
     68        (WTF::BoundsCheckedPointer::operator+=):
     69        (WTF::BoundsCheckedPointer::operator-=):
     70        (WTF::BoundsCheckedPointer::operator+):
     71        (WTF::BoundsCheckedPointer::operator-):
     72        (WTF::BoundsCheckedPointer::operator++):
     73        (WTF::BoundsCheckedPointer::operator--):
     74        (WTF::BoundsCheckedPointer::operator<):
     75        (WTF::BoundsCheckedPointer::operator<=):
     76        (WTF::BoundsCheckedPointer::operator>):
     77        (WTF::BoundsCheckedPointer::operator>=):
     78        (WTF::BoundsCheckedPointer::operator==):
     79        (WTF::BoundsCheckedPointer::operator!=):
     80        (WTF::BoundsCheckedPointer::operator!):
     81        (WTF::BoundsCheckedPointer::get):
     82        (WTF::BoundsCheckedPointer::operator*):
     83        (WTF::BoundsCheckedPointer::operator[]):
     84        (WTF::BoundsCheckedPointer::strcat):
     85        (WTF::BoundsCheckedPointer::validate):
     86        * wtf/CMakeLists.txt:
     87
    1882011-09-14  Csaba Osztrogonác  <ossy@webkit.org>
    289
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r94920 r95115  
    458458        Source/JavaScriptCore/wtf/BlockStack.h \
    459459        Source/JavaScriptCore/wtf/BloomFilter.h \
     460        Source/JavaScriptCore/wtf/BoundsCheckedPointer.h \
    460461        Source/JavaScriptCore/wtf/BumpPointerAllocator.h \
    461462        Source/JavaScriptCore/wtf/ByteArray.cpp \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj

    r94920 r95115  
    630630                </File>
    631631                <File
     632                        RelativePath="..\..\wtf\BoundsCheckedPointer.h"
     633                        >
     634                </File>
     635                <File
    632636                        RelativePath="..\..\wtf\BumpPointerAllocator.h"
    633637                        >
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r95016 r95115  
    7171                0FD82E56141DAF0800179C94 /* DFGOSREntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */; };
    7272                0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */; settings = {ATTRIBUTES = (Private, ); }; };
     73                0FD82E85141F3FE300179C94 /* BoundsCheckedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E82141F3FC900179C94 /* BoundsCheckedPointer.h */; settings = {ATTRIBUTES = (Private, ); }; };
     74                0FD82E86141F3FF100179C94 /* PredictedType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E84141F3FDA00179C94 /* PredictedType.cpp */; };
    7375                1400067712A6F7830064D123 /* OSAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1400067612A6F7830064D123 /* OSAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
    7476                1400069312A6F9E10064D123 /* OSAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */; };
     
    808810                0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSREntry.cpp; path = dfg/DFGOSREntry.cpp; sourceTree = "<group>"; };
    809811                0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSREntry.h; path = dfg/DFGOSREntry.h; sourceTree = "<group>"; };
     812                0FD82E82141F3FC900179C94 /* BoundsCheckedPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BoundsCheckedPointer.h; sourceTree = "<group>"; };
     813                0FD82E84141F3FDA00179C94 /* PredictedType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PredictedType.cpp; sourceTree = "<group>"; };
    810814                1400067612A6F7830064D123 /* OSAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSAllocator.h; sourceTree = "<group>"; };
    811815                1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSAllocatorPosix.cpp; sourceTree = "<group>"; };
     
    17831787                        isa = PBXGroup;
    17841788                        children = (
     1789                                0FD82E82141F3FC900179C94 /* BoundsCheckedPointer.h */,
    17851790                                0F963B2E13FC66AE0002D9B2 /* MetaAllocatorHandle.h */,
    17861791                                0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */,
     
    23092314                        isa = PBXGroup;
    23102315                        children = (
     2316                                0FD82E84141F3FDA00179C94 /* PredictedType.cpp */,
    23112317                                0FD82E4F141DAEA100179C94 /* PredictedType.h */,
    23122318                                0FD82E50141DAEA100179C94 /* PredictionTracker.h */,
     
    24102416                                86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
    24112417                                86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
     2418                                0FD82E85141F3FE300179C94 /* BoundsCheckedPointer.h in Headers */,
    24122419                                0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */,
    24132420                                0FD82E55141DAEEE00179C94 /* PredictionTracker.h in Headers */,
     
    30843091                        buildActionMask = 2147483647;
    30853092                        files = (
     3093                                0FD82E86141F3FF100179C94 /* PredictedType.cpp in Sources */,
    30863094                                0FD82E56141DAF0800179C94 /* DFGOSREntry.cpp in Sources */,
    30873095                                0F963B2C13F853EC0002D9B2 /* MetaAllocator.cpp in Sources */,
  • trunk/Source/JavaScriptCore/bytecode/PredictedType.h

    r95016 r95115  
    3434namespace JSC {
    3535
    36 typedef uint8_t PredictedType;
    37 static const PredictedType PredictNone   = 0;
    38 static const PredictedType PredictCell   = 0x01;
    39 static const PredictedType PredictArray  = 0x03;
    40 static const PredictedType PredictInt32  = 0x04;
    41 static const PredictedType PredictDouble = 0x08;
    42 static const PredictedType PredictNumber = 0x0c;
    43 static const PredictedType PredictBoolean = 0x10;
    44 static const PredictedType PredictTop    = 0x1f;
    45 static const PredictedType StrongPredictionTag = 0x80;
    46 static const PredictedType PredictionTagMask    = 0x80;
     36typedef uint16_t PredictedType;
     37static const PredictedType PredictNone          = 0x0000; // We don't know anything yet.
     38static const PredictedType PredictFinalObject   = 0x0001; // It's definitely a JSFinalObject.
     39static const PredictedType PredictArray         = 0x0002; // It's definitely a JSArray.
     40static const PredictedType PredictObjectOther   = 0x0010; // It's definitely an object other than JSFinalObject or JSArray.
     41static const PredictedType PredictObjectUnknown = 0x0020; // It's definitely an object, but we didn't record enough informatin to know more.
     42static const PredictedType PredictObjectMask    = 0x003f; // Bitmask used for testing for any kind of object prediction.
     43static const PredictedType PredictString        = 0x0040; // It's definitely a JSString.
     44static const PredictedType PredictCellOther     = 0x0080; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
     45static const PredictedType PredictCell          = 0x00ff; // It's definitely a JSCell.
     46static const PredictedType PredictInt32         = 0x0100; // It's definitely an Int32.
     47static const PredictedType PredictDouble        = 0x0200; // It's definitely a Double.
     48static const PredictedType PredictNumber        = 0x0300; // It's either an Int32 or a Double.
     49static const PredictedType PredictBoolean       = 0x0400; // It's definitely a Boolean.
     50static const PredictedType PredictOther         = 0x4000; // It's definitely none of the above.
     51static const PredictedType PredictTop           = 0x7fff; // It can be any of the above.
     52static const PredictedType StrongPredictionTag  = 0x8000; // It's a strong prediction (all strong predictions trump all weak ones).
     53static const PredictedType PredictionTagMask    = 0x8000;
    4754
    4855enum PredictionSource { WeakPrediction, StrongPrediction };
     
    5057inline bool isCellPrediction(PredictedType value)
    5158{
    52     return (value & PredictCell) == PredictCell && !(value & ~(PredictArray | PredictionTagMask));
     59    return !!(value & PredictCell) && !(value & ~(PredictCell | PredictionTagMask));
     60}
     61
     62inline bool isObjectPrediction(PredictedType value)
     63{
     64    return !!(value & PredictObjectMask) && !(value & ~(PredictObjectMask | PredictionTagMask));
     65}
     66
     67inline bool isFinalObjectPrediction(PredictedType value)
     68{
     69    return (value & ~PredictionTagMask) == PredictFinalObject;
     70}
     71
     72inline bool isStringPrediction(PredictedType value)
     73{
     74    return (value & ~PredictionTagMask) == PredictString;
    5375}
    5476
     
    85107
    86108#ifndef NDEBUG
    87 inline const char* predictionToString(PredictedType value)
    88 {
    89     if (isStrongPrediction(value)) {
    90         switch (value & ~PredictionTagMask) {
    91         case PredictNone:
    92             return "p-strong-bottom";
    93         case PredictCell:
    94             return "p-strong-cell";
    95         case PredictArray:
    96             return "p-strong-array";
    97         case PredictInt32:
    98             return "p-strong-int32";
    99         case PredictDouble:
    100             return "p-strong-double";
    101         case PredictNumber:
    102             return "p-strong-number";
    103         case PredictBoolean:
    104             return "p-strong-boolean";
    105         default:
    106             return "p-strong-top";
    107         }
    108     }
    109     switch (value) {
    110     case PredictNone:
    111         return "p-weak-bottom";
    112     case PredictCell:
    113         return "p-weak-cell";
    114     case PredictArray:
    115         return "p-weak-array";
    116     case PredictInt32:
    117         return "p-weak-int32";
    118     case PredictDouble:
    119         return "p-weak-double";
    120     case PredictNumber:
    121         return "p-weak-number";
    122     case PredictBoolean:
    123         return "p-weak-boolean";
    124     default:
    125         return "p-weak-top";
    126     }
    127 }
     109const char* predictionToString(PredictedType value);
    128110#endif
    129111
    130112inline PredictedType mergePredictions(PredictedType left, PredictedType right)
    131113{
    132     if (isStrongPrediction(left) == isStrongPrediction(right))
     114    if (isStrongPrediction(left) == isStrongPrediction(right)) {
     115        if (left & PredictObjectUnknown) {
     116            ASSERT(!(left & (PredictObjectMask & ~PredictObjectUnknown)));
     117            if (right & PredictObjectMask)
     118                return (left & ~PredictObjectUnknown) | right;
     119        } else if (right & PredictObjectUnknown) {
     120            ASSERT(!(right & (PredictObjectMask & ~PredictObjectUnknown)));
     121            if (left & PredictObjectMask)
     122                return (right & ~PredictObjectUnknown) | left;
     123        }
    133124        return left | right;
     125    }
    134126    if (isStrongPrediction(left)) {
    135127        ASSERT(!isStrongPrediction(right));
     
    160152
    161153#if ENABLE(VALUE_PROFILER)
    162 inline PredictedType makePrediction(JSGlobalData& globalData, const ValueProfile& profile)
    163 {
    164     ValueProfile::Statistics statistics;
    165     profile.computeStatistics(globalData, statistics);
    166    
    167     if (!statistics.samples)
    168         return PredictNone;
    169    
    170     if (statistics.int32s == statistics.samples)
    171         return StrongPredictionTag | PredictInt32;
    172    
    173     if (statistics.doubles == statistics.samples)
    174         return StrongPredictionTag | PredictDouble;
    175    
    176     if (statistics.int32s + statistics.doubles == statistics.samples)
    177         return StrongPredictionTag | PredictNumber;
    178    
    179     if (statistics.arrays == statistics.samples)
    180         return StrongPredictionTag | PredictArray;
    181    
    182     if (statistics.cells == statistics.samples)
    183         return StrongPredictionTag | PredictCell;
    184    
    185     if (statistics.booleans == statistics.samples)
    186         return StrongPredictionTag | PredictBoolean;
    187    
    188     return StrongPredictionTag | PredictTop;
    189 }
     154PredictedType makePrediction(const ValueProfile&);
    190155#endif
     156
     157PredictedType predictionFromValue(JSValue);
    191158
    192159} // namespace JSC
  • 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   
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r95060 r95115  
    485485        printf("\n");
    486486#endif
    487         m_graph[nodeIndex].predict(makePrediction(*m_globalData, *profile), StrongPrediction);
     487        m_graph[nodeIndex].predict(makePrediction(*profile) & ~PredictionTagMask, StrongPrediction);
    488488#if ENABLE(DFG_DEBUG_VERBOSE)
    489489        printf("    Prediction: %s\n", predictionToString(m_graph[nodeIndex].getPrediction()));
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r95016 r95115  
    140140   
    141141    printf(")");
    142    
    143     if (node.hasLocal())
    144         printf("  predicting %s", predictionToString(getPrediction(node.local())));
    145     if (node.hasVarNumber())
    146         printf("  predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber())));
    147     if (node.hasPrediction())
    148         printf("  predicting %s", predictionToString(node.getPrediction()));
     142
     143    if (!skipped) {
     144        if (node.hasLocal())
     145            printf("  predicting %s", predictionToString(getPrediction(node.local())));
     146        if (node.hasVarNumber())
     147            printf("  predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber())));
     148        if (node.hasPrediction())
     149            printf("  predicting %s", predictionToString(node.getPrediction()));
     150    }
    149151   
    150152    printf("\n");
     
    210212    ASSERT(codeBlock->alternative);
    211213
    212     JSGlobalData& globalData = exec->globalData();
    213214    CodeBlock* profiledCodeBlock = codeBlock->alternative();
    214215    ASSERT(codeBlock->m_numParameters >= 1);
     
    224225#endif
    225226       
    226         m_predictions.predictArgument(arg, makePrediction(globalData, *profile) & ~PredictionTagMask, StrongPrediction);
     227        m_predictions.predictArgument(arg, makePrediction(*profile) & ~PredictionTagMask, StrongPrediction);
    227228       
    228229#if ENABLE(DFG_DEBUG_VERBOSE)
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r95060 r95115  
    479479        ASSERT(source == StrongPrediction);
    480480       
    481         PredictedType newPrediction = StrongPredictionTag | prediction | m_opInfo2;
    482         bool result = m_opInfo2 != newPrediction;
    483         m_opInfo2 = newPrediction;
    484         return result;
     481        return mergePrediction(m_opInfo2, makePrediction(prediction, source));
    485482    }
    486483   
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r95016 r95115  
    129129        switch (op) {
    130130        case JSConstant: {
    131             JSValue value = node.valueOfJSConstant(m_codeBlock);
    132             if (value.isInt32())
    133                 changed |= setPrediction(makePrediction(PredictInt32, StrongPrediction));
    134             else if (value.isDouble())
    135                 changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction));
    136             else if (value.isCell()) {
    137                 JSCell* cell = value.asCell();
    138                 if (isJSArray(&m_globalData, cell))
    139                     changed |= setPrediction(makePrediction(PredictArray, StrongPrediction));
    140                 else
    141                     changed |= setPrediction(makePrediction(PredictCell, StrongPrediction));
    142             } else if (value.isBoolean())
    143                 changed |= setPrediction(makePrediction(PredictBoolean, StrongPrediction));
    144             else
    145                 changed |= setPrediction(makePrediction(PredictTop, StrongPrediction));
     131            changed |= setPrediction(makePrediction(predictionFromValue(node.valueOfJSConstant(m_codeBlock)), StrongPrediction));
    146132            break;
    147133        }
     
    199185                    else
    200186                        changed |= mergePrediction(makePrediction(PredictDouble, StrongPrediction));
     187                } else if (!(left & PredictNumber) || !(right & PredictNumber)) {
     188                    // left or right is definitely something other than a number.
     189                    changed |= mergePrediction(makePrediction(PredictString, StrongPrediction));
    201190                } else
    202                     changed |= mergePrediction(makePrediction(PredictTop, StrongPrediction));
     191                    changed |= mergePrediction(makePrediction(PredictString | PredictInt32 | PredictDouble, StrongPrediction));
    203192            }
    204193            break;
     
    240229        case GetMethod:
    241230        case GetByVal: {
    242             changed |= mergeUse(node.child1(), PredictCell | StrongPredictionTag);
     231            changed |= mergeUse(node.child1(), PredictObjectUnknown | StrongPredictionTag);
    243232            changed |= node.predict(m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction);
    244233            if (isStrongPrediction(node.getPrediction()))
     
    246235            break;
    247236        }
    248            
     237
    249238        case Call:
    250239        case Construct: {
    251             changed |= mergeUse(m_graph.m_varArgChildren[node.firstChild()], PredictCell | StrongPredictionTag);
     240            changed |= mergeUse(m_graph.m_varArgChildren[node.firstChild()], PredictObjectUnknown | StrongPredictionTag);
    252241            changed |= node.predict(m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction);
    253242            if (isStrongPrediction(node.getPrediction()))
     
    257246           
    258247        case ConvertThis: {
    259             changed |= setPrediction(makePrediction(PredictCell, StrongPrediction));
     248            changed |= setPrediction(makePrediction(PredictObjectUnknown, StrongPrediction));
    260249            break;
    261250        }
     
    278267        case PutByValAlias:
    279268        case PutById:
    280         case PutByIdDirect:
    281             changed |= mergeUse(node.child1(), PredictCell | StrongPredictionTag);
    282             break;
     269        case PutByIdDirect: {
     270            changed |= mergeUse(node.child1(), PredictObjectUnknown | StrongPredictionTag);
     271            break;
     272        }
    283273
    284274#ifndef NDEBUG
     
    307297
    308298#if ENABLE(DFG_DEBUG_VERBOSE)
    309         printf("expect(%s) use(%s) %s\n", predictionToString(m_predictions[m_compileIndex]), predictionToString(m_uses[m_compileIndex]), changed ? "CHANGED" : "");
     299        printf("expect(%s) ", predictionToString(m_predictions[m_compileIndex]));
     300        printf("use(%s) %s\n", predictionToString(m_uses[m_compileIndex]), changed ? "CHANGED" : "");
    310301#endif
    311302       
  • trunk/Source/JavaScriptCore/runtime/ClassInfo.h

    r46528 r95115  
    5252            return staticPropHashTable;
    5353        }
     54       
     55        bool isSubClassOf(const ClassInfo* other) const
     56        {
     57            for (const ClassInfo* ci = this; ci; ci = ci->parentClass) {
     58                if (ci == other)
     59                    return true;
     60            }
     61            return false;
     62        }
    5463
    5564        const HashTable* staticPropHashTable;
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r94929 r95115  
    500500inline bool JSCell::inherits(const ClassInfo* info) const
    501501{
    502     for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) {
    503         if (ci == info)
    504             return true;
    505     }
    506     return false;
     502    return classInfo()->isSubClassOf(info);
    507503}
    508504
  • trunk/Source/JavaScriptCore/wtf/CMakeLists.txt

    r94920 r95115  
    77    Atomics.h
    88    Bitmap.h
     9    BoundsCheckedPointer.h
    910    BumpPointerAllocator.h
    1011    ByteArray.h
  • trunk/Source/JavaScriptCore/wtf/Platform.h

    r95110 r95115  
    958958
    959959#if !defined(ENABLE_TIERED_COMPILATION)
    960 #define ENABLE_TIERED_COMPILATION 0
     960#define ENABLE_TIERED_COMPILATION 1
    961961#endif
    962962
Note: See TracChangeset for help on using the changeset viewer.