Title: [184776] trunk
Revision
184776
Author
[email protected]
Date
2015-05-22 10:24:05 -0700 (Fri, 22 May 2015)

Log Message

Allow DFGClobberize to return non-node constants that must be later created
https://bugs.webkit.org/show_bug.cgi?id=145272

Reviewed by Filip Pizlo.

Source/_javascript_Core:

This adds a new LazyNode class in DFG that represents either a Node*,
or a FrozenValue* with a way to convert it to a Node* provided a block
to insert it into. DFGClobberize is converted to use LazyNode instead
of Node* when def()'ing values, which allows to now define the array's
length as well as the value of its various fields in NewArray and
NewArrayBuffer nodes.

We also introduce a Vector<uint32_t> in DFG::Graph to collect all the
values that can be used as index, in order to avoid def()'ing too many
values at once for big NewArrayBuffers.

HeapLocation had to be updated to use a LazyNode as its index to be
able to define array values.

* CMakeLists.txt:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
* _javascript_Core.xcodeproj/project.pbxproj:
* dfg/DFGCSEPhase.cpp:
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
(JSC::DFG::DefMethodClobberize::operator()):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::freezeFragile):
* dfg/DFGGraph.h:
* dfg/DFGHeapLocation.h:
(JSC::DFG::HeapLocation::HeapLocation):
(JSC::DFG::HeapLocation::index):
(JSC::DFG::HeapLocation::hash):
* dfg/DFGLazyNode.cpp: Added.
(JSC::DFG::LazyNode::dump):
* dfg/DFGLazyNode.h: Added.
(JSC::DFG::LazyNode::LazyNode):
(JSC::DFG::LazyNode::setNode):
(JSC::DFG::LazyNode::isHashTableDeletedValue):
(JSC::DFG::LazyNode::isNode):
(JSC::DFG::LazyNode::op):
(JSC::DFG::LazyNode::asNode):
(JSC::DFG::LazyNode::asValue):
(JSC::DFG::LazyNode::hash):
(JSC::DFG::LazyNode::operator==):
(JSC::DFG::LazyNode::operator!=):
(JSC::DFG::LazyNode::ensureIsNode):
(JSC::DFG::LazyNode::operator->):
(JSC::DFG::LazyNode::operator*):
(JSC::DFG::LazyNode::operator!):
(JSC::DFG::LazyNode::operator UnspecifiedBoolType*):
(JSC::DFG::LazyNode::setFrozenValue):
* dfg/DFGPreciseLocalClobberize.h:
(JSC::DFG::PreciseLocalClobberizeAdaptor::def):
* dfg/DFGPutStackSinkingPhase.cpp:

LayoutTests:

* js/regress/script-tests/cse-new-array-buffer.js: Added.
(foo):
* js/regress/script-tests/cse-new-array.js: Added.
(foo):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (184775 => 184776)


--- trunk/LayoutTests/ChangeLog	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/LayoutTests/ChangeLog	2015-05-22 17:24:05 UTC (rev 184776)
@@ -1,3 +1,15 @@
+2015-05-22  Basile Clement  <[email protected]>
+
+        Allow DFGClobberize to return non-node constants that must be later created
+        https://bugs.webkit.org/show_bug.cgi?id=145272
+
+        Reviewed by Filip Pizlo.
+
+        * js/regress/script-tests/cse-new-array-buffer.js: Added.
+        (foo):
+        * js/regress/script-tests/cse-new-array.js: Added.
+        (foo):
+
 2015-05-22  Marcos Chavarría Teijeiro  <[email protected]>
 
         [GTK] Gardening 21st May.

Added: trunk/LayoutTests/js/regress/script-tests/cse-new-array-buffer.js (0 => 184776)


--- trunk/LayoutTests/js/regress/script-tests/cse-new-array-buffer.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/cse-new-array-buffer.js	2015-05-22 17:24:05 UTC (rev 184776)
@@ -0,0 +1,8 @@
+function foo() {
+    var array = [1.5];
+    return Math.cos(Math.sqrt(Math.abs(Math.sin(array[0]) * 5 / 4.5))) % 3.5;
+}
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i)
+    foo();

Added: trunk/LayoutTests/js/regress/script-tests/cse-new-array.js (0 => 184776)


--- trunk/LayoutTests/js/regress/script-tests/cse-new-array.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/cse-new-array.js	2015-05-22 17:24:05 UTC (rev 184776)
@@ -0,0 +1,8 @@
+function foo(p) {
+    var array = [1.5, p];
+    return Math.cos(Math.sqrt(Math.abs(Math.sin(array[0]) * 5 / 4.5))) % 3.5;
+}
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i)
+    foo(0);

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (184775 => 184776)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2015-05-22 17:24:05 UTC (rev 184776)
@@ -187,6 +187,7 @@
     dfg/DFGJumpReplacement.cpp
     dfg/DFGLICMPhase.cpp
     dfg/DFGLazyJSValue.cpp
+    dfg/DFGLazyNode.cpp
     dfg/DFGLivenessAnalysisPhase.cpp
     dfg/DFGLongLivedState.cpp
     dfg/DFGLoopPreHeaderCreationPhase.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (184775 => 184776)


--- trunk/Source/_javascript_Core/ChangeLog	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-05-22 17:24:05 UTC (rev 184776)
@@ -1,3 +1,62 @@
+2015-05-22  Basile Clement  <[email protected]>
+
+        Allow DFGClobberize to return non-node constants that must be later created
+        https://bugs.webkit.org/show_bug.cgi?id=145272
+
+        Reviewed by Filip Pizlo.
+
+        This adds a new LazyNode class in DFG that represents either a Node*,
+        or a FrozenValue* with a way to convert it to a Node* provided a block
+        to insert it into. DFGClobberize is converted to use LazyNode instead
+        of Node* when def()'ing values, which allows to now define the array's
+        length as well as the value of its various fields in NewArray and
+        NewArrayBuffer nodes.
+
+        We also introduce a Vector<uint32_t> in DFG::Graph to collect all the
+        values that can be used as index, in order to avoid def()'ing too many
+        values at once for big NewArrayBuffers.
+
+        HeapLocation had to be updated to use a LazyNode as its index to be
+        able to define array values.
+
+        * CMakeLists.txt:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * dfg/DFGCSEPhase.cpp:
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        (JSC::DFG::DefMethodClobberize::operator()):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::freezeFragile):
+        * dfg/DFGGraph.h:
+        * dfg/DFGHeapLocation.h:
+        (JSC::DFG::HeapLocation::HeapLocation):
+        (JSC::DFG::HeapLocation::index):
+        (JSC::DFG::HeapLocation::hash):
+        * dfg/DFGLazyNode.cpp: Added.
+        (JSC::DFG::LazyNode::dump):
+        * dfg/DFGLazyNode.h: Added.
+        (JSC::DFG::LazyNode::LazyNode):
+        (JSC::DFG::LazyNode::setNode):
+        (JSC::DFG::LazyNode::isHashTableDeletedValue):
+        (JSC::DFG::LazyNode::isNode):
+        (JSC::DFG::LazyNode::op):
+        (JSC::DFG::LazyNode::asNode):
+        (JSC::DFG::LazyNode::asValue):
+        (JSC::DFG::LazyNode::hash):
+        (JSC::DFG::LazyNode::operator==):
+        (JSC::DFG::LazyNode::operator!=):
+        (JSC::DFG::LazyNode::ensureIsNode):
+        (JSC::DFG::LazyNode::operator->):
+        (JSC::DFG::LazyNode::operator*):
+        (JSC::DFG::LazyNode::operator!):
+        (JSC::DFG::LazyNode::operator UnspecifiedBoolType*):
+        (JSC::DFG::LazyNode::setFrozenValue):
+        * dfg/DFGPreciseLocalClobberize.h:
+        (JSC::DFG::PreciseLocalClobberizeAdaptor::def):
+        * dfg/DFGPutStackSinkingPhase.cpp:
+
 2015-05-22  Andreas Kling  <[email protected]>
 
         [JSC] Speed up new array construction in Array.prototype.splice().

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (184775 => 184776)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2015-05-22 17:24:05 UTC (rev 184776)
@@ -423,6 +423,7 @@
     <ClCompile Include="..\dfg\DFGJITFinalizer.cpp" />
     <ClCompile Include="..\dfg\DFGJumpReplacement.cpp" />
     <ClCompile Include="..\dfg\DFGLazyJSValue.cpp" />
+    <ClCompile Include="..\dfg\DFGLazyNode.cpp" />
     <ClCompile Include="..\dfg\DFGLICMPhase.cpp" />
     <ClCompile Include="..\dfg\DFGLivenessAnalysisPhase.cpp" />
     <ClCompile Include="..\dfg\DFGLongLivedState.cpp" />
@@ -1115,6 +1116,7 @@
     <ClInclude Include="..\dfg\DFGJITFinalizer.h" />
     <ClInclude Include="..\dfg\DFGJumpReplacement.h" />
     <ClInclude Include="..\dfg\DFGLazyJSValue.h" />
+    <ClInclude Include="..\dfg\DFGLazyNode.h" />
     <ClInclude Include="..\dfg\DFGLICMPhase.h" />
     <ClInclude Include="..\dfg\DFGLivenessAnalysisPhase.h" />
     <ClInclude Include="..\dfg\DFGLongLivedState.h" />

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters (184775 => 184776)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2015-05-22 17:24:05 UTC (rev 184776)
@@ -1191,6 +1191,9 @@
     <ClCompile Include="..\dfg\DFGLazyJSValue.cpp">
       <Filter>dfg</Filter>
     </ClCompile>
+    <ClCompile Include="..\dfg\DFGLazyNode.cpp">
+      <Filter>dfg</Filter>
+    </ClCompile>
     <ClCompile Include="..\dfg\DFGLICMPhase.cpp">
       <Filter>dfg</Filter>
     </ClCompile>
@@ -3562,6 +3565,9 @@
     <ClInclude Include="..\dfg\DFGLazyJSValue.h">
       <Filter>dfg</Filter>
     </ClInclude>
+    <ClInclude Include="..\dfg\DFGLazyNode.h">
+      <Filter>dfg</Filter>
+    </ClInclude>
     <ClInclude Include="..\dfg\DFGLICMPhase.h">
       <Filter>dfg</Filter>
     </ClInclude>

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (184775 => 184776)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-05-22 17:24:05 UTC (rev 184776)
@@ -960,6 +960,8 @@
 		5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */ = {isa = PBXBuildFile; fileRef = F692A8540255597D01FF60F7 /* create_hash_table */; settings = {ATTRIBUTES = (); }; };
 		62D2D38F1ADF103F000206C1 /* FunctionRareData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 62D2D38D1ADF103F000206C1 /* FunctionRareData.cpp */; };
 		62D2D3901ADF103F000206C1 /* FunctionRareData.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D2D38E1ADF103F000206C1 /* FunctionRareData.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		62F2AA371B0BEDE300610C7A /* DFGLazyNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 62A9A29E1B0BED4800BD54CA /* DFGLazyNode.cpp */; };
+		62F2AA381B0BEDE300610C7A /* DFGLazyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 62A9A29F1B0BED4800BD54CA /* DFGLazyNode.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		6507D29E0E871E5E00D7D896 /* JSTypeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 6507D2970E871E4A00D7D896 /* JSTypeInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		651122FD14046A4C002B101D /* _javascript_Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* _javascript_Core.framework */; };
 		651122FE14046A4C002B101D /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; };
@@ -2673,6 +2675,8 @@
 		5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = JSC.xcconfig; sourceTree = "<group>"; };
 		5DDDF44614FEE72200B4FB4D /* LLIntDesiredOffsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntDesiredOffsets.h; path = LLIntOffsets/LLIntDesiredOffsets.h; sourceTree = BUILT_PRODUCTS_DIR; };
 		5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitAvailability.h; sourceTree = "<group>"; };
+		62A9A29E1B0BED4800BD54CA /* DFGLazyNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLazyNode.cpp; path = dfg/DFGLazyNode.cpp; sourceTree = "<group>"; };
+		62A9A29F1B0BED4800BD54CA /* DFGLazyNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLazyNode.h; path = dfg/DFGLazyNode.h; sourceTree = "<group>"; };
 		62D2D38D1ADF103F000206C1 /* FunctionRareData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionRareData.cpp; sourceTree = "<group>"; };
 		62D2D38E1ADF103F000206C1 /* FunctionRareData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FunctionRareData.h; sourceTree = "<group>"; };
 		6507D2970E871E4A00D7D896 /* JSTypeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypeInfo.h; sourceTree = "<group>"; };
@@ -4989,6 +4993,8 @@
 				0FC97F3A18202119002C9B26 /* DFGJumpReplacement.h */,
 				A73A53581799CD5D00170C19 /* DFGLazyJSValue.cpp */,
 				A73A53591799CD5D00170C19 /* DFGLazyJSValue.h */,
+				62A9A29E1B0BED4800BD54CA /* DFGLazyNode.cpp */,
+				62A9A29F1B0BED4800BD54CA /* DFGLazyNode.h */,
 				A7D9A29217A0BC7400EE2618 /* DFGLICMPhase.cpp */,
 				A7D9A29317A0BC7400EE2618 /* DFGLICMPhase.h */,
 				A7D89CEC17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.cpp */,
@@ -5867,6 +5873,7 @@
 				A7D89CFE17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.h in Headers */,
 				0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */,
 				0FD8A32617D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h in Headers */,
+				62F2AA381B0BEDE300610C7A /* DFGLazyNode.h in Headers */,
 				0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */,
 				0F235BEC17178E7300690C7F /* DFGOSRExitBase.h in Headers */,
 				0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */,
@@ -7247,6 +7254,7 @@
 				0FEA0A0D170513DB00BB722C /* FTLJITCode.cpp in Sources */,
 				A78A9780179738D5009DF744 /* FTLJITFinalizer.cpp in Sources */,
 				0F2B9CF419D0BAC100B1D1B5 /* FTLExitPropertyValue.cpp in Sources */,
+				62F2AA371B0BEDE300610C7A /* DFGLazyNode.cpp in Sources */,
 				0F6B1CB5185FC9E900845D97 /* FTLJSCall.cpp in Sources */,
 				0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */,
 				0FCEFADF180738C000472CE4 /* FTLLocation.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (184775 => 184776)


--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2015-05-22 17:24:05 UTC (rev 184776)
@@ -148,7 +148,7 @@
             return nullptr;
         }
         
-        Node* findReplacement(HeapLocation location)
+        LazyNode findReplacement(HeapLocation location)
         {
             for (unsigned i = m_impureLength; i--;) {
                 if (m_impureMap[i].key == location)
@@ -157,18 +157,22 @@
             return nullptr;
         }
     
-        Node* addImpure(HeapLocation location, Node* node)
+        LazyNode addImpure(HeapLocation location, LazyNode node)
         {
-            if (Node* result = findReplacement(location))
+            // FIXME: If we are using small maps, we must not def() derived values.
+            // For now the only derived values we def() are constant-based.
+            if (location.index() && !location.index().isNode())
+                return nullptr;
+            if (LazyNode result = findReplacement(location))
                 return result;
             ASSERT(m_impureLength < capacity);
-            m_impureMap[m_impureLength++] = WTF::KeyValuePair<HeapLocation, Node*>(location, node);
+            m_impureMap[m_impureLength++] = WTF::KeyValuePair<HeapLocation, LazyNode>(location, node);
             return nullptr;
         }
     
     private:
         WTF::KeyValuePair<PureValue, Node*> m_pureMap[capacity];
-        WTF::KeyValuePair<HeapLocation, Node*> m_impureMap[capacity];
+        WTF::KeyValuePair<HeapLocation, LazyNode> m_impureMap[capacity];
         unsigned m_pureLength;
         unsigned m_impureLength;
     };
@@ -198,12 +202,12 @@
             return result.iterator->value;
         }
         
-        Node* findReplacement(HeapLocation location)
+        LazyNode findReplacement(HeapLocation location)
         {
             return m_impureMap.get(location);
         }
     
-        Node* addImpure(HeapLocation location, Node* node)
+        LazyNode addImpure(HeapLocation location, LazyNode node)
         {
             auto result = m_impureMap.add(location, node);
             if (result.isNewEntry)
@@ -213,7 +217,7 @@
 
     private:
         HashMap<PureValue, Node*> m_pureMap;
-        HashMap<HeapLocation, Node*> m_impureMap;
+        HashMap<HeapLocation, LazyNode> m_impureMap;
     };
 
     template<typename Maps>
@@ -221,6 +225,7 @@
     public:
         BlockCSE(Graph& graph)
             : m_graph(graph)
+            , m_insertionSet(graph)
         {
         }
     
@@ -228,6 +233,7 @@
         {
             m_maps.clear();
             m_changed = false;
+            m_block = block;
         
             for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
                 m_node = block->at(nodeIndex);
@@ -297,6 +303,8 @@
                     clobberize(m_graph, m_node, *this);
                 }
             }
+
+            m_insertionSet.execute(block);
         
             return m_changed;
         }
@@ -318,9 +326,9 @@
             m_changed = true;
         }
     
-        void def(HeapLocation location, Node* value)
+        void def(HeapLocation location, LazyNode value)
         {
-            Node* match = m_maps.addImpure(location, value);
+            LazyNode match = m_maps.addImpure(location, value);
             if (!match)
                 return;
         
@@ -343,8 +351,12 @@
                 m_graph.dethread();
             }
         
-            m_node->replaceWith(match);
-            m_changed = true;
+            if (value.isNode() && value.asNode() == m_node) {
+                match.ensureIsNode(m_insertionSet, m_block, 0)->owner = m_block;
+                ASSERT(match.isNode());
+                m_node->replaceWith(match.asNode());
+                m_changed = true;
+            }
         }
     
     private:
@@ -352,8 +364,11 @@
         
         bool m_changed;
         Node* m_node;
+        BasicBlock* m_block;
     
         Maps m_maps;
+
+        InsertionSet m_insertionSet;
     };
 
     BlockCSE<SmallMaps> m_smallBlock;
@@ -365,6 +380,7 @@
     GlobalCSEPhase(Graph& graph)
         : Phase(graph, "global common subexpression elimination")
         , m_impureDataMap(graph)
+        , m_insertionSet(graph)
     {
     }
     
@@ -429,6 +445,7 @@
                 dataLog("Processing block ", *m_block, ":\n");
 
             for (unsigned nodeIndex = 0; nodeIndex < m_block->size(); ++nodeIndex) {
+                m_nodeIndex = nodeIndex;
                 m_node = m_block->at(nodeIndex);
                 if (verbose)
                     dataLog("  Looking at node ", m_node, ":\n");
@@ -441,6 +458,8 @@
                 } else
                     clobberize(m_graph, m_node, *this);
             }
+
+            m_insertionSet.execute(m_block);
             
             m_impureData->didVisit = true;
         }
@@ -486,13 +505,13 @@
         result.iterator->value.append(m_node);
     }
     
-    Node* findReplacement(HeapLocation location)
+    LazyNode findReplacement(HeapLocation location)
     {
         // At this instant, our "availableAtTail" reflects the set of things that are available in
         // this block so far. We check this map to find block-local CSE opportunities before doing
         // a global search.
-        Node* match = m_impureData->availableAtTail.get(location);
-        if (match) {
+        LazyNode match = m_impureData->availableAtTail.get(location);
+        if (!!match) {
             if (verbose)
                 dataLog("      Found local match: ", match, "\n");
             return match;
@@ -575,7 +594,7 @@
                 match = data.availableAtTail.get(location);
                 if (verbose)
                     dataLog("        Availability: ", match, "\n");
-                if (match) {
+                if (!!match) {
                     // Don't examine the predecessors of a match. At this point we just want to
                     // establish that other blocks on the path from here to there don't clobber
                     // the location we're interested in.
@@ -616,12 +635,12 @@
         return match;
     }
     
-    void def(HeapLocation location, Node* value)
+    void def(HeapLocation location, LazyNode value)
     {
         if (verbose)
             dataLog("    Got heap location def: ", location, " -> ", value, "\n");
         
-        Node* match = findReplacement(location);
+        LazyNode match = findReplacement(location);
         
         if (verbose)
             dataLog("      Got match: ", match, "\n");
@@ -633,9 +652,33 @@
             ASSERT_UNUSED(result, result.isNewEntry);
             return;
         }
-        
-        m_node->replaceWith(match);
-        m_changed = true;
+
+        if (value.isNode() && value.asNode() == m_node) {
+            if (!match.isNode()) {
+                // We need to properly record the constant in order to use an existing one if applicable.
+                // This ensures that re-running GCSE will not find new optimizations.
+                match.ensureIsNode(m_insertionSet, m_block, m_nodeIndex)->owner = m_block;
+                auto result = m_pureValues.add(PureValue(match.asNode(), match->constant()), Vector<Node*>());
+                bool replaced = false;
+                if (!result.isNewEntry) {
+                    for (unsigned i = result.iterator->value.size(); i--;) {
+                        Node* candidate = result.iterator->value[i];
+                        if (m_graph.m_dominators.dominates(candidate->owner, m_block)) {
+                            ASSERT(candidate);
+                            match->replaceWith(candidate);
+                            match.setNode(candidate);
+                            replaced = true;
+                            break;
+                        }
+                    }
+                }
+                if (!replaced)
+                    result.iterator->value.append(match.asNode());
+            }
+            ASSERT(match.asNode());
+            m_node->replaceWith(match.asNode());
+            m_changed = true;
+        }
     }
     
     struct ImpureBlockData {
@@ -656,8 +699,10 @@
     
     BasicBlock* m_block;
     Node* m_node;
+    unsigned m_nodeIndex;
     ImpureBlockData* m_impureData;
     ClobberSet m_writesSoFar;
+    InsertionSet m_insertionSet;
     
     bool m_changed;
 };

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (184775 => 184776)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2015-05-22 17:24:05 UTC (rev 184776)
@@ -32,6 +32,7 @@
 #include "DFGEdgeUsesStructure.h"
 #include "DFGGraph.h"
 #include "DFGHeapLocation.h"
+#include "DFGLazyNode.h"
 #include "DFGPureValue.h"
 
 namespace JSC { namespace DFG {
@@ -195,7 +196,7 @@
             if (mode.isInBounds()) {
                 read(Butterfly_publicLength);
                 read(IndexedInt32Properties);
-                def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node);
+                def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), LazyNode(node));
                 return;
             }
             read(Heap);
@@ -206,7 +207,7 @@
             if (mode.isInBounds()) {
                 read(Butterfly_publicLength);
                 read(IndexedDoubleProperties);
-                def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node);
+                def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), LazyNode(node));
                 return;
             }
             read(Heap);
@@ -217,7 +218,7 @@
             if (mode.isInBounds()) {
                 read(Butterfly_publicLength);
                 read(IndexedContiguousProperties);
-                def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), node);
+                def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), LazyNode(node));
                 return;
             }
             read(Heap);
@@ -303,7 +304,7 @@
         
     case InvalidationPoint:
         write(SideState);
-        def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), node);
+        def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), LazyNode(node));
         return;
 
     case Flush:
@@ -354,17 +355,17 @@
 
     case VarInjectionWatchpoint:
         read(MiscFields);
-        def(HeapLocation(VarInjectionWatchpointLoc, MiscFields), node);
+        def(HeapLocation(VarInjectionWatchpointLoc, MiscFields), LazyNode(node));
         return;
 
     case IsObjectOrNull:
         read(MiscFields);
-        def(HeapLocation(IsObjectOrNullLoc, MiscFields, node->child1()), node);
+        def(HeapLocation(IsObjectOrNullLoc, MiscFields, node->child1()), LazyNode(node));
         return;
         
     case IsFunction:
         read(MiscFields);
-        def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), node);
+        def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), LazyNode(node));
         return;
         
     case GetById:
@@ -391,45 +392,45 @@
         
     case GetGetter:
         read(GetterSetter_getter);
-        def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), node);
+        def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), LazyNode(node));
         return;
         
     case GetSetter:
         read(GetterSetter_setter);
-        def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), node);
+        def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), LazyNode(node));
         return;
         
     case GetCallee:
         read(AbstractHeap(Stack, JSStack::Callee));
-        def(HeapLocation(StackLoc, AbstractHeap(Stack, JSStack::Callee)), node);
+        def(HeapLocation(StackLoc, AbstractHeap(Stack, JSStack::Callee)), LazyNode(node));
         return;
         
     case GetArgumentCount:
         read(AbstractHeap(Stack, JSStack::ArgumentCount));
-        def(HeapLocation(StackPayloadLoc, AbstractHeap(Stack, JSStack::ArgumentCount)), node);
+        def(HeapLocation(StackPayloadLoc, AbstractHeap(Stack, JSStack::ArgumentCount)), LazyNode(node));
         return;
         
     case GetLocal:
         read(AbstractHeap(Stack, node->local()));
-        def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), node);
+        def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node));
         return;
         
     case SetLocal:
         write(AbstractHeap(Stack, node->local()));
-        def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), node->child1().node());
+        def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), LazyNode(node->child1().node()));
         return;
         
     case GetStack: {
         AbstractHeap heap(Stack, node->stackAccessData()->local);
         read(heap);
-        def(HeapLocation(StackLoc, heap), node);
+        def(HeapLocation(StackLoc, heap), LazyNode(node));
         return;
     }
         
     case PutStack: {
         AbstractHeap heap(Stack, node->stackAccessData()->local);
         write(heap);
-        def(HeapLocation(StackLoc, heap), node->child1().node());
+        def(HeapLocation(StackLoc, heap), LazyNode(node->child1().node()));
         return;
     }
         
@@ -456,7 +457,7 @@
         
     case GetLocalUnlinked:
         read(AbstractHeap(Stack, node->unlinkedLocal()));
-        def(HeapLocation(StackLoc, AbstractHeap(Stack, node->unlinkedLocal())), node);
+        def(HeapLocation(StackLoc, AbstractHeap(Stack, node->unlinkedLocal())), LazyNode(node));
         return;
         
     case GetByVal: {
@@ -491,19 +492,19 @@
             
         case Array::DirectArguments:
             read(DirectArgumentsProperties);
-            def(HeapLocation(IndexedPropertyLoc, DirectArgumentsProperties, node->child1(), node->child2()), node);
+            def(HeapLocation(IndexedPropertyLoc, DirectArgumentsProperties, node->child1(), node->child2()), LazyNode(node));
             return;
             
         case Array::ScopedArguments:
             read(ScopeProperties);
-            def(HeapLocation(IndexedPropertyLoc, ScopeProperties, node->child1(), node->child2()), node);
+            def(HeapLocation(IndexedPropertyLoc, ScopeProperties, node->child1(), node->child2()), LazyNode(node));
             return;
             
         case Array::Int32:
             if (mode.isInBounds()) {
                 read(Butterfly_publicLength);
                 read(IndexedInt32Properties);
-                def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node);
+                def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), LazyNode(node));
                 return;
             }
             read(World);
@@ -514,7 +515,7 @@
             if (mode.isInBounds()) {
                 read(Butterfly_publicLength);
                 read(IndexedDoubleProperties);
-                def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node);
+                def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), LazyNode(node));
                 return;
             }
             read(World);
@@ -525,7 +526,7 @@
             if (mode.isInBounds()) {
                 read(Butterfly_publicLength);
                 read(IndexedContiguousProperties);
-                def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), node);
+                def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), LazyNode(node));
                 return;
             }
             read(World);
@@ -554,7 +555,7 @@
         case Array::Float64Array:
             read(TypedArrayProperties);
             read(MiscFields);
-            def(HeapLocation(IndexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), node);
+            def(HeapLocation(IndexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), LazyNode(node));
             return;
         }
         RELEASE_ASSERT_NOT_REACHED();
@@ -605,7 +606,7 @@
             write(IndexedInt32Properties);
             if (node->arrayMode().mayStoreToHole())
                 write(Butterfly_publicLength);
-            def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, base, index), value);
+            def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, base, index), LazyNode(value));
             return;
             
         case Array::Double:
@@ -620,7 +621,7 @@
             write(IndexedDoubleProperties);
             if (node->arrayMode().mayStoreToHole())
                 write(Butterfly_publicLength);
-            def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, base, index), value);
+            def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, base, index), LazyNode(value));
             return;
             
         case Array::Contiguous:
@@ -635,7 +636,7 @@
             write(IndexedContiguousProperties);
             if (node->arrayMode().mayStoreToHole())
                 write(Butterfly_publicLength);
-            def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, base, index), value);
+            def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, base, index), LazyNode(value));
             return;
             
         case Array::ArrayStorage:
@@ -681,12 +682,12 @@
 
     case CheckHasInstance:
         read(JSCell_typeInfoFlags);
-        def(HeapLocation(CheckHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), node);
+        def(HeapLocation(CheckHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
         return;
 
     case InstanceOf:
         read(JSCell_structureID);
-        def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), node);
+        def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), LazyNode(node));
         return;
 
     case PutStructure:
@@ -698,18 +699,18 @@
         
     case AllocatePropertyStorage:
         write(JSObject_butterfly);
-        def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
+        def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
         return;
         
     case ReallocatePropertyStorage:
         read(JSObject_butterfly);
         write(JSObject_butterfly);
-        def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
+        def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
         return;
         
     case GetButterfly:
         read(JSObject_butterfly);
-        def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
+        def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), LazyNode(node));
         return;
         
     case Arrayify:
@@ -729,12 +730,12 @@
             return;
         }
         read(MiscFields);
-        def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), node);
+        def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), LazyNode(node));
         return;
         
     case GetTypedArrayByteOffset:
         read(MiscFields);
-        def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), node);
+        def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), LazyNode(node));
         return;
         
     case GetByOffset:
@@ -742,7 +743,7 @@
         unsigned identifierNumber = node->storageAccessData().identifierNumber;
         AbstractHeap heap(NamedProperties, identifierNumber);
         read(heap);
-        def(HeapLocation(NamedPropertyLoc, heap, node->child2()), node);
+        def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node));
         return;
     }
         
@@ -751,7 +752,7 @@
         read(JSObject_butterfly);
         AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
         read(heap);
-        def(HeapLocation(NamedPropertyLoc, heap, node->child1()), node);
+        def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node));
         return;
     }
         
@@ -764,7 +765,7 @@
             write(JSCell_structureID);
         if (node->multiPutByOffsetData().reallocatesStorage())
             write(JSObject_butterfly);
-        def(HeapLocation(NamedPropertyLoc, heap, node->child1()), node->child2().node());
+        def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(node->child2().node()));
         return;
     }
         
@@ -772,7 +773,7 @@
         unsigned identifierNumber = node->storageAccessData().identifierNumber;
         AbstractHeap heap(NamedProperties, identifierNumber);
         write(heap);
-        def(HeapLocation(NamedPropertyLoc, heap, node->child2()), node->child3().node());
+        def(HeapLocation(NamedPropertyLoc, heap, node->child2()), LazyNode(node->child3().node()));
         return;
     }
         
@@ -785,7 +786,7 @@
         case Array::ArrayStorage:
         case Array::SlowPutArrayStorage:
             read(Butterfly_publicLength);
-            def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), node);
+            def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), LazyNode(node));
             return;
             
         case Array::String:
@@ -795,63 +796,150 @@
         case Array::DirectArguments:
         case Array::ScopedArguments:
             read(MiscFields);
-            def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node);
+            def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
             return;
             
         default:
             ASSERT(mode.typedArrayType() != NotTypedArray);
             read(MiscFields);
-            def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node);
+            def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node));
             return;
         }
     }
         
     case GetClosureVar:
         read(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
-        def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), node);
+        def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node));
         return;
         
     case PutClosureVar:
         write(AbstractHeap(ScopeProperties, node->scopeOffset().offset()));
-        def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), node->child2().node());
+        def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), LazyNode(node->child2().node()));
         return;
         
     case GetFromArguments: {
         AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
         read(heap);
-        def(HeapLocation(DirectArgumentsLoc, heap), node);
+        def(HeapLocation(DirectArgumentsLoc, heap), LazyNode(node));
         return;
     }
         
     case PutToArguments: {
         AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset());
         write(heap);
-        def(HeapLocation(DirectArgumentsLoc, heap), node->child2().node());
+        def(HeapLocation(DirectArgumentsLoc, heap), LazyNode(node->child2().node()));
         return;
     }
         
     case GetGlobalVar:
         read(AbstractHeap(Absolute, node->variablePointer()));
-        def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), node);
+        def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node));
         return;
         
     case PutGlobalVar:
         write(AbstractHeap(Absolute, node->variablePointer()));
-        def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), node->child2().node());
+        def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), LazyNode(node->child2().node()));
         return;
 
-    case NewArray:
     case NewArrayWithSize:
-    case NewArrayBuffer:
     case NewTypedArray:
-        // FIXME: Enable CSE for these nodes. We can't do this right now because there is no way
-        // for us to claim an index node and a value node. We could make this work if we lowered
-        // these nodes or if we had a more flexible way of def()'ing.
-        // https://bugs.webkit.org/show_bug.cgi?id=134737
         read(HeapObjectCount);
         write(HeapObjectCount);
         return;
 
+    case NewArray: {
+        read(HeapObjectCount);
+        write(HeapObjectCount);
+
+        unsigned numElements = node->numChildren();
+
+        def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
+            LazyNode(graph.freeze(jsNumber(numElements))));
+
+        if (!numElements)
+            return;
+
+        AbstractHeap heap;
+        switch (node->indexingType()) {
+        case ALL_DOUBLE_INDEXING_TYPES:
+            heap = IndexedDoubleProperties;
+            break;
+
+        case ALL_INT32_INDEXING_TYPES:
+            heap = IndexedInt32Properties;
+            break;
+
+        case ALL_CONTIGUOUS_INDEXING_TYPES:
+            heap = IndexedContiguousProperties;
+            break;
+
+        default:
+            return;
+        }
+
+        if (numElements < graph.m_uint32ValuesInUse.size()) {
+            for (unsigned operandIdx = 0; operandIdx < numElements; ++operandIdx) {
+                Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
+                def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
+                    LazyNode(use.node()));
+            }
+        } else {
+            for (uint32_t operandIdx : graph.m_uint32ValuesInUse) {
+                if (operandIdx >= numElements)
+                    continue;
+                Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx];
+                def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))),
+                    LazyNode(use.node()));
+            }
+        }
+        return;
+    }
+
+    case NewArrayBuffer: {
+        read(HeapObjectCount);
+        write(HeapObjectCount);
+
+        unsigned numElements = node->numConstants();
+        def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node),
+            LazyNode(graph.freeze(jsNumber(numElements))));
+
+        AbstractHeap heap;
+        NodeType op = JSConstant;
+        switch (node->indexingType()) {
+        case ALL_DOUBLE_INDEXING_TYPES:
+            heap = IndexedDoubleProperties;
+            op = DoubleConstant;
+            break;
+
+        case ALL_INT32_INDEXING_TYPES:
+            heap = IndexedInt32Properties;
+            break;
+
+        case ALL_CONTIGUOUS_INDEXING_TYPES:
+            heap = IndexedContiguousProperties;
+            break;
+
+        default:
+            return;
+        }
+
+        JSValue* data = ""
+        if (numElements < graph.m_uint32ValuesInUse.size()) {
+            for (unsigned index = 0; index < numElements; ++index) {
+                def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
+                    LazyNode(graph.freeze(data[index]), op));
+            }
+        } else {
+            for (uint32_t index : graph.m_uint32ValuesInUse) {
+                if (index >= numElements)
+                    continue;
+                def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))),
+                    LazyNode(graph.freeze(data[index]), op));
+            }
+        }
+        return;
+    }
+
     case NewObject:
     case NewRegexp:
     case NewStringObject:
@@ -1039,7 +1127,7 @@
         m_value.def(value);
     }
     
-    void operator()(HeapLocation location, Node* node) const
+    void operator()(HeapLocation location, LazyNode node) const
     {
         m_value.def(location, node);
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (184775 => 184776)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2015-05-22 17:24:05 UTC (rev 184776)
@@ -1210,6 +1210,9 @@
     auto result = m_frozenValueMap.add(JSValue::encode(value), nullptr);
     if (LIKELY(!result.isNewEntry))
         return result.iterator->value;
+
+    if (value.isUInt32())
+        m_uint32ValuesInUse.append(value.asUInt32());
     
     return result.iterator->value = m_frozenValues.add(FrozenValue::freeze(value));
 }

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (184775 => 184776)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.h	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h	2015-05-22 17:24:05 UTC (rev 184776)
@@ -806,6 +806,8 @@
 
     HashMap<EncodedJSValue, FrozenValue*, EncodedJSValueHash, EncodedJSValueHashTraits> m_frozenValueMap;
     Bag<FrozenValue> m_frozenValues;
+
+    Vector<uint32_t> m_uint32ValuesInUse;
     
     Bag<StorageAccessData> m_storageAccessData;
     

Modified: trunk/Source/_javascript_Core/dfg/DFGHeapLocation.h (184775 => 184776)


--- trunk/Source/_javascript_Core/dfg/DFGHeapLocation.h	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/dfg/DFGHeapLocation.h	2015-05-22 17:24:05 UTC (rev 184776)
@@ -29,6 +29,7 @@
 #if ENABLE(DFG_JIT)
 
 #include "DFGAbstractHeap.h"
+#include "DFGLazyNode.h"
 #include "DFGNode.h"
 
 namespace JSC { namespace DFG {
@@ -64,7 +65,7 @@
     HeapLocation(
         LocationKind kind = InvalidLocationKind,
         AbstractHeap heap = AbstractHeap(),
-        Node* base = nullptr, Node* index = nullptr)
+        Node* base = nullptr, LazyNode index = LazyNode())
         : m_kind(kind)
         , m_heap(heap)
         , m_base(base)
@@ -74,6 +75,11 @@
         ASSERT(!!m_heap || !m_base);
         ASSERT(m_base || !m_index);
     }
+
+    HeapLocation(LocationKind kind, AbstractHeap heap, Node* base, Node* index)
+        : HeapLocation(kind, heap, base, LazyNode(index))
+    {
+    }
     
     HeapLocation(LocationKind kind, AbstractHeap heap, Edge base, Edge index = Edge())
         : HeapLocation(kind, heap, base.node(), index.node())
@@ -93,11 +99,11 @@
     LocationKind kind() const { return m_kind; }
     AbstractHeap heap() const { return m_heap; }
     Node* base() const { return m_base; }
-    Node* index() const { return m_index; }
+    LazyNode index() const { return m_index; }
     
     unsigned hash() const
     {
-        return m_kind + m_heap.hash() + WTF::PtrHash<Node*>::hash(m_index) + m_kind;
+        return m_kind + m_heap.hash() + m_index.hash() + m_kind;
     }
     
     bool operator==(const HeapLocation& other) const
@@ -119,7 +125,7 @@
     LocationKind m_kind;
     AbstractHeap m_heap;
     Node* m_base;
-    Node* m_index;
+    LazyNode m_index;
 };
 
 struct HeapLocationHash {
@@ -148,7 +154,7 @@
 
 namespace JSC { namespace DFG {
 
-typedef HashMap<HeapLocation, Node*> ImpureMap;
+typedef HashMap<HeapLocation, LazyNode> ImpureMap;
 
 } } // namespace JSC::DFG
 

Added: trunk/Source/_javascript_Core/dfg/DFGLazyNode.cpp (0 => 184776)


--- trunk/Source/_javascript_Core/dfg/DFGLazyNode.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/dfg/DFGLazyNode.cpp	2015-05-22 17:24:05 UTC (rev 184776)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
+ */
+
+#include "config.h"
+#include "DFGLazyNode.h"
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+void LazyNode::dump(PrintStream& out) const
+{
+    if (!*this)
+        out.print("LazyNode:0");
+    else {
+        if (isNode())
+            out.print("LazyNode:@", asNode()->index());
+        else
+            out.print("LazyNode:FrozenValue:", Graph::opName(op()), ", ", pointerDump(asValue()));
+        out.print(")");
+    }
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)

Added: trunk/Source/_javascript_Core/dfg/DFGLazyNode.h (0 => 184776)


--- trunk/Source/_javascript_Core/dfg/DFGLazyNode.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/dfg/DFGLazyNode.h	2015-05-22 17:24:05 UTC (rev 184776)
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2015 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
+ */
+
+#ifndef DFGLazyNode_h
+#define DFGLazyNode_h
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGCommon.h"
+#include "DFGInsertionSet.h"
+#include <wtf/PrintStream.h>
+
+namespace JSC { namespace DFG {
+
+
+
+class LazyNode {
+public:
+    static const size_t jsConstantTag = 0;
+    static const size_t doubleConstantTag = 1;
+    static const size_t int52ConstantTag = 2;
+
+    static const uintptr_t tagMask = 0x3;
+    static const uintptr_t pointerMask = ~tagMask;
+
+    explicit LazyNode(Node* node = nullptr)
+        : m_node(node)
+        , m_value(reinterpret_cast<uintptr_t>(nullptr))
+    {
+        if (node && node->isConstant())
+            setFrozenValue(node->constant(), node->op());
+    }
+
+    explicit LazyNode(FrozenValue* value, NodeType op = JSConstant)
+        : m_node(nullptr)
+        , m_value(reinterpret_cast<uintptr_t>(nullptr))
+    {
+        setFrozenValue(value, op);
+    }
+
+    LazyNode(std::nullptr_t)
+        : m_node(nullptr)
+        , m_value(reinterpret_cast<uintptr_t>(nullptr))
+    {
+    }
+
+    LazyNode(WTF::HashTableDeletedValueType)
+        : m_node(reinterpret_cast<Node*>(-1))
+    {
+    }
+
+    void setNode(Node* node)
+    {
+        m_node = node;
+        if (node && node->isConstant())
+            setFrozenValue(node->constant(), node->op());
+    }
+
+    bool isHashTableDeletedValue() const { return m_node == reinterpret_cast<Node*>(-1); }
+
+    bool isNode() const { return m_node; }
+
+    NodeType op() const
+    {
+        if (m_node)
+            return m_node->op();
+
+        switch (m_value & tagMask) {
+        case jsConstantTag:
+            return JSConstant;
+        case doubleConstantTag:
+            return DoubleConstant;
+        case int52ConstantTag:
+            return Int52Constant;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+    }
+
+    Node* asNode() const
+    {
+        ASSERT(m_node || !asValue());
+        return m_node;
+    }
+
+    FrozenValue* asValue() const
+    {
+        return reinterpret_cast<FrozenValue*>(m_value & pointerMask);
+    }
+
+    unsigned hash() const
+    {
+        if (asValue())
+            return WTF::PtrHash<FrozenValue*>::hash(asValue());
+        return WTF::PtrHash<Node*>::hash(m_node);
+    }
+
+    bool operator==(const LazyNode& other) const
+    {
+        if (asValue())
+            return m_value == other.m_value;
+        return m_node == other.m_node;
+    }
+
+    bool operator!=(const LazyNode& other) const
+    {
+        return !(*this == other);
+    }
+
+    Node* ensureIsNode(InsertionSet& insertionSet, BasicBlock* block, unsigned nodeIndex)
+    {
+        if (!m_node)
+            m_node = insertionSet.insertConstant(nodeIndex, block->at(nodeIndex)->origin, asValue(), op());
+
+        return asNode();
+    }
+
+    Node* operator->() const { return asNode(); }
+
+    Node& operator*() const { return *asNode(); }
+
+    bool operator!() const { return !asValue() && !asNode(); }
+
+    typedef void* (LazyNode::*UnspecifiedBoolType);
+
+    operator UnspecifiedBoolType*() const
+    {
+        return !!*this ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0;
+    }
+
+    void dump(PrintStream& out) const;
+
+private:
+    void setFrozenValue(FrozenValue* value, NodeType op)
+    {
+        ASSERT(value);
+        m_value = reinterpret_cast<uintptr_t>(value);
+        ASSERT(m_value == (m_value & pointerMask));
+        switch (op) {
+        case JSConstant:
+            m_value |= jsConstantTag;
+            break;
+        case DoubleConstant:
+            m_value |= doubleConstantTag;
+            break;
+        case Int52Constant:
+            m_value |= int52ConstantTag;
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+    }
+
+    Node* m_node;
+    uintptr_t m_value;
+};
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::DFG::LazyNode> : SimpleClassHashTraits<JSC::DFG::LazyNode> {
+    static const bool emptyValueIsZero = true;
+};
+
+} // namespace WTF
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGLazyNode_h

Modified: trunk/Source/_javascript_Core/dfg/DFGPreciseLocalClobberize.h (184775 => 184776)


--- trunk/Source/_javascript_Core/dfg/DFGPreciseLocalClobberize.h	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/dfg/DFGPreciseLocalClobberize.h	2015-05-22 17:24:05 UTC (rev 184776)
@@ -82,7 +82,7 @@
         // PureValue defs never have anything to do with locals, so ignore this.
     }
     
-    void def(HeapLocation location, Node* node)
+    void def(HeapLocation location, LazyNode node)
     {
         if (location.kind() != StackLoc)
             return;

Modified: trunk/Source/_javascript_Core/dfg/DFGPutStackSinkingPhase.cpp (184775 => 184776)


--- trunk/Source/_javascript_Core/dfg/DFGPutStackSinkingPhase.cpp	2015-05-22 17:24:04 UTC (rev 184775)
+++ trunk/Source/_javascript_Core/dfg/DFGPutStackSinkingPhase.cpp	2015-05-22 17:24:05 UTC (rev 184776)
@@ -109,8 +109,10 @@
                     
                     preciseLocalClobberize(
                         m_graph, node, escapeHandler, escapeHandler,
-                        [&] (VirtualRegister operand, Node* source) {
-                            if (source == node) {
+                        [&] (VirtualRegister operand, LazyNode source) {
+                            RELEASE_ASSERT(source.isNode());
+
+                            if (source.asNode() == node) {
                                 // This is a load. Ignore it.
                                 return;
                             }
@@ -231,8 +233,10 @@
                     
                     preciseLocalClobberize(
                         m_graph, node, escapeHandler, escapeHandler,
-                        [&] (VirtualRegister operand, Node* source) {
-                            if (source == node) {
+                        [&] (VirtualRegister operand, LazyNode source) {
+                            RELEASE_ASSERT(source.isNode());
+
+                            if (source.asNode() == node) {
                                 // This is a load. Ignore it.
                                 return;
                             }
@@ -436,7 +440,7 @@
                 
                     preciseLocalClobberize(
                         m_graph, node, escapeHandler, escapeHandler,
-                        [&] (VirtualRegister, Node*) { });
+                        [&] (VirtualRegister, LazyNode) { });
                     break;
                 } }
             }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to