Support integer typed arrays in the DFG JIT
https://bugs.webkit.org/show_bug.cgi?id=73608

Reviewed by Filip Pizlo.

Add support for all the integral typed arrays in the DFG JIT.
Currently this loads the contents of Uint32 arrays as doubles,
which is clearly not as efficient as it could be, but this is
still in the order of 10-20x faster than the existing behaviour.

This needed us to add support for writing 16bit values to the
macroassembler, and also to support double<->unsigned conversion.

* assembler/ARMv7Assembler.h:
(JSC::ARMv7Assembler::strh):
(JSC::ARMv7Assembler::vcvt_floatingPointToUnsigned):
* assembler/MacroAssemblerARMv7.h:
(JSC::MacroAssemblerARMv7::store16):
(JSC::MacroAssemblerARMv7::truncateDoubleToUint32):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::store16):
(JSC::MacroAssemblerX86Common::truncateDoubleToUint32):
* assembler/X86Assembler.h:
(JSC::X86Assembler::movw_rm):
(JSC::X86Assembler::cvttsd2siq_rr):
* bytecode/PredictedType.cpp:
(JSC::predictionToString):
(JSC::predictionFromClassInfo):
* bytecode/PredictedType.h:
(JSC::isInt8ArrayPrediction):
(JSC::isInt16ArrayPrediction):
(JSC::isInt32ArrayPrediction):
(JSC::isUint8ArrayPrediction):
(JSC::isUint16ArrayPrediction):
(JSC::isUint32ArrayPrediction):
(JSC::isFloat32ArrayPrediction):
(JSC::isFloat64ArrayPrediction):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::initialize):
(JSC::DFG::AbstractState::execute):
* dfg/DFGNode.h:
(JSC::DFG::Node::shouldSpeculateInt8Array):
(JSC::DFG::Node::shouldSpeculateInt16Array):
(JSC::DFG::Node::shouldSpeculateInt32Array):
(JSC::DFG::Node::shouldSpeculateUint8Array):
(JSC::DFG::Node::shouldSpeculateUint16Array):
(JSC::DFG::Node::shouldSpeculateUint32Array):
(JSC::DFG::Node::shouldSpeculateFloat32Array):
(JSC::DFG::Node::shouldSpeculateFloat64Array):
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::fixupNode):
(JSC::DFG::Propagator::performNodeCSE):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::compileGetTypedArrayLength):
(JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* runtime/JSGlobalData.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@101729 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index f516bee..4176129 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -113,6 +113,22 @@
             root->valuesAtHead.argument(i).set(PredictByteArray);
         else if (isBooleanPrediction(prediction))
             root->valuesAtHead.argument(i).set(PredictBoolean);
+        else if (isInt8ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictInt8Array);
+        else if (isInt16ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictInt16Array);
+        else if (isInt32ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictInt32Array);
+        else if (isUint8ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictUint8Array);
+        else if (isUint16ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictUint16Array);
+        else if (isUint32ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictUint32Array);
+        else if (isFloat32ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictFloat32Array);
+        else if (isFloat64ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictFloat64Array);
         else
             root->valuesAtHead.argument(i).makeTop();
     }
@@ -198,6 +214,22 @@
             forNode(node.child1()).filter(PredictArray);
         else if (isByteArrayPrediction(predictedType))
             forNode(node.child1()).filter(PredictByteArray);
+        else if (isInt8ArrayPrediction(predictedType))
+            forNode(node.child1()).filter(PredictInt8Array);
+        else if (isInt16ArrayPrediction(predictedType))
+            forNode(node.child1()).filter(PredictInt16Array);
+        else if (isInt32ArrayPrediction(predictedType))
+            forNode(node.child1()).filter(PredictInt32Array);
+        else if (isUint8ArrayPrediction(predictedType))
+            forNode(node.child1()).filter(PredictUint8Array);
+        else if (isUint16ArrayPrediction(predictedType))
+            forNode(node.child1()).filter(PredictUint16Array);
+        else if (isUint32ArrayPrediction(predictedType))
+            forNode(node.child1()).filter(PredictUint32Array);
+        else if (isFloat32ArrayPrediction(predictedType))
+            forNode(node.child1()).filter(PredictFloat32Array);
+        else if (isFloat64ArrayPrediction(predictedType))
+            forNode(node.child1()).filter(PredictFloat64Array);
         else if (isBooleanPrediction(predictedType))
             forNode(node.child1()).filter(PredictBoolean);
         
@@ -398,6 +430,43 @@
             forNode(nodeIndex).set(PredictInt32);
             break;
         }
+        
+        if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
+            forNode(node.child1()).filter(PredictInt8Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
+            forNode(node.child1()).filter(PredictInt16Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
+            forNode(node.child1()).filter(PredictInt32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
+            forNode(node.child1()).filter(PredictUint8Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
+            forNode(node.child1()).filter(PredictUint16Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
+            forNode(node.child1()).filter(PredictUint32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictDouble);
+            break;
+        }
         forNode(node.child1()).filter(PredictArray);
         forNode(node.child2()).filter(PredictInt32);
         forNode(nodeIndex).makeTop();
@@ -418,6 +487,44 @@
             forNode(node.child3()).filter(PredictNumber);
             break;
         }
+        
+        if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
+            forNode(node.child1()).filter(PredictInt8Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
+            forNode(node.child1()).filter(PredictInt16Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
+            forNode(node.child1()).filter(PredictInt32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
+            forNode(node.child1()).filter(PredictUint8Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
+            forNode(node.child1()).filter(PredictUint16Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
+            forNode(node.child1()).filter(PredictUint32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+            
         forNode(node.child1()).filter(PredictArray);
         forNode(node.child2()).filter(PredictInt32);
         break;
@@ -583,6 +690,38 @@
         forNode(node.child1()).filter(PredictByteArray);
         forNode(nodeIndex).set(PredictInt32);
         break;
+    case GetInt8ArrayLength:
+        forNode(node.child1()).filter(PredictInt8Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetInt16ArrayLength:
+        forNode(node.child1()).filter(PredictInt16Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetInt32ArrayLength:
+        forNode(node.child1()).filter(PredictInt32Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetUint8ArrayLength:
+        forNode(node.child1()).filter(PredictUint8Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetUint16ArrayLength:
+        forNode(node.child1()).filter(PredictUint16Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetUint32ArrayLength:
+        forNode(node.child1()).filter(PredictUint32Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetFloat32ArrayLength:
+        forNode(node.child1()).filter(PredictFloat32Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetFloat64ArrayLength:
+        forNode(node.child1()).filter(PredictFloat64Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
             
     case CheckStructure:
         // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).