Skip to content

Commit 159314f

Browse files
vassilmladenovfacebook-github-bot
authored andcommitted
Make APC and internal serialize use lazy classes for class pointers
Summary: The logic for APC serialization is inconsistent for lazy classes and class pointers depending on the container. Before this diff, `apc_store` on a bare class pointer works fine, but in a `Pair` it comes back as a string. With this diff, I'm still inconsistent between storing the pointer (see `APCTypedValue(const Class*)`) vs. a lazy class, but it eliminates the stringy-ness. The unserialize logic for `c` kinds appears to only have been added for the record-replay logic, so I would like to test it separately. Filed T227444162 to track unification. --- Code pointers: https://www.internalfb.com/code/fbsource/[a3b0b69363b85c03111e37c07a59651631b2d9ca]/fbcode/hphp/runtime/base/apc-handle.cpp?lines=89-101 https://www.internalfb.com/code/fbsource/[a3b0b69363b85c03111e37c07a59651631b2d9ca]/fbcode/hphp/runtime/base/apc-collection.cpp?lines=88-94 https://www.internalfb.com/code/fbsource/[a3b0b69363b85c03111e37c07a59651631b2d9ca]/fbcode/hphp/runtime/base/collections.cpp?lines=131-146 https://www.internalfb.com/code/fbsource/[a36f581b09a9239b7f3ba740615a512e7a8255e9]/fbcode/hphp/runtime/base/variable-unserializer.cpp?lines=1217-1223 Reviewed By: jano Differential Revision: D76558975 fbshipit-source-id: 5f631c32198b4c4b4227a13c8d82e7be066bb6e0
1 parent 3b9759b commit 159314f

File tree

5 files changed

+186
-3
lines changed

5 files changed

+186
-3
lines changed

hphp/runtime/base/variable-serializer.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,13 +1622,19 @@ void VariableSerializer::serializeClass(const Class* cls) {
16221622
m_buf->append(')');
16231623
break;
16241624
case Type::JSON:
1625+
case Type::Serialize:
16251626
write(StrNR(classToStringHelper(cls, "serialization")));
16261627
break;
1627-
case Type::Serialize:
16281628
case Type::Internal:
1629-
case Type::APCSerialize:
1630-
write(StrNR(classToStringHelper(cls, "serialization")));
1629+
case Type::APCSerialize: {
1630+
auto cname = cls->name();
1631+
m_buf->append("l:");
1632+
m_buf->append(cname->size());
1633+
m_buf->append(":\"");
1634+
m_buf->append(cname->data(), cname->size());
1635+
m_buf->append("\";");
16311636
break;
1637+
}
16321638
case Type::DebuggerSerialize:
16331639
m_buf->append("c:");
16341640
m_buf->append(cls->name()->size());
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?hh
2+
3+
class C {
4+
public static function f(): void { echo " called\n"; }
5+
}
6+
7+
function check_array($key, $arr): void {
8+
apc_store($key, $arr);
9+
$a = __hhvm_intrinsics\apc_fetch_no_check($key);
10+
foreach ($a as $k => $v) {
11+
echo "$k:";
12+
$v::f();
13+
}
14+
}
15+
16+
<<__EntryPoint>>
17+
function main(): void {
18+
$ss = nameof C;
19+
$s = __hhvm_intrinsics\launder_value($ss)."";
20+
$lc = C::class;
21+
$c = HH\classname_to_class($lc);
22+
23+
$collection = Map {
24+
'static_string' => $ss,
25+
'string' => $s,
26+
'lazy_class' => $lc,
27+
'class' => $c,
28+
};
29+
30+
echo "===== Basic =====\n";
31+
foreach ($collection as $k => $v) {
32+
apc_store($k, $v);
33+
$x = __hhvm_intrinsics\apc_fetch_no_check($k);
34+
echo "$k:";
35+
$x::f();
36+
}
37+
38+
echo "\n\n===== Map =====\n";
39+
check_array('collection', $collection);
40+
41+
echo "\n\n===== dict =====\n";
42+
$dict = dict($collection);
43+
check_array('dict', $dict);
44+
45+
echo "\n\n===== Pair =====\n";
46+
foreach ($collection as $k => $v) {
47+
$pair = Pair { $k, $v };
48+
apc_store('pair', $pair);
49+
$p = __hhvm_intrinsics\apc_fetch_no_check('pair');
50+
$k = $p[0];
51+
$v = $p[1];
52+
echo "$k:";
53+
$v::f();
54+
}
55+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
===== Basic =====
2+
static_string:
3+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/apc-serialize-round-trip.php on line 35
4+
called
5+
string:
6+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/apc-serialize-round-trip.php on line 35
7+
called
8+
lazy_class: called
9+
class: called
10+
11+
12+
===== Map =====
13+
static_string:
14+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/apc-serialize-round-trip.php on line 12
15+
called
16+
string:
17+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/apc-serialize-round-trip.php on line 12
18+
called
19+
lazy_class: called
20+
class: called
21+
22+
23+
===== dict =====
24+
static_string:
25+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/apc-serialize-round-trip.php on line 12
26+
called
27+
string:
28+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/apc-serialize-round-trip.php on line 12
29+
called
30+
lazy_class: called
31+
class: called
32+
33+
34+
===== Pair =====
35+
static_string:
36+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/apc-serialize-round-trip.php on line 53
37+
called
38+
string:
39+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/apc-serialize-round-trip.php on line 53
40+
called
41+
lazy_class: called
42+
class: called
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?hh
2+
3+
const int SER_INTERNAL = 6; // VariableSerializer::Type::Internal
4+
const int DES_INTERNAL = 2; // VariableUnserializer::Type::Internal
5+
6+
class C {
7+
public static function f(): void { echo " called\n"; }
8+
}
9+
10+
function round_trip($p): void {
11+
$key = $p[0];
12+
$val = $p[1];
13+
14+
$x = __hhvm_intrinsics\serialize_with_format(
15+
$val,
16+
SER_INTERNAL,
17+
);
18+
$v = __hhvm_intrinsics\deserialize_with_format(
19+
$x,
20+
DES_INTERNAL,
21+
);
22+
echo "$key:";
23+
$v::f();
24+
}
25+
26+
function pair_round_trip($p): void {
27+
$x = __hhvm_intrinsics\serialize_with_format(
28+
$p,
29+
SER_INTERNAL,
30+
);
31+
$pair = __hhvm_intrinsics\deserialize_with_format(
32+
$x,
33+
DES_INTERNAL,
34+
);
35+
$key = $pair[0];
36+
$val = $pair[1];
37+
38+
echo "$key:";
39+
$val::f();
40+
}
41+
42+
<<__EntryPoint>>
43+
function main(): void {
44+
$ss = Pair { 'static_string', nameof C };
45+
$s = Pair { 'string', __hhvm_intrinsics\launder_value(nameof C)."" };
46+
$l = Pair { 'lazy_class', C::class };
47+
$c = Pair { 'class', HH\classname_to_class(C::class) };
48+
49+
echo "===== Basic =====\n";
50+
round_trip($ss); // log
51+
round_trip($s); // log
52+
round_trip($l);
53+
round_trip($c);
54+
55+
echo "\n\n===== Pair =====\n";
56+
pair_round_trip($ss); // log
57+
pair_round_trip($s); // log
58+
pair_round_trip($l);
59+
pair_round_trip($c);
60+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
===== Basic =====
2+
static_string:
3+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/internal-serialize-round-trip.php on line 23
4+
called
5+
string:
6+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/internal-serialize-round-trip.php on line 23
7+
called
8+
lazy_class: called
9+
class: called
10+
11+
12+
===== Pair =====
13+
static_string:
14+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/internal-serialize-round-trip.php on line 39
15+
called
16+
string:
17+
Notice: Implicit string to Class conversion for classname C in %s/class-ptr/internal-serialize-round-trip.php on line 39
18+
called
19+
lazy_class: called
20+
class: called

0 commit comments

Comments
 (0)