Bring minstr-effects up to date
[hiphop-php.git] / hphp / runtime / vm / jit / minstr-effects.cpp
bloba4342fbc4fd6cd34193979ee1fa1277ed56d37ab
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 #include "hphp/runtime/vm/jit/minstr-effects.h"
18 #include "hphp/runtime/vm/jit/frame-state.h"
20 namespace HPHP { namespace jit {
22 namespace {
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 */
48 baseType = TStr;
49 } else if (baseType <= TStr && rawOp == SetNewElem) {
50 /* new-elem to string will always raise, empty or not */
51 baseType = TBottom;
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 */
55 baseType -= TNull;
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 :
92 bad_value<int>();
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 //////////////////////////////////////////////////////////////////////