Changeset 126715 in webkit


Ignore:
Timestamp:
Aug 26, 2012 3:35:26 PM (12 years ago)
Author:
fpizlo@apple.com
Message:

Array type checks and storage accesses should be uniformly represented and available to CSE
https://bugs.webkit.org/show_bug.cgi?id=95013

Reviewed by Oliver Hunt.

This uniformly breaks up all array accesses into up to three parts:

1) The type check, using a newly introduced CheckArray node, in addition to possibly

a CheckStructure node. We were already inserting the CheckStructure prior to this
patch. The CheckArray node will be automatically eliminated if the thing it was
checking for had already been checked for, either intentionally (a CheckStructure
inserted based on the array profile of this access) or accidentally (some checks,
typically a CheckStructure, inserted for some unrelated operations). The
CheckArray node may not be inserted if the array type is non-specific (Generic or
ForceExit).


2) The storage load using GetIndexedPropertyStorage. Previously, this only worked for

GetByVal. Now it works for all array accesses. The storage load may not be
inserted if the mode of array access does not permit CSE of storage loads (like
non-specific modes or Arguments).


3) The access itself: one of GetByVal, PutByVal, PutByValAlias, ArrayPush, ArrayPop,

GetArrayLength, StringCharAt, or StringCharCodeAt.


This means that the type check can be subjected to CSE even if the CFA isn't smart
enough to reason about it (yet!). It also means that the storage load can always be
subjected to CSE; previously CSE on storage load only worked for array loads and not
other forms of access. Finally, it removes the bizarre behavior that
GetIndexedPropertyStorage previously had: previously, it was responsible for the type
check in some cases, but not others; this made reasoning about the CFA really
confusing.

This change also disables late refinement of array mode, since I decided that
supporting that feature is both confusing and likely unprofitable. The array modes are
now locked in in the first fixup run after prediction propagation. Of course,
refinements from Generic to something else would not have been a problem; we could
reenable those if we thought we really needed to.

  • dfg/DFGAbstractState.cpp:

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

  • dfg/DFGArgumentsSimplificationPhase.cpp:

(JSC::DFG::ArgumentsSimplificationPhase::run):

  • dfg/DFGArrayMode.cpp:

(JSC::DFG::fromStructure):
(DFG):
(JSC::DFG::refineArrayMode):

  • dfg/DFGArrayMode.h:

(DFG):
(JSC::DFG::modeIsJSArray):
(JSC::DFG::lengthNeedsStorage):
(JSC::DFG::modeIsSpecific):
(JSC::DFG::modeSupportsLength):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::ByteCodeParser):
(JSC::DFG::ByteCodeParser::getArrayMode):
(ByteCodeParser):
(JSC::DFG::ByteCodeParser::getArrayModeAndEmitChecks):
(JSC::DFG::ByteCodeParser::handleIntrinsic):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCFGSimplificationPhase.cpp:

(JSC::DFG::CFGSimplificationPhase::mergeBlocks):

  • dfg/DFGCSEPhase.cpp:

(JSC::DFG::CSEPhase::CSEPhase):
(JSC::DFG::CSEPhase::checkStructureElimination):
(CSEPhase):
(JSC::DFG::CSEPhase::checkArrayElimination):
(JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
(JSC::DFG::performCSE):

  • dfg/DFGCSEPhase.h:

(DFG):

  • dfg/DFGCommon.h:
  • dfg/DFGConstantFoldingPhase.cpp:

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

  • dfg/DFGDriver.cpp:

(JSC::DFG::compile):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::checkArray):
(FixupPhase):
(JSC::DFG::FixupPhase::blessArrayOperation):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::Graph):
(DFG):
(JSC::DFG::Graph::dump):
(JSC::DFG::Graph::collectGarbage):

  • dfg/DFGGraph.h:

(Graph):
(JSC::DFG::Graph::vote):
(JSC::DFG::Graph::substitute):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasArrayMode):
(JSC::DFG::Node::setArrayMode):

  • dfg/DFGNodeType.h:

(DFG):

  • dfg/DFGOperations.cpp:
  • dfg/DFGPhase.h:

(DFG):

  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):
(JSC::DFG::PredictionPropagationPhase::mergeDefaultFlags):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::checkArray):
(JSC::DFG::SpeculativeJIT::useChildren):
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
(JSC::DFG::SpeculativeJIT::compileGetArrayLength):

  • dfg/DFGSpeculativeJIT.h:

(SpeculativeJIT):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGStructureCheckHoistingPhase.cpp:

(JSC::DFG::StructureCheckHoistingPhase::run):

Location:
trunk/Source/JavaScriptCore
Files:
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r126712 r126715  
     12012-08-26  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Array type checks and storage accesses should be uniformly represented and available to CSE
     4        https://bugs.webkit.org/show_bug.cgi?id=95013
     5
     6        Reviewed by Oliver Hunt.
     7
     8        This uniformly breaks up all array accesses into up to three parts:
     9       
     10        1) The type check, using a newly introduced CheckArray node, in addition to possibly
     11           a CheckStructure node. We were already inserting the CheckStructure prior to this
     12           patch. The CheckArray node will be automatically eliminated if the thing it was
     13           checking for had already been checked for, either intentionally (a CheckStructure
     14           inserted based on the array profile of this access) or accidentally (some checks,
     15           typically a CheckStructure, inserted for some unrelated operations). The
     16           CheckArray node may not be inserted if the array type is non-specific (Generic or
     17           ForceExit).
     18       
     19        2) The storage load using GetIndexedPropertyStorage. Previously, this only worked for
     20           GetByVal. Now it works for all array accesses. The storage load may not be
     21           inserted if the mode of array access does not permit CSE of storage loads (like
     22           non-specific modes or Arguments).
     23       
     24        3) The access itself: one of GetByVal, PutByVal, PutByValAlias, ArrayPush, ArrayPop,
     25           GetArrayLength, StringCharAt, or StringCharCodeAt.
     26       
     27        This means that the type check can be subjected to CSE even if the CFA isn't smart
     28        enough to reason about it (yet!). It also means that the storage load can always be
     29        subjected to CSE; previously CSE on storage load only worked for array loads and not
     30        other forms of access. Finally, it removes the bizarre behavior that
     31        GetIndexedPropertyStorage previously had: previously, it was responsible for the type
     32        check in some cases, but not others; this made reasoning about the CFA really
     33        confusing.
     34       
     35        This change also disables late refinement of array mode, since I decided that
     36        supporting that feature is both confusing and likely unprofitable. The array modes are
     37        now locked in in the first fixup run after prediction propagation. Of course,
     38        refinements from Generic to something else would not have been a problem; we could
     39        reenable those if we thought we really needed to.
     40
     41        * dfg/DFGAbstractState.cpp:
     42        (JSC::DFG::AbstractState::execute):
     43        * dfg/DFGArgumentsSimplificationPhase.cpp:
     44        (JSC::DFG::ArgumentsSimplificationPhase::run):
     45        * dfg/DFGArrayMode.cpp:
     46        (JSC::DFG::fromStructure):
     47        (DFG):
     48        (JSC::DFG::refineArrayMode):
     49        * dfg/DFGArrayMode.h:
     50        (DFG):
     51        (JSC::DFG::modeIsJSArray):
     52        (JSC::DFG::lengthNeedsStorage):
     53        (JSC::DFG::modeIsSpecific):
     54        (JSC::DFG::modeSupportsLength):
     55        * dfg/DFGByteCodeParser.cpp:
     56        (JSC::DFG::ByteCodeParser::ByteCodeParser):
     57        (JSC::DFG::ByteCodeParser::getArrayMode):
     58        (ByteCodeParser):
     59        (JSC::DFG::ByteCodeParser::getArrayModeAndEmitChecks):
     60        (JSC::DFG::ByteCodeParser::handleIntrinsic):
     61        (JSC::DFG::ByteCodeParser::parseBlock):
     62        * dfg/DFGCFGSimplificationPhase.cpp:
     63        (JSC::DFG::CFGSimplificationPhase::mergeBlocks):
     64        * dfg/DFGCSEPhase.cpp:
     65        (JSC::DFG::CSEPhase::CSEPhase):
     66        (JSC::DFG::CSEPhase::checkStructureElimination):
     67        (CSEPhase):
     68        (JSC::DFG::CSEPhase::checkArrayElimination):
     69        (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination):
     70        (JSC::DFG::CSEPhase::performNodeCSE):
     71        (JSC::DFG::performCSE):
     72        * dfg/DFGCSEPhase.h:
     73        (DFG):
     74        * dfg/DFGCommon.h:
     75        * dfg/DFGConstantFoldingPhase.cpp:
     76        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     77        * dfg/DFGDriver.cpp:
     78        (JSC::DFG::compile):
     79        * dfg/DFGFixupPhase.cpp:
     80        (JSC::DFG::FixupPhase::fixupNode):
     81        (JSC::DFG::FixupPhase::checkArray):
     82        (FixupPhase):
     83        (JSC::DFG::FixupPhase::blessArrayOperation):
     84        * dfg/DFGGraph.cpp:
     85        (JSC::DFG::Graph::Graph):
     86        (DFG):
     87        (JSC::DFG::Graph::dump):
     88        (JSC::DFG::Graph::collectGarbage):
     89        * dfg/DFGGraph.h:
     90        (Graph):
     91        (JSC::DFG::Graph::vote):
     92        (JSC::DFG::Graph::substitute):
     93        * dfg/DFGNode.h:
     94        (JSC::DFG::Node::hasArrayMode):
     95        (JSC::DFG::Node::setArrayMode):
     96        * dfg/DFGNodeType.h:
     97        (DFG):
     98        * dfg/DFGOperations.cpp:
     99        * dfg/DFGPhase.h:
     100        (DFG):
     101        * dfg/DFGPredictionPropagationPhase.cpp:
     102        (JSC::DFG::PredictionPropagationPhase::propagate):
     103        (JSC::DFG::PredictionPropagationPhase::mergeDefaultFlags):
     104        * dfg/DFGSpeculativeJIT.cpp:
     105        (JSC::DFG::SpeculativeJIT::checkArray):
     106        (JSC::DFG::SpeculativeJIT::useChildren):
     107        (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
     108        (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
     109        (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
     110        (JSC::DFG::SpeculativeJIT::compileGetArrayLength):
     111        * dfg/DFGSpeculativeJIT.h:
     112        (SpeculativeJIT):
     113        * dfg/DFGSpeculativeJIT32_64.cpp:
     114        (JSC::DFG::SpeculativeJIT::compile):
     115        * dfg/DFGSpeculativeJIT64.cpp:
     116        (JSC::DFG::SpeculativeJIT::compile):
     117        * dfg/DFGStructureCheckHoistingPhase.cpp:
     118        (JSC::DFG::StructureCheckHoistingPhase::run):
     119
    11202012-08-26  Filip Pizlo  <fpizlo@apple.com>
    2121
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp

    r126494 r126715  
    888888            break;
    889889        case Array::String:
    890             forNode(node.child1()).filter(SpecString);
    891890            forNode(node.child2()).filter(SpecInt32);
    892891            forNode(nodeIndex).set(SpecString);
    893892            break;
    894893        case Array::Arguments:
    895             forNode(node.child1()).filter(SpecArguments);
    896894            forNode(node.child2()).filter(SpecInt32);
    897895            forNode(nodeIndex).makeTop();
     
    901899            // FIXME: We should have more conservative handling of the out-of-bounds
    902900            // case.
    903             forNode(node.child1()).filter(SpecCell);
    904901            forNode(node.child2()).filter(SpecInt32);
    905902            forNode(nodeIndex).makeTop();
    906903            break;
    907904        case Array::Int8Array:
    908             forNode(node.child1()).filter(SpecInt8Array);
    909905            forNode(node.child2()).filter(SpecInt32);
    910906            forNode(nodeIndex).set(SpecInt32);
    911907            break;
    912908        case Array::Int16Array:
    913             forNode(node.child1()).filter(SpecInt16Array);
    914909            forNode(node.child2()).filter(SpecInt32);
    915910            forNode(nodeIndex).set(SpecInt32);
    916911            break;
    917912        case Array::Int32Array:
    918             forNode(node.child1()).filter(SpecInt32Array);
    919913            forNode(node.child2()).filter(SpecInt32);
    920914            forNode(nodeIndex).set(SpecInt32);
    921915            break;
    922916        case Array::Uint8Array:
    923             forNode(node.child1()).filter(SpecUint8Array);
    924917            forNode(node.child2()).filter(SpecInt32);
    925918            forNode(nodeIndex).set(SpecInt32);
    926919            break;
    927920        case Array::Uint8ClampedArray:
    928             forNode(node.child1()).filter(SpecUint8ClampedArray);
    929921            forNode(node.child2()).filter(SpecInt32);
    930922            forNode(nodeIndex).set(SpecInt32);
    931923            break;
    932924        case Array::Uint16Array:
    933             forNode(node.child1()).filter(SpecUint16Array);
    934925            forNode(node.child2()).filter(SpecInt32);
    935926            forNode(nodeIndex).set(SpecInt32);
    936927            break;
    937928        case Array::Uint32Array:
    938             forNode(node.child1()).filter(SpecUint32Array);
    939929            forNode(node.child2()).filter(SpecInt32);
    940930            if (node.shouldSpeculateInteger())
     
    944934            break;
    945935        case Array::Float32Array:
    946             forNode(node.child1()).filter(SpecFloat32Array);
    947936            forNode(node.child2()).filter(SpecInt32);
    948937            forNode(nodeIndex).set(SpecDouble);
    949938            break;
    950939        case Array::Float64Array:
    951             forNode(node.child1()).filter(SpecFloat64Array);
    952940            forNode(node.child2()).filter(SpecInt32);
    953941            forNode(nodeIndex).set(SpecDouble);
     
    960948    case PutByValAlias: {
    961949        node.setCanExit(true);
    962         Edge child1 = m_graph.varArgChild(node, 0);
    963950        Edge child2 = m_graph.varArgChild(node, 1);
    964951        Edge child3 = m_graph.varArgChild(node, 2);
     
    971958            break;
    972959        case Array::JSArray:
    973             forNode(child1).filter(SpecCell);
    974960            forNode(child2).filter(SpecInt32);
    975961            break;
    976962        case Array::JSArrayOutOfBounds:
    977             forNode(child1).filter(SpecCell);
    978963            forNode(child2).filter(SpecInt32);
    979964            clobberWorld(node.codeOrigin, indexInBlock);
    980965            break;
    981966        case Array::Arguments:
    982             forNode(child1).filter(SpecArguments);
    983967            forNode(child2).filter(SpecInt32);
    984968            break;
    985969        case Array::Int8Array:
    986             forNode(child1).filter(SpecInt8Array);
    987970            forNode(child2).filter(SpecInt32);
    988971            if (m_graph[child3].shouldSpeculateInteger())
     
    992975            break;
    993976        case Array::Int16Array:
    994             forNode(child1).filter(SpecInt16Array);
    995977            forNode(child2).filter(SpecInt32);
    996978            if (m_graph[child3].shouldSpeculateInteger())
     
    1000982            break;
    1001983        case Array::Int32Array:
    1002             forNode(child1).filter(SpecInt32Array);
    1003984            forNode(child2).filter(SpecInt32);
    1004985            if (m_graph[child3].shouldSpeculateInteger())
     
    1008989            break;
    1009990        case Array::Uint8Array:
    1010             forNode(child1).filter(SpecUint8Array);
    1011991            forNode(child2).filter(SpecInt32);
    1012992            if (m_graph[child3].shouldSpeculateInteger())
     
    1016996            break;
    1017997        case Array::Uint8ClampedArray:
    1018             forNode(child1).filter(SpecUint8ClampedArray);
    1019998            forNode(child2).filter(SpecInt32);
    1020999            if (m_graph[child3].shouldSpeculateInteger())
     
    10241003            break;
    10251004        case Array::Uint16Array:
    1026             forNode(child1).filter(SpecUint16Array);
    10271005            forNode(child2).filter(SpecInt32);
    10281006            if (m_graph[child3].shouldSpeculateInteger())
     
    10321010            break;
    10331011        case Array::Uint32Array:
    1034             forNode(child1).filter(SpecUint32Array);
    10351012            forNode(child2).filter(SpecInt32);
    10361013            if (m_graph[child3].shouldSpeculateInteger())
     
    10401017            break;
    10411018        case Array::Float32Array:
    1042             forNode(child1).filter(SpecFloat32Array);
    10431019            forNode(child2).filter(SpecInt32);
    10441020            forNode(child3).filter(SpecNumber);
    10451021            break;
    10461022        case Array::Float64Array:
    1047             forNode(child1).filter(SpecFloat64Array);
    10481023            forNode(child2).filter(SpecInt32);
    10491024            forNode(child3).filter(SpecNumber);
     
    10581033    case ArrayPush:
    10591034        node.setCanExit(true);
    1060         forNode(node.child1()).filter(SpecCell);
    10611035        forNode(nodeIndex).set(SpecNumber);
    10621036        break;
     
    10641038    case ArrayPop:
    10651039        node.setCanExit(true);
    1066         forNode(node.child1()).filter(SpecCell);
    10671040        forNode(nodeIndex).makeTop();
    10681041        break;
     
    13481321           
    13491322    case GetArrayLength:
    1350         switch (node.arrayMode()) {
    1351         case Array::Undecided:
    1352             ASSERT_NOT_REACHED();
    1353             break;
    1354         case Array::ForceExit:
    1355             m_isValid = false;
    1356             break;
    1357         case Array::Generic:
    1358             ASSERT_NOT_REACHED();
    1359             break;
    1360         case Array::String:
    1361             node.setCanExit(!isStringSpeculation(forNode(node.child1()).m_type));
    1362             forNode(node.child1()).filter(SpecString);
    1363             forNode(nodeIndex).set(SpecInt32);
    1364             break;
    1365         case Array::JSArray:
    1366             node.setCanExit(true);
    1367             forNode(node.child1()).filter(SpecCell);
    1368             forNode(nodeIndex).set(SpecInt32);
    1369             break;
    1370         case Array::JSArrayOutOfBounds:
    1371             ASSERT_NOT_REACHED();
    1372             break;
    1373         case Array::Arguments:
    1374             node.setCanExit(true);
    1375             forNode(node.child1()).filter(SpecArguments);
    1376             forNode(nodeIndex).set(SpecInt32);
    1377             break;
    1378         case Array::Int8Array:
    1379             node.setCanExit(!isInt8ArraySpeculation(forNode(node.child1()).m_type));
    1380             forNode(node.child1()).filter(SpecInt8Array);
    1381             forNode(nodeIndex).set(SpecInt32);
    1382             break;
    1383         case Array::Int16Array:
    1384             node.setCanExit(!isInt16ArraySpeculation(forNode(node.child1()).m_type));
    1385             forNode(node.child1()).filter(SpecInt16Array);
    1386             forNode(nodeIndex).set(SpecInt32);
    1387             break;
    1388         case Array::Int32Array:
    1389             node.setCanExit(!isInt32ArraySpeculation(forNode(node.child1()).m_type));
    1390             forNode(node.child1()).filter(SpecInt32Array);
    1391             forNode(nodeIndex).set(SpecInt32);
    1392             break;
    1393         case Array::Uint8Array:
    1394             node.setCanExit(!isUint8ArraySpeculation(forNode(node.child1()).m_type));
    1395             forNode(node.child1()).filter(SpecUint8Array);
    1396             forNode(nodeIndex).set(SpecInt32);
    1397             break;
    1398         case Array::Uint8ClampedArray:
    1399             node.setCanExit(!isUint8ClampedArraySpeculation(forNode(node.child1()).m_type));
    1400             forNode(node.child1()).filter(SpecUint8ClampedArray);
    1401             forNode(nodeIndex).set(SpecInt32);
    1402             break;
    1403         case Array::Uint16Array:
    1404             node.setCanExit(!isUint16ArraySpeculation(forNode(node.child1()).m_type));
    1405             forNode(node.child1()).filter(SpecUint16Array);
    1406             forNode(nodeIndex).set(SpecInt32);
    1407             break;
    1408         case Array::Uint32Array:
    1409             node.setCanExit(!isUint32ArraySpeculation(forNode(node.child1()).m_type));
    1410             forNode(node.child1()).filter(SpecUint32Array);
    1411             forNode(nodeIndex).set(SpecInt32);
    1412             break;
    1413         case Array::Float32Array:
    1414             node.setCanExit(!isFloat32ArraySpeculation(forNode(node.child1()).m_type));
    1415             forNode(node.child1()).filter(SpecFloat32Array);
    1416             forNode(nodeIndex).set(SpecInt32);
    1417             break;
    1418         case Array::Float64Array:
    1419             node.setCanExit(!isFloat64ArraySpeculation(forNode(node.child1()).m_type));
    1420             forNode(node.child1()).filter(SpecFloat64Array);
    1421             forNode(nodeIndex).set(SpecInt32);
    1422             break;
    1423         }
     1323        node.setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
     1324        forNode(nodeIndex).set(SpecInt32);
    14241325        break;
    14251326
     
    14931394        forNode(nodeIndex).clear(); // The result is not a JS value.
    14941395        break;
    1495     case GetIndexedPropertyStorage: {
    1496         node.setCanExit(true); // Lies, but this is (almost) always followed by GetByVal, which does exit. So no point in trying to be more precise.
     1396    case CheckArray: {
     1397        if (modeAlreadyChecked(forNode(node.child1()), node.arrayMode())) {
     1398            m_foundConstants = true;
     1399            node.setCanExit(false);
     1400            break;
     1401        }
     1402        node.setCanExit(true); // Lies, but this is followed by operations (like GetByVal) that always exit, so there is no point in us trying to be clever here.
    14971403        switch (node.arrayMode()) {
    14981404        case Array::String:
     
    15051411            forNode(node.child1()).filter(SpecCell);
    15061412            break;
     1413        case Array::Arguments:
     1414            forNode(node.child1()).filter(SpecArguments);
     1415            break;
    15071416        case Array::Int8Array:
    15081417            forNode(node.child1()).filter(SpecInt8Array);
     
    15341443        default:
    15351444            ASSERT_NOT_REACHED();
     1445            break;
     1446        }
     1447        break;
     1448    }
     1449    case GetIndexedPropertyStorage: {
     1450        switch (node.arrayMode()) {
     1451        case Array::String:
     1452            // Strings are weird - we may spec fail if the string was a rope. That is of course
     1453            // stupid, and we should fix that, but for now let's at least be honest about it.
     1454            node.setCanExit(true);
     1455            break;
     1456        default:
     1457            node.setCanExit(false);
    15361458            break;
    15371459        }
  • trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp

    r126387 r126715  
    313313                case StructureTransitionWatchpoint:
    314314                case ForwardStructureTransitionWatchpoint:
     315                case CheckArray:
    315316                    // We don't care about these because if we get uses of the relevant
    316317                    // variable then we can safely get rid of these, too. This of course
     
    477478                case ForwardCheckStructure:
    478479                case StructureTransitionWatchpoint:
    479                 case ForwardStructureTransitionWatchpoint: {
     480                case ForwardStructureTransitionWatchpoint:
     481                case CheckArray: {
    480482                    // We can just get rid of this node, if it references a phantom argument.
    481483                    if (!isOKToOptimize(m_graph[node.child1()]))
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp

    r126387 r126715  
    5252}
    5353
     54Array::Mode fromStructure(Structure* structure, bool makeSafe)
     55{
     56    return fromObserved(arrayModeFromStructure(structure), makeSafe);
     57}
     58
    5459Array::Mode refineArrayMode(Array::Mode arrayMode, SpeculatedType base, SpeculatedType index)
    5560{
     
    6570        return Array::Generic;
    6671   
    67     // Pass through any array modes that would have been decided by the array profile, since
    68     // the predictions of the inputs will not tell us anything useful that we didn't already
    69     // get from the array profile.
    70     switch (arrayMode) {
    71     case Array::ForceExit:
    72     case Array::JSArray:
    73     case Array::JSArrayOutOfBounds:
     72    if (arrayMode != Array::Undecided)
    7473        return arrayMode;
    75     default:
    76         break;
    77     }
    7874   
    7975    if (isStringSpeculation(base))
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h

    r126387 r126715  
    6464Array::Mode fromObserved(ArrayModes modes, bool makeSafe);
    6565
     66Array::Mode fromStructure(Structure*, bool makeSafe);
     67
    6668Array::Mode refineArrayMode(Array::Mode, SpeculatedType base, SpeculatedType index);
    6769
     
    6971
    7072const char* modeToString(Array::Mode);
     73
     74inline bool modeIsJSArray(Array::Mode arrayMode)
     75{
     76    switch (arrayMode) {
     77    case Array::JSArray:
     78    case Array::JSArrayOutOfBounds:
     79        return true;
     80    default:
     81        return false;
     82    }
     83}
    7184
    7285inline bool canCSEStorage(Array::Mode arrayMode)
     
    8194        return true;
    8295    }
     96}
     97
     98inline bool lengthNeedsStorage(Array::Mode arrayMode)
     99{
     100    return modeIsJSArray(arrayMode);
    83101}
    84102
     
    116134}
    117135
    118 inline bool modeSupportsLength(Array::Mode mode)
     136inline bool modeIsSpecific(Array::Mode mode)
    119137{
    120138    switch (mode) {
     
    128146}
    129147
     148inline bool modeSupportsLength(Array::Mode mode)
     149{
     150    return modeIsSpecific(mode);
     151}
     152
    130153} } // namespace JSC::DFG
    131154
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r126695 r126715  
    7272        , m_haveBuiltOperandMaps(false)
    7373        , m_emptyJSValueIndex(UINT_MAX)
     74        , m_currentInstruction(0)
    7475    {
    7576        ASSERT(m_profiledBlock);
     
    819820    }
    820821   
    821     Array::Mode getArrayModeWithoutOSRExit(Instruction* currentInstruction, NodeIndex base)
    822     {
    823         ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     822    Array::Mode getArrayMode(ArrayProfile* profile)
     823    {
     824        profile->computeUpdatedPrediction();
     825        return fromObserved(profile->observedArrayModes(), false);
     826    }
     827   
     828    Array::Mode getArrayModeAndEmitChecks(ArrayProfile* profile, NodeIndex base)
     829    {
    824830        profile->computeUpdatedPrediction();
    825831        if (profile->hasDefiniteStructure())
     
    839845    }
    840846   
    841     Array::Mode getArrayMode(Instruction* currentInstruction, NodeIndex base)
    842     {
    843         Array::Mode result = getArrayModeWithoutOSRExit(currentInstruction, base);
    844        
    845         if (result == Array::ForceExit)
    846             addToGraph(ForceOSRExit);
    847        
    848         return result;
    849     }
    850 
    851847    NodeIndex makeSafe(NodeIndex nodeIndex)
    852848    {
     
    11511147    // Cache of code blocks that we've generated bytecode for.
    11521148    ByteCodeCache<canInlineFunctionFor> m_codeBlockCache;
     1149   
     1150    Instruction* m_currentInstruction;
    11531151};
    11541152
     
    15541552            return false;
    15551553       
    1556         NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
     1554        Array::Mode arrayMode = getArrayMode(m_currentInstruction[5].u.arrayProfile);
     1555        if (!modeIsJSArray(arrayMode))
     1556            return false;
     1557        NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
    15571558        if (usesResult)
    15581559            set(resultOperand, arrayPush);
     
    15651566            return false;
    15661567       
    1567         NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)));
     1568        Array::Mode arrayMode = getArrayMode(m_currentInstruction[5].u.arrayProfile);
     1569        if (!modeIsJSArray(arrayMode))
     1570            return false;
     1571        NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0)));
    15681572        if (usesResult)
    15691573            set(resultOperand, arrayPop);
     
    17931797        // Switch on the current bytecode opcode.
    17941798        Instruction* currentInstruction = instructionsBegin + m_currentIndex;
     1799        m_currentInstruction = currentInstruction; // Some methods want to use this, and we'd rather not thread it through calls.
    17951800        OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction->u.opcode);
    17961801        switch (opcodeID) {
     
    21782183           
    21792184            NodeIndex base = get(currentInstruction[2].u.operand);
    2180             Array::Mode arrayMode = getArrayMode(currentInstruction, base);
     2185            Array::Mode arrayMode = getArrayModeAndEmitChecks(currentInstruction[4].u.arrayProfile, base);
    21812186            NodeIndex property = get(currentInstruction[3].u.operand);
    21822187            NodeIndex getByVal = addToGraph(GetByVal, OpInfo(arrayMode), OpInfo(prediction), base, property);
     
    21892194            NodeIndex base = get(currentInstruction[1].u.operand);
    21902195
    2191             Array::Mode arrayMode = getArrayMode(currentInstruction, base);
     2196            Array::Mode arrayMode = getArrayModeAndEmitChecks(currentInstruction[4].u.arrayProfile, base);
    21922197           
    21932198            NodeIndex property = get(currentInstruction[2].u.operand);
     
    21972202            addVarArgChild(property);
    21982203            addVarArgChild(value);
     2204            addVarArgChild(NoNode); // Leave room for property storage.
    21992205            addToGraph(Node::VarArg, PutByVal, OpInfo(arrayMode), OpInfo(0));
    22002206
  • trunk/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp

    r126494 r126715  
    660660                    for (unsigned childIdx = node.firstChild();
    661661                         childIdx < node.firstChild() + node.numChildren();
    662                          ++childIdx)
    663                         fixPossibleGetLocal(firstBlock, m_graph.m_varArgChildren[childIdx], changeRef);
     662                         ++childIdx) {
     663                        if (!!m_graph.m_varArgChildren[childIdx])
     664                            fixPossibleGetLocal(firstBlock, m_graph.m_varArgChildren[childIdx], changeRef);
     665                    }
    664666                } else if (!!node.child1()) {
    665667                    fixPossibleGetLocal(firstBlock, node.children.child1(), changeRef);
  • trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp

    r126387 r126715  
    3636class CSEPhase : public Phase {
    3737public:
    38     CSEPhase(Graph& graph, OptimizationFixpointState fixpointState)
     38    CSEPhase(Graph& graph)
    3939        : Phase(graph, "common subexpression elimination")
    40         , m_fixpointState(fixpointState)
    4140    {
    4241        // Replacements are used to implement local common subexpression elimination.
     
    328327    }
    329328
    330     bool checkStructureLoadElimination(const StructureSet& structureSet, NodeIndex child1)
     329    bool checkStructureElimination(const StructureSet& structureSet, NodeIndex child1)
    331330    {
    332331        for (unsigned i = m_indexInBlock; i--;) {
     
    625624        return NoNode;
    626625    }
    627 
    628     NodeIndex getIndexedPropertyStorageLoadElimination(NodeIndex child1, bool hasIntegerIndexPrediction)
     626   
     627    bool checkArrayElimination(NodeIndex child1, Array::Mode arrayMode)
    629628    {
    630629        for (unsigned i = m_indexInBlock; i--;) {
     
    635634            Node& node = m_graph[index];
    636635            switch (node.op()) {
     636            case PutByOffset:
     637            case PutStructure:
     638                // Changing the structure or putting to the storage cannot
     639                // change the property storage pointer.
     640                break;
     641               
     642            case CheckArray:
     643                if (node.child1() == child1 && node.arrayMode() == arrayMode)
     644                    return true;
     645                break;
     646               
     647            default:
     648                if (m_graph.clobbersWorld(index))
     649                    return false;
     650                break;
     651            }
     652        }
     653        return false;
     654    }
     655
     656    NodeIndex getIndexedPropertyStorageLoadElimination(NodeIndex child1, Array::Mode arrayMode)
     657    {
     658        for (unsigned i = m_indexInBlock; i--;) {
     659            NodeIndex index = m_currentBlock->at(i);
     660            if (index == child1)
     661                break;
     662
     663            Node& node = m_graph[index];
     664            switch (node.op()) {
    637665            case GetIndexedPropertyStorage: {
    638                 SpeculatedType basePrediction = m_graph[node.child2()].prediction();
    639                 bool nodeHasIntegerIndexPrediction = !(!(basePrediction & SpecInt32) && basePrediction);
    640                 if (node.child1() == child1 && hasIntegerIndexPrediction == nodeHasIntegerIndexPrediction)
     666                if (node.child1() == child1 && node.arrayMode() == arrayMode)
    641667                    return index;
    642668                break;
     
    9891015            // FIXME: We should be able to remove SetLocals that can exit; we just need
    9901016            // to replace them with appropriate type checks.
    991             if (m_fixpointState == FixpointNotConverged) {
     1017            if (m_graph.m_fixpointState == FixpointNotConverged) {
    9921018                // Need to be conservative at this time; if the SetLocal has any chance of performing
    9931019                // any speculations then we cannot do anything.
     
    10781104        case PutGlobalVar:
    10791105        case PutGlobalVarCheck:
    1080             if (m_fixpointState == FixpointNotConverged)
     1106            if (m_graph.m_fixpointState == FixpointNotConverged)
    10811107                break;
    10821108            eliminate(globalVarStoreElimination(node.registerPointer()));
     
    11041130        case CheckStructure:
    11051131        case ForwardCheckStructure:
    1106             if (checkStructureLoadElimination(node.structureSet(), node.child1().index()))
     1132            if (checkStructureElimination(node.structureSet(), node.child1().index()))
    11071133                eliminate();
    11081134            break;
     
    11151141           
    11161142        case PutStructure:
    1117             if (m_fixpointState == FixpointNotConverged)
     1143            if (m_graph.m_fixpointState == FixpointNotConverged)
    11181144                break;
    11191145            eliminate(putStructureStoreElimination(node.child1().index()), PhantomPutStructure);
     
    11251151            break;
    11261152               
     1153        case CheckArray:
     1154            if (checkArrayElimination(node.child1().index(), node.arrayMode()))
     1155                eliminate();
     1156            break;
     1157           
    11271158        case GetIndexedPropertyStorage: {
    1128             SpeculatedType basePrediction = m_graph[node.child2()].prediction();
    1129             bool nodeHasIntegerIndexPrediction = !(!(basePrediction & SpecInt32) && basePrediction);
    1130             setReplacement(getIndexedPropertyStorageLoadElimination(node.child1().index(), nodeHasIntegerIndexPrediction));
     1159            setReplacement(getIndexedPropertyStorageLoadElimination(node.child1().index(), node.arrayMode()));
    11311160            break;
    11321161        }
     
    11411170           
    11421171        case PutByOffset:
    1143             if (m_fixpointState == FixpointNotConverged)
     1172            if (m_graph.m_fixpointState == FixpointNotConverged)
    11441173                break;
    11451174            eliminate(putByOffsetStoreElimination(m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber, node.child1().index()));
     
    11791208    Vector<NodeIndex, 16> m_replacements;
    11801209    FixedArray<unsigned, LastNodeType> m_lastSeen;
    1181     OptimizationFixpointState m_fixpointState;
    11821210    bool m_changed; // Only tracks changes that have a substantive effect on other optimizations.
    11831211};
    11841212
    1185 bool performCSE(Graph& graph, OptimizationFixpointState fixpointState)
     1213bool performCSE(Graph& graph)
    11861214{
    11871215    SamplingRegion samplingRegion("DFG CSE Phase");
    1188     return runPhase<CSEPhase>(graph, fixpointState);
     1216    return runPhase<CSEPhase>(graph);
    11891217}
    11901218
  • trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.h

    r118468 r126715  
    4242// on a few benchmarks, and is relatively cheap to run.
    4343
    44 bool performCSE(Graph&, OptimizationFixpointState);
     44bool performCSE(Graph&);
    4545
    4646} } // namespace JSC::DFG
  • trunk/Source/JavaScriptCore/dfg/DFGCommon.h

    r121798 r126715  
    133133enum NoResultTag { NoResult };
    134134
    135 enum OptimizationFixpointState { FixpointConverged, FixpointNotConverged };
     135enum OptimizationFixpointState { BeforeFixpoint, FixpointNotConverged, FixpointConverged };
    136136
    137137inline bool shouldShowDisassembly()
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r125999 r126715  
    102102                break;
    103103            }
    104                    
     104               
     105            case CheckArray: {
     106                if (!modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode()))
     107                    break;
     108                ASSERT(node.refCount() == 1);
     109                node.setOpAndDefaultFlags(Phantom);
     110                eliminated = true;
     111                break;
     112            }
     113               
    105114            default:
    106115                break;
  • trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp

    r126689 r126715  
    117117    performStructureCheckHoisting(dfg);
    118118    unsigned cnt = 1;
     119    dfg.m_fixpointState = FixpointNotConverged;
    119120    for (;; ++cnt) {
    120121#if DFG_ENABLE(DEBUG_VERBOSE)
     
    126127        changed |= performArgumentsSimplification(dfg);
    127128        changed |= performCFGSimplification(dfg);
    128         changed |= performCSE(dfg, FixpointNotConverged);
     129        changed |= performCSE(dfg);
    129130        if (!changed)
    130131            break;
     
    132133        performFixup(dfg);
    133134    }
    134     performCSE(dfg, FixpointConverged);
     135    dfg.m_fixpointState = FixpointConverged;
     136    performCSE(dfg);
    135137#if DFG_ENABLE(DEBUG_VERBOSE)
    136138    dataLog("DFG optimization fixpoint converged in %u iterations.\n", cnt);
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r126387 r126715  
    7575        switch (op) {
    7676        case GetById: {
     77            if (m_graph.m_fixpointState > BeforeFixpoint)
     78                break;
     79           
    7780            Node* nodePtr = &node;
    7881           
     
    9194                    m_graph[node.child1()].prediction(),
    9295                    m_graph[m_compileIndex].prediction());                   
    93                 if (modeSupportsLength(arrayMode)
    94                     && arrayProfile->hasDefiniteStructure()) {
     96                if (modeSupportsLength(arrayMode) && arrayProfile->hasDefiniteStructure()) {
    9597                    m_graph.ref(nodePtr->child1());
    9698                    Node checkStructure(CheckStructure, nodePtr->codeOrigin, OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())), nodePtr->child1().index());
     
    114116            m_graph.deref(m_compileIndex);
    115117            nodePtr->setArrayMode(arrayMode);
     118           
     119            NodeIndex storage = checkArray(arrayMode, nodePtr->codeOrigin, nodePtr->child1().index(), lengthNeedsStorage, nodePtr->shouldGenerate());
     120            if (storage == NoNode)
     121                break;
     122           
     123            nodePtr = &m_graph[m_compileIndex];
     124            nodePtr->children.child2() = Edge(storage);
    116125            break;
    117126        }
    118127        case GetIndexedPropertyStorage: {
    119             node.setArrayMode(
    120                 refineArrayMode(
    121                     node.arrayMode(),
    122                     m_graph[node.child1()].prediction(),
    123                     m_graph[node.child2()].prediction()));
    124             // Predictions should only become more, rather than less, refined. Hence
    125             // if we were ever able to CSE the storage pointer for this operation,
    126             // then we should always continue to be able to do so.
    127128            ASSERT(canCSEStorage(node.arrayMode()));
    128129            break;
     
    137138                    m_graph[node.child2()].prediction()));
    138139           
    139             if (canCSEStorage(node.arrayMode())) {
    140                 if (node.child3()) {
    141                     ASSERT(m_graph[node.child3()].op() == GetIndexedPropertyStorage);
    142                     ASSERT(modesCompatibleForStorageLoad(m_graph[node.child3()].arrayMode(), node.arrayMode()));
    143                 } else {
    144                     // Make sure we don't use the node reference after we do the append.
    145                     Node getIndexedPropertyStorage(
    146                         GetIndexedPropertyStorage, node.codeOrigin, OpInfo(node.arrayMode()),
    147                         node.child1().index(), node.child2().index());
    148                     NodeIndex getIndexedPropertyStorageIndex = m_graph.size();
    149                     node.children.child3() = Edge(getIndexedPropertyStorageIndex);
    150                     m_graph.append(getIndexedPropertyStorage);
    151                     m_graph.ref(getIndexedPropertyStorageIndex); // Once because it's MustGenerate.
    152                     m_graph.ref(getIndexedPropertyStorageIndex); // And again because it's referenced from the GetByVal.
    153                     m_insertionSet.append(m_indexInBlock, getIndexedPropertyStorageIndex);
    154                 }
    155             } else {
    156                 // See above. Continued fixup of the graph should not regress our ability
    157                 // to speculate.
    158                 ASSERT(!node.child3());
    159             }
    160             break;
     140            blessArrayOperation(node.child1(), 2);
     141            break;
     142        }
     143           
     144        case ArrayPush: {
     145            blessArrayOperation(node.child1(), 2);
     146            break;
     147        }
     148           
     149        case ArrayPop: {
     150            blessArrayOperation(node.child1(), 1);
    161151        }
    162152           
     
    331321            Edge child2 = m_graph.varArgChild(node, 1);
    332322            Edge child3 = m_graph.varArgChild(node, 2);
     323
    333324            node.setArrayMode(
    334325                refineArrayMode(
    335                     node.arrayMode(), m_graph[child1].prediction(), m_graph[child2].prediction()));
    336            
    337             switch (modeForPut(node.arrayMode())) {
     326                    node.arrayMode(),
     327                    m_graph[child1].prediction(),
     328                    m_graph[child2].prediction()));
     329           
     330            blessArrayOperation(child1, 3);
     331           
     332            Node* nodePtr = &m_graph[m_compileIndex];
     333           
     334            switch (modeForPut(nodePtr->arrayMode())) {
    338335            case Array::Int8Array:
    339336            case Array::Int16Array:
     
    369366    }
    370367   
     368    NodeIndex checkArray(Array::Mode arrayMode, CodeOrigin codeOrigin, NodeIndex array, bool (*storageCheck)(Array::Mode) = canCSEStorage, bool shouldGenerate = true)
     369    {
     370        ASSERT(modeIsSpecific(arrayMode));
     371       
     372        m_graph.ref(array);
     373        Node checkArray(CheckArray, codeOrigin, OpInfo(arrayMode), array);
     374        checkArray.ref();
     375        NodeIndex checkArrayIndex = m_graph.size();
     376        m_graph.append(checkArray);
     377        m_insertionSet.append(m_indexInBlock, checkArrayIndex);
     378
     379        if (!storageCheck(arrayMode))
     380            return NoNode;
     381       
     382        if (shouldGenerate)
     383            m_graph.ref(array);
     384        Node getIndexedPropertyStorage(
     385            GetIndexedPropertyStorage, codeOrigin, OpInfo(arrayMode), array);
     386        if (shouldGenerate)
     387            getIndexedPropertyStorage.ref();
     388        NodeIndex getIndexedPropertyStorageIndex = m_graph.size();
     389        m_graph.append(getIndexedPropertyStorage);
     390        m_insertionSet.append(m_indexInBlock, getIndexedPropertyStorageIndex);
     391       
     392        return getIndexedPropertyStorageIndex;
     393    }
     394   
     395    void blessArrayOperation(Edge base, unsigned storageChildIdx)
     396    {
     397        if (m_graph.m_fixpointState > BeforeFixpoint)
     398            return;
     399           
     400        Node* nodePtr = &m_graph[m_compileIndex];
     401       
     402        if (nodePtr->arrayMode() == Array::ForceExit) {
     403            Node forceExit(ForceOSRExit, nodePtr->codeOrigin);
     404            forceExit.ref();
     405            NodeIndex forceExitIndex = m_graph.size();
     406            m_graph.append(forceExit);
     407            m_insertionSet.append(m_indexInBlock, forceExitIndex);
     408            return;
     409        }
     410       
     411        if (!modeIsSpecific(nodePtr->arrayMode()))
     412            return;
     413           
     414        NodeIndex storage = checkArray(nodePtr->arrayMode(), nodePtr->codeOrigin, base.index());
     415        if (storage == NoNode)
     416            return;
     417           
     418        m_graph.child(m_graph[m_compileIndex], storageChildIdx) = Edge(storage);
     419    }
     420   
    371421    void fixIntEdge(Edge& edge)
    372422    {
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r126387 r126715  
    4040#undef STRINGIZE_DFG_OP_ENUM
    4141};
     42
     43Graph::Graph(JSGlobalData& globalData, CodeBlock* codeBlock, unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues)
     44    : m_globalData(globalData)
     45    , m_codeBlock(codeBlock)
     46    , m_profiledBlock(codeBlock->alternative())
     47    , m_hasArguments(false)
     48    , m_osrEntryBytecodeIndex(osrEntryBytecodeIndex)
     49    , m_mustHandleValues(mustHandleValues)
     50    , m_fixpointState(BeforeFixpoint)
     51{
     52    ASSERT(m_profiledBlock);
     53}
    4254
    4355const char *Graph::opName(NodeType op)
     
    180192            else
    181193                hasPrinted = true;
     194            if (!m_varArgChildren[childIdx])
     195                continue;
    182196            dataLog("%s@%u%s",
    183197                    useKindToString(m_varArgChildren[childIdx].useKind()),
     
    393407            for (unsigned _childIdx = _node.firstChild();               \
    394408                 _childIdx < _node.firstChild() + _node.numChildren();  \
    395                  _childIdx++)                                           \
    396                 thingToDo(m_varArgChildren[_childIdx]);                 \
     409                 _childIdx++) {                                         \
     410                if (!!m_varArgChildren[_childIdx])                      \
     411                    thingToDo(m_varArgChildren[_childIdx]);             \
     412            }                                                           \
    397413        } else {                                                        \
    398414            if (!_node.child1()) {                                      \
     
    484500                 childIdx < node.firstChild() + node.numChildren();
    485501                 ++childIdx) {
     502                if (!m_varArgChildren[childIdx])
     503                    continue;
    486504                NodeIndex childNodeIndex = m_varArgChildren[childIdx].index();
    487505                if (!at(childNodeIndex).ref())
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r126712 r126715  
    6969class Graph : public Vector<Node, 64> {
    7070public:
    71     Graph(JSGlobalData& globalData, CodeBlock* codeBlock, unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues)
    72         : m_globalData(globalData)
    73         , m_codeBlock(codeBlock)
    74         , m_profiledBlock(codeBlock->alternative())
    75         , m_hasArguments(false)
    76         , m_osrEntryBytecodeIndex(osrEntryBytecodeIndex)
    77         , m_mustHandleValues(mustHandleValues)
    78     {
    79         ASSERT(m_profiledBlock);
    80     }
     71    Graph(JSGlobalData&, CodeBlock*, unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues);
    8172   
    8273    using Vector<Node, 64>::operator[];
     
    578569            for (unsigned childIdx = node.firstChild();
    579570                 childIdx < node.firstChild() + node.numChildren();
    580                  childIdx++)
    581                 vote(m_varArgChildren[childIdx], ballot);
     571                 childIdx++) {
     572                if (!!m_varArgChildren[childIdx])
     573                    vote(m_varArgChildren[childIdx], ballot);
     574            }
    582575            return;
    583576        }
     
    601594            Node& node = at(nodeIndex);
    602595            if (node.flags() & NodeHasVarArgs) {
    603                 for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); ++childIdx)
    604                     compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing, node.shouldGenerate());
     596                for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); ++childIdx) {
     597                    if (!!m_varArgChildren[childIdx])
     598                        compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing, node.shouldGenerate());
     599                }
    605600                continue;
    606601            }
     
    678673    unsigned m_osrEntryBytecodeIndex;
    679674    Operands<JSValue> m_mustHandleValues;
     675   
     676    OptimizationFixpointState m_fixpointState;
    680677private:
    681678   
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r126387 r126715  
    744744        case StringCharAt:
    745745        case StringCharCodeAt:
     746        case CheckArray:
     747        case ArrayPush:
     748        case ArrayPop:
    746749            return true;
    747750        default:
     
    756759    }
    757760   
    758     void setArrayMode(Array::Mode arrayMode)
     761    bool setArrayMode(Array::Mode arrayMode)
    759762    {
    760763        ASSERT(hasArrayMode());
     764        if (this->arrayMode() == arrayMode)
     765            return false;
    761766        m_opInfo = arrayMode;
     767        return true;
    762768    }
    763769   
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r126387 r126715  
    139139    macro(ReallocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \
    140140    macro(GetPropertyStorage, NodeResultStorage) \
    141     macro(GetIndexedPropertyStorage, NodeMustGenerate | NodeResultStorage) \
     141    macro(CheckArray, NodeMustGenerate) \
     142    macro(GetIndexedPropertyStorage, NodeResultStorage) \
    142143    macro(GetByOffset, NodeResultJS) \
    143144    macro(PutByOffset, NodeMustGenerate) \
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r126494 r126715  
    576576}
    577577
     578EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
     579{
     580    JSGlobalData* globalData = &exec->globalData();
     581    NativeCallFrameTracer tracer(globalData, exec);
     582   
     583    return JSValue::encode(array->pop(exec));
     584}
     585       
    578586EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument)
    579587{
     
    602610    JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
    603611    return asRegExpObject(base)->test(exec, input);
    604 }
    605        
    606 EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
    607 {
    608     JSGlobalData* globalData = &exec->globalData();
    609     NativeCallFrameTracer tracer(globalData, exec);
    610    
    611     return JSValue::encode(array->pop(exec));
    612612}
    613613       
  • trunk/Source/JavaScriptCore/dfg/DFGPhase.h

    r122167 r126715  
    9696}
    9797
    98 template<typename PhaseType, typename ArgumentType1>
    99 bool runPhase(Graph& graph, ArgumentType1 arg1)
    100 {
    101     PhaseType phase(graph, arg1);
    102     return runAndLog(phase);
    103 }
    104 
    10598} } // namespace JSC::DFG
    10699
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r126387 r126715  
    619619        case GetMyArgumentByVal:
    620620        case PhantomPutStructure:
    621         case PhantomArguments: {
     621        case PhantomArguments:
     622        case CheckArray: {
    622623            // This node should never be visible at this stage of compilation. It is
    623624            // inserted by fixup(), which follows this phase.
     
    704705            for (unsigned childIdx = node.firstChild();
    705706                 childIdx < node.firstChild() + node.numChildren();
    706                  childIdx++)
    707                 changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsValue);
     707                 childIdx++) {
     708                if (!!m_graph.m_varArgChildren[childIdx])
     709                    changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsValue);
     710            }
    708711        } else {
    709712            if (!node.child1())
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r126387 r126715  
    296296}
    297297
    298 const TypedArrayDescriptor* SpeculativeJIT::speculateArray(Array::Mode arrayMode, Edge edge, GPRReg baseReg)
    299 {
    300     const TypedArrayDescriptor* result = typedArrayDescriptor(arrayMode);
    301    
    302     if (modeAlreadyChecked(m_state.forNode(edge), arrayMode))
    303         return result;
     298void SpeculativeJIT::checkArray(Node& node)
     299{
     300    ASSERT(modeIsSpecific(node.arrayMode()));
     301   
     302    SpeculateCellOperand base(this, node.child1());
     303    GPRReg baseReg = base.gpr();
     304   
     305    const TypedArrayDescriptor* result = typedArrayDescriptor(node.arrayMode());
     306   
     307    if (modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode())) {
     308        noResult(m_compileIndex);
     309        return;
     310    }
    304311   
    305312    const ClassInfo* expectedClassInfo = 0;
    306313   
    307     switch (arrayMode) {
    308     case Array::ForceExit:
    309         ASSERT_NOT_REACHED();
    310         terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
    311         return result;
     314    switch (node.arrayMode()) {
    312315    case Array::String:
    313316        expectedClassInfo = &JSString::s_info;
     
    326329                MacroAssembler::Address(temp.gpr(), Structure::classInfoOffset()),
    327330                MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    328         return result;
     331       
     332        noResult(m_compileIndex);
     333        return;
    329334    }
    330335    case Array::Arguments:
     
    357362            MacroAssembler::TrustedImmPtr(expectedClassInfo)));
    358363   
    359     return result;
     364    noResult(m_compileIndex);
    360365}
    361366
     
    394399{
    395400    if (node.flags() & NodeHasVarArgs) {
    396         for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
    397             use(m_jit.graph().m_varArgChildren[childIdx]);
     401        for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) {
     402            if (!!m_jit.graph().m_varArgChildren[childIdx])
     403                use(m_jit.graph().m_varArgChildren[childIdx]);
     404        }
    398405    } else {
    399406        Edge child1 = node.child1();
     
    21472154void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySignedness signedness, TypedArrayRounding rounding)
    21482155{
     2156    StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
     2157    GPRReg storageReg = storage.gpr();
     2158   
    21492159    Edge valueUse = m_jit.graph().varArgChild(node, 2);
    21502160   
     
    22142224    ASSERT_UNUSED(valueGPR, valueGPR != property);
    22152225    ASSERT(valueGPR != base);
    2216     GPRTemporary storage(this);
    2217     GPRReg storageReg = storage.gpr();
    22182226    ASSERT(valueGPR != storageReg);
    2219     m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
    22202227    MacroAssembler::Jump outOfBounds;
    22212228    if (node.op() == PutByVal)
     
    22792286void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize)
    22802287{
     2288    StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
     2289    GPRReg storageReg = storage.gpr();
     2290   
    22812291    Edge baseUse = m_jit.graph().varArgChild(node, 0);
    22822292    Edge valueUse = m_jit.graph().varArgChild(node, 2);
     
    22882298    GPRTemporary result(this);
    22892299   
    2290     GPRTemporary storage(this);
    2291     GPRReg storageReg = storage.gpr();
    2292    
    2293     m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
    22942300    MacroAssembler::Jump outOfBounds;
    22952301    if (node.op() == PutByVal)
     
    31103116    GPRReg storageReg = storage.gpr();
    31113117   
    3112     const TypedArrayDescriptor* descriptor =
    3113         speculateArray(node.arrayMode(), node.child1(), baseReg);
     3118    const TypedArrayDescriptor* descriptor = typedArrayDescriptor(node.arrayMode());
    31143119   
    31153120    switch (node.arrayMode()) {
     
    32533258void SpeculativeJIT::compileGetArrayLength(Node& node)
    32543259{
    3255     SpeculateCellOperand base(this, node.child1());
    3256     GPRTemporary result(this);
    3257        
    3258     GPRReg baseGPR = base.gpr();
    3259     GPRReg resultGPR = result.gpr();
    3260        
    3261     const TypedArrayDescriptor* descriptor =
    3262         speculateArray(node.arrayMode(), node.child1(), baseGPR);
     3260    const TypedArrayDescriptor* descriptor = typedArrayDescriptor(node.arrayMode());
    32633261
    32643262    switch (node.arrayMode()) {
    32653263    case Array::JSArray:
    3266     case Array::JSArrayOutOfBounds:
    3267         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
    3268         m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
     3264    case Array::JSArrayOutOfBounds: {
     3265        StorageOperand storage(this, node.child2());
     3266        GPRTemporary result(this, storage);
     3267        GPRReg storageReg = storage.gpr();
     3268        GPRReg resultReg = result.gpr();
     3269        m_jit.load32(MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultReg);
    32693270           
    3270         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultGPR, MacroAssembler::TrustedImm32(0)));
     3271        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultReg, MacroAssembler::TrustedImm32(0)));
    32713272           
    3272         integerResult(resultGPR, m_compileIndex);
     3273        integerResult(resultReg, m_compileIndex);
    32733274        break;
    3274     case Array::String:
     3275    }
     3276    case Array::String: {
     3277        SpeculateCellOperand base(this, node.child1());
     3278        GPRTemporary result(this, base);
     3279        GPRReg baseGPR = base.gpr();
     3280        GPRReg resultGPR = result.gpr();
    32753281        m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
    32763282        integerResult(resultGPR, m_compileIndex);
    32773283        break;
    3278     case Array::Arguments:
     3284    }
     3285    case Array::Arguments: {
    32793286        compileGetArgumentsLength(node);
    32803287        break;
     3288    }
    32813289    default:
     3290        SpeculateCellOperand base(this, node.child1());
     3291        GPRTemporary result(this, base);
     3292        GPRReg baseGPR = base.gpr();
     3293        GPRReg resultGPR = result.gpr();
    32823294        ASSERT(descriptor);
    32833295        m_jit.load32(MacroAssembler::Address(baseGPR, descriptor->m_lengthOffset), resultGPR);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r126387 r126715  
    21982198    const TypedArrayDescriptor* typedArrayDescriptor(Array::Mode);
    21992199   
    2200     const TypedArrayDescriptor* speculateArray(Array::Mode, Edge baseEdge, GPRReg baseReg);
     2200    void checkArray(Node&);
    22012201   
    22022202    template<bool strict>
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r126695 r126715  
    23742374        break;
    23752375    }
     2376       
     2377    case CheckArray: {
     2378        checkArray(node);
     2379        break;
     2380    }
    23762381
    23772382    case GetByVal: {
     
    24712476        Edge child2 = m_jit.graph().varArgChild(node, 1);
    24722477        Edge child3 = m_jit.graph().varArgChild(node, 2);
     2478        Edge child4 = m_jit.graph().varArgChild(node, 3);
    24732479       
    24742480        Array::Mode arrayMode = modeForPut(node.arrayMode());
     
    25142520        GPRReg propertyReg = property.gpr();
    25152521
    2516         speculateArray(arrayMode, child1, baseReg);
    2517 
    25182522        switch (arrayMode) {
    25192523        case Array::JSArray:
     
    25322536                writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratchReg);
    25332537            }
     2538           
     2539            StorageOperand storage(this, child4);
     2540            GPRReg storageReg = storage.gpr();
    25342541
    25352542            if (node.op() == PutByValAlias) {
    2536                 // Get the array storage.
    2537                 GPRTemporary storage(this);
    2538                 GPRReg storageReg = storage.gpr();
    2539                 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
    2540                
    25412543                // Store the value to the array.
    25422544                GPRReg propertyReg = property.gpr();
     
    25552557            property.use();
    25562558            value.use();
    2557            
    2558             // Get the array storage.
    2559             GPRTemporary storage(this);
    2560             GPRReg storageReg = storage.gpr();
    2561             m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
    2562 
     2559            storage.use();
     2560           
    25632561            // Check if we're writing to a hole; if so increment m_numValuesInVector.
    25642562            MacroAssembler::Jump notHoleValue = m_jit.branch32(MacroAssembler::NotEqual, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
     
    26892687       
    26902688    case ArrayPush: {
     2689        ASSERT(modeIsJSArray(node.arrayMode()));
     2690       
    26912691        SpeculateCellOperand base(this, node.child1());
    26922692        JSValueOperand value(this, node.child2());
     
    26982698        GPRReg storageLengthGPR = storageLength.gpr();
    26992699       
    2700         {
     2700        if (Heap::isWriteBarrierEnabled()) {
    27012701            GPRTemporary scratch(this);
    27022702            writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
    27032703        }
    27042704
    2705         speculateArray(Array::JSArray, node.child1(), baseGPR);
    2706        
    2707         GPRTemporary storage(this);
     2705        StorageOperand storage(this, node.child3());
    27082706        GPRReg storageGPR = storage.gpr();
    27092707
    2710         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
    27112708        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
    27122709       
     
    27312728       
    27322729    case ArrayPop: {
     2730        ASSERT(modeIsJSArray(node.arrayMode()));
     2731       
    27332732        SpeculateCellOperand base(this, node.child1());
     2733        StorageOperand storage(this, node.child2());
    27342734        GPRTemporary valueTag(this);
    27352735        GPRTemporary valuePayload(this);
    2736         GPRTemporary storage(this);
    27372736        GPRTemporary storageLength(this);
    27382737       
     
    27432742        GPRReg storageLengthGPR = storageLength.gpr();
    27442743       
    2745         speculateArray(Array::JSArray, node.child1(), baseGPR);
    2746        
    2747         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
    27482744        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
    27492745       
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r126695 r126715  
    24072407        break;
    24082408    }
     2409       
     2410    case CheckArray: {
     2411        checkArray(node);
     2412        break;
     2413    }
    24092414
    24102415    case GetByVal: {
     
    24982503        Edge child2 = m_jit.graph().varArgChild(node, 1);
    24992504        Edge child3 = m_jit.graph().varArgChild(node, 2);
     2505        Edge child4 = m_jit.graph().varArgChild(node, 3);
    25002506       
    25012507        Array::Mode arrayMode = modeForPut(node.arrayMode());
     
    25392545        GPRReg propertyReg = property.gpr();
    25402546
    2541         speculateArray(arrayMode, child1, baseReg);
    2542 
    25432547        switch (arrayMode) {
    25442548        case Array::JSArray:
    25452549        case Array::JSArrayOutOfBounds: {
    25462550            JSValueOperand value(this, child3);
    2547             GPRTemporary scratch(this);
    25482551
    25492552            // Map base, property & value into registers, allocate a scratch register.
    25502553            GPRReg valueReg = value.gpr();
    2551             GPRReg scratchReg = scratch.gpr();
    25522554       
    25532555            if (!m_compileOkay)
    25542556                return;
    25552557       
    2556             writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratchReg);
     2558            if (Heap::isWriteBarrierEnabled()) {
     2559                GPRTemporary scratch(this);
     2560                writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratch.gpr());
     2561            }
     2562
     2563            StorageOperand storage(this, child4);
     2564            GPRReg storageReg = storage.gpr();
    25572565
    25582566            if (node.op() == PutByValAlias) {
    2559                 GPRReg storageReg = scratchReg;
    2560                 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
    2561                
    25622567                // Store the value to the array.
    25632568                GPRReg propertyReg = property.gpr();
     
    25762581            property.use();
    25772582            value.use();
    2578        
    2579             // Get the array storage.
    2580             GPRReg storageReg = scratchReg;
    2581             m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
    2582 
     2583            storage.use();
     2584       
    25832585            // Check if we're writing to a hole; if so increment m_numValuesInVector.
    25842586            MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
     
    27482750       
    27492751    case ArrayPush: {
     2752        ASSERT(modeIsJSArray(node.arrayMode()));
     2753       
    27502754        SpeculateCellOperand base(this, node.child1());
    27512755        JSValueOperand value(this, node.child2());
    2752         GPRTemporary storage(this);
    27532756        GPRTemporary storageLength(this);
    27542757       
    27552758        GPRReg baseGPR = base.gpr();
    27562759        GPRReg valueGPR = value.gpr();
     2760        GPRReg storageLengthGPR = storageLength.gpr();
     2761       
     2762        if (Heap::isWriteBarrierEnabled()) {
     2763            GPRTemporary scratch(this);
     2764            writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
     2765        }
     2766
     2767        StorageOperand storage(this, node.child3());
    27572768        GPRReg storageGPR = storage.gpr();
    2758         GPRReg storageLengthGPR = storageLength.gpr();
    2759        
    2760         writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
    2761 
    2762         speculateArray(Array::JSArray, node.child1(), baseGPR);
    2763 
    2764         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
     2769
    27652770        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
    27662771       
     
    27872792       
    27882793    case ArrayPop: {
     2794        ASSERT(modeIsJSArray(node.arrayMode()));
     2795
    27892796        SpeculateCellOperand base(this, node.child1());
     2797        StorageOperand storage(this, node.child2());
    27902798        GPRTemporary value(this);
    2791         GPRTemporary storage(this);
    27922799        GPRTemporary storageLength(this);
    27932800       
    27942801        GPRReg baseGPR = base.gpr();
     2802        GPRReg storageGPR = storage.gpr();
    27952803        GPRReg valueGPR = value.gpr();
    2796         GPRReg storageGPR = storage.gpr();
    27972804        GPRReg storageLengthGPR = storageLength.gpr();
    27982805       
    2799         speculateArray(Array::JSArray, node.child1(), baseGPR);
    2800 
    2801         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
    28022806        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
    28032807       
  • trunk/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp

    r126387 r126715  
    100100                case PutByValAlias:
    101101                case GetArrayLength:
     102                case CheckArray:
     103                case GetIndexedPropertyStorage:
    102104                case Phantom:
    103105                    // Don't count these uses.
Note: See TracChangeset for help on using the changeset viewer.