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.h b/src/compiler/translator/intermediate.h
index db3481c..b09fc9e 100644
--- a/src/compiler/translator/intermediate.h
+++ b/src/compiler/translator/intermediate.h
@@ -19,6 +19,7 @@
#include "GLSLANG/ShaderLang.h"
#include <algorithm>
+#include <queue>
#include "compiler/translator/Common.h"
#include "compiler/translator/Types.h"
#include "compiler/translator/ConstantUnion.h"
@@ -243,6 +244,10 @@
virtual bool replaceChildNode(
TIntermNode *original, TIntermNode *replacement) = 0;
+ // For traversing a tree in no particular order, but using
+ // heap memory.
+ virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const = 0;
+
protected:
TSourceLoc line;
};
@@ -328,6 +333,8 @@
void setUnrollFlag(bool flag) { unrollFlag = flag; }
bool getUnrollFlag() { return unrollFlag; }
+ virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
+
protected:
TLoopType type;
TIntermNode* init; // for-loop initialization
@@ -354,6 +361,8 @@
TOperator getFlowOp() { return flowOp; }
TIntermTyped* getExpression() { return expression; }
+ virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
+
protected:
TOperator flowOp;
TIntermTyped* expression; // non-zero except for "return exp;" statements
@@ -381,6 +390,8 @@
virtual TIntermSymbol* getAsSymbolNode() { return this; }
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
+ virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
+
protected:
int id;
TString symbol;
@@ -405,6 +416,8 @@
TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
+ virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
+
protected:
ConstantUnion *unionArrayPointer;
};
@@ -451,6 +464,8 @@
void setAddIndexClamp() { addIndexClamp = true; }
bool getAddIndexClamp() { return addIndexClamp; }
+ virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
+
protected:
TIntermTyped* left;
TIntermTyped* right;
@@ -481,6 +496,8 @@
void setUseEmulatedFunction() { useEmulatedFunction = true; }
bool getUseEmulatedFunction() { return useEmulatedFunction; }
+ virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
+
protected:
TIntermTyped* operand;
@@ -525,6 +542,8 @@
void setUseEmulatedFunction() { useEmulatedFunction = true; }
bool getUseEmulatedFunction() { return useEmulatedFunction; }
+ virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
+
protected:
TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
@@ -563,6 +582,8 @@
TIntermNode* getFalseBlock() const { return falseBlock; }
TIntermSelection* getAsSelectionNode() { return this; }
+ virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
+
protected:
TIntermTyped* condition;
TIntermNode* trueBlock;