Diving into HHVM Extensions (Brno PHP Conference 2015)

Post on 26-Jan-2017

479 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

Transcript

Diving intoHHVM Extensions

James TitcumbBrnoPHP Conference 2015

First, some background...

source: Microsoft

How PHP works

PHP code

OpCache

Execute (VM)

Lexer + Parser

Compiler

How HHVM worksPHP code

OpCache

Execute (VM)

Lexer + Parser

Compiler

JIT

Execute (Native)

Hack features

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

The HHVM codebase

The Engine

hphp/parser

The Engine

hphp/parserhphp/compiler

The Engine

hphp/parserhphp/compilerhphp/hhbbc

The Engine

hphp/parserhphp/compilerhphp/hhbbchphp/hhvm

The Engine

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

The Engine

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

The Extensions

hphp/runtime/ext

The Extensions

hphp/runtime/exthphp/system/php

Compile HHVM?

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

My First HHVM Extension™

config.cmake

HHVM_EXTENSION(calc ext_calc.cpp)

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

Compile it.(waaaat?!)

Compile & run the test#!/bin/bash

hphpize

cmake . && make

/usr/bin/hhvm \

-d extension_dir=. \

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

test.php

Compile & run the test$ ./build.sh

bool(true)

$

Hack it!

source: http://goo.gl/kUAxBI

config.cmake

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

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

ext_calc.php<?hh

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

return $a - $b;

}

… that’s it.

<?php

var_dump(extension_loaded('calc'));

var_dump(calc_sub(5, 3));

test.php

Compile & run the test$ ./build.sh

bool(true)

int(2)

$

Sprinkle some C++ infor good measure

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

virtual void moduleInit() {

HHVM_FE(calc_add);

loadSystemlib();

}

// ... SNIP ...

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

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

return a + b;

}

// ... SNIP ...

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;

}

… that’s it.

<?php

var_dump(extension_loaded('calc'));

var_dump(calc_sub(5, 3));

var_dump(calc_add(5, 3));

test.php

Compile & run the test$ ./build.sh

bool(true)

int(2)

int(8)

$

Debugging?!

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

Add debug mode#!/bin/bash

hphpize

cmake \

-DCMAKE_C_FLAGS="-O0 -ggdb3" \

-DCMAKE_CXX_FLAGS="-O0 -ggdb3" \

-DCMAKE_BUILD_TYPE=Debug \

.

make

# ... SNIP ...

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)

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

When NOT to write extensions

When to write extensions

BUCKLE UP.

source: https://goo.gl/x7Srhe

Integrating OpenGLinto an HHVM extension

Don’t try this in production!

srsly.

Extension

Browser

What I did

huh?!

Make it OOOOOOO

ext_foo.php<?hh

<<__NativeData("Foo")>>

class Foo {

<<__Native>>

public function bar(): int;

}

C++ object!==

PHP object

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

ext_foo.php<?hh

class Foo {

private int $value

public function bar(): int

{

return $this->value;

}

}

Demo?

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

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

Any questions? :)

https://joind.in/16263James Titcumb @asgrim

top related