3v4l.org

run code in 300+ PHP versions simultaneously
<?php class RecursionDetector { private array $obj_ref_stack = []; private array $arr_ref_stack = []; public function detect(&$val): bool { switch (gettype($val)) { case 'object': $hash = spl_object_hash($val); var_dump($hash); if (isset($this->obj_ref_stack[$hash])) { debug_print_backtrace(); return true; } $this->obj_ref_stack[$hash] = true; $copy = (array) $val; break; case 'array': $ref = ReflectionReference::fromArrayElement([&$var], 0)->getId(); if (isset($this->arr_ref_stack[$ref])) { debug_print_backtrace(); return true; } $this->arr_ref_stack[$ref] = true; $copy = $val; break; default: return false; } $recurse = false; foreach ($copy as $k => $_) { if ($this->detect($copy[$k])) { $recurse = true; break; } } switch (gettype($val)) { case 'object': unset($this->obj_ref_stack[$hash]); break; case 'array': unset($this->arr_ref_stack[$ref]); break; } return $recurse; } } $d = new RecursionDetector(); class X { public array $y = []; } $x = new X(); $r = new ReflectionClass('X'); $z = $r->newLazyProxy(fn() => $x); $x->y[] = [[$z]]; $_ = $z->y; var_dump($x, $z); var_dump($d->detect($x)); var_dump($d->detect($z));
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/Ad9CN
function name:  (null)
number of ops:  40
compiled vars:  !0 = $d, !1 = $x, !2 = $r, !3 = $z, !4 = $_
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   54     0  E >   NEW                                              $5      'RecursionDetector'
          1        DO_FCALL                                      0          
          2        ASSIGN                                                   !0, $5
   60     3        NEW                                              $8      'X'
          4        DO_FCALL                                      0          
          5        ASSIGN                                                   !1, $8
   62     6        NEW                                              $11     'ReflectionClass'
          7        SEND_VAL_EX                                              'X'
          8        DO_FCALL                                      0          
          9        ASSIGN                                                   !2, $11
   63    10        INIT_METHOD_CALL                                         !2, 'newLazyProxy'
         11        DECLARE_LAMBDA_FUNCTION                          ~14     [0]
         12        BIND_LEXICAL                                             ~14, !1
         13        SEND_VAL_EX                                              ~14
         14        DO_FCALL                                      0  $15     
         15        ASSIGN                                                   !3, $15
   65    16        INIT_ARRAY                                       ~19     !3
         17        INIT_ARRAY                                       ~20     ~19
         18        FETCH_OBJ_W                                      $17     !1, 'y'
         19        ASSIGN_DIM                                               $17
         20        OP_DATA                                                  ~20
   66    21        FETCH_OBJ_R                                      ~21     !3, 'y'
         22        ASSIGN                                                   !4, ~21
   68    23        INIT_FCALL                                               'var_dump'
         24        SEND_VAR                                                 !1
         25        SEND_VAR                                                 !3
         26        DO_ICALL                                                 
   69    27        INIT_FCALL                                               'var_dump'
         28        INIT_METHOD_CALL                                         !0, 'detect'
         29        SEND_VAR_EX                                              !1
         30        DO_FCALL                                      0  $24     
         31        SEND_VAR                                                 $24
         32        DO_ICALL                                                 
   70    33        INIT_FCALL                                               'var_dump'
         34        INIT_METHOD_CALL                                         !0, 'detect'
         35        SEND_VAR_EX                                              !3
         36        DO_FCALL                                      0  $26     
         37        SEND_VAR                                                 $26
         38        DO_ICALL                                                 
         39      > RETURN                                                   1


Dynamic Functions:
Dynamic Function 0
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/Ad9CN
function name:  {closure}
number of ops:  3
compiled vars:  !0 = $x
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   63     0  E >   BIND_STATIC                                              !0
          1      > RETURN                                                   !0
          2*     > RETURN                                                   null

End of Dynamic Function 0

Class RecursionDetector:
Function detect:
Finding entry points
Branch analysis from position: 0
4 jumps found. (Code = 188) Position 1 = 8, Position 2 = 28, Position 3 = 48, Position 4 = 3
Branch analysis from position: 8
2 jumps found. (Code = 43) Position 1 = 18, Position 2 = 22
Branch analysis from position: 18
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 22
1 jumps found. (Code = 42) Position 1 = 50
Branch analysis from position: 50
2 jumps found. (Code = 77) Position 1 = 53, Position 2 = 64
Branch analysis from position: 53
2 jumps found. (Code = 78) Position 1 = 54, Position 2 = 64
Branch analysis from position: 54
2 jumps found. (Code = 43) Position 1 = 61, Position 2 = 63
Branch analysis from position: 61
1 jumps found. (Code = 42) Position 1 = 64
Branch analysis from position: 64
4 jumps found. (Code = 188) Position 1 = 72, Position 2 = 75, Position 3 = 78, Position 4 = 67
Branch analysis from position: 72
1 jumps found. (Code = 42) Position 1 = 78
Branch analysis from position: 78
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 75
1 jumps found. (Code = 42) Position 1 = 78
Branch analysis from position: 78
Branch analysis from position: 78
Branch analysis from position: 67
2 jumps found. (Code = 44) Position 1 = 69, Position 2 = 72
Branch analysis from position: 69
2 jumps found. (Code = 44) Position 1 = 71, Position 2 = 75
Branch analysis from position: 71
1 jumps found. (Code = 42) Position 1 = 78
Branch analysis from position: 78
Branch analysis from position: 75
Branch analysis from position: 72
Branch analysis from position: 63
1 jumps found. (Code = 42) Position 1 = 53
Branch analysis from position: 53
Branch analysis from position: 64
Branch analysis from position: 64
Branch analysis from position: 28
2 jumps found. (Code = 43) Position 1 = 39, Position 2 = 43
Branch analysis from position: 39
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 43
1 jumps found. (Code = 42) Position 1 = 50
Branch analysis from position: 50
Branch analysis from position: 48
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 3
2 jumps found. (Code = 44) Position 1 = 5, Position 2 = 8
Branch analysis from position: 5
2 jumps found. (Code = 44) Position 1 = 7, Position 2 = 28
Branch analysis from position: 7
1 jumps found. (Code = 42) Position 1 = 48
Branch analysis from position: 48
Branch analysis from position: 28
Branch analysis from position: 8
filename:       /in/Ad9CN
function name:  detect
number of ops:  83
compiled vars:  !0 = $val, !1 = $hash, !2 = $copy, !3 = $ref, !4 = $var, !5 = $recurse, !6 = $_, !7 = $k
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
    7     0  E >   RECV                                             !0      
    8     1        GET_TYPE                                         ~8      !0
          2      > SWITCH_STRING                                            ~8, [ 'object':->8, 'array':->28, ], ->48
    9     3    >   CASE                                                     ~8, 'object'
          4      > JMPNZ                                                    ~9, ->8
   19     5    >   CASE                                                     ~8, 'array'
          6      > JMPNZ                                                    ~9, ->28
          7    > > JMP                                                      ->48
   10     8    >   INIT_FCALL                                               'spl_object_hash'
          9        SEND_VAR                                                 !0
         10        DO_ICALL                                         $10     
         11        ASSIGN                                                   !1, $10
   11    12        INIT_FCALL                                               'var_dump'
         13        SEND_VAR                                                 !1
         14        DO_ICALL                                                 
   12    15        FETCH_OBJ_IS                                     ~13     'obj_ref_stack'
         16        ISSET_ISEMPTY_DIM_OBJ                         0          ~13, !1
         17      > JMPZ                                                     ~14, ->22
   13    18    >   INIT_FCALL                                               'debug_print_backtrace'
         19        DO_ICALL                                                 
   14    20        FREE                                                     ~8
         21      > RETURN                                                   <true>
   16    22    >   FETCH_OBJ_W                                      $16     'obj_ref_stack'
         23        ASSIGN_DIM                                               $16, !1
         24        OP_DATA                                                  <true>
   17    25        CAST                                          7  ~18     !0
         26        ASSIGN                                                   !2, ~18
   18    27      > JMP                                                      ->50
   20    28    >   INIT_STATIC_METHOD_CALL                                  'ReflectionReference', 'fromArrayElement'
         29        INIT_ARRAY                                       ~20     !4
         30        SEND_VAL                                                 ~20
         31        SEND_VAL                                                 0
         32        DO_FCALL                                      0  $21     
         33        INIT_METHOD_CALL                                         $21, 'getId'
         34        DO_FCALL                                      0  $22     
         35        ASSIGN                                                   !3, $22
   21    36        FETCH_OBJ_IS                                     ~24     'arr_ref_stack'
         37        ISSET_ISEMPTY_DIM_OBJ                         0          ~24, !3
         38      > JMPZ                                                     ~25, ->43
   22    39    >   INIT_FCALL                                               'debug_print_backtrace'
         40        DO_ICALL                                                 
   23    41        FREE                                                     ~8
         42      > RETURN                                                   <true>
   25    43    >   FETCH_OBJ_W                                      $27     'arr_ref_stack'
         44        ASSIGN_DIM                                               $27, !3
         45        OP_DATA                                                  <true>
   26    46        ASSIGN                                                   !2, !0
   27    47      > JMP                                                      ->50
   29    48    >   FREE                                                     ~8
         49      > RETURN                                                   <false>
         50    >   FREE                                                     ~8
   32    51        ASSIGN                                                   !5, <false>
   34    52      > FE_RESET_R                                       $31     !2, ->64
         53    > > FE_FETCH_R                                       ~32     $31, !6, ->64
         54    >   ASSIGN                                                   !7, ~32
   35    55        INIT_METHOD_CALL                                         'detect'
         56        CHECK_FUNC_ARG                                           
         57        FETCH_DIM_FUNC_ARG                               $34     !2, !7
         58        SEND_FUNC_ARG                                            $34
         59        DO_FCALL                                      0  $35     
         60      > JMPZ                                                     $35, ->63
   36    61    >   ASSIGN                                                   !5, <true>
   37    62      > JMP                                                      ->64
   34    63    > > JMP                                                      ->53
         64    >   FE_FREE                                                  $31
   41    65        GET_TYPE                                         ~37     !0
         66      > SWITCH_STRING                                            ~37, [ 'object':->72, 'array':->75, ], ->78
   42    67    >   CASE                                                     ~37, 'object'
         68      > JMPNZ                                                    ~38, ->72
   45    69    >   CASE                                                     ~37, 'array'
         70      > JMPNZ                                                    ~38, ->75
         71    > > JMP                                                      ->78
   43    72    >   FETCH_OBJ_UNSET                                  $39     'obj_ref_stack'
         73        UNSET_DIM                                                $39, !1
   44    74      > JMP                                                      ->78
   46    75    >   FETCH_OBJ_UNSET                                  $40     'arr_ref_stack'
         76        UNSET_DIM                                                $40, !3
   47    77      > JMP                                                      ->78
         78    >   FREE                                                     ~37
   50    79        VERIFY_RETURN_TYPE                                       !5
         80      > RETURN                                                   !5
   51    81*       VERIFY_RETURN_TYPE                                       
         82*     > RETURN                                                   null

End of function detect

End of class RecursionDetector.

Class X: [no user functions]

Generated using Vulcan Logic Dumper, using php 8.0.0


preferences:
150.7 ms | 1017 KiB | 16 Q