2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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 +----------------------------------------------------------------------+
16 #include "hphp/runtime/vm/jit/opt.h"
20 #include "hphp/runtime/vm/jit/ir-instruction.h"
21 #include "hphp/runtime/vm/jit/block.h"
22 #include "hphp/runtime/vm/jit/ir-unit.h"
23 #include "hphp/runtime/vm/jit/cfg.h"
25 namespace HPHP
{ namespace jit
{
29 //////////////////////////////////////////////////////////////////////
32 * Insert `inst' after `definer'.
34 * If `definer' ends its block, it must have a fallthrough block, and `inst'
35 * will be inserted at the beginning of that block, as long as the block has no
38 * Returns: true if it inserted the intruction.
40 bool insertAfter(IRInstruction
* definer
, IRInstruction
* inst
) {
41 assertx(!definer
->isTerminal());
42 if (definer
->isControlFlow()) {
43 assertx(definer
->next());
44 if (definer
->next()->numPreds() == 1) {
45 definer
->next()->prepend(inst
);
51 auto const block
= definer
->block();
52 auto const pos
= block
->iteratorTo(definer
);
53 block
->insert(std::next(pos
), inst
);
58 * Insert a DbgAssertRefCount instruction after each place we define a
59 * maybe-refcounted SSATmp.
61 void insertRefCountAsserts(IRUnit
& unit
, IRInstruction
& inst
) {
62 for (auto dst
: inst
.dsts()) {
63 auto const t
= dst
->type();
64 if (t
<= TGen
&& t
.maybe(TCounted
)) {
65 insertAfter(&inst
, unit
.gen(DbgAssertRefCount
, inst
.marker(), dst
));
70 void insertStkAssert(IRUnit
& unit
,
74 auto const addr
= unit
.gen(
78 IRSPOffsetData
{ off
},
81 if (!insertAfter(where
, addr
)) return;
82 auto const check
= unit
.gen(DbgAssertPtr
, where
->marker(), addr
->dst());
83 insertAfter(addr
, check
);
86 //////////////////////////////////////////////////////////////////////
88 void visit(IRUnit
& unit
, Block
* block
) {
89 for (auto it
= block
->begin(); it
!= block
->end();) {
96 auto const extra
= inst
.extra
<Call
>();
97 insertStkAssert(unit
, &inst
, inst
.src(0),
98 extra
->spOffset
+ extra
->numParams
+ kNumActRecCells
- 1);
102 insertRefCountAsserts(unit
, inst
);
108 //////////////////////////////////////////////////////////////////////
112 void insertAsserts(IRUnit
& unit
) {
113 // Note: it doesn't matter what order we visit the blocks for this pass.
114 for (auto& block
: poSortCfg(unit
)) visit(unit
, block
);
117 //////////////////////////////////////////////////////////////////////