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 #include "hphp/runtime/vm/jit/minstr-effects.h"
18 #include "hphp/runtime/vm/jit/frame-state.h"
20 namespace HPHP
{ namespace jit
{
24 //////////////////////////////////////////////////////////////////////
26 template<typename T
> T
bad_value() { not_reached(); }
28 Opcode
canonicalOp(Opcode op
) {
29 if (op
== ElemUX
|| op
== UnsetElem
) return UnsetElem
;
30 if (op
== SetRange
|| op
== SetRangeRev
) return SetRange
;
32 return opcodeHasFlags(op
, MInstrProp
) ? SetProp
33 : opcodeHasFlags(op
, MInstrElem
) ? SetElem
34 : bad_value
<Opcode
>();
37 void getBaseType(Opcode rawOp
, bool predict
,
38 Type
& baseType
, bool& baseValChanged
) {
39 always_assert(baseType
<= TCell
);
40 auto const op
= canonicalOp(rawOp
);
42 if ((op
== SetElem
|| op
== SetProp
) &&
43 baseType
.maybe(TNull
| TBool
| TStr
)) {
44 if (predict
&& baseType
.maybe(TStr
)) {
45 /* If the output type will be used as a prediction and not as fact, we
46 * can be optimistic here. Assume no promotion for string bases and
47 * an exception otherwise */
49 } else if (baseType
<= TStr
&& rawOp
== SetNewElem
) {
50 /* new-elem to string will always raise, empty or not */
52 } else if (baseType
.maybe(TNull
| TBool
)) {
53 /* we used to promote falsey things to array or an instance of stdClass,
54 * now these always raise, except a base of `true` gets coerced to null */
58 if (baseType
!= TBottom
) baseValChanged
= true;
61 if ((op
== SetElem
|| op
== SetRange
|| op
== UnsetElem
) &&
62 baseType
.maybe(TArrLike
| TStr
| TRecord
| TClsMeth
)) {
63 /* Member operations never cause us to lose the vanilla bit. */
64 auto const vanilla
= baseType
.arrSpec().vanilla();
66 /* Modifying an array or string element, even when COW doesn't kick in,
67 * produces a new SSATmp for the base. StaticArr/StaticStr may be promoted
68 * to CountedArr/CountedStr. */
69 baseValChanged
= true;
71 if (baseType
.maybe(TVArr
)) baseType
|= TCountedVArr
;
72 if (baseType
.maybe(TDArr
)) baseType
|= TCountedDArr
;
73 if (baseType
.maybe(TVec
)) baseType
|= TCountedVec
;
74 if (baseType
.maybe(TDict
)) baseType
|= TCountedDict
;
75 if (baseType
.maybe(TKeyset
)) baseType
|= TCountedKeyset
;
76 if (baseType
.maybe(TStr
)) baseType
|= TCountedStr
;
77 if (baseType
.maybe(TClsMeth
)) {
78 baseType
|= RO::EvalHackArrDVArrs
? TCountedVec
: TCountedVArr
;
80 if (vanilla
) baseType
= baseType
.narrowToVanilla();
84 //////////////////////////////////////////////////////////////////////
88 // minstrBaseIdx returns the src index for inst's base operand.
89 int minstrBaseIdx(Opcode opc
) {
90 return opcodeHasFlags(opc
, MInstrProp
) ? 0 :
91 opcodeHasFlags(opc
, MInstrElem
) ? 0 :
95 bool MInstrEffects::supported(Opcode op
) {
96 return opcodeHasFlags(op
, MInstrProp
| MInstrElem
);
98 bool MInstrEffects::supported(const IRInstruction
* inst
) {
99 return supported(inst
->op());
102 MInstrEffects::MInstrEffects(const Opcode rawOp
, const Type origBase
) {
103 // Note: MInstrEffects wants to manipulate pointer types in some situations
104 // for historical reasons. We'll eventually change that.
105 bool const is_ptr
= origBase
<= TLvalToCell
;
106 auto const basePtr
= is_ptr
? origBase
.ptrKind() : Ptr::Bottom
;
107 baseType
= origBase
.derefIfPtr();
109 baseTypeChanged
= baseValChanged
= false;
111 getBaseType(rawOp
, false, baseType
, baseValChanged
);
113 baseType
= is_ptr
? baseType
.lval(basePtr
) : baseType
;
114 baseTypeChanged
= baseType
!= origBase
;
115 baseValChanged
= baseValChanged
|| (baseTypeChanged
&& baseType
!= TBottom
);
118 //////////////////////////////////////////////////////////////////////