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 +----------------------------------------------------------------------+
17 #include "hphp/runtime/vm/jit/irlower-internal.h"
19 #include "hphp/runtime/base/collections.h"
20 #include "hphp/runtime/base/object-data.h"
21 #include "hphp/runtime/base/packed-array.h"
23 #include "hphp/runtime/ext/collections/ext_collections.h"
24 #include "hphp/runtime/ext/collections/ext_collections-pair.h"
25 #include "hphp/runtime/ext/collections/ext_collections-vector.h"
26 #include "hphp/runtime/ext/collections/hash-collection.h"
28 #include "hphp/runtime/vm/jit/types.h"
29 #include "hphp/runtime/vm/jit/call-spec.h"
30 #include "hphp/runtime/vm/jit/code-gen-cf.h"
31 #include "hphp/runtime/vm/jit/code-gen-helpers.h"
32 #include "hphp/runtime/vm/jit/extra-data.h"
33 #include "hphp/runtime/vm/jit/ir-instruction.h"
34 #include "hphp/runtime/vm/jit/ir-opcode.h"
35 #include "hphp/runtime/vm/jit/ssa-tmp.h"
36 #include "hphp/runtime/vm/jit/type.h"
37 #include "hphp/runtime/vm/jit/type-specialization.h"
38 #include "hphp/runtime/vm/jit/vasm-gen.h"
39 #include "hphp/runtime/vm/jit/vasm-instr.h"
40 #include "hphp/runtime/vm/jit/vasm-reg.h"
42 #include "hphp/util/asm-x64.h"
43 #include "hphp/util/trace.h"
45 namespace HPHP
{ namespace jit
{ namespace irlower
{
47 TRACE_SET_MOD(irlower
);
49 ///////////////////////////////////////////////////////////////////////////////
53 void implColTestSize(IRLS
& env
, const IRInstruction
* inst
, ConditionCode cc
) {
54 DEBUG_ONLY
auto const ty
= inst
->src(0)->type();
57 ty
.clsSpec().cls()->isCollectionClass());
59 auto const dst
= dstLoc(env
, inst
, 0).reg();
60 auto const src
= srcLoc(env
, inst
, 0).reg();
63 auto const sf
= v
.makeReg();
64 v
<< cmplim
{0, src
[collections::FAST_SIZE_OFFSET
], sf
};
65 v
<< setcc
{cc
, sf
, dst
};
70 void cgIsCol(IRLS
& env
, const IRInstruction
* inst
) {
71 assertx(inst
->src(0)->type() <= TObj
);
73 auto const dst
= dstLoc(env
, inst
, 0).reg();
74 auto const src
= srcLoc(env
, inst
, 0).reg();
77 auto const sf
= emitIsCollection(v
, src
);
78 v
<< setcc
{CC_BE
, sf
, dst
};
81 void cgColIsEmpty(IRLS
& env
, const IRInstruction
* inst
) {
82 implColTestSize(env
, inst
, CC_E
);
85 void cgColIsNEmpty(IRLS
& env
, const IRInstruction
* inst
) {
86 implColTestSize(env
, inst
, CC_NE
);
89 void cgCountCollection(IRLS
& env
, const IRInstruction
* inst
) {
90 auto const src
= srcLoc(env
, inst
, 0).reg();
91 auto const dst
= dstLoc(env
, inst
, 0).reg();
93 v
<< loadzlq
{src
[collections::FAST_SIZE_OFFSET
], dst
};
96 void cgNewCol(IRLS
& env
, const IRInstruction
* inst
) {
97 auto const target
= [&] {
98 auto const col_type
= inst
->extra
<NewCol
>()->type
;
99 auto const helper
= collections::allocEmptyFunc(col_type
);
100 return CallSpec::direct(helper
);
102 cgCallHelper(vmain(env
), env
, target
, callDest(env
, inst
),
103 SyncOptions::Sync
, argGroup(env
, inst
));
106 IMPL_OPCODE_CALL(NewPair
)
108 void cgNewColFromArray(IRLS
& env
, const IRInstruction
* inst
) {
109 auto const target
= [&] {
110 auto const col_type
= inst
->extra
<NewColFromArray
>()->type
;
111 auto const helper
= collections::allocFromArrayFunc(col_type
);
112 return CallSpec::direct(helper
);
114 cgCallHelper(vmain(env
), env
, target
, callDest(env
, inst
),
115 SyncOptions::Sync
, argGroup(env
, inst
).ssa(0));
118 void cgLdColVec(IRLS
& env
, const IRInstruction
* inst
) {
119 auto const ty
= inst
->src(0)->type();
120 auto const cls
= ty
.clsSpec().cls();
122 auto const src
= srcLoc(env
, inst
, 0).reg();
123 auto const dst
= dstLoc(env
, inst
, 0).reg();
124 auto& v
= vmain(env
);
128 collections::isType(cls
, CollectionType::Vector
, CollectionType::ImmVector
),
129 "LdColVec received an unsupported type: {}\n",
133 v
<< load
{src
[BaseVector::arrOffset()], dst
};
136 void cgLdColDict(IRLS
& env
, const IRInstruction
* inst
) {
137 auto const ty
= inst
->src(0)->type();
138 auto const cls
= ty
.clsSpec().cls();
140 auto const src
= srcLoc(env
, inst
, 0).reg();
141 auto const dst
= dstLoc(env
, inst
, 0).reg();
142 auto& v
= vmain(env
);
146 collections::isType(cls
,
147 CollectionType::Map
, CollectionType::ImmMap
,
148 CollectionType::Set
, CollectionType::ImmSet
),
149 "LdColDict received an unsupported type: {}\n",
153 v
<< load
{src
[HashCollection::arrOffset()], dst
};
156 ///////////////////////////////////////////////////////////////////////////////
161 void assertHasVectorSrc(const IRInstruction
* inst
, bool imm_allowed
) {
162 DEBUG_ONLY
auto const vec
= inst
->src(0);
163 assertx(vec
->type() < TObj
);
166 assertx(collections::isType(vec
->type().clsSpec().cls(),
167 CollectionType::Vector
,
168 CollectionType::ImmVector
));
170 assertx(collections::isType(vec
->type().clsSpec().cls(),
171 CollectionType::Vector
));
177 void cgLdVectorSize(IRLS
& env
, const IRInstruction
* inst
) {
178 assertHasVectorSrc(inst
, true);
180 auto const src
= srcLoc(env
, inst
, 0).reg();
181 auto const dst
= dstLoc(env
, inst
, 0).reg();
182 auto& v
= vmain(env
);
183 v
<< loadzlq
{src
[BaseVector::sizeOffset()], dst
};
186 void cgLdVectorBase(IRLS
& env
, const IRInstruction
* inst
) {
187 assertHasVectorSrc(inst
, true);
189 auto const src
= srcLoc(env
, inst
, 0).reg();
190 auto const dst
= dstLoc(env
, inst
, 0).reg();
191 auto& v
= vmain(env
);
193 auto const arr
= v
.makeReg();
194 v
<< load
{src
[BaseVector::arrOffset()], arr
};
195 v
<< lea
{arr
[PackedArray::entriesOffset()], dst
};
198 ///////////////////////////////////////////////////////////////////////////////
201 void cgLdPairBase(IRLS
& env
, const IRInstruction
* inst
) {
202 DEBUG_ONLY
auto const pair
= inst
->src(0);
203 assertx(pair
->type() < TObj
);
204 assertx(collections::isType(pair
->type().clsSpec().cls(),
205 CollectionType::Pair
));
207 auto const src
= srcLoc(env
, inst
, 0).reg();
208 auto const dst
= dstLoc(env
, inst
, 0).reg();
209 vmain(env
) << lea
{src
[c_Pair::dataOffset()], dst
};
212 ///////////////////////////////////////////////////////////////////////////////