Use a heap-memory traversal to free compiler resources.

The stack-memory traversal is prone to stack overflow. See the
WebGL conformance test long-expressions-should-not-crash.

BUG=angle:584

Change-Id: I02d72bc2e4101b7141d609c50303403ea8298e60
Reviewed-on: https://chromium-review.googlesource.com/191930
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Reviewed-by: Nicolas Capens <nicolascapens@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/Intermediate.cpp b/src/compiler/translator/Intermediate.cpp
index 74b9a6e..9df2afc 100644
--- a/src/compiler/translator/Intermediate.cpp
+++ b/src/compiler/translator/Intermediate.cpp
@@ -786,6 +786,26 @@
     return false;
 }
 
+void TIntermLoop::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
+{
+    if (init)
+    {
+        nodeQueue->push(init);
+    }
+    if (cond)
+    {
+        nodeQueue->push(cond);
+    }
+    if (expr)
+    {
+        nodeQueue->push(expr);
+    }
+    if (body)
+    {
+        nodeQueue->push(body);
+    }
+}
+
 bool TIntermBranch::replaceChildNode(
     TIntermNode *original, TIntermNode *replacement)
 {
@@ -793,6 +813,14 @@
     return false;
 }
 
+void TIntermBranch::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
+{
+    if (expression)
+    {
+        nodeQueue->push(expression);
+    }
+}
+
 bool TIntermBinary::replaceChildNode(
     TIntermNode *original, TIntermNode *replacement)
 {
@@ -801,6 +829,18 @@
     return false;
 }
 
+void TIntermBinary::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
+{
+    if (left)
+    {
+        nodeQueue->push(left);
+    }
+    if (right)
+    {
+        nodeQueue->push(right);
+    }
+}
+
 bool TIntermUnary::replaceChildNode(
     TIntermNode *original, TIntermNode *replacement)
 {
@@ -808,6 +848,14 @@
     return false;
 }
 
+void TIntermUnary::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
+{
+    if (operand)
+    {
+        nodeQueue->push(operand);
+    }
+}
+
 bool TIntermAggregate::replaceChildNode(
     TIntermNode *original, TIntermNode *replacement)
 {
@@ -818,6 +866,14 @@
     return false;
 }
 
+void TIntermAggregate::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
+{
+    for (size_t childIndex = 0; childIndex < sequence.size(); childIndex++)
+    {
+        nodeQueue->push(sequence[childIndex]);
+    }
+}
+
 bool TIntermSelection::replaceChildNode(
     TIntermNode *original, TIntermNode *replacement)
 {
@@ -827,6 +883,22 @@
     return false;
 }
 
+void TIntermSelection::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
+{
+    if (condition)
+    {
+        nodeQueue->push(condition);
+    }
+    if (trueBlock)
+    {
+        nodeQueue->push(trueBlock);
+    }
+    if (falseBlock)
+    {
+        nodeQueue->push(falseBlock);
+    }
+}
+
 //
 // Say whether or not an operation node changes the value of a variable.
 //