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.

Diving into HHVM Extensions (PHPNW Conference 2015)

627 views

Published on

HHVM is currently gaining popularity at quite a pace, and it's a pretty exciting time for PHP runtimes. Have you ever wondered what is going on beneath this slick and super-speedy engine? I wondered that myself, so I dived into the internals of HHVM, discovering a treasure trove of awesome stuff. In this talk, I'll show you how HHVM itself works with a guided tour of the codebase, demonstrating how it all pieces together. I'll also show you a couple of ways to write your own incredible HHVM extension. You don't need to know C++ to understand this talk - just PHP language knowledge is enough.

Published in: Technology
  • Be the first to comment

Diving into HHVM Extensions (PHPNW Conference 2015)

  1. 1. Diving into HHVM Extensions James Titcumb PHPNW Conference 2015
  2. 2. James Titcumb www.jamestitcumb.com www.roave.com www.phphants.co.uk www.phpsouthcoast.co.uk @asgrim Who is this guy?
  3. 3. First, some background... source: Microsoft
  4. 4. How PHP works PHP code OpCache Execute (VM) Lexer + Parser Compiler
  5. 5. How HHVM works PHP code OpCache Execute (VM) Lexer + Parser Compiler JIT Execute (Native)
  6. 6. Hack features ● Return/parameter type hints ● ?nullable ● Collections (Vectors, Sets, Maps, etc.) ● Async functions ● Enums ● Generics ● Lambda expressions ==> ● XHP ● more stuff
  7. 7. The HHVM codebase
  8. 8. The Engine hphp/parser
  9. 9. The Engine hphp/parser hphp/compiler
  10. 10. The Engine hphp/parser hphp/compiler hphp/hhbbc
  11. 11. The Engine hphp/parser hphp/compiler hphp/hhbbc hphp/hhvm
  12. 12. The Engine hphp/parser hphp/compiler hphp/hhbbc hphp/hhvm hphp/runtime/vm
  13. 13. The Engine hphp/parser hphp/compiler hphp/hhbbc hphp/hhvm hphp/runtime/vm hphp/runtime/vm/jit
  14. 14. The Extensions hphp/runtime/ext
  15. 15. The Extensions hphp/runtime/ext hphp/system/php
  16. 16. Compile HHVM?
  17. 17. source: https://xkcd.com/303/
  18. 18. My First HHVM Extension™
  19. 19. config.cmake HHVM_EXTENSION(calc ext_calc.cpp)
  20. 20. ext_calc.cpp #include "hphp/runtime/ext/extension.h" namespace HPHP { static class CalcExtension : public Extension { public: CalcExtension(): Extension("calc") {} virtual void moduleInit() {} } s_calc_extension; HHVM_GET_MODULE(calc); } // namespace HPHP
  21. 21. ext_calc.cpp #include "hphp/runtime/ext/extension.h" namespace HPHP { static class CalcExtension : public Extension { public: CalcExtension(): Extension("calc") {} virtual void moduleInit() {} } s_calc_extension; HHVM_GET_MODULE(calc); } // namespace HPHP
  22. 22. ext_calc.cpp #include "hphp/runtime/ext/extension.h" namespace HPHP { static class CalcExtension : public Extension { public: CalcExtension(): Extension("calc") {} virtual void moduleInit() {} } s_calc_extension; HHVM_GET_MODULE(calc); } // namespace HPHP
  23. 23. ext_calc.cpp #include "hphp/runtime/ext/extension.h" namespace HPHP { static class CalcExtension : public Extension { public: CalcExtension(): Extension("calc") {} virtual void moduleInit() {} } s_calc_extension; HHVM_GET_MODULE(calc); } // namespace HPHP
  24. 24. ext_calc.cpp #include "hphp/runtime/ext/extension.h" namespace HPHP { static class CalcExtension : public Extension { public: CalcExtension(): Extension("calc") {} virtual void moduleInit() {} } s_calc_extension; HHVM_GET_MODULE(calc); } // namespace HPHP
  25. 25. … that’s it. <?php var_dump(extension_loaded('calc')); test.php
  26. 26. Compile it. (waaaat?!)
  27. 27. Compile & run the test #!/bin/bash hphpize cmake . && make /usr/bin/hhvm -d extension_dir=. -d hhvm.extensions[]=calc.so test.php
  28. 28. Compile & run the test $ ./build.sh bool(true) $
  29. 29. Hack it!
  30. 30. source: http://goo.gl/kUAxBI
  31. 31. config.cmake HHVM_EXTENSION(calc ext_calc.cpp) HHVM_SYSTEMLIB(calc ext_calc.php)
  32. 32. ext_calc.cpp #include "hphp/runtime/ext/extension.h" namespace HPHP { static class CalcExtension : public Extension { public: CalcExtension(): Extension("calc") {} virtual void moduleInit() { loadSystemlib(); } } s_calc_extension; HHVM_GET_MODULE(calc); } // namespace HPHP
  33. 33. ext_calc.php <?hh function calc_sub(int $a, int $b): int { return $a - $b; }
  34. 34. … that’s it. <?php var_dump(extension_loaded('calc')); var_dump(calc_sub(5, 3)); test.php
  35. 35. Compile & run the test $ ./build.sh bool(true) int(2) $
  36. 36. Sprinkle some C++ in for good measure
  37. 37. ext_calc.cpp // ... SNIP ... virtual void moduleInit() { HHVM_FE(calc_add); loadSystemlib(); } // ... SNIP ...
  38. 38. ext_calc.cpp // ... SNIP ... static int64_t HHVM_FUNCTION(calc_add, int64_t a, int64_t b) { return a + b; } // ... SNIP ...
  39. 39. in php extensions... PHP_FUNCTION(calc_add) { // ... SNIP ... #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &a, &b) == FAILURE) { return; } #else ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_LONG(a) Z_PARAM_LONG(b) ZEND_PARSE_PARAMETERS_END(); #endif // ... SNIP ...
  40. 40. ext_calc.php <?hh <<__Native>> function calc_add(int $a, int $b): int; function calc_sub(int $a, int $b): int { return $a - $b; }
  41. 41. … that’s it. <?php var_dump(extension_loaded('calc')); var_dump(calc_sub(5, 3)); var_dump(calc_add(5, 3)); test.php
  42. 42. Compile & run the test $ ./build.sh bool(true) int(2) int(8) $
  43. 43. Debugging?!
  44. 44. source: http://www.gnu.org/software/gdb/
  45. 45. Add debug mode #!/bin/bash hphpize cmake -DCMAKE_C_FLAGS="-O0 -ggdb3" -DCMAKE_CXX_FLAGS="-O0 -ggdb3" -DCMAKE_BUILD_TYPE=Debug . make # ... SNIP ...
  46. 46. Run with gdb $ gdb --args /usr/bin/hhvm -d extension_dir=. -d hhvm.extensions[]=calc.so test.php GNU gdb (Ubuntu 7.9-1ubuntu1) 7.9 Copyright (C) 2015 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu. org/licenses/gpl.html> --- snip --- Reading symbols from /usr/bin/hhvm...done. (gdb)
  47. 47. Breakpoints (gdb) b ext_calc.cpp:6 No source file named ext_calc.cpp. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (ext_calc.cpp:6) pending. (gdb)
  48. 48. Running (gdb) r Starting program: /usr/bin/hhvm -d extension_dir=. -d hhvm.extensions[] =calc.so smoke.php [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Breakpoint 2, HPHP::f_calc_add (a=5, b=3) at /home/james/workspace/hhvm- calc/ext_calc.cpp:6 6 return a + b; (gdb) p a $1 = 5 (gdb) p b $2 = 3 (gdb)
  49. 49. Handy commands c continue / step out n step over s step into p x print the value of a variable (x) set x = y set a variable (x) to value (y) bt print backtrace q quit :)
  50. 50. When NOT to write extensions
  51. 51. When to write extensions
  52. 52. BUCKLE UP.
  53. 53. source: https://goo.gl/x7Srhe
  54. 54. Integrating OpenGL into an HHVM extension
  55. 55. Don’t try this in production!
  56. 56. srsly.
  57. 57. Extension Browser
  58. 58. What I did
  59. 59. huh?!
  60. 60. Make it OOOOOOO
  61. 61. ext_foo.php <?hh <<__NativeData("Foo")>> class Foo { <<__Native>> public function bar(): int; }
  62. 62. C++ object !== PHP object
  63. 63. source: http://goo.gl/HORwLQ
  64. 64. HHVM Universe <?php $o = new Foo(); $o->bar(); PHP Land class Foo { public: Foo() {} ~Foo() {} int value = 5; } Planet C++ int64_t HHVM_METHOD(Foo,bar) { auto data = Native::data<Foo>(this_); return data->value; } Time Vortex!?!?! C++ object !== PHP object
  65. 65. HHVM Universe <?php $o = new Foo(); $o->bar(); PHP Land class Foo { public: Foo() {} ~Foo() {} int value = 5; } Planet C++ int64_t HHVM_METHOD(Foo,bar) { auto data = Native::data<Foo>(this_); return data->value; } Time Vortex!?!?! C++ object !== PHP object
  66. 66. HHVM Universe <?php $o = new Foo(); $o->bar(); PHP Land class Foo { public: Foo() {} ~Foo() {} int value = 5; } Planet C++ int64_t HHVM_METHOD(Foo,bar) { auto data = Native::data<Foo>(this_); return data->value; } Time Vortex!?!?! C++ object !== PHP object
  67. 67. HHVM Universe <?php $o = new Foo(); $o->bar(); PHP Land class Foo { public: Foo() {} ~Foo() {} int value = 5; } Planet C++ int64_t HHVM_METHOD(Foo,bar) { auto data = Native::data<Foo>(this_); return data->value; } Time Vortex!?!?! C++ object !== PHP object
  68. 68. this slide is intentionally left blank
  69. 69. ext_foo.php <?hh class Foo { private int $value public function bar(): int { return $this->value; } }
  70. 70. Demo?
  71. 71. source: http://goo.gl/7gWfNz
  72. 72. Resources ● OpenGL Tutorial ○ http://www.opengl-tutorial.org/ ● HHVM Example Extension ○ https://github.com/hhvm/extension-example ● Sara Golemon - HHVM extension blog series ○ http://blog.golemon.com/2015/01/hhvm-extension-writing-part-iii.html ● Derick Rethans’ extension API cookbook ○ https://github.com/derickr/hhvm-hni-cookbook ● The official API documentation ○ https://github.com/facebook/hhvm/wiki/Extension%20API ● Journey of a Thousand Bytecodes ○ http://hhvm.com/blog/6323/the-journey-of-a-thousand-bytecodes
  73. 73. Any questions? :) https://joind.in/15434 James Titcumb @asgrim

×