2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 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 #ifndef incl_HPHP_RUNTIME_VM_TRANSLATOR_HOPT_VECTOR_TRANSLATOR_HELPERS_H_
18 #define incl_HPHP_RUNTIME_VM_TRANSLATOR_HOPT_VECTOR_TRANSLATOR_HELPERS_H_
20 #include "hphp/util/base.h"
21 #include "hphp/runtime/base/types.h"
22 #include "hphp/runtime/base/stats.h"
23 #include "hphp/runtime/vm/jit/translator.h"
24 #include "hphp/runtime/vm/member_operations.h"
26 namespace HPHP
{ namespace JIT
{
28 #define CTX() cns(contextClass())
30 static const MInstrAttr Warn
= MIA_warn
;
31 static const MInstrAttr Unset
= MIA_unset
;
32 static const MInstrAttr Reffy
= MIA_reffy
;
33 static const MInstrAttr Define
= MIA_define
;
34 static const MInstrAttr None
= MIA_none
;
35 static const MInstrAttr WarnDefine
= MInstrAttr(Warn
| Define
);
36 static const MInstrAttr DefineReffy
= MInstrAttr(Define
| Reffy
);
37 static const MInstrAttr WarnDefineReffy
= MInstrAttr(Warn
| Define
| Reffy
);
38 #define WDU(attrs) (attrs & Warn) != 0, (attrs & Define) != 0, \
40 #define WDRU(attrs) (attrs & Warn) != 0, (attrs & Define) != 0, \
41 (attrs & Reffy) != 0, (attrs & Unset) != 0
43 /* The following bunch of macros and functions are used to build up tables of
44 * helper function pointers and determine which helper should be called based
45 * on a variable number of bool and enum arguments. */
47 template<typename T
> constexpr unsigned bitWidth() {
48 static_assert(IncDec_invalid
== 4,
49 "IncDecOp enum must fit in 2 bits");
50 static_assert(SetOp_invalid
== 11,
51 "SetOpOp enum must fit in 4 bits");
52 return std::is_same
<T
, bool>::value
? 1
53 : std::is_same
<T
, KeyType
>::value
? 2
54 : std::is_same
<T
, MInstrAttr
>::value
? 4
55 : std::is_same
<T
, IncDecOp
>::value
? 2
56 : std::is_same
<T
, SetOpOp
>::value
? 4
57 : sizeof(T
) * CHAR_BIT
;
60 // Determines the width in bits of all of its arguments
61 template<typename
... T
> unsigned multiBitWidth();
62 template<typename T
, typename
... Args
>
63 inline unsigned multiBitWidth(T t
, Args
... args
) {
64 return bitWidth
<T
>() + multiBitWidth
<Args
...>(args
...);
67 inline unsigned multiBitWidth() {
71 // Given the same arguments as multiBitWidth, buildBitmask will determine which
72 // index in the table corresponds to the provided parameters.
73 template<unsigned bit
>
74 inline unsigned buildBitmask() {
75 static_assert(bit
< (sizeof(unsigned) * CHAR_BIT
- 1), "Too many bits");
78 template<unsigned bit
= 0, typename T
, typename
... Args
>
79 inline unsigned buildBitmask(T c
, Args
... args
) {
80 unsigned bits
= (unsigned)c
& ((1u << bitWidth
<T
>()) - 1);
81 return buildBitmask
<bit
+ bitWidth
<T
>()>(args
...) | bits
<< bit
;
84 // FILL_ROW and BUILD_OPTAB* build up the static table of function pointers
85 #define FILL_ROW(nm, ...) do { \
86 OpFunc* dest = &optab[buildBitmask(__VA_ARGS__)]; \
87 assert(*dest == nullptr); \
88 *dest = (OpFunc)VectorHelpers::nm; \
90 #define FILL_ROW_HOT(nm, hot, ...) FILL_ROW(nm, __VA_ARGS__)
92 #define BUILD_OPTAB(...) BUILD_OPTAB_ARG(HELPER_TABLE(FILL_ROW), __VA_ARGS__)
93 #define BUILD_OPTAB_HOT(...) \
94 BUILD_OPTAB_ARG(HELPER_TABLE(FILL_ROW_HOT), __VA_ARGS__)
95 #define BUILD_OPTAB_ARG(FILL_TABLE, ...) \
96 static OpFunc* optab = nullptr; \
98 optab = (OpFunc*)calloc(1 << multiBitWidth(__VA_ARGS__), sizeof(OpFunc)); \
101 unsigned idx = buildBitmask(__VA_ARGS__); \
102 OpFunc opFunc = optab[idx]; \
105 // The getKeyType family of functions determine the KeyType to be used as a
106 // template argument to helper functions. S, IS, or I at the end of the
107 // function names signals that the caller supports non-literal strings, int, or
108 // both, respectively.
109 static KeyType
getKeyType(const SSATmp
* key
, bool nonLitStr
,
111 auto DEBUG_ONLY keyType
= key
->type();
112 assert(keyType
.notBoxed());
113 assert(keyType
.isKnownDataType() || keyType
.equals(Type::Cell
));
115 if ((key
->isConst() || nonLitStr
) && key
->isString()) {
117 } else if ((key
->isConst() || nonLitInt
) && key
->isA(Type::Int
)) {
123 inline static KeyType
getKeyType(const SSATmp
* key
) {
124 return getKeyType(key
, false, false);
126 inline static KeyType
getKeyTypeS(const SSATmp
* key
) {
127 return getKeyType(key
, true, false);
129 inline static KeyType
getKeyTypeIS(const SSATmp
* key
) {
130 return getKeyType(key
, true, true);
133 // keyPtr is used by helper function implementations to convert a
134 // TypedValue passed by value into a TypedValue* suitable for passing
135 // to helpers from member_operations.h, which are prepared to handle
136 // int64 and StringData* keys in their key argument. This should be
137 // cleaned up to use the right types: #2174037
139 static inline TypedValue
* keyPtr(TypedValue
& key
) {
140 if (kt
== KeyType::Any
) {
141 assert(tvIsPlausible(&key
));
144 return reinterpret_cast<TypedValue
*>(key
.m_data
.num
);