phparchitect-2019-08

(Rick Simeone) #1

36 \ August 2019 \ http://www.phparch.com


Generated Singletons


Internal Apparatus


We learned last month the code generator always produces
RETURN null for the closing brace of a function or method. We
see the same thing here at line 15 (generated line L2).


We know that a class constructor returns an object of that
class. That’s what a constructor does, but we don’t see that
here. We’ll see that in the next section of generated code.


Get Instance


The third section, Output 1 lines 17–41, is the generated
code for our static getInstance() method. Line 17 identi-
fies the method name getInstance and line 19 verifies we’re
dealing with lines 13-18 of our source code. Let’s walk
through the generated code, lines L0–L18.


L0 (13): EXT_NOP


We saw last month that any function/method declaration
becomes a no-op (NOP or, as here, EXT_NOP). The generator does
not produce any executable code for the function declaration.


L1 (14): EXT_STMT
L2 (14): V0 = FETCH_STATIC_PROP_R string("instance") (self)
(exception)
L3 (14): T1 = BOOL_NOT V0
L4 (14): JMPZ T1 L12

We also learned last month that every PHP statement
begins with a generated EXT_STMT line, as we see for line L1
here. This provides a safe, quiescent, place for the PHP virtual
machine to invoke debugger hooks such as with Xdebug.
We now see, with line L2, the PHP virtual machine has a
special instruction for reading a static property, FETCH_STATIC_
PROP_R. As we’ll see below, PHP has a series of instructions
for situations involving self, static, sand/or parent. This
line fetches the value of self::$instance and places it in the
temporary variable V0.
Line L3 implements the !self::$instance calculation. We
already have self::$instance in variable V0. We now need
to compute the Boolean “not” of that value. If V0 is “truthy,”
the result ill be 0 (false); if V0 is “falsy,” the result is 1 (true).
The BOOL_NOT instruction performs this calculation, placing
the result in the temporary variable T1.
Note that BOOL_NOT produces a numeric
zero or one rather than true or false.
Line L4 implements the if() block.
We have a double-negative here, so let
me explain. When the PHP if(...)
condition is not true, we do not execute
the inside of the if(...) {...} block.
Program execution jumps around
it, moving to the next section of code
(elseif, else, or the end of the if block).
The JMPZ instruction means “jump on
zero.” Line L4 reads “When temporary
variable T1 contains a zero (based on
the BOOL_NOT calculation), skip down to
line L12 and continue program execu-
tion at line L12.”
Lines L5–L11 are quite a bit of work
for our one line of code static::$in-
stance = new static;.

L5 (15): EXT_STMT
L6 (15): V3 = NEW 0 (self) (exception)
L7 (15): EXT_FCALL_BEGIN
L8 (15): DO_FCALL
L9 (15): EXT_FCALL_END
L10 (15): V2 = FETCH_STATIC_PROP_W
string("instance") (self) (exception)
L11 (15): ASSIGN V2 V3

Recall that our constructor method’s
generated code did not appear to be
returning a new object. That’s handled
here with the NEW instruction on line
L6. NEW tells the PHP virtual machine to
create the new object. The 0 says we are

Output 1


  1. $_main: ; (lines=5, args=0, vars=0, tmps=1)

  2. ; (before optimizer)

  3. ; /PragmaticPHP/pragma/src/GeneratedSingleton/CamdenStatePark.php:1-20

  4. L0 (2): NOP

  5. L1 (4): NOP

  6. L2 (6): EXT_STMT

  7. L3 (6): NOP

  8. L4 (20): RETURN int(1)



  9. App\GeneratedSingleton\CamdenStatePark::__construct: ; (lines=3, args=0, vars=0, tmps=0)

  10. ; (before optimizer)

  11. ; /PragmaticPHP/pragma/src/GeneratedSingleton/CamdenStatePark.php:10-11

  12. L0 (10): EXT_NOP

  13. L1 (11): EXT_STMT

  14. L2 (11): RETURN null



  15. App\GeneratedSingleton\CamdenStatePark::getInstance: ; (lines=19, args=0, vars=0, tmps=7)

  16. ; (before optimizer)

  17. ; /PragmaticPHP/pragma/src/GeneratedSingleton/CamdenStatePark.php:13-18

  18. L0 (13): EXT_NOP

  19. L1 (14): EXT_STMT

  20. L2 (14): V0 = FETCH_STATIC_PROP_R string("instance") (self) (exception)

  21. L3 (14): T1 = BOOL_NOT V0

  22. L4 (14): JMPZ T1 L12

  23. L5 (15): EXT_STMT

  24. L6 (15): V3 = NEW 0 (self) (exception)

  25. L7 (15): EXT_FCALL_BEGIN

  26. L8 (15): DO_FCALL

  27. L9 (15): EXT_FCALL_END

  28. L10 (15): V2 = FETCH_STATIC_PROP_W string("instance") (self) (exception)

  29. L11 (15): ASSIGN V2 V3

  30. L12 (17): EXT_STMT

  31. L13 (17): V6 = FETCH_STATIC_PROP_R string("instance") (self) (exception)

  32. L14 (17): VERIFY_RETURN_TYPE V6

  33. L15 (17): RETURN V6

  34. L16 (18): EXT_STMT

  35. L17 (18): VERIFY_RETURN_TYPE

  36. L18 (18): RETURN null

  37. LIVE RANGES:

  38. 3: L10 - L11 (tmp/var)

  39. 6: L14 - L15 (tmp/var)

Free download pdf