Arquivos
hhvm/hphp/test/quick/va_poly.php
T
mwilliams 412dce677f Better reffiness checks
While debugging a sandbox crash, I spent some time looking at a huge
sequnce of conditional masks, compares and branches that didnt seem
to belong in the code I was debugging. Finally realized that it was
a reffiness check. It looked way too complicated, so I investigated.

Part of the problem was that we were avoiding a malloc in the case
of a zero param function at the expense of an extra check.

Instead, this diff always sets up at least 64 bits worth of m_refBitVec.
But by using the space set aside for the pointer in Func::m_shared it
avoids a malloc for any function with fewer than 65 arguments, and
avoids the numParams check for the first 64 parameters.

In addition, the existing code was spitting out a generic test for
the guard condition - (mask & bits) == value - where mask and value
are known constants. Since the most common case is that value == 0
(all the parameters are expected to be by value), we can usually omit
the compare. In addition, since most functions only have a small
number of parameters, we can usually get away with 8 bit, or 32
bit operations.

The result is that for a typical function (fewer than 64 args, args
expected to be by value) the reffiness guard is now

  test <mask>, Func::m_refBitVec[0]
  jne exit

Rather than:

  move <mask>, reg1
  xor reg2, reg2
  cmp 1, Func::m_numParams
  jnl ok
  test AttrVarArgs, Func::m_attrs
  jne exit
  jmp done
ok:
  load reg3, Func::m_refBitVec[0]
  and mask, reg3
  cmp reg3, reg2
  jne exit
done:
2013-06-11 11:48:25 -07:00

39 linhas
651 B
PHP

<?
class C1 {
function __call($a, $b) {
echo '.';
}
}
class C2 {
function __call($a, $b) {
echo '+';
}
}
class C3 {
function maul($a,$b,&$c) {
echo '*';
$c++;
}
}
function main() {
$o = new C1();
// First pass through, "learn" that these calls go to C1::__call.
for ($i = 0; $i < 12; $i++) {
$o->maul(1, 2, $i, 3);
$o->maul(1, 2, $i, 3, 4);
$o->maul(1, 2, $i, 3, 4, 5);
$o->maul(1, 2, $i, 3, 4, 5, 6);
$o->maul(1, 2, $i, 3, 4, 5, 6, 7);
$o->maul(1, 2, $i, 3, 4, 5, 6, 7, 8);
// Send subsequent passes to C2::__call
$o = $i == 0 ? new C2() : new C3();
echo "\n";
}
}
main();