Commit dd0d3426 by Jamie Madill

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/191930Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Reviewed-by: 's avatarNicolas Capens <nicolascapens@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent d19fae55
...@@ -786,6 +786,26 @@ bool TIntermLoop::replaceChildNode( ...@@ -786,6 +786,26 @@ bool TIntermLoop::replaceChildNode(
return false; 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( bool TIntermBranch::replaceChildNode(
TIntermNode *original, TIntermNode *replacement) TIntermNode *original, TIntermNode *replacement)
{ {
...@@ -793,6 +813,14 @@ bool TIntermBranch::replaceChildNode( ...@@ -793,6 +813,14 @@ bool TIntermBranch::replaceChildNode(
return false; return false;
} }
void TIntermBranch::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
{
if (expression)
{
nodeQueue->push(expression);
}
}
bool TIntermBinary::replaceChildNode( bool TIntermBinary::replaceChildNode(
TIntermNode *original, TIntermNode *replacement) TIntermNode *original, TIntermNode *replacement)
{ {
...@@ -801,6 +829,18 @@ bool TIntermBinary::replaceChildNode( ...@@ -801,6 +829,18 @@ bool TIntermBinary::replaceChildNode(
return false; return false;
} }
void TIntermBinary::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
{
if (left)
{
nodeQueue->push(left);
}
if (right)
{
nodeQueue->push(right);
}
}
bool TIntermUnary::replaceChildNode( bool TIntermUnary::replaceChildNode(
TIntermNode *original, TIntermNode *replacement) TIntermNode *original, TIntermNode *replacement)
{ {
...@@ -808,6 +848,14 @@ bool TIntermUnary::replaceChildNode( ...@@ -808,6 +848,14 @@ bool TIntermUnary::replaceChildNode(
return false; return false;
} }
void TIntermUnary::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
{
if (operand)
{
nodeQueue->push(operand);
}
}
bool TIntermAggregate::replaceChildNode( bool TIntermAggregate::replaceChildNode(
TIntermNode *original, TIntermNode *replacement) TIntermNode *original, TIntermNode *replacement)
{ {
...@@ -818,6 +866,14 @@ bool TIntermAggregate::replaceChildNode( ...@@ -818,6 +866,14 @@ bool TIntermAggregate::replaceChildNode(
return false; 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( bool TIntermSelection::replaceChildNode(
TIntermNode *original, TIntermNode *replacement) TIntermNode *original, TIntermNode *replacement)
{ {
...@@ -827,6 +883,22 @@ bool TIntermSelection::replaceChildNode( ...@@ -827,6 +883,22 @@ bool TIntermSelection::replaceChildNode(
return false; 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. // Say whether or not an operation node changes the value of a variable.
// //
......
...@@ -8,70 +8,22 @@ ...@@ -8,70 +8,22 @@
#include "compiler/translator/RemoveTree.h" #include "compiler/translator/RemoveTree.h"
// //
// Code to recursively delete the intermediate tree. // Code to delete the intermediate tree.
// //
void RemoveAllTreeNodes(TIntermNode* root)
class RemoveTree : public TIntermTraverser
{
public:
RemoveTree() : TIntermTraverser(false, false, true)
{
}
protected:
void visitSymbol(TIntermSymbol*);
void visitConstantUnion(TIntermConstantUnion*);
bool visitBinary(Visit visit, TIntermBinary*);
bool visitUnary(Visit visit, TIntermUnary*);
bool visitSelection(Visit visit, TIntermSelection*);
bool visitAggregate(Visit visit, TIntermAggregate*);
};
void RemoveTree::visitSymbol(TIntermSymbol* node)
{
delete node;
}
bool RemoveTree::visitBinary(Visit visit, TIntermBinary* node)
{
delete node;
return true;
}
bool RemoveTree::visitUnary(Visit visit, TIntermUnary* node)
{
delete node;
return true;
}
bool RemoveTree::visitAggregate(Visit visit, TIntermAggregate* node)
{ {
delete node; std::queue<TIntermNode*> nodeQueue;
return true; nodeQueue.push(root);
}
bool RemoveTree::visitSelection(Visit visit, TIntermSelection* node) while (!nodeQueue.empty())
{ {
delete node; TIntermNode *node = nodeQueue.front();
nodeQueue.pop();
return true; node->enqueueChildren(&nodeQueue);
}
void RemoveTree::visitConstantUnion(TIntermConstantUnion* node)
{
delete node; delete node;
} }
//
// Entry point.
//
void RemoveAllTreeNodes(TIntermNode* root)
{
RemoveTree it;
root->traverse(&it);
} }
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "GLSLANG/ShaderLang.h" #include "GLSLANG/ShaderLang.h"
#include <algorithm> #include <algorithm>
#include <queue>
#include "compiler/translator/Common.h" #include "compiler/translator/Common.h"
#include "compiler/translator/Types.h" #include "compiler/translator/Types.h"
#include "compiler/translator/ConstantUnion.h" #include "compiler/translator/ConstantUnion.h"
...@@ -243,6 +244,10 @@ public: ...@@ -243,6 +244,10 @@ public:
virtual bool replaceChildNode( virtual bool replaceChildNode(
TIntermNode *original, TIntermNode *replacement) = 0; 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: protected:
TSourceLoc line; TSourceLoc line;
}; };
...@@ -328,6 +333,8 @@ public: ...@@ -328,6 +333,8 @@ public:
void setUnrollFlag(bool flag) { unrollFlag = flag; } void setUnrollFlag(bool flag) { unrollFlag = flag; }
bool getUnrollFlag() { return unrollFlag; } bool getUnrollFlag() { return unrollFlag; }
virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
protected: protected:
TLoopType type; TLoopType type;
TIntermNode* init; // for-loop initialization TIntermNode* init; // for-loop initialization
...@@ -354,6 +361,8 @@ public: ...@@ -354,6 +361,8 @@ public:
TOperator getFlowOp() { return flowOp; } TOperator getFlowOp() { return flowOp; }
TIntermTyped* getExpression() { return expression; } TIntermTyped* getExpression() { return expression; }
virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
protected: protected:
TOperator flowOp; TOperator flowOp;
TIntermTyped* expression; // non-zero except for "return exp;" statements TIntermTyped* expression; // non-zero except for "return exp;" statements
...@@ -381,6 +390,8 @@ public: ...@@ -381,6 +390,8 @@ public:
virtual TIntermSymbol* getAsSymbolNode() { return this; } virtual TIntermSymbol* getAsSymbolNode() { return this; }
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
protected: protected:
int id; int id;
TString symbol; TString symbol;
...@@ -405,6 +416,8 @@ public: ...@@ -405,6 +416,8 @@ public:
TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
protected: protected:
ConstantUnion *unionArrayPointer; ConstantUnion *unionArrayPointer;
}; };
...@@ -451,6 +464,8 @@ public: ...@@ -451,6 +464,8 @@ public:
void setAddIndexClamp() { addIndexClamp = true; } void setAddIndexClamp() { addIndexClamp = true; }
bool getAddIndexClamp() { return addIndexClamp; } bool getAddIndexClamp() { return addIndexClamp; }
virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
protected: protected:
TIntermTyped* left; TIntermTyped* left;
TIntermTyped* right; TIntermTyped* right;
...@@ -481,6 +496,8 @@ public: ...@@ -481,6 +496,8 @@ public:
void setUseEmulatedFunction() { useEmulatedFunction = true; } void setUseEmulatedFunction() { useEmulatedFunction = true; }
bool getUseEmulatedFunction() { return useEmulatedFunction; } bool getUseEmulatedFunction() { return useEmulatedFunction; }
virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
protected: protected:
TIntermTyped* operand; TIntermTyped* operand;
...@@ -525,6 +542,8 @@ public: ...@@ -525,6 +542,8 @@ public:
void setUseEmulatedFunction() { useEmulatedFunction = true; } void setUseEmulatedFunction() { useEmulatedFunction = true; }
bool getUseEmulatedFunction() { return useEmulatedFunction; } bool getUseEmulatedFunction() { return useEmulatedFunction; }
virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
protected: protected:
TIntermAggregate(const TIntermAggregate&); // disallow copy constructor TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
...@@ -563,6 +582,8 @@ public: ...@@ -563,6 +582,8 @@ public:
TIntermNode* getFalseBlock() const { return falseBlock; } TIntermNode* getFalseBlock() const { return falseBlock; }
TIntermSelection* getAsSelectionNode() { return this; } TIntermSelection* getAsSelectionNode() { return this; }
virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
protected: protected:
TIntermTyped* condition; TIntermTyped* condition;
TIntermNode* trueBlock; TIntermNode* trueBlock;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment