by Enrico Zimuel
							Co-founder PUG Torino
						
					
				
								 
							 | 
							
								
  | 
						
 PUG Torino
								 
							 | 
							
								
  | 
						
A Just-In-Time (JIT) compiler is a feature of the run-time interpreter, that instead of interpreting bytecode every time a method is invoked, will compile the bytecode into machine code, and then invoke this object code instead
				
for ($i=0; $i<100; $i++) {
    echo $i;
}	
Opcode:
L0 (2):     ASSIGN CV0($i) int(0)
L1 (2):     JMP L4
L2 (3):     ECHO CV0($i)
L3 (2):     PRE_INC CV0($i)
L4 (2):     T1 = IS_SMALLER CV0($i) int(100)
L5 (2):     JMPNZ T1 L2
L6 (5):     RETURN int(1)
					php -d opcache.opt_debug_level=0x20000 -d opcache.enable_cli=1 test.php
				
				
	sub $0x10, %rsp
	lea 0x50(%r14), %rdi
	cmp $0xa, 0x8(%rdi)
	jnz .L1
	mov (%rdi), %rdi
	cmp $0x0, 0x18(%rdi)
	jnz .L6
	add $0x8, %rdi
.L1:
	test $0x1, 0x9(%rdi)
	jnz .L7
	mov $0x0, (%rdi)
	mov $0x4, 0x8(%rdi)
.L2:
	mov $EG(exception), %rax
	cmp $0x0, (%rax)
	jnz JIT$$exception_handler
	jmp .L4
.L3:
	mov $0x7fcc67e2e630, %r15
	mov $0x561f82773690, %rax
	call *%rax
	mov $EG(exception), %rax
	cmp $0x0, (%rax)
	jnz JIT$$exception_handler
	cmp $0x4, 0x58(%r14)
	jnz .L9
	add $0x1, 0x50(%r14)
.L4:
	mov $EG(vm_interrupt), %rax
	cmp $0x0, (%rax)
	jnz .L11
	cmp $0x4, 0x58(%r14)
	jnz .L12
	cmp $0x64, 0x50(%r14)
	jl .L3
.L5:
	mov $0x7fcc67e2e6b0, %r15
	add $0x10, %rsp
	mov $ZEND_RETURN_SPEC_CONST_LABEL, %rax
	jmp *%rax
	sub $0x10, %rsp
	jmp .L4
.L6:
	mov $0x7fcc67e2e5c0, %rsi
	mov %r15, (%r14)
	mov $zend_jit_assign_const_to_typed_ref, %rax
	call *%rax
	jmp .L2
.L7:
	mov (%rdi), %rax
	mov %rax, (%rsp)
	mov $0x0, (%rdi)
	mov $0x4, 0x8(%rdi)
	mov (%rsp), %rdi
	sub $0x1, (%rdi)
	jnz .L8
	mov %r15, (%r14)
	mov $rc_dtor_func, %rax
	call *%rax
	jmp .L2
.L8:
	mov 0x4(%rdi), %eax
	and $0xfffffc10, %eax
	cmp $0x10, %eax
	jnz .L2
	mov $gc_possible_root, %rax
	call *%rax
	jmp .L2
.L9:
	mov %r15, (%r14)
	lea 0x50(%r14), %rdi
	cmp $0xa, 0x8(%rdi)
	jnz .L10
	mov (%rdi), %rsi
	cmp $0x0, 0x18(%rsi)
	lea 0x8(%rsi), %rdi
	jz .L10
	mov $0x0, %rdx
	mov $zend_jit_pre_inc_typed_ref, %rax
	call *%rax
	mov $EG(exception), %rax
	cmp $0x0, (%rax)
	jnz JIT$$exception_handler
	jmp .L4
.L10:
	mov $increment_function, %rax
	call *%rax
	jmp .L4
.L11:
	mov $0x7fcc67e2e670, %r15
	jmp JIT$$interrupt_handler
.L12:
	cmp $0x5, 0x58(%r14)
	jnz .L13
	mov $0x64, %rax
	vcvtsi2sd %rax, %xmm0, %xmm0
	vucomisd 0x50(%r14), %xmm0
	ja .L3
	jmp .L5
.L13:
	mov $0x7fcc67e2e670, %rax
	mov %rax, (%r14)
	lea 0x50(%r14), %rsi
	mov $0x7fcc67e2e5d0, %rdx
	lea 0x60(%r14), %rdi
	mov $compare_function, %rax
	call *%rax
	mov $EG(exception), %rax
	cmp $0x0, (%rax)
	jnz JIT$$exception_handler_undef
	cmp $0x0, 0x60(%r14)
	jl .L3
	jmp .L5
					php -d opcache.enable_cli=1 -d opcache.jit=1235 
-d opcache.jit_buffer_size=64M -d opcache.jit_debug=1 test.php
					Execution time (sec) of Zend/bench.php, using PHP 7.4.4 (Zend Engine 3.4.0)
and PHP 8.0.0-dev (Zend Engine 4.0.0-dev)
class Number {
    private int|float $number;
	
    public function setNumber(int|float $number): void {
        $this->number = $number;
    }
	
    public function getNumber(): int|float {
        return $this->number;
    }
}
				
class A {
    public function __construct($params = []) {
        $this->params = $params;
    }
    public function create($params): static {
        return new static($params);
    }
}
class B extends A {
}
$b = new B();
$result = $b->create(['x' => 'y']);
var_dump($result); // object(B) {["params"]=> ["x" => "y"]}
				
				
class A {
    public function doWhatever(): static {
        // Do whatever.
        return $this;
    }
}
$a = new A();
$result = $a->doWhatever(); // $result === $a
				To provide "weakly referenced" map objects
$map = new WeakMap;
$obj = new stdClass;
$map[$obj] = 42;
var_dump($map);
// object(WeakMap)#1 (1) {
//   [0]=> [ 
//     "key" => object(stdClass)#2,
//     "value" => int(42)
//   ]
// }
	
// The object is destroyed here, key automatically removed
unset($obj);
var_dump($map);
// object(WeakMap)#1 (0) { }	
				
class Foo {
    private WeakMap $cache;
	
    public function getSomethingWithCaching(object $obj) {
        return $this->cache[$obj] ??= $this->somethingExpensive($obj);
    }
}
					??= Null Coalescing Assignment (PHP 7.4+)
$object = new stdClass;
var_dump($object::class); // "stdClass"
	
$object = null;
var_dump($object::class); // TypeError
		
									
interface Stringable
{
    public function __toString(): string;
}
					Stringable interface is automatically added to classes that implement the __toString() method
Feature freeze: July 28th 2020
GA release: December 3rd 2020
Follow me: @ezimuel
Subscribe to PUG Torino on Meetup!
					
This work is licensed under a
 Creative Commons Attribution-ShareAlike 3.0 Unported License.
I used reveal.js to make this presentation.