2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2016 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/extra-data.h"
19 #include "hphp/runtime/vm/jit/ssa-tmp.h"
20 #include "hphp/runtime/vm/jit/abi-x64.h"
21 #include "hphp/util/text-util.h"
23 namespace HPHP
{ namespace jit
{
25 std::string
NewStructData::show() const {
26 std::ostringstream os
;
27 os
<< offset
.offset
<< ',';
29 for (uint32_t i
= 0; i
< numKeys
; i
++) {
30 os
<< delim
<< "\"" <<
31 escapeStringForCPP(keys
[i
]->data(), keys
[i
]->size()) <<
38 //////////////////////////////////////////////////////////////////////
42 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_hash
, hash
);
43 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_equals
, equals
);
44 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_clone
, clone
);
45 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_show
, show
);
48 * dispatchExtra translates from runtime values for the Opcode enum
49 * into compile time types. The goal is to call a `targetFunction'
50 * that is overloaded on the extra data type structs.
52 * The purpose of the MAKE_DISPATCHER layer is to weed out Opcode
53 * values that have no associated extra data.
55 * Basically this is doing dynamic dispatch without a vtable in
56 * IRExtraData, instead using the Opcode tag from the associated
57 * instruction to discriminate the runtime type.
59 * Note: functions made with this currently only make sense to call if
60 * it's already known that the opcode has extra data. If you call it
61 * for one that doesn't, you'll get an abort. Generally hasExtra()
62 * should be checked first.
65 #define MAKE_DISPATCHER(name, rettype, targetFunction) \
66 template<bool HasExtra, Opcode opc> struct name { \
67 template<class... Args> \
68 static rettype go(IRExtraData* vp, Args&&...) { not_reached(); } \
70 template<Opcode opc> struct name<true,opc> { \
71 template<class... Args> \
72 static rettype go(IRExtraData* vp, Args&&... args) { \
73 return targetFunction( \
74 static_cast<typename IRExtraDataType<opc>::type*>(vp), \
75 std::forward<Args>(args)... \
82 template<bool, Opcode
> class Dispatcher
,
85 RetType
dispatchExtra(Opcode opc
, IRExtraData
* data
, Args
&&... args
) {
86 #define O(opcode, dstinfo, srcinfo, flags) \
89 OpHasExtraData<opcode>::value, \
91 >::go(data, std::forward<Args>(args)...);
92 switch (opc
) { IR_OPCODES
default: not_reached(); }
98 typename
std::enable_if
<
99 has_hash
<T
,size_t () const>::value
,
101 >::type
hashExtraImpl(T
* t
) { return t
->hash(); }
102 size_t hashExtraImpl(IRExtraData
*) {
103 // This probably means we tried to hash an IRInstruction with extra data that
104 // had no hash function.
105 always_assert(!"attempted to hash extra data that didn't "
106 "provide a hash function");
110 typename
std::enable_if
<
111 has_equals
<T
,bool (T
const&) const>::value
||
112 has_equals
<T
,bool (T
) const>::value
,
114 >::type
equalsExtraImpl(T
* t
, IRExtraData
* o
) {
115 return t
->equals(*static_cast<T
*>(o
));
117 bool equalsExtraImpl(IRExtraData
*, IRExtraData
*) {
118 // This probably means we tried to compare IRInstructions with extra data that
119 // had no equals function.
120 always_assert(!"attempted to compare extra data that didn't "
121 "provide an equals function");
124 // Clone using a data-specific clone function.
126 typename
std::enable_if
<
127 has_clone
<T
,T
* (Arena
&) const>::value
,
129 >::type
cloneExtraImpl(T
* t
, Arena
& arena
) {
130 return t
->clone(arena
);
133 // Use the copy constructor if no clone() function was supplied.
135 typename
std::enable_if
<
136 !has_clone
<T
,T
* (Arena
&) const>::value
,
138 >::type
cloneExtraImpl(T
* t
, Arena
& arena
) {
139 return new (arena
) T(*t
);
143 std::string
showExtraImpl(const T
* extra
) { return extra
->show(); }
145 MAKE_DISPATCHER(HashDispatcher
, size_t, hashExtraImpl
);
146 MAKE_DISPATCHER(EqualsDispatcher
, bool, equalsExtraImpl
);
147 MAKE_DISPATCHER(CloneDispatcher
, IRExtraData
*, cloneExtraImpl
);
148 MAKE_DISPATCHER(ShowDispatcher
, std::string
, showExtraImpl
);
152 //////////////////////////////////////////////////////////////////////
154 size_t hashExtra(Opcode opc
, const IRExtraData
* data
) {
155 return dispatchExtra
<size_t,HashDispatcher
>(
156 opc
, const_cast<IRExtraData
*>(data
));
161 const IRExtraData
* data
,
162 const IRExtraData
* other
164 return dispatchExtra
<bool,EqualsDispatcher
>(
165 opc
, const_cast<IRExtraData
*>(data
), const_cast<IRExtraData
*>(other
));
168 IRExtraData
* cloneExtra(Opcode opc
, IRExtraData
* data
, Arena
& a
) {
169 return dispatchExtra
<IRExtraData
*,CloneDispatcher
>(opc
, data
, a
);
172 std::string
showExtra(Opcode opc
, const IRExtraData
* data
) {
173 return dispatchExtra
<std::string
,ShowDispatcher
>(
174 opc
, const_cast<IRExtraData
*>(data
)
178 //////////////////////////////////////////////////////////////////////