Diving into HHVM Extensions (php[tek] 2016)

79
Diving into HHVM Extensions James Titcumb

Transcript of Diving into HHVM Extensions (php[tek] 2016)

Diving intoHHVM Extensions

James Titcumb

First, some background...

source: Microsoft

Hack features

● Return/parameter type hints● ?nullable● Collections (Vectors, Sets, Maps, etc.)● Async functions● Enums● Generics● Lambda expressions ==>● XHP● more stuff

@asgrim

How PHP works

PHP code

OpCache

Execute (VM)

Lexer + Parser

Compiler

@asgrim

How HHVM worksPHP code

OpCache

Execute (VM)

Lexer + Parser

Compiler

JIT

Execute (Native)

@asgrim

The HHVM codebase

@asgrim

The Engine

hphp/parser

@asgrim

The Engine

hphp/parserhphp/compiler

@asgrim

The Engine

hphp/parserhphp/compilerhphp/hhbbc

@asgrim

The Engine

hphp/parserhphp/compilerhphp/hhbbchphp/hhvm

@asgrim

The Engine

hphp/parserhphp/compilerhphp/hhbbchphp/hhvmhphp/runtime/vm

@asgrim

The Engine

hphp/parserhphp/compilerhphp/hhbbchphp/hhvmhphp/runtime/vmhphp/runtime/vm/jit

@asgrim

The Extensions

hphp/runtime/ext

@asgrim

The Extensions

hphp/runtime/exthphp/system/php

@asgrim

Compile HHVM?

@asgrim

source: https://xkcd.com/303/

@asgrim

My First HHVM Extension™

@asgrim

config.cmake

HHVM_EXTENSION(calc ext_calc.cpp)

@asgrim

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

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

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

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

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

… that’s it.<?php

var_dump(extension_loaded('calc'));

test.php

@asgrim

Compile it.(waaaat?!)

@asgrim

Compile & run the test#!/usr/bin/env bash

hphpize

cmake . && make

/usr/bin/hhvm \

-d extension_dir=. \

-d hhvm.extensions[]=calc.so \

test.php

@asgrim

Compile & run the test$ ./build.sh

bool(true)

$

@asgrim

Hack it!

@asgrim

source: http://goo.gl/kUAxBI

config.cmake

HHVM_EXTENSION(calc ext_calc.cpp)HHVM_SYSTEMLIB(calc ext_calc.php)

@asgrim

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

@asgrim

ext_calc.php<?hh

function calc_sub(int $a, int $b): int {

return $a - $b;

}

@asgrim

… that’s it.

<?php

var_dump(extension_loaded('calc'));

var_dump(calc_sub(5, 3));

test.php

@asgrim

Compile & run the test$ ./build.sh

bool(true)

int(2)

$

@asgrim

Sprinkle some C++ infor good measure

@asgrim

ext_calc.cpp// ... SNIP ...

virtual void moduleInit() {

HHVM_FE(calc_add);

loadSystemlib();

}

// ... SNIP ...

@asgrim

ext_calc.cpp// ... SNIP ...

static int64_t HHVM_FUNCTION(calc_add, int64_t a, int64_t b) {

return a + b;

}

// ... SNIP ...

@asgrim

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 ...

ext_calc.php<?hh

<<__Native>>

function calc_add(int $a, int $b): int;

function calc_sub(int $a, int $b): int {

return $a - $b;

}

@asgrim

… that’s it.

<?php

var_dump(extension_loaded('calc'));

var_dump(calc_sub(5, 3));

var_dump(calc_add(5, 3));

test.php

@asgrim

Compile & run the test$ ./build.sh

bool(true)

int(2)

int(8)

$

@asgrim

Debugging?!

@asgrim

source: http://www.gnu.org/software/gdb/

@asgrim

Add debug mode#!/bin/bash

hphpize

cmake \

-DCMAKE_C_FLAGS="-O0 -ggdb3" \

-DCMAKE_CXX_FLAGS="-O0 -ggdb3" \

-DCMAKE_BUILD_TYPE=Debug \

.

make

# ... SNIP ...

@asgrim

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)

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)

@asgrim

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)

Handy commandsc 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 :)

@asgrim

When NOT to write extensions

@asgrim

When to write extensions

@asgrim

BUCKLE UP.

@asgrim

source: https://goo.gl/x7Srhe

@asgrim

Integrating OpenGLinto an HHVM extension

@asgrim

Don’t try this in production!

@asgrim

srsly.

@asgrim

Extension

Browser

@asgrim

What I did

@asgrim

@asgrim

huh?!@asgrim

Make it OOOOOOO

@asgrim

ext_foo.php<?hh

<<__NativeData("Foo")>>

class Foo {

<<__Native>>

public function bar(): int;

}@asgrim

C++ object!==

PHP object

@asgrim

source: http://goo.gl/HORwLQ

HHVM Universe

<?php

$o = new Foo();$o->bar();

PHP Landclass 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

HHVM Universe

<?php

$o = new Foo();$o->bar();

PHP Landclass 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

HHVM Universe

<?php

$o = new Foo();$o->bar();

PHP Landclass 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

HHVM Universe

<?php

$o = new Foo();$o->bar();

PHP Landclass 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

this slide is intentionally left blank

@asgrim

ext_foo.php<?hh

class Foo {

private int $value

public function bar(): int

{

return $this->value;

}

}

@asgrim

Demo?

@asgrim

source: http://goo.gl/7gWfNz

● 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

Resources

@asgrim

Any questions? :)

https://joind.in/talk/a4320James Titcumb @asgrim