Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 //
2 // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
7 #ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
8 #define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
10 #include "compiler/depgraph/DependencyGraph.h"
12 //
13 // Creates a dependency graph of symbols, function calls, conditions etc. by traversing a
14 // intermediate tree.
15 //
16 class TDependencyGraphBuilder : public TIntermTraverser {
17 public:
18 static void build(TIntermNode* node, TDependencyGraph* graph);
20 virtual void visitSymbol(TIntermSymbol*);
21 virtual bool visitBinary(Visit visit, TIntermBinary*);
22 virtual bool visitSelection(Visit visit, TIntermSelection*);
23 virtual bool visitAggregate(Visit visit, TIntermAggregate*);
24 virtual bool visitLoop(Visit visit, TIntermLoop*);
26 private:
27 typedef std::stack<TGraphSymbol*> TSymbolStack;
28 typedef std::set<TGraphParentNode*> TParentNodeSet;
30 //
31 // For collecting the dependent nodes of assignments, conditions, etc.
32 // while traversing the intermediate tree.
33 //
34 // This data structure is stack of sets. Each set contains dependency graph parent nodes.
35 //
36 class TNodeSetStack {
37 public:
38 TNodeSetStack() {};
39 ~TNodeSetStack() { clear(); }
41 // This should only be called after a pushSet.
42 // Returns NULL if the top set is empty.
43 TParentNodeSet* getTopSet() const
44 {
45 ASSERT(!nodeSets.empty());
46 TParentNodeSet* topSet = nodeSets.top();
47 return !topSet->empty() ? topSet : NULL;
48 }
50 void pushSet() { nodeSets.push(new TParentNodeSet()); }
51 void popSet()
52 {
53 ASSERT(!nodeSets.empty());
54 delete nodeSets.top();
55 nodeSets.pop();
56 }
58 // Pops the top set and adds its contents to the new top set.
59 // This should only be called after a pushSet.
60 // If there is no set below the top set, the top set is just deleted.
61 void popSetIntoNext()
62 {
63 ASSERT(!nodeSets.empty());
64 TParentNodeSet* oldTopSet = nodeSets.top();
65 nodeSets.pop();
67 if (!nodeSets.empty()) {
68 TParentNodeSet* newTopSet = nodeSets.top();
69 newTopSet->insert(oldTopSet->begin(), oldTopSet->end());
70 }
72 delete oldTopSet;
73 }
75 // Does nothing if there is no top set.
76 // This can be called when there is no top set if we are visiting
77 // symbols that are not under an assignment or condition.
78 // We don't need to track those symbols.
79 void insertIntoTopSet(TGraphParentNode* node)
80 {
81 if (nodeSets.empty())
82 return;
84 nodeSets.top()->insert(node);
85 }
87 void clear()
88 {
89 while (!nodeSets.empty())
90 popSet();
91 }
93 private:
94 typedef std::stack<TParentNodeSet*> TParentNodeSetStack;
96 TParentNodeSetStack nodeSets;
97 };
99 //
100 // An instance of this class pushes a new node set when instantiated.
101 // When the instance goes out of scope, it and pops the node set.
102 //
103 class TNodeSetMaintainer {
104 public:
105 TNodeSetMaintainer(TDependencyGraphBuilder* factory)
106 : sets(factory->mNodeSets) { sets.pushSet(); }
107 ~TNodeSetMaintainer() { sets.popSet(); }
108 protected:
109 TNodeSetStack& sets;
110 };
112 //
113 // An instance of this class pushes a new node set when instantiated.
114 // When the instance goes out of scope, it and pops the top node set and adds its contents to
115 // the new top node set.
116 //
117 class TNodeSetPropagatingMaintainer {
118 public:
119 TNodeSetPropagatingMaintainer(TDependencyGraphBuilder* factory)
120 : sets(factory->mNodeSets) { sets.pushSet(); }
121 ~TNodeSetPropagatingMaintainer() { sets.popSetIntoNext(); }
122 protected:
123 TNodeSetStack& sets;
124 };
126 //
127 // An instance of this class keeps track of the leftmost symbol while we're exploring an
128 // assignment.
129 // It will push the placeholder symbol kLeftSubtree when instantiated under a left subtree,
130 // and kRightSubtree under a right subtree.
131 // When it goes out of scope, it will pop the leftmost symbol at the top of the scope.
132 // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with a real symbol.
133 // kRightSubtree will never be replaced by a real symbol because we are tracking the leftmost
134 // symbol.
135 //
136 class TLeftmostSymbolMaintainer {
137 public:
138 TLeftmostSymbolMaintainer(TDependencyGraphBuilder* factory, TGraphSymbol& subtree)
139 : leftmostSymbols(factory->mLeftmostSymbols)
140 {
141 needsPlaceholderSymbol = leftmostSymbols.empty() || leftmostSymbols.top() != &subtree;
142 if (needsPlaceholderSymbol)
143 leftmostSymbols.push(&subtree);
144 }
146 ~TLeftmostSymbolMaintainer()
147 {
148 if (needsPlaceholderSymbol)
149 leftmostSymbols.pop();
150 }
152 protected:
153 TSymbolStack& leftmostSymbols;
154 bool needsPlaceholderSymbol;
155 };
157 TDependencyGraphBuilder(TDependencyGraph* graph)
158 : TIntermTraverser(true, false, false)
159 , mLeftSubtree(NULL)
160 , mRightSubtree(NULL)
161 , mGraph(graph) {}
162 void build(TIntermNode* intermNode) { intermNode->traverse(this); }
164 void connectMultipleNodesToSingleNode(TParentNodeSet* nodes, TGraphNode* node) const;
166 void visitAssignment(TIntermBinary*);
167 void visitLogicalOp(TIntermBinary*);
168 void visitBinaryChildren(TIntermBinary*);
169 void visitFunctionDefinition(TIntermAggregate*);
170 void visitFunctionCall(TIntermAggregate* intermFunctionCall);
171 void visitAggregateChildren(TIntermAggregate*);
173 TGraphSymbol mLeftSubtree;
174 TGraphSymbol mRightSubtree;
176 TDependencyGraph* mGraph;
177 TNodeSetStack mNodeSets;
178 TSymbolStack mLeftmostSymbols;
179 };
181 #endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H