Skip to content

Commit 9e80b6d

Browse files
committed
JIT
1 parent 81d16b0 commit 9e80b6d

9 files changed

+477
-14
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
--TEST--
2+
Lazy objects: JIT: ASSIGN_OBJ with dynamic prop
3+
--FILE--
4+
<?php
5+
6+
#[AllowDynamicProperties]
7+
class C {
8+
public int $b = 1;
9+
10+
public function __construct() {
11+
var_dump(__METHOD__);
12+
$this->b = 3;
13+
}
14+
}
15+
16+
function test(string $name, object $obj) {
17+
printf("# %s:\n", $name);
18+
19+
var_dump($obj);
20+
$obj->a = 2;
21+
var_dump($obj);
22+
}
23+
24+
$reflector = new ReflectionClass(C::class);
25+
26+
$obj = $reflector->newLazyGhost(function ($obj) {
27+
var_dump("initializer");
28+
$obj->__construct();
29+
});
30+
31+
test('Ghost', $obj);
32+
33+
$obj = $reflector->newLazyProxy(function ($obj) {
34+
var_dump("initializer");
35+
return new C();
36+
});
37+
38+
test('Proxy', $obj);
39+
40+
--EXPECTF--
41+
# Ghost:
42+
lazy ghost object(C)#%d (0) {
43+
["b"]=>
44+
uninitialized(int)
45+
}
46+
string(11) "initializer"
47+
string(14) "C::__construct"
48+
object(C)#%d (2) {
49+
["b"]=>
50+
int(3)
51+
["a"]=>
52+
int(2)
53+
}
54+
# Proxy:
55+
lazy proxy object(C)#%d (0) {
56+
["b"]=>
57+
uninitialized(int)
58+
}
59+
string(11) "initializer"
60+
string(14) "C::__construct"
61+
lazy proxy object(C)#%d (1) {
62+
["instance"]=>
63+
object(C)#%d (2) {
64+
["b"]=>
65+
int(3)
66+
["a"]=>
67+
int(2)
68+
}
69+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
--TEST--
2+
Lazy objects: JIT: ASSIGN_OBJ_OP with dynamic prop
3+
--FILE--
4+
<?php
5+
6+
#[AllowDynamicProperties]
7+
class C {
8+
public int $b = 1;
9+
10+
public function __construct() {
11+
var_dump(__METHOD__);
12+
$this->a = 1;
13+
$this->b = 3;
14+
}
15+
}
16+
17+
function test(string $name, object $obj) {
18+
printf("# %s:\n", $name);
19+
20+
var_dump($obj);
21+
$obj->a += 1;
22+
var_dump($obj);
23+
}
24+
25+
$reflector = new ReflectionClass(C::class);
26+
27+
$obj = $reflector->newLazyGhost(function ($obj) {
28+
var_dump("initializer");
29+
$obj->__construct();
30+
});
31+
32+
test('Ghost', $obj);
33+
34+
$obj = $reflector->newLazyProxy(function ($obj) {
35+
var_dump("initializer");
36+
return new C();
37+
});
38+
39+
test('Proxy', $obj);
40+
41+
--EXPECTF--
42+
# Ghost:
43+
lazy ghost object(C)#%d (0) {
44+
["b"]=>
45+
uninitialized(int)
46+
}
47+
string(11) "initializer"
48+
string(14) "C::__construct"
49+
object(C)#%d (2) {
50+
["b"]=>
51+
int(1)
52+
["a"]=>
53+
int(2)
54+
}
55+
# Proxy:
56+
lazy proxy object(C)#%d (0) {
57+
["b"]=>
58+
uninitialized(int)
59+
}
60+
string(11) "initializer"
61+
string(14) "C::__construct"
62+
lazy proxy object(C)#%d (1) {
63+
["instance"]=>
64+
object(C)#%d (2) {
65+
["b"]=>
66+
int(3)
67+
["a"]=>
68+
int(2)
69+
}
70+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
--TEST--
2+
Lazy objects: JIT: ASSIGN_OBJ_OP with known prop_info
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public $a;
8+
public int $b = 1;
9+
10+
public function __construct() {
11+
var_dump(__METHOD__);
12+
$this->b = 3;
13+
}
14+
}
15+
16+
function test(string $name, object $obj) {
17+
printf("# %s:\n", $name);
18+
19+
var_dump($obj);
20+
$obj->a += 1;
21+
var_dump($obj);
22+
}
23+
24+
$reflector = new ReflectionClass(C::class);
25+
26+
$obj = $reflector->newLazyGhost(function ($obj) {
27+
var_dump("initializer");
28+
$obj->__construct();
29+
});
30+
31+
test('Ghost', $obj);
32+
33+
$obj = $reflector->newLazyProxy(function ($obj) {
34+
var_dump("initializer");
35+
return new C();
36+
});
37+
38+
test('Proxy', $obj);
39+
40+
--EXPECTF--
41+
# Ghost:
42+
lazy ghost object(C)#%d (0) {
43+
["b"]=>
44+
uninitialized(int)
45+
}
46+
string(11) "initializer"
47+
string(14) "C::__construct"
48+
object(C)#%d (2) {
49+
["a"]=>
50+
int(1)
51+
["b"]=>
52+
int(3)
53+
}
54+
# Proxy:
55+
lazy proxy object(C)#%d (0) {
56+
["b"]=>
57+
uninitialized(int)
58+
}
59+
string(11) "initializer"
60+
string(14) "C::__construct"
61+
lazy proxy object(C)#%d (1) {
62+
["instance"]=>
63+
object(C)#%d (2) {
64+
["a"]=>
65+
int(1)
66+
["b"]=>
67+
int(3)
68+
}
69+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
--TEST--
2+
Lazy objects: JIT: ASSIGN_OBJ_OP with unknown prop info
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
// Private prop so that prop_info is not inferred
8+
private int $a;
9+
public int $b;
10+
function __construct() {
11+
$this->a = 1;
12+
$this->b = 2;
13+
}
14+
function test(object $obj) {
15+
$obj->a += 1;
16+
}
17+
}
18+
19+
$reflector = new ReflectionClass(C::class);
20+
21+
for ($i = 0; $i < 2; $i++) {
22+
$obj = $reflector->newLazyGhost(function ($obj) {
23+
var_dump("initializer");
24+
$obj->__construct();
25+
});
26+
// Call via reflection to avoid inlining.
27+
// - test() handlers are executed once, and prime the runtime cache
28+
// - On subsequent calls, the JIT'ed code is used, and we enter the valid runtime cache path
29+
$reflector->getMethod('test')->invoke($obj, $obj);
30+
var_dump($obj);
31+
}
32+
33+
--EXPECTF--
34+
string(11) "initializer"
35+
object(C)#%d (2) {
36+
["a":"C":private]=>
37+
int(2)
38+
["b"]=>
39+
int(2)
40+
}
41+
string(11) "initializer"
42+
object(C)#%d (2) {
43+
["a":"C":private]=>
44+
int(2)
45+
["b"]=>
46+
int(2)
47+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
Lazy objects: JIT: ASSIGN_OBJ_OP with unknown prop info untyped
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
// Private prop so that prop_info is not inferred
8+
private int $a;
9+
public int $b;
10+
function __construct() {
11+
$this->a = 1;
12+
$this->b = 2;
13+
}
14+
function test(object $obj) {
15+
$obj->a += 1;
16+
}
17+
}
18+
19+
$reflector = new ReflectionClass(C::class);
20+
21+
for ($i = 0; $i < 2; $i++) {
22+
$obj = $reflector->newLazyGhost(function ($obj) {
23+
var_dump("initializer");
24+
$obj->__construct();
25+
});
26+
// Call via reflection to avoid inlining.
27+
// - test() handlers are executed once, and prime the runtime cache
28+
// - On subsequent calls, the JIT'ed code is used, and we enter the valid runtime cache path
29+
$reflector->getMethod('test')->invoke($obj, $obj);
30+
var_dump($obj);
31+
}
32+
33+
?>
34+
--EXPECTF--
35+
string(11) "initializer"
36+
object(C)#%d (2) {
37+
["a":"C":private]=>
38+
int(2)
39+
["b"]=>
40+
int(2)
41+
}
42+
string(11) "initializer"
43+
object(C)#%d (2) {
44+
["a":"C":private]=>
45+
int(2)
46+
["b"]=>
47+
int(2)
48+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
--TEST--
2+
Lazy objects: JIT: ASSIGN_OBJ with known prop_info
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public $a;
8+
public int $b = 1;
9+
10+
public function __construct() {
11+
var_dump(__METHOD__);
12+
$this->b = 3;
13+
}
14+
}
15+
16+
function test(string $name, object $obj) {
17+
printf("# %s:\n", $name);
18+
19+
var_dump($obj);
20+
$obj->a = 2;
21+
var_dump($obj);
22+
}
23+
24+
$reflector = new ReflectionClass(C::class);
25+
26+
$obj = $reflector->newLazyGhost(function ($obj) {
27+
var_dump("initializer");
28+
$obj->__construct();
29+
});
30+
31+
test('Ghost', $obj);
32+
33+
$obj = $reflector->newLazyProxy(function ($obj) {
34+
var_dump("initializer");
35+
return new C();
36+
});
37+
38+
test('Proxy', $obj);
39+
40+
--EXPECTF--
41+
# Ghost:
42+
lazy ghost object(C)#%d (0) {
43+
["b"]=>
44+
uninitialized(int)
45+
}
46+
string(11) "initializer"
47+
string(14) "C::__construct"
48+
object(C)#%d (2) {
49+
["a"]=>
50+
int(2)
51+
["b"]=>
52+
int(3)
53+
}
54+
# Proxy:
55+
lazy proxy object(C)#%d (0) {
56+
["b"]=>
57+
uninitialized(int)
58+
}
59+
string(11) "initializer"
60+
string(14) "C::__construct"
61+
lazy proxy object(C)#%d (1) {
62+
["instance"]=>
63+
object(C)#%d (2) {
64+
["a"]=>
65+
int(2)
66+
["b"]=>
67+
int(3)
68+
}
69+
}

0 commit comments

Comments
 (0)