Handle magic calls to unknown methods in interpreter
[hiphop-php.git] / hphp / runtime / vm / jit / ssa-tmp.cpp
blob9bb89aebb7843bb8f6bc1141848bdfc7ec7f3684
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 +----------------------------------------------------------------------+
17 #include "hphp/runtime/vm/jit/ssa-tmp.h"
19 #include <sstream>
21 #include "hphp/runtime/vm/jit/ir-instruction.h"
22 #include "hphp/runtime/vm/jit/print.h"
23 #include "hphp/util/low-ptr.h"
25 namespace HPHP { namespace jit {
27 SSATmp::SSATmp(uint32_t opndId, IRInstruction* i, int dstId /* = 0 */)
28 : m_id(opndId)
30 setInstruction(i, dstId);
33 void SSATmp::setInstruction(IRInstruction* inst, int dstId) {
34 m_inst = inst;
35 m_type = outputType(inst, dstId);
38 namespace {
39 int typeNeededWords(Type t) {
40 // Although we say we have zero registers, we always allocate 1 in
41 // reg-alloc.cpp. In practice this doesn't mean much.
42 if (t.subtypeOfAny(TUninit,
43 TInitNull,
44 TNullptr)) {
45 // These don't need a register because their values are static or unused.
46 return 0;
48 if (t.maybe(TNullptr)) {
49 return typeNeededWords(t - TNullptr);
51 if (t <= TCtx || t <= TPtrToGen) {
52 // Ctx and PtrTo* may be statically unknown but always need just one
53 // register.
54 return 1;
56 if (t <= TLvalToGen) {
57 // If tv_val<> is ever anything other than 1 or more normal pointers, this
58 // will need to change.
59 static_assert(sizeof(tv_lval) % 8 == 0, "");
60 return sizeof(tv_lval) / 8;
62 if (!t.isUnion()) {
63 // Not a union type and not a special case: 1 register.
64 assertx(IMPLIES(t <= TGen, t.isKnownDataType()));
65 return 1;
68 assertx(t <= TGen);
70 // XXX(t4592459): This will return 2 for TNull, even though it only
71 // needs 1 register (one for the type, none for the value). This is to work
72 // around limitations in codegen; see the task for details. It does mean we
73 // will be loading and storing garbage m_data for Null values but that's fine
74 // since m_data is undefined for Null values.
75 return t.needsReg() ? 2 : 1;
79 int SSATmp::numWords() const {
80 return typeNeededWords(type());
83 Variant SSATmp::variantVal() const {
84 switch (type().toDataType()) {
85 case KindOfUninit:
86 case KindOfNull:
87 // Upon return both will converted to KindOfNull anyway.
88 return init_null();
89 case KindOfBoolean:
90 return boolVal();
91 case KindOfInt64:
92 return intVal();
93 case KindOfDouble:
94 return dblVal();
95 case KindOfPersistentString:
96 return Variant{strVal(), Variant::PersistentStrInit{}};
97 case KindOfPersistentVec:
98 return Variant{vecVal(), KindOfPersistentVec,
99 Variant::PersistentArrInit{}};
100 case KindOfPersistentDict:
101 return Variant{dictVal(), KindOfPersistentDict,
102 Variant::PersistentArrInit{}};
103 case KindOfPersistentKeyset:
104 return Variant{keysetVal(), KindOfPersistentKeyset,
105 Variant::PersistentArrInit{}};
106 case KindOfPersistentShape:
107 return Variant{shapeVal(), KindOfPersistentShape,
108 Variant::PersistentArrInit{}};
109 case KindOfPersistentArray:
110 return Variant{arrVal(), KindOfPersistentArray,
111 Variant::PersistentArrInit{}};
112 case KindOfClass:
113 return Variant{const_cast<Class*>(clsVal())};
114 case KindOfFunc:
115 return Variant{funcVal()};
116 case KindOfClsMeth:
117 if (use_lowptr) return Variant{clsmethVal()};
118 // fallthrough
119 case KindOfString:
120 case KindOfVec:
121 case KindOfDict:
122 case KindOfKeyset:
123 case KindOfShape:
124 case KindOfArray:
125 case KindOfObject:
126 case KindOfResource:
127 case KindOfRef:
128 case KindOfRecord:
129 break;
131 always_assert(false);
134 std::string SSATmp::toString() const {
135 std::ostringstream out;
136 print(out, this);
137 return out.str();