Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Zend VMにおける例外の実装

PHPerKaigi 2020 (2020/2/11) 発表資料。PHPカンファレンス 2019発表の再演です。



  • Login to see the comments

  • Be the first to like this

Zend VMにおける例外の実装

  1. 1. Explaining exception handling on Zend VM 
 

  2. 2. ❖ ❖ ❖ ❖ ❖
  3. 3. ❖ ❖ ❖ ❖
  4. 4. ❖ ❖ ❖ ❖
  5. 5.
  6. 6.
  7. 7. ❖ ❖
  8. 8. ❖ ❖
  9. 9. ❖ ❖
  10. 10. ❖ <?php function mydiv($a, $b) { return $b ? $a / $b : 0; } $ php -dopcache.enable_cli=1 -dopcache.opt_debug_level=0x10000 mydiv.php
  11. 11. L0 (2): CV0($a) = RECV 1 L1 (2): CV1($b) = RECV 2 L2 (3): JMPZ CV1($b) L6 L3 (3): T2 = DIV CV0($a) CV1($b) L4 (3): T3 = QM_ASSIGN T2 L5 (3): JMP L7 L6 (3): T3 = QM_ASSIGN int(0) L7 (3): RETURN T3 L8 (4): RETURN null ❖ ❖ ❖
  12. 12. ❖ JMPZ CV1($b) L6 T2 = DIV CV0($a) CV1($b) ❖
  13. 13. ❖ ❖ ❖ ❖
  14. 14. ❖ ❖ ❖ ❖
  15. 15. <?php function bar() { $e = new Exception(); throw $e; try { throw $e; } catch (FooException $e) { throw $e; } catch (BarException $e) { return 0; } } ❖
  16. 16. L0 (4): V1 = NEW 0 string("Exception") L1 (4): DO_FCALL L2 (3): ASSIGN CV0($e) V1 L3 (4): THROW CV0($e) L4 (6): THROW CV0($e) L5 (6): JMP L11 L6 (7): CV0($e) = CATCH string("FooException") L9 L7 (8): THROW CV0($e) L8 (8): JMP L11 L9 (9): CV0($e) = CATCH string("BarException") L10 (10): RETURN int(0) L11 (12): RETURN null EXCEPTION TABLE: L4, L6, -, - ❖
  17. 17. L0 (4): V1 = NEW 0 string("Exception") L1 (4): DO_FCALL L2 (3): ASSIGN CV0($e) V1 L3 (4): THROW CV0($e) L4 (6): THROW CV0($e) L5 (6): JMP L11 L6 (7): CV0($e) = CATCH string("FooException") L9 L7 (8): THROW CV0($e) L8 (8): JMP L11 L9 (9): CV0($e) = CATCH string("BarException") L10 (10): RETURN int(0) L11 (12): RETURN null EXCEPTION TABLE: L4, L6, -, - ❖
  18. 18. ❖ THROW CV0($e) ❖ CV0($e) = CATCH string("FooException") L9
  19. 19. ❖ ❖ ❖ ❖ THROW CV0($e)
  20. 20. ZEND_API ZEND_COLD void zend_throw_exception_internal (zval *exception) /* {{{ */ { if (exception != NULL) { EG(exception) = Z_OBJ_P(exception); ❖ ❖ ❖
  21. 21. EG(current_execute_data)->opline = EG(exception_op); ❖ ❖ ❖ ❖
  22. 22. ❖ ❖
  23. 23. ❖ ❖ ❖ ❖ ❖
  24. 24. ❖ ❖ ❖ THROW CV0($e)
  25. 25. ❖ ❖ ❖ ❖
  26. 26. L0 (4): V1 = NEW 0 string("Exception") L1 (4): DO_FCALL L2 (3): ASSIGN CV0($e) V1 L3 (4): THROW CV0($e) L4 (6): THROW CV0($e) L5 (6): JMP L11 L6 (7): CV0($e) = CATCH string("FooException") L9 L7 (8): THROW CV0($e) L8 (8): JMP L11 L9 (9): CV0($e) = CATCH string("BarException") L10 (10): RETURN int(0) L11 (12): RETURN null EXCEPTION TABLE: L4, L6, -, - ❖
  27. 27. if (ce != catch_ce) { if (!catch_ce || !instanceof_function(ce, catch_ce)) { if (opline->extended_value & ZEND_LAST_CATCH) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION(); } ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } } ❖ ❖ ❖ ❖
  28. 28. static zend_always_inline void zend_rethrow_exception(zend_execute_data *execute_data) { if (EX(opline)->opcode != ZEND_HANDLE_EXCEPTION) { EG(opline_before_exception) = EX(opline); EX(opline) = EG(exception_op); } } ❖ ❖ ❖ ❖
  29. 29. ❖ THROW CV0($e) ❖ HANDLE_EXEPTION
  30. 30. CV0($e) = CATCH string("FooException") L9 ❖ ❖ ❖
  31. 31. ❖ ❖ ❖ ❖
  32. 32. ❖ ❖ ❖ ❖ ❖
  33. 33. ❖ ❖ ❖ ❖
  34. 34. <?php function baz() { try { throw new Exception(); } finally { return 0; } } ❖
  35. 35. <?php function baz() { try { throw new Exception(); } finally { return 0; } } ❖ ❖ ❖
  36. 36. L0 (4): V1 = NEW 0 string("Exception") L1 (4): DO_FCALL L2 (4): THROW V1 L3 (5): T0 = FAST_CALL L5 L4 (5): JMP L8 L5 (6): DISCARD_EXCEPTION T0 L6 (6): RETURN int(0) L7 (6): FAST_RET T0 L8 (8): RETURN null EXCEPTION TABLE: L0, -, L5, L7 ❖ ❖ 

  37. 37. ❖ ❖ ❖ ❖
  38. 38. <?php function baz() { try { throw new Exception(1); } finally { throw new Exception(2); } } ❖
  39. 39. <?php function baz() { try { throw new Exception(1); } finally { throw new Exception(2); } } ❖ ❖
  40. 40. try { baz(); } catch (Exception $e) { echo $e->getMessage(); // 2 echo $e->getPrevious()->getMessage(); // 1 } ❖ ❖
  41. 41. ❖ ❖ ❖ ❖ ❖
  42. 42. ❖ ❖ ❖ ❖
  43. 43. ❖ ❖
  44. 44. ❖ ❖ ❖ ❖ ❖
  45. 45. ❖ ❖

×