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/array-offset-profile.h"
19 #include "hphp/runtime/base/array-data.h"
20 #include "hphp/runtime/base/mixed-array.h"
21 #include "hphp/runtime/base/mixed-array-defs.h"
22 #include "hphp/runtime/base/set-array.h"
23 #include "hphp/runtime/base/runtime-option.h"
24 #include "hphp/runtime/base/string-data.h"
25 #include "hphp/runtime/vm/member-operations.h"
27 #include "hphp/util/safe-cast.h"
29 #include <folly/Optional.h>
34 namespace HPHP
{ namespace jit
{
36 ///////////////////////////////////////////////////////////////////////////////
38 std::string
ArrayOffsetProfile::toString() const {
39 if (!m_init
) return std::string("uninitialized");
40 std::ostringstream out
;
41 for (auto const& line
: m_hits
) {
42 out
<< folly::format("{}:{},", line
.pos
, line
.count
);
44 out
<< folly::format("untracked:{}", m_untracked
);
48 folly::Optional
<uint32_t>
49 ArrayOffsetProfile::choose() const {
53 if (!m_init
) return folly::none
;
55 for (auto i
= 0; i
< kNumTrackedSamples
; ++i
) {
56 auto const& line
= m_hits
[i
];
57 if (!validPos(line
.pos
)) break;
59 if (line
.count
> hottest
.count
) hottest
= line
;
64 auto const bound
= total
* RuntimeOption::EvalHHIRMixedArrayProfileThreshold
;
65 return hottest
.count
>= bound
66 ? folly::make_optional(safe_cast
<uint32_t>(hottest
.pos
))
70 bool ArrayOffsetProfile::update(int32_t pos
, uint32_t count
) {
78 for (auto i
= 0; i
< kNumTrackedSamples
; ++i
) {
79 auto& line
= m_hits
[i
];
81 if (line
.pos
== pos
) {
96 void ArrayOffsetProfile::update(const ArrayData
* ad
, int64_t i
) {
97 auto h
= hash_int64(i
);
99 ad
->hasMixedLayout() ? MixedArray::asMixed(ad
)->find(i
, h
) :
100 ad
->isKeyset() ? SetArray::asSet(ad
)->find(i
, h
) :
105 void ArrayOffsetProfile::update(const ArrayData
* ad
,
106 const StringData
* sd
,
108 auto const pos
= [&]() -> int32_t {
109 if (ad
->hasMixedLayout()) {
110 auto const a
= MixedArray::asMixed(ad
);
113 if (checkForInt
&& ad
->convertKey(sd
, i
, false)) {
114 return !checkHACIntishCast() ?
115 a
->find(i
, hash_int64(i
)) : -1;
117 return a
->find(sd
, sd
->hash());
118 } else if (ad
->isKeyset()) {
119 return SetArray::asSet(ad
)->find(sd
, sd
->hash());
127 void ArrayOffsetProfile::reduce(ArrayOffsetProfile
& l
,
128 const ArrayOffsetProfile
& r
) {
129 if (!r
.m_init
) return;
131 Line scratch
[2 * kNumTrackedSamples
];
132 auto n
= uint32_t{0};
134 for (auto i
= 0; i
< kNumTrackedSamples
; ++i
) {
135 auto const& rline
= r
.m_hits
[i
];
136 if (!validPos(rline
.pos
)) break;
138 // Update `l'. If `l' can't record the update, save it to scratch.
139 if (!l
.update(rline
.pos
, rline
.count
)) {
140 scratch
[n
++] = rline
;
143 l
.m_untracked
+= r
.m_untracked
;
146 assertx(n
<= kNumTrackedSamples
);
148 // Sort the combined samples, then copy the top hits back into `l'.
149 std::memcpy(&scratch
[n
], &l
.m_hits
[0],
150 kNumTrackedSamples
* sizeof(Line
));
151 std::sort(&scratch
[0], &scratch
[n
+ kNumTrackedSamples
],
152 [] (Line a
, Line b
) { return a
.count
> b
.count
; });
153 std::memcpy(l
.m_hits
, scratch
, kNumTrackedSamples
);
155 // Add the hits in the discarded tail to m_untracked.
156 for (auto i
= kNumTrackedSamples
; i
< n
+ kNumTrackedSamples
; ++i
) {
157 auto const& line
= scratch
[i
];
158 if (!validPos(line
.pos
)) break;
160 l
.m_untracked
+= line
.count
;
164 void ArrayOffsetProfile::init() {
166 for (auto i
= 0; i
< kNumTrackedSamples
; ++i
) {
172 ///////////////////////////////////////////////////////////////////////////////