1 // escape.h -- Go escape analysis (based on Go compiler algorithm).
3 // Copyright 2016 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
17 // There can be loops in the escape graph that lead to arbitrary recursions.
18 // See comment in gc/esc.go.
19 static const int MIN_LEVEL
= -2;
21 // Level models the escapement of a Node using two integers that are computed
22 // by backwards-analyzing the flow of a function from its sink and increasing or
23 // decreasing based on dereferences and addressing, respectively.
24 // One integer, known as the level's VALUE (think absolute value), is just the
25 // sum of indirections (via referencing or dereferencing) applied to the Node.
26 // The second, known as the level's SUFFIX_VALUE, is the amount of indirections
27 // applied after some data has been copied from the node. When accessing a
28 // field F of an object O and then applying indirections, for example, the field
29 // access O.F is assumed to copy that data from O before applying indirections.
30 // With this, even if O.F escapes, it might mean that the content of O escape,
31 // but not the object O itself.
37 : value_(0), suffix_value_(0)
40 Level(int value
, int suffix
)
41 : value_(value
), suffix_value_(suffix
)
44 // Return this level's value.
47 { return this->value_
; }
49 // Return this level's suffix value.
52 { return this->suffix_value_
; }
54 // Increase the level because a node is dereferenced.
58 if (this->value_
<= MIN_LEVEL
)
59 return Level(MIN_LEVEL
, 0);
61 return Level(this->value_
+ 1, this->suffix_value_
+ 1);
64 // Decrease the level because a node is referenced.
68 if (this->value_
<= MIN_LEVEL
)
69 return Level(MIN_LEVEL
, 0);
71 return Level(this->value_
- 1, this->suffix_value_
- 1);
74 // Model a node being copied.
78 return Level(this->value_
, std::max(this->suffix_value_
, 0));
81 // Return a level with the minimum values of this level and l.
83 min(const Level
& l
) const
85 return Level(std::min(this->value_
, l
.value()),
86 std::min(this->suffix_value_
, l
.suffix_value()));
89 // Compare two levels for equality.
91 operator==(const Level
& l
) const
93 return (this->value_
== l
.value()
94 && this->suffix_value_
== l
.suffix_value());
97 // Create a level from an integer value.
102 return Level(MIN_LEVEL
, 0);
107 // The sum of all references (-1) and indirects (+1) applied to a Node.
109 // The sum of all references (-1) abd indirects (+1) applied to a copied Node.
113 // A node in the escape graph. This node is an alias to a particular node
114 // in the Go parse tree. Specifically, it can represent an expression node,
115 // a statement node, or a named object node (a variable or function).
120 // This classification represents type of nodes in the Go parse tree that are
121 // interesting during the analysis.
122 enum Node_classification
127 // A "fake" node that models the indirection of its child node.
128 // This node does not correspond to an AST node.
132 // The state necessary to keep track of how a node escapes.
135 // The current function.
137 // A list of source nodes that flow into this node.
138 std::set
<Node
*> flows
;
139 // If the node is a function call, the list of nodes returned.
140 std::vector
<Node
*> retvals
;
141 // The node's loop depth.
143 // There is an extra loop depth in the flood phase used to account for
144 // variables referenced across closures. This is the maximum value of the
145 // extra loop depth seen during the flood that touches this node.
146 int max_extra_loop_depth
;
149 // An ID given to a node when it is encountered as a flow from the current
150 // dst node. This is used to avoid infinite recursion of cyclic nodes.
154 : fn(NULL
), loop_depth(0), max_extra_loop_depth(0), flood_id(0)
158 // Note: values in this enum appear in export data, and therefore MUST NOT
160 enum Escapement_encoding
163 // Does not escape to heap, result, or parameters.
165 // Is returned or reachable from a return statement.
167 // Reachable from the heap.
169 // By construction will not escape.
173 // Multiple constructors for each classification.
174 Node(Named_object
* no
)
175 : classification_(NODE_OBJECT
), state_(NULL
), encoding_(ESCAPE_UNKNOWN
),
177 { this->u_
.object_val
= no
; }
180 : classification_(NODE_EXPRESSION
), state_(NULL
), encoding_(ESCAPE_UNKNOWN
),
182 { this->u_
.expression_val
= e
; }
185 : classification_(NODE_STATEMENT
), state_(NULL
), encoding_(ESCAPE_UNKNOWN
),
187 { this->u_
.statement_val
= s
; }
190 : classification_(NODE_INDIRECT
), state_(NULL
), encoding_(ESCAPE_UNKNOWN
),
196 // Return this node's type.
200 // Return this node's location.
204 // Return the location where the node's underlying object is defined.
206 definition_location() const;
208 // Return this node's AST formatted string.
210 ast_format(Gogo
*) const;
212 // Return this node's detailed format string.
219 // Return this node's escape state.
221 state(Escape_context
* context
, Named_object
* fn
);
223 // Return this node's escape encoding.
227 // Set the node's escape encoding.
229 set_encoding(int enc
);
232 is_big(Escape_context
*) const;
237 // Methods to return the underlying value in the Node union.
241 return (this->classification_
== NODE_OBJECT
242 ? this->u_
.object_val
249 return (this->classification_
== NODE_EXPRESSION
250 ? this->u_
.expression_val
257 return (this->classification_
== NODE_STATEMENT
258 ? this->u_
.statement_val
264 { return this->classification_
== NODE_INDIRECT
; }
266 // Return its child node.
267 // Child node is used only in indirect node, and in expression node
268 // representing slicing an array.
271 { return this->child_
; }
273 // Set the child node.
276 { this->child_
= n
; }
278 // Static creation methods for each value supported in the union.
280 make_node(Named_object
*);
283 make_node(Expression
*);
286 make_node(Statement
*);
289 make_indirect_node(Node
*);
291 // Return the maximum of an existing escape encoding E and a new
294 max_encoding(int e
, int etype
);
296 // Return a modified encoding for an input parameter that flows into an
299 note_inout_flows(int e
, int index
, Level level
);
306 // The classification of this Node.
307 Node_classification classification_
;
312 Named_object
* object_val
;
313 // If NODE_EXPRESSION.
314 Expression
* expression_val
;
315 // If NODE_STATEMENT.
316 Statement
* statement_val
;
318 // The node's escape state.
319 Escape_state
* state_
;
320 // The node's escape encoding.
322 // | Return Encoding: (width - ESCAPE_RETURN_BITS) |
323 // | Content Escapes bit: 1 |
324 // | Escapement_encoding: ESCAPE_BITS |
327 // Child node, used only in indirect node, and expression node representing
331 // Cache all the Nodes created via Node::make_node to make the API simpler.
332 static Unordered_map(Named_object
*, Node
*) objects
;
333 static Unordered_map(Expression
*, Node
*) expressions
;
334 static Unordered_map(Statement
*, Node
*) statements
;
336 // Collection of all NODE_INDIRECT Nodes, used for reclaiming memory. This
337 // is not a cache -- each make_indirect_node will make a fresh Node.
338 static std::vector
<Node
*> indirects
;
341 // The amount of bits used for the escapement encoding.
342 static const int ESCAPE_BITS
= 3;
344 // Mask used to extract encoding.
345 static const int ESCAPE_MASK
= (1 << ESCAPE_BITS
) - 1;
347 // Value obtained by indirect of parameter escapes to heap.
348 static const int ESCAPE_CONTENT_ESCAPES
= 1 << ESCAPE_BITS
;
350 // The amount of bits used in encoding of return values.
351 static const int ESCAPE_RETURN_BITS
= ESCAPE_BITS
+ 1;
353 // For each output, the number of bits for a tag.
354 static const int ESCAPE_BITS_PER_OUTPUT_IN_TAG
= 3;
356 // The bit max to extract a single tag.
357 static const int ESCAPE_BITS_MASK_FOR_TAG
= (1 << ESCAPE_BITS_PER_OUTPUT_IN_TAG
) - 1;
359 // The largest level that can be stored in a tag.
360 static const int ESCAPE_MAX_ENCODED_LEVEL
= ESCAPE_BITS_MASK_FOR_TAG
- 1;
362 // A helper for converting escape notes from encoded integers to a
363 // textual format and vice-versa.
368 // Return the string representation of an escapement encoding.
370 make_tag(int encoding
);
372 // Return the escapement encoding for a string tag.
374 parse_tag(std::string
* tag
);
377 // The escape context for a set of functions being analyzed.
382 Escape_context(Gogo
* gogo
, bool recursive
);
387 { return this->gogo_
; }
389 // Return the current function being analyzed.
391 current_function() const
392 { return this->current_function_
; }
394 // Change the function being analyzed.
396 set_current_function(Named_object
* fn
)
397 { this->current_function_
= fn
; }
399 // Return the name of the current function.
401 current_function_name() const;
403 // Return true if this is the context for a mutually recursive set of functions.
406 { return this->recursive_
; }
408 // Return the special sink node for this context.
411 { return this->sink_
; }
413 // Return the current loop depth.
416 { return this->loop_depth_
; }
418 // Increase the loop depth.
420 increase_loop_depth()
421 { this->loop_depth_
++; }
423 // Decrease the loop depth.
425 decrease_loop_depth()
426 { this->loop_depth_
--; }
429 set_loop_depth(int depth
)
430 { this->loop_depth_
= depth
; }
432 // Return the destination nodes encountered in this context.
433 const std::set
<Node
*>&
435 { return this->dsts_
; }
437 // Add a destination node.
440 { this->dsts_
.insert(dst
); }
442 // Return the nodes initially marked as non-escaping before flooding.
443 const std::vector
<Node
*>&
444 non_escaping_nodes() const
445 { return this->noesc_
; }
447 // Initialize the dummy return values for this Node N using the results
450 init_retvals(Node
* n
, Function_type
* fntype
);
452 // Return the indirection of Node N.
454 add_dereference(Node
* n
);
456 // Keep track of possibly non-escaping node N.
462 { return this->flood_id_
; }
466 { this->flood_id_
++; }
470 { return this->pdepth_
; }
483 // The current function being analyzed.
484 Named_object
* current_function_
;
485 // Return whether this is the context for a recursive function or a group of mutually
486 // recursive functions.
488 // The sink for this escape context. Nodes whose reference objects created
489 // outside the current function are assigned to the sink as well as nodes that
490 // the analysis loses track of.
492 // Used to detect nested loop scopes.
494 // All the destination nodes considered in this set of analyzed functions.
495 std::set
<Node
*> dsts_
;
496 // All the nodes that were noted as possibly not escaping in this context.
497 std::vector
<Node
*> noesc_
;
498 // An ID given to each dst and the flows discovered through DFS of that dst.
499 // This is used to avoid infinite recursion from nodes that point to each
500 // other within the flooding phase.
502 // The current level of recursion within a flooded section; used to debug.
506 #endif // !defined(GO_ESCAPE_H)