Remove SpillFrame, merge its memory effects into CallEffects and InlineEnterEffects
[hiphop-php.git] / hphp / runtime / vm / jit / memory-effects.h
blobe705b151f4754d66a46e27045aab898eed850a2e
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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_
19 #include <string>
21 #include <folly/Optional.h>
23 #include <boost/variant.hpp>
25 #include "hphp/runtime/vm/jit/alias-class.h"
27 namespace HPHP { namespace jit {
29 struct SSATmp;
30 struct IRInstruction;
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
37 * side-effects.
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
54 * GenericRetDecRefs.
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
63 * small).
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;
78 AliasClass stores;
79 AliasClass moves;
80 AliasClass kills; };
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
86 * be in the location.
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
100 * happen in loops).
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
116 * variables to.
118 * The `locals` set contains frame locations that the call might read.
120 * Note that calls that have been weakened to CallBuiltin use GeneralEffects,
121 * not CallEffects.
123 struct CallEffects { AliasClass kills;
124 AliasClass inputs;
125 AliasClass actrec;
126 AliasClass outputs;
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
143 * stack.
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
160 * frame.
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;
167 AliasClass inlFrame;
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;
178 AliasClass inlFrame;
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
195 , PureLoad
196 , PureStore
197 , CallEffects
198 , ReturnEffects
199 , ExitEffects
200 , InlineEnterEffects
201 , InlineExitEffects
202 , IrrelevantEffects
203 , UnknownEffects
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
217 * analysis.h)
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 //////////////////////////////////////////////////////////////////////
236 #endif