2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #ifndef incl_HPHP_MEMORY_EFFECTS_H_
17 #define incl_HPHP_MEMORY_EFFECTS_H_
21 #include <folly/Optional.h>
23 #include <boost/variant.hpp>
25 #include "hphp/runtime/vm/jit/alias-class.h"
27 namespace HPHP
{ namespace jit
{
32 //////////////////////////////////////////////////////////////////////
35 * General effect information used by most IR instructions. The instruction
36 * may load or store to different alias classes, as well as have any other
39 * Locations that contain PHP values are assumed (except for `moves', see
40 * below) to be affected with normal VM semantics with regard to memory
41 * barriers---that is, if the instruction loads from a `loads' location and
42 * keeps a pointer to the value, it must IncRef it, and if the instruction
43 * stores to a `stores' location, it must decref the old value that was in
44 * memory (if there could be any) and incref the one it is storing. The reason
45 * to make this expectation clear is for the use of this module by refcount
46 * optimizations. Note that this means that instructions which do nothing but
47 * store a php value to a location (without decreffing the old value that may
48 * have been there) cannot use GeneralEffects to represent that (they must use
49 * PureStore)---the same thing does not /quite/ apply to loads.
51 * Furthermore, all locations that contain values the instruction may decref
52 * should be included in `stores', even if (as an "optimization") we don't need
53 * to store anything over it. This requirement basically only applies to
56 * The exception to the "normal VM semantics" is for values in the class
57 * `moves', which must always be a subclass of `loads'. This set of locations
58 * may be loaded by the instruction, but in order to `transfer' them to another
59 * memory location (which must be somewhere in its `stores' set), without an
60 * IncRef. Note: this set is also may-information---and it is required to
61 * contain any location this instruction may do this to for correct analysis in
62 * refcount optimizations (it must be conservatively "too big" rather than too
65 * Additionally, there is a set `kills'. For this set of locations, when the
66 * instruction executes (before any of its other effects), it becomes
67 * semantically illegal for any part of the program to read from those
68 * locations again (without writing to them first). This is used for the
69 * ReturnHook to prevent uses of the stack and frame, and for killing stack
70 * slots below the re-entry depth for potentially re-entering instructions.
72 * If there is an overlap between `loads' and `kills', then `kills' takes
73 * precedence for locations that are contained in both (i.e. those locations
74 * should be treated as actually killed).
77 struct GeneralEffects
{ AliasClass loads
;
83 * The effect of definitely loading from an abstract location, without
84 * performing any other work. Instructions with these memory effects can be
85 * removed and replaced with a Mov if we have a value available that's known to
88 struct PureLoad
{ AliasClass src
; };
91 * The effect of definitely storing `value' to a location, without performing
92 * any other work. Instructions with these memory effects can be removed if we
93 * know the value being stored does not change the value of the location, or if
94 * we know the location can never be loaded from again. `value' can be a
95 * nullptr, in which case the store can still be elided if it is known to never
96 * be loaded afterwards.
98 * dep is a "base" address that the store is relative to. This is used
99 * so we can mark stores altered across its definition (which can only
102 struct PureStore
{ AliasClass dst
; SSATmp
* value
; SSATmp
* dep
; };
105 * Calls are somewhat special enough that they get a top-level effect.
107 * The `kills' set are locations that cannot be read by this instruction unless
108 * it writes to them first, and which it generally may write to. (This is used
109 * for killing stack slots below the call depth and MInstrState locations)
111 * The `inputs' set contains stack locations the call will read as arguments.
113 * The `actrec' set contains stack locations the call will write ActRec to.
115 * The `outputs' set contains stack locations the call will write inout
118 * The `locals` set contains frame locations that the call might read.
120 * Note that calls that have been weakened to CallBuiltin use GeneralEffects,
123 struct CallEffects
{ AliasClass kills
;
127 AliasClass locals
; };
130 * ReturnEffects is a return, either from the php function or an inlined
131 * function. You may assume if the instruction it came from is not an
132 * InlineReturn, it is a return from the entire region. It does not cover
133 * suspending a resumable, but it covers returning from a suspended resumable.
135 * All locals on the returning frame may be considered dead after
136 * ReturnEffects. However, the stack is a little more complicated. The
137 * `kills' set is an additional alias class of locations that cannot be read
138 * after the return, which is used to provide the range of stack that can be
139 * considered dead. In normal functions it will effectively be AStackAny, but
140 * in generators a return may still leave part of the eval stack alive for the
141 * caller. When returning from an inlined function, the locals may all be
142 * considered dead, and `kills' will contain the whole inlined function's
145 struct ReturnEffects
{ AliasClass kills
; };
148 * ExitEffects contains two sets of alias classes, representing locations that
149 * are considered live exiting the region, and locations that will never be
150 * read (unless written again) after exiting the region (`kills'). Various
151 * instructions that exit regions populate these in different ways.
153 struct ExitEffects
{ AliasClass live
; AliasClass kills
; };
156 * InlineEnterEffects indicate that an update to the vmfp for an inlined frame.
157 * In effect the instruction represents a move of inlStack locations to inlFrame
158 * locations. In actuality these alias locations occupy the same memory on the
159 * VM stack. Additionally the rbp chain is updated with actrec becoming the live
162 * Stores to frame locations on the caller frame cannot be propagated passed
163 * an InlineEnterEffects unless they are moved after the corresponding
164 * InlineExitEffects instruction.
166 struct InlineEnterEffects
{ AliasClass inlStack
;
168 AliasClass actrec
; };
171 * InlineExitEffects denotes the update of the vmfp for a return from an inlined
172 * frame. Logically it kills the inlStack, inlFrame, and inlMeta locations. In
173 * addition, following this instruction it is incorrect to propgate writes to
174 * inlFrame and inlMeta as they represent locations no longer accessible due to
175 * the reserved nature fo the frame pointer.
177 struct InlineExitEffects
{ AliasClass inlStack
;
179 AliasClass inlMeta
; };
182 * "Irrelevant" effects means it doesn't do anything we currently care about
183 * for consumers of this module. If you want to care about a new kind of
184 * memory effect, you get to re-audit everything---have fun. :)
186 struct IrrelevantEffects
{};
189 * Instruction hasn't been audited for effects that we care about. Users of
190 * this module should do the most pessimistic thing possible.
192 struct UnknownEffects
{};
194 using MemEffects
= boost::variant
< GeneralEffects
206 //////////////////////////////////////////////////////////////////////
209 * Return information about the kinds of memory effects an instruction may
210 * have. See the above branches of MemEffects for more information.
212 MemEffects
memory_effects(const IRInstruction
&);
215 * Replace any abstract locations in a MemEffects structure with their
216 * canonical name (chasing passthrough instructions like canonical() from
219 MemEffects
canonicalize(MemEffects
);
222 * Return an alias class representing the pointee of the given value, which
223 * must be <= TMemToGen.
225 AliasClass
pointee(const SSATmp
*);
228 * Produces a string about some MemEffects for debug-printing.
230 std::string
show(MemEffects
);
232 //////////////////////////////////////////////////////////////////////