Changeset 131982 in webkit


Ignore:
Timestamp:
Oct 19, 2012 11:53:04 PM (12 years ago)
Author:
fpizlo@apple.com
Message:

DFG should have some facility for recognizing redundant CheckArrays and Arrayifies
https://bugs.webkit.org/show_bug.cgi?id=99287

Reviewed by Mark Hahnenberg.

Adds reasoning about indexing type sets (i.e. ArrayModes) to AbstractValue, which
then enables us to fold away CheckArray's and Arrayify's that are redundant.

  • bytecode/ArrayProfile.cpp:

(JSC::arrayModesToString):
(JSC):

  • bytecode/ArrayProfile.h:

(JSC):
(JSC::mergeArrayModes):
(JSC::arrayModesAlreadyChecked):

  • bytecode/StructureSet.h:

(JSC::StructureSet::arrayModesFromStructures):
(StructureSet):

  • dfg/DFGAbstractState.cpp:

(JSC::DFG::AbstractState::execute):

  • dfg/DFGAbstractValue.h:

(JSC::DFG::AbstractValue::AbstractValue):
(JSC::DFG::AbstractValue::clear):
(JSC::DFG::AbstractValue::isClear):
(JSC::DFG::AbstractValue::makeTop):
(JSC::DFG::AbstractValue::clobberStructures):
(AbstractValue):
(JSC::DFG::AbstractValue::setMostSpecific):
(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::operator==):
(JSC::DFG::AbstractValue::merge):
(JSC::DFG::AbstractValue::filter):
(JSC::DFG::AbstractValue::filterArrayModes):
(JSC::DFG::AbstractValue::validate):
(JSC::DFG::AbstractValue::checkConsistency):
(JSC::DFG::AbstractValue::dump):
(JSC::DFG::AbstractValue::clobberArrayModes):
(JSC::DFG::AbstractValue::clobberArrayModesSlow):
(JSC::DFG::AbstractValue::setFuturePossibleStructure):
(JSC::DFG::AbstractValue::filterFuturePossibleStructure):

  • dfg/DFGArrayMode.cpp:

(JSC::DFG::modeAlreadyChecked):

  • dfg/DFGArrayMode.h:

(JSC::DFG::arrayModesFor):
(DFG):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::arrayify):

Location:
trunk/Source/JavaScriptCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r131977 r131982  
     12012-10-19  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG should have some facility for recognizing redundant CheckArrays and Arrayifies
     4        https://bugs.webkit.org/show_bug.cgi?id=99287
     5
     6        Reviewed by Mark Hahnenberg.
     7
     8        Adds reasoning about indexing type sets (i.e. ArrayModes) to AbstractValue, which
     9        then enables us to fold away CheckArray's and Arrayify's that are redundant.
     10
     11        * bytecode/ArrayProfile.cpp:
     12        (JSC::arrayModesToString):
     13        (JSC):
     14        * bytecode/ArrayProfile.h:
     15        (JSC):
     16        (JSC::mergeArrayModes):
     17        (JSC::arrayModesAlreadyChecked):
     18        * bytecode/StructureSet.h:
     19        (JSC::StructureSet::arrayModesFromStructures):
     20        (StructureSet):
     21        * dfg/DFGAbstractState.cpp:
     22        (JSC::DFG::AbstractState::execute):
     23        * dfg/DFGAbstractValue.h:
     24        (JSC::DFG::AbstractValue::AbstractValue):
     25        (JSC::DFG::AbstractValue::clear):
     26        (JSC::DFG::AbstractValue::isClear):
     27        (JSC::DFG::AbstractValue::makeTop):
     28        (JSC::DFG::AbstractValue::clobberStructures):
     29        (AbstractValue):
     30        (JSC::DFG::AbstractValue::setMostSpecific):
     31        (JSC::DFG::AbstractValue::set):
     32        (JSC::DFG::AbstractValue::operator==):
     33        (JSC::DFG::AbstractValue::merge):
     34        (JSC::DFG::AbstractValue::filter):
     35        (JSC::DFG::AbstractValue::filterArrayModes):
     36        (JSC::DFG::AbstractValue::validate):
     37        (JSC::DFG::AbstractValue::checkConsistency):
     38        (JSC::DFG::AbstractValue::dump):
     39        (JSC::DFG::AbstractValue::clobberArrayModes):
     40        (JSC::DFG::AbstractValue::clobberArrayModesSlow):
     41        (JSC::DFG::AbstractValue::setFuturePossibleStructure):
     42        (JSC::DFG::AbstractValue::filterFuturePossibleStructure):
     43        * dfg/DFGArrayMode.cpp:
     44        (JSC::DFG::modeAlreadyChecked):
     45        * dfg/DFGArrayMode.h:
     46        (JSC::DFG::arrayModesFor):
     47        (DFG):
     48        * dfg/DFGConstantFoldingPhase.cpp:
     49        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     50        * dfg/DFGSpeculativeJIT.cpp:
     51        (JSC::DFG::SpeculativeJIT::arrayify):
     52
    1532012-10-19  Filip Pizlo  <fpizlo@apple.com>
    254
  • trunk/Source/JavaScriptCore/bytecode/ArrayProfile.cpp

    r128957 r131982  
    2727#include "ArrayProfile.h"
    2828
     29#include <wtf/StringExtras.h>
     30
    2931namespace JSC {
     32
     33const char* arrayModesToString(ArrayModes arrayModes)
     34{
     35    if (!arrayModes)
     36        return "0:<empty>";
     37   
     38    if (arrayModes == ALL_ARRAY_MODES)
     39        return "TOP";
     40
     41    bool isNonArray = !!(arrayModes & NonArray);
     42    bool isNonArrayWithContiguous = !!(arrayModes & NonArrayWithContiguous);
     43    bool isNonArrayWithArrayStorage = !!(arrayModes & NonArrayWithArrayStorage);
     44    bool isNonArrayWithSlowPutArrayStorage = !!(arrayModes & NonArrayWithSlowPutArrayStorage);
     45    bool isArray = !!(arrayModes & ArrayClass);
     46    bool isArrayWithContiguous = !!(arrayModes & ArrayWithContiguous);
     47    bool isArrayWithArrayStorage = !!(arrayModes & ArrayWithArrayStorage);
     48    bool isArrayWithSlowPutArrayStorage = !!(arrayModes & ArrayWithSlowPutArrayStorage);
     49   
     50    static char result[256];
     51    snprintf(
     52        result, sizeof(result),
     53        "%u:%s%s%s%s%s%s%s%s",
     54        arrayModes,
     55        isNonArray ? "NonArray" : "",
     56        isNonArrayWithContiguous ? "NonArrayWithContiguous" : "",
     57        isNonArrayWithArrayStorage ? " NonArrayWithArrayStorage" : "",
     58        isNonArrayWithSlowPutArrayStorage ? "NonArrayWithSlowPutArrayStorage" : "",
     59        isArray ? "ArrayClass" : "",
     60        isArrayWithContiguous ? "ArrayWithContiguous" : "",
     61        isArrayWithArrayStorage ? " ArrayWithArrayStorage" : "",
     62        isArrayWithSlowPutArrayStorage ? "ArrayWithSlowPutArrayStorage" : "");
     63   
     64    return result;
     65}
    3066
    3167void ArrayProfile::computeUpdatedPrediction(OperationInProgress operation)
  • trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h

    r129045 r131982  
    4141
    4242#define asArrayModes(type) \
    43     (1 << static_cast<unsigned>(type))
     43    (static_cast<unsigned>(1) << static_cast<unsigned>(type))
     44
     45#define ALL_NON_ARRAY_ARRAY_MODES                       \
     46    (asArrayModes(NonArray)                             \
     47     | asArrayModes(NonArrayWithContiguous)             \
     48     | asArrayModes(NonArrayWithArrayStorage)           \
     49     | asArrayModes(NonArrayWithSlowPutArrayStorage))
     50
     51#define ALL_ARRAY_ARRAY_MODES                           \
     52    (asArrayModes(ArrayClass)                           \
     53     | asArrayModes(ArrayWithContiguous)                \
     54     | asArrayModes(ArrayWithArrayStorage)              \
     55     | asArrayModes(ArrayWithSlowPutArrayStorage))
     56
     57#define ALL_ARRAY_MODES (ALL_NON_ARRAY_ARRAY_MODES | ALL_ARRAY_ARRAY_MODES)
    4458
    4559inline ArrayModes arrayModeFromStructure(Structure* structure)
    4660{
    4761    return asArrayModes(structure->indexingType());
     62}
     63
     64const char* arrayModesToString(ArrayModes);
     65
     66inline bool mergeArrayModes(ArrayModes& left, ArrayModes right)
     67{
     68    ArrayModes newModes = left | right;
     69    if (newModes == left)
     70        return false;
     71    left = newModes;
     72    return true;
     73}
     74
     75// Checks if proven is a subset of expected.
     76inline bool arrayModesAlreadyChecked(ArrayModes proven, ArrayModes expected)
     77{
     78    return (expected | proven) == expected;
    4879}
    4980
  • trunk/Source/JavaScriptCore/bytecode/StructureSet.h

    r121925 r131982  
    2727#define StructureSet_h
    2828
     29#include "ArrayProfile.h"
    2930#include "SpeculatedType.h"
    3031#include "Structure.h"
     
    138139    }
    139140   
     141    ArrayModes arrayModesFromStructures() const
     142    {
     143        ArrayModes result = 0;
     144       
     145        for (size_t i = 0; i < m_structures.size(); ++i)
     146            mergeArrayModes(result, asArrayModes(m_structures[i]->indexingType()));
     147       
     148        return result;
     149    }
     150   
    140151    bool operator==(const StructureSet& other) const
    141152    {
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp

    r131822 r131982  
    14211421            break;
    14221422        }
     1423        forNode(node.child1()).filterArrayModes(arrayModesFor(node.arrayMode()));
    14231424        break;
    14241425    }
    14251426    case Arrayify: {
     1427        if (modeAlreadyChecked(forNode(node.child1()), node.arrayMode())) {
     1428            m_foundConstants = true;
     1429            node.setCanExit(false);
     1430            break;
     1431        }
    14261432        switch (node.arrayMode()) {
    14271433        case ALL_EFFECTFUL_MODES:
     
    14321438            forNode(nodeIndex).clear();
    14331439            clobberStructures(indexInBlock);
     1440            forNode(node.child1()).filterArrayModes(arrayModesFor(node.arrayMode()));
    14341441            break;
    14351442        default:
    1436             ASSERT_NOT_REACHED();
     1443            CRASH();
    14371444            break;
    14381445        }
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h

    r125999 r131982  
    3131#if ENABLE(DFG_JIT)
    3232
     33#include "ArrayProfile.h"
    3334#include "DFGStructureAbstractValue.h"
    3435#include "JSCell.h"
     
    4142    AbstractValue()
    4243        : m_type(SpecNone)
     44        , m_arrayModes(0)
    4345    {
    4446    }
     
    4749    {
    4850        m_type = SpecNone;
     51        m_arrayModes = 0;
    4952        m_currentKnownStructure.clear();
    5053        m_futurePossibleStructure.clear();
     
    5558    bool isClear() const
    5659    {
    57         bool result = m_type == SpecNone && m_currentKnownStructure.isClear() && m_futurePossibleStructure.isClear();
     60        bool result = m_type == SpecNone && !m_arrayModes && m_currentKnownStructure.isClear() && m_futurePossibleStructure.isClear();
    5861        if (result)
    5962            ASSERT(!m_value);
     
    6467    {
    6568        m_type = SpecTop;
     69        m_arrayModes = ALL_ARRAY_MODES;
    6670        m_currentKnownStructure.makeTop();
    6771        m_futurePossibleStructure.makeTop();
     
    7276    void clobberStructures()
    7377    {
    74         if (m_type & SpecCell)
     78        if (m_type & SpecCell) {
    7579            m_currentKnownStructure.makeTop();
    76         else
     80            clobberArrayModes();
     81        } else {
    7782            ASSERT(m_currentKnownStructure.isClear());
    78         checkConsistency();
    79     }
    80    
     83            ASSERT(!m_arrayModes);
     84        }
     85        checkConsistency();
     86    }
     87       
    8188    void clobberValue()
    8289    {
     
    104111        result.makeTop();
    105112        return result;
    106     }
    107    
    108     void setFuturePossibleStructure(Structure* structure)
    109     {
    110         if (structure->transitionWatchpointSetIsStillValid())
    111             m_futurePossibleStructure = structure;
    112         else
    113             m_futurePossibleStructure.makeTop();
    114     }
    115    
    116     void filterFuturePossibleStructure(Structure* structure)
    117     {
    118         if (structure->transitionWatchpointSetIsStillValid())
    119             m_futurePossibleStructure.filter(StructureAbstractValue(structure));
    120113    }
    121114   
     
    126119            m_currentKnownStructure = structure;
    127120            setFuturePossibleStructure(structure);
     121            m_arrayModes = asArrayModes(structure->indexingType());
    128122        } else {
    129123            m_currentKnownStructure.clear();
    130124            m_futurePossibleStructure.clear();
     125            m_arrayModes = 0;
    131126        }
    132127       
     
    141136        if (!!value && value.isCell()) {
    142137            m_currentKnownStructure.makeTop();
    143             setFuturePossibleStructure(value.asCell()->structure());
     138            Structure* structure = value.asCell()->structure();
     139            setFuturePossibleStructure(structure);
     140            m_arrayModes = asArrayModes(structure->indexingType());
     141            clobberArrayModes();
    144142        } else {
    145143            m_currentKnownStructure.clear();
    146144            m_futurePossibleStructure.clear();
     145            m_arrayModes = 0;
    147146        }
    148147       
     
    157156        m_currentKnownStructure = structure;
    158157        setFuturePossibleStructure(structure);
     158        m_arrayModes = asArrayModes(structure->indexingType());
    159159        m_type = speculationFromStructure(structure);
    160160        m_value = JSValue();
     
    168168            m_currentKnownStructure.makeTop();
    169169            m_futurePossibleStructure.makeTop();
     170            m_arrayModes = ALL_ARRAY_MODES;
    170171        } else {
    171172            m_currentKnownStructure.clear();
    172173            m_futurePossibleStructure.clear();
     174            m_arrayModes = 0;
    173175        }
    174176        m_type = type;
     
    180182    {
    181183        return m_type == other.m_type
     184            && m_arrayModes == other.m_arrayModes
    182185            && m_currentKnownStructure == other.m_currentKnownStructure
    183186            && m_futurePossibleStructure == other.m_futurePossibleStructure
     
    200203        } else {
    201204            result |= mergeSpeculation(m_type, other.m_type);
     205            result |= mergeArrayModes(m_arrayModes, other.m_arrayModes);
    202206            result |= m_currentKnownStructure.addAll(other.m_currentKnownStructure);
    203207            result |= m_futurePossibleStructure.addAll(other.m_futurePossibleStructure);
     
    219223            m_currentKnownStructure.makeTop();
    220224            m_futurePossibleStructure.makeTop();
     225            m_arrayModes = ALL_ARRAY_MODES;
    221226        }
    222227        m_value = JSValue();
     
    228233    {
    229234        m_type &= other.speculationFromStructures();
     235        m_arrayModes &= other.arrayModesFromStructures();
    230236        m_currentKnownStructure.filter(other);
    231237        if (m_currentKnownStructure.isClear())
     
    242248        m_futurePossibleStructure.filter(m_type);
    243249       
     250        filterArrayModesByType();
    244251        filterValueByType();
     252       
     253        checkConsistency();
     254    }
     255   
     256    void filterArrayModes(ArrayModes arrayModes)
     257    {
     258        ASSERT(arrayModes);
     259       
     260        m_type &= SpecCell;
     261        m_arrayModes &= arrayModes;
     262       
     263        // I could do more fancy filtering here. But it probably won't make any difference.
    245264       
    246265        checkConsistency();
     
    259278        m_currentKnownStructure.filter(m_type);
    260279        m_futurePossibleStructure.filter(m_type);
    261 
     280       
     281        filterArrayModesByType();
    262282        filterValueByType();
    263283       
    264284        checkConsistency();
    265     }
    266    
    267     // We could go further, and ensure that if the futurePossibleStructure contravenes
    268     // the value, then we could clear both of those things. But that's unlikely to help
    269     // in any realistic scenario, so we don't do it. Simpler is better.
    270     void filterValueByType()
    271     {
    272         if (!!m_type) {
    273             // The type is still non-empty. This implies that regardless of what filtering
    274             // was done, we either didn't have a value to begin with, or that value is still
    275             // valid.
    276             ASSERT(!m_value || validateType(m_value));
    277             return;
    278         }
    279        
    280         // The type has been rendered empty. That means that the value must now be invalid,
    281         // as well.
    282         ASSERT(!m_value || !validateType(m_value));
    283         m_value = JSValue();
    284285    }
    285286   
     
    320321            Structure* structure = value.asCell()->structure();
    321322            return m_currentKnownStructure.contains(structure)
    322                 && m_futurePossibleStructure.contains(structure);
     323                && m_futurePossibleStructure.contains(structure)
     324                && (m_arrayModes & asArrayModes(structure->indexingType()));
    323325        }
    324326       
     
    331333            ASSERT(m_currentKnownStructure.isClear());
    332334            ASSERT(m_futurePossibleStructure.isClear());
     335            ASSERT(!m_arrayModes);
    333336        }
    334337       
     
    347350    void dump(FILE* out) const
    348351    {
    349         fprintf(out, "(%s, ", speculationToString(m_type));
     352        fprintf(out, "(%s, %s, ", speculationToString(m_type), arrayModesToString(m_arrayModes));
    350353        m_currentKnownStructure.dump(out);
    351354        dataLog(", ");
     
    438441    SpeculatedType m_type;
    439442   
     443    // This is a proven constraint on the possible indexing types that this value
     444    // can have right now. It also implicitly constraints the set of structures
     445    // that the value may have right now, since a structure has an immutable
     446    // indexing type. This is subject to change upon reassignment, or any side
     447    // effect that makes non-obvious changes to the heap.
     448    ArrayModes m_arrayModes;
     449   
    440450    // This is a proven constraint on the possible values that this value can
    441451    // have now or any time in the future, unless it is reassigned. Note that this
     
    445455    // means TOP.
    446456    JSValue m_value;
     457
     458private:
     459    void clobberArrayModes()
     460    {
     461        if (m_arrayModes == ALL_ARRAY_MODES)
     462            return;
     463       
     464        if (LIKELY(m_arrayModes & asArrayModes(NonArray)))
     465            m_arrayModes = ALL_ARRAY_MODES;
     466        else
     467            clobberArrayModesSlow();
     468    }
     469   
     470    void clobberArrayModesSlow()
     471    {
     472        if (m_arrayModes & asArrayModes(ArrayClass))
     473            m_arrayModes = ALL_ARRAY_MODES;
     474        else if (m_arrayModes & asArrayModes(NonArrayWithContiguous))
     475            m_arrayModes |= asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage);
     476        else if (m_arrayModes & asArrayModes(ArrayWithContiguous))
     477            m_arrayModes |= asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage);
     478        else if (m_arrayModes & asArrayModes(NonArrayWithArrayStorage))
     479            m_arrayModes |= asArrayModes(NonArrayWithSlowPutArrayStorage);
     480        else if (m_arrayModes & asArrayModes(ArrayWithArrayStorage))
     481            m_arrayModes |= asArrayModes(ArrayWithArrayStorage);
     482    }
     483
     484    void setFuturePossibleStructure(Structure* structure)
     485    {
     486        if (structure->transitionWatchpointSetIsStillValid())
     487            m_futurePossibleStructure = structure;
     488        else
     489            m_futurePossibleStructure.makeTop();
     490    }
     491   
     492    void filterFuturePossibleStructure(Structure* structure)
     493    {
     494        if (structure->transitionWatchpointSetIsStillValid())
     495            m_futurePossibleStructure.filter(StructureAbstractValue(structure));
     496    }
     497
     498    // We could go further, and ensure that if the futurePossibleStructure contravenes
     499    // the value, then we could clear both of those things. But that's unlikely to help
     500    // in any realistic scenario, so we don't do it. Simpler is better.
     501    void filterValueByType()
     502    {
     503        if (!!m_type) {
     504            // The type is still non-empty. This implies that regardless of what filtering
     505            // was done, we either didn't have a value to begin with, or that value is still
     506            // valid.
     507            ASSERT(!m_value || validateType(m_value));
     508            return;
     509        }
     510       
     511        // The type has been rendered empty. That means that the value must now be invalid,
     512        // as well.
     513        ASSERT(!m_value || !validateType(m_value));
     514        m_value = JSValue();
     515    }
     516   
     517    void filterArrayModesByType()
     518    {
     519        if (!(m_type & SpecCell))
     520            m_arrayModes = 0;
     521        else if (!(m_type & ~SpecArray))
     522            m_arrayModes &= ALL_ARRAY_ARRAY_MODES;
     523        else if (!(m_type & SpecArray))
     524            m_arrayModes &= ALL_NON_ARRAY_ARRAY_MODES;
     525    }
    447526};
    448527
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp

    r131289 r131982  
    168168    case Array::PossiblyArrayWithContiguousToTail:
    169169    case Array::PossiblyArrayWithContiguousOutOfBounds:
     170    case Array::ToContiguous:
     171        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous)))
     172            return true;
    170173        return value.m_currentKnownStructure.hasSingleton()
    171174            && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType());
     
    174177    case Array::ArrayWithContiguousToTail:
    175178    case Array::ArrayWithContiguousOutOfBounds:
     179        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithContiguous)))
     180            return true;
    176181        return value.m_currentKnownStructure.hasSingleton()
    177182            && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType())
     
    184189    case Array::PossiblyArrayWithArrayStorageToHole:
    185190    case Array::PossiblyArrayWithArrayStorageOutOfBounds:
     191    case Array::ToArrayStorage:
     192    case Array::PossiblyArrayToArrayStorage:
     193        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage)))
     194            return true;
    186195        return value.m_currentKnownStructure.hasSingleton()
    187196            && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType());
     
    189198    case Array::SlowPutArrayStorage:
    190199    case Array::PossiblyArrayWithSlowPutArrayStorage:
     200    case Array::ToSlowPutArrayStorage:
     201        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
     202            return true;
    191203        return value.m_currentKnownStructure.hasSingleton()
    192204            && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType());
     
    195207    case Array::ArrayWithArrayStorageToHole:
    196208    case Array::ArrayWithArrayStorageOutOfBounds:
     209    case Array::ArrayToArrayStorage:
     210        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage)))
     211            return true;
    197212        return value.m_currentKnownStructure.hasSingleton()
    198213            && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType())
     
    200215       
    201216    case Array::ArrayWithSlowPutArrayStorage:
     217        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
     218            return true;
    202219        return value.m_currentKnownStructure.hasSingleton()
    203220            && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType())
    204221            && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
    205        
    206     case ALL_EFFECTFUL_MODES:
    207         return false;
    208222       
    209223    case Array::Arguments:
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h

    r131289 r131982  
    350350}
    351351
     352// This returns the set of array modes that will pass filtering of a CheckArray or
     353// Arrayify with the given mode.
     354inline ArrayModes arrayModesFor(Array::Mode arrayMode)
     355{
     356    switch (arrayMode) {
     357    case Array::Generic:
     358        return ALL_ARRAY_MODES;
     359    case Array::Contiguous:
     360    case Array::ContiguousToTail:
     361    case Array::ContiguousOutOfBounds:
     362    case Array::ToContiguous:
     363        return asArrayModes(NonArrayWithContiguous);
     364    case Array::PossiblyArrayWithContiguous:
     365    case Array::PossiblyArrayWithContiguousToTail:
     366    case Array::PossiblyArrayWithContiguousOutOfBounds:
     367        return asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous);
     368    case ARRAY_WITH_CONTIGUOUS_MODES:
     369        return asArrayModes(ArrayWithContiguous);
     370    case Array::ArrayStorage:
     371    case Array::ArrayStorageToHole:
     372    case Array::ArrayStorageOutOfBounds:
     373    case Array::ToArrayStorage:
     374        return asArrayModes(NonArrayWithArrayStorage);
     375    case Array::ToSlowPutArrayStorage:
     376    case Array::SlowPutArrayStorage:
     377        return asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage);
     378    case Array::PossiblyArrayWithArrayStorage:
     379    case Array::PossiblyArrayWithArrayStorageToHole:
     380    case Array::PossiblyArrayWithArrayStorageOutOfBounds:
     381    case Array::PossiblyArrayToArrayStorage:
     382        return asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage);
     383    case Array::PossiblyArrayWithSlowPutArrayStorage:
     384        return asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage);
     385    case Array::ArrayWithArrayStorage:
     386    case Array::ArrayWithArrayStorageToHole:
     387    case Array::ArrayWithArrayStorageOutOfBounds:
     388    case Array::ArrayToArrayStorage:
     389        return asArrayModes(ArrayWithArrayStorage);
     390    case Array::ArrayWithSlowPutArrayStorage:
     391        return asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage);
     392    default:
     393        return asArrayModes(NonArray);
     394    }
     395}
     396
    352397} } // namespace JSC::DFG
    353398
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r129948 r131982  
    103103            }
    104104               
    105             case CheckArray: {
     105            case CheckArray:
     106            case Arrayify: {
    106107                if (!modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode()))
    107108                    break;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r131868 r131982  
    580580{
    581581    ASSERT(modeIsSpecific(node.arrayMode()));
    582     ASSERT(!modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode()));
    583582   
    584583    SpeculateCellOperand base(this, node.child1());
     584   
     585    if (modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode())) {
     586        GPRTemporary temp(this);
     587        m_jit.loadPtr(
     588            MacroAssembler::Address(base.gpr(), JSObject::butterflyOffset()), temp.gpr());
     589        storageResult(temp.gpr(), m_compileIndex);
     590        return;
     591    }
    585592   
    586593    if (!node.child2()) {
Note: See TracChangeset for help on using the changeset viewer.