Title: [154218] trunk
Revision
154218
Author
[email protected]
Date
2013-08-16 22:50:48 -0700 (Fri, 16 Aug 2013)

Log Message

DFG should optimize typedArray.byteLength
https://bugs.webkit.org/show_bug.cgi?id=119909

Source/_javascript_Core: 

Reviewed by Oliver Hunt.
        
This adds typedArray.byteLength inlining to the DFG, and does so without changing
the IR: byteLength is turned into GetArrayLength followed by BitLShift. This is
legal since the byteLength of a typed array cannot exceed
numeric_limits<int32_t>::max().

* bytecode/SpeculatedType.cpp:
(JSC::typedArrayTypeFromSpeculation):
* bytecode/SpeculatedType.h:
* dfg/DFGArrayMode.cpp:
(JSC::DFG::toArrayType):
* dfg/DFGArrayMode.h:
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::attemptToMakeGetArrayLength):
(JSC::DFG::FixupPhase::attemptToMakeGetByteLength):
(JSC::DFG::FixupPhase::convertToGetArrayLength):
(JSC::DFG::FixupPhase::prependGetArrayLength):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::constantRegisterForConstant):
(JSC::DFG::Graph::convertToConstant):
* runtime/TypedArrayType.h:
(JSC::logElementSize):
(JSC::elementSize):

LayoutTests: 

Reviewed by Oliver Hunt.
        
Convert two of the tyepd array tests to use byteLength instead of length.
These tests show speed-ups around 2.5x-5x.

* fast/js/regress/Int16Array-bubble-sort-with-byteLength-expected.txt: Added.
* fast/js/regress/Int16Array-bubble-sort-with-byteLength.html: Added.
* fast/js/regress/Int8Array-load-with-byteLength-expected.txt: Added.
* fast/js/regress/Int8Array-load-with-byteLength.html: Added.
* fast/js/regress/script-tests/Int16Array-bubble-sort-with-byteLength.js: Added.
(bubbleSort):
(myRandom):
(validateSort):
* fast/js/regress/script-tests/Int8Array-load-with-byteLength.js: Added.
(adler32):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (154217 => 154218)


--- trunk/LayoutTests/ChangeLog	2013-08-17 05:36:32 UTC (rev 154217)
+++ trunk/LayoutTests/ChangeLog	2013-08-17 05:50:48 UTC (rev 154218)
@@ -1,5 +1,26 @@
 2013-08-16  Filip Pizlo  <[email protected]>
 
+        DFG should optimize typedArray.byteLength
+        https://bugs.webkit.org/show_bug.cgi?id=119909
+
+        Reviewed by Oliver Hunt.
+        
+        Convert two of the tyepd array tests to use byteLength instead of length.
+        These tests show speed-ups around 2.5x-5x.
+
+        * fast/js/regress/Int16Array-bubble-sort-with-byteLength-expected.txt: Added.
+        * fast/js/regress/Int16Array-bubble-sort-with-byteLength.html: Added.
+        * fast/js/regress/Int8Array-load-with-byteLength-expected.txt: Added.
+        * fast/js/regress/Int8Array-load-with-byteLength.html: Added.
+        * fast/js/regress/script-tests/Int16Array-bubble-sort-with-byteLength.js: Added.
+        (bubbleSort):
+        (myRandom):
+        (validateSort):
+        * fast/js/regress/script-tests/Int8Array-load-with-byteLength.js: Added.
+        (adler32):
+
+2013-08-16  Filip Pizlo  <[email protected]>
+
         DFG optimizes out strict mode arguments tear off
         https://bugs.webkit.org/show_bug.cgi?id=119504
 

Added: trunk/LayoutTests/fast/js/regress/Int16Array-bubble-sort-with-byteLength-expected.txt (0 => 154218)


--- trunk/LayoutTests/fast/js/regress/Int16Array-bubble-sort-with-byteLength-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/regress/Int16Array-bubble-sort-with-byteLength-expected.txt	2013-08-17 05:50:48 UTC (rev 154218)
@@ -0,0 +1,10 @@
+JSRegress/Int16Array-bubble-sort-with-byteLength
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/regress/Int16Array-bubble-sort-with-byteLength.html (0 => 154218)


--- trunk/LayoutTests/fast/js/regress/Int16Array-bubble-sort-with-byteLength.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/regress/Int16Array-bubble-sort-with-byteLength.html	2013-08-17 05:50:48 UTC (rev 154218)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/js/regress/Int8Array-load-with-byteLength-expected.txt (0 => 154218)


--- trunk/LayoutTests/fast/js/regress/Int8Array-load-with-byteLength-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/regress/Int8Array-load-with-byteLength-expected.txt	2013-08-17 05:50:48 UTC (rev 154218)
@@ -0,0 +1,10 @@
+JSRegress/Int8Array-load-with-byteLength
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/regress/Int8Array-load-with-byteLength.html (0 => 154218)


--- trunk/LayoutTests/fast/js/regress/Int8Array-load-with-byteLength.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/regress/Int8Array-load-with-byteLength.html	2013-08-17 05:50:48 UTC (rev 154218)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/js/regress/script-tests/Int16Array-bubble-sort-with-byteLength.js (0 => 154218)


--- trunk/LayoutTests/fast/js/regress/script-tests/Int16Array-bubble-sort-with-byteLength.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/regress/script-tests/Int16Array-bubble-sort-with-byteLength.js	2013-08-17 05:50:48 UTC (rev 154218)
@@ -0,0 +1,89 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright (C) 2013 Apple Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test the performance of Int16Array by implementing a bubble sort.
+
+function bubbleSort(array)
+{
+    for (var i = 1; i < (array.byteLength >> 1); ++i) {
+        for (var j = 0; j < (array.byteLength >> 1) - i; ++j) {
+            if (array[j + 1] < array[j]) {
+                var tmp = array[j];
+                array[j] = array[j + 1];
+                array[j + 1] = tmp;
+            }
+        }
+    }
+}
+
+// V8's random function.
+myRandom = (function() {
+  var seed = 49734321;
+  return function() {
+    // Robert Jenkins' 32 bit integer hash function.
+    seed = ((seed + 0x7ed55d16) + (seed << 12))  & 0xffffffff;
+    seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
+    seed = ((seed + 0x165667b1) + (seed << 5))   & 0xffffffff;
+    seed = ((seed + 0xd3a2646c) ^ (seed << 9))   & 0xffffffff;
+    seed = ((seed + 0xfd7046c5) + (seed << 3))   & 0xffffffff;
+    seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
+    return (seed & 0xfffffff) / 0x10000000;
+  };
+})();
+
+function arrayToString(array) {
+    var result = "[";
+    for (var i = 0; i < (array.byteLength >> 1); ++i) {
+        if (i)
+            result += ", ";
+        result += array[i];
+    }
+    return result + "]";
+}
+
+function validateSort(array) {
+    for (var i = 0; i < (array.byteLength >> 1) - 1; ++i) {
+        if (array[i + 1] < array[i])
+            return false;
+    }
+    return true;
+}
+
+var array = new Int16Array(1000);
+for (var count = 0; count < 10; ++count) {
+    for (var i = 0; i < (array.byteLength >> 1); ++i) {
+        array[i] = myRandom() * 65535;
+    }
+    
+    bubbleSort(array);
+    
+    if (!validateSort(array))
+        throw "Bad result: " + arrayToString(array);
+}
+

Added: trunk/LayoutTests/fast/js/regress/script-tests/Int8Array-load-with-byteLength.js (0 => 154218)


--- trunk/LayoutTests/fast/js/regress/script-tests/Int8Array-load-with-byteLength.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/regress/script-tests/Int8Array-load-with-byteLength.js	2013-08-17 05:50:48 UTC (rev 154218)
@@ -0,0 +1,29 @@
+// Test the performance of Int8Array by implementing Adler32.
+
+function adler32(array)
+{
+    var MOD_ADLER = 65521;
+    var a = 1;
+    var b = 0;
+    var index;
+ 
+    /* Process each byte of the data in order */
+    for (index = 0; index < array.byteLength; ++index)
+    {
+        a = (a + array[index]) % MOD_ADLER;
+        b = (b + a) % MOD_ADLER;
+    }
+ 
+    return (b << 16) | a;
+}
+
+var array = new Int8Array(1000);
+for (var i = 0; i < array.byteLength ; ++i)
+    array[i] = i;
+
+var result = 0;
+for (var i = 0; i < 300; ++i)
+    result += adler32(array);
+
+if (result != -63300)
+    throw "Bad result: " + result;

Modified: trunk/Source/_javascript_Core/ChangeLog (154217 => 154218)


--- trunk/Source/_javascript_Core/ChangeLog	2013-08-17 05:36:32 UTC (rev 154217)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-08-17 05:50:48 UTC (rev 154218)
@@ -1,5 +1,36 @@
 2013-08-16  Filip Pizlo  <[email protected]>
 
+        DFG should optimize typedArray.byteLength
+        https://bugs.webkit.org/show_bug.cgi?id=119909
+
+        Reviewed by Oliver Hunt.
+        
+        This adds typedArray.byteLength inlining to the DFG, and does so without changing
+        the IR: byteLength is turned into GetArrayLength followed by BitLShift. This is
+        legal since the byteLength of a typed array cannot exceed
+        numeric_limits<int32_t>::max().
+
+        * bytecode/SpeculatedType.cpp:
+        (JSC::typedArrayTypeFromSpeculation):
+        * bytecode/SpeculatedType.h:
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::toArrayType):
+        * dfg/DFGArrayMode.h:
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::attemptToMakeGetArrayLength):
+        (JSC::DFG::FixupPhase::attemptToMakeGetByteLength):
+        (JSC::DFG::FixupPhase::convertToGetArrayLength):
+        (JSC::DFG::FixupPhase::prependGetArrayLength):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::constantRegisterForConstant):
+        (JSC::DFG::Graph::convertToConstant):
+        * runtime/TypedArrayType.h:
+        (JSC::logElementSize):
+        (JSC::elementSize):
+
+2013-08-16  Filip Pizlo  <[email protected]>
+
         DFG optimizes out strict mode arguments tear off
         https://bugs.webkit.org/show_bug.cgi?id=119504
 

Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp (154217 => 154218)


--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp	2013-08-17 05:36:32 UTC (rev 154217)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp	2013-08-17 05:50:48 UTC (rev 154218)
@@ -334,5 +334,37 @@
     return SpecOther;
 }
 
+TypedArrayType typedArrayTypeFromSpeculation(SpeculatedType type)
+{
+    if (isInt8ArraySpeculation(type))
+        return TypeInt8;
+        
+    if (isInt16ArraySpeculation(type))
+        return TypeInt16;
+        
+    if (isInt32ArraySpeculation(type))
+        return TypeInt32;
+        
+    if (isUint8ArraySpeculation(type))
+        return TypeUint8;
+        
+    if (isUint8ClampedArraySpeculation(type))
+        return TypeUint8Clamped;
+        
+    if (isUint16ArraySpeculation(type))
+        return TypeUint16;
+        
+    if (isUint32ArraySpeculation(type))
+        return TypeUint32;
+        
+    if (isFloat32ArraySpeculation(type))
+        return TypeFloat32;
+        
+    if (isFloat64ArraySpeculation(type))
+        return TypeFloat64;
+    
+    return NotTypedArray;
+}
+
 } // namespace JSC
 

Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.h (154217 => 154218)


--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.h	2013-08-17 05:36:32 UTC (rev 154217)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.h	2013-08-17 05:50:48 UTC (rev 154218)
@@ -30,6 +30,7 @@
 #define SpeculatedType_h
 
 #include "JSCJSValue.h"
+#include "TypedArrayType.h"
 #include <wtf/PrintStream.h>
 
 namespace JSC {
@@ -330,6 +331,8 @@
 SpeculatedType speculationFromCell(JSCell*);
 SpeculatedType speculationFromValue(JSValue);
 
+TypedArrayType typedArrayTypeFromSpeculation(SpeculatedType);
+
 } // namespace JSC
 
 #endif // SpeculatedType_h

Modified: trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp (154217 => 154218)


--- trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp	2013-08-17 05:36:32 UTC (rev 154217)
+++ trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp	2013-08-17 05:50:48 UTC (rev 154218)
@@ -484,6 +484,32 @@
     }
 }
 
+Array::Type toArrayType(TypedArrayType type)
+{
+    switch (type) {
+    case TypeInt8:
+        return Array::Int8Array;
+    case TypeInt16:
+        return Array::Int16Array;
+    case TypeInt32:
+        return Array::Int32Array;
+    case TypeUint8:
+        return Array::Uint8Array;
+    case TypeUint8Clamped:
+        return Array::Uint8ClampedArray;
+    case TypeUint16:
+        return Array::Uint16Array;
+    case TypeUint32:
+        return Array::Uint32Array;
+    case TypeFloat32:
+        return Array::Float32Array;
+    case TypeFloat64:
+        return Array::Float64Array;
+    default:
+        return Array::Generic;
+    }
+}
+
 void ArrayMode::dump(PrintStream& out) const
 {
     out.print(type(), arrayClass(), speculation(), conversion());

Modified: trunk/Source/_javascript_Core/dfg/DFGArrayMode.h (154217 => 154218)


--- trunk/Source/_javascript_Core/dfg/DFGArrayMode.h	2013-08-17 05:36:32 UTC (rev 154217)
+++ trunk/Source/_javascript_Core/dfg/DFGArrayMode.h	2013-08-17 05:50:48 UTC (rev 154218)
@@ -105,6 +105,7 @@
 const char* arrayConversionToString(Array::Conversion);
 
 TypedArrayType toTypedArrayType(Array::Type);
+Array::Type toArrayType(TypedArrayType);
 
 class ArrayMode {
 public:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (154217 => 154218)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2013-08-17 05:36:32 UTC (rev 154217)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2013-08-17 05:50:48 UTC (rev 154218)
@@ -729,56 +729,14 @@
         case GetByIdFlush: {
             if (!node->child1()->shouldSpeculateCell())
                 break;
-            setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
-            if (!isInt32Speculation(node->prediction()))
+            if (m_graph.identifiers()[node->identifierNumber()] == vm().propertyNames->length.impl()) {
+                attemptToMakeGetArrayLength(node);
                 break;
-            if (m_graph.identifiers()[node->identifierNumber()] != vm().propertyNames->length.impl())
+            }
+            if (m_graph.identifiers()[node->identifierNumber()] == vm().propertyNames->byteLength.impl()) {
+                attemptToMakeGetByteLength(node);
                 break;
-            CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->codeOrigin);
-            ArrayProfile* arrayProfile = 
-                profiledBlock->getArrayProfile(node->codeOrigin.bytecodeIndex);
-            ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
-            if (arrayProfile) {
-                ConcurrentJITLocker locker(profiledBlock->m_lock);
-                arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
-                arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
-                if (arrayMode.type() == Array::Unprofiled) {
-                    // For normal array operations, it makes sense to treat Unprofiled
-                    // accesses as ForceExit and get more data rather than using
-                    // predictions and then possibly ending up with a Generic. But here,
-                    // we treat anything that is Unprofiled as Generic and keep the
-                    // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
-                    // profit - from treating the Unprofiled case as
-                    // SelectUsingPredictions.
-                    arrayMode = ArrayMode(Array::SelectUsingPredictions);
-                }
             }
-            
-            arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction());
-            
-            if (arrayMode.type() == Array::Generic) {
-                // Check if the input is something that we can't get array length for, but for which we
-                // could insert some conversions in order to transform it into something that we can do it
-                // for.
-                if (node->child1()->shouldSpeculateStringObject())
-                    attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
-                else if (node->child1()->shouldSpeculateStringOrStringObject())
-                    attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
-            }
-            
-            if (!arrayMode.supportsLength())
-                break;
-            node->setOp(GetArrayLength);
-            ASSERT(node->flags() & NodeMustGenerate);
-            node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
-            setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
-            node->setArrayMode(arrayMode);
-            
-            Node* storage = checkArray(arrayMode, node->codeOrigin, node->child1().node(), 0, lengthNeedsStorage);
-            if (!storage)
-                break;
-            
-            node->child2() = Edge(storage);
             break;
         }
             
@@ -1448,6 +1406,105 @@
         setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
         return true;
     }
+    
+    bool attemptToMakeGetArrayLength(Node* node)
+    {
+        if (!isInt32Speculation(node->prediction()))
+            return false;
+        CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->codeOrigin);
+        ArrayProfile* arrayProfile = 
+            profiledBlock->getArrayProfile(node->codeOrigin.bytecodeIndex);
+        ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
+        if (arrayProfile) {
+            ConcurrentJITLocker locker(profiledBlock->m_lock);
+            arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
+            arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
+            if (arrayMode.type() == Array::Unprofiled) {
+                // For normal array operations, it makes sense to treat Unprofiled
+                // accesses as ForceExit and get more data rather than using
+                // predictions and then possibly ending up with a Generic. But here,
+                // we treat anything that is Unprofiled as Generic and keep the
+                // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
+                // profit - from treating the Unprofiled case as
+                // SelectUsingPredictions.
+                arrayMode = ArrayMode(Array::SelectUsingPredictions);
+            }
+        }
+            
+        arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction());
+            
+        if (arrayMode.type() == Array::Generic) {
+            // Check if the input is something that we can't get array length for, but for which we
+            // could insert some conversions in order to transform it into something that we can do it
+            // for.
+            if (node->child1()->shouldSpeculateStringObject())
+                attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
+            else if (node->child1()->shouldSpeculateStringOrStringObject())
+                attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
+        }
+            
+        if (!arrayMode.supportsLength())
+            return false;
+        
+        convertToGetArrayLength(node, arrayMode);
+        return true;
+    }
+    
+    bool attemptToMakeGetByteLength(Node* node)
+    {
+        if (!isInt32Speculation(node->prediction()))
+            return false;
+        
+        TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
+        if (!isTypedView(type))
+            return false;
+        
+        if (elementSize(type) == 1) {
+            convertToGetArrayLength(node, ArrayMode(toArrayType(type)));
+            return true;
+        }
+        
+        Node* length = prependGetArrayLength(
+            node->codeOrigin, node->child1().node(), ArrayMode(toArrayType(type)));
+        
+        Node* shiftAmount = m_insertionSet.insertNode(
+            m_indexInBlock, SpecInt32, JSConstant, node->codeOrigin,
+            OpInfo(m_graph.constantRegisterForConstant(jsNumber(logElementSize(type)))));
+        
+        // We can use a BitLShift here because typed arrays will never have a byteLength
+        // that overflows int32.
+        node->setOp(BitLShift);
+        ASSERT(node->flags() & NodeMustGenerate);
+        node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+        observeUseKindOnNode(length, Int32Use);
+        observeUseKindOnNode(shiftAmount, Int32Use);
+        node->child1() = Edge(length, Int32Use);
+        node->child2() = Edge(shiftAmount, Int32Use);
+        return true;
+    }
+    
+    void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
+    {
+        node->setOp(GetArrayLength);
+        ASSERT(node->flags() & NodeMustGenerate);
+        node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+        setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
+        node->setArrayMode(arrayMode);
+            
+        Node* storage = checkArray(arrayMode, node->codeOrigin, node->child1().node(), 0, lengthNeedsStorage);
+        if (!storage)
+            return;
+            
+        node->child2() = Edge(storage);
+    }
+    
+    Node* prependGetArrayLength(CodeOrigin codeOrigin, Node* child, ArrayMode arrayMode)
+    {
+        Node* storage = checkArray(arrayMode, codeOrigin, child, 0, lengthNeedsStorage);
+        return m_insertionSet.insertNode(
+            m_indexInBlock, SpecInt32, GetArrayLength, codeOrigin,
+            OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
+    }
 
     BasicBlock* m_block;
     unsigned m_indexInBlock;

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (154217 => 154218)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.h	2013-08-17 05:36:32 UTC (rev 154217)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h	2013-08-17 05:50:48 UTC (rev 154218)
@@ -151,7 +151,7 @@
         node->convertToConstant(constantNumber);
     }
     
-    void convertToConstant(Node* node, JSValue value)
+    unsigned constantRegisterForConstant(JSValue value)
     {
         unsigned constantRegister;
         if (!m_codeBlock->findConstant(value, constantRegister)) {
@@ -161,8 +161,13 @@
                 m_codeBlock->ownerExecutable(),
                 value);
         }
-        convertToConstant(node, constantRegister);
+        return constantRegister;
     }
+    
+    void convertToConstant(Node* node, JSValue value)
+    {
+        convertToConstant(node, constantRegisterForConstant(value));
+    }
 
     // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
     void dump(PrintStream& = WTF::dataFile(), DumpContext* = 0);

Modified: trunk/Source/_javascript_Core/runtime/TypedArrayType.h (154217 => 154218)


--- trunk/Source/_javascript_Core/runtime/TypedArrayType.h	2013-08-17 05:36:32 UTC (rev 154217)
+++ trunk/Source/_javascript_Core/runtime/TypedArrayType.h	2013-08-17 05:50:48 UTC (rev 154218)
@@ -64,7 +64,7 @@
     }
 }
 
-inline size_t elementSize(TypedArrayType type)
+inline unsigned logElementSize(TypedArrayType type)
 {
     switch (type) {
     case NotTypedArray:
@@ -73,21 +73,26 @@
     case TypeUint8:
     case TypeUint8Clamped:
     case TypeDataView:
-        return 1;
+        return 0;
     case TypeInt16:
     case TypeUint16:
-        return 2;
+        return 1;
     case TypeInt32:
     case TypeUint32:
     case TypeFloat32:
-        return 4;
+        return 2;
     case TypeFloat64:
-        return 8;
+        return 3;
     }
     RELEASE_ASSERT_NOT_REACHED();
     return 0;
 }
 
+inline size_t elementSize(TypedArrayType type)
+{
+    return static_cast<size_t>(1) << logElementSize(type);
+}
+
 const ClassInfo* classInfoForType(TypedArrayType);
 
 inline bool isInt(TypedArrayType type)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to