DFG should handle polymorphic array modes by eagerly transforming arrays into the...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Oct 2012 03:17:17 +0000 (03:17 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Oct 2012 03:17:17 +0000 (03:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=99269

Reviewed by Geoffrey Garen.

This kills off a bunch of code for "polymorphic" array modes in the DFG. It should
also be a performance win for code that uses a lot of array storage arrays.

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGArrayMode.cpp:
(JSC::DFG::fromObserved):
(JSC::DFG::modeAlreadyChecked):
(JSC::DFG::modeToString):
* dfg/DFGArrayMode.h:
(DFG):
(JSC::DFG::modeUsesButterfly):
(JSC::DFG::modeIsJSArray):
(JSC::DFG::mayStoreToTail):
(JSC::DFG::mayStoreToHole):
(JSC::DFG::canCSEStorage):
(JSC::DFG::modeSupportsLength):
(JSC::DFG::benefitsFromStructureCheck):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::checkArray):
(JSC::DFG::FixupPhase::blessArrayOperation):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::byValIsPure):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::jumpSlowForUnwantedArrayMode):
(JSC::DFG::SpeculativeJIT::checkArray):
(JSC::DFG::SpeculativeJIT::arrayify):
(DFG):
(JSC::DFG::SpeculativeJIT::compileGetArrayLength):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::putByValWillNeedExtraRegister):
(SpeculativeJIT):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@131289 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGAbstractState.cpp
Source/JavaScriptCore/dfg/DFGArrayMode.cpp
Source/JavaScriptCore/dfg/DFGArrayMode.h
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

index c3813e9..8188350 100644 (file)
@@ -1,5 +1,49 @@
 2012-10-14  Filip Pizlo  <fpizlo@apple.com>
 
+        DFG should handle polymorphic array modes by eagerly transforming arrays into the most general applicable form
+        https://bugs.webkit.org/show_bug.cgi?id=99269
+
+        Reviewed by Geoffrey Garen.
+
+        This kills off a bunch of code for "polymorphic" array modes in the DFG. It should
+        also be a performance win for code that uses a lot of array storage arrays.
+
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::execute):
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::fromObserved):
+        (JSC::DFG::modeAlreadyChecked):
+        (JSC::DFG::modeToString):
+        * dfg/DFGArrayMode.h:
+        (DFG):
+        (JSC::DFG::modeUsesButterfly):
+        (JSC::DFG::modeIsJSArray):
+        (JSC::DFG::mayStoreToTail):
+        (JSC::DFG::mayStoreToHole):
+        (JSC::DFG::canCSEStorage):
+        (JSC::DFG::modeSupportsLength):
+        (JSC::DFG::benefitsFromStructureCheck):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::checkArray):
+        (JSC::DFG::FixupPhase::blessArrayOperation):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::byValIsPure):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::jumpSlowForUnwantedArrayMode):
+        (JSC::DFG::SpeculativeJIT::checkArray):
+        (JSC::DFG::SpeculativeJIT::arrayify):
+        (DFG):
+        (JSC::DFG::SpeculativeJIT::compileGetArrayLength):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::putByValWillNeedExtraRegister):
+        (SpeculativeJIT):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
+2012-10-14  Filip Pizlo  <fpizlo@apple.com>
+
         REGRESSION(126886): Fat binary builds don't know how to handle architecture variants to which the LLInt is agnostic
         https://bugs.webkit.org/show_bug.cgi?id=99270
 
index 6de8127..da5682f 100644 (file)
@@ -868,7 +868,6 @@ bool AbstractState::execute(unsigned indexInBlock)
         case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
         case SLOW_PUT_ARRAY_STORAGE_MODES:
         case ALL_EFFECTFUL_MODES:
-        case POLYMORPHIC_MODES:
             forNode(node.child1()).filter(SpecCell);
             forNode(node.child2()).filter(SpecInt32);
             clobberWorld(node.codeOrigin, indexInBlock);
@@ -943,7 +942,6 @@ bool AbstractState::execute(unsigned indexInBlock)
         case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
         case SLOW_PUT_ARRAY_STORAGE_MODES:
         case ALL_EFFECTFUL_MODES:
-        case POLYMORPHIC_MODES:
             forNode(child1).filter(SpecCell);
             forNode(child2).filter(SpecInt32);
             clobberWorld(node.codeOrigin, indexInBlock);
@@ -1384,7 +1382,6 @@ bool AbstractState::execute(unsigned indexInBlock)
             break;
         case ALL_CONTIGUOUS_MODES:
         case ALL_ARRAY_STORAGE_MODES:
-        case POLYMORPHIC_MODES: // These only get a CheckArray for GetArrayLength
             // This doesn't filter anything meaningful right now. We may want to add
             // CFA tracking of array mode speculations, but we don't have that, yet.
             forNode(node.child1()).filter(SpecCell);
@@ -1430,7 +1427,8 @@ bool AbstractState::execute(unsigned indexInBlock)
         case ALL_EFFECTFUL_MODES:
             node.setCanExit(true);
             forNode(node.child1()).filter(SpecCell);
-            forNode(node.child2()).filter(SpecInt32);
+            if (node.child2())
+                forNode(node.child2()).filter(SpecInt32);
             forNode(nodeIndex).clear();
             clobberStructures(indexInBlock);
             break;
index e192cfe..3985d76 100644 (file)
@@ -39,7 +39,7 @@ Array::Mode fromObserved(ArrayProfile* profile, Array::Action action, bool makeS
         return Array::Unprofiled;
     case asArrayModes(NonArray):
         if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
-            return Array::BlankToContiguousOrArrayStorage; // FIXME: we don't know whether to go to slow put mode or not. We're guessing that we don't need slow put.
+            return Array::ToContiguous; // FIXME: we don't know whether to go to contiguous or array storage. We're making a static guess here. In future we should use exit profiling for this.
         return Array::Undecided;
     case asArrayModes(NonArrayWithContiguous):
         return makeSafe ? Array::ContiguousOutOfBounds : (profile->mayStoreToHole() ? Array::ContiguousToTail : Array::Contiguous);
@@ -63,27 +63,24 @@ Array::Mode fromObserved(ArrayProfile* profile, Array::Action action, bool makeS
     case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
         return Array::PossiblyArrayWithSlowPutArrayStorage;
     case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage):
-        return Array::ContiguousOrArrayStorage;
+        return Array::ToArrayStorage;
     case asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage):
-        return Array::ArrayWithContiguousOrArrayStorage;
+        return Array::ArrayToArrayStorage;
     case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage):
-        return Array::PossiblyArrayWithContiguousOrArrayStorage;
+        return Array::PossiblyArrayToArrayStorage;
     case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous):
         if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
-            return Array::BlankToContiguous;
+            return Array::ToContiguous;
         return Array::Undecided;
     case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage):
-        if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
-            return Array::BlankToContiguousOrArrayStorage;
-        return Array::Undecided;
     case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage):
         if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
-            return Array::BlankToArrayStorage;
+            return Array::ToArrayStorage;
         return Array::Undecided;
     case asArrayModes(NonArray) | asArrayModes(NonArrayWithSlowPutArrayStorage):
     case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage):
         if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
-            return Array::BlankToSlowPutArrayStorage;
+            return Array::ToSlowPutArrayStorage;
         return Array::Undecided;
     default:
         // We know that this is possibly a kind of array for which, though there is no
@@ -207,7 +204,6 @@ bool modeAlreadyChecked(AbstractValue& value, Array::Mode arrayMode)
             && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
         
     case ALL_EFFECTFUL_MODES:
-    case POLYMORPHIC_MODES:
         return false;
         
     case Array::Arguments:
@@ -304,20 +300,16 @@ const char* modeToString(Array::Mode mode)
         return "PossiblyArrayWithSlowPutArrayStorage";
     case Array::PossiblyArrayWithArrayStorageOutOfBounds:
         return "PossiblyArrayWithArrayStorageOutOfBounds";
-    case Array::BlankToContiguous:
-        return "BlankToContiguous";
-    case Array::BlankToArrayStorage:
-        return "BlankToArrayStorage";
-    case Array::BlankToSlowPutArrayStorage:
-        return "BlankToSlowPutArrayStorage";
-    case Array::BlankToContiguousOrArrayStorage:
-        return "BlankToContiguousOrArrayStorage";
-    case Array::ContiguousOrArrayStorage:
-        return "ContiguousOrArrayStorage";
-    case Array::ArrayWithContiguousOrArrayStorage:
-        return "ArrayWithContiguousOrArrayStorage";
-    case Array::PossiblyArrayWithContiguousOrArrayStorage:
-        return "PossiblyArrayWithContiguousOrArrayStorage";
+    case Array::ToContiguous:
+        return "ToContiguous";
+    case Array::ToArrayStorage:
+        return "ToArrayStorage";
+    case Array::ToSlowPutArrayStorage:
+        return "ToSlowPutArrayStorage";
+    case Array::ArrayToArrayStorage:
+        return "ArrayToArrayStorage";
+    case Array::PossiblyArrayToArrayStorage:
+        return "PossiblyArrayToArrayStorage";
     case Array::Arguments:
         return "Arguments";
     case Array::Int8Array:
index b360c12..a666bb8 100644 (file)
@@ -77,16 +77,11 @@ enum Mode {
     PossiblyArrayWithArrayStorageOutOfBounds,
     
     // Modes of conventional indexed storage where the check is side-effecting.
-    BlankToContiguous,
-    BlankToArrayStorage,
-    BlankToSlowPutArrayStorage,
-    BlankToContiguousOrArrayStorage,
-    
-    // Modes that indicate polymorphic array storage. These don't benefit from
-    // any checking or storage CSE.
-    ContiguousOrArrayStorage,
-    ArrayWithContiguousOrArrayStorage,
-    PossiblyArrayWithContiguousOrArrayStorage,
+    ToContiguous,
+    ToArrayStorage,
+    ArrayToArrayStorage,
+    PossiblyArrayToArrayStorage,
+    ToSlowPutArrayStorage,
     
     Arguments,
     Int8Array,
@@ -167,30 +162,25 @@ enum Mode {
     case Array::PossiblyArrayWithArrayStorageOutOfBounds
 
 // Next: helpers for side-effecting checks.
+#define NON_ARRAY_EFFECTFUL_MODES                          \
+    Array::ToContiguous:                                   \
+    case Array::ToArrayStorage:                            \
+    case Array::ToSlowPutArrayStorage:                     \
+    case Array::PossiblyArrayToArrayStorage
+#define ARRAY_EFFECTFUL_MODES                              \
+    Array::ArrayToArrayStorage
 #define ALL_EFFECTFUL_CONTIGUOUS_MODES                     \
-    Array::BlankToContiguous
-#define EFFECTFUL_NON_ARRAY_ARRAY_STORAGE_MODES            \
-    Array::BlankToArrayStorage:                            \
-    case Array::BlankToSlowPutArrayStorage
+    Array::ToContiguous
 #define ALL_EFFECTFUL_ARRAY_STORAGE_MODES                  \
-    EFFECTFUL_NON_ARRAY_ARRAY_STORAGE_MODES
+    Array::ToArrayStorage:                                 \
+    case Array::ToSlowPutArrayStorage:                     \
+    case Array::ArrayToArrayStorage:                       \
+    case Array::PossiblyArrayToArrayStorage
 #define SLOW_PUT_EFFECTFUL_ARRAY_STORAGE_MODES             \
-    Array::BlankToSlowPutArrayStorage
-#define POLYMORPHIC_EFFECTFUL_MODES                        \
-    Array::BlankToContiguousOrArrayStorage
+    Array::ToSlowPutArrayStorage
 #define ALL_EFFECTFUL_MODES                                \
     ALL_EFFECTFUL_CONTIGUOUS_MODES:                        \
-    case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:                \
-    case POLYMORPHIC_EFFECTFUL_MODES
-
-// Finally: helpers for polymorphic array accesses.
-#define POLYMORPHIC_MODES                                  \
-    Array::ContiguousOrArrayStorage:                       \
-    case Array::ArrayWithContiguousOrArrayStorage:         \
-    case Array::PossiblyArrayWithContiguousOrArrayStorage
-#define ALL_POLYMORPHIC_MODES                              \
-    POLYMORPHIC_EFFECTFUL_MODES:                           \
-    case POLYMORPHIC_MODES
+    case ALL_EFFECTFUL_ARRAY_STORAGE_MODES
 
 Array::Mode fromObserved(ArrayProfile*, Array::Action, bool makeSafe);
 
@@ -206,7 +196,6 @@ inline bool modeUsesButterfly(Array::Mode arrayMode)
     case ALL_CONTIGUOUS_MODES:
     case ALL_ARRAY_STORAGE_MODES:
     case ALL_EFFECTFUL_MODES:
-    case POLYMORPHIC_MODES:
         return true;
     default:
         return false;
@@ -218,7 +207,7 @@ inline bool modeIsJSArray(Array::Mode arrayMode)
     switch (arrayMode) {
     case ARRAY_WITH_CONTIGUOUS_MODES:
     case ARRAY_WITH_ARRAY_STORAGE_MODES:
-    case Array::ArrayWithContiguousOrArrayStorage:
+    case ARRAY_EFFECTFUL_MODES:
         return true;
     default:
         return false;
@@ -255,7 +244,6 @@ inline bool mayStoreToTail(Array::Mode arrayMode)
     case CONTIGUOUS_TO_TAIL_MODES:
     case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
     case ALL_EFFECTFUL_CONTIGUOUS_MODES:
-    case ALL_POLYMORPHIC_MODES:
         return true;
     default:
         return false;
@@ -269,35 +257,12 @@ inline bool mayStoreToHole(Array::Mode arrayMode)
     case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
     case SLOW_PUT_ARRAY_STORAGE_MODES:
     case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
-    case ALL_POLYMORPHIC_MODES:
-        return true;
-    default:
-        return false;
-    }
-}
-
-inline bool modeIsPolymorphic(Array::Mode mode)
-{
-    switch (mode) {
-    case ALL_POLYMORPHIC_MODES:
         return true;
     default:
         return false;
     }
 }
 
-inline bool polymorphicIncludesContiguous(Array::Mode arrayMode)
-{
-    ASSERT_UNUSED(arrayMode, modeIsPolymorphic(arrayMode));
-    return true;
-}
-
-inline bool polymorphicIncludesArrayStorage(Array::Mode arrayMode)
-{
-    ASSERT_UNUSED(arrayMode, modeIsPolymorphic(arrayMode));
-    return true;
-}
-
 inline bool canCSEStorage(Array::Mode arrayMode)
 {
     switch (arrayMode) {
@@ -306,7 +271,6 @@ inline bool canCSEStorage(Array::Mode arrayMode)
     case Array::ForceExit:
     case Array::Generic:
     case Array::Arguments:
-    case ALL_POLYMORPHIC_MODES:
         return false;
     default:
         return true;
@@ -354,9 +318,7 @@ inline bool modeSupportsLength(Array::Mode mode)
     case Array::Generic:
     case NON_ARRAY_CONTIGUOUS_MODES:
     case NON_ARRAY_ARRAY_STORAGE_MODES:
-    case ALL_EFFECTFUL_MODES:
-    case Array::ContiguousOrArrayStorage:
-    case Array::PossiblyArrayWithContiguousOrArrayStorage:
+    case NON_ARRAY_EFFECTFUL_MODES:
         return false;
     default:
         return true;
@@ -367,7 +329,6 @@ inline bool benefitsFromStructureCheck(Array::Mode mode)
 {
     switch (mode) {
     case ALL_EFFECTFUL_MODES:
-    case POLYMORPHIC_MODES:
     case Array::Undecided:
     case Array::Unprofiled:
     case Array::ForceExit:
index c1095b4..be58117 100644 (file)
@@ -382,8 +382,8 @@ private:
         m_graph.ref(array);
 
         if (isEffectful(arrayMode)) {
-            ASSERT(index != NoNode);
-            m_graph.ref(index);
+            if (index != NoNode)
+                m_graph.ref(index);
             Node arrayify(Arrayify, codeOrigin, OpInfo(arrayMode), array, index);
             arrayify.ref(); // Once because it's used as a butterfly.
             arrayify.ref(); // And twice because it's must-generate.
@@ -391,11 +391,12 @@ private:
             m_graph.append(arrayify);
             m_insertionSet.append(m_indexInBlock, arrayifyIndex);
             
-            ASSERT(storageCheck == canCSEStorage);
             ASSERT(shouldGenerate);
             ASSERT(canCSEStorage(arrayMode));
             ASSERT(modeUsesButterfly(arrayMode));
-            
+
+            if (!storageCheck(arrayMode))
+                return NoNode;
             return arrayifyIndex;
         }
         
@@ -440,7 +441,6 @@ private:
             return;
             
         case Array::Generic:
-        case ALL_POLYMORPHIC_MODES:
             return;
             
         default: {
index c36b041..212c8bb 100644 (file)
@@ -484,7 +484,6 @@ public:
         case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
         case SLOW_PUT_ARRAY_STORAGE_MODES:
         case ALL_EFFECTFUL_MODES:
-        case POLYMORPHIC_MODES:
             return false;
         case Array::String:
             return node.op() == GetByVal;
index 7ee7d4b..850d5aa 100644 (file)
@@ -379,17 +379,6 @@ JITCompiler::JumpList SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGP
                 TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
         break;
     }
-    case POLYMORPHIC_MODES: {
-        if (modeIsJSArray(arrayMode)) {
-            result.append(
-                m_jit.branchTest32(
-                    MacroAssembler::Zero, tempGPR, TrustedImm32(IsArray)));
-        }
-        result.append(
-            m_jit.branchTest32(
-                MacroAssembler::Zero, tempGPR, TrustedImm32(IndexingShapeMask)));
-        break;
-    }
     default:
         CRASH();
         break;
@@ -421,8 +410,7 @@ void SpeculativeJIT::checkArray(Node& node)
     case NON_ARRAY_CONTIGUOUS_MODES:
     case ARRAY_WITH_CONTIGUOUS_MODES:
     case NON_ARRAY_ARRAY_STORAGE_MODES:
-    case ARRAY_WITH_ARRAY_STORAGE_MODES:
-    case POLYMORPHIC_MODES: {
+    case ARRAY_WITH_ARRAY_STORAGE_MODES: {
         GPRTemporary temp(this);
         GPRReg tempGPR = temp.gpr();
         m_jit.loadPtr(
@@ -467,30 +455,25 @@ void SpeculativeJIT::checkArray(Node& node)
     noResult(m_compileIndex);
 }
 
-void SpeculativeJIT::arrayify(Node& node)
+void SpeculativeJIT::arrayify(Node& node, GPRReg baseReg, GPRReg propertyReg)
 {
-    ASSERT(modeIsSpecific(node.arrayMode()));
-    ASSERT(!modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode()));
-    
-    SpeculateCellOperand base(this, node.child1());
-    SpeculateIntegerOperand property(this, node.child2());
-    GPRReg baseReg = base.gpr();
-    GPRReg propertyReg = property.gpr();
-    
     Array::Mode desiredArrayMode;
     
     switch (node.arrayMode()) {
-    case Array::BlankToContiguous:
+    case Array::ToContiguous:
         desiredArrayMode = Array::Contiguous;
         break;
-    case Array::BlankToArrayStorage:
+    case Array::ToArrayStorage:
         desiredArrayMode = Array::ArrayStorage;
         break;
-    case Array::BlankToSlowPutArrayStorage:
+    case Array::ToSlowPutArrayStorage:
         desiredArrayMode = Array::SlowPutArrayStorage;
         break;
-    case Array::BlankToContiguousOrArrayStorage:
-        desiredArrayMode = Array::ContiguousOrArrayStorage;
+    case Array::ArrayToArrayStorage:
+        desiredArrayMode = Array::ArrayWithArrayStorage;
+        break;
+    case Array::PossiblyArrayToArrayStorage:
+        desiredArrayMode = Array::PossiblyArrayWithArrayStorage;
         break;
     default:
         CRASH();
@@ -522,7 +505,7 @@ void SpeculativeJIT::arrayify(Node& node)
     
     // If we're allegedly creating contiguous storage and the index is bogus, then
     // just don't.
-    if (node.arrayMode() == Array::BlankToContiguous) {
+    if (node.arrayMode() == Array::ToContiguous && propertyReg != InvalidGPRReg) {
         speculationCheck(
             Uncountable, JSValueRegs(), NoNode,
             m_jit.branch32(
@@ -541,16 +524,12 @@ void SpeculativeJIT::arrayify(Node& node)
     // Now call out to create the array storage.
     silentSpillAllRegisters(tempGPR);
     switch (node.arrayMode()) {
-    case Array::BlankToContiguous:
+    case ALL_EFFECTFUL_CONTIGUOUS_MODES:
         callOperation(operationEnsureContiguous, tempGPR, baseReg);
         break;
-    case Array::BlankToArrayStorage:
-    case Array::BlankToSlowPutArrayStorage:
+    case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
         callOperation(operationEnsureArrayStorage, tempGPR, baseReg);
         break;
-    case Array::BlankToContiguousOrArrayStorage:
-        callOperation(operationEnsureContiguousOrArrayStorage, tempGPR, baseReg, propertyReg);
-        break;
     default:
         CRASH();
         break;
@@ -572,11 +551,28 @@ void SpeculativeJIT::arrayify(Node& node)
     speculationCheck(
         Uncountable, JSValueRegs(), NoNode,
         jumpSlowForUnwantedArrayMode(structureGPR, desiredArrayMode));
-        
+    
     done.link(&m_jit);
     storageResult(tempGPR, m_compileIndex);
 }
 
+void SpeculativeJIT::arrayify(Node& node)
+{
+    ASSERT(modeIsSpecific(node.arrayMode()));
+    ASSERT(!modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode()));
+    
+    SpeculateCellOperand base(this, node.child1());
+    
+    if (!node.child2()) {
+        arrayify(node, base.gpr(), InvalidGPRReg);
+        return;
+    }
+    
+    SpeculateIntegerOperand property(this, node.child2());
+    
+    arrayify(node, base.gpr(), property.gpr());
+}
+
 GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex)
 {
     Node& node = m_jit.graph()[nodeIndex];
@@ -3336,7 +3332,7 @@ void SpeculativeJIT::compileGetArrayLength(Node& node)
         break;
     }
     case ARRAY_WITH_ARRAY_STORAGE_MODES:
-    case Array::ArrayWithContiguousOrArrayStorage: {
+    case ARRAY_EFFECTFUL_MODES: {
         StorageOperand storage(this, node.child2());
         GPRTemporary result(this, storage);
         GPRReg storageReg = storage.gpr();
index c36f40b..90b6d48 100644 (file)
@@ -2215,10 +2215,6 @@ public:
         case ALL_EFFECTFUL_CONTIGUOUS_MODES:
             return true;
             
-        // All polymorphic modes need an extra reg.
-        case ALL_POLYMORPHIC_MODES:
-            return true;
-            
         default:
             return false;
         }
@@ -2373,6 +2369,7 @@ public:
     
     JITCompiler::JumpList jumpSlowForUnwantedArrayMode(GPRReg tempWithIndexingTypeReg, Array::Mode arrayMode);
     void checkArray(Node&);
+    void arrayify(Node&, GPRReg baseReg, GPRReg propertyReg);
     void arrayify(Node&);
     
     template<bool strict>
index c9cd3be..0396f86 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
  * Copyright (C) 2011 Intel Corporation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -2782,57 +2782,6 @@ void SpeculativeJIT::compile(Node& node)
             jsValueResult(resultTagReg, resultPayloadReg, m_compileIndex);
             break;
         }
-        case ALL_POLYMORPHIC_MODES: {
-            SpeculateCellOperand base(this, node.child1());
-            SpeculateStrictInt32Operand property(this, node.child2());
-            
-            GPRReg baseReg = base.gpr();
-            GPRReg propertyReg = property.gpr();
-            
-            if (!m_compileOkay)
-                return;
-            
-            GPRTemporary storage(this);
-            GPRTemporary resultTag(this);
-            GPRTemporary resultPayload(this);
-            GPRReg storageReg = storage.gpr();
-            GPRReg resultTagReg = resultTag.gpr();
-            GPRReg resultPayloadReg = resultPayload.gpr();
-            
-            MacroAssembler::JumpList slowCases;
-            MacroAssembler::JumpList doneCases;
-            MacroAssembler::Jump fallThrough;
-            m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), resultTagReg);
-            m_jit.loadPtr(MacroAssembler::Address(baseReg, JSObject::butterflyOffset()), storageReg);
-            m_jit.load8(MacroAssembler::Address(resultTagReg, Structure::indexingTypeOffset()), resultTagReg);
-            m_jit.and32(TrustedImm32(IndexingShapeMask), resultTagReg);
-            if (polymorphicIncludesContiguous(node.arrayMode())) {
-                if (fallThrough.isSet()) {
-                    doneCases.append(m_jit.jump());
-                    fallThrough.link(&m_jit);
-                }
-                fallThrough = m_jit.branch32(MacroAssembler::NotEqual, resultTagReg, MacroAssembler::TrustedImm32(ContiguousShape));
-                slowCases.append(compileContiguousGetByVal(node, baseReg, propertyReg, storageReg, resultTagReg, resultPayloadReg));
-            }
-            if (polymorphicIncludesArrayStorage(node.arrayMode())) {
-                if (fallThrough.isSet()) {
-                    doneCases.append(m_jit.jump());
-                    fallThrough.link(&m_jit);
-                }
-                fallThrough = m_jit.branch32(MacroAssembler::NotEqual, resultTagReg, MacroAssembler::TrustedImm32(ArrayStorageShape));
-                slowCases.append(compileArrayStorageGetByVal(node, baseReg, propertyReg, storageReg, resultTagReg, resultPayloadReg));
-            }
-            ASSERT(fallThrough.isSet());
-            doneCases.link(&m_jit);
-            slowCases.append(fallThrough);
-            addSlowPathGenerator(
-                slowPathCall(
-                    slowCases, this, operationGetByValArrayInt,
-                    JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
-            
-            jsValueResult(resultTagReg, resultPayloadReg, m_compileIndex);
-            break;
-        }
         case Array::String:
             compileGetByValOnString(node);
             break;
@@ -3022,64 +2971,6 @@ void SpeculativeJIT::compile(Node& node)
             break;
         }
             
-        case ALL_POLYMORPHIC_MODES: {
-            ASSERT(node.op() == PutByVal);
-            
-            JSValueOperand value(this, child3);
-            
-            GPRReg valueTagReg = value.tagGPR();
-            GPRReg valuePayloadReg = value.payloadGPR();
-            
-            if (!m_compileOkay)
-                return;
-            
-            GPRTemporary storage(this);
-            GPRReg storageReg = storage.gpr();
-            
-            MacroAssembler::JumpList slowCases;
-            MacroAssembler::JumpList doneCases;
-            MacroAssembler::Jump fallThrough;
-            m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), storageReg);
-            m_jit.load8(MacroAssembler::Address(storageReg, Structure::indexingTypeOffset()), storageReg);
-            m_jit.and32(TrustedImm32(IndexingShapeMask), storageReg);
-            if (polymorphicIncludesContiguous(node.arrayMode())) {
-                if (fallThrough.isSet()) {
-                    doneCases.append(m_jit.jump());
-                    fallThrough.link(&m_jit);
-                }
-                fallThrough = m_jit.branch32(MacroAssembler::NotEqual, storageReg, MacroAssembler::TrustedImm32(ContiguousShape));
-                m_jit.loadPtr(MacroAssembler::Address(baseReg, JSObject::butterflyOffset()), storageReg);
-                slowCases.append(compileContiguousPutByVal(node, baseReg, propertyReg, storageReg, valueTagReg, valuePayloadReg));
-            }
-            if (polymorphicIncludesArrayStorage(node.arrayMode())) {
-                if (fallThrough.isSet()) {
-                    doneCases.append(m_jit.jump());
-                    fallThrough.link(&m_jit);
-                }
-                fallThrough = m_jit.branch32(MacroAssembler::NotEqual, storageReg, MacroAssembler::TrustedImm32(ArrayStorageShape));
-                m_jit.loadPtr(MacroAssembler::Address(baseReg, JSObject::butterflyOffset()), storageReg);
-                slowCases.append(compileArrayStoragePutByVal(node, baseReg, propertyReg, storageReg, valueTagReg, valuePayloadReg));
-            }
-            ASSERT(fallThrough.isSet());
-            doneCases.link(&m_jit);
-            slowCases.append(fallThrough);
-
-            base.use();
-            property.use();
-            value.use();
-
-            // FIXME: the decision of whether or not we're in strict mode should be made
-            // based on the inline call frame, not the machine code block.
-            addSlowPathGenerator(
-                slowPathCall(
-                    slowCases, this,
-                    m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
-                    NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
-            
-            noResult(m_compileIndex, UseChildrenCalledExplicitly);
-            break;
-        }
-            
         case Array::Arguments:
             // FIXME: we could at some point make this work. Right now we're assuming that the register
             // pressure would be too great.
index 94d0dcc..0928dfa 100644 (file)
@@ -2788,55 +2788,6 @@ void SpeculativeJIT::compile(Node& node)
             jsValueResult(resultReg, m_compileIndex);
             break;
         }
-        case ALL_POLYMORPHIC_MODES: {
-            SpeculateCellOperand base(this, node.child1());
-            SpeculateStrictInt32Operand property(this, node.child2());
-            
-            GPRReg baseReg = base.gpr();
-            GPRReg propertyReg = property.gpr();
-            
-            if (!m_compileOkay)
-                return;
-            
-            GPRTemporary storage(this);
-            GPRTemporary result(this);
-            GPRReg storageReg = storage.gpr();
-            GPRReg resultReg = result.gpr();
-            
-            MacroAssembler::JumpList slowCases;
-            MacroAssembler::JumpList doneCases;
-            MacroAssembler::Jump fallThrough;
-            m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), resultReg);
-            m_jit.loadPtr(MacroAssembler::Address(baseReg, JSObject::butterflyOffset()), storageReg);
-            m_jit.load8(MacroAssembler::Address(resultReg, Structure::indexingTypeOffset()), resultReg);
-            m_jit.and32(TrustedImm32(IndexingShapeMask), resultReg);
-            if (polymorphicIncludesContiguous(node.arrayMode())) {
-                if (fallThrough.isSet()) {
-                    doneCases.append(m_jit.jump());
-                    fallThrough.link(&m_jit);
-                }
-                fallThrough = m_jit.branch32(MacroAssembler::NotEqual, resultReg, MacroAssembler::TrustedImm32(ContiguousShape));
-                slowCases.append(compileContiguousGetByVal(node, baseReg, propertyReg, storageReg, resultReg));
-            }
-            if (polymorphicIncludesArrayStorage(node.arrayMode())) {
-                if (fallThrough.isSet()) {
-                    doneCases.append(m_jit.jump());
-                    fallThrough.link(&m_jit);
-                }
-                fallThrough = m_jit.branch32(MacroAssembler::NotEqual, resultReg, MacroAssembler::TrustedImm32(ArrayStorageShape));
-                slowCases.append(compileArrayStorageGetByVal(node, baseReg, propertyReg, storageReg, resultReg));
-            }
-            ASSERT(fallThrough.isSet());
-            doneCases.link(&m_jit);
-            slowCases.append(fallThrough);
-            addSlowPathGenerator(
-                slowPathCall(
-                    slowCases, this, operationGetByValArrayInt,
-                    result.gpr(), baseReg, propertyReg));
-            
-            jsValueResult(resultReg, m_compileIndex);
-            break;
-        }
         case Array::String:
             compileGetByValOnString(node);
             break;
@@ -3030,64 +2981,6 @@ void SpeculativeJIT::compile(Node& node)
             break;
         }
             
-        case ALL_POLYMORPHIC_MODES: {
-            ASSERT(node.op() == PutByVal);
-            
-            JSValueOperand value(this, child3);
-            
-            GPRReg valueReg = value.gpr();
-            
-            if (!m_compileOkay)
-                return;
-            
-            GPRTemporary storage(this);
-            GPRTemporary temporary(this);
-            GPRReg storageReg = storage.gpr();
-            GPRReg temporaryReg = temporary.gpr();
-            
-            MacroAssembler::JumpList slowCases;
-            MacroAssembler::JumpList doneCases;
-            MacroAssembler::Jump fallThrough;
-            m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), temporaryReg);
-            m_jit.loadPtr(MacroAssembler::Address(baseReg, JSObject::butterflyOffset()), storageReg);
-            m_jit.load8(MacroAssembler::Address(temporaryReg, Structure::indexingTypeOffset()), temporaryReg);
-            m_jit.and32(TrustedImm32(IndexingShapeMask), temporaryReg);
-            if (polymorphicIncludesContiguous(node.arrayMode())) {
-                if (fallThrough.isSet()) {
-                    doneCases.append(m_jit.jump());
-                    fallThrough.link(&m_jit);
-                }
-                fallThrough = m_jit.branch32(MacroAssembler::NotEqual, temporaryReg, MacroAssembler::TrustedImm32(ContiguousShape));
-                slowCases.append(compileContiguousPutByVal(node, baseReg, propertyReg, storageReg, valueReg, temporaryReg));
-            }
-            if (polymorphicIncludesArrayStorage(node.arrayMode())) {
-                if (fallThrough.isSet()) {
-                    doneCases.append(m_jit.jump());
-                    fallThrough.link(&m_jit);
-                }
-                fallThrough = m_jit.branch32(MacroAssembler::NotEqual, temporaryReg, MacroAssembler::TrustedImm32(ArrayStorageShape));
-                slowCases.append(compileArrayStoragePutByVal(node, baseReg, propertyReg, storageReg, valueReg, temporaryReg));
-            }
-            ASSERT(fallThrough.isSet());
-            doneCases.link(&m_jit);
-            slowCases.append(fallThrough);
-
-            base.use();
-            property.use();
-            value.use();
-
-            // FIXME: the decision of whether or not we're in strict mode should be made
-            // based on the inline call frame, not the machine code block.
-            addSlowPathGenerator(
-                slowPathCall(
-                    slowCases, this,
-                    m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
-                    NoResult, baseReg, propertyReg, valueReg));
-            
-            noResult(m_compileIndex, UseChildrenCalledExplicitly);
-            break;
-        }
-            
         case Array::Arguments: {
             JSValueOperand value(this, child3);
             GPRTemporary scratch(this);